void MLProcDCBlocker::calcCoeffs(void) { const float f = getParam("f"); const double omega = f * kMLTwoPi / getContextSampleRate(); mR = cos(omega); mParamsChanged = false; }
void MLProcDelayOutput::process(const int frames) { const MLSignal& delayTime = getInput(1); MLSignal& y = getOutput(); int delayInt; const float sr = getContextSampleRate(); MLSample delay; int delayedIndex; if (mParamsChanged) doParams(); if(mpDelayInputProc) { MLSignal& buffer = mpDelayInputProc->getBuffer(); if (delayTime.isConstant()) { delay = delayTime[0] * sr - mVectorDelay; if (delay < mVectorDelay) delay = mVectorDelay; delayInt = (int)(delay); for (int n=0; n<frames; ++n) { delayedIndex = mReadIndex - delayInt; delayedIndex &= mLengthMask; y[n] = buffer[delayedIndex]; mReadIndex++; } } else { for (int n=0; n<frames; ++n) { // read // zero order (integer delay) // get delay time. // if no signal is attached, 0. should result // and we get a single-vector delay. delay = delayTime[n] * sr - mVectorDelay; if (delay < mVectorDelay) delay = mVectorDelay; delayInt = (int)(delay); delayedIndex = mReadIndex - delayInt; delayedIndex &= mLengthMask; y[n] = buffer[delayedIndex]; mReadIndex++; } } } // linear interp: //y[n] = frac*x[m+1] + (1-frac)*x[m] // allpass interp: // y[n] = x[m+1] + (1-frac)*x[m] - (1-frac)*y[n-1] }
MLProc::err MLProcParamToSignal::resize() { int vecSize = getContextVectorSize(); MLSampleRate rate = getContextSampleRate(); mChangeList.setDims(vecSize); mChangeList.setSampleRate(rate); mChangeList.setGlideTime(mGlide); // TODO return OK; }
// MLProc::prepareToProcess() is called after all connections in DSP graph are made. // This is where sample rates and block sizes propagate through the graph, and // are checked for consistency. // Setup internal buffers and data to prepare for processing any attached input signals. // MLProcs have no concept of enabled -- it's up to the enclosing container to disable // itself if things go wrong here. // MLProc::err MLProc::prepareToProcess() { MLProc::err e = OK; // debug() << "preparing " << getClassName() << " \"" << getName() << "\" : " ; int ins = getNumInputs(); int outs = getNumOutputs(); float rate = getContextSampleRate(); int blockSize = getContextVectorSize(); // debug() << ins << " ins, " << outs << " outs, rate " << rate << ", blockSize " << blockSize << "\n"; // All inputs must have a signal connected. // So connect unconnected inputs to null input signal. for (int i=0; i<ins; i++) { if (!mInputs[i]) { mInputs[i] = &getContext()->getNullInput(); } } // set size and rate of output signals // TODO it looks like this allocation may be redundant because outputs are allocated in compile() already!? for (int i=1; i<=outs; ++i) { MLSignal& out = getOutput(i); if (&out) { out.setRate(rate); MLSample* outData = out.setDims(blockSize, getOutputFrameSize(i)); if (!outData) { e = memErr; goto bail; } } else { debug() << "MLProc::prepareToProcess: null output " << i << " for " << getName() << "! \n"; } //debug() << " out " << i << ": " << (void *)(MLSignal*)(&out) << ", " << out.getSize() << " samples.\n"; } e = resize(); // recalc params for new sample rate mParamsChanged = true; bail: return e; }
MLProc::err MLProcDelayInput::resize() { MLProc::err e = OK; const float sr = getContextSampleRate(); int lenBits = bitsToContain((int)(getParam("length") * sr)); int length = 1 << lenBits; mLengthMask = length - 1; MLSample* pBuf = mBuffer.setDims(length); if (!pBuf) { e = memErr; } return e; }
void MLProcDebug::process(const int frames) { const int intervalSeconds = 2; const int intervalFrames = getContextSampleRate() * intervalSeconds; if (mParamsChanged) doParams(); mTemp += frames; if (mTemp > intervalFrames) { const MLSignal& in = getInput(1); debug() << std::setw(6); debug() << std::setprecision(2); debug() << "sig " << getName() << " (" << static_cast<const void *>(&in) << "), n=" << frames << " = " << std::setprecision(4) << in[0] ; if(in.isConstant()) { debug() << "(const)"; } else { debug() << " min:" << in.getMin() << ", max:" << in.getMax(); } debug() << "\n"; mTemp -= intervalFrames; if (mVerbose) { debug() << frames << " frames\n"; debug() << "["; debug() << std::setw(6); debug() << std::setprecision(2); for(int j=0; j<frames; ++j) { debug() << in[j] << " " ; if ((j%8 == 7) && (j < frames-1)) debug() << "\n"; } debug() << "]\n\n"; } } }
void MLProcBiquad::calcCoeffs(const int frames) { static MLSymbol modeSym("mode"); int mode = (int)getParam(modeSym); const MLSignal& frequency = getInput(2); const MLSignal& q = getInput(3); int coeffFrames; float twoPiOverSr = kMLTwoPi*getContextInvSampleRate(); bool paramSignalsAreConstant = frequency.isConstant() && q.isConstant(); if (paramSignalsAreConstant) { coeffFrames = 1; } else { coeffFrames = frames; } // set proper constant state for coefficient signals mA0.setConstant(paramSignalsAreConstant); mA1.setConstant(paramSignalsAreConstant); mA2.setConstant(paramSignalsAreConstant); mB1.setConstant(paramSignalsAreConstant); mB2.setConstant(paramSignalsAreConstant); float a0, a1, a2, b0, b1, b2; float qm1, omega, alpha, sinOmega, cosOmega; float highLimit = getContextSampleRate() * 0.33f; // generate coefficient signals // TODO SSE for(int n=0; n<coeffFrames; ++n) { qm1 = 1.f/(q[n] + 0.05f); omega = clamp(frequency[n], kLowFrequencyLimit, highLimit) * twoPiOverSr; sinOmega = fsin1(omega); cosOmega = fcos1(omega); alpha = sinOmega * 0.5f * qm1; b0 = 1.f/(1.f + alpha); switch (mode) { default: case kLowpass: a0 = ((1.f - cosOmega) * 0.5f) * b0; a1 = (1.f - cosOmega); a2 = a0; b1 = (-2.f * cosOmega); b2 = (1.f - alpha); break; case kHighpass: a0 = ((1.f + cosOmega) * 0.5f); a1 = -(1.f + cosOmega); a2 = a0; b1 = (-2.f * cosOmega); b2 = (1.f - alpha); break; case kBandpass: a0 = alpha; a1 = 0.f; a2 = -alpha; b1 = -2.f * cosOmega; b2 = (1.f - alpha); break; case kNotch: a0 = 1; a1 = -2.f * cosOmega; a2 = 1; b1 = -2.f * cosOmega; b2 = (1.f - alpha); break; } mA0[n] = a0*b0; mA1[n] = a1*b0; mA2[n] = a2*b0; mB1[n] = b1*b0; mB2[n] = b2*b0; } }