970 lines
29 KiB
C++
970 lines
29 KiB
C++
/*******************************************************************************
|
|
* ReverbFX.cpp *
|
|
*-------------*
|
|
* Description:
|
|
* This module is the implementation file for the CReverbFX class.
|
|
*-------------------------------------------------------------------------------
|
|
* Created By: mc Date: 03/12/99
|
|
* Copyright (C) 1999 Microsoft Corporation
|
|
* All Rights Reserved
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#ifndef __spttseng_h__
|
|
#include "spttseng.h"
|
|
#endif
|
|
#ifndef SPDebug_h
|
|
#include <spdebug.h>
|
|
#endif
|
|
#ifndef ReverbFX_H
|
|
#include "ReverbFX.h"
|
|
#endif
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::DecibelToPercent *
|
|
*-----------------------------*
|
|
* Description:
|
|
* Converts Voltage percentage from dB
|
|
* v = 10^(dB/20)
|
|
*
|
|
********************************************************************** MC ***/
|
|
REVERBL CReverbFX::DecibelToPercent( float flDecibel )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::DecibelToPercent" );
|
|
float fltIntVol;
|
|
|
|
if( flDecibel >= REVERB_MIN_DB )
|
|
{
|
|
fltIntVol = (float) pow( 10.0, (double)flDecibel / 20.0 );
|
|
}
|
|
else
|
|
{
|
|
fltIntVol = 0.0;
|
|
}
|
|
|
|
#ifdef FLOAT_REVERB
|
|
return fltIntVol;
|
|
#else
|
|
fltIntVol = fltIntVol * REVERB_VOL_LEVELS;
|
|
return (REVERBL)fltIntVol;
|
|
#endif
|
|
} /* CReverbFX::DecibelToPercent */
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::ClearReverb *
|
|
*------------------------*
|
|
* Description:
|
|
* Fills the delay line with silence.
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::ClearReverb( LP_Reverb_Mod mod )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::ClearReverb" );
|
|
long i;
|
|
REVERBT *dPtr;
|
|
|
|
dPtr = mod->psDelayBuffer;
|
|
for( i = 0; i < mod->dwDelayBufferSize; i++ )
|
|
{
|
|
*dPtr++ = 0;
|
|
}
|
|
} /* CReverbFX::ClearReverb */
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::AllocReverbModule *
|
|
*------------------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
short CReverbFX::AllocReverbModule
|
|
(
|
|
LP_Reverb_Mod mod,
|
|
REVERBL lGain, // Gain of the amplifiers.
|
|
long dwDelay, // Length of the delay line.
|
|
long dwDelayBufferSize // Size of the delay buffer.
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::AllocReverbModule" );
|
|
short result;
|
|
|
|
|
|
result = KREVERB_NOERROR;
|
|
mod->lGain = lGain;
|
|
mod->dwDelay = dwDelay;
|
|
mod->dwDelayBufferSize = dwDelayBufferSize;
|
|
mod->psDelayBuffer = new REVERBT[mod->dwDelayBufferSize];
|
|
if( mod->psDelayBuffer == NULL )
|
|
{
|
|
result = KREVERB_MEMERROR;
|
|
}
|
|
else
|
|
{
|
|
mod->psDelayEnd = mod->psDelayBuffer + mod->dwDelayBufferSize;
|
|
mod->psDelayOut = mod->psDelayBuffer;
|
|
if( mod->dwDelayBufferSize == mod->dwDelay )
|
|
{
|
|
mod->psDelayIn = mod->psDelayBuffer;
|
|
}
|
|
else
|
|
{
|
|
mod->psDelayIn = mod->psDelayBuffer + mod->dwDelay;
|
|
}
|
|
ClearReverb( mod );
|
|
}
|
|
|
|
return result;
|
|
} /* CReverbFX::AllocReverbModule */
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::CreateReverbModules *
|
|
*--------------------------------*
|
|
* Description:
|
|
* Creates an array of reverb modules.
|
|
*
|
|
********************************************************************** MC ***/
|
|
short CReverbFX::CreateReverbModules
|
|
(
|
|
short wModules, // Number of modules to create.
|
|
LP_Reverb_Mod *mods,
|
|
float * pfltDelay, // Array of delay values for the modules.
|
|
float * pfltDB, // Array of gain values for the modules.
|
|
float fltSamplesPerMS // Number of samples per millisecond.
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::CreateReverbModules" );
|
|
long dwDelay, i;
|
|
float tempF;
|
|
REVERBL vol;
|
|
short result = KREVERB_NOERROR;
|
|
|
|
|
|
if( wModules > 0 )
|
|
{
|
|
for( i = 0; i < wModules; i++ )
|
|
{
|
|
mods[i] = new Reverb_Mod;
|
|
if( !mods[i] )
|
|
{
|
|
//---------------------------------------
|
|
// Not enough memory
|
|
//---------------------------------------
|
|
result = KREVERB_MEMERROR;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
tempF = *pfltDelay++ * fltSamplesPerMS;
|
|
dwDelay = (long) tempF;
|
|
if( dwDelay < 2 )
|
|
dwDelay = 2; // @@@@
|
|
vol = DecibelToPercent( *pfltDB++ );
|
|
result = AllocReverbModule( mods[i], vol, dwDelay, dwDelay );
|
|
if( result != KREVERB_NOERROR )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
} /* CReverbFX::CreateReverbModules */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::DeleteReverbModules *
|
|
*--------------------------------*
|
|
* Description:
|
|
* Deletes an array of reverb modules.
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::DeleteReverbModules( )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::DeleteReverbModules" );
|
|
long i;
|
|
|
|
for( i = 0; i < KMAXREVBMODS; i++ )
|
|
{
|
|
if( m_Reverb_Mods[i] != NULL )
|
|
{
|
|
if( m_Reverb_Mods[i]->psDelayBuffer != NULL )
|
|
{
|
|
delete m_Reverb_Mods[i]->psDelayBuffer;
|
|
}
|
|
delete m_Reverb_Mods[i];
|
|
m_Reverb_Mods[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if( m_pWorkBuf != NULL )
|
|
{
|
|
delete m_pWorkBuf;
|
|
m_pWorkBuf = NULL;
|
|
}
|
|
} /* CReverbFX::DeleteReverbModules */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::GetReverbConfig *
|
|
*----------------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
LPREVERBCONFIG CReverbFX::GetReverbConfig( REVERBTYPE dwReverbConfig )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::GetReverbConfig" );
|
|
LPREVERBCONFIG pReverbConfig = NULL;
|
|
|
|
switch( dwReverbConfig )
|
|
{
|
|
//-----------------------------
|
|
// Hall
|
|
//-----------------------------
|
|
case REVERB_TYPE_HALL:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(float)(30.6), (float)(20.83), (float)(14.85), (float)(10.98) };
|
|
static float afltLeftGain[] = { (float)(-2.498), (float)(-2.2533), (float)(-2.7551), (float)(-2.5828) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(-17.0), // Wet
|
|
(-2.0), // Dry
|
|
4,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
//-----------------------------
|
|
// Stadium
|
|
//-----------------------------
|
|
case REVERB_TYPE_STADIUM:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(40.6*4), (float)(27.65*4), (float)(17.85*4), (float)(10.98*4) };
|
|
static float afltLeftGain[] = { (float)(-2.498), (float)(-2.2533), (float)(-2.7551), (float)(-2.5828) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(-3.0), // Wet
|
|
(-5.0), // Dry
|
|
4,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
//-----------------------------
|
|
// Church
|
|
//-----------------------------
|
|
case REVERB_TYPE_CHURCH:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(40.6*2), (float)(27.65*2), (float)(17.85*2), (float)(10.98*2) };
|
|
static float afltLeftGain[] = { (float)(-2.498), (float)(-2.2533), (float)(-2.7551), (float)(-2.5828) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(-5.0), // Wet
|
|
(-5.0), // Dry
|
|
4,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
|
|
//-----------------------------
|
|
// Bathtub
|
|
//-----------------------------
|
|
case REVERB_TYPE_BATHTUB:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(10.0) };
|
|
static float afltLeftGain[] = { (float)(-0.5) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(7.0), // Wet
|
|
(9.0), // Dry
|
|
1,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
//-----------------------------
|
|
// Room
|
|
//-----------------------------
|
|
case REVERB_TYPE_ROOM:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(10.6) };
|
|
static float afltLeftGain[] = { (float)(-10.498) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(0.0), // Wet
|
|
(0.0), // Dry
|
|
1,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
//-----------------------------
|
|
// Echo
|
|
//-----------------------------
|
|
case REVERB_TYPE_ECHO:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(400.6) };
|
|
static float afltLeftGain[] = { (float)(-10.498) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(-10.0), // Wet
|
|
(0.0), // Dry
|
|
1,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.0,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
//-----------------------------
|
|
// Sequencer
|
|
//-----------------------------
|
|
case REVERB_TYPE_ROBOSEQ:
|
|
{
|
|
static float afltLeftDelay[] = { (float)(10.0) };
|
|
static float afltLeftGain[] = { (float)(-0.5) };
|
|
|
|
static REVERBCONFIG reverbConfig =
|
|
{
|
|
(6.5), // Wet
|
|
(9.0), // Dry
|
|
1,
|
|
afltLeftDelay,
|
|
afltLeftGain,
|
|
(float)0.05,
|
|
};
|
|
|
|
pReverbConfig = &reverbConfig;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return pReverbConfig;
|
|
} /* CReverbFX::GetReverbConfig */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::Reverb_Init *
|
|
*------------------------*
|
|
* Description:
|
|
* Initialize a reverberator array.
|
|
*
|
|
********************************************************************** MC ***/
|
|
short CReverbFX::Reverb_Init( REVERBTYPE reverbPreset, long nSamplesPerSec, long stereoOut )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::Reverb_Init" );
|
|
short result = KREVERB_NOERROR;
|
|
float fltSamplesPerMS;
|
|
|
|
|
|
m_StereoOut = stereoOut;
|
|
if( reverbPreset > REVERB_TYPE_OFF )
|
|
{
|
|
//----------------------------------------------
|
|
// Get params from preset number
|
|
//----------------------------------------------
|
|
m_pReverbConfig = GetReverbConfig( reverbPreset );
|
|
m_numOfMods = m_pReverbConfig->numOfReflect;
|
|
|
|
//----------------------------------------------
|
|
// Convert dB's to linear gain
|
|
//----------------------------------------------
|
|
m_wetVolGain = DecibelToPercent( m_pReverbConfig->wetGain_dB );
|
|
m_dryVolGain = DecibelToPercent( m_pReverbConfig->dryGain_dB );
|
|
|
|
fltSamplesPerMS = (float)nSamplesPerSec / (float)1000.0;
|
|
|
|
result = CreateReverbModules
|
|
(
|
|
(short)m_numOfMods,
|
|
(LP_Reverb_Mod*)&m_Reverb_Mods,
|
|
m_pReverbConfig->gain_ms_Array,
|
|
m_pReverbConfig->gain_dB_Array,
|
|
fltSamplesPerMS
|
|
);
|
|
if( result != KREVERB_NOERROR )
|
|
{
|
|
//--------------------------------
|
|
// Failure! Not enough memory
|
|
//--------------------------------
|
|
return result;
|
|
}
|
|
|
|
if( m_pWorkBuf == NULL )
|
|
{
|
|
m_pWorkBuf = new REVERBT[m_dwWorkBufferSize];
|
|
if( m_pWorkBuf == NULL )
|
|
{
|
|
//--------------------------------
|
|
// Failure! Not enough memory
|
|
//--------------------------------
|
|
result = KREVERB_MEMERROR;
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DeleteReverbModules( );
|
|
result = KREVERB_OFF;
|
|
}
|
|
return result;
|
|
} /* CReverbFX::Reverb_Init */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::CReverbFX *
|
|
*----------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
CReverbFX::CReverbFX( void )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::CReverbFX" );
|
|
long i;
|
|
|
|
//--------------------------------
|
|
// Initilize
|
|
//--------------------------------
|
|
m_dwWorkBufferSize = KWORKBUFLEN;
|
|
m_pWorkBuf = NULL;
|
|
m_wetVolGain = 0;
|
|
m_dryVolGain = 0;
|
|
m_numOfMods = 0;
|
|
m_Count = 0;
|
|
m_StereoOut = false;
|
|
for( i = 0; i < KMAXREVBMODS; i++ )
|
|
{
|
|
m_Reverb_Mods[i] = NULL;
|
|
}
|
|
} /* CReverbFX::CReverbFX */
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::~CReverbFX *
|
|
*-----------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
CReverbFX::~CReverbFX( void )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::~CReverbFX" );
|
|
DeleteReverbModules( );
|
|
} /* CReverbFX::~CReverbFX */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
// Run-time
|
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::CopyWithGain *
|
|
*-------------------------*
|
|
* Description:
|
|
* Copies audio buffer with gain
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::CopyWithGain
|
|
( REVERBT *psDest,
|
|
REVERBT *psSource,
|
|
long dwSamples,
|
|
REVERBL gain)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::CopyWithGain" );
|
|
|
|
if( gain <= REVERB_VOL_OFF )
|
|
{
|
|
//----------------------------------------
|
|
// Clear buffer, gain = 0
|
|
//----------------------------------------
|
|
memset( psDest, 0, sizeof(REVERBT) * dwSamples );
|
|
}
|
|
else if( gain == REVERB_VOL_UNITY )
|
|
{
|
|
//----------------------------------------
|
|
// Copy buffer, gain = 1
|
|
//----------------------------------------
|
|
memcpy( psDest, psSource, sizeof(REVERBT) * dwSamples );
|
|
}
|
|
else
|
|
{
|
|
//----------------------------------------
|
|
// Copy with gain
|
|
//----------------------------------------
|
|
while( dwSamples )
|
|
{
|
|
#ifdef FLOAT_REVERB
|
|
*psDest++ = (*psSource++) * gain;
|
|
#else
|
|
*psDest++ = (short) (( (long)(*psSource++) * (long)gain) >> REVERB_VOL_SHIFT);
|
|
#endif
|
|
dwSamples--;
|
|
}
|
|
}
|
|
} /* CReverbFX::CopyWithGain */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::MixWithGain_MONO *
|
|
*-----------------------------*
|
|
* Description:
|
|
* (psDest * gain) + psSource -> psDest
|
|
* Clipping is performed.
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::MixWithGain_MONO
|
|
(
|
|
REVERBT *pWet,
|
|
REVERBT *pDry,
|
|
short *pDest,
|
|
long dwSamples,
|
|
REVERBL gain
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::MixWithGain_MONO" );
|
|
REVERBL lSample; // long or float
|
|
|
|
if( gain <= REVERB_VOL_OFF )
|
|
{
|
|
//----------------------------------
|
|
// Do nothing...I guess
|
|
//----------------------------------
|
|
}
|
|
else if( gain == REVERB_VOL_UNITY )
|
|
{
|
|
//----------------------------------
|
|
// Don't apply any gain (= 1.0)
|
|
//----------------------------------
|
|
while( dwSamples )
|
|
{
|
|
lSample = (REVERBL)(*pWet++) + *pDry;
|
|
//------------------------------------
|
|
// Clip signal if overflow
|
|
//------------------------------------
|
|
if( lSample < -32768 )
|
|
{
|
|
lSample = -32768;
|
|
}
|
|
else if( lSample > 32767 )
|
|
{
|
|
lSample = 32767;
|
|
}
|
|
*pDest++ = (short)lSample;
|
|
|
|
pDry++;
|
|
dwSamples--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while( dwSamples )
|
|
{
|
|
//----------------------------------
|
|
// Mix with gain on source audio
|
|
//----------------------------------
|
|
#ifdef FLOAT_REVERB
|
|
lSample = ((*pDry) * gain) + *pWet++;
|
|
#else
|
|
lSample = ((long)(*pDry * (long)(gain)) >> REVERB_VOL_SHIFT) + *pWet++;
|
|
#endif
|
|
//------------------------------------
|
|
// Clip signal if overflow
|
|
//------------------------------------
|
|
if( lSample < -32768 )
|
|
{
|
|
lSample = -32768;
|
|
}
|
|
else if( lSample > 32767 )
|
|
{
|
|
lSample = 32767;
|
|
}
|
|
*pDest++ = (short)lSample;
|
|
|
|
pDry++;
|
|
dwSamples--;
|
|
}
|
|
}
|
|
} /* CReverbFX::MixWithGain_MONO */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::MixWithGain_STEREO *
|
|
*-------------------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::MixWithGain_STEREO
|
|
(
|
|
REVERBT *pWet,
|
|
REVERBT *pDry,
|
|
short *pDest,
|
|
long dwSamples,
|
|
REVERBL gain
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::MixWithGain_STEREO" );
|
|
REVERBL lSample, hold; // long or float
|
|
REVERBL lSample_B; // long or float
|
|
|
|
if( gain <= REVERB_VOL_OFF )
|
|
{
|
|
//----------------------------------
|
|
// Do nothing...I guess
|
|
//----------------------------------
|
|
}
|
|
else if( gain == REVERB_VOL_UNITY )
|
|
{
|
|
//----------------------------------
|
|
// Don't apply any gain (= 1.0)
|
|
//----------------------------------
|
|
while( dwSamples )
|
|
{
|
|
lSample = (REVERBL)(*pWet++) + (*pDry++);
|
|
//------------------------------------
|
|
// Clip signal if overflow
|
|
//------------------------------------
|
|
if( lSample < -32768 )
|
|
{
|
|
lSample = -32768;
|
|
}
|
|
else if( lSample > 32767 )
|
|
{
|
|
lSample = 32767;
|
|
}
|
|
*pDest++ = (short)lSample;
|
|
*pDest++ = (short)(0 - (short)lSample);
|
|
dwSamples--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while( dwSamples )
|
|
{
|
|
//----------------------------------
|
|
// Mix with gain on source audio
|
|
//----------------------------------
|
|
#ifdef FLOAT_REVERB
|
|
hold = ((*pDry) * gain);
|
|
lSample = hold + *pWet;
|
|
lSample_B = hold - *pWet++;
|
|
//lSample_B = 0 - lSample_B;
|
|
//lSample_B = (0 - hold) - *pWet++;
|
|
#else
|
|
lSample = ((long)(*pDry * (long)(gain)) >> REVERB_VOL_SHIFT) + *pWet;
|
|
lSample_B = ((long)(*pDry * (long)(gain)) >> REVERB_VOL_SHIFT) - *pWet++;
|
|
#endif
|
|
//------------------------------------
|
|
// Clip signal if overflow
|
|
//------------------------------------
|
|
if( lSample < -32768 )
|
|
{
|
|
lSample = -32768;
|
|
}
|
|
else if( lSample > 32767 )
|
|
{
|
|
lSample = 32767;
|
|
}
|
|
*pDest++ = (short)lSample;
|
|
|
|
if( lSample < -32768 )
|
|
{
|
|
lSample = -32768;
|
|
}
|
|
else if( lSample > 32767 )
|
|
{
|
|
lSample = 32767;
|
|
}
|
|
*pDest++ = (short)lSample_B;
|
|
|
|
pDry++;
|
|
dwSamples--;
|
|
}
|
|
}
|
|
} /* CReverbFX::MixWithGain_STEREO */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::ProcessReverbModule *
|
|
*-------------------*
|
|
* Description:
|
|
* Process one delay buffer
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::ProcessReverbModule
|
|
(
|
|
LP_Reverb_Mod mod,
|
|
long dwDestSamples, // Number of samples to process.
|
|
REVERBT *pSource, // Source sample buffer.
|
|
REVERBT *pDestination // Destination sample buffer.
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::ProcessReverbModule" );
|
|
REVERBT sDelayOut;
|
|
REVERBT sDelayIn;
|
|
REVERBT *psDelayEnd;
|
|
|
|
//(void) QueryPerformanceCounter (&g_StartTime );
|
|
|
|
psDelayEnd = mod->psDelayBuffer + (long)((float)mod->dwDelayBufferSize * m_LenScale);
|
|
dwDestSamples++;
|
|
while( --dwDestSamples )
|
|
{
|
|
//----------------------------------------
|
|
// Delay + current --> delay buffer
|
|
//----------------------------------------
|
|
sDelayOut = *mod->psDelayOut;
|
|
#ifdef FLOAT_REVERB
|
|
sDelayIn = (sDelayOut * mod->lGain) + *pSource;
|
|
//------------------------------------------------------------
|
|
// Take this test out and you'll die in about 10 sec...
|
|
//------------------------------------------------------------
|
|
if( sDelayIn > 0)
|
|
{
|
|
if( sDelayIn < 0.001 )
|
|
sDelayIn = 0;
|
|
}
|
|
else if( sDelayIn > -0.001 )
|
|
{
|
|
sDelayIn = 0;
|
|
}
|
|
#else
|
|
sDelayIn = ((sDelayOut * mod->lGain) >> REVERB_VOL_SHIFT) + *pSource;
|
|
#endif
|
|
*mod->psDelayIn++ = sDelayIn;
|
|
|
|
//----------------------------------------
|
|
// Delay - (Delay + current) --> current
|
|
//----------------------------------------
|
|
#ifdef FLOAT_REVERB
|
|
*pDestination = sDelayOut - (sDelayIn * mod->lGain);
|
|
#else
|
|
*pDestination = sDelayOut - ((sDelayIn * mod->lGain) >> REVERB_VOL_SHIFT);
|
|
#endif
|
|
|
|
//---------------------------------------
|
|
// Wrap circular buffer ptrs
|
|
//---------------------------------------
|
|
if( mod->psDelayIn >= psDelayEnd )
|
|
{
|
|
mod->psDelayIn = mod->psDelayBuffer;
|
|
}
|
|
mod->psDelayOut++;
|
|
if( mod->psDelayOut >= psDelayEnd )
|
|
{
|
|
mod->psDelayOut = mod->psDelayBuffer;
|
|
}
|
|
pSource++;
|
|
pDestination++;
|
|
}
|
|
//(void) QueryPerformanceCounter (&g_EndTime);
|
|
//g_LapseTime.QuadPart = (g_EndTime.QuadPart - g_StartTime.QuadPart);
|
|
} /* CReverbFX::ProcessReverbModule */
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Applies an array of reverb modules to a block of samples.
|
|
//----------------------------------------------------------------------------
|
|
/*****************************************************************************
|
|
* CReverbFX::ProcessReverbBuffer *
|
|
*--------------------------------*
|
|
* Description:
|
|
* Applies an array of reverb modules to a block of samples.
|
|
*
|
|
********************************************************************** MC ***/
|
|
void CReverbFX::ProcessReverbBuffer
|
|
( REVERBT *psSample, // Samples to process (in/out).
|
|
long dwSamples, // Number of samples to process.
|
|
LP_Reverb_Mod *mods // Array of modules to apply.
|
|
)
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::ProcessReverbBuffer" );
|
|
short i;
|
|
|
|
for (i = 0; i < KMAXREVBMODS; i++)
|
|
{
|
|
if( mods[i] != NULL )
|
|
{
|
|
ProcessReverbModule( mods[i], dwSamples, psSample, psSample );
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
} /* CReverbFX::ProcessReverbBuffer */
|
|
|
|
|
|
/*****************************************************************************
|
|
* CReverbFX::Reverb_Process *
|
|
*---------------------------*
|
|
* Description:
|
|
*
|
|
********************************************************************** MC ***/
|
|
short CReverbFX::Reverb_Process( float *sampleBuffer,
|
|
long dwSamplesRemaining, float audioGain )
|
|
{
|
|
SPDBG_FUNC( "CReverbFX::Reverb_Process" );
|
|
long dwSamplesToProcess;
|
|
short *pOutBuffer;
|
|
REVERBL totalWetGain, totalDryGain;
|
|
|
|
if( m_numOfMods )
|
|
{
|
|
#ifdef FLOAT_REVERB
|
|
totalWetGain = m_wetVolGain * audioGain;
|
|
if (totalWetGain < REVERB_MIN_MIX)
|
|
totalWetGain = REVERB_MIN_MIX;
|
|
totalDryGain = m_dryVolGain * audioGain;
|
|
if (totalDryGain < REVERB_MIN_MIX)
|
|
totalDryGain = REVERB_MIN_MIX;
|
|
#else
|
|
totalWetGain = (REVERBL)(m_wetVolGain * audioGain * (float)REVERB_VOL_LEVELS);
|
|
totalDryGain = (REVERBL)(m_dryVolGain * audioGain * (float)REVERB_VOL_LEVELS);
|
|
#endif
|
|
pOutBuffer = (short*)sampleBuffer;
|
|
m_LenScale = (float)1.0 - (m_Count * m_pReverbConfig->seqIndex);
|
|
|
|
while( dwSamplesRemaining > 0 )
|
|
{
|
|
//----------------------------------------------------------------------------
|
|
// Process client's buffer using 'work buffer' chunks
|
|
//----------------------------------------------------------------------------
|
|
if( dwSamplesRemaining < m_dwWorkBufferSize )
|
|
{
|
|
dwSamplesToProcess = dwSamplesRemaining;
|
|
}
|
|
else
|
|
{
|
|
dwSamplesToProcess = m_dwWorkBufferSize;
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
// Copy audio into WET buffer with wet gain
|
|
// sampleBuffer * totalWetGain --> m_pWorkBuf
|
|
//-----------------------------------------------------------------
|
|
CopyWithGain( m_pWorkBuf, sampleBuffer, dwSamplesToProcess, totalWetGain );
|
|
|
|
//-----------------------------------------------------------------
|
|
// Perform reverb processing on the work buffer
|
|
//-----------------------------------------------------------------
|
|
ProcessReverbBuffer
|
|
(
|
|
m_pWorkBuf,
|
|
dwSamplesToProcess,
|
|
(LP_Reverb_Mod*)&m_Reverb_Mods
|
|
);
|
|
|
|
//-----------------------------------------------------------------
|
|
// Mix the dry with wet samples
|
|
// (sampleBuffer * totalDryGain) + m_pWorkBuf --> sampleBuffer
|
|
//-----------------------------------------------------------------
|
|
if( m_StereoOut )
|
|
{
|
|
MixWithGain_STEREO( m_pWorkBuf, sampleBuffer, pOutBuffer, dwSamplesToProcess, totalDryGain );
|
|
pOutBuffer += dwSamplesToProcess * 2;
|
|
}
|
|
else
|
|
{
|
|
MixWithGain_MONO( m_pWorkBuf, sampleBuffer, pOutBuffer, dwSamplesToProcess, totalDryGain );
|
|
pOutBuffer += dwSamplesToProcess;
|
|
}
|
|
|
|
sampleBuffer += dwSamplesToProcess;
|
|
dwSamplesRemaining -= dwSamplesToProcess;
|
|
}
|
|
}
|
|
|
|
m_Count = (float)rand() / (float)4096; // 0 - 32K -> 0 - 8
|
|
|
|
return 0;
|
|
} /* CReverbFX::Reverb_Process */
|
|
|