LowPass2FilterNode::LowPass2FilterNode(AudioContext* context, float sampleRate)
    : AudioBasicProcessorNode(context, sampleRate)
{
    m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::LowPass, sampleRate, 1, false));
    biquadProcessor()->parameter1()->setContext(context);
    biquadProcessor()->parameter2()->setContext(context);
    biquadProcessor()->parameter3()->setContext(context);
    setNodeType(NodeTypeLowPass2Filter);
}
Пример #2
0
BiquadFilterNode::BiquadFilterNode(AudioContext* context, double sampleRate)
    : AudioBasicProcessorNode(context, sampleRate)
{
    // Initially setup as lowpass filter.
    m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::LowPass, sampleRate, 1, false));
    biquadProcessor()->parameter1()->setContext(context);
    biquadProcessor()->parameter2()->setContext(context);
    biquadProcessor()->parameter3()->setContext(context);
    setType(NodeTypeBiquadFilter);
}
Пример #3
0
void BiquadDSPKernel::updateCoefficientsIfNecessary(bool useSmoothing, bool forceUpdate)
{
    if (forceUpdate || biquadProcessor()->filterCoefficientsDirty()) {
        double value1;
        double value2;
        double gain;
        
        if (useSmoothing) {
            value1 = biquadProcessor()->parameter1()->smoothedValue();
            value2 = biquadProcessor()->parameter2()->smoothedValue();
            gain = biquadProcessor()->parameter3()->smoothedValue();
        } else {
            value1 = biquadProcessor()->parameter1()->value();
            value2 = biquadProcessor()->parameter2()->value();
            gain = biquadProcessor()->parameter3()->value();
        }

        // Convert from Hertz to normalized frequency 0 -> 1.
        double nyquist = this->nyquist();
        double normalizedFrequency = value1 / nyquist;

        // Configure the biquad with the new filter parameters for the appropriate type of filter.
        switch (biquadProcessor()->type()) {
        case BiquadProcessor::LowPass:
            m_biquad.setLowpassParams(normalizedFrequency, value2);
            break;

        case BiquadProcessor::HighPass:
            m_biquad.setHighpassParams(normalizedFrequency, value2);
            break;

        case BiquadProcessor::BandPass:
            m_biquad.setBandpassParams(normalizedFrequency, value2);
            break;

        case BiquadProcessor::LowShelf:
            m_biquad.setLowShelfParams(normalizedFrequency, gain);
            break;

        case BiquadProcessor::HighShelf:
            m_biquad.setHighShelfParams(normalizedFrequency, gain);
            break;

        case BiquadProcessor::Peaking:
            m_biquad.setPeakingParams(normalizedFrequency, value2, gain);
            break;

        case BiquadProcessor::Notch:
            m_biquad.setNotchParams(normalizedFrequency, value2);
            break;

        case BiquadProcessor::Allpass:
            m_biquad.setAllpassParams(normalizedFrequency, value2);
            break;
        }
    }
}
bool BiquadFilterNode::setType(unsigned type)
{
    if (type > BiquadProcessor::Allpass)
        return false;
    
    biquadProcessor()->setType(static_cast<BiquadProcessor::FilterType>(type));
    return true;
}
Пример #5
0
void BiquadDSPKernel::getFrequencyResponse(int nFrequencies, const float* frequencyHz, float* magResponse, float* phaseResponse)
{
    bool isGood = nFrequencies > 0 && frequencyHz && magResponse && phaseResponse;
    ASSERT(isGood);
    if (!isGood)
        return;

    Vector<float> frequency(nFrequencies);

    double nyquist = this->nyquist();

    // Convert from frequency in Hz to normalized frequency (0 -> 1),
    // with 1 equal to the Nyquist frequency.
    for (int k = 0; k < nFrequencies; ++k)
        frequency[k] = narrowPrecisionToFloat(frequencyHz[k] / nyquist);

    double cutoffFrequency;
    double Q;
    double gain;
    double detune; // in Cents

    {
        // Get a copy of the current biquad filter coefficients so we can update the biquad with
        // these values. We need to synchronize with process() to prevent process() from updating
        // the filter coefficients while we're trying to access them. The process will update it
        // next time around.
        //
        // The BiquadDSPKernel object here (along with it's Biquad object) is for querying the
        // frequency response and is NOT the same as the one in process() which is used for
        // performing the actual filtering. This one is is created in
        // BiquadProcessor::getFrequencyResponse for this purpose. Both, however, point to the same
        // BiquadProcessor object.
        //
        // FIXME: Simplify this: crbug.com/390266
        MutexLocker processLocker(m_processLock);

        cutoffFrequency = biquadProcessor()->parameter1().value();
        Q = biquadProcessor()->parameter2().value();
        gain = biquadProcessor()->parameter3().value();
        detune = biquadProcessor()->parameter4().value();
    }

    updateCoefficients(cutoffFrequency, Q, gain, detune);

    m_biquad.getFrequencyResponse(nFrequencies, frequency.data(), magResponse, phaseResponse);
}
Пример #6
0
void BiquadFilterNode::setType(unsigned short type, ExceptionCode& ec)
{
    if (type > BiquadProcessor::Allpass) {
        ec = NOT_SUPPORTED_ERR;
        return;
    }
    
    biquadProcessor()->setType(static_cast<BiquadProcessor::FilterType>(type));
}
Пример #7
0
void BiquadFilterNode::getFrequencyResponse(const RefPtr<Float32Array>& frequencyHz, const RefPtr<Float32Array>& magResponse, const RefPtr<Float32Array>& phaseResponse)
{
    if (!frequencyHz || !magResponse || !phaseResponse)
        return;
    
    int n = std::min(frequencyHz->length(), std::min(magResponse->length(), phaseResponse->length()));

    if (n)
        biquadProcessor()->getFrequencyResponse(n, frequencyHz->data(), magResponse->data(), phaseResponse->data());
}
Пример #8
0
void BiquadDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source && destination && biquadProcessor());
    
    // Recompute filter coefficients if any of the parameters have changed.
    // FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object.
    // Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor.

    updateCoefficientsIfNecessary(true, false);

    m_biquad.process(source, destination, framesToProcess);
}
Пример #9
0
void BiquadDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source && destination && biquadProcessor());
    
    // Recompute filter coefficients if any of the parameters have changed.
    // FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object.
    // Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor.
    if (biquadProcessor()->filterCoefficientsDirty()) {
        double value1 = biquadProcessor()->parameter1()->smoothedValue();
        double value2 = biquadProcessor()->parameter2()->smoothedValue();
        
        // Convert from Hertz to normalized frequency 0 -> 1.
        double nyquist = this->nyquist();
        double normalizedValue1 = value1 / nyquist;

        // Configure the biquad with the new filter parameters for the appropriate type of filter.
        switch (biquadProcessor()->type()) {
        case BiquadProcessor::LowPass2:
            m_biquad.setLowpassParams(normalizedValue1, value2);
            break;

        case BiquadProcessor::HighPass2:
            m_biquad.setHighpassParams(normalizedValue1, value2);
            break;

        case BiquadProcessor::LowShelf:
            m_biquad.setLowShelfParams(normalizedValue1, value2);
            break;

        // FIXME: add other biquad filter types...
        case BiquadProcessor::Peaking:
        case BiquadProcessor::Allpass:
        case BiquadProcessor::HighShelf:
            break;
        }
    }

    m_biquad.process(source, destination, framesToProcess);
}
Пример #10
0
void BiquadDSPKernel::updateCoefficientsIfNecessary()
{
    if (biquadProcessor()->filterCoefficientsDirty()) {
        double cutoffFrequency;
        double Q;
        double gain;
        double detune; // in Cents

        if (biquadProcessor()->hasSampleAccurateValues()) {
            cutoffFrequency = biquadProcessor()->parameter1().finalValue();
            Q = biquadProcessor()->parameter2().finalValue();
            gain = biquadProcessor()->parameter3().finalValue();
            detune = biquadProcessor()->parameter4().finalValue();
        } else {
            cutoffFrequency = biquadProcessor()->parameter1().smoothedValue();
            Q = biquadProcessor()->parameter2().smoothedValue();
            gain = biquadProcessor()->parameter3().smoothedValue();
            detune = biquadProcessor()->parameter4().smoothedValue();
        }

        updateCoefficients(cutoffFrequency, Q, gain, detune);
    }
}
Пример #11
0
void BiquadDSPKernel::updateCoefficients(double cutoffFrequency, double Q, double gain, double detune)
{
    // Convert from Hertz to normalized frequency 0 -> 1.
    double nyquist = this->nyquist();
    double normalizedFrequency = cutoffFrequency / nyquist;

    // Offset frequency by detune.
    if (detune)
        normalizedFrequency *= pow(2, detune / 1200);

    // Configure the biquad with the new filter parameters for the appropriate type of filter.
    switch (biquadProcessor()->type()) {
    case BiquadProcessor::LowPass:
        m_biquad.setLowpassParams(normalizedFrequency, Q);
        break;

    case BiquadProcessor::HighPass:
        m_biquad.setHighpassParams(normalizedFrequency, Q);
        break;

    case BiquadProcessor::BandPass:
        m_biquad.setBandpassParams(normalizedFrequency, Q);
        break;

    case BiquadProcessor::LowShelf:
        m_biquad.setLowShelfParams(normalizedFrequency, gain);
        break;

    case BiquadProcessor::HighShelf:
        m_biquad.setHighShelfParams(normalizedFrequency, gain);
        break;

    case BiquadProcessor::Peaking:
        m_biquad.setPeakingParams(normalizedFrequency, Q, gain);
        break;

    case BiquadProcessor::Notch:
        m_biquad.setNotchParams(normalizedFrequency, Q);
        break;

    case BiquadProcessor::Allpass:
        m_biquad.setAllpassParams(normalizedFrequency, Q);
        break;
    }
}
Пример #12
0
void BiquadDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source);
    ASSERT(destination);
    ASSERT(biquadProcessor());

    // Recompute filter coefficients if any of the parameters have changed.
    // FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object.
    // Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor.


    // The audio thread can't block on this lock; skip updating the coefficients for this block if
    // necessary. We'll get them the next time around.
    {
        MutexTryLocker tryLocker(m_processLock);
        if (tryLocker.locked())
            updateCoefficientsIfNecessary();
    }

    m_biquad.process(source, destination, framesToProcess);
}
Пример #13
0
void BiquadFilterNode::setType(BiquadFilterType type)
{
    biquadProcessor()->setType(type);
}