Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: media/filters/audio_renderer_algorithm_unittest.cc

Issue 19111004: Upgrade AudioRendererAlgorithm to use WSOLA, (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments addressed, AudioRendererAlgorithmTest::WsolaTest modified. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // The format of these tests are to enqueue a known amount of data and then 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 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 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 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. 9 // expectation that FillBuffer() will fill as much as it can but no more.
10 10
11 #include <algorithm> // For std::min().
11 #include <cmath> 12 #include <cmath>
13 #include <vector>
12 14
13 #include "base/bind.h" 15 #include "base/bind.h"
14 #include "base/callback.h" 16 #include "base/callback.h"
17 #include "base/memory/scoped_ptr.h"
15 #include "media/base/audio_buffer.h" 18 #include "media/base/audio_buffer.h"
16 #include "media/base/audio_bus.h" 19 #include "media/base/audio_bus.h"
17 #include "media/base/buffers.h" 20 #include "media/base/buffers.h"
18 #include "media/base/channel_layout.h" 21 #include "media/base/channel_layout.h"
19 #include "media/base/test_helpers.h" 22 #include "media/base/test_helpers.h"
20 #include "media/filters/audio_renderer_algorithm.h" 23 #include "media/filters/audio_renderer_algorithm.h"
24 #include "media/filters/wsola_internals.h"
21 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
22 26
23 namespace media { 27 namespace media {
24 28
25 static const int kFrameSize = 250; 29 static const int kFrameSize = 250;
26 static const int kSamplesPerSecond = 3000; 30 static const int kSamplesPerSecond = 3000;
27 static const SampleFormat kSampleFormat = kSampleFormatS16; 31 static const SampleFormat kSampleFormat = kSampleFormatS16;
32 static const int kOutputDurationInSec = 10;
33
34 static void FillWithSquarePulseTrain(
35 int half_pulse_width, int offset, int num_samples, float* data) {
36 ASSERT_GE(offset, 0);
37 ASSERT_LE(offset, num_samples);
38
39 // Fill backward from |offset| - 1 toward zero, starting with -1, alternating
40 // between -1 and 1 every |pulse_width| samples.
41 float pulse = -1.0f;
42 for (int n = offset - 1, k = 0; n >= 0; --n, ++k) {
43 if (k >= half_pulse_width) {
44 pulse = -pulse;
45 k = 0;
46 }
47 data[n] = pulse;
48 }
49
50 // Fill forward from |offset| towards the end, starting with 1, alternating
51 // between 1 and -1 every |pulse_width| samples.
52 pulse = 1.0f;
53 for (int n = offset, k = 0; n < num_samples; ++n, ++k) {
54 if (k >= half_pulse_width) {
55 pulse = -pulse;
56 k = 0;
57 }
58 data[n] = pulse;
59 }
60 }
61
62 static void FillWithSquarePulseTrain(
63 int half_pulse_width, int offset, int channel, AudioBus* audio_bus) {
64 FillWithSquarePulseTrain(half_pulse_width, offset, audio_bus->frames(),
65 audio_bus->channel(channel));
66 }
28 67
29 class AudioRendererAlgorithmTest : public testing::Test { 68 class AudioRendererAlgorithmTest : public testing::Test {
30 public: 69 public:
31 AudioRendererAlgorithmTest() 70 AudioRendererAlgorithmTest()
32 : frames_enqueued_(0), 71 : frames_enqueued_(0),
33 channels_(0), 72 channels_(0),
34 sample_format_(kUnknownSampleFormat), 73 sample_format_(kUnknownSampleFormat),
35 bytes_per_sample_(0) { 74 bytes_per_sample_(0) {
36 } 75 }
37 76
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 int initial_frames_buffered) { 150 int initial_frames_buffered) {
112 int frame_delta = frames_enqueued_ - initial_frames_enqueued; 151 int frame_delta = frames_enqueued_ - initial_frames_enqueued;
113 int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered; 152 int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered;
114 int consumed = frame_delta - buffered_delta; 153 int consumed = frame_delta - buffered_delta;
115 CHECK_GE(consumed, 0); 154 CHECK_GE(consumed, 0);
116 return consumed; 155 return consumed;
117 } 156 }
118 157
119 void TestPlaybackRate(double playback_rate) { 158 void TestPlaybackRate(double playback_rate) {
120 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100; 159 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100;
121 const int kDefaultFramesRequested = 2 * algorithm_.samples_per_second(); 160 const int kDefaultFramesRequested = kOutputDurationInSec *
161 algorithm_.samples_per_second();
122 162
123 TestPlaybackRate( 163 TestPlaybackRate(
124 playback_rate, kDefaultBufferSize, kDefaultFramesRequested); 164 playback_rate, kDefaultBufferSize, kDefaultFramesRequested);
125 } 165 }
126 166
127 void TestPlaybackRate(double playback_rate, 167 void TestPlaybackRate(double playback_rate,
128 int buffer_size_in_frames, 168 int buffer_size_in_frames,
129 int total_frames_requested) { 169 int total_frames_requested) {
130 int initial_frames_enqueued = frames_enqueued_; 170 int initial_frames_enqueued = frames_enqueued_;
131 int initial_frames_buffered = algorithm_.frames_buffered(); 171 int initial_frames_buffered = algorithm_.frames_buffered();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 // large, one can expect less than a 1% difference in most cases. In our 208 // 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 209 // current implementation, sped up playback is less accurate than slowed
170 // down playback, and for playback_rate > 1, playback rate generally gets 210 // 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 211 // less and less accurate the farther it drifts from 1 (though this is
172 // nonlinear). 212 // nonlinear).
173 double actual_playback_rate = 213 double actual_playback_rate =
174 1.0 * frames_consumed / total_frames_requested; 214 1.0 * frames_consumed / total_frames_requested;
175 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0); 215 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0);
176 } 216 }
177 217
218 void WsolaTest(float playback_rate) {
219 const int kSampleRateHz = 48000;
220 const media::ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
221 const int kBytesPerSample = 2;
222 const int kNumFrames = kSampleRateHz / 100; // 10 milliseconds.
223
224 channels_ = ChannelLayoutToChannelCount(kChannelLayout);
225 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
226 kSampleRateHz, kBytesPerSample * 8, kNumFrames);
227 algorithm_.Initialize(playback_rate, params);
228
229 // A pulse is 6 milliseconds (even number of samples).
230 const int kPulseWidthSamples = 6 * kSampleRateHz / 1000;
231 const int kHalfPulseWidthSamples = kPulseWidthSamples / 2;
232
233 // For the ease of implementation get 1 frame every call to FillBuffer().
234 scoped_ptr<AudioBus> output = AudioBus::Create(channels_, 1);
235
236 // Input buffer to inject pulses.
237 scoped_refptr<AudioBuffer> input = AudioBuffer::CreateBuffer(
238 kSampleFormatPlanarF32, channels_, kPulseWidthSamples);
239
240 std::vector<uint8_t*> channel_data = input->channel_data();
241
242 // Fill |input| channels.
243 FillWithSquarePulseTrain(kHalfPulseWidthSamples, 0, kPulseWidthSamples,
244 reinterpret_cast<float*>(channel_data[0]));
245 FillWithSquarePulseTrain(kHalfPulseWidthSamples, kHalfPulseWidthSamples,
246 kPulseWidthSamples,
247 reinterpret_cast<float*>(channel_data[1]));
248
249 // A buffer for the output until a complete pulse is created. Then
250 // reference pulse is compared with this buffer.
251 scoped_ptr<AudioBus> pulse_buffer = AudioBus::Create(
252 channels_, kPulseWidthSamples);
253
254 float kTolerance = 0.0001f;
255 // Equivalent of 4 seconds.
256 const int kNumRequestedPulses = kSampleRateHz * 4 / kPulseWidthSamples;
257 for (int n = 0; n < kNumRequestedPulses; ++n) {
258 int num_buffered_frames = 0;
259 while (num_buffered_frames < kPulseWidthSamples) {
260 int num_samples = algorithm_.FillBuffer(output.get(), 1);
261 ASSERT_LE(num_samples, 1);
262 if (num_samples > 0) {
263 output->CopyPartialFramesTo(0, num_samples, num_buffered_frames,
264 pulse_buffer.get());
265 num_buffered_frames++;
266 } else {
267 algorithm_.EnqueueBuffer(input);
268 }
269 }
270
271 // Pulses in the first half of WSOLA AOL frame are not constructed
272 // perfectly. Do not check them.
273 if (n > 3) {
274 for (int m = 0; m < channels_; ++m) {
275 const float* pulse_ch = pulse_buffer->channel(m);
276
277 // Because of overlap-and-add we might have round off error.
278 for (int k = 0; k < kPulseWidthSamples; ++k) {
279 EXPECT_NEAR(reinterpret_cast<float*>(channel_data[m])[k],
280 pulse_ch[k], kTolerance) << " loop " << n
281 << " channel/sample " << m << "/" << k;
282 }
283 }
284 }
285
286 // Zero out the buffer to be sure the next comparison is relevant.
287 pulse_buffer->Zero();
288 }
289 }
290
178 protected: 291 protected:
179 AudioRendererAlgorithm algorithm_; 292 AudioRendererAlgorithm algorithm_;
180 int frames_enqueued_; 293 int frames_enqueued_;
181 int channels_; 294 int channels_;
182 SampleFormat sample_format_; 295 SampleFormat sample_format_;
183 int bytes_per_sample_; 296 int bytes_per_sample_;
184 }; 297 };
185 298
186 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) { 299 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) {
187 Initialize(); 300 Initialize();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 TestPlaybackRate(2.1); 376 TestPlaybackRate(2.1);
264 TestPlaybackRate(0.9); 377 TestPlaybackRate(0.9);
265 TestPlaybackRate(0.6); 378 TestPlaybackRate(0.6);
266 TestPlaybackRate(1.4); 379 TestPlaybackRate(1.4);
267 TestPlaybackRate(0.3); 380 TestPlaybackRate(0.3);
268 } 381 }
269 382
270 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) { 383 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) {
271 Initialize(); 384 Initialize();
272 static const int kBufferSizeInFrames = 1; 385 static const int kBufferSizeInFrames = 1;
273 static const int kFramesRequested = 2 * kSamplesPerSecond; 386 static const int kFramesRequested = kOutputDurationInSec * kSamplesPerSecond;
274 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested); 387 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested);
275 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested); 388 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested);
276 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested); 389 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested);
277 } 390 }
278 391
279 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) { 392 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) {
280 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100); 393 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100);
281 TestPlaybackRate(1.0); 394 TestPlaybackRate(1.0);
282 TestPlaybackRate(0.5); 395 TestPlaybackRate(0.5);
283 TestPlaybackRate(1.5); 396 TestPlaybackRate(1.5);
284 } 397 }
285 398
286 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) { 399 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) {
287 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond); 400 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond);
288 TestPlaybackRate(1.0); 401 TestPlaybackRate(1.0);
289 TestPlaybackRate(0.5); 402 TestPlaybackRate(0.5);
290 TestPlaybackRate(1.5); 403 TestPlaybackRate(1.5);
291 } 404 }
292 405
293 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) { 406 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) {
294 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond); 407 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond);
295 TestPlaybackRate(1.0); 408 TestPlaybackRate(1.0);
296 TestPlaybackRate(0.5); 409 TestPlaybackRate(0.5);
297 TestPlaybackRate(1.5); 410 TestPlaybackRate(1.5);
298 } 411 }
299 412
413 TEST_F(AudioRendererAlgorithmTest, DotProduct) {
414 const int kChannels = 3;
415 const int kFrames = 20;
416 const int kHalfPulseWidth = 2;
417
418 scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
419 scoped_ptr<AudioBus> b = AudioBus::Create(kChannels, kFrames);
420
421 scoped_ptr<float[]> dot_prod(new float[kChannels]);
422
423 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, a.get());
424 FillWithSquarePulseTrain(kHalfPulseWidth, 1, 1, a.get());
425 FillWithSquarePulseTrain(kHalfPulseWidth, 2, 2, a.get());
426
427 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, b.get());
428 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 1, b.get());
429 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 2, b.get());
430
431 internal::MultiChannelDotProduct(a.get(), 0, b.get(), 0, kFrames,
432 dot_prod.get());
433
434 EXPECT_FLOAT_EQ(kFrames, dot_prod[0]);
435 EXPECT_FLOAT_EQ(0, dot_prod[1]);
436 EXPECT_FLOAT_EQ(-kFrames, dot_prod[2]);
437
438 internal::MultiChannelDotProduct(a.get(), 4, b.get(), 8, kFrames / 2,
439 dot_prod.get());
440
441 EXPECT_FLOAT_EQ(kFrames / 2, dot_prod[0]);
442 EXPECT_FLOAT_EQ(0, dot_prod[1]);
443 EXPECT_FLOAT_EQ(-kFrames / 2, dot_prod[2]);
444 }
445
446 TEST_F(AudioRendererAlgorithmTest, MovingBlockEnergy) {
447 const int kChannels = 2;
448 const int kFrames = 20;
449 const int kFramesPerBlock = 3;
450 const int kNumBlocks = kFrames - (kFramesPerBlock - 1);
451 scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames);
452 scoped_ptr<float[]> energies(new float[kChannels * kNumBlocks]);
453 float* ch_left = a->channel(0);
454 float* ch_right = a->channel(1);
455
456 // Fill up both channels.
457 for (int n = 0; n < kFrames; ++n) {
458 ch_left[n] = n;
459 ch_right[n] = kFrames - 1 - n;
460 }
461
462 internal::MultiChannelMovingBlockEnergies(a.get(), kFramesPerBlock,
463 energies.get());
464
465 // Check if the energy of candidate blocks of each channel computed correctly.
466 for (int n = 0; n < kNumBlocks; ++n) {
467 float expected_energy = 0;
468 for (int k = 0; k < kFramesPerBlock; ++k)
469 expected_energy += ch_left[n + k] * ch_left[n + k];
470
471 // Left (first) channel.
472 EXPECT_FLOAT_EQ(expected_energy, energies[2 * n]);
473
474 expected_energy = 0;
475 for (int k = 0; k < kFramesPerBlock; ++k)
476 expected_energy += ch_right[n + k] * ch_right[n + k];
477
478 // Second (right) channel.
479 EXPECT_FLOAT_EQ(expected_energy, energies[2 * n + 1]);
480 }
481 }
482
483 TEST_F(AudioRendererAlgorithmTest, FullAndDecimatedSearch) {
484 const int kFramesInSearchRegion = 12;
485 const int kChannels = 2;
486 float ch_0[] = {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0};
487 float ch_1[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 1.0, 0.1, 0.0, 0.0};
488 ASSERT_EQ(sizeof(ch_0), sizeof(ch_1));
489 ASSERT_EQ(static_cast<size_t>(kFramesInSearchRegion),
490 sizeof(ch_0) / sizeof(*ch_0));
491 scoped_ptr<AudioBus> search_region = AudioBus::CreateWrapper(kChannels);
492
493 search_region->SetChannelData(0, ch_0);
494 search_region->SetChannelData(1, ch_1);
495 search_region->set_frames(kFramesInSearchRegion);
496 ASSERT_EQ(kFramesInSearchRegion, search_region->frames());
497
498 const int kFramePerBlock = 4;
499 float target_0[] = {1.0, 1.0, 1.0, 0.0};
500 float target_1[] = {0.0, 1.0, 0.1, 1.0};
501 ASSERT_EQ(sizeof(target_0), sizeof(target_1));
502 ASSERT_EQ(static_cast<size_t>(kFramePerBlock),
503 sizeof(target_0) / sizeof(*target_0));
504
505 scoped_ptr<AudioBus> target = AudioBus::CreateWrapper(2);
506 target->SetChannelData(0, target_0);
507 target->SetChannelData(1, target_1);
508 target->set_frames(kFramePerBlock);
509 ASSERT_EQ(kFramePerBlock, target->frames());
510
511 scoped_ptr<float[]> energy_target(new float[kChannels]);
512
513 internal::MultiChannelDotProduct(target.get(), 0, target.get(), 0,
514 kFramePerBlock, energy_target.get());
515
516 ASSERT_EQ(3.f, energy_target[0]);
517 ASSERT_EQ(2.01f, energy_target[1]);
518
519 const int kNumCandidBlocks = kFramesInSearchRegion - (kFramePerBlock - 1);
520 scoped_ptr<float[]> energy_candid_blocks(new float[kNumCandidBlocks *
521 kChannels]);
522
523 internal::MultiChannelMovingBlockEnergies(
524 search_region.get(), kFramePerBlock, energy_candid_blocks.get());
525
526 // Check the energy of the candidate blocks of the first channel.
527 ASSERT_FLOAT_EQ(0, energy_candid_blocks[0]);
528 ASSERT_FLOAT_EQ(0, energy_candid_blocks[2]);
529 ASSERT_FLOAT_EQ(1, energy_candid_blocks[4]);
530 ASSERT_FLOAT_EQ(2, energy_candid_blocks[6]);
531 ASSERT_FLOAT_EQ(3, energy_candid_blocks[8]);
532 ASSERT_FLOAT_EQ(3, energy_candid_blocks[10]);
533 ASSERT_FLOAT_EQ(2, energy_candid_blocks[12]);
534 ASSERT_FLOAT_EQ(1, energy_candid_blocks[14]);
535 ASSERT_FLOAT_EQ(0, energy_candid_blocks[16]);
536
537 // Check the energy of the candidate blocks of the second channel.
538 ASSERT_FLOAT_EQ(0, energy_candid_blocks[1]);
539 ASSERT_FLOAT_EQ(0, energy_candid_blocks[3]);
540 ASSERT_FLOAT_EQ(0, energy_candid_blocks[5]);
541 ASSERT_FLOAT_EQ(0, energy_candid_blocks[7]);
542 ASSERT_FLOAT_EQ(0.01, energy_candid_blocks[9]);
543 ASSERT_FLOAT_EQ(1.01, energy_candid_blocks[11]);
544 ASSERT_FLOAT_EQ(1.02, energy_candid_blocks[13]);
545 ASSERT_FLOAT_EQ(1.02, energy_candid_blocks[15]);
546 ASSERT_FLOAT_EQ(1.01, energy_candid_blocks[17]);
547
548 // An interval which is of no effect.
549 internal::Interval exclude_interval = std::make_pair(-100, -10);
550 EXPECT_EQ(5, internal::FullSearch(
551 0, kNumCandidBlocks - 1, exclude_interval, target.get(),
552 search_region.get(), energy_target.get(), energy_candid_blocks.get()));
553
554 // Exclude the the best match.
555 exclude_interval = std::make_pair(2, 5);
556 EXPECT_EQ(7, internal::FullSearch(
557 0, kNumCandidBlocks - 1, exclude_interval, target.get(),
558 search_region.get(), energy_target.get(), energy_candid_blocks.get()));
559
560 // An interval which is of no effect.
561 exclude_interval = std::make_pair(-100, -10);
562 EXPECT_EQ(4, internal::DecimatedSearch(
563 4, exclude_interval, target.get(), search_region.get(),
564 energy_target.get(), energy_candid_blocks.get()));
565
566 EXPECT_EQ(5, internal::OptimalIndex(search_region.get(), target.get(),
567 exclude_interval));
568 }
569
570 TEST_F(AudioRendererAlgorithmTest, CubicInterpolation) {
571 // Arbitrary coefficients.
572 const float kA = 0.7;
573 const float kB = 1.2;
574 const float kC = 0.8;
575
576 float y_values[3];
577 y_values[0] = kA - kB + kC;
578 y_values[1] = kC;
579 y_values[2] = kA + kB + kC;
580
581 float extremum;
582 float extremum_value;
583
584 internal::CubicInterpolation(y_values, &extremum, &extremum_value);
585
586 float x_star = -kB / (2.f * kA);
587 float y_star = kA * x_star * x_star + kB * x_star + kC;
588
589 EXPECT_FLOAT_EQ(x_star, extremum);
590 EXPECT_FLOAT_EQ(y_star, extremum_value);
591 }
592
593 TEST_F(AudioRendererAlgorithmTest, WsolaSlowdown) {
594 WsolaTest(1.6f);
595 }
596
597 TEST_F(AudioRendererAlgorithmTest, WsolaSpeedup) {
598 WsolaTest(0.6f);
599 }
600
300 } // namespace media 601 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698