diff options
Diffstat (limited to 'media/audio/win')
-rw-r--r-- | media/audio/win/audio_manager_win.h | 3 | ||||
-rw-r--r-- | media/audio/win/audio_output_win.cc | 94 | ||||
-rw-r--r-- | media/audio/win/audio_output_win_unittest.cc | 45 | ||||
-rw-r--r-- | media/audio/win/waveout_output_win.cc | 4 | ||||
-rw-r--r-- | media/audio/win/waveout_output_win.h | 1 |
5 files changed, 145 insertions, 2 deletions
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h index f060fc4..12a4c06 100644 --- a/media/audio/win/audio_manager_win.h +++ b/media/audio/win/audio_manager_win.h @@ -11,6 +11,7 @@ #include "media/audio/audio_output.h" class PCMWaveOutAudioOutputStream; +class AudioOutputStreamMockWin; // Windows implementation of the AudioManager singleton. This class is internal // to the audio output and only internal users can call methods not exposed by @@ -25,10 +26,12 @@ class AudioManagerWin : public AudioManager { char bits_per_sample); virtual void MuteAll(); virtual void UnMuteAll(); + virtual const void* GetLastMockBuffer(); // Windows-only methods to free a stream created in MakeAudioStream. These // are called internally by the audio stream when it has been closed. void ReleaseStream(PCMWaveOutAudioOutputStream* stream); + void ReleaseStream(AudioOutputStreamMockWin* stream); private: friend void DestroyAudioManagerWin(void *); diff --git a/media/audio/win/audio_output_win.cc b/media/audio/win/audio_output_win.cc index f7eac01..bc8c712 100644 --- a/media/audio/win/audio_output_win.cc +++ b/media/audio/win/audio_output_win.cc @@ -9,10 +9,81 @@ #include "base/at_exit.h" #include "base/basictypes.h" -#include "media/audio/fake_audio_output_stream.h" #include "media/audio/win/audio_manager_win.h" #include "media/audio/win/waveout_output_win.h" +// A do-nothing audio stream. It behaves like a regular audio stream but does +// not have any side effect, except possibly the creation and tear-down of +// of a thread. It is useful to test code that uses audio streams such as +// audio sources. +class AudioOutputStreamMockWin : public AudioOutputStream { + public: + explicit AudioOutputStreamMockWin(AudioManagerWin* manager) + : manager_(manager), + callback_(NULL), + buffer_(NULL), + packet_size_(0), + left_volume_(1.0), + right_volume_(1.0) { + } + + virtual ~AudioOutputStreamMockWin() { + delete[] buffer_; + packet_size_ = 0; + } + + virtual bool Open(size_t packet_size) { + if (packet_size < sizeof(int16)) + return false; + packet_size_ = packet_size; + buffer_ = new char[packet_size_]; + return true; + } + + virtual void Start(AudioSourceCallback* callback) { + callback_ = callback; + memset(buffer_, 0, packet_size_); + callback_->OnMoreData(this, buffer_, packet_size_); + } + + // TODO(cpu): flesh out Start and Stop methods. We need a thread to + // perform periodic callbacks. + virtual void Stop() { + } + + virtual void SetVolume(double left_level, double right_level) { + left_volume_ = left_level; + right_volume_ = right_level; + } + + virtual void GetVolume(double* left_level, double* right_level) { + *left_level = left_volume_; + *right_level = right_volume_; + } + + virtual size_t GetNumBuffers() { + return 1; + } + + virtual void Close() { + callback_->OnClose(this); + callback_ = NULL; + manager_->ReleaseStream(this); + } + + char* buffer() { + return buffer_; + } + + private: + AudioManagerWin* manager_; + AudioSourceCallback* callback_; + char* buffer_; + size_t packet_size_; + double left_volume_; + double right_volume_; +}; + namespace { // The next 3 constants are some sensible limits to prevent integer overflow @@ -31,10 +102,18 @@ const int kMaxChannels = 6; const int kMaxSampleRate = 192000; const int kMaxBitsPerSample = 64; +AudioOutputStreamMockWin* g_last_mock_stream = NULL; AudioManagerWin* g_audio_manager = NULL; +void ReplaceLastMockStream(AudioOutputStreamMockWin* newer) { + if (g_last_mock_stream) + delete g_last_mock_stream; + g_last_mock_stream = newer; +} + } // namespace. + bool AudioManagerWin::HasAudioDevices() { return (::waveOutGetNumDevs() != 0); } @@ -43,6 +122,7 @@ bool AudioManagerWin::HasAudioDevices() { // should suffice most windows user's needs. // - PCMWaveOutAudioOutputStream: Based on the waveOutWrite API (in progress) // - PCMDXSoundAudioOutputStream: Based on DirectSound or XAudio (future work). + AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, int sample_rate, char bits_per_sample) { @@ -52,7 +132,7 @@ AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, return NULL; if (format == AUDIO_MOCK) { - return FakeAudioOutputStream::MakeFakeStream(); + return new AudioOutputStreamMockWin(this); } else if (format == AUDIO_PCM_LINEAR) { return new PCMWaveOutAudioOutputStream(this, channels, sample_rate, bits_per_sample, WAVE_MAPPER); @@ -65,6 +145,15 @@ void AudioManagerWin::ReleaseStream(PCMWaveOutAudioOutputStream* stream) { delete stream; } +void AudioManagerWin::ReleaseStream(AudioOutputStreamMockWin *stream) { + // Note that we keep the last mock stream so GetLastMockBuffer() works. + ReplaceLastMockStream(stream); +} + +const void* AudioManagerWin::GetLastMockBuffer() { + return (g_last_mock_stream) ? g_last_mock_stream->buffer() : NULL; +} + void AudioManagerWin::MuteAll() { } @@ -72,6 +161,7 @@ void AudioManagerWin::UnMuteAll() { } AudioManagerWin::~AudioManagerWin() { + ReplaceLastMockStream(NULL); } void DestroyAudioManagerWin(void* param) { diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc index f47bd9c..fae74ac 100644 --- a/media/audio/win/audio_output_win_unittest.cc +++ b/media/audio/win/audio_output_win_unittest.cc @@ -193,6 +193,51 @@ TEST(WinAudioTest, MockStreamBasicCallbacks) { EXPECT_EQ(1, source.was_closed()); } +// Validate that the SineWaveAudioSource writes the expected values for +// the FORMAT_16BIT_MONO. The values are carefully selected so rounding issues +// do not affect the result. We also test that AudioManager::GetLastMockBuffer +// works. +// TODO(hclam): move this test to SimpleSourcesTest once mock audio stream is +// implemented on other platform. +TEST(WinAudioTest, SineWaveAudio16MonoTest) { + const size_t samples = 1024; + const size_t bytes_per_sample = 2; + const int freq = 200; + + SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, + freq, AudioManager::kTelephoneSampleRate); + + AudioManager* audio_man = AudioManager::GetAudioManager(); + ASSERT_TRUE(NULL != audio_man); + AudioOutputStream* oas = + audio_man->MakeAudioStream(AudioManager::AUDIO_MOCK, 1, + AudioManager::kTelephoneSampleRate, + bytes_per_sample * 2); + ASSERT_TRUE(NULL != oas); + EXPECT_TRUE(oas->Open(samples * bytes_per_sample)); + + oas->Start(&source); + oas->Stop(); + oas->Close(); + + const int16* last_buffer = + reinterpret_cast<const int16*>(audio_man->GetLastMockBuffer()); + ASSERT_TRUE(NULL != last_buffer); + + size_t half_period = AudioManager::kTelephoneSampleRate / (freq * 2); + + // Spot test positive incursion of sine wave. + EXPECT_EQ(0, last_buffer[0]); + EXPECT_EQ(5126, last_buffer[1]); + EXPECT_TRUE(last_buffer[1] < last_buffer[2]); + EXPECT_TRUE(last_buffer[2] < last_buffer[3]); + // Spot test negative incursion of sine wave. + EXPECT_EQ(0, last_buffer[half_period]); + EXPECT_EQ(-5126, last_buffer[half_period + 1]); + EXPECT_TRUE(last_buffer[half_period + 1] > last_buffer[half_period + 2]); + EXPECT_TRUE(last_buffer[half_period + 2] > last_buffer[half_period + 3]); +} + // =========================================================================== // Validation of AudioManager::AUDIO_PCM_LINEAR // diff --git a/media/audio/win/waveout_output_win.cc b/media/audio/win/waveout_output_win.cc index 124d8e7..d8d2ebdd 100644 --- a/media/audio/win/waveout_output_win.cc +++ b/media/audio/win/waveout_output_win.cc @@ -215,6 +215,10 @@ void PCMWaveOutAudioOutputStream::GetVolume(double* left_level, *right_level = volume_; } +size_t PCMWaveOutAudioOutputStream::GetNumBuffers() { + return kNumBuffers; +} + void PCMWaveOutAudioOutputStream::HandleError(MMRESULT error) { DLOG(WARNING) << "PCMWaveOutAudio error " << error; callback_->OnError(this, error); diff --git a/media/audio/win/waveout_output_win.h b/media/audio/win/waveout_output_win.h index 3f822e9..ea9bdef 100644 --- a/media/audio/win/waveout_output_win.h +++ b/media/audio/win/waveout_output_win.h @@ -40,6 +40,7 @@ class PCMWaveOutAudioOutputStream : public AudioOutputStream { virtual void Stop(); virtual void SetVolume(double left_level, double right_level); virtual void GetVolume(double* left_level, double* right_level); + virtual size_t GetNumBuffers(); // Sends a buffer to the audio driver for playback. void QueueNextPacket(WAVEHDR* buffer); |