1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
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.
11 #include "media/filters/audio_renderer_algorithm.h"
16 #include <algorithm> // For std::min().
21 #include "base/functional/bind.h"
22 #include "base/functional/callback.h"
23 #include "media/base/audio_buffer.h"
24 #include "media/base/audio_bus.h"
25 #include "media/base/audio_timestamp_helper.h"
26 #include "media/base/channel_layout.h"
27 #include "media/base/media_util.h"
28 #include "media/base/test_helpers.h"
29 #include "media/base/timestamp_constants.h"
30 #include "media/filters/wsola_internals.h"
31 #include "testing/gtest/include/gtest/gtest.h"
35 const int kFrameSize = 250;
36 const int kSamplesPerSecond = 3000;
37 const int kOutputDurationInSec = 10;
39 static void FillWithSquarePulseTrain(
40 int half_pulse_width, int offset, int num_samples, float* data) {
42 ASSERT_LE(offset, num_samples);
44 // Fill backward from |offset| - 1 toward zero, starting with -1, alternating
45 // between -1 and 1 every |pulse_width| samples.
47 for (int n = offset - 1, k = 0; n >= 0; --n, ++k) {
48 if (k >= half_pulse_width) {
55 // Fill forward from |offset| towards the end, starting with 1, alternating
56 // between 1 and -1 every |pulse_width| samples.
58 for (int n = offset, k = 0; n < num_samples; ++n, ++k) {
59 if (k >= half_pulse_width) {
67 static void FillWithSquarePulseTrain(
68 int half_pulse_width, int offset, int channel, AudioBus* audio_bus) {
69 FillWithSquarePulseTrain(half_pulse_width, offset, audio_bus->frames(),
70 audio_bus->channel(channel));
73 class AudioRendererAlgorithmTest : public testing::Test {
75 AudioRendererAlgorithmTest()
76 : algorithm_(&media_log_),
79 channel_layout_(CHANNEL_LAYOUT_NONE),
80 sample_format_(kUnknownSampleFormat),
81 samples_per_second_(0),
82 bytes_per_sample_(0) {}
84 ~AudioRendererAlgorithmTest() override = default;
87 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, kSamplesPerSecond,
88 kSamplesPerSecond / 10);
91 void Initialize(ChannelLayout channel_layout,
92 SampleFormat sample_format,
93 int samples_per_second,
94 int frames_per_buffer) {
96 channel_layout, sample_format, samples_per_second, frames_per_buffer,
97 std::vector<bool>(ChannelLayoutToChannelCount(channel_layout), true));
100 void Initialize(ChannelLayout channel_layout,
101 SampleFormat sample_format,
102 int samples_per_second,
103 int frames_per_buffer,
104 std::vector<bool> channel_mask) {
105 channels_ = ChannelLayoutToChannelCount(channel_layout);
106 samples_per_second_ = samples_per_second;
107 channel_layout_ = channel_layout;
108 sample_format_ = sample_format;
109 bytes_per_sample_ = SampleFormatToBytesPerChannel(sample_format);
111 media::AudioParameters::Format format =
112 media::AudioParameters::AUDIO_PCM_LINEAR;
113 if (sample_format == kSampleFormatAc3)
114 format = media::AudioParameters::AUDIO_BITSTREAM_AC3;
115 else if (sample_format == kSampleFormatEac3)
116 format = media::AudioParameters::AUDIO_BITSTREAM_EAC3;
117 else if (sample_format == kSampleFormatDts)
118 format = media::AudioParameters::AUDIO_BITSTREAM_DTS;
120 AudioParameters params(format,
121 ChannelLayoutConfig(channel_layout, channels_),
122 samples_per_second, frames_per_buffer);
123 is_bitstream_format_ = params.IsBitstreamFormat();
124 bool is_encrypted = false;
125 algorithm_.Initialize(params, is_encrypted);
126 algorithm_.SetChannelMask(std::move(channel_mask));
127 FillAlgorithmQueueUntilFull();
130 base::TimeDelta BufferedTime() {
131 return AudioTimestampHelper::FramesToTime(algorithm_.BufferedFrames(),
132 samples_per_second_);
135 scoped_refptr<AudioBuffer> MakeBuffer(int frame_size) {
136 // The value of the data is meaningless; we just want non-zero data to
137 // differentiate it from muted data.
138 scoped_refptr<AudioBuffer> buffer;
139 switch (sample_format_) {
140 case kSampleFormatAc3:
141 case kSampleFormatEac3:
142 buffer = MakeBitstreamAudioBuffer(
143 sample_format_, channel_layout_,
144 ChannelLayoutToChannelCount(channel_layout_), samples_per_second_,
145 1, 1, frame_size, kFrameSize, kNoTimestamp);
147 case kSampleFormatU8:
148 buffer = MakeAudioBuffer<uint8_t>(
149 sample_format_, channel_layout_,
150 ChannelLayoutToChannelCount(channel_layout_), samples_per_second_,
151 1, 1, frame_size, kNoTimestamp);
153 case kSampleFormatS16:
154 buffer = MakeAudioBuffer<int16_t>(
155 sample_format_, channel_layout_,
156 ChannelLayoutToChannelCount(channel_layout_), samples_per_second_,
157 1, 1, frame_size, kNoTimestamp);
159 case kSampleFormatS32:
160 buffer = MakeAudioBuffer<int32_t>(
161 sample_format_, channel_layout_,
162 ChannelLayoutToChannelCount(channel_layout_), samples_per_second_,
163 1, 1, frame_size, kNoTimestamp);
165 case kSampleFormatDts:
166 case kSampleFormatDtse:
167 case kSampleFormatDtsxP2:
168 buffer = MakeBitstreamAudioBuffer(
169 sample_format_, channel_layout_,
170 ChannelLayoutToChannelCount(channel_layout_), samples_per_second_,
171 1, 1, frame_size, kFrameSize, kNoTimestamp);
174 NOTREACHED() << "Unrecognized format " << sample_format_;
179 void FillAlgorithmQueueUntilAdequate() {
180 // Note: "adequate" may be <= "full" depending on current latency hint.
181 EXPECT_FALSE(algorithm_.IsQueueFull());
182 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
183 while (!algorithm_.IsQueueAdequateForPlayback()) {
184 // "Adequate" tests may be sensitive to over-filling. Only add one buffer
185 // at a time to trigger "adequate" threshold precisely.
186 algorithm_.EnqueueBuffer(MakeBuffer(1));
190 void FillAlgorithmQueueUntilFull() {
191 while (!algorithm_.IsQueueFull()) {
192 algorithm_.EnqueueBuffer(MakeBuffer(kFrameSize));
193 frames_enqueued_ += kFrameSize;
197 bool VerifyAudioData(AudioBus* bus, int offset, int frames, float value) {
198 for (int ch = 0; ch < bus->channels(); ++ch) {
199 for (int i = offset; i < offset + frames; ++i) {
200 if (bus->channel(ch)[i] != value)
207 bool AudioDataIsMuted(AudioBus* audio_data, int frames_written, int offset) {
208 return VerifyAudioData(audio_data, offset, frames_written, 0);
211 int ComputeConsumedFrames(int initial_frames_enqueued,
212 int initial_frames_buffered) {
213 int frame_delta = frames_enqueued_ - initial_frames_enqueued;
214 int buffered_delta = algorithm_.BufferedFrames() - initial_frames_buffered;
215 int consumed = frame_delta - buffered_delta;
217 CHECK_GE(consumed, 0);
221 void TestPlaybackRate(double playback_rate) {
222 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100;
223 const int kDefaultFramesRequested = kOutputDurationInSec *
224 algorithm_.samples_per_second();
226 TestPlaybackRate(playback_rate, kDefaultBufferSize, kDefaultFramesRequested,
230 void TestPlaybackRate(double playback_rate,
231 int buffer_size_in_frames,
232 int total_frames_requested,
234 int initial_frames_enqueued = frames_enqueued_;
236 std::unique_ptr<AudioBus> bus =
237 AudioBus::Create(channels_, buffer_size_in_frames);
238 bus->ZeroFrames(dest_offset);
240 if (playback_rate == 0.0) {
241 int frames_written = algorithm_.FillBuffer(
242 bus.get(), 0, buffer_size_in_frames, playback_rate);
243 EXPECT_EQ(0, frames_written);
247 if (!is_bitstream_format_) {
248 // When we switch playback rates (specifically from non-1.0 to 1.0), the
249 // BufferedFrames() can change since some internal buffers are cleared.
250 // Fill 0 frames to make sure the BufferedFrames() is correct for the
252 algorithm_.FillBuffer(bus.get(), 0, 0, playback_rate);
254 int initial_frames_buffered = algorithm_.BufferedFrames();
256 int frames_remaining = total_frames_requested;
257 bool first_fill_buffer = true;
258 while (frames_remaining > 0) {
259 int frames_requested =
260 std::min(buffer_size_in_frames - dest_offset, frames_remaining);
261 int frames_written = algorithm_.FillBuffer(
262 bus.get(), dest_offset, frames_requested, playback_rate);
263 ASSERT_GT(frames_written, 0) << "Requested: " << frames_requested
264 << ", playing at " << playback_rate;
266 // Do not check data if it is first pull out and only one frame written.
267 // The very first frame out of WSOLA is always zero because of
268 // overlap-and-add window, which is zero for the first sample. Therefore,
269 // if at very first buffer-fill only one frame is written, that is zero
270 // which might cause exception in CheckFakeData().
271 if (!first_fill_buffer || frames_written > 1)
272 ASSERT_FALSE(AudioDataIsMuted(bus.get(), frames_written, dest_offset));
273 first_fill_buffer = false;
274 frames_remaining -= frames_written;
276 FillAlgorithmQueueUntilFull();
279 EXPECT_EQ(algorithm_.BufferedFrames() * channels_ * sizeof(float),
280 static_cast<size_t>(algorithm_.GetMemoryUsage()));
282 int frames_consumed =
283 ComputeConsumedFrames(initial_frames_enqueued, initial_frames_buffered);
285 // If playing back at normal speed, we should always get back the same
286 // number of bytes requested.
287 if (playback_rate == 1.0) {
288 EXPECT_EQ(total_frames_requested, frames_consumed);
292 // Otherwise, allow |kMaxAcceptableDelta| difference between the target and
293 // actual playback rate.
294 // When |kSamplesPerSecond| and |total_frames_requested| are reasonably
295 // large, one can expect less than a 1% difference in most cases. In our
296 // current implementation, sped up playback is less accurate than slowed
297 // down playback, and for playback_rate > 1, playback rate generally gets
298 // less and less accurate the farther it drifts from 1 (though this is
300 double actual_playback_rate =
301 1.0 * frames_consumed / total_frames_requested;
302 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0);
305 void TestResamplingWithUnderflow(double playback_rate, bool end_of_stream) {
306 // We are only testing the behavior of the resampling case.
307 algorithm_.SetPreservesPitch(false);
310 algorithm_.MarkEndOfStream();
312 algorithm_.FlushBuffers();
315 const int buffer_size_in_frames = algorithm_.samples_per_second() / 10;
316 const int initial_frames_enqueued = frames_enqueued_;
318 std::unique_ptr<AudioBus> bus =
319 AudioBus::Create(channels_, buffer_size_in_frames);
321 FillAlgorithmQueueUntilFull();
324 int total_frames_written = 0;
326 frames_written = algorithm_.FillBuffer(
327 bus.get(), 0, buffer_size_in_frames, playback_rate);
329 total_frames_written += frames_written;
330 } while (frames_written && algorithm_.BufferedFrames() > 0);
332 int input_frames_enqueued = frames_enqueued_ - initial_frames_enqueued;
334 int ouput_frames_available =
335 static_cast<int>(input_frames_enqueued / playback_rate + 0.5);
338 // If we marked the EOS, all data should we played out, possibly with some
340 EXPECT_GE(total_frames_written, ouput_frames_available);
342 // If we don't mark the EOS, we expect to have lost some frames because
343 // we don't partially handle requests.
344 EXPECT_LE(total_frames_written, ouput_frames_available);
348 void WsolaTest(double playback_rate) {
349 const int kSampleRateHz = 48000;
350 constexpr ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
351 const int kNumFrames = kSampleRateHz / 100; // 10 milliseconds.
353 channels_ = ChannelLayoutToChannelCount(kChannelLayout);
354 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
355 ChannelLayoutConfig::FromLayout<kChannelLayout>(),
356 kSampleRateHz, kNumFrames);
357 bool is_encrypted = false;
358 algorithm_.Initialize(params, is_encrypted);
360 // A pulse is 6 milliseconds (even number of samples).
361 const int kPulseWidthSamples = 6 * kSampleRateHz / 1000;
362 const int kHalfPulseWidthSamples = kPulseWidthSamples / 2;
364 // For the ease of implementation get 1 frame every call to FillBuffer().
365 std::unique_ptr<AudioBus> output = AudioBus::Create(channels_, 1);
367 // Input buffer to inject pulses.
368 scoped_refptr<AudioBuffer> input =
369 AudioBuffer::CreateBuffer(kSampleFormatPlanarF32,
375 const std::vector<uint8_t*>& channel_data = input->channel_data();
377 // Fill |input| channels.
378 FillWithSquarePulseTrain(kHalfPulseWidthSamples, 0, kPulseWidthSamples,
379 reinterpret_cast<float*>(channel_data[0]));
380 FillWithSquarePulseTrain(kHalfPulseWidthSamples, kHalfPulseWidthSamples,
382 reinterpret_cast<float*>(channel_data[1]));
384 // A buffer for the output until a complete pulse is created. Then
385 // reference pulse is compared with this buffer.
386 std::unique_ptr<AudioBus> pulse_buffer =
387 AudioBus::Create(channels_, kPulseWidthSamples);
389 const float kTolerance = 0.000001f;
390 // Equivalent of 4 seconds.
391 const int kNumRequestedPulses = kSampleRateHz * 4 / kPulseWidthSamples;
392 for (int n = 0; n < kNumRequestedPulses; ++n) {
393 int num_buffered_frames = 0;
394 while (num_buffered_frames < kPulseWidthSamples) {
396 algorithm_.FillBuffer(output.get(), 0, 1, playback_rate);
397 ASSERT_LE(num_samples, 1);
398 if (num_samples > 0) {
399 output->CopyPartialFramesTo(0, num_samples, num_buffered_frames,
401 num_buffered_frames++;
403 algorithm_.EnqueueBuffer(input);
407 // Pulses in the first half of WSOLA AOL frame are not constructed
408 // perfectly. Do not check them.
410 for (int m = 0; m < channels_; ++m) {
411 const float* pulse_ch = pulse_buffer->channel(m);
413 // Because of overlap-and-add we might have round off error.
414 for (int k = 0; k < kPulseWidthSamples; ++k) {
415 ASSERT_NEAR(reinterpret_cast<float*>(channel_data[m])[k],
416 pulse_ch[k], kTolerance) << " loop " << n
417 << " channel/sample " << m << "/" << k;
422 // Zero out the buffer to be sure the next comparison is relevant.
423 pulse_buffer->Zero();
428 AudioRendererAlgorithm algorithm_;
429 NullMediaLog media_log_;
430 int frames_enqueued_;
432 ChannelLayout channel_layout_;
433 SampleFormat sample_format_;
434 int samples_per_second_;
435 int bytes_per_sample_;
436 bool is_bitstream_format_;
439 TEST_F(AudioRendererAlgorithmTest, InitializeWithLargeParameters) {
440 const int kBufferSize = 0.5 * kSamplesPerSecond;
441 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond,
443 EXPECT_LT(kBufferSize, algorithm_.QueueCapacity());
444 algorithm_.FlushBuffers();
445 EXPECT_LT(kBufferSize, algorithm_.QueueCapacity());
448 TEST_F(AudioRendererAlgorithmTest, FillBuffer_Bitstream) {
449 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatEac3, kSamplesPerSecond,
450 kSamplesPerSecond / 100);
451 TestPlaybackRate(1.0, kFrameSize, 16 * kFrameSize, /* dest_offset */ 0);
454 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) {
456 TestPlaybackRate(1.0);
459 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalFasterRate) {
461 TestPlaybackRate(1.0001);
464 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NearlyNormalSlowerRate) {
466 TestPlaybackRate(0.9999);
469 // This test verifies that the resampling based time stretch algorithms works.
470 // The range of playback rates in which we use resampling is [0.95, 1.06].
471 TEST_F(AudioRendererAlgorithmTest, FillBuffer_ResamplingRates) {
474 TestPlaybackRate(0.50);
475 TestPlaybackRate(0.95);
476 TestPlaybackRate(1.00);
477 TestPlaybackRate(1.05);
478 TestPlaybackRate(2.00);
481 algorithm_.SetPreservesPitch(false);
482 TestPlaybackRate(0.50);
483 TestPlaybackRate(0.95);
484 TestPlaybackRate(1.00);
485 TestPlaybackRate(1.05);
486 TestPlaybackRate(2.00);
489 TEST_F(AudioRendererAlgorithmTest, FillBuffer_WithOffset) {
491 const int kBufferSize = algorithm_.samples_per_second() / 10;
492 const int kOffset = kBufferSize / 10;
493 const int kFramesRequested =
494 kOutputDurationInSec * algorithm_.samples_per_second();
497 TestPlaybackRate(1.00, kBufferSize, kFramesRequested, kOffset);
499 // Resampling based time-strech.
500 TestPlaybackRate(1.05, kBufferSize, kFramesRequested, kOffset);
502 // WSOLA based time-strech.
503 TestPlaybackRate(1.25, kBufferSize, kFramesRequested, kOffset);
506 TEST_F(AudioRendererAlgorithmTest, FillBuffer_UnderFlow) {
508 TestResamplingWithUnderflow(0.75, true);
509 TestResamplingWithUnderflow(0.75, false);
510 TestResamplingWithUnderflow(1.25, true);
511 TestResamplingWithUnderflow(1.25, false);
514 TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAQuarterRate) {
516 TestPlaybackRate(1.25);
519 TEST_F(AudioRendererAlgorithmTest, FillBuffer_OneAndAHalfRate) {
521 TestPlaybackRate(1.5);
524 TEST_F(AudioRendererAlgorithmTest, FillBuffer_DoubleRate) {
526 TestPlaybackRate(2.0);
529 TEST_F(AudioRendererAlgorithmTest, FillBuffer_EightTimesRate) {
531 TestPlaybackRate(8.0);
534 TEST_F(AudioRendererAlgorithmTest, FillBuffer_ThreeQuartersRate) {
536 TestPlaybackRate(0.75);
539 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HalfRate) {
541 TestPlaybackRate(0.5);
544 TEST_F(AudioRendererAlgorithmTest, FillBuffer_QuarterRate) {
546 TestPlaybackRate(0.25);
549 TEST_F(AudioRendererAlgorithmTest, FillBuffer_Pause) {
551 TestPlaybackRate(0.0);
554 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SlowDown) {
556 TestPlaybackRate(4.5);
557 TestPlaybackRate(3.0);
558 TestPlaybackRate(2.0);
559 TestPlaybackRate(1.0);
560 TestPlaybackRate(0.5);
561 TestPlaybackRate(0.25);
564 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SpeedUp) {
566 TestPlaybackRate(0.25);
567 TestPlaybackRate(0.5);
568 TestPlaybackRate(1.0);
569 TestPlaybackRate(2.0);
570 TestPlaybackRate(3.0);
571 TestPlaybackRate(4.5);
574 TEST_F(AudioRendererAlgorithmTest, FillBuffer_JumpAroundSpeeds) {
576 TestPlaybackRate(2.1);
577 TestPlaybackRate(0.9);
578 TestPlaybackRate(0.6);
579 TestPlaybackRate(1.4);
580 TestPlaybackRate(0.3);
583 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) {
585 static const int kBufferSizeInFrames = 1;
586 static const int kFramesRequested = kOutputDurationInSec * kSamplesPerSecond;
587 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested, 0);
588 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested, 0);
589 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested, 0);
592 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) {
593 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100, 441);
594 TestPlaybackRate(1.0);
595 TestPlaybackRate(0.5);
596 TestPlaybackRate(1.5);
599 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) {
600 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond,
601 kSamplesPerSecond / 100);
602 TestPlaybackRate(1.0);
603 TestPlaybackRate(0.5);
604 TestPlaybackRate(1.5);
607 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) {
608 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond,
609 kSamplesPerSecond / 100);
610 TestPlaybackRate(1.0);
611 TestPlaybackRate(0.5);
612 TestPlaybackRate(1.5);
615 TEST_F(AudioRendererAlgorithmTest, DotProduct) {
616 const int kChannels = 3;
617 const int kFrames = 20;
618 const int kHalfPulseWidth = 2;
620 std::unique_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
621 std::unique_ptr<AudioBus> b = AudioBus::Create(kChannels, kFrames);
623 auto dot_prod = std::make_unique<float[]>(kChannels);
625 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, a.get());
626 FillWithSquarePulseTrain(kHalfPulseWidth, 1, 1, a.get());
627 FillWithSquarePulseTrain(kHalfPulseWidth, 2, 2, a.get());
629 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, b.get());
630 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 1, b.get());
631 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 2, b.get());
633 internal::MultiChannelDotProduct(a.get(), 0, b.get(), 0, kFrames,
636 EXPECT_FLOAT_EQ(kFrames, dot_prod[0]);
637 EXPECT_FLOAT_EQ(0, dot_prod[1]);
638 EXPECT_FLOAT_EQ(-kFrames, dot_prod[2]);
640 internal::MultiChannelDotProduct(a.get(), 4, b.get(), 8, kFrames / 2,
643 EXPECT_FLOAT_EQ(kFrames / 2, dot_prod[0]);
644 EXPECT_FLOAT_EQ(0, dot_prod[1]);
645 EXPECT_FLOAT_EQ(-kFrames / 2, dot_prod[2]);
648 TEST_F(AudioRendererAlgorithmTest, MovingBlockEnergy) {
649 const int kChannels = 2;
650 const int kFrames = 20;
651 const int kFramesPerBlock = 3;
652 const int kNumBlocks = kFrames - (kFramesPerBlock - 1);
653 std::unique_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
654 auto energies = std::make_unique<float[]>(kChannels * kNumBlocks);
655 float* ch_left = a->channel(0);
656 float* ch_right = a->channel(1);
658 // Fill up both channels.
659 for (int n = 0; n < kFrames; ++n) {
661 ch_right[n] = kFrames - 1 - n;
664 internal::MultiChannelMovingBlockEnergies(a.get(), kFramesPerBlock,
667 // Check if the energy of candidate blocks of each channel computed correctly.
668 for (int n = 0; n < kNumBlocks; ++n) {
669 float expected_energy = 0;
670 for (int k = 0; k < kFramesPerBlock; ++k)
671 expected_energy += ch_left[n + k] * ch_left[n + k];
673 // Left (first) channel.
674 EXPECT_FLOAT_EQ(expected_energy, energies[2 * n]);
677 for (int k = 0; k < kFramesPerBlock; ++k)
678 expected_energy += ch_right[n + k] * ch_right[n + k];
680 // Second (right) channel.
681 EXPECT_FLOAT_EQ(expected_energy, energies[2 * n + 1]);
685 TEST_F(AudioRendererAlgorithmTest, FullAndDecimatedSearch) {
686 const int kFramesInSearchRegion = 12;
687 const int kChannels = 2;
689 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f };
691 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.1f, 1.0f, 0.1f, 0.0f, 0.0f };
692 ASSERT_EQ(sizeof(ch_0), sizeof(ch_1));
693 ASSERT_EQ(static_cast<size_t>(kFramesInSearchRegion),
694 sizeof(ch_0) / sizeof(*ch_0));
695 std::unique_ptr<AudioBus> search_region =
696 AudioBus::Create(kChannels, kFramesInSearchRegion);
697 float* ch = search_region->channel(0);
698 memcpy(ch, ch_0, sizeof(float) * kFramesInSearchRegion);
699 ch = search_region->channel(1);
700 memcpy(ch, ch_1, sizeof(float) * kFramesInSearchRegion);
702 const int kFramePerBlock = 4;
703 float target_0[] = { 1.0f, 1.0f, 1.0f, 0.0f };
704 float target_1[] = { 0.0f, 1.0f, 0.1f, 1.0f };
705 ASSERT_EQ(sizeof(target_0), sizeof(target_1));
706 ASSERT_EQ(static_cast<size_t>(kFramePerBlock),
707 sizeof(target_0) / sizeof(*target_0));
709 std::unique_ptr<AudioBus> target =
710 AudioBus::Create(kChannels, kFramePerBlock);
711 ch = target->channel(0);
712 memcpy(ch, target_0, sizeof(float) * kFramePerBlock);
713 ch = target->channel(1);
714 memcpy(ch, target_1, sizeof(float) * kFramePerBlock);
716 auto energy_target = std::make_unique<float[]>(kChannels);
718 internal::MultiChannelDotProduct(target.get(), 0, target.get(), 0,
719 kFramePerBlock, energy_target.get());
721 ASSERT_EQ(3.f, energy_target[0]);
722 ASSERT_EQ(2.01f, energy_target[1]);
724 const int kNumCandidBlocks = kFramesInSearchRegion - (kFramePerBlock - 1);
725 auto energy_candid_blocks =
726 std::make_unique<float[]>(kNumCandidBlocks * kChannels);
728 internal::MultiChannelMovingBlockEnergies(
729 search_region.get(), kFramePerBlock, energy_candid_blocks.get());
731 // Check the energy of the candidate blocks of the first channel.
732 ASSERT_FLOAT_EQ(0, energy_candid_blocks[0]);
733 ASSERT_FLOAT_EQ(0, energy_candid_blocks[2]);
734 ASSERT_FLOAT_EQ(1, energy_candid_blocks[4]);
735 ASSERT_FLOAT_EQ(2, energy_candid_blocks[6]);
736 ASSERT_FLOAT_EQ(3, energy_candid_blocks[8]);
737 ASSERT_FLOAT_EQ(3, energy_candid_blocks[10]);
738 ASSERT_FLOAT_EQ(2, energy_candid_blocks[12]);
739 ASSERT_FLOAT_EQ(1, energy_candid_blocks[14]);
740 ASSERT_FLOAT_EQ(0, energy_candid_blocks[16]);
742 // Check the energy of the candidate blocks of the second channel.
743 ASSERT_FLOAT_EQ(0, energy_candid_blocks[1]);
744 ASSERT_FLOAT_EQ(0, energy_candid_blocks[3]);
745 ASSERT_FLOAT_EQ(0, energy_candid_blocks[5]);
746 ASSERT_FLOAT_EQ(0, energy_candid_blocks[7]);
747 ASSERT_FLOAT_EQ(0.01f, energy_candid_blocks[9]);
748 ASSERT_FLOAT_EQ(1.01f, energy_candid_blocks[11]);
749 ASSERT_FLOAT_EQ(1.02f, energy_candid_blocks[13]);
750 ASSERT_FLOAT_EQ(1.02f, energy_candid_blocks[15]);
751 ASSERT_FLOAT_EQ(1.01f, energy_candid_blocks[17]);
753 // An interval which is of no effect.
754 internal::Interval exclude_interval = std::make_pair(-100, -10);
755 EXPECT_EQ(5, internal::FullSearch(
756 0, kNumCandidBlocks - 1, exclude_interval, target.get(),
757 search_region.get(), energy_target.get(), energy_candid_blocks.get()));
759 // Exclude the the best match.
760 exclude_interval = std::make_pair(2, 5);
761 EXPECT_EQ(7, internal::FullSearch(
762 0, kNumCandidBlocks - 1, exclude_interval, target.get(),
763 search_region.get(), energy_target.get(), energy_candid_blocks.get()));
765 // An interval which is of no effect.
766 exclude_interval = std::make_pair(-100, -10);
767 EXPECT_EQ(4, internal::DecimatedSearch(
768 4, exclude_interval, target.get(), search_region.get(),
769 energy_target.get(), energy_candid_blocks.get()));
771 EXPECT_EQ(5, internal::OptimalIndex(search_region.get(), target.get(),
775 TEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation) {
776 // Arbitrary coefficients.
777 const float kA = 0.7f;
778 const float kB = 1.2f;
779 const float kC = 0.8f;
782 y_values[0] = kA - kB + kC;
784 y_values[2] = kA + kB + kC;
787 float extremum_value;
789 internal::QuadraticInterpolation(y_values, &extremum, &extremum_value);
791 float x_star = -kB / (2.f * kA);
792 float y_star = kA * x_star * x_star + kB * x_star + kC;
794 EXPECT_FLOAT_EQ(x_star, extremum);
795 EXPECT_FLOAT_EQ(y_star, extremum_value);
798 TEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation_Colinear) {
805 float extremum_value;
807 internal::QuadraticInterpolation(y_values, &extremum, &extremum_value);
809 EXPECT_FLOAT_EQ(extremum, 0.0);
810 EXPECT_FLOAT_EQ(extremum_value, 1.0);
813 TEST_F(AudioRendererAlgorithmTest, WsolaSlowdown) {
817 TEST_F(AudioRendererAlgorithmTest, WsolaSpeedup) {
821 TEST_F(AudioRendererAlgorithmTest, FillBufferOffset) {
823 // Pad the queue capacity so fill requests for all rates bellow can be fully
825 algorithm_.IncreasePlaybackThreshold();
827 std::unique_ptr<AudioBus> bus = AudioBus::Create(channels_, kFrameSize);
829 // Verify that the first half of |bus| remains zero and the last half is
830 // filled appropriately at normal, above normal, and below normal.
831 const int kHalfSize = kFrameSize / 2;
832 const float kAudibleRates[] = {1.0f, 2.0f, 0.5f, 5.0f, 0.25f};
833 for (size_t i = 0; i < std::size(kAudibleRates); ++i) {
834 SCOPED_TRACE(kAudibleRates[i]);
837 const int frames_filled = algorithm_.FillBuffer(
838 bus.get(), kHalfSize, kHalfSize, kAudibleRates[i]);
839 ASSERT_EQ(kHalfSize, frames_filled);
840 ASSERT_TRUE(VerifyAudioData(bus.get(), 0, kHalfSize, 0));
841 ASSERT_FALSE(VerifyAudioData(bus.get(), kHalfSize, kHalfSize, 0));
842 FillAlgorithmQueueUntilFull();
846 TEST_F(AudioRendererAlgorithmTest, FillBuffer_ChannelMask) {
847 // Setup a quad channel layout where even channels are always muted.
848 Initialize(CHANNEL_LAYOUT_QUAD, kSampleFormatS16, 44100, 441,
849 {true, false, true, false});
851 std::unique_ptr<AudioBus> bus = AudioBus::Create(channels_, kFrameSize);
852 int frames_filled = algorithm_.FillBuffer(bus.get(), 0, kFrameSize, 2.0);
853 ASSERT_GT(frames_filled, 0);
855 // Verify the channels are muted appropriately; even though the created buffer
856 // actually has audio data in it.
857 for (int ch = 0; ch < bus->channels(); ++ch) {
859 for (int i = 0; i < bus->frames(); ++i)
860 sum += bus->channel(ch)[i];
867 // Update the channel mask and verify it's reflected correctly.
868 algorithm_.SetChannelMask({true, true, true, true});
869 frames_filled = algorithm_.FillBuffer(bus.get(), 0, kFrameSize, 2.0);
870 ASSERT_GT(frames_filled, 0);
872 // Verify no channels are muted now.
873 for (int ch = 0; ch < bus->channels(); ++ch) {
875 for (int i = 0; i < bus->frames(); ++i)
876 sum += bus->channel(ch)[i];
881 // The |plabyack_threshold_| should == |capacity_| by default, when no
882 // |latency_hint_| is set.
883 TEST_F(AudioRendererAlgorithmTest, NoLatencyHint) {
884 // Queue is initially empty. Capacity is unset.
885 EXPECT_EQ(algorithm_.BufferedFrames(), 0);
886 EXPECT_EQ(algorithm_.QueueCapacity(), 0);
888 // Initialize sets capacity fills queue.
890 EXPECT_GT(algorithm_.QueueCapacity(), 0);
891 EXPECT_TRUE(algorithm_.IsQueueFull());
892 EXPECT_TRUE(algorithm_.IsQueueAdequateForPlayback());
894 // No latency hint is set, so playback threshold should == capacity. Observe
895 // that the queue is neither "full" nor "adequate for playback" if we are one
896 // one frame below the capacity limit.
897 std::unique_ptr<AudioBus> bus = AudioBus::Create(channels_, kFrameSize);
898 int requested_frames =
899 (algorithm_.BufferedFrames() - algorithm_.QueueCapacity()) + 1;
900 const int frames_filled =
901 algorithm_.FillBuffer(bus.get(), 0, requested_frames, 1);
902 EXPECT_EQ(frames_filled, requested_frames);
903 EXPECT_EQ(algorithm_.BufferedFrames(), algorithm_.QueueCapacity() - 1);
904 EXPECT_FALSE(algorithm_.IsQueueFull());
905 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
907 // Queue should again be "adequate for playback" and "full" it we add a single
908 // frame such that BufferedFrames() == QueueCapacity().
909 DCHECK_EQ(sample_format_, kSampleFormatS16);
910 algorithm_.EnqueueBuffer(MakeBuffer(1));
911 EXPECT_TRUE(algorithm_.IsQueueFull());
912 EXPECT_TRUE(algorithm_.IsQueueAdequateForPlayback());
913 EXPECT_EQ(algorithm_.BufferedFrames(), algorithm_.QueueCapacity());
915 // Increasing playback threshold should also increase capacity.
916 int orig_capacity = algorithm_.QueueCapacity();
917 algorithm_.IncreasePlaybackThreshold();
918 EXPECT_GT(algorithm_.QueueCapacity(), orig_capacity);
919 EXPECT_FALSE(algorithm_.IsQueueFull());
920 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
922 // Filling again, 1 frame at a time, we should reach "adequate" and "full" in
924 while (!algorithm_.IsQueueFull()) {
925 algorithm_.EnqueueBuffer(MakeBuffer(1));
926 EXPECT_EQ(algorithm_.IsQueueFull(),
927 algorithm_.IsQueueAdequateForPlayback());
930 // Flushing should restore queue capacity and playback threshold to the
932 algorithm_.FlushBuffers();
933 EXPECT_EQ(algorithm_.QueueCapacity(), orig_capacity);
934 EXPECT_FALSE(algorithm_.IsQueueFull());
935 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
937 // Filling again, 1 frame at a time, we should reach "adequate" and "full" in
939 while (!algorithm_.IsQueueFull()) {
940 algorithm_.EnqueueBuffer(MakeBuffer(1));
941 EXPECT_EQ(algorithm_.IsQueueFull(),
942 algorithm_.IsQueueAdequateForPlayback());
946 // The |playback_threshold_| should be < |capacity_| when a latency hint is
947 // set to reduce the playback delay.
948 TEST_F(AudioRendererAlgorithmTest, LowLatencyHint) {
949 // Initialize with a buffer size that leaves some gap between the min capacity
950 // (2*buffer_size) and the default capacity (200ms).
951 const int kBufferSize = kSamplesPerSecond / 50;
952 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, kSamplesPerSecond,
955 // FlushBuffers to start out empty.
956 algorithm_.FlushBuffers();
958 EXPECT_GT(algorithm_.QueueCapacity(), 0);
959 EXPECT_FALSE(algorithm_.IsQueueFull());
960 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
962 // Set a latency hint at half the default capacity.
963 const int orig_queue_capcity = algorithm_.QueueCapacity();
964 base::TimeDelta low_latency_hint = AudioTimestampHelper::FramesToTime(
965 orig_queue_capcity / 2, samples_per_second_);
966 algorithm_.SetLatencyHint(low_latency_hint);
968 // Hint is less than capacity, so capacity should be unchanged.
969 EXPECT_EQ(algorithm_.QueueCapacity(), orig_queue_capcity);
971 // Fill until "adequate". Verify "adequate" buffer time reflects the hinted
972 // latency, and that "adequate" is less than "full".
973 FillAlgorithmQueueUntilAdequate();
974 EXPECT_EQ(BufferedTime(), low_latency_hint);
975 EXPECT_FALSE(algorithm_.IsQueueFull());
977 // Set a new *slightly higher* hint. Verify we're no longer "adequate".
978 low_latency_hint += base::Milliseconds(10);
979 algorithm_.SetLatencyHint(low_latency_hint);
980 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
982 // Fill until "adequate". Verify "adequate" buffer time reflects the
983 // *slightly higher* hinted latency, and that "adequate" is less than "full".
984 FillAlgorithmQueueUntilAdequate();
985 EXPECT_EQ(BufferedTime(), low_latency_hint);
986 EXPECT_FALSE(algorithm_.IsQueueFull());
988 // Clearing the hint should restore the higher default playback threshold,
989 // such that we no longer have enough buffer to be "adequate for playback".
990 algorithm_.SetLatencyHint(absl::nullopt);
991 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
993 // Fill until "full". Verify that "adequate" now matches "full".
994 while (!algorithm_.IsQueueFull()) {
995 algorithm_.EnqueueBuffer(MakeBuffer(1));
996 EXPECT_EQ(algorithm_.IsQueueAdequateForPlayback(),
997 algorithm_.IsQueueFull());
1001 // Note: the behavior of FlushBuffers() that is not specific to high vs low
1002 // latency hints. Testing it with "high" is slightly more interesting. Testing
1003 // with both "high" and "low" is excessive.
1004 TEST_F(AudioRendererAlgorithmTest, HighLatencyHint) {
1005 // Initialize with a buffer size that leaves some gap between the min capacity
1006 // (2*buffer_size) and the default capacity (200ms).
1007 const int kBufferSize = kSamplesPerSecond / 50;
1008 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, kSamplesPerSecond,
1010 const int default_capacity = algorithm_.QueueCapacity();
1012 // FlushBuffers to start out empty.
1013 algorithm_.FlushBuffers();
1015 // Set a "high" latency hint.
1016 const base::TimeDelta high_latency_hint = AudioTimestampHelper::FramesToTime(
1017 algorithm_.QueueCapacity() * 2, samples_per_second_);
1018 algorithm_.SetLatencyHint(high_latency_hint);
1019 const int high_latency_capacity = algorithm_.QueueCapacity();
1020 EXPECT_GT(high_latency_capacity, default_capacity);
1022 // Fill until "adequate". Verify it reflects the high latency hint.
1023 EXPECT_TRUE(BufferedTime().is_zero());
1024 FillAlgorithmQueueUntilAdequate();
1025 EXPECT_EQ(BufferedTime(), high_latency_hint);
1028 algorithm_.FlushBuffers();
1030 // Verify |capcity_| was not changed by flush. The latency hint supersedes any
1031 // automatic queue size adjustments.
1032 EXPECT_EQ(algorithm_.QueueCapacity(), high_latency_capacity);
1034 // Similarly, verify that |playback_threshold_| was not changed by refilling
1035 // and observing that the "adequate" buffered time still matches the hint.
1036 FillAlgorithmQueueUntilAdequate();
1037 EXPECT_EQ(BufferedTime(), high_latency_hint);
1039 // Clearing the hint should restore the lower default playback threshold and
1041 algorithm_.SetLatencyHint(absl::nullopt);
1042 EXPECT_EQ(algorithm_.QueueCapacity(), default_capacity);
1044 // The queue is over-full from our last fill when the hint was set. Flush and
1045 // refill to the reduced "adequate" threshold.
1046 algorithm_.FlushBuffers();
1047 FillAlgorithmQueueUntilAdequate();
1048 EXPECT_LT(BufferedTime(), high_latency_hint);
1050 // With latency hint now unset, callers are now free to adjust the queue size
1051 // (e.g. in response to underflow). Lets increase the threshold!
1052 algorithm_.IncreasePlaybackThreshold();
1054 // Verify higher capacity means we're no longer "adequate" nor "full".
1055 EXPECT_GT(algorithm_.QueueCapacity(), default_capacity);
1056 EXPECT_FALSE(algorithm_.IsQueueAdequateForPlayback());
1057 EXPECT_FALSE(algorithm_.IsQueueFull());
1059 // Flush the queue and verify the increase has been reverted.
1060 algorithm_.FlushBuffers();
1061 EXPECT_EQ(algorithm_.QueueCapacity(), default_capacity);
1063 // Refill to verify "adequate" matches the "full" at the default capacity.
1064 while (!algorithm_.IsQueueAdequateForPlayback()) {
1065 algorithm_.EnqueueBuffer(MakeBuffer(1));
1066 EXPECT_EQ(algorithm_.IsQueueAdequateForPlayback(),
1067 algorithm_.IsQueueFull());
1071 // Algorithm should clam specified hint to a reasonable min/max.
1072 TEST_F(AudioRendererAlgorithmTest, ClampLatencyHint) {
1073 // Initialize with a buffer size that leaves some gap between the min capacity
1074 // (2*buffer_size) and the default capacity (200ms).
1075 const int kBufferSize = kSamplesPerSecond / 50;
1076 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, kSamplesPerSecond,
1078 const int default_capacity = algorithm_.QueueCapacity();
1080 // FlushBuffers to start out empty.
1081 algorithm_.FlushBuffers();
1083 // Set a crazy high latency hint.
1084 algorithm_.SetLatencyHint(base::Seconds(100));
1086 const base::TimeDelta kDefaultMax = base::Seconds(3);
1087 // Verify "full" and "adequate" thresholds increased, but to a known max well
1088 // bellow the hinted value.
1089 EXPECT_GT(algorithm_.QueueCapacity(), default_capacity);
1090 FillAlgorithmQueueUntilAdequate();
1091 EXPECT_EQ(BufferedTime(), kDefaultMax);
1093 // FlushBuffers to return to empty.
1094 algorithm_.FlushBuffers();
1096 // Set an impossibly low latency hint.
1097 algorithm_.SetLatencyHint(base::Seconds(0));
1099 // Verify "full" and "adequate" thresholds decreased, but to a known minimum
1100 // well above the hinted value.
1101 EXPECT_EQ(algorithm_.QueueCapacity(), default_capacity);
1102 FillAlgorithmQueueUntilAdequate();
1103 EXPECT_EQ(algorithm_.BufferedFrames(), 2 * kBufferSize);
1106 } // namespace media