Skip to content
Snippets Groups Projects
Commit 5c9b0873 authored by Dan Minor's avatar Dan Minor
Browse files

Bug 1222405 - (part 2) Build band limited tables after fundamental frequency is known r=padenot

If we build the band limited tables after the fundamental frequency is known,
we can exclude partials that are above the nyquist frequency for the sampling
frequency being used.

We rebuild the band limited tables each time we see a request for data for a
lower fundamental frequency so we have the required partials.

--HG--
extra : rebase_source : 067075c7c8a90580650bf850c50ca7d8fc1eb6ff
parent eec8d40a
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,7 @@
#include "PeriodicWave.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include "mozilla/FFTBlock.h"
const unsigned MinPeriodicWaveSize = 4096; // This must be a power of two.
......@@ -64,7 +65,6 @@ PeriodicWave::create(float sampleRate,
memcpy(periodicWave->m_imagComponents->Elements(), imag,
numberOfComponents * sizeof(float));
periodicWave->createBandLimitedTables();
return periodicWave.forget();
}
return nullptr;
......@@ -109,6 +109,7 @@ PeriodicWave::createTriangle(float sampleRate)
PeriodicWave::PeriodicWave(float sampleRate, size_t numberOfComponents)
: m_sampleRate(sampleRate)
, m_centsPerRange(CentsPerRange)
, m_lowestRequestedFundamentalFrequency(std::numeric_limits<float>::max())
{
float nyquist = 0.5 * m_sampleRate;
......@@ -120,6 +121,7 @@ PeriodicWave::PeriodicWave(float sampleRate, size_t numberOfComponents)
}
m_numberOfRanges = (unsigned)(3.0f*logf(m_periodicWaveSize)/logf(2.0f));
m_bandLimitedTables.SetCapacity(m_numberOfRanges);
m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials();
m_rateScale = m_periodicWaveSize / m_sampleRate;
}
......@@ -140,10 +142,16 @@ size_t PeriodicWave::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) co
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);
m_lowestRequestedFundamentalFrequency = fundamentalFrequency;
}
// Calculate the pitch range.
float ratio = fundamentalFrequency > 0 ? fundamentalFrequency / m_lowestFundamentalFrequency : 0.5;
float centsAboveLowestFrequency = logf(ratio)/logf(2.0f) * 1200;
......@@ -192,7 +200,7 @@ unsigned PeriodicWave::numberOfPartialsForRange(unsigned rangeIndex) const
// 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()
void PeriodicWave::createBandLimitedTables(float fundamentalFrequency)
{
float normalizationScale = 1;
......@@ -202,7 +210,7 @@ void PeriodicWave::createBandLimitedTables()
const float *realData = m_realComponents->Elements();
const float *imagData = m_imagComponents->Elements();
m_bandLimitedTables.SetCapacity(m_numberOfRanges);
m_bandLimitedTables.Clear();
for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
// This FFTBlock is used to cull partials (represented by frequency bins).
......@@ -215,6 +223,11 @@ void PeriodicWave::createBandLimitedTables()
// 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));
// 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
......@@ -317,8 +330,6 @@ void PeriodicWave::generateBasicWaveform(OscillatorType shape)
realP[n] = a;
imagP[n] = b;
}
createBandLimitedTables();
}
} // namespace WebCore
......@@ -105,7 +105,8 @@ private:
unsigned numberOfPartialsForRange(unsigned rangeIndex) const;
// Creates tables based on numberOfComponents Fourier coefficients.
void createBandLimitedTables();
void createBandLimitedTables(float fundamentalFrequency);
float m_lowestRequestedFundamentalFrequency;
nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables;
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment