| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/audio/audio_output.h" | 5 #include "media/audio/audio_output.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <mmsystem.h> | 8 #include <mmsystem.h> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "media/audio/fake_audio_output_stream.h" |
| 12 #include "media/audio/win/audio_manager_win.h" | 13 #include "media/audio/win/audio_manager_win.h" |
| 13 #include "media/audio/win/waveout_output_win.h" | 14 #include "media/audio/win/waveout_output_win.h" |
| 14 | 15 |
| 15 // A do-nothing audio stream. It behaves like a regular audio stream but does | |
| 16 // not have any side effect, except possibly the creation and tear-down of | |
| 17 // of a thread. It is useful to test code that uses audio streams such as | |
| 18 // audio sources. | |
| 19 class AudioOutputStreamMockWin : public AudioOutputStream { | |
| 20 public: | |
| 21 explicit AudioOutputStreamMockWin(AudioManagerWin* manager) | |
| 22 : manager_(manager), | |
| 23 callback_(NULL), | |
| 24 buffer_(NULL), | |
| 25 packet_size_(0), | |
| 26 left_volume_(1.0), | |
| 27 right_volume_(1.0) { | |
| 28 } | |
| 29 | |
| 30 virtual ~AudioOutputStreamMockWin() { | |
| 31 delete[] buffer_; | |
| 32 packet_size_ = 0; | |
| 33 } | |
| 34 | |
| 35 virtual bool Open(size_t packet_size) { | |
| 36 if (packet_size < sizeof(int16)) | |
| 37 return false; | |
| 38 packet_size_ = packet_size; | |
| 39 buffer_ = new char[packet_size_]; | |
| 40 return true; | |
| 41 } | |
| 42 | |
| 43 virtual void Start(AudioSourceCallback* callback) { | |
| 44 callback_ = callback; | |
| 45 memset(buffer_, 0, packet_size_); | |
| 46 callback_->OnMoreData(this, buffer_, packet_size_); | |
| 47 } | |
| 48 | |
| 49 // TODO(cpu): flesh out Start and Stop methods. We need a thread to | |
| 50 // perform periodic callbacks. | |
| 51 virtual void Stop() { | |
| 52 } | |
| 53 | |
| 54 virtual void SetVolume(double left_level, double right_level) { | |
| 55 left_volume_ = left_level; | |
| 56 right_volume_ = right_level; | |
| 57 } | |
| 58 | |
| 59 virtual void GetVolume(double* left_level, double* right_level) { | |
| 60 *left_level = left_volume_; | |
| 61 *right_level = right_volume_; | |
| 62 } | |
| 63 | |
| 64 virtual size_t GetNumBuffers() { | |
| 65 return 1; | |
| 66 } | |
| 67 | |
| 68 virtual void Close() { | |
| 69 callback_->OnClose(this); | |
| 70 callback_ = NULL; | |
| 71 manager_->ReleaseStream(this); | |
| 72 } | |
| 73 | |
| 74 char* buffer() { | |
| 75 return buffer_; | |
| 76 } | |
| 77 | |
| 78 private: | |
| 79 AudioManagerWin* manager_; | |
| 80 AudioSourceCallback* callback_; | |
| 81 char* buffer_; | |
| 82 size_t packet_size_; | |
| 83 double left_volume_; | |
| 84 double right_volume_; | |
| 85 }; | |
| 86 | |
| 87 namespace { | 16 namespace { |
| 88 | 17 |
| 89 // The next 3 constants are some sensible limits to prevent integer overflow | 18 // The next 3 constants are some sensible limits to prevent integer overflow |
| 90 // at this layer. | 19 // at this layer. |
| 91 // Up to 6 channels can be passed to the driver. | 20 // Up to 6 channels can be passed to the driver. |
| 92 // This should work, given the right drivers, but graceful error handling is | 21 // This should work, given the right drivers, but graceful error handling is |
| 93 // needed. | 22 // needed. |
| 94 // In theory 7.1 could also be supported, but it has not been tested. | 23 // In theory 7.1 could also be supported, but it has not been tested. |
| 95 // The 192 Khz constant is the frequency of quicktime lossless audio codec. | 24 // The 192 Khz constant is the frequency of quicktime lossless audio codec. |
| 96 // MP4 is limited to 96 Khz, and mp3 is limited to 48 Khz. | 25 // MP4 is limited to 96 Khz, and mp3 is limited to 48 Khz. |
| 97 // OGG vorbis was initially limited to 96 Khz, but recent tools are unlimited. | 26 // OGG vorbis was initially limited to 96 Khz, but recent tools are unlimited. |
| 98 // 192 Khz is also the limit on most PC audio hardware. The minimum is 100 Hz. | 27 // 192 Khz is also the limit on most PC audio hardware. The minimum is 100 Hz. |
| 99 // Humans range is 20 to 20000 Hz. Below 20 can be felt (woofer). | 28 // Humans range is 20 to 20000 Hz. Below 20 can be felt (woofer). |
| 100 | 29 |
| 101 const int kMaxChannels = 6; | 30 const int kMaxChannels = 6; |
| 102 const int kMaxSampleRate = 192000; | 31 const int kMaxSampleRate = 192000; |
| 103 const int kMaxBitsPerSample = 64; | 32 const int kMaxBitsPerSample = 64; |
| 104 | 33 |
| 105 AudioOutputStreamMockWin* g_last_mock_stream = NULL; | |
| 106 AudioManagerWin* g_audio_manager = NULL; | 34 AudioManagerWin* g_audio_manager = NULL; |
| 107 | 35 |
| 108 void ReplaceLastMockStream(AudioOutputStreamMockWin* newer) { | |
| 109 if (g_last_mock_stream) | |
| 110 delete g_last_mock_stream; | |
| 111 g_last_mock_stream = newer; | |
| 112 } | |
| 113 | |
| 114 } // namespace. | 36 } // namespace. |
| 115 | 37 |
| 116 | |
| 117 bool AudioManagerWin::HasAudioDevices() { | 38 bool AudioManagerWin::HasAudioDevices() { |
| 118 return (::waveOutGetNumDevs() != 0); | 39 return (::waveOutGetNumDevs() != 0); |
| 119 } | 40 } |
| 120 | 41 |
| 121 // Factory for the implementations of AudioOutputStream. Two implementations | 42 // Factory for the implementations of AudioOutputStream. Two implementations |
| 122 // should suffice most windows user's needs. | 43 // should suffice most windows user's needs. |
| 123 // - PCMWaveOutAudioOutputStream: Based on the waveOutWrite API (in progress) | 44 // - PCMWaveOutAudioOutputStream: Based on the waveOutWrite API (in progress) |
| 124 // - PCMDXSoundAudioOutputStream: Based on DirectSound or XAudio (future work). | 45 // - PCMDXSoundAudioOutputStream: Based on DirectSound or XAudio (future work). |
| 125 | |
| 126 AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, | 46 AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, |
| 127 int sample_rate, | 47 int sample_rate, |
| 128 char bits_per_sample) { | 48 char bits_per_sample) { |
| 129 if ((channels > kMaxChannels) || (channels <= 0) || | 49 if ((channels > kMaxChannels) || (channels <= 0) || |
| 130 (sample_rate > kMaxSampleRate) || (sample_rate <= 0) || | 50 (sample_rate > kMaxSampleRate) || (sample_rate <= 0) || |
| 131 (bits_per_sample > kMaxBitsPerSample) || (bits_per_sample <= 0)) | 51 (bits_per_sample > kMaxBitsPerSample) || (bits_per_sample <= 0)) |
| 132 return NULL; | 52 return NULL; |
| 133 | 53 |
| 134 if (format == AUDIO_MOCK) { | 54 if (format == AUDIO_MOCK) { |
| 135 return new AudioOutputStreamMockWin(this); | 55 return FakeAudioOutputStream::MakeFakeStream(); |
| 136 } else if (format == AUDIO_PCM_LINEAR) { | 56 } else if (format == AUDIO_PCM_LINEAR) { |
| 137 return new PCMWaveOutAudioOutputStream(this, channels, sample_rate, | 57 return new PCMWaveOutAudioOutputStream(this, channels, sample_rate, |
| 138 bits_per_sample, WAVE_MAPPER); | 58 bits_per_sample, WAVE_MAPPER); |
| 139 } | 59 } |
| 140 return NULL; | 60 return NULL; |
| 141 } | 61 } |
| 142 | 62 |
| 143 void AudioManagerWin::ReleaseStream(PCMWaveOutAudioOutputStream* stream) { | 63 void AudioManagerWin::ReleaseStream(PCMWaveOutAudioOutputStream* stream) { |
| 144 if (stream) | 64 if (stream) |
| 145 delete stream; | 65 delete stream; |
| 146 } | 66 } |
| 147 | 67 |
| 148 void AudioManagerWin::ReleaseStream(AudioOutputStreamMockWin *stream) { | |
| 149 // Note that we keep the last mock stream so GetLastMockBuffer() works. | |
| 150 ReplaceLastMockStream(stream); | |
| 151 } | |
| 152 | |
| 153 const void* AudioManagerWin::GetLastMockBuffer() { | |
| 154 return (g_last_mock_stream) ? g_last_mock_stream->buffer() : NULL; | |
| 155 } | |
| 156 | |
| 157 void AudioManagerWin::MuteAll() { | 68 void AudioManagerWin::MuteAll() { |
| 158 } | 69 } |
| 159 | 70 |
| 160 void AudioManagerWin::UnMuteAll() { | 71 void AudioManagerWin::UnMuteAll() { |
| 161 } | 72 } |
| 162 | 73 |
| 163 AudioManagerWin::~AudioManagerWin() { | 74 AudioManagerWin::~AudioManagerWin() { |
| 164 ReplaceLastMockStream(NULL); | |
| 165 } | 75 } |
| 166 | 76 |
| 167 void DestroyAudioManagerWin(void* param) { | 77 void DestroyAudioManagerWin(void* param) { |
| 168 delete g_audio_manager; | 78 delete g_audio_manager; |
| 169 g_audio_manager = NULL; | 79 g_audio_manager = NULL; |
| 170 } | 80 } |
| 171 | 81 |
| 172 AudioManager* AudioManager::GetAudioManager() { | 82 AudioManager* AudioManager::GetAudioManager() { |
| 173 if (!g_audio_manager) { | 83 if (!g_audio_manager) { |
| 174 g_audio_manager = new AudioManagerWin(); | 84 g_audio_manager = new AudioManagerWin(); |
| 175 base::AtExitManager::RegisterCallback(&DestroyAudioManagerWin, NULL); | 85 base::AtExitManager::RegisterCallback(&DestroyAudioManagerWin, NULL); |
| 176 } | 86 } |
| 177 return g_audio_manager; | 87 return g_audio_manager; |
| 178 } | 88 } |
| OLD | NEW |