From e7b24dd7da9de84e218f7d7be623f0cf8b9d1b9c Mon Sep 17 00:00:00 2001 From: "N.N." Date: Mon, 17 Feb 2003 14:12:16 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r415, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/dfx/; revision=416 --- buffer_override/bufferoverrideProcess.cpp | 253 ++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100755 buffer_override/bufferoverrideProcess.cpp (limited to 'buffer_override/bufferoverrideProcess.cpp') diff --git a/buffer_override/bufferoverrideProcess.cpp b/buffer_override/bufferoverrideProcess.cpp new file mode 100755 index 0000000..5877020 --- /dev/null +++ b/buffer_override/bufferoverrideProcess.cpp @@ -0,0 +1,253 @@ +/*------------------- by Marc Poirier ][ March 2001 -------------------*/ + +#ifndef __bufferoverride +#include "bufferoverride.hpp" +#endif + + + +//----------------------------------------------------------------------------- +void bufferoverride::updateBuffer(long samplePos) +{ + bool doSmoothing = true; // but in some situations, we shouldn't + float divisorLFOvalue, bufferLFOvalue; // the current output values of the LFOs + long prevForcedBufferSize; // the previous forced buffer size + + + readPos = 0; // reset for starting a new minibuffer + prevMinibufferSize = minibufferSize; + prevForcedBufferSize = currentForcedBufferSize; + + //--------------------------PROCESS THE LFOs---------------------------- + // update the LFOs' positions to the current position + divisorLFO->updatePosition(prevMinibufferSize); + bufferLFO->updatePosition(prevMinibufferSize); + // Then get the current output values of the LFOs, which also updates their positions once more. + // Scale the 0.0 - 1.0 LFO output values to 0.0 - 2.0 (oscillating around 1.0). + divisorLFOvalue = processLFOzero2two(divisorLFO); + bufferLFOvalue = 2.0f - processLFOzero2two(bufferLFO); // inverting it makes more pitch sense + // & then update the stepSize for each LFO, in case the LFO parameters have changed + if (onOffTest(divisorLFO->fTempoSync)) + divisorLFO->stepSize = currentTempoBPS * (tempoRateTable->getScalar(divisorLFO->fRate)) * numLFOpointsDivSR; + else + divisorLFO->stepSize = LFOrateScaled(divisorLFO->fRate) * numLFOpointsDivSR; + if (onOffTest(bufferLFO->fTempoSync)) + bufferLFO->stepSize = currentTempoBPS * (tempoRateTable->getScalar(bufferLFO->fRate)) * numLFOpointsDivSR; + else + bufferLFO->stepSize = LFOrateScaled(bufferLFO->fRate) * numLFOpointsDivSR; + + //---------------------------CALCULATE FORCED BUFFER SIZE---------------------------- + // check if it's the end of this forced buffer + if (writePos >= currentForcedBufferSize) + { + writePos = 0; // start up a new forced buffer + + // check on the previous forced & minibuffers; don't smooth if the last forced buffer wasn't divided + if (prevMinibufferSize >= currentForcedBufferSize) + doSmoothing = false; + else + doSmoothing = true; + + // now update the the size of the current force buffer + if ( onOffTest(fBufferTempoSync) && // the user wants to do tempo sync / beat division rate + (currentTempoBPS > 0.0f) ) // avoid division by zero + { + currentForcedBufferSize = (long) ( SAMPLERATE / (currentTempoBPS * tempoRateTable->getScalar(fBuffer)) ); + // set this true so that we make sure to do the measure syncronisation later on + } + else + currentForcedBufferSize = forcedBufferSizeSamples(fBuffer); + // apply the buffer LFO to the forced buffer size + currentForcedBufferSize = (long) ((float)currentForcedBufferSize * bufferLFOvalue); + // really low tempos & tempo rate values can cause huge forced buffer sizes, + // so prevent going outside of the allocated buffer space + if (currentForcedBufferSize > SUPER_MAX_BUFFER) + currentForcedBufferSize = SUPER_MAX_BUFFER; + if (currentForcedBufferSize < 2) + currentForcedBufferSize = 2; + + // untrue this so that we don't do the measure sync calculations again unnecessarily + needResync = false; + } + + //-----------------------CALCULATE THE DIVISOR------------------------- + currentBufferDivisor = bufferDivisorScaled(fDivisor); + // apply the divisor LFO to the divisor value if there's an "active" divisor (i.e. 2 or greater) + if (currentBufferDivisor >= 2.0f) + { + currentBufferDivisor *= divisorLFOvalue; + // now it's possible that the LFO could make the divisor less than 2, + // which will essentially turn the effect off, so we stop the modulation at 2 + if (currentBufferDivisor < 2.0f) + currentBufferDivisor = 2.0f; + } + + //-----------------------CALCULATE THE MINIBUFFER SIZE------------------------- + // this is not a new forced buffer starting up + if (writePos > 0) + { + // if it's allowed, update the minibuffer size midway through this forced buffer + if (onOffTest(fBufferInterrupt)) + minibufferSize = (long) ( (float)currentForcedBufferSize / currentBufferDivisor ); + // if it's the last minibuffer, then fill up the forced buffer to the end + // by extending this last minibuffer to fill up the end of the forced buffer + long remainingForcedBuffer = currentForcedBufferSize - writePos; + if ( (minibufferSize*2) >= remainingForcedBuffer ) + minibufferSize = remainingForcedBuffer; + } + // this is a new forced buffer just beginning, act accordingly, do bar sync if necessary + else { + // because there isn't really any division (given my implementation) when the divisor is < 2 + if (currentBufferDivisor < 2.0f) minibufferSize = currentForcedBufferSize; + else minibufferSize = (long) ( (float)currentForcedBufferSize / currentBufferDivisor ); + } + + //-----------------------CALCULATE SMOOTHING DURATION------------------------- + // no smoothing if the previous forced buffer wasn't divided + if (!doSmoothing) + smoothcount = smoothDur = 0; + else + { + smoothDur = (long) (fSmooth * (float)minibufferSize); + long maxSmoothDur; + // if we're just starting a new forced buffer, + // then the samples beyond the end of the previous one are not valid + if (writePos <= 0) + maxSmoothDur = prevForcedBufferSize - prevMinibufferSize; + // otherwise just make sure that we don't go outside of the allocated arrays + else + maxSmoothDur = SUPER_MAX_BUFFER - prevMinibufferSize; + if (smoothDur > maxSmoothDur) + smoothDur = maxSmoothDur; + smoothcount = smoothDur; + smoothStep = 1.0f / (float)(smoothDur+1); // the gain increment for each smoothing step + + fadeOutGain = cosf(PI/(float)(4*smoothDur)); + fadeInGain = sinf(PI/(float)(4*smoothDur)); + realFadePart = (fadeOutGain * fadeOutGain) - (fadeInGain * fadeInGain); // cosf(3.141592/2/n) + imaginaryFadePart = 2.0f * fadeOutGain * fadeInGain; // sinf(3.141592/2/n) + } +} + +void bufferoverride::m_signal(int n, float *const *in, float *const *out) { + // directly move everything to the vst part + doTheProcess((float **)in, (float **)out, (long)n, true); +} // end m_signal + + +void bufferoverride::m_help() { +} + +//--------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------- +void bufferoverride::doTheProcess(float **inputs, float **outputs, long sampleFrames, bool replacing) +{ + +//-------------------------SAFETY CHECK---------------------- + + // there must have not been available memory or something (like WaveLab goofing up), + // so try to allocate buffers now + if ((buffer1 == NULL)) createAudioBuffers(); + + // if the creation failed, then abort audio processing + if (buffer1 == NULL) return; + + +//-------------------------INITIALIZATIONS---------------------- + // this is a handy value to have during LFO calculations & wasteful to recalculate at every sample + numLFOpointsDivSR = NUM_LFO_POINTS_FLOAT / SAMPLERATE; + divisorLFO->pickTheLFOwaveform(); + bufferLFO->pickTheLFOwaveform(); + + // calculate this scaler value to minimize calculations later during processOutput() +// float inputGain = 1.0f - fDryWetMix; +// float outputGain = fDryWetMix; + float inputGain = sqrtf(1.0f - fDryWetMix); + float outputGain = sqrtf(fDryWetMix); + + +//-----------------------TEMPO STUFF--------------------------- + // figure out the current tempo if we're doing tempo sync + if ( onOffTest(fBufferTempoSync) || + (onOffTest(divisorLFO->fTempoSync) || onOffTest(bufferLFO->fTempoSync)) ) + { + // calculate the tempo at the current processing buffer + if ( (fTempo > 0.0f) || (hostCanDoTempo != 1) ) // get the tempo from the user parameter + { + currentTempoBPS = tempoScaled(fTempo) / 60.0f; + needResync = false; // we don't want it true if we're not syncing to host tempo + } + else // get the tempo from the host + { +/* timeInfo = getTimeInfo(kBeatSyncTimeInfoFlags); + if (timeInfo) + { + if (kVstTempoValid & timeInfo->flags) + currentTempoBPS = (float)timeInfo->tempo / 60.0f; + else + currentTempoBPS = tempoScaled(fTempo) / 60.0f; +// currentTempoBPS = ((float)tempoAt(reportCurrentPosition())) / 600000.0f; + // but zero & negative tempos are bad, so get the user tempo value instead if that happens + if (currentTempoBPS <= 0.0f) + currentTempoBPS = tempoScaled(fTempo) / 60.0f; + // + // check if audio playback has just restarted & reset buffer stuff if it has (for measure sync) + if (timeInfo->flags & kVstTransportChanged) + { + needResync = true; + currentForcedBufferSize = 1; + writePos = 1; + minibufferSize = 1; + prevMinibufferSize = 0; + smoothcount = smoothDur = 0; + } + } + else // do the same stuff as above if the timeInfo gets a null pointer + { +*/ currentTempoBPS = tempoScaled(fTempo) / 60.0f; + needResync = false; // we don't want it true if we're not syncing to host tempo +// } + } + } + + +//-----------------------AUDIO STUFF--------------------------- + // here we begin the audio output loop, which has two checkpoints at the beginning + for (long samplecount = 0; (samplecount < sampleFrames); samplecount++) + { + // check if it's the end of this minibuffer + if (readPos >= minibufferSize) + updateBuffer(samplecount); + + // store the latest input samples into the buffers + buffer1[writePos] = inputs[0][samplecount]; + + // get the current output without any smoothing + float out1 = buffer1[readPos]; + + // and if smoothing is taking place, get the smoothed audio output + if (smoothcount > 0) + { + out1 = (out1 * fadeInGain) + (buffer1[readPos+prevMinibufferSize] * fadeOutGain); + + smoothcount--; + + fadeInGain = (fadeOutGain * imaginaryFadePart) + (fadeInGain * realFadePart); + fadeOutGain = (realFadePart * fadeOutGain) - (imaginaryFadePart * fadeInGain); + } + + // write the output samples into the output stream + if (replacing) + { + outputs[0][samplecount] = (out1 * outputGain) + (inputs[0][samplecount] * inputGain); + } + else + { + outputs[0][samplecount] += (out1 * outputGain) + (inputs[0][samplecount] * inputGain); + } + + // increment the position trackers + readPos++; + writePos++; + } +} -- cgit v1.2.1