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 |