[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

crogers at google.com crogers at google.com
Wed Dec 22 15:25:02 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit cb1d3ae8849677e2a12d7836ea68d65578d236b0
Author: crogers at google.com <crogers at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Nov 3 00:44:34 2010 +0000

    2010-11-02  Chris Rogers  <crogers at google.com>
    
            Reviewed by Kenneth Russell.
    
            Add RealtimeAnalyser files
            https://bugs.webkit.org/show_bug.cgi?id=48810
    
            No new tests since audio API is not yet implemented.
    
            * webaudio/RealtimeAnalyser.cpp: Added.
            (WebCore::RealtimeAnalyser::RealtimeAnalyser):
            (WebCore::RealtimeAnalyser::~RealtimeAnalyser):
            (WebCore::RealtimeAnalyser::reset):
            (WebCore::RealtimeAnalyser::setFftSize):
            (WebCore::RealtimeAnalyser::writeInput):
            (WebCore::RealtimeAnalyser::doFFTAnalysis):
            (WebCore::RealtimeAnalyser::getFloatFrequencyData):
            (WebCore::RealtimeAnalyser::getByteFrequencyData):
            (WebCore::RealtimeAnalyser::getByteTimeDomainData):
            * webaudio/RealtimeAnalyser.h: Added.
            (WebCore::RealtimeAnalyser::fftSize):
            (WebCore::RealtimeAnalyser::frequencyBinCount):
            (WebCore::RealtimeAnalyser::setMinDecibels):
            (WebCore::RealtimeAnalyser::minDecibels):
            (WebCore::RealtimeAnalyser::setMaxDecibels):
            (WebCore::RealtimeAnalyser::maxDecibels):
            (WebCore::RealtimeAnalyser::setSmoothingTimeConstant):
            (WebCore::RealtimeAnalyser::smoothingTimeConstant):
            (WebCore::RealtimeAnalyser::magnitudeBuffer):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71193 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 99eaaaf..de2484f 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,33 @@
+2010-11-02  Chris Rogers  <crogers at google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Add RealtimeAnalyser files
+        https://bugs.webkit.org/show_bug.cgi?id=48810
+
+        No new tests since audio API is not yet implemented.
+
+        * webaudio/RealtimeAnalyser.cpp: Added.
+        (WebCore::RealtimeAnalyser::RealtimeAnalyser):
+        (WebCore::RealtimeAnalyser::~RealtimeAnalyser):
+        (WebCore::RealtimeAnalyser::reset):
+        (WebCore::RealtimeAnalyser::setFftSize):
+        (WebCore::RealtimeAnalyser::writeInput):
+        (WebCore::RealtimeAnalyser::doFFTAnalysis):
+        (WebCore::RealtimeAnalyser::getFloatFrequencyData):
+        (WebCore::RealtimeAnalyser::getByteFrequencyData):
+        (WebCore::RealtimeAnalyser::getByteTimeDomainData):
+        * webaudio/RealtimeAnalyser.h: Added.
+        (WebCore::RealtimeAnalyser::fftSize):
+        (WebCore::RealtimeAnalyser::frequencyBinCount):
+        (WebCore::RealtimeAnalyser::setMinDecibels):
+        (WebCore::RealtimeAnalyser::minDecibels):
+        (WebCore::RealtimeAnalyser::setMaxDecibels):
+        (WebCore::RealtimeAnalyser::maxDecibels):
+        (WebCore::RealtimeAnalyser::setSmoothingTimeConstant):
+        (WebCore::RealtimeAnalyser::smoothingTimeConstant):
+        (WebCore::RealtimeAnalyser::magnitudeBuffer):
+
 2010-11-02  Ilya Sherman  <isherman at chromium.org>
 
         Reviewed by Kent Tamura.
diff --git a/WebCore/webaudio/RealtimeAnalyser.cpp b/WebCore/webaudio/RealtimeAnalyser.cpp
new file mode 100644
index 0000000..282f299
--- /dev/null
+++ b/WebCore/webaudio/RealtimeAnalyser.cpp
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 "RealtimeAnalyser.h"
+
+#include "AudioBus.h"
+#include "AudioUtilities.h"
+#include "FFTFrame.h"
+
+#if ENABLE(3D_CANVAS)
+#include "Float32Array.h"
+#include "Uint8Array.h"
+#endif
+
+#include <algorithm>
+#include <limits.h>
+#include <wtf/Complex.h>
+#include <wtf/Threading.h>
+
+using namespace std;
+
+namespace WebCore {
+
+const double RealtimeAnalyser::DefaultSmoothingTimeConstant  = 0.8;
+const double RealtimeAnalyser::DefaultMinDecibels = -100.0;
+const double RealtimeAnalyser::DefaultMaxDecibels = -30.0;
+
+const unsigned RealtimeAnalyser::DefaultFFTSize = 2048;
+const unsigned RealtimeAnalyser::MaxFFTSize = 2048;
+const unsigned RealtimeAnalyser::InputBufferSize = RealtimeAnalyser::MaxFFTSize * 2;
+
+RealtimeAnalyser::RealtimeAnalyser()
+    : m_inputBuffer(InputBufferSize)
+    , m_writeIndex(0)
+    , m_fftSize(DefaultFFTSize)
+    , m_magnitudeBuffer(DefaultFFTSize / 2)
+    , m_smoothingTimeConstant(DefaultSmoothingTimeConstant)
+    , m_minDecibels(DefaultMinDecibels)
+    , m_maxDecibels(DefaultMaxDecibels)
+{
+    m_analysisFrame = adoptPtr(new FFTFrame(DefaultFFTSize));
+}
+
+RealtimeAnalyser::~RealtimeAnalyser()
+{
+}
+
+void RealtimeAnalyser::reset()
+{
+    m_writeIndex = 0;
+    m_inputBuffer.zero();
+    m_magnitudeBuffer.zero();
+}
+
+void RealtimeAnalyser::setFftSize(size_t size)
+{
+    ASSERT(isMainThread());
+
+    // Only allow powers of two.
+    unsigned log2size = static_cast<unsigned>(log2(size));
+    bool isPOT(1UL << log2size == size);
+    
+    if (!isPOT || size > MaxFFTSize) {
+        // FIXME: It would be good to also set an exception.
+        return;
+    }
+
+    if (m_fftSize != size) {
+        m_analysisFrame = adoptPtr(new FFTFrame(m_fftSize));
+        m_magnitudeBuffer.resize(size);
+        m_fftSize = size;
+    }
+}
+
+void RealtimeAnalyser::writeInput(AudioBus* bus, size_t framesToProcess)
+{
+    bool isBusGood = bus && bus->numberOfChannels() > 0 && bus->channel(0)->length() >= framesToProcess;
+    ASSERT(isBusGood);
+    if (!isBusGood)
+        return;
+        
+    // FIXME : allow to work with non-FFTSize divisible chunking
+    bool isDestinationGood = m_writeIndex < m_inputBuffer.size() && m_writeIndex + framesToProcess <= m_inputBuffer.size();
+    ASSERT(isDestinationGood);
+    if (!isDestinationGood)
+        return;    
+    
+    // Perform real-time analysis
+    // FIXME : for now just use left channel (must mix if stereo source)
+    float* source = bus->channel(0)->data();
+
+    // The source has already been sanity checked with isBusGood above.
+    
+    memcpy(m_inputBuffer.data() + m_writeIndex, source, sizeof(float) * framesToProcess);
+
+    m_writeIndex += framesToProcess;
+    if (m_writeIndex >= InputBufferSize)
+        m_writeIndex = 0;
+}
+
+namespace {
+
+void applyWindow(float* p, size_t n)
+{
+    ASSERT(isMainThread());
+    
+    // Blackman window
+    double alpha = 0.16;
+    double a0 = 0.5 * (1.0 - alpha);
+    double a1 = 0.5;
+    double a2 = 0.5 * alpha;
+    
+    for (unsigned i = 0; i < n; ++i) {
+        double x = static_cast<double>(i) / static_cast<double>(n);
+        double window = a0 - a1 * cos(2.0 * M_PI * x) + a2 * cos(4.0 * M_PI * x);
+        p[i] *= float(window);
+    }
+}
+
+} // namespace
+
+void RealtimeAnalyser::doFFTAnalysis()
+{    
+    ASSERT(isMainThread());
+
+    // Unroll the input buffer into a temporary buffer, where we'll apply an analysis window followed by an FFT.
+    size_t fftSize = this->fftSize();
+    
+    AudioFloatArray temporaryBuffer(fftSize);
+    float* inputBuffer = m_inputBuffer.data();
+    float* tempP = temporaryBuffer.data();
+
+    // Take the previous fftSize values from the input buffer and copy into the temporary buffer.
+    // FIXME : optimize with memcpy().
+    unsigned writeIndex = m_writeIndex;
+    for (unsigned i = 0; i < fftSize; ++i)
+        tempP[i] = inputBuffer[(i + writeIndex - fftSize + InputBufferSize) % InputBufferSize];
+    
+    // Window the input samples.
+    applyWindow(tempP, fftSize);
+    
+    // Do the analysis.
+    m_analysisFrame->doFFT(tempP);
+
+    size_t n = DefaultFFTSize / 2;
+
+    float* realP = m_analysisFrame->realData();
+    float* imagP = m_analysisFrame->imagData();
+
+    // Blow away the packed nyquist component.
+    imagP[0] = 0.0f;
+    
+    // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FFT scaling factor).
+    const double MagnitudeScale = 1.0 / DefaultFFTSize;
+
+    // A value of 0 does no averaging with the previous result.  Larger values produce slower, but smoother changes.
+    double k = m_smoothingTimeConstant;
+    k = max(0.0, k);
+    k = min(1.0, k);    
+    
+    // Convert the analysis data from complex to magnitude and average with the previous result.
+    float* destination = magnitudeBuffer().data();
+    for (unsigned i = 0; i < n; ++i) {
+        Complex c(realP[i], imagP[i]);
+        double scalarMagnitude = abs(c) * MagnitudeScale;        
+        destination[i] = float(k * destination[i] + (1.0 - k) * scalarMagnitude);
+    }
+}
+
+#if ENABLE(3D_CANVAS)
+
+void RealtimeAnalyser::getFloatFrequencyData(Float32Array* destinationArray)
+{
+    ASSERT(isMainThread());
+
+    if (!destinationArray)
+        return;
+        
+    doFFTAnalysis();
+    
+    // Convert from linear magnitude to floating-point decibels.
+    const double MinDecibels = m_minDecibels;
+    unsigned sourceLength = magnitudeBuffer().size();
+    size_t len = min(sourceLength, destinationArray->length());
+    if (len > 0) {
+        const float* source = magnitudeBuffer().data();
+        float* destination = destinationArray->data();
+        
+        for (unsigned i = 0; i < len; ++i) {
+            float linearValue = source[i];
+            double dbMag = !linearValue ? MinDecibels : AudioUtilities::linearToDecibels(linearValue);
+            destination[i] = float(dbMag);
+        }
+    }
+}
+
+void RealtimeAnalyser::getByteFrequencyData(Uint8Array* destinationArray)
+{
+    ASSERT(isMainThread());
+
+    if (!destinationArray)
+        return;
+        
+    doFFTAnalysis();
+    
+    // Convert from linear magnitude to unsigned-byte decibels.
+    unsigned sourceLength = magnitudeBuffer().size();
+    size_t len = min(sourceLength, destinationArray->length());
+    if (len > 0) {
+        const double RangeScaleFactor = m_maxDecibels == m_minDecibels ? 1.0 : 1.0 / (m_maxDecibels - m_minDecibels);
+
+        const float* source = magnitudeBuffer().data();
+        unsigned char* destination = destinationArray->data();        
+        
+        for (unsigned i = 0; i < len; ++i) {
+            float linearValue = source[i];
+            double dbMag = !linearValue ? m_minDecibels : AudioUtilities::linearToDecibels(linearValue);
+            
+            // The range m_minDecibels to m_maxDecibels will be scaled to byte values from 0 to UCHAR_MAX.
+            double scaledValue = UCHAR_MAX * (dbMag - m_minDecibels) * RangeScaleFactor;
+
+            // Clip to valid range.
+            if (scaledValue < 0.0)
+                scaledValue = 0.0;
+            if (scaledValue > UCHAR_MAX)
+                scaledValue = UCHAR_MAX;
+            
+            destination[i] = static_cast<unsigned char>(scaledValue);
+        }
+    }
+}
+
+void RealtimeAnalyser::getByteTimeDomainData(Uint8Array* destinationArray)
+{
+    ASSERT(isMainThread());
+
+    if (!destinationArray)
+        return;
+        
+    unsigned fftSize = this->fftSize();
+    size_t len = min(fftSize, destinationArray->length());
+    if (len > 0) {
+        bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize;
+        ASSERT(isInputBufferGood);
+        if (!isInputBufferGood)
+            return;
+
+        float* inputBuffer = m_inputBuffer.data();        
+        unsigned char* destination = destinationArray->data();
+        
+        unsigned writeIndex = m_writeIndex;
+
+        for (unsigned i = 0; i < len; ++i) {
+            // Buffer access is protected due to modulo operation.
+            float value = inputBuffer[(i + writeIndex - fftSize + InputBufferSize) % InputBufferSize];
+
+            // Scale from nominal -1.0 -> +1.0 to unsigned byte.
+            double scaledValue = 128.0 * (value + 1.0);
+
+            // Clip to valid range.
+            if (scaledValue < 0.0)
+                scaledValue = 0.0;
+            if (scaledValue > UCHAR_MAX)
+                scaledValue = UCHAR_MAX;
+            
+            destination[i] = static_cast<unsigned char>(scaledValue);
+        }
+    }
+}
+
+#endif // 3D_CANVAS
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/webaudio/RealtimeAnalyser.h b/WebCore/webaudio/RealtimeAnalyser.h
new file mode 100644
index 0000000..686c17c
--- /dev/null
+++ b/WebCore/webaudio/RealtimeAnalyser.h
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#ifndef RealtimeAnalyser_h
+#define RealtimeAnalyser_h
+
+#include "AudioArray.h"
+#include <wtf/NonCopyable.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class AudioBus;
+class FFTFrame;
+
+#if ENABLE(3D_CANVAS)
+class Float32Array;
+class Uint8Array;
+#endif
+
+class RealtimeAnalyser : public Noncopyable {
+public:
+    RealtimeAnalyser();
+    virtual ~RealtimeAnalyser();
+    
+    void reset();
+
+    size_t fftSize() const { return m_fftSize; }
+    void setFftSize(size_t size);
+
+    unsigned frequencyBinCount() const { return m_fftSize / 2; }
+
+    void setMinDecibels(float k) { m_minDecibels = k; }
+    float minDecibels() const { return static_cast<float>(m_minDecibels); }
+
+    void setMaxDecibels(float k) { m_maxDecibels = k; }
+    float maxDecibels() const { return static_cast<float>(m_maxDecibels); }
+
+    void setSmoothingTimeConstant(float k) { m_smoothingTimeConstant = k; }
+    float smoothingTimeConstant() const { return static_cast<float>(m_smoothingTimeConstant); }
+
+#if ENABLE(3D_CANVAS)
+    void getFloatFrequencyData(Float32Array*);
+    void getByteFrequencyData(Uint8Array*);
+    void getByteTimeDomainData(Uint8Array*);
+#endif
+
+    // The audio thread writes input data here.
+    void writeInput(AudioBus*, size_t framesToProcess);
+
+    static const double DefaultSmoothingTimeConstant;
+    static const double DefaultMinDecibels;
+    static const double DefaultMaxDecibels;
+
+    static const unsigned DefaultFFTSize;
+    static const unsigned MaxFFTSize;
+    static const unsigned InputBufferSize;
+
+private:
+    // The audio thread writes the input audio here.
+    AudioFloatArray m_inputBuffer;
+    unsigned m_writeIndex;
+    
+    size_t m_fftSize;
+    OwnPtr<FFTFrame> m_analysisFrame;
+    void doFFTAnalysis();
+    
+    // doFFTAnalysis() stores the floating-point magnitude analysis data here.
+    AudioFloatArray m_magnitudeBuffer;
+    AudioFloatArray& magnitudeBuffer() { return m_magnitudeBuffer; }
+
+    // A value between 0 and 1 which averages the previous version of m_magnitudeBuffer with the current analysis magnitude data.
+    double m_smoothingTimeConstant;    
+
+    // The range used when converting when using getByteFrequencyData(). 
+    double m_minDecibels;
+    double m_maxDecibels;
+};
+
+} // namespace WebCore
+
+#endif // RealtimeAnalyser_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list