Bug 1154043 - (part 1) Store PeriodicWave components for later use r=dminor
authorDan Minor <dminor@mozilla.com>
Thu, 12 Nov 2015 10:40:45 -0500
changeset 326863 107fb1f539dad7ea2ee66f7c29e43817879344b2
parent 326862 fcd9df15e93764277b014019a473d5d1bccd810e
child 326864 82d122e1b8c3dc52799fb830452c18b9cd267b3d
push id10169
push userdminor@mozilla.com
push dateThu, 28 Jan 2016 13:10:48 +0000
reviewersdminor
bugs1154043
milestone45.0a1
Bug 1154043 - (part 1) Store PeriodicWave components for later use r=dminor We need to store the components used to create the PeriodicWave for later use if we want to be able to build the band limited tables lazily.
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
@@ -46,17 +46,30 @@ PeriodicWave::create(float sampleRate,
                      const float* imag,
                      size_t numberOfComponents)
 {
     bool isGood = real && imag && numberOfComponents > 0;
     MOZ_ASSERT(isGood);
     if (isGood) {
         RefPtr<PeriodicWave> periodicWave =
             new PeriodicWave(sampleRate, numberOfComponents);
-        periodicWave->createBandLimitedTables(real, imag, numberOfComponents);
+
+        // Limit the number of components used to those for frequencies below the
+        // Nyquist of the fixed length inverse FFT.
+        size_t halfSize = periodicWave->m_periodicWaveSize / 2;
+        numberOfComponents = std::min(numberOfComponents, halfSize);
+        periodicWave->m_numberOfComponents = numberOfComponents;
+        periodicWave->m_realComponents = new AudioFloatArray(numberOfComponents);
+        periodicWave->m_imagComponents = new AudioFloatArray(numberOfComponents);
+        memcpy(periodicWave->m_realComponents->Elements(), real,
+               numberOfComponents * sizeof(float));
+        memcpy(periodicWave->m_imagComponents->Elements(), imag,
+               numberOfComponents * sizeof(float));
+
+        periodicWave->createBandLimitedTables();
         return periodicWave.forget();
     }
     return nullptr;
 }
 
 already_AddRefed<PeriodicWave>
 PeriodicWave::createSine(float sampleRate)
 {
@@ -174,40 +187,38 @@ 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(const float* realData, const float* imagData, unsigned numberOfComponents)
+void PeriodicWave::createBandLimitedTables()
 {
     float normalizationScale = 1;
 
     unsigned fftSize = m_periodicWaveSize;
-    unsigned halfSize = fftSize / 2;
     unsigned i;
 
-    // Limit the number of components used to those for frequencies below the
-    // Nyquist of the fixed length inverse FFT.
-    numberOfComponents = std::min(numberOfComponents, halfSize);
+    const float *realData = m_realComponents->Elements();
+    const float *imagData = m_imagComponents->Elements();
 
     m_bandLimitedTables.SetCapacity(m_numberOfRanges);
 
     for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
         // 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, numberOfComponents - 1);
+        numberOfPartials = std::min(numberOfPartials, m_numberOfComponents - 1);
 
         // 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];
@@ -242,20 +253,21 @@ void PeriodicWave::createBandLimitedTabl
 }
 
 void PeriodicWave::generateBasicWaveform(OscillatorType shape)
 {
     const float piFloat = float(M_PI);
     unsigned fftSize = periodicWaveSize();
     unsigned halfSize = fftSize / 2;
 
-    AudioFloatArray real(halfSize);
-    AudioFloatArray imag(halfSize);
-    float* realP = real.Elements();
-    float* imagP = imag.Elements();
+    m_numberOfComponents = halfSize;
+    m_realComponents = new AudioFloatArray(halfSize);
+    m_imagComponents = new AudioFloatArray(halfSize);
+    float* realP = m_realComponents->Elements();
+    float* imagP = m_imagComponents->Elements();
 
     // Clear DC and imag value which is ignored.
     realP[0] = 0;
     imagP[0] = 0;
 
     for (unsigned n = 1; n < halfSize; ++n) {
         float omega = 2 * piFloat * n;
         float invOmega = 1 / omega;
@@ -301,12 +313,12 @@ void PeriodicWave::generateBasicWaveform
             b = 0;
             break;
         }
 
         realP[n] = a;
         imagP[n] = b;
     }
 
-    createBandLimitedTables(realP, imagP, halfSize);
+    createBandLimitedTables();
 }
 
 } // namespace WebCore
--- a/dom/media/webaudio/blink/PeriodicWave.h
+++ b/dom/media/webaudio/blink/PeriodicWave.h
@@ -80,16 +80,19 @@ private:
     ~PeriodicWave() {}
 
     void generateBasicWaveform(mozilla::dom::OscillatorType);
 
     float m_sampleRate;
     unsigned m_periodicWaveSize;
     unsigned m_numberOfRanges;
     float m_centsPerRange;
+    unsigned m_numberOfComponents;
+    nsAutoPtr<AudioFloatArray> m_realComponents;
+    nsAutoPtr<AudioFloatArray> m_imagComponents;
 
     // The lowest frequency (in Hertz) where playback will include all of the
     // partials.  Playing back lower than this frequency will gradually lose
     // more high-frequency information.
     // This frequency is quite low (~10Hz @ // 44.1KHz)
     float m_lowestFundamentalFrequency;
 
     float m_rateScale;
@@ -97,15 +100,15 @@ 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(const float* real, const float* imag, unsigned numberOfComponents);
+    void createBandLimitedTables();
     nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables;
 };
 
 } // namespace WebCore
 
 #endif // PeriodicWave_h