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
3 // found in the LICENSE file.
4 // MSVC++ requires this to be set before any other includes to get M_PI.
5 #define _USE_MATH_DEFINES
8 #include "media/audio/simple_sources.h"
12 #include "base/files/file.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "media/audio/sounds/wav_audio_handler.h"
16 #include "media/base/audio_bus.h"
20 // Opens |wav_filename|, reads it and loads it as a wav file. This function will
21 // bluntly trigger CHECKs if we can't read the file or if it's malformed. The
22 // caller takes ownership of the returned data. The size of the data is stored
24 static scoped_ptr
<uint8
[]> ReadWavFile(const base::FilePath
& wav_filename
,
25 size_t* file_length
) {
27 wav_filename
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
28 CHECK(wav_file
.IsValid())
29 << "Failed to read " << wav_filename
.value()
30 << " as input to the fake device.";
32 size_t wav_file_length
= wav_file
.GetLength();
33 CHECK_GT(wav_file_length
, 0u)
34 << "Input file to fake device is empty: " << wav_filename
.value();
36 uint8
* wav_file_data
= new uint8
[wav_file_length
];
37 size_t read_bytes
= wav_file
.Read(0, reinterpret_cast<char*>(wav_file_data
),
39 CHECK_EQ(read_bytes
, wav_file_length
)
40 << "Failed to read all bytes of " << wav_filename
.value();
41 *file_length
= wav_file_length
;
42 return scoped_ptr
<uint8
[]>(wav_file_data
);
45 // Opens |wav_filename|, reads it and loads it as a wav file. This function will
46 // bluntly trigger CHECKs if we can't read the file or if it's malformed.
47 static scoped_ptr
<WavAudioHandler
> CreateWavAudioHandler(
48 const base::FilePath
& wav_filename
, const uint8
* wav_file_data
,
49 size_t wav_file_length
, const AudioParameters
& expected_params
) {
50 base::StringPiece
wav_data(reinterpret_cast<const char*>(wav_file_data
),
52 scoped_ptr
<WavAudioHandler
> wav_audio_handler(new WavAudioHandler(wav_data
));
53 return wav_audio_handler
.Pass();
56 // These values are based on experiments for local-to-local
57 // PeerConnection to demonstrate audio/video synchronization.
58 static const int kBeepDurationMilliseconds
= 20;
59 static const int kBeepFrequency
= 400;
61 // Intervals between two automatic beeps.
62 static const int kAutomaticBeepIntervalInMs
= 500;
64 // Automatic beep will be triggered every |kAutomaticBeepIntervalInMs| unless
65 // users explicitly call BeepOnce(), which will disable the automatic beep.
68 BeepContext() : beep_once_(false), automatic_beep_(true) {}
70 void SetBeepOnce(bool enable
) {
71 base::AutoLock
auto_lock(lock_
);
74 // Disable the automatic beep if users explicit set |beep_once_| to true.
76 automatic_beep_
= false;
79 bool beep_once() const {
80 base::AutoLock
auto_lock(lock_
);
84 bool automatic_beep() const {
85 base::AutoLock
auto_lock(lock_
);
86 return automatic_beep_
;
90 mutable base::Lock lock_
;
95 static base::LazyInstance
<BeepContext
>::Leaky g_beep_context
=
96 LAZY_INSTANCE_INITIALIZER
;
98 //////////////////////////////////////////////////////////////////////////////
99 // SineWaveAudioSource implementation.
101 SineWaveAudioSource::SineWaveAudioSource(int channels
,
102 double freq
, double sample_freq
)
103 : channels_(channels
),
104 f_(freq
/ sample_freq
),
111 SineWaveAudioSource::~SineWaveAudioSource() {
114 // The implementation could be more efficient if a lookup table is constructed
115 // but it is efficient enough for our simple needs.
116 int SineWaveAudioSource::OnMoreData(AudioBus
* audio_bus
,
117 uint32 total_bytes_delay
) {
118 base::AutoLock
auto_lock(time_lock_
);
121 // The table is filled with s(t) = kint16max*sin(Theta*t),
122 // where Theta = 2*PI*fs.
123 // We store the discrete time value |t| in a member to ensure that the
124 // next pass starts at a correct state.
125 int max_frames
= cap_
> 0 ?
126 std::min(audio_bus
->frames(), cap_
- time_state_
) : audio_bus
->frames();
127 for (int i
= 0; i
< max_frames
; ++i
)
128 audio_bus
->channel(0)[i
] = sin(2.0 * M_PI
* f_
* time_state_
++);
129 for (int i
= 1; i
< audio_bus
->channels(); ++i
) {
130 memcpy(audio_bus
->channel(i
), audio_bus
->channel(0),
131 max_frames
* sizeof(*audio_bus
->channel(i
)));
136 void SineWaveAudioSource::OnError(AudioOutputStream
* stream
) {
140 void SineWaveAudioSource::CapSamples(int cap
) {
141 base::AutoLock
auto_lock(time_lock_
);
146 void SineWaveAudioSource::Reset() {
147 base::AutoLock
auto_lock(time_lock_
);
151 FileSource::FileSource(const AudioParameters
& params
,
152 const base::FilePath
& path_to_wav_file
)
154 path_to_wav_file_(path_to_wav_file
),
155 wav_file_read_pos_(0) {
158 FileSource::~FileSource() {
161 void FileSource::LoadWavFile(const base::FilePath
& path_to_wav_file
) {
162 // Read the file, and put its data in a scoped_ptr so it gets deleted later.
163 size_t file_length
= 0;
164 wav_file_data_
= ReadWavFile(path_to_wav_file
, &file_length
);
165 wav_audio_handler_
= CreateWavAudioHandler(
166 path_to_wav_file
, wav_file_data_
.get(), file_length
, params_
);
168 // Hook us up so we pull in data from the file into the converter. We need to
169 // modify the wav file's audio parameters since we'll be reading small slices
170 // of it at a time and not the whole thing (like 10 ms at a time).
171 AudioParameters
file_audio_slice(
172 wav_audio_handler_
->params().format(),
173 wav_audio_handler_
->params().channel_layout(),
174 wav_audio_handler_
->params().sample_rate(),
175 wav_audio_handler_
->params().bits_per_sample(),
176 params_
.frames_per_buffer());
178 file_audio_converter_
.reset(
179 new AudioConverter(file_audio_slice
, params_
, false));
180 file_audio_converter_
->AddInput(this);
183 int FileSource::OnMoreData(AudioBus
* audio_bus
, uint32 total_bytes_delay
) {
184 // Load the file if we haven't already. This load needs to happen on the
185 // audio thread, otherwise we'll run on the UI thread on Mac for instance.
186 // This will massively delay the first OnMoreData, but we'll catch up.
187 if (!wav_audio_handler_
)
188 LoadWavFile(path_to_wav_file_
);
190 DCHECK(wav_audio_handler_
.get());
192 // Stop playing if we've played out the whole file.
193 if (wav_audio_handler_
->AtEnd(wav_file_read_pos_
))
196 // This pulls data from ProvideInput.
197 file_audio_converter_
->Convert(audio_bus
);
198 return audio_bus
->frames();
201 double FileSource::ProvideInput(AudioBus
* audio_bus_into_converter
,
202 base::TimeDelta buffer_delay
) {
203 // Unfilled frames will be zeroed by CopyTo.
204 size_t bytes_written
;
205 wav_audio_handler_
->CopyTo(audio_bus_into_converter
, wav_file_read_pos_
,
207 wav_file_read_pos_
+= bytes_written
;
211 void FileSource::OnError(AudioOutputStream
* stream
) {
214 BeepingSource::BeepingSource(const AudioParameters
& params
)
215 : buffer_size_(params
.GetBytesPerBuffer()),
216 buffer_(new uint8
[buffer_size_
]),
218 last_callback_time_(base::TimeTicks::Now()),
219 beep_duration_in_buffers_(kBeepDurationMilliseconds
*
220 params
.sample_rate() /
221 params
.frames_per_buffer() /
223 beep_generated_in_buffers_(0),
224 beep_period_in_frames_(params
.sample_rate() / kBeepFrequency
) {
227 BeepingSource::~BeepingSource() {
230 int BeepingSource::OnMoreData(AudioBus
* audio_bus
, uint32 total_bytes_delay
) {
231 // Accumulate the time from the last beep.
232 interval_from_last_beep_
+= base::TimeTicks::Now() - last_callback_time_
;
234 memset(buffer_
.get(), 0, buffer_size_
);
235 bool should_beep
= false;
236 BeepContext
* beep_context
= g_beep_context
.Pointer();
237 if (beep_context
->automatic_beep()) {
238 base::TimeDelta delta
= interval_from_last_beep_
-
239 base::TimeDelta::FromMilliseconds(kAutomaticBeepIntervalInMs
);
240 if (delta
> base::TimeDelta()) {
242 interval_from_last_beep_
= delta
;
245 should_beep
= beep_context
->beep_once();
246 beep_context
->SetBeepOnce(false);
249 // If this object was instructed to generate a beep or has started to
250 // generate a beep sound.
251 if (should_beep
|| beep_generated_in_buffers_
) {
252 // Compute the number of frames to output high value. Then compute the
253 // number of bytes based on channels and bits per channel.
254 int high_frames
= beep_period_in_frames_
/ 2;
255 int high_bytes
= high_frames
* params_
.bits_per_sample() *
256 params_
.channels() / 8;
258 // Separate high and low with the same number of bytes to generate a
261 while (position
+ high_bytes
<= buffer_size_
) {
262 // Write high values first.
263 memset(buffer_
.get() + position
, 128, high_bytes
);
264 // Then leave low values in the buffer with |high_bytes|.
265 position
+= high_bytes
* 2;
268 ++beep_generated_in_buffers_
;
269 if (beep_generated_in_buffers_
>= beep_duration_in_buffers_
)
270 beep_generated_in_buffers_
= 0;
273 last_callback_time_
= base::TimeTicks::Now();
274 audio_bus
->FromInterleaved(
275 buffer_
.get(), audio_bus
->frames(), params_
.bits_per_sample() / 8);
276 return audio_bus
->frames();
279 void BeepingSource::OnError(AudioOutputStream
* stream
) {
282 void BeepingSource::BeepOnce() {
283 g_beep_context
.Pointer()->SetBeepOnce(true);