summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorsandersd@chromium.org <sandersd@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-02 01:52:39 +0000
committersandersd@chromium.org <sandersd@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-02 01:52:39 +0000
commit2c28a92bd629133a93ed6cb42b704afae7bf4782 (patch)
tree4ffba277e8dae269b289c79533ba7db4dcd606ac /media
parent8dafed5b8aede5253f8adbbab44585076e9c4f60 (diff)
downloadchromium_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
Diffstat (limited to 'media')
-rw-r--r--media/filters/audio_renderer_algorithm_unittest.cc19
-rw-r--r--media/filters/wsola_internals.cc28
-rw-r--r--media/filters/wsola_internals.h20
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