OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // MSVC++ requires this to be set before any other includes to get M_PI. | 4 // MSVC++ requires this to be set before any other includes to get M_PI. |
5 #define _USE_MATH_DEFINES | 5 #define _USE_MATH_DEFINES |
6 | 6 |
7 #include "media/audio/simple_sources.h" | 7 #include "media/audio/simple_sources.h" |
8 | 8 |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 #include <cmath> | 12 #include <cmath> |
13 | 13 |
14 #include "base/files/file.h" | 14 #include "base/files/file.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/time/time.h" |
17 #include "media/audio/sounds/wav_audio_handler.h" | 18 #include "media/audio/sounds/wav_audio_handler.h" |
18 #include "media/base/audio_bus.h" | 19 #include "media/base/audio_bus.h" |
19 | 20 |
20 namespace media { | 21 namespace media { |
21 namespace { | 22 namespace { |
22 // Opens |wav_filename|, reads it and loads it as a wav file. This function will | 23 // Opens |wav_filename|, reads it and loads it as a wav file. This function will |
23 // return a null pointer if we can't read the file or if it's malformed. The | 24 // return a null pointer if we can't read the file or if it's malformed. The |
24 // caller takes ownership of the returned data. The size of the data is stored | 25 // caller takes ownership of the returned data. The size of the data is stored |
25 // in |read_length|. | 26 // in |read_length|. |
26 std::unique_ptr<char[]> ReadWavFile(const base::FilePath& wav_filename, | 27 std::unique_ptr<char[]> ReadWavFile(const base::FilePath& wav_filename, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 cap_(0), | 109 cap_(0), |
109 callbacks_(0), | 110 callbacks_(0), |
110 errors_(0) { | 111 errors_(0) { |
111 } | 112 } |
112 | 113 |
113 SineWaveAudioSource::~SineWaveAudioSource() { | 114 SineWaveAudioSource::~SineWaveAudioSource() { |
114 } | 115 } |
115 | 116 |
116 // The implementation could be more efficient if a lookup table is constructed | 117 // The implementation could be more efficient if a lookup table is constructed |
117 // but it is efficient enough for our simple needs. | 118 // but it is efficient enough for our simple needs. |
118 int SineWaveAudioSource::OnMoreData(AudioBus* audio_bus, | 119 int SineWaveAudioSource::OnMoreData(base::TimeDelta /* delay */, |
119 uint32_t total_bytes_delay, | 120 base::TimeTicks /* delay_timestamp */, |
120 uint32_t frames_skipped) { | 121 int /* prior_frames_skipped */, |
| 122 AudioBus* dest) { |
121 base::AutoLock auto_lock(time_lock_); | 123 base::AutoLock auto_lock(time_lock_); |
122 callbacks_++; | 124 callbacks_++; |
123 | 125 |
124 // The table is filled with s(t) = kint16max*sin(Theta*t), | 126 // The table is filled with s(t) = kint16max*sin(Theta*t), |
125 // where Theta = 2*PI*fs. | 127 // where Theta = 2*PI*fs. |
126 // We store the discrete time value |t| in a member to ensure that the | 128 // We store the discrete time value |t| in a member to ensure that the |
127 // next pass starts at a correct state. | 129 // next pass starts at a correct state. |
128 int max_frames = cap_ > 0 ? | 130 int max_frames = |
129 std::min(audio_bus->frames(), cap_ - time_state_) : audio_bus->frames(); | 131 cap_ > 0 ? std::min(dest->frames(), cap_ - time_state_) : dest->frames(); |
130 for (int i = 0; i < max_frames; ++i) | 132 for (int i = 0; i < max_frames; ++i) |
131 audio_bus->channel(0)[i] = sin(2.0 * M_PI * f_ * time_state_++); | 133 dest->channel(0)[i] = sin(2.0 * M_PI * f_ * time_state_++); |
132 for (int i = 1; i < audio_bus->channels(); ++i) { | 134 for (int i = 1; i < dest->channels(); ++i) { |
133 memcpy(audio_bus->channel(i), audio_bus->channel(0), | 135 memcpy(dest->channel(i), dest->channel(0), |
134 max_frames * sizeof(*audio_bus->channel(i))); | 136 max_frames * sizeof(*dest->channel(i))); |
135 } | 137 } |
136 return max_frames; | 138 return max_frames; |
137 } | 139 } |
138 | 140 |
139 void SineWaveAudioSource::OnError(AudioOutputStream* stream) { | 141 void SineWaveAudioSource::OnError(AudioOutputStream* stream) { |
140 errors_++; | 142 errors_++; |
141 } | 143 } |
142 | 144 |
143 void SineWaveAudioSource::CapSamples(int cap) { | 145 void SineWaveAudioSource::CapSamples(int cap) { |
144 base::AutoLock auto_lock(time_lock_); | 146 base::AutoLock auto_lock(time_lock_); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 AudioParameters::AUDIO_PCM_LOW_LATENCY, | 196 AudioParameters::AUDIO_PCM_LOW_LATENCY, |
195 GuessChannelLayout(wav_audio_handler_->num_channels()), | 197 GuessChannelLayout(wav_audio_handler_->num_channels()), |
196 wav_audio_handler_->sample_rate(), wav_audio_handler_->bits_per_sample(), | 198 wav_audio_handler_->sample_rate(), wav_audio_handler_->bits_per_sample(), |
197 params_.frames_per_buffer()); | 199 params_.frames_per_buffer()); |
198 | 200 |
199 file_audio_converter_.reset( | 201 file_audio_converter_.reset( |
200 new AudioConverter(file_audio_slice, params_, false)); | 202 new AudioConverter(file_audio_slice, params_, false)); |
201 file_audio_converter_->AddInput(this); | 203 file_audio_converter_->AddInput(this); |
202 } | 204 } |
203 | 205 |
204 int FileSource::OnMoreData(AudioBus* audio_bus, | 206 int FileSource::OnMoreData(base::TimeDelta /* delay */, |
205 uint32_t total_bytes_delay, | 207 base::TimeTicks /* delay_timestamp */, |
206 uint32_t frames_skipped) { | 208 int /* prior_frames_skipped */, |
| 209 AudioBus* dest) { |
207 // Load the file if we haven't already. This load needs to happen on the | 210 // Load the file if we haven't already. This load needs to happen on the |
208 // audio thread, otherwise we'll run on the UI thread on Mac for instance. | 211 // audio thread, otherwise we'll run on the UI thread on Mac for instance. |
209 // This will massively delay the first OnMoreData, but we'll catch up. | 212 // This will massively delay the first OnMoreData, but we'll catch up. |
210 if (!wav_audio_handler_) | 213 if (!wav_audio_handler_) |
211 LoadWavFile(path_to_wav_file_); | 214 LoadWavFile(path_to_wav_file_); |
212 if (load_failed_) | 215 if (load_failed_) |
213 return 0; | 216 return 0; |
214 | 217 |
215 DCHECK(wav_audio_handler_.get()); | 218 DCHECK(wav_audio_handler_.get()); |
216 | 219 |
217 if (wav_audio_handler_->AtEnd(wav_file_read_pos_)) { | 220 if (wav_audio_handler_->AtEnd(wav_file_read_pos_)) { |
218 if (looping_) | 221 if (looping_) |
219 Rewind(); | 222 Rewind(); |
220 else | 223 else |
221 return 0; | 224 return 0; |
222 } | 225 } |
223 | 226 |
224 // This pulls data from ProvideInput. | 227 // This pulls data from ProvideInput. |
225 file_audio_converter_->Convert(audio_bus); | 228 file_audio_converter_->Convert(dest); |
226 return audio_bus->frames(); | 229 return dest->frames(); |
227 } | 230 } |
228 | 231 |
229 void FileSource::Rewind() { | 232 void FileSource::Rewind() { |
230 wav_file_read_pos_ = 0; | 233 wav_file_read_pos_ = 0; |
231 } | 234 } |
232 | 235 |
233 double FileSource::ProvideInput(AudioBus* audio_bus_into_converter, | 236 double FileSource::ProvideInput(AudioBus* audio_bus_into_converter, |
234 uint32_t frames_delayed) { | 237 uint32_t frames_delayed) { |
235 // Unfilled frames will be zeroed by CopyTo. | 238 // Unfilled frames will be zeroed by CopyTo. |
236 size_t bytes_written; | 239 size_t bytes_written; |
(...skipping 14 matching lines...) Expand all Loading... |
251 beep_duration_in_buffers_(kBeepDurationMilliseconds * | 254 beep_duration_in_buffers_(kBeepDurationMilliseconds * |
252 params.sample_rate() / | 255 params.sample_rate() / |
253 params.frames_per_buffer() / | 256 params.frames_per_buffer() / |
254 1000), | 257 1000), |
255 beep_generated_in_buffers_(0), | 258 beep_generated_in_buffers_(0), |
256 beep_period_in_frames_(params.sample_rate() / kBeepFrequency) {} | 259 beep_period_in_frames_(params.sample_rate() / kBeepFrequency) {} |
257 | 260 |
258 BeepingSource::~BeepingSource() { | 261 BeepingSource::~BeepingSource() { |
259 } | 262 } |
260 | 263 |
261 int BeepingSource::OnMoreData(AudioBus* audio_bus, | 264 int BeepingSource::OnMoreData(base::TimeDelta /* delay */, |
262 uint32_t total_bytes_delay, | 265 base::TimeTicks /* delay_timestamp */, |
263 uint32_t frames_skipped) { | 266 int /* prior_frames_skipped */, |
| 267 AudioBus* dest) { |
264 // Accumulate the time from the last beep. | 268 // Accumulate the time from the last beep. |
265 interval_from_last_beep_ += base::TimeTicks::Now() - last_callback_time_; | 269 interval_from_last_beep_ += base::TimeTicks::Now() - last_callback_time_; |
266 | 270 |
267 memset(buffer_.get(), 0, buffer_size_); | 271 memset(buffer_.get(), 0, buffer_size_); |
268 bool should_beep = false; | 272 bool should_beep = false; |
269 BeepContext* beep_context = g_beep_context.Pointer(); | 273 BeepContext* beep_context = g_beep_context.Pointer(); |
270 if (beep_context->automatic_beep()) { | 274 if (beep_context->automatic_beep()) { |
271 base::TimeDelta delta = interval_from_last_beep_ - | 275 base::TimeDelta delta = interval_from_last_beep_ - |
272 base::TimeDelta::FromMilliseconds(kAutomaticBeepIntervalInMs); | 276 base::TimeDelta::FromMilliseconds(kAutomaticBeepIntervalInMs); |
273 if (delta > base::TimeDelta()) { | 277 if (delta > base::TimeDelta()) { |
(...skipping 23 matching lines...) Expand all Loading... |
297 // Then leave low values in the buffer with |high_bytes|. | 301 // Then leave low values in the buffer with |high_bytes|. |
298 position += high_bytes * 2; | 302 position += high_bytes * 2; |
299 } | 303 } |
300 | 304 |
301 ++beep_generated_in_buffers_; | 305 ++beep_generated_in_buffers_; |
302 if (beep_generated_in_buffers_ >= beep_duration_in_buffers_) | 306 if (beep_generated_in_buffers_ >= beep_duration_in_buffers_) |
303 beep_generated_in_buffers_ = 0; | 307 beep_generated_in_buffers_ = 0; |
304 } | 308 } |
305 | 309 |
306 last_callback_time_ = base::TimeTicks::Now(); | 310 last_callback_time_ = base::TimeTicks::Now(); |
307 audio_bus->FromInterleaved( | 311 dest->FromInterleaved(buffer_.get(), dest->frames(), |
308 buffer_.get(), audio_bus->frames(), params_.bits_per_sample() / 8); | 312 params_.bits_per_sample() / 8); |
309 return audio_bus->frames(); | 313 return dest->frames(); |
310 } | 314 } |
311 | 315 |
312 void BeepingSource::OnError(AudioOutputStream* stream) { | 316 void BeepingSource::OnError(AudioOutputStream* stream) { |
313 } | 317 } |
314 | 318 |
315 void BeepingSource::BeepOnce() { | 319 void BeepingSource::BeepOnce() { |
316 g_beep_context.Pointer()->SetBeepOnce(true); | 320 g_beep_context.Pointer()->SetBeepOnce(true); |
317 } | 321 } |
318 | 322 |
319 } // namespace media | 323 } // namespace media |
OLD | NEW |