Ejemplo n.º 1
0
Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize, float sampleRate)
{
    float scale = 1;

    if (normalize) {
        scale = calculateNormalizationScale(impulseResponse, impulseResponseBufferLength, sampleRate);

        if (scale) {
            for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) {
                AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)),
                                        1, scale, impulseResponseBufferLength);
            }
        }
    }

    initialize(impulseResponse, impulseResponseBufferLength, renderSliceSize, maxFFTSize, numberOfChannels, useBackgroundThreads);

    // Undo scaling since this shouldn't be a destructive operation on impulseResponse.
    // FIXME: What about roundoff? Perhaps consider making a temporary scaled copy
    // instead of scaling and unscaling in place.
    if (normalize && scale) {
        for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) {
            AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)),
                                    1, 1 / scale, impulseResponseBufferLength);
        }
    }
}
Ejemplo n.º 2
0
void
AudioBufferInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
                        uint32_t aChannelCount,
                        float aScale)
{
    AudioBufferInPlaceScale(aBlock, aChannelCount, aScale, WEBAUDIO_BLOCK_SIZE);
}
Ejemplo n.º 3
0
void
AudioBlockInPlaceScale(float aBlock[WEBAUDIO_BLOCK_SIZE],
                       float aScale)
{
  AudioBufferInPlaceScale(aBlock, aScale, WEBAUDIO_BLOCK_SIZE);
}
Ejemplo n.º 4
0
// 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)
{
    float normalizationScale = 1;

    unsigned fftSize = m_periodicWaveSize;
    unsigned halfSize = fftSize / 2 + 1;
    unsigned i;

    numberOfComponents = std::min(numberOfComponents, halfSize);

    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);
        nsAutoArrayPtr<float> realP(new float[halfSize]);
        nsAutoArrayPtr<float> imagP(new float[halfSize]);

        // Copy from loaded frequency data and scale.
        float scale = fftSize;
        AudioBufferCopyWithScale(realData, scale, realP, numberOfComponents);
        AudioBufferCopyWithScale(imagData, scale, imagP, numberOfComponents);

        // If fewer components were provided than 1/2 FFT size,
        // then clear the remaining bins.
        for (i = numberOfComponents; i < halfSize; ++i) {
            realP[i] = 0;
            imagP[i] = 0;
        }

        // Generate complex conjugate because of the way the
        // inverse FFT is defined.
        float minusOne = -1;
        AudioBufferInPlaceScale(imagP, minusOne, halfSize);

        // Find the starting bin where we should start culling.
        // We need to clear out the highest frequencies to band-limit
        // the waveform.
        unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);

        // Cull the aliasing partials for this pitch range.
        for (i = numberOfPartials + 1; i < halfSize; ++i) {
            realP[i] = 0;
            imagP[i] = 0;
        }
        // Clear nyquist if necessary.
        if (numberOfPartials < halfSize)
            realP[halfSize-1] = 0;

        // Clear any DC-offset.
        realP[0] = 0;

        // Clear values which have no effect.
        imagP[0] = 0;
        imagP[halfSize-1] = 0;

        // Create the band-limited table.
        AudioFloatArray* table = new AudioFloatArray(m_periodicWaveSize);
        m_bandLimitedTables.AppendElement(table);

        // Apply an inverse FFT to generate the time-domain table data.
        float* data = m_bandLimitedTables[rangeIndex]->Elements();
        frame.PerformInverseFFT(realP, imagP, 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);

            if (maxValue)
                normalizationScale = 1.0f / maxValue;
        }

        // Apply normalization scale.
        AudioBufferInPlaceScale(data, normalizationScale, m_periodicWaveSize);
    }
}