void WaveShaperDSPKernel::process(ContextRenderLock&, const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source && destination && waveShaperProcessor());

    std::shared_ptr<std::vector<float>> curve = waveShaperProcessor()->curve();
    if (!curve) {
        // Act as "straight wire" pass-through if no curve is set.
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    float* curveData = &(*curve)[0];
    int curveLength = (*curve).size();

    ASSERT(curveData);

    if (!curveData || !curveLength) {
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    // Apply waveshaping curve.
    for (unsigned i = 0; i < framesToProcess; ++i) {
        const float input = source[i];

        // Calculate an index based on input -1 -> +1 with 0 being at the center of the curve data.
        int index = (curveLength * (input + 1)) / 2;

        // Clip index to the input range of the curve.
        // This takes care of input outside of nominal range -1 -> +1
        index = max(index, 0);
        index = min(index, curveLength - 1);
        destination[i] = curveData[index];
    }
}
void WaveShaperDSPKernel::processCurve(const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source);
    ASSERT(destination);
    ASSERT(waveShaperProcessor());

    DOMFloat32Array* curve = waveShaperProcessor()->curve();
    if (!curve) {
        // Act as "straight wire" pass-through if no curve is set.
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    float* curveData = curve->data();
    int curveLength = curve->length();

    ASSERT(curveData);

    if (!curveData || !curveLength) {
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    // Apply waveshaping curve.
    for (unsigned i = 0; i < framesToProcess; ++i) {
        const float input = source[i];

        // Calculate a virtual index based on input -1 -> +1 with -1 being curve[0], +1 being
        // curve[curveLength - 1], and 0 being at the center of the curve data. Then linearly
        // interpolate between the two points in the curve.
        double virtualIndex = 0.5 * (input + 1) * (curveLength - 1);
        double output;

        if (virtualIndex < 0) {
            // input < -1, so use curve[0]
            output = curveData[0];
        } else if (virtualIndex >= curveLength - 1) {
            // input >= 1, so use last curve value
            output = curveData[curveLength - 1];
        } else {
            // The general case where -1 <= input < 1, where 0 <= virtualIndex < curveLength - 1,
            // so interpolate between the nearest samples on the curve.
            unsigned index1 = static_cast<unsigned>(virtualIndex);
            unsigned index2 = index1 + 1;
            double interpolationFactor = virtualIndex - index1;

            double value1 = curveData[index1];
            double value2 = curveData[index2];

            output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2;
        }
        destination[i] = output;
    }
}
Beispiel #3
0
void WaveShaperNode::setOversample(OverSampleType type)
{
    ASSERT(isMainThread());

    // Synchronize with any graph changes or changes to channel configuration.
    AudioContext::AutoLocker contextLocker(context());
    waveShaperProcessor()->setOversample(processorType(type));
}
void WaveShaperDSPKernel::processCurve(const float* source, float* destination, size_t framesToProcess)
{
    ASSERT(source && destination && waveShaperProcessor());

    Float32Array* curve = waveShaperProcessor()->curve();
    if (!curve) {
        // Act as "straight wire" pass-through if no curve is set.
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    float* curveData = curve->data();
    int curveLength = curve->length();

    ASSERT(curveData);

    if (!curveData || !curveLength) {
        memcpy(destination, source, sizeof(float) * framesToProcess);
        return;
    }

    // Apply waveshaping curve.
    for (unsigned i = 0; i < framesToProcess; ++i) {
        const float input = source[i];

        // Calculate a virtual index based on input -1 -> +1 with 0 being at the center of the curve data.
        // Then linearly interpolate between the two points in the curve.
        double virtualIndex = 0.5 * (input + 1) * curveLength;
        int index1 = static_cast<int>(virtualIndex);
        int index2 = index1 + 1;
        double interpolationFactor = virtualIndex - index1;

        // Clip index to the input range of the curve.
        // This takes care of input outside of nominal range -1 -> +1
        index1 = max(index1, 0);
        index1 = min(index1, curveLength - 1);
        index2 = max(index2, 0);
        index2 = min(index2, curveLength - 1);

        double value1 = curveData[index1];
        double value2 = curveData[index2];

        double output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2;
        destination[i] = output;
    }
}
Beispiel #5
0
void WaveShaperNode::setOversample(const String& type, ExceptionCode& ec)
{
    ASSERT(isMainThread());

    // This is to synchronize with the changes made in
    // AudioBasicProcessorNode::checkNumberOfChannelsForInput() where we can
    // initialize() and uninitialize().
    AudioContext::AutoLocker contextLocker(context());

    if (type == "none")
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSampleNone);
    else if (type == "2x")
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample2x);
    else if (type == "4x")
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample4x);
    else
        ec = INVALID_STATE_ERR;
}
void WaveShaperNode::setOversample(const String& type)
{
    ASSERT(isMainThread());

    // This is to synchronize with the changes made in
    // AudioBasicProcessorNode::checkNumberOfChannelsForInput() where we can
    // initialize() and uninitialize().
    AbstractAudioContext::AutoLocker contextLocker(context());

    if (type == "none") {
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSampleNone);
    } else if (type == "2x") {
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample2x);
    } else if (type == "4x") {
        waveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample4x);
    } else {
        ASSERT_NOT_REACHED();
    }
}
void WaveShaperNode::setCurve(DOMFloat32Array* curve, ExceptionState& exceptionState)
{
    ASSERT(isMainThread());

    if (curve && curve->length() < 2) {
        exceptionState.throwDOMException(
            InvalidAccessError,
            ExceptionMessages::indexExceedsMinimumBound<unsigned>(
                "curve length",
                curve->length(),
                2));
        return;
    }

    waveShaperProcessor()->setCurve(curve);
}
void WaveShaperDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
{
    switch (waveShaperProcessor()->oversample()) {
    case WaveShaperProcessor::OverSampleNone:
        processCurve(source, destination, framesToProcess);
        break;
    case WaveShaperProcessor::OverSample2x:
        processCurve2x(source, destination, framesToProcess);
        break;
    case WaveShaperProcessor::OverSample4x:
        processCurve4x(source, destination, framesToProcess);
        break;

    default:
        ASSERT_NOT_REACHED();
    }
}
Beispiel #9
0
Float32Array* WaveShaperNode::curve()
{
    return waveShaperProcessor()->curve();
}
Beispiel #10
0
void WaveShaperNode::setCurve(Float32Array* curve)
{
    ASSERT(isMainThread());
    waveShaperProcessor()->setCurve(curve);
}
Beispiel #11
0
std::shared_ptr<std::vector<float>> WaveShaperNode::curve()
{
    return waveShaperProcessor()->curve();
}
Beispiel #12
0
void WaveShaperNode::setCurve(ContextRenderLock& r, std::shared_ptr<std::vector<float>> curve)
{
    waveShaperProcessor()->setCurve(r, curve);
}