summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/audio/FFTFrame.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/platform/audio/FFTFrame.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/platform/audio/FFTFrame.cpp')
-rw-r--r--WebCore/platform/audio/FFTFrame.cpp269
1 files changed, 0 insertions, 269 deletions
diff --git a/WebCore/platform/audio/FFTFrame.cpp b/WebCore/platform/audio/FFTFrame.cpp
deleted file mode 100644
index d9979d9..0000000
--- a/WebCore/platform/audio/FFTFrame.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "FFTFrame.h"
-
-#include <wtf/Complex.h>
-#include <wtf/MathExtras.h>
-#include <wtf/OwnPtr.h>
-
-namespace WebCore {
-
-void FFTFrame::doPaddedFFT(float* data, size_t dataSize)
-{
- // Zero-pad the impulse response
- AudioFloatArray paddedResponse(fftSize()); // zero-initialized
- paddedResponse.copyToRange(data, 0, dataSize);
-
- // Get the frequency-domain version of padded response
- doFFT(paddedResponse.data());
-}
-
-PassOwnPtr<FFTFrame> FFTFrame::createInterpolatedFrame(const FFTFrame& frame1, const FFTFrame& frame2, double x)
-{
- OwnPtr<FFTFrame> newFrame = adoptPtr(new FFTFrame(frame1.fftSize()));
-
- newFrame->interpolateFrequencyComponents(frame1, frame2, x);
-
- // In the time-domain, the 2nd half of the response must be zero, to avoid circular convolution aliasing...
- int fftSize = newFrame->fftSize();
- AudioFloatArray buffer(fftSize);
- newFrame->doInverseFFT(buffer.data());
- buffer.zeroRange(fftSize / 2, fftSize);
-
- // Put back into frequency domain.
- newFrame->doFFT(buffer.data());
-
- return newFrame.release();
-}
-
-void FFTFrame::interpolateFrequencyComponents(const FFTFrame& frame1, const FFTFrame& frame2, double interp)
-{
- // FIXME : with some work, this method could be optimized
-
- float* realP = realData();
- float* imagP = imagData();
-
- const float* realP1 = frame1.realData();
- const float* imagP1 = frame1.imagData();
- const float* realP2 = frame2.realData();
- const float* imagP2 = frame2.imagData();
-
- m_FFTSize = frame1.fftSize();
- m_log2FFTSize = frame1.log2FFTSize();
-
- double s1base = (1.0 - interp);
- double s2base = interp;
-
- double phaseAccum = 0.0;
- double lastPhase1 = 0.0;
- double lastPhase2 = 0.0;
-
- realP[0] = static_cast<float>(s1base * realP1[0] + s2base * realP2[0]);
- imagP[0] = static_cast<float>(s1base * imagP1[0] + s2base * imagP2[0]);
-
- int n = m_FFTSize / 2;
-
- for (int i = 1; i < n; ++i) {
- Complex c1(realP1[i], imagP1[i]);
- Complex c2(realP2[i], imagP2[i]);
-
- double mag1 = abs(c1);
- double mag2 = abs(c2);
-
- // Interpolate magnitudes in decibels
- double mag1db = 20.0 * log10(mag1);
- double mag2db = 20.0 * log10(mag2);
-
- double s1 = s1base;
- double s2 = s2base;
-
- double magdbdiff = mag1db - mag2db;
-
- // Empirical tweak to retain higher-frequency zeroes
- double threshold = (i > 16) ? 5.0 : 2.0;
-
- if (magdbdiff < -threshold && mag1db < 0.0) {
- s1 = pow(s1, 0.75);
- s2 = 1.0 - s1;
- } else if (magdbdiff > threshold && mag2db < 0.0) {
- s2 = pow(s2, 0.75);
- s1 = 1.0 - s2;
- }
-
- // Average magnitude by decibels instead of linearly
- double magdb = s1 * mag1db + s2 * mag2db;
- double mag = pow(10.0, 0.05 * magdb);
-
- // Now, deal with phase
- double phase1 = arg(c1);
- double phase2 = arg(c2);
-
- double deltaPhase1 = phase1 - lastPhase1;
- double deltaPhase2 = phase2 - lastPhase2;
- lastPhase1 = phase1;
- lastPhase2 = phase2;
-
- // Unwrap phase deltas
- if (deltaPhase1 > piDouble)
- deltaPhase1 -= 2.0 * piDouble;
- if (deltaPhase1 < -piDouble)
- deltaPhase1 += 2.0 * piDouble;
- if (deltaPhase2 > piDouble)
- deltaPhase2 -= 2.0 * piDouble;
- if (deltaPhase2 < -piDouble)
- deltaPhase2 += 2.0 * piDouble;
-
- // Blend group-delays
- double deltaPhaseBlend;
-
- if (deltaPhase1 - deltaPhase2 > piDouble)
- deltaPhaseBlend = s1 * deltaPhase1 + s2 * (2.0 * piDouble + deltaPhase2);
- else if (deltaPhase2 - deltaPhase1 > piDouble)
- deltaPhaseBlend = s1 * (2.0 * piDouble + deltaPhase1) + s2 * deltaPhase2;
- else
- deltaPhaseBlend = s1 * deltaPhase1 + s2 * deltaPhase2;
-
- phaseAccum += deltaPhaseBlend;
-
- // Unwrap
- if (phaseAccum > piDouble)
- phaseAccum -= 2.0 * piDouble;
- if (phaseAccum < -piDouble)
- phaseAccum += 2.0 * piDouble;
-
- Complex c = complexFromMagnitudePhase(mag, phaseAccum);
-
- realP[i] = static_cast<float>(c.real());
- imagP[i] = static_cast<float>(c.imag());
- }
-}
-
-double FFTFrame::extractAverageGroupDelay()
-{
- float* realP = realData();
- float* imagP = imagData();
-
- double aveSum = 0.0;
- double weightSum = 0.0;
- double lastPhase = 0.0;
-
- int halfSize = fftSize() / 2;
-
- const double kSamplePhaseDelay = (2.0 * piDouble) / double(fftSize());
-
- // Calculate weighted average group delay
- for (int i = 0; i < halfSize; i++) {
- Complex c(realP[i], imagP[i]);
- double mag = abs(c);
- double phase = arg(c);
-
- double deltaPhase = phase - lastPhase;
- lastPhase = phase;
-
- // Unwrap
- if (deltaPhase < -piDouble)
- deltaPhase += 2.0 * piDouble;
- if (deltaPhase > piDouble)
- deltaPhase -= 2.0 * piDouble;
-
- aveSum += mag * deltaPhase;
- weightSum += mag;
- }
-
- // Note how we invert the phase delta wrt frequency since this is how group delay is defined
- double ave = aveSum / weightSum;
- double aveSampleDelay = -ave / kSamplePhaseDelay;
-
- // Leave 20 sample headroom (for leading edge of impulse)
- if (aveSampleDelay > 20.0)
- aveSampleDelay -= 20.0;
-
- // Remove average group delay (minus 20 samples for headroom)
- addConstantGroupDelay(-aveSampleDelay);
-
- // Remove DC offset
- realP[0] = 0.0f;
-
- return aveSampleDelay;
-}
-
-void FFTFrame::addConstantGroupDelay(double sampleFrameDelay)
-{
- int halfSize = fftSize() / 2;
-
- float* realP = realData();
- float* imagP = imagData();
-
- const double kSamplePhaseDelay = (2.0 * piDouble) / double(fftSize());
-
- double phaseAdj = -sampleFrameDelay * kSamplePhaseDelay;
-
- // Add constant group delay
- for (int i = 1; i < halfSize; i++) {
- Complex c(realP[i], imagP[i]);
- double mag = abs(c);
- double phase = arg(c);
-
- phase += i * phaseAdj;
-
- Complex c2 = complexFromMagnitudePhase(mag, phase);
-
- realP[i] = static_cast<float>(c2.real());
- imagP[i] = static_cast<float>(c2.imag());
- }
-}
-
-#ifndef NDEBUG
-void FFTFrame::print()
-{
- FFTFrame& frame = *this;
- float* realP = frame.realData();
- float* imagP = frame.imagData();
- printf("**** \n");
- printf("DC = %f : nyquist = %f\n", realP[0], imagP[0]);
-
- int n = m_FFTSize / 2;
-
- for (int i = 1; i < n; i++) {
- double mag = sqrt(realP[i] * realP[i] + imagP[i] * imagP[i]);
- double phase = atan2(realP[i], imagP[i]);
-
- printf("[%d] (%f %f)\n", i, mag, phase);
- }
- printf("****\n");
-}
-#endif // NDEBUG
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)