Esempio n. 1
0
void DRowAudioFilter::processBlock (AudioSampleBuffer& buffer,
									MidiBuffer& midiMessages)
{
	smoothParameters();
	const int numInputChannels = getNumInputChannels();
	int numSamples = buffer.getNumSamples();

	// set up the parameters to be used
	float preDelay = (float)params[PREDELAY].getSmoothedValue();
	float earlyDecay = (float)params[EARLYDECAY].getSmoothedNormalisedValue();
	earlyDecay = sqrt(sqrt(earlyDecay));
	float late = (float)params[EARLYLATEMIX].getSmoothedNormalisedValue();
	float early = 1.0f - late;
	float fbCoeff = (float)params[FBCOEFF].getSmoothedNormalisedValue();
	fbCoeff = -sqrt(sqrt(fbCoeff));
	float delayTime = (float)params[DELTIME].getSmoothedValue();
	float filterCf = (float)params[FILTERCF].getSmoothedValue();
	float allpassCoeff = (float)params[DIFFUSION].getSmoothedNormalisedValue();
	float spread1 = (float)params[SPREAD].getSmoothedNormalisedValue();
	float spread2 = 1.0f - spread1;
	float lowEQGain = (float)decibelsToAbsolute(params[LOWEQ].getSmoothedValue());
	float highEQGain = (float)decibelsToAbsolute(params[HIGHEQ].getSmoothedValue());
	float wet = (float)params[WETDRYMIX].getSmoothedNormalisedValue();
	float dry = 1.0f - wet;

	float width = (spread1-0.5f) * 0.1f * delayTime;


	// we can only deal with 2-in, 2-out at the moment
	if (numInputChannels == 2)
	{
		// pre-delay section
		preDelayFilterL.setDelayTime(currentSampleRate, preDelay);
		preDelayFilterR.setDelayTime(currentSampleRate, preDelay);


		// early reflections section
		int roomShape = roundFloatToInt(params[ROOMSHAPE].getValue());
		float delayCoeff = 0.08f * delayTime;
		if (roomShape != prevRoomShape)
		{
			delayLineL.removeAllTaps();
			delayLineR.removeAllTaps();

			for(int i = 0; i < 5; i++) {
				delayLineL.addTapAtTime(earlyReflectionCoeffs[roomShape-3][i], currentSampleRate);
				delayLineR.addTapAtTime(earlyReflectionCoeffs[roomShape-3][i], currentSampleRate);
			}

			// we have to set this here incase the delay time has not changed
			delayLineL.setTapSpacingExplicitly(delayCoeff);
			delayLineR.setTapSpacingExplicitly(delayCoeff + spread1);

			prevRoomShape = roomShape;
		}

		delayLineL.setTapSpacing(delayCoeff);
		delayLineL.scaleFeedbacks(earlyDecay);
		delayLineR.setTapSpacing(delayCoeff + spread1);
		delayLineR.scaleFeedbacks(earlyDecay);


		// comb filter section
		for (int i = 0; i < 8; ++i)
		{
			delayTime *= filterMultCoeffs[i];
			delayTime += Random::getSystemRandom().nextInt(100)*0.0001;

			setupFilter(combFilterL[i], fbCoeff, delayTime, filterCf);
			setupFilter(combFilterR[i], fbCoeff, delayTime + width, filterCf);
		}

		// allpass section
		for (int i = 0; i < 4; ++i)
		{
			delayTime *= allpassMultCoeffs[i];
			delayTime -= Random::getSystemRandom().nextInt(100)*0.0001;

			allpassFilterL[i].setGain(allpassCoeff);
			allpassFilterL[i].setDelayTime(currentSampleRate, delayTime);

			allpassFilterR[i].setGain(allpassCoeff);
			allpassFilterR[i].setDelayTime(currentSampleRate, delayTime + width);
		}

		// final EQ section
		lowEQL.makeLowShelf(currentSampleRate, 500, 1, lowEQGain);
		lowEQR.makeLowShelf(currentSampleRate, 500, 1, lowEQGain);
		highEQL.makeHighShelf(currentSampleRate, 3000, 1, highEQGain);
		highEQR.makeHighShelf(currentSampleRate, 3000, 1, highEQGain);


		//========================================================================
		//	Processing
		//========================================================================
		int noSamples = buffer.getNumSamples();
		int noChannels = buffer.getNumChannels();

		// create a copy of the input buffer so we can apply a wet/dry mix later
		AudioSampleBuffer wetBuffer(noChannels, noSamples);
		wetBuffer.copyFrom(0, 0, buffer, 0, 0, noSamples);
		wetBuffer.copyFrom(1, 0, buffer, 1, 0, noSamples);

		// mono mix wet buffer (used for stereo spread later)
		float *pfWetL = wetBuffer.getSampleData(0);
		float *pfWetR = wetBuffer.getSampleData(1);
		while (--numSamples >= 0)
		{
			*pfWetL = *pfWetR = (0.5f * (*pfWetL + *pfWetR));
			pfWetL++;
			pfWetR++;
		}
		numSamples = buffer.getNumSamples();

		// apply the pre-delay to the wet buffer
		preDelayFilterL.processSamples(wetBuffer.getSampleData(0), noSamples);
		preDelayFilterR.processSamples(wetBuffer.getSampleData(1), noSamples);


		// create a buffer to hold the early reflections
		AudioSampleBuffer earlyReflections(noChannels, noSamples);
		earlyReflections.copyFrom(0, 0, wetBuffer, 0, 0, noSamples);
		earlyReflections.copyFrom(1, 0, wetBuffer, 1, 0, noSamples);

		// and process the early reflections
		delayLineL.processSamples(earlyReflections.getSampleData(0), noSamples);
		delayLineR.processSamples(earlyReflections.getSampleData(1), noSamples);


		// create a buffer to hold the late reverb
		AudioSampleBuffer lateReverb(noChannels, noSamples);
		lateReverb.clear();

		float *pfLateL = lateReverb.getSampleData(0);
		float *pfLateR = lateReverb.getSampleData(1);
		pfWetL = wetBuffer.getSampleData(0);
		pfWetR = wetBuffer.getSampleData(1);

		// comb filter section
		for (int i = 0; i < 8; ++i)
		{
			combFilterL[i].processSamplesAdding(pfWetL, pfLateL, noSamples);
			combFilterR[i].processSamplesAdding(pfWetR, pfLateR, noSamples);
		}

		// allpass filter section
		for (int i = 0; i < 4; ++i)
		{
			allpassFilterL[i].processSamples(lateReverb.getSampleData(0), noSamples);
			allpassFilterR[i].processSamples(lateReverb.getSampleData(1), noSamples);
		}


		// clear wet buffer
		wetBuffer.clear();
		// add early reflections to wet buffer
		wetBuffer.addFrom(0, 0, earlyReflections, 0, 0, noSamples, early);
		wetBuffer.addFrom(1, 0, earlyReflections, 1, 0, noSamples, early);
		// add late reverb to wet buffer
		lateReverb.applyGain(0, noSamples, 0.1f);
		wetBuffer.addFrom(0, 0, lateReverb, 0, 0, noSamples, late);
		wetBuffer.addFrom(1, 0, lateReverb, 1, 0, noSamples, late);

		// final EQ
		lowEQL.processSamples(pfWetL, noSamples);
		lowEQR.processSamples(pfWetR, noSamples);

		highEQL.processSamples(pfWetL, noSamples);
		highEQR.processSamples(pfWetR, noSamples);

		// create stereo spread
		while (--numSamples >= 0)
		{
			float fLeft = *pfWetL;
			float fRight = *pfWetR;
			*pfWetL = (fLeft * spread1) + (fRight * spread2);
			*pfWetR = (fRight * spread1) + (fLeft * spread2);
			pfWetL++;
			pfWetR++;
		}
		numSamples = buffer.getNumSamples();

		// apply wet/dry mix gains
		wetBuffer.applyGain(0, noSamples, wet);
		buffer.applyGain(0, noSamples, dry);

		// add wet buffer to output buffer
		buffer.addFrom(0, 0, wetBuffer, 0, 0, noSamples);
		buffer.addFrom(1, 0, wetBuffer, 1, 0, noSamples);
	}
	//========================================================================


    // in case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}
Esempio n. 2
0
void DRowAudioFilter::processBlock (AudioSampleBuffer& buffer,
									MidiBuffer& midiMessages)
{
	waveformDisplayPre->processBlock(buffer.getSampleData(0), buffer.getNumSamples());
	
	smoothParameters();
	
	const int numInputChannels = getNumInputChannels();
	const float oneOverNumInputChannels = 1.0f / numInputChannels;
	int numSamples = buffer.getNumSamples();


	// create parameters to use
	float fThresh = params[THRESH].getNormalisedValue();
	float fClosedLevel = params[REDUCTION].getSmoothedNormalisedValue();
	
	float fAttack	= params[ATTACK].getSmoothedValue();
	float fHold	= params[HOLD].getSmoothedValue();
	float fRelease	= params[RELEASE].getSmoothedValue();
	
	float fMonitor = params[MONITOR].getNormalisedValue();
	float fFilter = params[FILTER].getNormalisedValue();
	
	// stereo
	if (numInputChannels == 2)
	{
		// set up array of pointers to samples
		float* pfSample[2];
		pfSample[0] = buffer.getSampleData(0);
		pfSample[1] = buffer.getSampleData(1);
		
		
		// set-up mixed mono buffer
		AudioSampleBuffer mixedBuffer(1, buffer.getNumSamples());
		float* pfMixedSample = mixedBuffer.getSampleData(0);
		
		// fill mono mixed buffer
		for(int i = 0; i < mixedBuffer.getNumSamples(); i++) {
			*pfMixedSample = 0.0;
			pfMixedSample++;
		}
		pfMixedSample = mixedBuffer.getSampleData(0);

		for(int i = 0; i < mixedBuffer.getNumSamples(); i++)
		{
			*pfMixedSample += oneOverNumInputChannels * (*pfSample[0]);
			pfSample[0]++;
			*pfMixedSample += oneOverNumInputChannels * (*pfSample[1]);
			pfSample[1]++;
			pfMixedSample++;
		}
		
		// filter mixed buffer
		if(fFilter > 0.5f)
			bandpassFilter.processSamples(mixedBuffer.getSampleData(0), mixedBuffer.getNumSamples());
		
		
		// reset buffer pointers
		pfSample[0] = buffer.getSampleData(0);
		pfSample[1] = buffer.getSampleData(1);
		pfMixedSample = mixedBuffer.getSampleData(0);
		
				
		//========================================================================
		while (--numSamples >= 0)
		{
			float fMix = *pfMixedSample;
			float fAbsMix = fabsf(fMix);
			pfMixedSample++;
			
			if (fAbsMix > fMax)
				fMax = fAbsMix;
			
			if (iMeasuredItems >= iMeasureLength)
			{
				if ( (fMax >= fThresh) && (currentState != attack) )		// opening gate
				{
					DBG("Attack");
					currentState = attack;
					noStageSamples = fAttack * currentSampleRate * 0.001;
					fOutMultIncriment = (1.0 - fOutMultCurrent) / noStageSamples;
					currentStageSample = 0;
					changingState = true;
				}
				else if ( (fMax < fThresh) && ((currentState == attack) || (currentState == open)) ) // closing gate, hold
				{
					DBG("Hold");
					currentState = hold;
					noStageSamples = fHold * currentSampleRate * 0.001;
					fOutMultIncriment = 0;
					currentStageSample = 0;
					changingState = true;
				}
				
				fMax = 0;
				iMeasuredItems = 0;
			}
			iMeasuredItems++;
			
			
			// apply appropriate gains to output
			if (fMonitor > 0.5f)	{
				*pfSample[0] = fMix;
				*pfSample[1] = fMix;
			}
			else	{
				*pfSample[0] *= fOutMultCurrent;
				*pfSample[1] *= fOutMultCurrent;
			}

			// incriment sample pointers
			pfSample[0]++;			
			pfSample[1]++;			
			

			fOutMultCurrent += fOutMultIncriment;
			currentStageSample++;
			if ( (currentStageSample == noStageSamples) && changingState)
			{
				DBG("Stage finished");
				fOutMultIncriment = 0.0;
				currentStageSample = 1;
				noStageSamples = 0;
				
				// if ended hold do release stage
				if (currentState == hold)
				{
					DBG("Release");
					currentState = release;
					noStageSamples = fRelease * currentSampleRate * 0.001;
					fOutMultIncriment = -((fOutMultCurrent - fClosedLevel) / noStageSamples);
					currentStageSample = 0;
					changingState = true;
				}
				else if (currentState == release)	{
					DBG("Closed");
					currentState = closed;
					changingState = false;
				}
				else if (currentState == attack)	{
					DBG("Open");
					currentState = open;
					changingState = false;
				}
			}
		}
		//========================================================================	
		
		// update the sample to use in the meter display
//		RMSLeft = buffer.getRMSLevel(0, 0, buffer.getNumSamples());
//		peakLeft = buffer.getMagnitude(0, 0, buffer.getNumSamples());
//		RMSRight = buffer.getRMSLevel(1 & (numInputChannels-1), 0, buffer.getNumSamples());
//		peakRight = buffer.getMagnitude(1 & (numInputChannels-1), 0, buffer.getNumSamples());
		
		waveformDisplayPost->processBlock(buffer.getSampleData(0), buffer.getNumSamples());

		RMSLeft = fOutMultIncriment;
		RMSRight = fOutMultCurrent;

	}

		
    // in case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }

}
Esempio n. 3
0
void DRowAudioFilter::processBlock (AudioSampleBuffer& buffer,
									MidiBuffer& midiMessages)
{
	smoothParameters();
	const int numInputChannels = getNumInputChannels();
	int numSamples = buffer.getNumSamples();		
	
	// set up the parameters to be used
	float inGain = decibelsToAbsolute(params[INGAIN].getSmoothedValue());
	float outGain = decibelsToAbsolute(params[OUTGAIN].getSmoothedValue());

	buffer.applyGain(0, buffer.getNumSamples(), inGain);

	if (numInputChannels == 2)
	{		
		// get sample pointers
		float* channelL = buffer.getSampleData(0); 
		float* channelR = buffer.getSampleData(1); 
		
		// pre-filter
		inFilterL->processSamples(buffer.getSampleData(0), numSamples);
		inFilterR->processSamples(buffer.getSampleData(1), numSamples);

		while (--numSamples >= 0)
		{
			float sampleL = *channelL;
			float sampleR = *channelR;
			
			// clip samples
			sampleL = jlimit(-1.0f, 1.0f, sampleL);
			sampleR = jlimit(-1.0f, 1.0f, sampleR);
									
			if (sampleL < 0.0f) {
				sampleL *= -1.0f;
				sampleL = linearInterpolate(distortionBuffer, distortionBufferSize, sampleL*distortionBufferMax);
				sampleL *= -1.0f;
			}
			else {
				sampleL = linearInterpolate(distortionBuffer, distortionBufferSize, sampleL*distortionBufferMax);
			}
			
			if (sampleR < 0.0f) {
				sampleR *= -1.0f;
				sampleR = linearInterpolate(distortionBuffer, distortionBufferSize, sampleR*distortionBufferMax);
				sampleR *= -1.0f;
			}
			else {
				sampleR = linearInterpolate(distortionBuffer, distortionBufferSize, sampleR*distortionBufferMax);
			}
						
			*channelL++ = sampleL;
			*channelR++ = sampleR;
		}
		
		// post-filter
		outFilterL->processSamples(buffer.getSampleData(0), buffer.getNumSamples());
		outFilterR->processSamples(buffer.getSampleData(1), buffer.getNumSamples());
		
		buffer.applyGain(0, buffer.getNumSamples(), outGain);
	}
	else if (numInputChannels == 1)
	{		
		// get sample pointers
		float* channelL = buffer.getSampleData(0); 
		
		// pre-filter
		inFilterL->processSamples(buffer.getSampleData(0), numSamples);
		
		while (--numSamples >= 0)
		{
			float sampleL = *channelL;
			
			// clip samples
			sampleL = jlimit(-1.0f, 1.0f, sampleL);
			
			if (sampleL < 0.0f) {
				sampleL *= -1.0f;
				sampleL = linearInterpolate(distortionBuffer, distortionBufferSize, sampleL*distortionBufferMax);
				sampleL *= -1.0f;
			}
			else {
				sampleL = linearInterpolate(distortionBuffer, distortionBufferSize, sampleL*distortionBufferMax);
			}
			
			*channelL++ = sampleL;
		}
		
		// post-filter
		outFilterL->processSamples(buffer.getSampleData(0), buffer.getNumSamples());
		
		buffer.applyGain(0, buffer.getNumSamples(), outGain);
	}
	//========================================================================

	
    // in case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}
Esempio n. 4
0
void DRowAudioFilter::processBlock (AudioSampleBuffer& buffer,
                                   MidiBuffer& midiMessages)
{
	smoothParameters();
	
	const int numInputChannels = getNumInputChannels();


	// create parameters to use
	fPreCf = params[PRE].getSmoothedValue();
	fPostCf = params[POST].getSmoothedValue();
	float fInGain = params[INGAIN].getSmoothedValue();
	float fOutGain = params[OUTGAIN].getSmoothedValue();
	float fColour = 100 * params[COLOUR].getSmoothedNormalisedValue();

	// set up array of pointers to samples
	int numSamples = buffer.getNumSamples();
	int samplesLeft = numSamples;
	float* pfSample[numInputChannels];
	for (int channel = 0; channel < numInputChannels; channel++)
		pfSample[channel] = buffer.getSampleData(channel);
		
		
	if (numInputChannels == 2)
	{
		// input filter the samples
		inFilterL.processSamples(pfSample[0], numSamples);
		inFilterR.processSamples(pfSample[1], numSamples);
		
		//========================================================================
		while (--samplesLeft >= 0)
		{
			// distort
			*pfSample[0] *= fInGain;
			*pfSample[1] *= fInGain;
		
			// shape (using the limit of tanh is 1 so no cliping required)
			*pfSample[0] = tanh(*pfSample[0] * fColour);
			*pfSample[1] = tanh(*pfSample[1] * fColour);

			// apply output gain
			*pfSample[0] *= fOutGain;
			*pfSample[1] *= fOutGain;
		
			// incriment sample pointers
			pfSample[0]++;
			pfSample[1]++;
		}
		//========================================================================
		
		// output filter the samples
		outFilterL.processSamples(buffer.getSampleData(0), numSamples);
		outFilterR.processSamples(buffer.getSampleData(1), numSamples);
	}
	else if (numInputChannels == 1)
	{
		// input filter the samples
		inFilterL.processSamples(pfSample[0], numSamples);
		
		//========================================================================
		while (--samplesLeft >= 0)
		{
			// distort
			*pfSample[0] *= fInGain;
			
			// shape (using the limit of tanh is 1 so no cliping required)
			*pfSample[0] = tanh(*pfSample[0] * fColour);
			
			// apply output gain
			*pfSample[0] *= fOutGain;
			
			// incriment sample pointers
			pfSample[0]++;
		}
		//========================================================================
		
		// output filter the samples
		outFilterL.processSamples(buffer.getSampleData(0), numSamples);
	}
	
		
    // clear any output channels that didn't contain input data
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
        buffer.clear (i, 0, buffer.getNumSamples());
}
Esempio n. 5
0
void DRowAudioFilter::processBlock (AudioSampleBuffer& buffer,
                                    MidiBuffer& midiMessages)
{
    smoothParameters();

    const int numInputChannels = getNumInputChannels();

    // create parameters to use
    float fRate = params[RATE].getSmoothedValue();
    float fDepth = (params[DEPTH].getSmoothedNormalisedValue() * 0.006f) + 0.0001f;
    float fFeedback = params[FEEDBACK].getSmoothedNormalisedValue();
    float fWetDryMix = params[MIX].getSmoothedNormalisedValue();

    // calculate current phase step
    float phaseStep = iLookupTableSize * oneOverCurrentSampleRate * fRate;

    // set up array of pointers to samples
    int numSamples = buffer.getNumSamples();
    float* pfSample[numInputChannels];
    for (int channel = 0; channel < getNumInputChannels(); channel++)
        pfSample[channel] = buffer.getSampleData(channel);

    if (numInputChannels == 2)
    {
        //========================================================================
        while (--numSamples >= 0)
        {
            int index =  (int)(iSamplesProcessed * phaseStep) &	iLookupTableSizeMask;

            iSamplesProcessed++;
            float fOsc = (pfLookupTable[index] * fDepth) + fDepth;

            float fBufferReadPos1 = (iBufferWritePos - (fOsc * iBufferSize));
            if (fBufferReadPos1 < 0)
                fBufferReadPos1 += iBufferSize;

            // read values from buffers
            int iPos1, iPos2;
            float fDiff, fDelL, fDelR;

            iPos1 = (int)fBufferReadPos1;
            iPos2 = iPos1 + 1;
            if (iPos2 == iBufferSize)
                iPos2 = 0;
            fDiff = fBufferReadPos1 - iPos1;
            fDelL = pfCircularBufferL[iPos2]*fDiff + pfCircularBufferL[iPos1]*(1-fDiff);
            fDelR = pfCircularBufferR[iPos2]*fDiff + pfCircularBufferR[iPos1]*(1-fDiff);

            // store current samples in buffers
            iBufferWritePos++;
            if (iBufferWritePos >= iBufferSize)
                iBufferWritePos = 0;
            pfCircularBufferL[iBufferWritePos] = *pfSample[0] + (fFeedback * fDelL);
            pfCircularBufferR[iBufferWritePos] = *pfSample[1] + (fFeedback * fDelR);

            // calculate output samples
            float fOutL = 0.5f * (*pfSample[0] + fWetDryMix*fDelL);
            float fOutR = 0.5f * (*pfSample[1] + fWetDryMix*fDelR);

            *pfSample[0] = fOutL;
            *pfSample[1] = fOutR;

            // incriment sample pointers
            pfSample[0]++;
            pfSample[1]++;
        }
        //========================================================================
    }
    else if (numInputChannels == 1)
    {
        //========================================================================
        while (--numSamples >= 0)
        {
            int index =  (int)(iSamplesProcessed * phaseStep) &	iLookupTableSizeMask;

            iSamplesProcessed++;
            float fOsc = (pfLookupTable[index] * fDepth) + fDepth;

            float fBufferReadPos1 = (iBufferWritePos - (fOsc * iBufferSize));
            if (fBufferReadPos1 < 0)
                fBufferReadPos1 += iBufferSize;

            // read values from buffers
            int iPos1, iPos2;
            float fDiff, fDelL;

            iPos1 = (int)fBufferReadPos1;
            iPos2 = iPos1 + 1;
            if (iPos2 == iBufferSize)
                iPos2 = 0;
            fDiff = fBufferReadPos1 - iPos1;
            fDelL = pfCircularBufferL[iPos2]*fDiff + pfCircularBufferL[iPos1]*(1-fDiff);

            // store current samples in buffers
            iBufferWritePos++;
            if (iBufferWritePos >= iBufferSize)
                iBufferWritePos = 0;
            pfCircularBufferL[iBufferWritePos] = *pfSample[0] + (fFeedback * fDelL);

            // calculate output samples
            float fOutL = 0.5f * (*pfSample[0] + fWetDryMix*fDelL);

            *pfSample[0] = fOutL;

            // incriment sample pointers
            pfSample[0]++;
        }
        //========================================================================
    }

    // in case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}