diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/simple_sources.cc | 18 | ||||
-rw-r--r-- | media/audio/simple_sources.h | 1 | ||||
-rw-r--r-- | media/audio/win/audio_output_win_unittest.cc | 59 |
3 files changed, 28 insertions, 50 deletions
diff --git a/media/audio/simple_sources.cc b/media/audio/simple_sources.cc index 4cd0ba3..4078315 100644 --- a/media/audio/simple_sources.cc +++ b/media/audio/simple_sources.cc @@ -21,8 +21,7 @@ SineWaveAudioSource::SineWaveAudioSource(Format format, int channels, : format_(format), channels_(channels), freq_(freq), - sample_freq_(sample_freq), - time_state_(0) { + sample_freq_(sample_freq) { // TODO(cpu): support other formats. DCHECK((format_ == FORMAT_16BIT_LINEAR_PCM) && (channels_ == 1)); } @@ -32,19 +31,14 @@ SineWaveAudioSource::SineWaveAudioSource(Format format, int channels, uint32 SineWaveAudioSource::OnMoreData( AudioOutputStream* stream, uint8* dest, uint32 max_size, AudioBuffersState audio_buffers) { - const double kTwoPi = 2.0 * 3.141592653589793; + const double kTwoPi = 2.0 * 3.141592653589; double f = freq_ / sample_freq_; int16* sin_tbl = reinterpret_cast<int16*>(dest); uint32 len = max_size / sizeof(int16); - - // The table is filled with s(t) = kint16max*sin(Theta*t), - // where Theta = 2*PI*fs. - // We store the discrete time value |t| in a member to ensure that the - // next pass starts at a correct state. - for (uint32 n = 0; n < len; ++n) { - double theta = kTwoPi * f; - sin_tbl[n] = static_cast<int16>(kint16max * sin(theta * time_state_)); - ++time_state_; + // The table is filled with s(t) = 32768*sin(2PI*f*t). + for (uint32 ix = 0; ix != len; ++ix) { + double th = kTwoPi * ix * f; + sin_tbl[ix] = static_cast<int16>((1 << 15) * sin(th)); } return max_size; } diff --git a/media/audio/simple_sources.h b/media/audio/simple_sources.h index a4373a0..dd2782c 100644 --- a/media/audio/simple_sources.h +++ b/media/audio/simple_sources.h @@ -36,7 +36,6 @@ class MEDIA_EXPORT SineWaveAudioSource int channels_; double freq_; double sample_freq_; - int time_state_; }; // Defines an interface for pushing audio output. In contrast, the interfaces diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc index d2447c5..4fcc5c8 100644 --- a/media/audio/win/audio_output_win_unittest.cc +++ b/media/audio/win/audio_output_win_unittest.cc @@ -10,11 +10,7 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/sync_socket.h" -#include "base/win/scoped_com_initializer.h" -#include "base/win/windows_version.h" -#include "media/base/limits.h" #include "media/audio/audio_io.h" -#include "media/audio/audio_util.h" #include "media/audio/audio_manager.h" #include "media/audio/simple_sources.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,8 +25,6 @@ using ::testing::NiceMock; using ::testing::NotNull; using ::testing::Return; -using base::win::ScopedCOMInitializer; - static const wchar_t kAudioFile1_16b_m_16K[] = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; @@ -237,7 +231,7 @@ TEST(WinAudioTest, PCMWaveStreamGetAndClose) { oas->Close(); } -// Test that can it be cannot be created with invalid parameters. +// Test that can it be cannot be created with crazy parameters TEST(WinAudioTest, SanityOnMakeParams) { if (IsRunningHeadless()) return; @@ -261,8 +255,7 @@ TEST(WinAudioTest, SanityOnMakeParams) { EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0))); EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, - media::Limits::kMaxSamplesPerPacket + 1))); + AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 100000))); } // Test that it can be opened and closed. @@ -540,10 +533,11 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { oas->Close(); } -// With the low latency mode, WASAPI is utilized by default for Vista and -// higher and Wave is used for XP and lower. It is possible to utilize a -// smaller buffer size for WASAPI than for Wave. -TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) { +// With the low latency mode, we have two buffers instead of 3 and we +// should be able to handle 20ms buffers at 44KHz. See also the SyncSocketBasic +// test below. +// TODO(cpu): right now the best we can do is 50ms before it sounds choppy. +TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44KssLowLatency) { if (IsRunningHeadless()) return; AudioManager* audio_man = AudioManager::GetAudioManager(); @@ -551,23 +545,15 @@ TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) { if (!audio_man->HasAudioOutputDevices()) return; - // The WASAPI API requires a correct COM environment. - ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); - - // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave. - // Take the existing native sample rate into account. - int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate()); - uint32 samples_10_ms = sample_rate / 100; - int n = 1; - (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; + uint32 samples_50_ms = AudioParameters::kAudioCDSampleRate / 20; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, - CHANNEL_LAYOUT_MONO, sample_rate, - 16, n * samples_10_ms)); + CHANNEL_LAYOUT_MONO, AudioParameters::kAudioCDSampleRate, + 16, samples_50_ms)); ASSERT_TRUE(NULL != oas); SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, - 200.0, sample_rate); + 200.0, AudioParameters::kAudioCDSampleRate); EXPECT_TRUE(oas->Open()); oas->SetVolume(1.0); @@ -665,7 +651,7 @@ struct SyncThreadContext { base::SyncSocket* socket; int sample_rate; double sine_freq; - uint32 packet_size_bytes; + uint32 packet_size; }; // This thread provides the data that the SyncSocketSource above needs @@ -686,11 +672,11 @@ DWORD __stdcall SyncSocketThread(void* context) { AudioBuffersState buffers_state; int times = 0; - for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size_bytes) { + for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size) { if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) break; if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); - ctx.socket->Send(&buffer[ix], ctx.packet_size_bytes); + ctx.socket->Send(&buffer[ix], ctx.packet_size); ++times; } @@ -699,13 +685,11 @@ DWORD __stdcall SyncSocketThread(void* context) { } // Test the basic operation of AudioOutputStream used with a SyncSocket. -// The emphasis is to verify that it is possible to feed data to the audio -// layer using a source based on SyncSocket. In a real situation we would -// go for the low-latency version in combination with SyncSocket, but to keep -// the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main -// principle of the test still remains and we avoid the additional complexity -// related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. -// In this test you should hear a continuous 200Hz tone for 2 seconds. +// The emphasis is to test low-latency with buffers less than 100ms. With +// the waveout api it seems not possible to go below 50ms. In this test +// you should hear a continous 200Hz tone. +// +// TODO(cpu): This actually sounds choppy most of the time. Fix it. TEST(WinAudioTest, SyncSocketBasic) { if (IsRunningHeadless()) return; @@ -718,10 +702,11 @@ TEST(WinAudioTest, SyncSocketBasic) { int sample_rate = AudioParameters::kAudioCDSampleRate; const uint32 kSamples20ms = sample_rate / 50; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( - AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, + AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms)); ASSERT_TRUE(NULL != oas); + // compute buffer size for 20ms of audio, 882 samples (mono). ASSERT_TRUE(oas->Open()); base::SyncSocket* sockets[2]; @@ -732,7 +717,7 @@ TEST(WinAudioTest, SyncSocketBasic) { SyncThreadContext thread_context; thread_context.sample_rate = sample_rate; thread_context.sine_freq = 200.0; - thread_context.packet_size_bytes = kSamples20ms * 2; + thread_context.packet_size = kSamples20ms; thread_context.socket = sockets[1]; HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, |