diff options
Diffstat (limited to 'arm-wt-22k/lib_src/eas_reverb.c')
-rw-r--r-- | arm-wt-22k/lib_src/eas_reverb.c | 2284 |
1 files changed, 1142 insertions, 1142 deletions
diff --git a/arm-wt-22k/lib_src/eas_reverb.c b/arm-wt-22k/lib_src/eas_reverb.c index 6d99862..cd5befe 100644 --- a/arm-wt-22k/lib_src/eas_reverb.c +++ b/arm-wt-22k/lib_src/eas_reverb.c @@ -1,13 +1,13 @@ -/*----------------------------------------------------------------------------
- *
- * File:
- * eas_reverb.c
- *
- * Contents and purpose:
- * Contains the implementation of the Reverb effect.
- *
- *
- * Copyright Sonic Network Inc. 2006
+/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.c + * + * Contents and purpose: + * Contains the implementation of the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,1135 +20,1135 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - *
- *----------------------------------------------------------------------------
- * Revision Control:
- * $Revision: 510 $
- * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $
- *----------------------------------------------------------------------------
-*/
-
-/*------------------------------------
- * includes
- *------------------------------------
-*/
-
-#include "eas_data.h"
-#include "eas_effects.h"
-#include "eas_math.h"
-#include "eas_reverbdata.h"
-#include "eas_reverb.h"
-#include "eas_config.h"
-#include "eas_host.h"
-#include "eas_report.h"
-
-/* prototypes for effects interface */
-static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
-static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
-static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
-static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
-static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
-
-/* common effects interface for configuration module */
-const S_EFFECTS_INTERFACE EAS_Reverb =
-{
- ReverbInit,
- ReverbProcess,
- ReverbShutdown,
- ReverbGetParam,
- ReverbSetParam
-};
-
-
-
-/*----------------------------------------------------------------------------
- * InitializeReverb()
- *----------------------------------------------------------------------------
- * Purpose:
- *
- * Inputs:
- *
- * Outputs:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
-{
- EAS_I32 i;
- EAS_U16 nOffset;
- EAS_INT temp;
-
- S_REVERB_OBJECT *pReverbData;
- S_REVERB_PRESET *pPreset;
-
- /* check Configuration Module for data allocation */
- if (pEASData->staticMemoryModel)
- pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB);
-
- /* allocate dynamic memory */
- else
- pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT));
-
- if (pReverbData == NULL)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ }
- return EAS_ERROR_MALLOC_FAILED;
- }
-
- /* clear the structure */
- EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT));
-
- ReverbReadInPresets(pReverbData);
-
- pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES;
-
- pReverbData->m_nRevOutFbkR = 0;
- pReverbData->m_nRevOutFbkL = 0;
-
- pReverbData->m_sAp0.m_zApIn = AP0_IN;
- pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH;
- pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN;
-
- pReverbData->m_zD0In = DELAY0_IN;
-
- pReverbData->m_sAp1.m_zApIn = AP1_IN;
- pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH;
- pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN;
-
- pReverbData->m_zD1In = DELAY1_IN;
-
- pReverbData->m_zLpf0 = 0;
- pReverbData->m_zLpf1 = 0;
- pReverbData->m_nLpfFwd = 8837;
- pReverbData->m_nLpfFbk = 6494;
-
- pReverbData->m_nSin = 0;
- pReverbData->m_nCos = 0;
- pReverbData->m_nSinIncrement = 0;
- pReverbData->m_nCosIncrement = 0;
-
- // set xfade parameters
- pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES;
- pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration
- pReverbData->m_nPhase = -32768;
- pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT;
-
- pReverbData->m_nNoise = (EAS_I16)0xABCD;
-
- pReverbData->m_nMaxExcursion = 0x007F;
-
- // set delay tap lengths
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
- &pReverbData->m_nNoise );
-
- pReverbData->m_zD1Cross =
- DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
-
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
- &pReverbData->m_nNoise );
-
- pReverbData->m_zD0Cross =
- DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset;
-
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
- &pReverbData->m_nNoise );
-
- pReverbData->m_zD0Self =
- DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
-
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion,
- &pReverbData->m_nNoise );
-
- pReverbData->m_zD1Self =
- DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
-
- // for debugging purposes, allow noise generator
- pReverbData->m_bUseNoise = EAS_FALSE;
-
- // for debugging purposes, allow bypass
- pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE;
-
- pReverbData->m_nNextRoom = 1;
-
- pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration
-
- pReverbData->m_nWet = REVERB_DEFAULT_WET;
-
- pReverbData->m_nDry = REVERB_DEFAULT_DRY;
-
- // set base index into circular buffer
- pReverbData->m_nBaseIndex = 0;
-
- // set the early reflections, L
- pReverbData->m_sEarlyL.m_nLpfFbk = 4915;
- pReverbData->m_sEarlyL.m_nLpfFwd = 27852;
- pReverbData->m_sEarlyL.m_zLpf = 0;
-
- for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++)
- {
- pReverbData->m_sEarlyL.m_nGain[i] = 0;
- pReverbData->m_sEarlyL.m_zDelay[i] = 0;
- }
-
- // set the early reflections, R
- pReverbData->m_sEarlyR.m_nLpfFbk = 4915;
- pReverbData->m_sEarlyR.m_nLpfFwd = 27852;
- pReverbData->m_sEarlyR.m_zLpf = 0;
-
- for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++)
- {
- pReverbData->m_sEarlyR.m_nGain[i] = 0;
- pReverbData->m_sEarlyR.m_zDelay[i] = 0;
- }
-
- // clear the reverb delay line
- for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++)
- {
- pReverbData->m_nDelayLine[i] = 0;
- }
-
- ////////////////////////////////
- ///code from the EAS DEMO Reverb
- //now copy from the new preset into the reverb
- pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom];
-
- pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk;
- pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd;
-
- pReverbData->m_nEarly = pPreset->m_nEarly;
- pReverbData->m_nWet = pPreset->m_nWet;
- pReverbData->m_nDry = pPreset->m_nDry;
-
- pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion;
- //stored as time based, convert to sample based
- temp = pPreset->m_nXfadeInterval;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_nXfadeInterval = (EAS_U16) temp;
- //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
-
- pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
- //stored as time based, convert to absolute sample value
- temp = pPreset->m_nAp0_ApOut;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp);
- //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut;
-
- pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
- //stored as time based, convert to absolute sample value
- temp = pPreset->m_nAp1_ApOut;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp);
- //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
- ///code from the EAS DEMO Reverb
- ////////////////////////////////
-
- *pInstData = pReverbData;
-
- return EAS_SUCCESS;
-
-} /* end InitializeReverb */
-
-
-
-/*----------------------------------------------------------------------------
- * ReverbProcess()
- *----------------------------------------------------------------------------
- * Purpose:
- * Reverberate the requested number of samples (block based processing)
- *
- * Inputs:
- * pInputBuffer - src buffer
- * pOutputBuffer - dst buffer
- * nNumSamplesToAdd - number of samples to write to buffer
- *
- * Outputs:
- * number of samples actually written to buffer
- *
- * Side Effects:
- * - samples are added to the presently free buffer
- *
- *----------------------------------------------------------------------------
-*/
-static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
-{
- S_REVERB_OBJECT *pReverbData;
-
- pReverbData = (S_REVERB_OBJECT*) pInstData;
-
- //if bypassed or the preset forces the signal to be completely dry
- if (pReverbData->m_bBypass ||
- (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767))
- {
- if (pSrc != pDst)
- EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
- return;
- }
-
- if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom)
- {
- ReverbUpdateRoom(pReverbData);
- }
-
- ReverbUpdateXfade(pReverbData, numSamples);
-
- Reverb(pReverbData, numSamples, pDst, pSrc);
-
- /* check if update counter needs to be reset */
- if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES)
- {
- /* update interval has elapsed, so reset counter */
- pReverbData->m_nUpdateCounter = 0;
- } /* end if m_nUpdateCounter >= update interval */
-
- /* increment update counter */
- pReverbData->m_nUpdateCounter += (EAS_I16)numSamples;
-
-} /* end ComputeReverb */
-
-/*----------------------------------------------------------------------------
- * ReverbUpdateXfade
- *----------------------------------------------------------------------------
- * Purpose:
- * Update the xfade parameters as required
- *
- * Inputs:
- * nNumSamplesToAdd - number of samples to write to buffer
- *
- * Outputs:
- *
- *
- * Side Effects:
- * - xfade parameters will be changed
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd)
-{
- EAS_U16 nOffset;
- EAS_I16 tempCos;
- EAS_I16 tempSin;
-
- if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval)
- {
- /* update interval has elapsed, so reset counter */
- pReverbData->m_nXfadeCounter = 0;
-
- // Pin the sin,cos values to min / max values to ensure that the
- // modulated taps' coefs are zero (thus no clicks)
- if (pReverbData->m_nPhaseIncrement > 0)
- {
- // if phase increment > 0, then sin -> 1, cos -> 0
- pReverbData->m_nSin = 32767;
- pReverbData->m_nCos = 0;
-
- // reset the phase to match the sin, cos values
- pReverbData->m_nPhase = 32767;
-
- // modulate the cross taps because their tap coefs are zero
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
-
- pReverbData->m_zD1Cross =
- DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
-
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
-
- pReverbData->m_zD0Cross =
- DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
- }
- else
- {
- // if phase increment < 0, then sin -> 0, cos -> 1
- pReverbData->m_nSin = 0;
- pReverbData->m_nCos = 32767;
-
- // reset the phase to match the sin, cos values
- pReverbData->m_nPhase = -32768;
-
- // modulate the self taps because their tap coefs are zero
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
-
- pReverbData->m_zD0Self =
- DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset;
-
- nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise );
-
- pReverbData->m_zD1Self =
- DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset;
-
- } // end if-else (pReverbData->m_nPhaseIncrement > 0)
-
- // Reverse the direction of the sin,cos so that the
- // tap whose coef was previously increasing now decreases
- // and vice versa
- pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement;
-
- } // end if counter >= update interval
-
- //compute what phase will be next time
- pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement;
-
- //calculate what the new sin and cos need to reach by the next update
- ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos);
-
- //calculate the per-sample increment required to get there by the next update
- /*lint -e{702} shift for performance */
- pReverbData->m_nSinIncrement =
- (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS;
-
- /*lint -e{702} shift for performance */
- pReverbData->m_nCosIncrement =
- (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS;
-
-
- /* increment update counter */
- pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd;
-
- return EAS_SUCCESS;
-
-} /* end ReverbUpdateXfade */
-
-
-/*----------------------------------------------------------------------------
- * ReverbCalculateNoise
- *----------------------------------------------------------------------------
- * Purpose:
- * Calculate a noise sample and limit its value
- *
- * Inputs:
- * nMaxExcursion - noise value is limited to this value
- * pnNoise - return new noise sample in this (not limited)
- *
- * Outputs:
- * new limited noise value
- *
- * Side Effects:
- * - *pnNoise noise value is updated
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise)
-{
- // calculate new noise value
- *pnNoise = (EAS_I16) (*pnNoise * 5 + 1);
-
-#if 0 // 1xxx, test
- *pnNoise = 0;
-#endif // 1xxx, test
-
- // return the limited noise value
- return (nMaxExcursion & (*pnNoise));
-
-} /* end ReverbCalculateNoise */
-
-/*----------------------------------------------------------------------------
- * ReverbCalculateSinCos
- *----------------------------------------------------------------------------
- * Purpose:
- * Calculate a new sin and cosine value based on the given phase
- *
- * Inputs:
- * nPhase - phase angle
- * pnSin - input old value, output new value
- * pnCos - input old value, output new value
- *
- * Outputs:
- *
- * Side Effects:
- * - *pnSin, *pnCos are updated
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos)
-{
- EAS_I32 nTemp;
- EAS_I32 nNetAngle;
-
- // -1 <= nPhase < 1
- // However, for the calculation, we need a value
- // that ranges from -1/2 to +1/2, so divide the phase by 2
- /*lint -e{702} shift for performance */
- nNetAngle = nPhase >> 1;
-
- /*
- Implement the following
- sin(x) = (2-4*c)*x^2 + c + x
- cos(x) = (2-4*c)*x^2 + c - x
-
- where c = 1/sqrt(2)
- using the a0 + x*(a1 + x*a2) approach
- */
-
- /* limit the input "angle" to be between -0.5 and +0.5 */
- if (nNetAngle > EG1_HALF)
- {
- nNetAngle = EG1_HALF;
- }
- else if (nNetAngle < EG1_MINUS_HALF)
- {
- nNetAngle = EG1_MINUS_HALF;
- }
-
- /* calculate sin */
- nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
- nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
- *pnSin = (EAS_I16) SATURATE_EG1(nTemp);
-
- /* calculate cos */
- nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
- nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
- *pnCos = (EAS_I16) SATURATE_EG1(nTemp);
-
- return EAS_SUCCESS;
-} /* end ReverbCalculateSinCos */
-
-/*----------------------------------------------------------------------------
- * Reverb
- *----------------------------------------------------------------------------
- * Purpose:
- * apply reverb to the given signal
- *
- * Inputs:
- * nNu
- * pnSin - input old value, output new value
- * pnCos - input old value, output new value
- *
- * Outputs:
- * number of samples actually reverberated
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer)
-{
- EAS_I32 i;
- EAS_I32 nDelayOut;
- EAS_U16 nBase;
-
- EAS_U32 nAddr;
- EAS_I32 nTemp1;
- EAS_I32 nTemp2;
- EAS_I32 nApIn;
- EAS_I32 nApOut;
-
- EAS_I32 j;
- EAS_I32 nEarlyOut;
-
- EAS_I32 tempValue;
-
-
- // get the base address
- nBase = pReverbData->m_nBaseIndex;
-
- for (i=0; i < nNumSamplesToAdd; i++)
- {
- // ********** Left Allpass - start
- // left input = (left dry/4) + right feedback from previous period
- /*lint -e{702} use shift for performance */
- nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR;
-// nApIn = *pInputBuffer++; // 1xxx test and debug ap
-
- // fetch allpass delay line out
- //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK);
- nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate allpass feedforward; subtract the feedforward result
- nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain);
- nApOut = SATURATE(nDelayOut - nTemp1); // allpass output
-
- // calculate allpass feedback; add the feedback result
- nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain);
- nTemp1 = SATURATE(nApIn + nTemp1);
-
- // inject into allpass delay
- nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK);
- pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1;
-
- // inject allpass output into delay line
- nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK);
- pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut;
-
- // ********** Left Allpass - end
-
- // ********** Right Allpass - start
- // right input = (right dry/4) + left feedback from previous period
- /*lint -e{702} use shift for performance */
- nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL;
-// nApIn = *pInputBuffer++; // 1xxx test and debug ap
-
- // fetch allpass delay line out
- nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate allpass feedforward; subtract the feedforward result
- nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain);
- nApOut = SATURATE(nDelayOut - nTemp1); // allpass output
-
- // calculate allpass feedback; add the feedback result
- nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain);
- nTemp1 = SATURATE(nApIn + nTemp1);
-
- // inject into allpass delay
- nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK);
- pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1;
-
- // inject allpass output into delay line
- nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK);
- pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut;
-
- // ********** Right Allpass - end
-
- // ********** D0 output - start
- // fetch delay line self out
- nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate delay line self out
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin);
-
- // fetch delay line cross out
- nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate delay line self out
- nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos);
-
- // calculate unfiltered delay out
- nDelayOut = SATURATE(nTemp1 + nTemp2);
-
- // calculate lowpass filter (mixer scale factor included in LPF feedforward)
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd);
-
- nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk);
-
- // calculate filtered delay out and simultaneously update LPF state variable
- // filtered delay output is stored in m_zLpf0
- pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2);
-
- // ********** D0 output - end
-
- // ********** D1 output - start
- // fetch delay line self out
- nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate delay line self out
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin);
-
- // fetch delay line cross out
- nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate delay line self out
- nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos);
-
- // calculate unfiltered delay out
- nDelayOut = SATURATE(nTemp1 + nTemp2);
-
- // calculate lowpass filter (mixer scale factor included in LPF feedforward)
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd);
-
- nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk);
-
- // calculate filtered delay out and simultaneously update LPF state variable
- // filtered delay output is stored in m_zLpf1
- pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2);
-
- // ********** D1 output - end
-
- // ********** mixer and feedback - start
- // sum is fedback to right input (R + L)
- pReverbData->m_nRevOutFbkL =
- (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0);
-
- // difference is feedback to left input (R - L)
- /*lint -e{685} lint complains that it can't saturate negative */
- pReverbData->m_nRevOutFbkR =
- (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0);
-
- // ********** mixer and feedback - end
-
- // ********** start early reflection generator, left
- //psEarly = &(pReverbData->m_sEarlyL);
-
- nEarlyOut = 0;
-
- for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
- {
- // fetch delay line out
- //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK);
- nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK);
-
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate reflection
- //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]);
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]);
-
- nEarlyOut = SATURATE(nEarlyOut + nTemp1);
-
- } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
-
- // apply lowpass to early reflections
- //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd);
- nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd);
-
- //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
- nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk);
-
-
- // calculate filtered out and simultaneously update LPF state variable
- // filtered output is stored in m_zLpf1
- //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2);
- pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2);
-
- // combine filtered early and late reflections for output
- //*pOutputBuffer++ = inL;
- //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL);
- tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL);
- //scale reverb output by wet level
- /*lint -e{701} use shift for performance */
- tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1));
- //sum with output buffer
- tempValue += *pOutputBuffer;
- *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue);
-
- // ********** end early reflection generator, left
-
- // ********** start early reflection generator, right
- //psEarly = &(pReverbData->m_sEarlyR);
-
- nEarlyOut = 0;
-
- for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
- {
- // fetch delay line out
- nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK);
- nDelayOut = pReverbData->m_nDelayLine[nAddr];
-
- // calculate reflection
- nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]);
-
- nEarlyOut = SATURATE(nEarlyOut + nTemp1);
-
- } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
-
- // apply lowpass to early reflections
- nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd);
-
- nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk);
-
- // calculate filtered out and simultaneously update LPF state variable
- // filtered output is stored in m_zLpf1
- pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2);
-
- // combine filtered early and late reflections for output
- //*pOutputBuffer++ = inR;
- tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR);
- //scale reverb output by wet level
- /*lint -e{701} use shift for performance */
- tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1));
- //sum with output buffer
- tempValue = tempValue + *pOutputBuffer;
- *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue);
-
- // ********** end early reflection generator, right
-
- // decrement base addr for next sample period
- nBase--;
-
- pReverbData->m_nSin += pReverbData->m_nSinIncrement;
- pReverbData->m_nCos += pReverbData->m_nCosIncrement;
-
- } // end for (i=0; i < nNumSamplesToAdd; i++)
-
- // store the most up to date version
- pReverbData->m_nBaseIndex = nBase;
-
- return EAS_SUCCESS;
-} /* end Reverb */
-
-
-
-/*----------------------------------------------------------------------------
- * ReverbShutdown()
- *----------------------------------------------------------------------------
- * Purpose:
- * Initializes the Reverb effect.
- *
- * Inputs:
- * pInstData - handle to instance data
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
-{
- /* check Configuration Module for static memory allocation */
- if (!pEASData->staticMemoryModel)
- EAS_HWFree(pEASData->hwInstData, pInstData);
- return EAS_SUCCESS;
-} /* end ReverbShutdown */
-
-/*----------------------------------------------------------------------------
- * ReverbGetParam()
- *----------------------------------------------------------------------------
- * Purpose:
- * Get a Reverb parameter
- *
- * Inputs:
- * pInstData - handle to instance data
- * param - parameter index
- * *pValue - pointer to variable to hold retrieved value
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
-{
- S_REVERB_OBJECT *p;
-
- p = (S_REVERB_OBJECT*) pInstData;
-
- switch (param)
- {
- case EAS_PARAM_REVERB_BYPASS:
- *pValue = (EAS_I32) p->m_bBypass;
- break;
- case EAS_PARAM_REVERB_PRESET:
- *pValue = (EAS_I8) p->m_nCurrentRoom;
- break;
- case EAS_PARAM_REVERB_WET:
- *pValue = p->m_nWet;
- break;
- case EAS_PARAM_REVERB_DRY:
- *pValue = p->m_nDry;
- break;
- default:
- return EAS_ERROR_INVALID_PARAMETER;
- }
- return EAS_SUCCESS;
-} /* end ReverbGetParam */
-
-
-/*----------------------------------------------------------------------------
- * ReverbSetParam()
- *----------------------------------------------------------------------------
- * Purpose:
- * Set a Reverb parameter
- *
- * Inputs:
- * pInstData - handle to instance data
- * param - parameter index
- * *pValue - new paramter value
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
-{
- S_REVERB_OBJECT *p;
-
- p = (S_REVERB_OBJECT*) pInstData;
-
- switch (param)
- {
- case EAS_PARAM_REVERB_BYPASS:
- p->m_bBypass = (EAS_BOOL) value;
- break;
- case EAS_PARAM_REVERB_PRESET:
- if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL &&
- value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM)
- return EAS_ERROR_INVALID_PARAMETER;
- p->m_nNextRoom = (EAS_I16)value;
- break;
- case EAS_PARAM_REVERB_WET:
- if(value>EAS_REVERB_WET_MAX || value<EAS_REVERB_WET_MIN)
- return EAS_ERROR_INVALID_PARAMETER;
- p->m_nWet = (EAS_I16)value;
- break;
- case EAS_PARAM_REVERB_DRY:
- if(value>EAS_REVERB_DRY_MAX || value<EAS_REVERB_DRY_MIN)
- return EAS_ERROR_INVALID_PARAMETER;
- p->m_nDry = (EAS_I16)value;
- break;
- default:
- return EAS_ERROR_INVALID_PARAMETER;
- }
- return EAS_SUCCESS;
-} /* end ReverbSetParam */
-
-
-/*----------------------------------------------------------------------------
- * ReverbUpdateRoom
- *----------------------------------------------------------------------------
- * Purpose:
- * Update the room's preset parameters as required
- *
- * Inputs:
- *
- * Outputs:
- *
- *
- * Side Effects:
- * - reverb paramters (fbk, fwd, etc) will be changed
- * - m_nCurrentRoom := m_nNextRoom
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData)
-{
- EAS_INT temp;
-
- S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom];
-
- pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd;
- pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk;
-
- pReverbData->m_nEarly = pPreset->m_nEarly;
- pReverbData->m_nWet = pPreset->m_nWet;
- pReverbData->m_nDry = pPreset->m_nDry;
-
-
- pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion;
- //stored as time based, convert to sample based
- temp = pPreset->m_nXfadeInterval;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_nXfadeInterval = (EAS_U16) temp;
- //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval;
- pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
- //stored as time based, convert to absolute sample value
- temp = pPreset->m_nAp0_ApOut;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp);
- //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut;
- pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
- //stored as time based, convert to absolute sample value
- temp = pPreset->m_nAp1_ApOut;
- /*lint -e{702} shift for performance */
- temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16;
- pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp);
- //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
-
- pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom;
-
- return EAS_SUCCESS;
-
-} /* end ReverbUpdateRoom */
-
-
-/*----------------------------------------------------------------------------
- * ReverbReadInPresets()
- *----------------------------------------------------------------------------
- * Purpose: sets global reverb preset bank to defaults
- *
- * Inputs:
- *
- * Outputs:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData)
-{
-
- int preset = 0;
- int defaultPreset = 0;
-
- //now init any remaining presets to defaults
- for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++)
- {
- S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset];
- if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1)
- {
- pPreset->m_nLpfFbk = 8307;
- pPreset->m_nLpfFwd = 14768;
- pPreset->m_nEarly = 0;
- pPreset->m_nWet = 27690;
- pPreset->m_nDry = 32767;
- pPreset->m_nEarlyL_LpfFbk = 3692;
- pPreset->m_nEarlyL_LpfFwd = 29075;
- pPreset->m_nEarlyL_Delay0 = 922;
- pPreset->m_nEarlyL_Gain0 = 22152;
- pPreset->m_nEarlyL_Delay1 = 1462;
- pPreset->m_nEarlyL_Gain1 = 17537;
- pPreset->m_nEarlyL_Delay2 = 0;
- pPreset->m_nEarlyL_Gain2 = 14768;
- pPreset->m_nEarlyL_Delay3 = 1221;
- pPreset->m_nEarlyL_Gain3 = 14307;
- pPreset->m_nEarlyL_Delay4 = 0;
- pPreset->m_nEarlyL_Gain4 = 13384;
- pPreset->m_nEarlyR_Delay0 = 502;
- pPreset->m_nEarlyR_Gain0 = 20306;
- pPreset->m_nEarlyR_Delay1 = 1762;
- pPreset->m_nEarlyR_Gain1 = 17537;
- pPreset->m_nEarlyR_Delay2 = 0;
- pPreset->m_nEarlyR_Gain2 = 14768;
- pPreset->m_nEarlyR_Delay3 = 0;
- pPreset->m_nEarlyR_Gain3 = 16153;
- pPreset->m_nEarlyR_Delay4 = 0;
- pPreset->m_nEarlyR_Gain4 = 13384;
- pPreset->m_nMaxExcursion = 127;
- pPreset->m_nXfadeInterval = 6388;
- pPreset->m_nAp0_ApGain = 15691;
- pPreset->m_nAp0_ApOut = 711;
- pPreset->m_nAp1_ApGain = 17999;
- pPreset->m_nAp1_ApOut = 1113;
- pPreset->m_rfu4 = 0;
- pPreset->m_rfu5 = 0;
- pPreset->m_rfu6 = 0;
- pPreset->m_rfu7 = 0;
- pPreset->m_rfu8 = 0;
- pPreset->m_rfu9 = 0;
- pPreset->m_rfu10 = 0;
- }
- else if (defaultPreset == 1)
- {
- pPreset->m_nLpfFbk = 6461;
- pPreset->m_nLpfFwd = 14307;
- pPreset->m_nEarly = 0;
- pPreset->m_nWet = 27690;
- pPreset->m_nDry = 32767;
- pPreset->m_nEarlyL_LpfFbk = 3692;
- pPreset->m_nEarlyL_LpfFwd = 29075;
- pPreset->m_nEarlyL_Delay0 = 922;
- pPreset->m_nEarlyL_Gain0 = 22152;
- pPreset->m_nEarlyL_Delay1 = 1462;
- pPreset->m_nEarlyL_Gain1 = 17537;
- pPreset->m_nEarlyL_Delay2 = 0;
- pPreset->m_nEarlyL_Gain2 = 14768;
- pPreset->m_nEarlyL_Delay3 = 1221;
- pPreset->m_nEarlyL_Gain3 = 14307;
- pPreset->m_nEarlyL_Delay4 = 0;
- pPreset->m_nEarlyL_Gain4 = 13384;
- pPreset->m_nEarlyR_Delay0 = 502;
- pPreset->m_nEarlyR_Gain0 = 20306;
- pPreset->m_nEarlyR_Delay1 = 1762;
- pPreset->m_nEarlyR_Gain1 = 17537;
- pPreset->m_nEarlyR_Delay2 = 0;
- pPreset->m_nEarlyR_Gain2 = 14768;
- pPreset->m_nEarlyR_Delay3 = 0;
- pPreset->m_nEarlyR_Gain3 = 16153;
- pPreset->m_nEarlyR_Delay4 = 0;
- pPreset->m_nEarlyR_Gain4 = 13384;
- pPreset->m_nMaxExcursion = 127;
- pPreset->m_nXfadeInterval = 6391;
- pPreset->m_nAp0_ApGain = 15230;
- pPreset->m_nAp0_ApOut = 708;
- pPreset->m_nAp1_ApGain = 9692;
- pPreset->m_nAp1_ApOut = 1113;
- pPreset->m_rfu4 = 0;
- pPreset->m_rfu5 = 0;
- pPreset->m_rfu6 = 0;
- pPreset->m_rfu7 = 0;
- pPreset->m_rfu8 = 0;
- pPreset->m_rfu9 = 0;
- pPreset->m_rfu10 = 0;
- }
- else if (defaultPreset == 2)
- {
- pPreset->m_nLpfFbk = 5077;
- pPreset->m_nLpfFwd = 12922;
- pPreset->m_nEarly = 0;
- pPreset->m_nWet = 24460;
- pPreset->m_nDry = 32767;
- pPreset->m_nEarlyL_LpfFbk = 3692;
- pPreset->m_nEarlyL_LpfFwd = 29075;
- pPreset->m_nEarlyL_Delay0 = 922;
- pPreset->m_nEarlyL_Gain0 = 22152;
- pPreset->m_nEarlyL_Delay1 = 1462;
- pPreset->m_nEarlyL_Gain1 = 17537;
- pPreset->m_nEarlyL_Delay2 = 0;
- pPreset->m_nEarlyL_Gain2 = 14768;
- pPreset->m_nEarlyL_Delay3 = 1221;
- pPreset->m_nEarlyL_Gain3 = 14307;
- pPreset->m_nEarlyL_Delay4 = 0;
- pPreset->m_nEarlyL_Gain4 = 13384;
- pPreset->m_nEarlyR_Delay0 = 502;
- pPreset->m_nEarlyR_Gain0 = 20306;
- pPreset->m_nEarlyR_Delay1 = 1762;
- pPreset->m_nEarlyR_Gain1 = 17537;
- pPreset->m_nEarlyR_Delay2 = 0;
- pPreset->m_nEarlyR_Gain2 = 14768;
- pPreset->m_nEarlyR_Delay3 = 0;
- pPreset->m_nEarlyR_Gain3 = 16153;
- pPreset->m_nEarlyR_Delay4 = 0;
- pPreset->m_nEarlyR_Gain4 = 13384;
- pPreset->m_nMaxExcursion = 127;
- pPreset->m_nXfadeInterval = 6449;
- pPreset->m_nAp0_ApGain = 15691;
- pPreset->m_nAp0_ApOut = 774;
- pPreset->m_nAp1_ApGain = 15691;
- pPreset->m_nAp1_ApOut = 1113;
- pPreset->m_rfu4 = 0;
- pPreset->m_rfu5 = 0;
- pPreset->m_rfu6 = 0;
- pPreset->m_rfu7 = 0;
- pPreset->m_rfu8 = 0;
- pPreset->m_rfu9 = 0;
- pPreset->m_rfu10 = 0;
- }
- else if (defaultPreset == 3)
- {
- pPreset->m_nLpfFbk = 5077;
- pPreset->m_nLpfFwd = 11076;
- pPreset->m_nEarly = 0;
- pPreset->m_nWet = 23075;
- pPreset->m_nDry = 32767;
- pPreset->m_nEarlyL_LpfFbk = 3692;
- pPreset->m_nEarlyL_LpfFwd = 29075;
- pPreset->m_nEarlyL_Delay0 = 922;
- pPreset->m_nEarlyL_Gain0 = 22152;
- pPreset->m_nEarlyL_Delay1 = 1462;
- pPreset->m_nEarlyL_Gain1 = 17537;
- pPreset->m_nEarlyL_Delay2 = 0;
- pPreset->m_nEarlyL_Gain2 = 14768;
- pPreset->m_nEarlyL_Delay3 = 1221;
- pPreset->m_nEarlyL_Gain3 = 14307;
- pPreset->m_nEarlyL_Delay4 = 0;
- pPreset->m_nEarlyL_Gain4 = 13384;
- pPreset->m_nEarlyR_Delay0 = 502;
- pPreset->m_nEarlyR_Gain0 = 20306;
- pPreset->m_nEarlyR_Delay1 = 1762;
- pPreset->m_nEarlyR_Gain1 = 17537;
- pPreset->m_nEarlyR_Delay2 = 0;
- pPreset->m_nEarlyR_Gain2 = 14768;
- pPreset->m_nEarlyR_Delay3 = 0;
- pPreset->m_nEarlyR_Gain3 = 16153;
- pPreset->m_nEarlyR_Delay4 = 0;
- pPreset->m_nEarlyR_Gain4 = 13384;
- pPreset->m_nMaxExcursion = 127;
- pPreset->m_nXfadeInterval = 6470; //6483;
- pPreset->m_nAp0_ApGain = 14768;
- pPreset->m_nAp0_ApOut = 792;
- pPreset->m_nAp1_ApGain = 15783;
- pPreset->m_nAp1_ApOut = 1113;
- pPreset->m_rfu4 = 0;
- pPreset->m_rfu5 = 0;
- pPreset->m_rfu6 = 0;
- pPreset->m_rfu7 = 0;
- pPreset->m_rfu8 = 0;
- pPreset->m_rfu9 = 0;
- pPreset->m_rfu10 = 0;
-
- }
- }
-
- return EAS_SUCCESS;
-}
+ * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 510 $ + * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_reverbdata.h" +#include "eas_reverb.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Reverb = +{ + ReverbInit, + ReverbProcess, + ReverbShutdown, + ReverbGetParam, + ReverbSetParam +}; + + + +/*---------------------------------------------------------------------------- + * InitializeReverb() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + EAS_I32 i; + EAS_U16 nOffset; + EAS_INT temp; + + S_REVERB_OBJECT *pReverbData; + S_REVERB_PRESET *pPreset; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB); + + /* allocate dynamic memory */ + else + pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT)); + + if (pReverbData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT)); + + ReverbReadInPresets(pReverbData); + + pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES; + + pReverbData->m_nRevOutFbkR = 0; + pReverbData->m_nRevOutFbkL = 0; + + pReverbData->m_sAp0.m_zApIn = AP0_IN; + pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH; + pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN; + + pReverbData->m_zD0In = DELAY0_IN; + + pReverbData->m_sAp1.m_zApIn = AP1_IN; + pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH; + pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN; + + pReverbData->m_zD1In = DELAY1_IN; + + pReverbData->m_zLpf0 = 0; + pReverbData->m_zLpf1 = 0; + pReverbData->m_nLpfFwd = 8837; + pReverbData->m_nLpfFbk = 6494; + + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 0; + pReverbData->m_nSinIncrement = 0; + pReverbData->m_nCosIncrement = 0; + + // set xfade parameters + pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES; + pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration + pReverbData->m_nPhase = -32768; + pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT; + + pReverbData->m_nNoise = (EAS_I16)0xABCD; + + pReverbData->m_nMaxExcursion = 0x007F; + + // set delay tap lengths + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + // for debugging purposes, allow noise generator + pReverbData->m_bUseNoise = EAS_FALSE; + + // for debugging purposes, allow bypass + pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE; + + pReverbData->m_nNextRoom = 1; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration + + pReverbData->m_nWet = REVERB_DEFAULT_WET; + + pReverbData->m_nDry = REVERB_DEFAULT_DRY; + + // set base index into circular buffer + pReverbData->m_nBaseIndex = 0; + + // set the early reflections, L + pReverbData->m_sEarlyL.m_nLpfFbk = 4915; + pReverbData->m_sEarlyL.m_nLpfFwd = 27852; + pReverbData->m_sEarlyL.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyL.m_nGain[i] = 0; + pReverbData->m_sEarlyL.m_zDelay[i] = 0; + } + + // set the early reflections, R + pReverbData->m_sEarlyR.m_nLpfFbk = 4915; + pReverbData->m_sEarlyR.m_nLpfFwd = 27852; + pReverbData->m_sEarlyR.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyR.m_nGain[i] = 0; + pReverbData->m_sEarlyR.m_zDelay[i] = 0; + } + + // clear the reverb delay line + for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++) + { + pReverbData->m_nDelayLine[i] = 0; + } + + //////////////////////////////// + ///code from the EAS DEMO Reverb + //now copy from the new preset into the reverb + pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; + + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + ///code from the EAS DEMO Reverb + //////////////////////////////// + + *pInstData = pReverbData; + + return EAS_SUCCESS; + +} /* end InitializeReverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbProcess() + *---------------------------------------------------------------------------- + * Purpose: + * Reverberate the requested number of samples (block based processing) + * + * Inputs: + * pInputBuffer - src buffer + * pOutputBuffer - dst buffer + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + S_REVERB_OBJECT *pReverbData; + + pReverbData = (S_REVERB_OBJECT*) pInstData; + + //if bypassed or the preset forces the signal to be completely dry + if (pReverbData->m_bBypass || + (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767)) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom) + { + ReverbUpdateRoom(pReverbData); + } + + ReverbUpdateXfade(pReverbData, numSamples); + + Reverb(pReverbData, numSamples, pDst, pSrc); + + /* check if update counter needs to be reset */ + if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nUpdateCounter = 0; + } /* end if m_nUpdateCounter >= update interval */ + + /* increment update counter */ + pReverbData->m_nUpdateCounter += (EAS_I16)numSamples; + +} /* end ComputeReverb */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd) +{ + EAS_U16 nOffset; + EAS_I16 tempCos; + EAS_I16 tempSin; + + if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nXfadeCounter = 0; + + // Pin the sin,cos values to min / max values to ensure that the + // modulated taps' coefs are zero (thus no clicks) + if (pReverbData->m_nPhaseIncrement > 0) + { + // if phase increment > 0, then sin -> 1, cos -> 0 + pReverbData->m_nSin = 32767; + pReverbData->m_nCos = 0; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = 32767; + + // modulate the cross taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + } + else + { + // if phase increment < 0, then sin -> 0, cos -> 1 + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 32767; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = -32768; + + // modulate the self taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + } // end if-else (pReverbData->m_nPhaseIncrement > 0) + + // Reverse the direction of the sin,cos so that the + // tap whose coef was previously increasing now decreases + // and vice versa + pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement; + + } // end if counter >= update interval + + //compute what phase will be next time + pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement; + + //calculate what the new sin and cos need to reach by the next update + ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos); + + //calculate the per-sample increment required to get there by the next update + /*lint -e{702} shift for performance */ + pReverbData->m_nSinIncrement = + (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS; + + /*lint -e{702} shift for performance */ + pReverbData->m_nCosIncrement = + (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS; + + + /* increment update counter */ + pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd; + + return EAS_SUCCESS; + +} /* end ReverbUpdateXfade */ + + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise) +{ + // calculate new noise value + *pnNoise = (EAS_I16) (*pnNoise * 5 + 1); + +#if 0 // 1xxx, test + *pnNoise = 0; +#endif // 1xxx, test + + // return the limited noise value + return (nMaxExcursion & (*pnNoise)); + +} /* end ReverbCalculateNoise */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos) +{ + EAS_I32 nTemp; + EAS_I32 nNetAngle; + + // -1 <= nPhase < 1 + // However, for the calculation, we need a value + // that ranges from -1/2 to +1/2, so divide the phase by 2 + /*lint -e{702} shift for performance */ + nNetAngle = nPhase >> 1; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* limit the input "angle" to be between -0.5 and +0.5 */ + if (nNetAngle > EG1_HALF) + { + nNetAngle = EG1_HALF; + } + else if (nNetAngle < EG1_MINUS_HALF) + { + nNetAngle = EG1_MINUS_HALF; + } + + /* calculate sin */ + nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnSin = (EAS_I16) SATURATE_EG1(nTemp); + + /* calculate cos */ + nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnCos = (EAS_I16) SATURATE_EG1(nTemp); + + return EAS_SUCCESS; +} /* end ReverbCalculateSinCos */ + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer) +{ + EAS_I32 i; + EAS_I32 nDelayOut; + EAS_U16 nBase; + + EAS_U32 nAddr; + EAS_I32 nTemp1; + EAS_I32 nTemp2; + EAS_I32 nApIn; + EAS_I32 nApOut; + + EAS_I32 j; + EAS_I32 nEarlyOut; + + EAS_I32 tempValue; + + + // get the base address + nBase = pReverbData->m_nBaseIndex; + + for (i=0; i < nNumSamplesToAdd; i++) + { + // ********** Left Allpass - start + // left input = (left dry/4) + right feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Left Allpass - end + + // ********** Right Allpass - start + // right input = (right dry/4) + left feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Right Allpass - end + + // ********** D0 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf0 + pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // ********** D0 output - end + + // ********** D1 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf1 + pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // ********** D1 output - end + + // ********** mixer and feedback - start + // sum is fedback to right input (R + L) + pReverbData->m_nRevOutFbkL = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0); + + // difference is feedback to left input (R - L) + /*lint -e{685} lint complains that it can't saturate negative */ + pReverbData->m_nRevOutFbkR = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0); + + // ********** mixer and feedback - end + + // ********** start early reflection generator, left + //psEarly = &(pReverbData->m_sEarlyL); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK); + + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]); + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd); + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd); + + //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk); + + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2); + pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inL; + //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL); + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1)); + //sum with output buffer + tempValue += *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, left + + // ********** start early reflection generator, right + //psEarly = &(pReverbData->m_sEarlyR); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inR; + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1)); + //sum with output buffer + tempValue = tempValue + *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, right + + // decrement base addr for next sample period + nBase--; + + pReverbData->m_nSin += pReverbData->m_nSinIncrement; + pReverbData->m_nCos += pReverbData->m_nCosIncrement; + + } // end for (i=0; i < nNumSamplesToAdd; i++) + + // store the most up to date version + pReverbData->m_nBaseIndex = nBase; + + return EAS_SUCCESS; +} /* end Reverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Reverb effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ReverbShutdown */ + +/*---------------------------------------------------------------------------- + * ReverbGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + *pValue = (EAS_I32) p->m_bBypass; + break; + case EAS_PARAM_REVERB_PRESET: + *pValue = (EAS_I8) p->m_nCurrentRoom; + break; + case EAS_PARAM_REVERB_WET: + *pValue = p->m_nWet; + break; + case EAS_PARAM_REVERB_DRY: + *pValue = p->m_nDry; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbGetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + p->m_bBypass = (EAS_BOOL) value; + break; + case EAS_PARAM_REVERB_PRESET: + if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL && + value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextRoom = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_WET: + if(value>EAS_REVERB_WET_MAX || value<EAS_REVERB_WET_MIN) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nWet = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_DRY: + if(value>EAS_REVERB_DRY_MAX || value<EAS_REVERB_DRY_MIN) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nDry = (EAS_I16)value; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbSetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData) +{ + EAS_INT temp; + + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval; + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom; + + return EAS_SUCCESS; + +} /* end ReverbUpdateRoom */ + + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) + { + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1) + { + pPreset->m_nLpfFbk = 8307; + pPreset->m_nLpfFwd = 14768; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6388; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 711; + pPreset->m_nAp1_ApGain = 17999; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 1) + { + pPreset->m_nLpfFbk = 6461; + pPreset->m_nLpfFwd = 14307; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6391; + pPreset->m_nAp0_ApGain = 15230; + pPreset->m_nAp0_ApOut = 708; + pPreset->m_nAp1_ApGain = 9692; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 2) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 12922; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 24460; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6449; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 774; + pPreset->m_nAp1_ApGain = 15691; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 3) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 11076; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 23075; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6470; //6483; + pPreset->m_nAp0_ApGain = 14768; + pPreset->m_nAp0_ApOut = 792; + pPreset->m_nAp1_ApGain = 15783; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + + } + } + + return EAS_SUCCESS; +} |