diff options
author | sandersd@chromium.org <sandersd@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 01:52:39 +0000 |
---|---|---|
committer | sandersd@chromium.org <sandersd@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-02 01:52:39 +0000 |
commit | 2c28a92bd629133a93ed6cb42b704afae7bf4782 (patch) | |
tree | 4ffba277e8dae269b289c79533ba7db4dcd606ac | |
parent | 8dafed5b8aede5253f8adbbab44585076e9c4f60 (diff) | |
download | chromium_src-2c28a92bd629133a93ed6cb42b704afae7bf4782.zip chromium_src-2c28a92bd629133a93ed6cb42b704afae7bf4782.tar.gz chromium_src-2c28a92bd629133a93ed6cb42b704afae7bf4782.tar.bz2 |
Handle near-colinear cases in WSOLAS QuadraticInterpolation better.
BUG=357870
Review URL: https://codereview.chromium.org/217553004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261033 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/filters/audio_renderer_algorithm_unittest.cc | 19 | ||||
-rw-r--r-- | media/filters/wsola_internals.cc | 28 | ||||
-rw-r--r-- | media/filters/wsola_internals.h | 20 |
3 files changed, 41 insertions, 26 deletions
diff --git a/media/filters/audio_renderer_algorithm_unittest.cc b/media/filters/audio_renderer_algorithm_unittest.cc index 13fa28b..ed6b6cc 100644 --- a/media/filters/audio_renderer_algorithm_unittest.cc +++ b/media/filters/audio_renderer_algorithm_unittest.cc @@ -597,7 +597,7 @@ TEST_F(AudioRendererAlgorithmTest, FullAndDecimatedSearch) { exclude_interval)); } -TEST_F(AudioRendererAlgorithmTest, CubicInterpolation) { +TEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation) { // Arbitrary coefficients. const float kA = 0.7f; const float kB = 1.2f; @@ -611,7 +611,7 @@ TEST_F(AudioRendererAlgorithmTest, CubicInterpolation) { float extremum; float extremum_value; - internal::CubicInterpolation(y_values, &extremum, &extremum_value); + internal::QuadraticInterpolation(y_values, &extremum, &extremum_value); float x_star = -kB / (2.f * kA); float y_star = kA * x_star * x_star + kB * x_star + kC; @@ -620,6 +620,21 @@ TEST_F(AudioRendererAlgorithmTest, CubicInterpolation) { EXPECT_FLOAT_EQ(y_star, extremum_value); } +TEST_F(AudioRendererAlgorithmTest, QuadraticInterpolation_Colinear) { + float y_values[3]; + y_values[0] = 1.0; + y_values[1] = 1.0; + y_values[2] = 1.0; + + float extremum; + float extremum_value; + + internal::QuadraticInterpolation(y_values, &extremum, &extremum_value); + + EXPECT_FLOAT_EQ(extremum, 0.0); + EXPECT_FLOAT_EQ(extremum_value, 1.0); +} + TEST_F(AudioRendererAlgorithmTest, WsolaSlowdown) { WsolaTest(0.6f); } diff --git a/media/filters/wsola_internals.cc b/media/filters/wsola_internals.cc index 45cdd8f..9ce1f0d 100644 --- a/media/filters/wsola_internals.cc +++ b/media/filters/wsola_internals.cc @@ -84,19 +84,25 @@ void MultiChannelMovingBlockEnergies(const AudioBus* input, } // Fit the curve f(x) = a * x^2 + b * x + c such that -// f(-1) = |y[0]| -// f(0) = |y[1]| -// f(1) = |y[2]|. -void CubicInterpolation(const float* y_values, - float* extremum, - float* extremum_value) { +// f(-1) = y[0] +// f(0) = y[1] +// f(1) = y[2] +// and return the maximum, assuming that y[0] <= y[1] >= y[2]. +void QuadraticInterpolation(const float* y_values, + float* extremum, + float* extremum_value) { float a = 0.5f * (y_values[2] + y_values[0]) - y_values[1]; float b = 0.5f * (y_values[2] - y_values[0]); float c = y_values[1]; - DCHECK_NE(a, 0); - *extremum = -b / (2.f * a); - *extremum_value = a * (*extremum) * (*extremum) + b * (*extremum) + c; + if (a == 0.f) { + // The coordinates are colinear (within floating-point error). + *extremum = 0; + *extremum_value = y_values[1]; + } else { + *extremum = -b / (2.f * a); + *extremum_value = a * (*extremum) * (*extremum) + b * (*extremum) + c; + } } int DecimatedSearch(int decimation, @@ -154,8 +160,8 @@ int DecimatedSearch(int decimation, // estimate of candidate maximum. float normalized_candidate_index; float candidate_similarity; - CubicInterpolation(similarity, &normalized_candidate_index, - &candidate_similarity); + QuadraticInterpolation(similarity, &normalized_candidate_index, + &candidate_similarity); int candidate_index = n - decimation + static_cast<int>( normalized_candidate_index * decimation + 0.5f); diff --git a/media/filters/wsola_internals.h b/media/filters/wsola_internals.h index 55fff04..13d2875 100644 --- a/media/filters/wsola_internals.h +++ b/media/filters/wsola_internals.h @@ -38,19 +38,13 @@ MEDIA_EXPORT void MultiChannelMovingBlockEnergies(const AudioBus* input, float* energy); // Fit the curve f(x) = a * x^2 + b * x + c such that -// -// f(-1) = |y[0]| -// f(0) = |y[1]| -// f(1) = |y[2]|. -// -// Then compute the |extremum| point -b / (2*a) and |extremum_value| -// b^2 / (4*a) - b^2 / (2*a) + c. -// -// It is not expected that this function is called with -// y[0] == y[1] == y[2]. -MEDIA_EXPORT void CubicInterpolation(const float* y_values, - float* extremum, - float* extremum_value); +// f(-1) = y[0] +// f(0) = y[1] +// f(1) = y[2] +// and return the maximum, assuming that y[0] <= y[1] >= y[2]. +MEDIA_EXPORT void QuadraticInterpolation(const float* y_values, + float* extremum, + float* extremum_value); // Search a subset of all candid blocks. The search is performed every // |decimation| frames. This reduces complexity by a factor of about |