Bug 1222405 - (part 3) Build band limited tables lazily r=padenot
authorDan Minor <dminor@mozilla.com>
Fri, 27 Nov 2015 15:01:28 -0500
changeset 309599 3785489fa210d38b890ab73f21202b94c5528c1f
parent 309598 7f2f19c2aca11a1087839848b6141e2cca1a10b8
child 309600 6139297dfb98c010a52c25b1bae658f84db2cd6e
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1222405
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1222405 - (part 3) Build band limited tables lazily r=padenot This builds the band limited tables for each range index individually as required.
dom/media/webaudio/blink/PeriodicWave.cpp
dom/media/webaudio/blink/PeriodicWave.h
--- a/dom/media/webaudio/blink/PeriodicWave.cpp
+++ b/dom/media/webaudio/blink/PeriodicWave.cpp
@@ -116,17 +116,17 @@ PeriodicWave::PeriodicWave(float sampleR
     if (numberOfComponents <= MinPeriodicWaveSize) {
         m_periodicWaveSize = MinPeriodicWaveSize;
     } else {
         unsigned npow2 = powf(2.0f, floorf(logf(numberOfComponents - 1.0)/logf(2.0f) + 1.0f));
         m_periodicWaveSize = std::min(MaxPeriodicWaveSize, npow2);
     }
 
     m_numberOfRanges = (unsigned)(3.0f*logf(m_periodicWaveSize)/logf(2.0f));
-    m_bandLimitedTables.SetCapacity(m_numberOfRanges);
+    m_bandLimitedTables.SetLength(m_numberOfRanges);
     m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials();
     m_rateScale = m_periodicWaveSize / m_sampleRate;
 }
 
 size_t PeriodicWave::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
     size_t amount = aMallocSizeOf(this);
 
@@ -143,17 +143,23 @@ size_t PeriodicWave::sizeOfIncludingThis
 void PeriodicWave::waveDataForFundamentalFrequency(float fundamentalFrequency, float* &lowerWaveData, float* &higherWaveData, float& tableInterpolationFactor)
 {
 
     // Negative frequencies are allowed, in which case we alias
     // to the positive frequency.
     fundamentalFrequency = fabsf(fundamentalFrequency);
 
     if (fundamentalFrequency < m_lowestRequestedFundamentalFrequency) {
-        createBandLimitedTables(fundamentalFrequency);
+        for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
+            m_bandLimitedTables[rangeIndex] = 0;
+        }
+
+        // We need to create the first table to determine the normalization
+        // constant.
+        createBandLimitedTables(fundamentalFrequency, 0);
         m_lowestRequestedFundamentalFrequency = fundamentalFrequency;
     }
 
     // Calculate the pitch range.
     float ratio = fundamentalFrequency > 0 ? fundamentalFrequency / m_lowestFundamentalFrequency : 0.5;
     float centsAboveLowestFrequency = logf(ratio)/logf(2.0f) * 1200;
 
     // Add one to round-up to the next range just in time to truncate
@@ -165,16 +171,22 @@ void PeriodicWave::waveDataForFundamenta
 
     // The words "lower" and "higher" refer to the table data having
     // the lower and higher numbers of partials. It's a little confusing
     // since the range index gets larger the more partials we cull out.
     // So the lower table data will have a larger range index.
     unsigned rangeIndex1 = static_cast<unsigned>(pitchRange);
     unsigned rangeIndex2 = rangeIndex1 < m_numberOfRanges - 1 ? rangeIndex1 + 1 : rangeIndex1;
 
+    if (!m_bandLimitedTables[rangeIndex1].get())
+        createBandLimitedTables(fundamentalFrequency, rangeIndex1);
+
+    if (!m_bandLimitedTables[rangeIndex2].get())
+        createBandLimitedTables(fundamentalFrequency, rangeIndex2);
+
     lowerWaveData = m_bandLimitedTables[rangeIndex2]->Elements();
     higherWaveData = m_bandLimitedTables[rangeIndex1]->Elements();
 
     // Ranges from 0 -> 1 to interpolate between lower -> higher.
     tableInterpolationFactor = rangeIndex2 - pitchRange;
 }
 
 unsigned PeriodicWave::maxNumberOfPartials() const
@@ -195,79 +207,74 @@ unsigned PeriodicWave::numberOfPartialsF
 
     return numberOfPartials;
 }
 
 // Convert into time-domain wave buffers.
 // One table is created for each range for non-aliasing playback
 // at different playback rates. Thus, higher ranges have more
 // high-frequency partials culled out.
-void PeriodicWave::createBandLimitedTables(float fundamentalFrequency)
+void PeriodicWave::createBandLimitedTables(float fundamentalFrequency,
+                                           unsigned rangeIndex)
 {
-    float normalizationScale = 1;
-
     unsigned fftSize = m_periodicWaveSize;
     unsigned i;
 
     const float *realData = m_realComponents->Elements();
     const float *imagData = m_imagComponents->Elements();
 
-    m_bandLimitedTables.Clear();
-
-    for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
-        // This FFTBlock is used to cull partials (represented by frequency bins).
-        FFTBlock frame(fftSize);
+    // This FFTBlock is used to cull partials (represented by frequency bins).
+    FFTBlock frame(fftSize);
 
-        // Find the starting bin where we should start culling the aliasing
-        // partials for this pitch range.  We need to clear out the highest
-        // frequencies to band-limit the waveform.
-        unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
-        // Also limit to the number of components that are provided.
-        numberOfPartials = std::min(numberOfPartials, m_numberOfComponents - 1);
+    // Find the starting bin where we should start culling the aliasing
+    // partials for this pitch range.  We need to clear out the highest
+    // frequencies to band-limit the waveform.
+    unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
+    // Also limit to the number of components that are provided.
+    numberOfPartials = std::min(numberOfPartials, m_numberOfComponents - 1);
 
-        // Limit number of partials to those below Nyquist frequency
-        float nyquist = 0.5 * m_sampleRate;
-        numberOfPartials = std::min(numberOfPartials,
-                                    (unsigned)(nyquist / fundamentalFrequency));
+    // Limit number of partials to those below Nyquist frequency
+    float nyquist = 0.5 * m_sampleRate;
+    numberOfPartials = std::min(numberOfPartials,
+                                (unsigned)(nyquist / fundamentalFrequency));
 
-        // Copy from loaded frequency data and generate complex conjugate
-        // because of the way the inverse FFT is defined.
-        // The coefficients of higher partials remain zero, as initialized in
-        // the FFTBlock constructor.
-        for (i = 0; i < numberOfPartials + 1; ++i) {
-            frame.RealData(i) = realData[i];
-            frame.ImagData(i) = -imagData[i];
-        }
+    // Copy from loaded frequency data and generate complex conjugate
+    // because of the way the inverse FFT is defined.
+    // The coefficients of higher partials remain zero, as initialized in
+    // the FFTBlock constructor.
+    for (i = 0; i < numberOfPartials + 1; ++i) {
+        frame.RealData(i) = realData[i];
+        frame.ImagData(i) = -imagData[i];
+    }
 
-        // Clear any DC-offset.
-        frame.RealData(0) = 0;
-        // Clear value which has no effect.
-        frame.ImagData(0) = 0;
+    // Clear any DC-offset.
+    frame.RealData(0) = 0;
+    // Clear value which has no effect.
+    frame.ImagData(0) = 0;
 
-        // Create the band-limited table.
-        AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize);
-        m_bandLimitedTables.AppendElement(table);
+    // Create the band-limited table.
+    AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize);
+    m_bandLimitedTables[rangeIndex] = table;
 
-        // Apply an inverse FFT to generate the time-domain table data.
-        float* data = m_bandLimitedTables[rangeIndex]->Elements();
-        frame.GetInverseWithoutScaling(data);
+    // Apply an inverse FFT to generate the time-domain table data.
+    float* data = m_bandLimitedTables[rangeIndex]->Elements();
+    frame.GetInverseWithoutScaling(data);
 
-        // For the first range (which has the highest power), calculate
-        // its peak value then compute normalization scale.
-        if (!rangeIndex) {
-            float maxValue;
-            maxValue = AudioBufferPeakValue(data, m_periodicWaveSize);
+    // For the first range (which has the highest power), calculate
+    // its peak value then compute normalization scale.
+    if (!rangeIndex) {
+        float maxValue;
+        maxValue = AudioBufferPeakValue(data, m_periodicWaveSize);
 
-            if (maxValue)
-                normalizationScale = 1.0f / maxValue;
-        }
+        if (maxValue)
+            m_normalizationScale = 1.0f / maxValue;
+    }
 
-        // Apply normalization scale.
-        AudioBufferInPlaceScale(data, normalizationScale, m_periodicWaveSize);
-    }
+    // Apply normalization scale.
+    AudioBufferInPlaceScale(data, m_normalizationScale, m_periodicWaveSize);
 }
 
 void PeriodicWave::generateBasicWaveform(OscillatorType shape)
 {
     const float piFloat = float(M_PI);
     unsigned fftSize = periodicWaveSize();
     unsigned halfSize = fftSize / 2;
 
--- a/dom/media/webaudio/blink/PeriodicWave.h
+++ b/dom/media/webaudio/blink/PeriodicWave.h
@@ -99,17 +99,18 @@ private:
 
     unsigned numberOfRanges() const { return m_numberOfRanges; }
 
     // Maximum possible number of partials (before culling).
     unsigned maxNumberOfPartials() const;
 
     unsigned numberOfPartialsForRange(unsigned rangeIndex) const;
 
-    // Creates tables based on numberOfComponents Fourier coefficients.
-    void createBandLimitedTables(float fundamentalFrequency);
+    // Creates table for specified index based on fundamental frequency.
+    void createBandLimitedTables(float fundamentalFrequency, unsigned rangeIndex);
     float m_lowestRequestedFundamentalFrequency;
+    float m_normalizationScale;
     nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables;
 };
 
 } // namespace WebCore
 
 #endif // PeriodicWave_h