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 // 5 // The format of these tests are to enqueue a known amount of data and then 6 // request the exact amount we expect in order to dequeue the known amount of 7 // data. This ensures that for any rate we are consuming input data at the 8 // correct rate. We always pass in a very large destination buffer with the 9 // expectation that FillBuffer() will fill as much as it can but no more. 10 11 #include <cmath> 12 13 #include "base/bind.h" 14 #include "base/callback.h" 15 #include "media/base/audio_buffer.h" 16 #include "media/base/audio_bus.h" 17 #include "media/base/buffers.h" 18 #include "media/base/channel_layout.h" 19 #include "media/base/test_helpers.h" 20 #include "media/filters/audio_renderer_algorithm.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace media { 24 25 static const int kFrameSize = 250; 26 static const int kSamplesPerSecond = 3000; 27 static const SampleFormat kSampleFormat = kSampleFormatS16; 28 29 class AudioRendererAlgorithmTest : public testing::Test { 30 public: 31 AudioRendererAlgorithmTest() 32 : frames_enqueued_(0), 33 channels_(0), 34 sample_format_(kUnknownSampleFormat), 35 bytes_per_sample_(0) { 36 } 37 38 virtual ~AudioRendererAlgorithmTest() {} 39 40 void Initialize() { 41 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 3000); 42 } 43 44 void Initialize(ChannelLayout channel_layout, 45 SampleFormat sample_format, 46 int samples_per_second) { 47 channels_ = ChannelLayoutToChannelCount(channel_layout); 48 sample_format_ = sample_format; 49 bytes_per_sample_ = SampleFormatToBytesPerChannel(sample_format); 50 AudioParameters params(media::AudioParameters::AUDIO_PCM_LINEAR, 51 channel_layout, 52 samples_per_second, 53 bytes_per_sample_ * 8, 54 samples_per_second / 100); 55 algorithm_.Initialize(1, params); 56 FillAlgorithmQueue(); 57 } 58 59 void FillAlgorithmQueue() { 60 // The value of the data is meaningless; we just want non-zero data to 61 // differentiate it from muted data. 62 scoped_refptr<AudioBuffer> buffer; 63 while (!algorithm_.IsQueueFull()) { 64 switch (sample_format_) { 65 case kSampleFormatU8: 66 buffer = MakeInterleavedAudioBuffer<uint8>(sample_format_, 67 channels_, 68 1, 69 1, 70 kFrameSize, 71 kNoTimestamp(), 72 kNoTimestamp()); 73 break; 74 case kSampleFormatS16: 75 buffer = MakeInterleavedAudioBuffer<int16>(sample_format_, 76 channels_, 77 1, 78 1, 79 kFrameSize, 80 kNoTimestamp(), 81 kNoTimestamp()); 82 break; 83 case kSampleFormatS32: 84 buffer = MakeInterleavedAudioBuffer<int32>(sample_format_, 85 channels_, 86 1, 87 1, 88 kFrameSize, 89 kNoTimestamp(), 90 kNoTimestamp()); 91 break; 92 default: 93 NOTREACHED() << "Unrecognized format " << sample_format_; 94 } 95 algorithm_.EnqueueBuffer(buffer); 96 frames_enqueued_ += kFrameSize; 97 } 98 } 99 100 void CheckFakeData(AudioBus* audio_data, int frames_written) { 101 // Check each channel individually. 102 for (int ch = 0; ch < channels_; ++ch) { 103 bool all_zero = true; 104 for (int i = 0; i < frames_written && all_zero; ++i) 105 all_zero = audio_data->channel(ch)[i] == 0.0f; 106 ASSERT_EQ(algorithm_.is_muted(), all_zero) << " for channel " << ch; 107 } 108 } 109 110 int ComputeConsumedFrames(int initial_frames_enqueued, 111 int initial_frames_buffered) { 112 int frame_delta = frames_enqueued_ - initial_frames_enqueued; 113 int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered; 114 int consumed = frame_delta - buffered_delta; 115 CHECK_GE(consumed, 0); 116 return consumed; 117 } 118 119 void TestPlaybackRate(double playback_rate) { 120 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100; 121 const int kDefaultFramesRequested = 2 * algorithm_.samples_per_second(); 122 123 TestPlaybackRate( 124 playback_rate, kDefaultBufferSize, kDefaultFramesRequested); 125 } 126 127 void TestPlaybackRate(double playback_rate, 128 int buffer_size_in_frames, 129 int total_frames_requested) { 130 int initial_frames_enqueued = frames_enqueued_; 131 int initial_frames_buffered = algorithm_.frames_buffered(); 132 algorithm_.SetPlaybackRate(static_cast<float>(playback_rate)); 133 134 scoped_ptr<AudioBus> bus = 135 AudioBus::Create(channels_, buffer_size_in_frames); 136 if (playback_rate == 0.0) { 137 int frames_written = 138 algorithm_.FillBuffer(bus.get(), buffer_size_in_frames); 139 EXPECT_EQ(0, frames_written); 140 return; 141 } 142 143 int frames_remaining = total_frames_requested; 144 while (frames_remaining > 0) { 145 int frames_requested = std::min(buffer_size_in_frames, frames_remaining); 146 int frames_written = algorithm_.FillBuffer(bus.get(), frames_requested); 147 ASSERT_GT(frames_written, 0) << "Requested: " << frames_requested 148 << ", playing at " << playback_rate; 149 CheckFakeData(bus.get(), frames_written); 150 frames_remaining -= frames_written; 151 152 FillAlgorithmQueue(); 153 } 154 155 int frames_consumed = 156 ComputeConsumedFrames(initial_frames_enqueued, initial_frames_buffered); 157 158 // If playing back at normal speed, we should always get back the same 159 // number of bytes requested. 160 if (playback_rate == 1.0) { 161 EXPECT_EQ(total_frames_requested, frames_consumed); 162 return; 163 } 164 165 // Otherwise, allow |kMaxAcceptableDelta| difference between the target and 166 // actual playback rate. 167 // When |kSamplesPerSecond| and |total_frames_requested| are reasonably 168 // large, one can expect less than a 1% difference in most cases. In our 169 // current implementation, sped up playback is less accurate than slowed 170 // down playback, and for playback_rate > 1, playback rate generally gets 171 // less and less accurate the farther it drifts from 1 (though this is 172 // nonlinear). 173 double actual_playback_rate = 174 1.0 * frames_consumed / total_frames_requested; 175 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0); 176 } 177 178 protected: 179 AudioRendererAlgorithm algorithm_; 180 int frames_enqueued_; 181 int channels_; 182 SampleFormat sample_format_; 183 int bytes_per_sample_; 184 }; 185 186 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) { 187 Initialize(); 188 TestPlaybackRate(1.0); 189 } 190 191 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalFasterRate) { 192 Initialize(); 193 TestPlaybackRate(1.0001); 194 } 195 196 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalSlowerRate) { 197 Initialize(); 198 TestPlaybackRate(0.9999); 199 } 200 201 TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAQuarterRate) { 202 Initialize(); 203 TestPlaybackRate(1.25); 204 } 205 206 TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAHalfRate) { 207 Initialize(); 208 TestPlaybackRate(1.5); 209 } 210 211 TEST_F(AudioRendererAlgorithmTest, FillBuffer_DoubleRate) { 212 Initialize(); 213 TestPlaybackRate(2.0); 214 } 215 216 TEST_F(AudioRendererAlgorithmTest, FillBuffer_EightTimesRate) { 217 Initialize(); 218 TestPlaybackRate(8.0); 219 } 220 221 TEST_F(AudioRendererAlgorithmTest, FillBuffer_ThreeQuartersRate) { 222 Initialize(); 223 TestPlaybackRate(0.75); 224 } 225 226 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HalfRate) { 227 Initialize(); 228 TestPlaybackRate(0.5); 229 } 230 231 TEST_F(AudioRendererAlgorithmTest, FillBuffer_QuarterRate) { 232 Initialize(); 233 TestPlaybackRate(0.25); 234 } 235 236 TEST_F(AudioRendererAlgorithmTest, FillBuffer_Pause) { 237 Initialize(); 238 TestPlaybackRate(0.0); 239 } 240 241 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SlowDown) { 242 Initialize(); 243 TestPlaybackRate(4.5); 244 TestPlaybackRate(3.0); 245 TestPlaybackRate(2.0); 246 TestPlaybackRate(1.0); 247 TestPlaybackRate(0.5); 248 TestPlaybackRate(0.25); 249 } 250 251 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SpeedUp) { 252 Initialize(); 253 TestPlaybackRate(0.25); 254 TestPlaybackRate(0.5); 255 TestPlaybackRate(1.0); 256 TestPlaybackRate(2.0); 257 TestPlaybackRate(3.0); 258 TestPlaybackRate(4.5); 259 } 260 261 TEST_F(AudioRendererAlgorithmTest, FillBuffer_JumpAroundSpeeds) { 262 Initialize(); 263 TestPlaybackRate(2.1); 264 TestPlaybackRate(0.9); 265 TestPlaybackRate(0.6); 266 TestPlaybackRate(1.4); 267 TestPlaybackRate(0.3); 268 } 269 270 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) { 271 Initialize(); 272 static const int kBufferSizeInFrames = 1; 273 static const int kFramesRequested = 2 * kSamplesPerSecond; 274 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested); 275 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested); 276 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested); 277 } 278 279 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) { 280 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100); 281 TestPlaybackRate(1.0); 282 TestPlaybackRate(0.5); 283 TestPlaybackRate(1.5); 284 } 285 286 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) { 287 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond); 288 TestPlaybackRate(1.0); 289 TestPlaybackRate(0.5); 290 TestPlaybackRate(1.5); 291 } 292 293 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) { 294 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond); 295 TestPlaybackRate(1.0); 296 TestPlaybackRate(0.5); 297 TestPlaybackRate(1.5); 298 } 299 300 } // namespace media 301