OLD | NEW |
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> |
12 | 13 |
13 #include "base/bind.h" | 14 #include "base/bind.h" |
14 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/memory/scoped_ptr.h" |
15 #include "media/base/audio_buffer.h" | 17 #include "media/base/audio_buffer.h" |
16 #include "media/base/audio_bus.h" | 18 #include "media/base/audio_bus.h" |
17 #include "media/base/buffers.h" | 19 #include "media/base/buffers.h" |
18 #include "media/base/channel_layout.h" | 20 #include "media/base/channel_layout.h" |
19 #include "media/base/test_helpers.h" | 21 #include "media/base/test_helpers.h" |
20 #include "media/filters/audio_renderer_algorithm.h" | 22 #include "media/filters/audio_renderer_algorithm.h" |
| 23 #include "media/filters/wsola_internals.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
22 | |
23 namespace media { | 25 namespace media { |
24 | 26 |
25 static const int kFrameSize = 250; | 27 static const int kFrameSize = 250; |
26 static const int kSamplesPerSecond = 3000; | 28 static const int kSamplesPerSecond = 3000; |
27 static const SampleFormat kSampleFormat = kSampleFormatS16; | 29 static const SampleFormat kSampleFormat = kSampleFormatS16; |
| 30 static const int kOutputDurationInSec = 10; |
| 31 |
| 32 static void FillWithSquarePulseTrain( |
| 33 int half_pulse_width, int offset, int channel, AudioBus* audio_bus) { |
| 34 ASSERT_GE(offset, 0); |
| 35 ASSERT_LT(offset, audio_bus->frames()); |
| 36 |
| 37 float* ch = audio_bus->channel(channel); |
| 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 ch[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 < audio_bus->frames(); ++n, ++k) { |
| 54 if (k >= half_pulse_width) { |
| 55 pulse = -pulse; |
| 56 k = 0; |
| 57 } |
| 58 ch[n] = pulse; |
| 59 } |
| 60 } |
| 61 |
28 | 62 |
29 class AudioRendererAlgorithmTest : public testing::Test { | 63 class AudioRendererAlgorithmTest : public testing::Test { |
30 public: | 64 public: |
31 AudioRendererAlgorithmTest() | 65 AudioRendererAlgorithmTest() |
32 : frames_enqueued_(0), | 66 : frames_enqueued_(0), |
33 channels_(0), | 67 channels_(0), |
34 sample_format_(kUnknownSampleFormat), | 68 sample_format_(kUnknownSampleFormat), |
35 bytes_per_sample_(0) { | 69 bytes_per_sample_(0) { |
36 } | 70 } |
37 | 71 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 int initial_frames_buffered) { | 145 int initial_frames_buffered) { |
112 int frame_delta = frames_enqueued_ - initial_frames_enqueued; | 146 int frame_delta = frames_enqueued_ - initial_frames_enqueued; |
113 int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered; | 147 int buffered_delta = algorithm_.frames_buffered() - initial_frames_buffered; |
114 int consumed = frame_delta - buffered_delta; | 148 int consumed = frame_delta - buffered_delta; |
115 CHECK_GE(consumed, 0); | 149 CHECK_GE(consumed, 0); |
116 return consumed; | 150 return consumed; |
117 } | 151 } |
118 | 152 |
119 void TestPlaybackRate(double playback_rate) { | 153 void TestPlaybackRate(double playback_rate) { |
120 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100; | 154 const int kDefaultBufferSize = algorithm_.samples_per_second() / 100; |
121 const int kDefaultFramesRequested = 2 * algorithm_.samples_per_second(); | 155 const int kDefaultFramesRequested = kOutputDurationInSec * |
| 156 algorithm_.samples_per_second(); |
122 | 157 |
123 TestPlaybackRate( | 158 TestPlaybackRate( |
124 playback_rate, kDefaultBufferSize, kDefaultFramesRequested); | 159 playback_rate, kDefaultBufferSize, kDefaultFramesRequested); |
125 } | 160 } |
126 | 161 |
127 void TestPlaybackRate(double playback_rate, | 162 void TestPlaybackRate(double playback_rate, |
128 int buffer_size_in_frames, | 163 int buffer_size_in_frames, |
129 int total_frames_requested) { | 164 int total_frames_requested) { |
130 int initial_frames_enqueued = frames_enqueued_; | 165 int initial_frames_enqueued = frames_enqueued_; |
131 int initial_frames_buffered = algorithm_.frames_buffered(); | 166 int initial_frames_buffered = algorithm_.frames_buffered(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 // large, one can expect less than a 1% difference in most cases. In our | 203 // 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 | 204 // current implementation, sped up playback is less accurate than slowed |
170 // down playback, and for playback_rate > 1, playback rate generally gets | 205 // 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 | 206 // less and less accurate the farther it drifts from 1 (though this is |
172 // nonlinear). | 207 // nonlinear). |
173 double actual_playback_rate = | 208 double actual_playback_rate = |
174 1.0 * frames_consumed / total_frames_requested; | 209 1.0 * frames_consumed / total_frames_requested; |
175 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0); | 210 EXPECT_NEAR(playback_rate, actual_playback_rate, playback_rate / 100.0); |
176 } | 211 } |
177 | 212 |
| 213 void WsolaTest(float playback_rate) { |
| 214 const int kSampleRateHz = 48000; |
| 215 const media::ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; |
| 216 const int kBytesPerSample = 2; |
| 217 const int kNumFrames = kSampleRateHz / 100; // 10 milliseconds. |
| 218 |
| 219 channels_ = ChannelLayoutToChannelCount(kChannelLayout); |
| 220 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, |
| 221 kSampleRateHz, kBytesPerSample * 8, kNumFrames); |
| 222 algorithm_.Initialize(playback_rate, params); |
| 223 |
| 224 // A pulse is 6 milliseconds (even number of samples). |
| 225 const int kPulseWidthSamples = 6 * kSampleRateHz / 1000; |
| 226 const int kHalfPulseWidthSamples = kPulseWidthSamples / 2; |
| 227 |
| 228 // For the ease of implementation get 1 frame every call to FillBuffer(). |
| 229 scoped_ptr<AudioBus> output = AudioBus::Create(channels_, 1); |
| 230 |
| 231 scoped_ptr<AudioBus> ref = |
| 232 AudioBus::Create(channels_, kPulseWidthSamples); |
| 233 |
| 234 FillWithSquarePulseTrain(kHalfPulseWidthSamples, 0, 0, ref.get()); |
| 235 FillWithSquarePulseTrain(kHalfPulseWidthSamples, kHalfPulseWidthSamples, 1, |
| 236 ref.get()); |
| 237 |
| 238 const int all_channels_samples = channels_ * kPulseWidthSamples; |
| 239 scoped_ptr<int16_t[]> ref_memory_buffer(new int16_t[all_channels_samples]); |
| 240 uint8_t* pp[] = { reinterpret_cast<uint8_t*>(ref_memory_buffer.get()) }; |
| 241 |
| 242 ref->ToInterleaved(kPulseWidthSamples, sizeof(*(ref_memory_buffer.get())), |
| 243 ref_memory_buffer.get()); |
| 244 |
| 245 base::TimeDelta timestamp = base::TimeDelta::FromInternalValue(0); |
| 246 base::TimeDelta duration = base::TimeDelta::FromInternalValue(5000); |
| 247 |
| 248 // |input| has a whole pulse, therefore, we can inject it |
| 249 // into |algorithm_| multiple of times to create a periodic input. |
| 250 scoped_refptr<AudioBuffer> input = AudioBuffer::CopyFrom( |
| 251 kSampleFormatS16, channels_, kPulseWidthSamples, pp, timestamp, |
| 252 duration); |
| 253 |
| 254 // Equivalent of 4 seconds. |
| 255 const int kNumRequestedPulses = kSampleRateHz * 4 / kPulseWidthSamples; |
| 256 for (int n = 0; n < kNumRequestedPulses; ++n) { |
| 257 // The output is buffered here until we have a pulse is created. Then |
| 258 // reference file is compared with this buffer. |
| 259 scoped_ptr<AudioBus> out_buffer = |
| 260 AudioBus::Create(channels_, kPulseWidthSamples); |
| 261 |
| 262 int num_buffered_frames = 0; |
| 263 while (num_buffered_frames < kPulseWidthSamples) { |
| 264 int num_samples = algorithm_.FillBuffer(output.get(), 1); |
| 265 EXPECT_LE(num_samples, 1); |
| 266 if (num_samples > 0) { |
| 267 output->CopyPartialFramesTo(0, num_samples, num_buffered_frames, |
| 268 out_buffer.get()); |
| 269 num_buffered_frames++; |
| 270 } else { |
| 271 algorithm_.EnqueueBuffer(input); |
| 272 } |
| 273 } |
| 274 |
| 275 // Pulses in the first half of WSOLA AOL frame are not constructed |
| 276 // perfectly. Do not check them. |
| 277 if (n > 3) { |
| 278 scoped_ptr<int16_t[]> test_memory_buffer( |
| 279 new int16_t[all_channels_samples]); |
| 280 out_buffer->ToInterleaved(kPulseWidthSamples, |
| 281 sizeof(*(test_memory_buffer.get())), |
| 282 test_memory_buffer.get()); |
| 283 |
| 284 // Because of overlap-and-add we might have round off error. |
| 285 for (int k = 0; k < all_channels_samples - 1; ++k) { |
| 286 ASSERT_NEAR(ref_memory_buffer[k], test_memory_buffer[k], 1) |
| 287 << " loop " << n << " at sample " << k; |
| 288 } |
| 289 } |
| 290 |
| 291 // Zero out the buffer to be sure the next comparison is relevant. |
| 292 out_buffer->Zero(); |
| 293 } |
| 294 } |
| 295 |
178 protected: | 296 protected: |
179 AudioRendererAlgorithm algorithm_; | 297 AudioRendererAlgorithm algorithm_; |
180 int frames_enqueued_; | 298 int frames_enqueued_; |
181 int channels_; | 299 int channels_; |
182 SampleFormat sample_format_; | 300 SampleFormat sample_format_; |
183 int bytes_per_sample_; | 301 int bytes_per_sample_; |
184 }; | 302 }; |
185 | 303 |
186 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) { | 304 TEST_F(AudioRendererAlgorithmTest, FillBuffer_NormalRate) { |
187 Initialize(); | 305 Initialize(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 TestPlaybackRate(2.1); | 381 TestPlaybackRate(2.1); |
264 TestPlaybackRate(0.9); | 382 TestPlaybackRate(0.9); |
265 TestPlaybackRate(0.6); | 383 TestPlaybackRate(0.6); |
266 TestPlaybackRate(1.4); | 384 TestPlaybackRate(1.4); |
267 TestPlaybackRate(0.3); | 385 TestPlaybackRate(0.3); |
268 } | 386 } |
269 | 387 |
270 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) { | 388 TEST_F(AudioRendererAlgorithmTest, FillBuffer_SmallBufferSize) { |
271 Initialize(); | 389 Initialize(); |
272 static const int kBufferSizeInFrames = 1; | 390 static const int kBufferSizeInFrames = 1; |
273 static const int kFramesRequested = 2 * kSamplesPerSecond; | 391 static const int kFramesRequested = kOutputDurationInSec * kSamplesPerSecond; |
274 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested); | 392 TestPlaybackRate(1.0, kBufferSizeInFrames, kFramesRequested); |
275 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested); | 393 TestPlaybackRate(0.5, kBufferSizeInFrames, kFramesRequested); |
276 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested); | 394 TestPlaybackRate(1.5, kBufferSizeInFrames, kFramesRequested); |
277 } | 395 } |
278 | 396 |
279 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) { | 397 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LargeBufferSize) { |
280 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100); | 398 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS16, 44100); |
281 TestPlaybackRate(1.0); | 399 TestPlaybackRate(1.0); |
282 TestPlaybackRate(0.5); | 400 TestPlaybackRate(0.5); |
283 TestPlaybackRate(1.5); | 401 TestPlaybackRate(1.5); |
284 } | 402 } |
285 | 403 |
286 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) { | 404 TEST_F(AudioRendererAlgorithmTest, FillBuffer_LowerQualityAudio) { |
287 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond); | 405 Initialize(CHANNEL_LAYOUT_MONO, kSampleFormatU8, kSamplesPerSecond); |
288 TestPlaybackRate(1.0); | 406 TestPlaybackRate(1.0); |
289 TestPlaybackRate(0.5); | 407 TestPlaybackRate(0.5); |
290 TestPlaybackRate(1.5); | 408 TestPlaybackRate(1.5); |
291 } | 409 } |
292 | 410 |
293 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) { | 411 TEST_F(AudioRendererAlgorithmTest, FillBuffer_HigherQualityAudio) { |
294 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond); | 412 Initialize(CHANNEL_LAYOUT_STEREO, kSampleFormatS32, kSamplesPerSecond); |
295 TestPlaybackRate(1.0); | 413 TestPlaybackRate(1.0); |
296 TestPlaybackRate(0.5); | 414 TestPlaybackRate(0.5); |
297 TestPlaybackRate(1.5); | 415 TestPlaybackRate(1.5); |
298 } | 416 } |
299 | 417 |
| 418 TEST_F(AudioRendererAlgorithmTest, DotProduct) { |
| 419 const int kChannels = 3; |
| 420 const int kFrames = 20; |
| 421 const int kHalfPulseWidth = 2; |
| 422 |
| 423 scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames); |
| 424 scoped_ptr<AudioBus> b = AudioBus::Create(kChannels, kFrames); |
| 425 |
| 426 scoped_ptr<float[]> dot_prod(new float[kChannels]); |
| 427 |
| 428 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, a.get()); |
| 429 FillWithSquarePulseTrain(kHalfPulseWidth, 1, 1, a.get()); |
| 430 FillWithSquarePulseTrain(kHalfPulseWidth, 2, 2, a.get()); |
| 431 |
| 432 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 0, b.get()); |
| 433 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 1, b.get()); |
| 434 FillWithSquarePulseTrain(kHalfPulseWidth, 0, 2, b.get()); |
| 435 |
| 436 internal::MultiChannelDotProduct(a.get(), 0, b.get(), 0, kFrames, |
| 437 dot_prod.get()); |
| 438 |
| 439 EXPECT_FLOAT_EQ(kFrames, dot_prod[0]); |
| 440 EXPECT_FLOAT_EQ(0, dot_prod[1]); |
| 441 EXPECT_FLOAT_EQ(-kFrames, dot_prod[2]); |
| 442 |
| 443 internal::MultiChannelDotProduct(a.get(), 4, b.get(), 8, kFrames / 2, |
| 444 dot_prod.get()); |
| 445 |
| 446 EXPECT_FLOAT_EQ(kFrames / 2, dot_prod[0]); |
| 447 EXPECT_FLOAT_EQ(0, dot_prod[1]); |
| 448 EXPECT_FLOAT_EQ(-kFrames / 2, dot_prod[2]); |
| 449 } |
| 450 |
| 451 TEST_F(AudioRendererAlgorithmTest, MovingBlockEnergy) { |
| 452 const int kChannels = 2; |
| 453 const int kFrames = 20; |
| 454 const int kFramesPerBlock = 3; |
| 455 const int kNumBlocks = kFrames - (kFramesPerBlock - 1); |
| 456 scoped_ptr<AudioBus> a = AudioBus::Create(kChannels, kFrames); |
| 457 scoped_ptr<float[]> energies(new float[kChannels * kNumBlocks]); |
| 458 float* ch_left = a->channel(0); |
| 459 float* ch_right = a->channel(1); |
| 460 |
| 461 // Fill up both channels. |
| 462 for (int n = 0; n < kFrames; ++n) { |
| 463 ch_left[n] = n; |
| 464 ch_right[n] = kFrames - 1 - n; |
| 465 } |
| 466 |
| 467 internal::MultiChannelMovingBlockEnergies(a.get(), kFramesPerBlock, |
| 468 energies.get()); |
| 469 |
| 470 for (int n = 0; n < kNumBlocks; ++n) { |
| 471 float expected_energy = 0; |
| 472 for (int k = 0; k < kFramesPerBlock; ++k) |
| 473 expected_energy += ch_left[n + k] * ch_left[n + k]; |
| 474 EXPECT_FLOAT_EQ(expected_energy, energies[2 * n]); |
| 475 |
| 476 expected_energy = 0; |
| 477 for (int k = 0; k < kFramesPerBlock; ++k) |
| 478 expected_energy += ch_right[n + k] * ch_right[n + k]; |
| 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 ASSERT_FLOAT_EQ(0, energy_candid_blocks[0]); |
| 527 ASSERT_FLOAT_EQ(0, energy_candid_blocks[2]); |
| 528 ASSERT_FLOAT_EQ(1, energy_candid_blocks[4]); |
| 529 ASSERT_FLOAT_EQ(2, energy_candid_blocks[6]); |
| 530 ASSERT_FLOAT_EQ(3, energy_candid_blocks[8]); |
| 531 ASSERT_FLOAT_EQ(3, energy_candid_blocks[10]); |
| 532 ASSERT_FLOAT_EQ(2, energy_candid_blocks[12]); |
| 533 ASSERT_FLOAT_EQ(1, energy_candid_blocks[14]); |
| 534 ASSERT_FLOAT_EQ(0, energy_candid_blocks[16]); |
| 535 |
| 536 ASSERT_FLOAT_EQ(0, energy_candid_blocks[1]); |
| 537 ASSERT_FLOAT_EQ(0, energy_candid_blocks[3]); |
| 538 ASSERT_FLOAT_EQ(0, energy_candid_blocks[5]); |
| 539 ASSERT_FLOAT_EQ(0, energy_candid_blocks[7]); |
| 540 ASSERT_FLOAT_EQ(0.01, energy_candid_blocks[9]); |
| 541 ASSERT_FLOAT_EQ(1.01, energy_candid_blocks[11]); |
| 542 ASSERT_FLOAT_EQ(1.02, energy_candid_blocks[13]); |
| 543 ASSERT_FLOAT_EQ(1.02, energy_candid_blocks[15]); |
| 544 ASSERT_FLOAT_EQ(1.01, energy_candid_blocks[17]); |
| 545 |
| 546 // An interval which is of no effect. |
| 547 internal::Interval exclude_interval = std::make_pair(-100, -10); |
| 548 EXPECT_EQ(5, internal::FullSearch( |
| 549 0, kNumCandidBlocks - 1, exclude_interval, target.get(), |
| 550 search_region.get(), energy_target.get(), energy_candid_blocks.get())); |
| 551 |
| 552 // Exclude the the best match. |
| 553 exclude_interval = std::make_pair(2, 5); |
| 554 EXPECT_EQ(7, internal::FullSearch( |
| 555 0, kNumCandidBlocks - 1, exclude_interval, target.get(), |
| 556 search_region.get(), energy_target.get(), energy_candid_blocks.get())); |
| 557 |
| 558 // An interval which is of no effect. |
| 559 exclude_interval = std::make_pair(-100, -10); |
| 560 EXPECT_EQ(4, internal::DecimatedSearch( |
| 561 4, exclude_interval, target.get(), search_region.get(), |
| 562 energy_target.get(), energy_candid_blocks.get())); |
| 563 |
| 564 EXPECT_EQ(5, internal::OptimalIndex(search_region.get(), target.get(), |
| 565 exclude_interval)); |
| 566 } |
| 567 |
| 568 TEST_F(AudioRendererAlgorithmTest, CubicInterpolation) { |
| 569 // Arbitrary coefficients. |
| 570 const float kA = 0.7; |
| 571 const float kB = 1.2; |
| 572 const float kC = 0.8; |
| 573 |
| 574 float y_values[3]; |
| 575 y_values[0] = kA - kB + kC; |
| 576 y_values[1] = kC; |
| 577 y_values[2] = kA + kB + kC; |
| 578 |
| 579 float extremum; |
| 580 float extremum_value; |
| 581 |
| 582 internal::CubicInterpolation(y_values, &extremum, &extremum_value); |
| 583 |
| 584 float x_star = -kB / (2.f * kA); |
| 585 float y_star = kA * x_star * x_star + kB * x_star + kC; |
| 586 |
| 587 EXPECT_FLOAT_EQ(x_star, extremum); |
| 588 EXPECT_FLOAT_EQ(y_star, extremum_value); |
| 589 } |
| 590 |
| 591 TEST_F(AudioRendererAlgorithmTest, WsolaSlowdown) { |
| 592 WsolaTest(1.6f); |
| 593 } |
| 594 |
| 595 TEST_F(AudioRendererAlgorithmTest, WsolaSpeedup) { |
| 596 WsolaTest(0.6f); |
| 597 } |
| 598 |
300 } // namespace media | 599 } // namespace media |
OLD | NEW |