speed optimizations
This commit is contained in:
parent
85d37b53b5
commit
55c680e6fd
7 changed files with 186 additions and 172 deletions
106
src/client.cpp
106
src/client.cpp
|
@ -27,7 +27,8 @@
|
|||
|
||||
/* Implementation *************************************************************/
|
||||
CClient::CClient ( const quint16 iPortNumber ) : bRun ( false ),
|
||||
iSndCrdBlockSizeSam ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES ),
|
||||
iSndCrdMonoBlockSizeSam ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES ),
|
||||
iSndCrdStereoBlockSizeSam ( 2 * MIN_SND_CRD_BLOCK_SIZE_SAMPLES ),
|
||||
Sound ( MIN_SND_CRD_BLOCK_SIZE_SAMPLES * 2 /* stereo */ ),
|
||||
Socket ( &Channel, iPortNumber ),
|
||||
iAudioInFader ( AUD_FADER_IN_MAX / 2 ),
|
||||
|
@ -172,30 +173,27 @@ void CClient::OnProtocolStatus ( bool bOk )
|
|||
void CClient::Init()
|
||||
{
|
||||
// set block size (in samples)
|
||||
iBlockSizeSam = MIN_BLOCK_SIZE_SAMPLES;
|
||||
iMonoBlockSizeSam = MIN_BLOCK_SIZE_SAMPLES;
|
||||
iStereoBlockSizeSam = 2 * MIN_BLOCK_SIZE_SAMPLES;
|
||||
|
||||
vecsAudioSndCrd.Init ( iSndCrdBlockSizeSam * 2 ); // stereo
|
||||
vecdAudioSndCrdL.Init ( iSndCrdBlockSizeSam );
|
||||
vecdAudioSndCrdR.Init ( iSndCrdBlockSizeSam );
|
||||
vecsAudioSndCrd.Init ( iSndCrdStereoBlockSizeSam );
|
||||
vecdAudioSndCrd.Init ( iSndCrdStereoBlockSizeSam );
|
||||
|
||||
vecdAudioL.Init ( iBlockSizeSam );
|
||||
vecdAudioR.Init ( iBlockSizeSam );
|
||||
vecdAudio.Init ( iStereoBlockSizeSam );
|
||||
|
||||
Sound.InitRecording();
|
||||
Sound.InitPlayback();
|
||||
|
||||
// resample objects are always initialized with the input block size
|
||||
// record
|
||||
ResampleObjDownL.Init ( iSndCrdBlockSizeSam, SND_CRD_SAMPLE_RATE, SYSTEM_SAMPLE_RATE );
|
||||
ResampleObjDownR.Init ( iSndCrdBlockSizeSam, SND_CRD_SAMPLE_RATE, SYSTEM_SAMPLE_RATE );
|
||||
ResampleObjDown.Init ( iSndCrdMonoBlockSizeSam, SND_CRD_SAMPLE_RATE, SYSTEM_SAMPLE_RATE );
|
||||
|
||||
// playback
|
||||
ResampleObjUpL.Init ( iBlockSizeSam, SYSTEM_SAMPLE_RATE, SND_CRD_SAMPLE_RATE );
|
||||
ResampleObjUpR.Init ( iBlockSizeSam, SYSTEM_SAMPLE_RATE, SND_CRD_SAMPLE_RATE );
|
||||
ResampleObjUp.Init ( iMonoBlockSizeSam, SYSTEM_SAMPLE_RATE, SND_CRD_SAMPLE_RATE );
|
||||
|
||||
// init network buffers
|
||||
vecsNetwork.Init ( iBlockSizeSam );
|
||||
vecdNetwData.Init ( iBlockSizeSam );
|
||||
vecsNetwork.Init ( iMonoBlockSizeSam );
|
||||
vecdNetwData.Init ( iMonoBlockSizeSam );
|
||||
|
||||
// init moving average buffer for response time evaluation
|
||||
RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE );
|
||||
|
@ -208,7 +206,7 @@ void CClient::Init()
|
|||
|
||||
void CClient::run()
|
||||
{
|
||||
int i, iInCnt;
|
||||
int i, j;
|
||||
|
||||
// Set thread priority (The working thread should have a higher
|
||||
// priority than the GUI)
|
||||
|
@ -242,7 +240,7 @@ void CClient::run()
|
|||
}
|
||||
|
||||
|
||||
// runtime phase ------------------------------------------------------------
|
||||
// runtime phase -----------------------------------------------------------
|
||||
// enable channel
|
||||
Channel.SetEnable ( true );
|
||||
|
||||
|
@ -261,21 +259,17 @@ void CClient::run()
|
|||
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
|
||||
}
|
||||
|
||||
// copy data from one stereo buffer in two separate buffers
|
||||
iInCnt = 0;
|
||||
for ( i = 0; i < iSndCrdBlockSizeSam; i++ )
|
||||
// convert data from short to double
|
||||
for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ )
|
||||
{
|
||||
vecdAudioSndCrdL[i] = (double) vecsAudioSndCrd[iInCnt++];
|
||||
vecdAudioSndCrdR[i] = (double) vecsAudioSndCrd[iInCnt++];
|
||||
vecdAudioSndCrd[i] = (double) vecsAudioSndCrd[i];
|
||||
}
|
||||
|
||||
// resample data for each channel seaparately
|
||||
ResampleObjDownL.Resample ( vecdAudioSndCrdL, vecdAudioL );
|
||||
ResampleObjDownR.Resample ( vecdAudioSndCrdR, vecdAudioR );
|
||||
ResampleObjDown.Resample ( vecdAudioSndCrd, vecdAudio );
|
||||
|
||||
// update signal level meters
|
||||
SignalLevelMeterL.Update ( vecdAudioL );
|
||||
SignalLevelMeterR.Update ( vecdAudioR );
|
||||
// update stereo signal level meter
|
||||
SignalLevelMeter.Update ( vecdAudio );
|
||||
|
||||
// add reverberation effect if activated
|
||||
if ( iReverbLevel != 0 )
|
||||
|
@ -285,44 +279,47 @@ void CClient::run()
|
|||
|
||||
if ( bReverbOnLeftChan )
|
||||
{
|
||||
for ( i = 0; i < iBlockSizeSam; i++ )
|
||||
for ( i = 0; i < iStereoBlockSizeSam; i += 2 )
|
||||
{
|
||||
// left channel
|
||||
vecdAudioL[i] +=
|
||||
dRevLev * AudioReverb.ProcessSample ( vecdAudioL[i] );
|
||||
vecdAudio[i] +=
|
||||
dRevLev * AudioReverb.ProcessSample ( vecdAudio[i] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < iBlockSizeSam; i++ )
|
||||
for ( i = 1; i < iStereoBlockSizeSam; i += 2 )
|
||||
{
|
||||
// right channel
|
||||
vecdAudioR[i] +=
|
||||
dRevLev * AudioReverb.ProcessSample ( vecdAudioR[i] );
|
||||
vecdAudio[i] +=
|
||||
dRevLev * AudioReverb.ProcessSample ( vecdAudio[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mix both signals depending on the fading setting
|
||||
const int iMiddleOfFader = AUD_FADER_IN_MAX / 2;
|
||||
const int iMiddleOfFader = AUD_FADER_IN_MAX / 2;
|
||||
const double dAttFact =
|
||||
(double) ( iMiddleOfFader - abs ( iMiddleOfFader - iAudioInFader ) ) /
|
||||
iMiddleOfFader;
|
||||
|
||||
for ( i = 0; i < iBlockSizeSam; i++ )
|
||||
if ( iAudioInFader > iMiddleOfFader )
|
||||
{
|
||||
double dMixedSignal;
|
||||
|
||||
if ( iAudioInFader > iMiddleOfFader )
|
||||
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
||||
{
|
||||
dMixedSignal = vecdAudioL[i] + dAttFact * vecdAudioR[i];
|
||||
// attenuation on right channel
|
||||
vecsNetwork[i] =
|
||||
Double2Short ( vecdAudio[j] + dAttFact * vecdAudio[j + 1] );
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
||||
{
|
||||
dMixedSignal = vecdAudioR[i] + dAttFact * vecdAudioL[i];
|
||||
// attenuation on left channel
|
||||
vecsNetwork[i] =
|
||||
Double2Short ( vecdAudio[j + 1] + dAttFact * vecdAudio[j] );
|
||||
}
|
||||
|
||||
vecsNetwork[i] = Double2Short ( dMixedSignal );
|
||||
}
|
||||
|
||||
// send it through the network
|
||||
|
@ -344,7 +341,7 @@ void CClient::run()
|
|||
// fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid);
|
||||
static FILE* pFileDelay = fopen("v.dat", "wb");
|
||||
short sData[2];
|
||||
for (i = 0; i < iBlockSizeSam; i++)
|
||||
for (i = 0; i < iMonoBlockSizeSam; i++)
|
||||
{
|
||||
sData[0] = (short) vecdNetwData[i];
|
||||
fwrite(&sData, size_t(2), size_t(1), pFileDelay);
|
||||
|
@ -356,30 +353,24 @@ fflush(pFileDelay);
|
|||
if ( Channel.IsConnected() )
|
||||
{
|
||||
// write mono input signal in both sound-card channels
|
||||
for ( i = 0; i < iBlockSizeSam; i++ )
|
||||
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
||||
{
|
||||
vecdAudioL[i] = vecdAudioR[i] = vecdNetwData[i];
|
||||
vecdAudio[j] = vecdAudio[j + 1] = vecdNetwData[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not connected, clear data
|
||||
for ( i = 0; i < iBlockSizeSam; i++ )
|
||||
{
|
||||
vecdAudioL[i] = vecdAudioR[i] = 0.0;
|
||||
}
|
||||
vecdAudio.Reset ( 0.0 );
|
||||
}
|
||||
|
||||
// resample data for each channel separately
|
||||
ResampleObjUpL.Resample ( vecdAudioL, vecdAudioSndCrdL );
|
||||
ResampleObjUpR.Resample ( vecdAudioR, vecdAudioSndCrdR );
|
||||
// resample data
|
||||
ResampleObjUp.Resample ( vecdAudio, vecdAudioSndCrd );
|
||||
|
||||
// copy data from one stereo buffer in two separate buffers
|
||||
iInCnt = 0;
|
||||
for ( i = 0; i < iSndCrdBlockSizeSam; i++ )
|
||||
// convert data from double to short type
|
||||
for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ )
|
||||
{
|
||||
vecsAudioSndCrd[iInCnt++] = Double2Short ( vecdAudioSndCrdL[i] );
|
||||
vecsAudioSndCrd[iInCnt++] = Double2Short ( vecdAudioSndCrdR[i] );
|
||||
vecsAudioSndCrd[i] = Double2Short ( vecdAudioSndCrd[i] );
|
||||
}
|
||||
|
||||
// play the new block
|
||||
|
@ -404,8 +395,7 @@ fflush(pFileDelay);
|
|||
Sound.Close();
|
||||
|
||||
// reset current signal level and LEDs
|
||||
SignalLevelMeterL.Reset();
|
||||
SignalLevelMeterR.Reset();
|
||||
SignalLevelMeter.Reset();
|
||||
PostWinMessage ( MS_RESET_ALL, 0 );
|
||||
}
|
||||
|
||||
|
|
71
src/client.h
71
src/client.h
|
@ -68,8 +68,8 @@ public:
|
|||
bool Stop();
|
||||
bool IsRunning() { return bRun; }
|
||||
bool SetServerAddr ( QString strNAddr );
|
||||
double MicLevelL() { return SignalLevelMeterL.MicLevel(); }
|
||||
double MicLevelR() { return SignalLevelMeterR.MicLevel(); }
|
||||
double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); }
|
||||
double MicLevelR() { return SignalLevelMeter.MicLevelRight(); }
|
||||
bool IsConnected() { return Channel.IsConnected(); }
|
||||
|
||||
/* We want to return the standard deviation. For that we need to calculate
|
||||
|
@ -143,59 +143,54 @@ public:
|
|||
|
||||
|
||||
// settings
|
||||
QString strIPAddress;
|
||||
QString strName;
|
||||
QString strIPAddress;
|
||||
QString strName;
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
void UpdateTimeResponseMeasurement();
|
||||
void UpdateSocketBufferSize();
|
||||
virtual void run();
|
||||
void UpdateTimeResponseMeasurement();
|
||||
void UpdateSocketBufferSize();
|
||||
|
||||
// only one channel is needed for client application
|
||||
CChannel Channel;
|
||||
bool bDoAutoSockBufSize;
|
||||
CChannel Channel;
|
||||
bool bDoAutoSockBufSize;
|
||||
|
||||
CSocket Socket;
|
||||
CSound Sound;
|
||||
CSignalLevelMeter SignalLevelMeterL;
|
||||
CSignalLevelMeter SignalLevelMeterR;
|
||||
CSocket Socket;
|
||||
CSound Sound;
|
||||
CStereoSignalLevelMeter SignalLevelMeter;
|
||||
|
||||
bool bRun;
|
||||
CVector<double> vecdNetwData;
|
||||
bool bRun;
|
||||
CVector<double> vecdNetwData;
|
||||
|
||||
int iAudioInFader;
|
||||
bool bReverbOnLeftChan;
|
||||
int iReverbLevel;
|
||||
CAudioReverb AudioReverb;
|
||||
int iAudioInFader;
|
||||
bool bReverbOnLeftChan;
|
||||
int iReverbLevel;
|
||||
CAudioReverb AudioReverb;
|
||||
|
||||
int iSndCrdBlockSizeSam;
|
||||
int iBlockSizeSam;
|
||||
int iSndCrdMonoBlockSizeSam;
|
||||
int iSndCrdStereoBlockSizeSam;
|
||||
int iMonoBlockSizeSam;
|
||||
int iStereoBlockSizeSam;
|
||||
|
||||
int iNetwBufSizeFactIn;
|
||||
int iNetwBufSizeFactIn;
|
||||
|
||||
bool bOpenChatOnNewMessage;
|
||||
bool bOpenChatOnNewMessage;
|
||||
|
||||
CVector<short> vecsAudioSndCrd;
|
||||
CVector<double> vecdAudioSndCrdL;
|
||||
CVector<double> vecdAudioSndCrdR;
|
||||
|
||||
CVector<double> vecdAudioL;
|
||||
CVector<double> vecdAudioR;
|
||||
|
||||
CVector<short> vecsNetwork;
|
||||
CVector<short> vecsAudioSndCrd;
|
||||
CVector<double> vecdAudioSndCrd;
|
||||
CVector<double> vecdAudio;
|
||||
CVector<short> vecsNetwork;
|
||||
|
||||
// resample objects
|
||||
CAudioResample ResampleObjDownL; // left channel
|
||||
CAudioResample ResampleObjDownR; // right channel
|
||||
CAudioResample ResampleObjUpL; // left channel
|
||||
CAudioResample ResampleObjUpR; // right channel
|
||||
CStereoAudioResample ResampleObjDown;
|
||||
CStereoAudioResample ResampleObjUp;
|
||||
|
||||
// for ping measurement and standard deviation of audio interface
|
||||
CPreciseTime PreciseTime;
|
||||
CPreciseTime PreciseTime;
|
||||
|
||||
// debugging, evaluating
|
||||
CMovingAv<double> RespTimeMoAvBuf;
|
||||
int TimeLastBlock;
|
||||
CMovingAv<double> RespTimeMoAvBuf;
|
||||
int TimeLastBlock;
|
||||
|
||||
public slots:
|
||||
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2008
|
||||
* Copyright (c) 2004-2009
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
|
@ -92,10 +92,6 @@
|
|||
// (just search for the tag in the entire code)
|
||||
#define MAX_NUM_CHANNELS 6 // max number channels for server
|
||||
|
||||
// sample rate offset estimation algorithm
|
||||
// time interval for sample rate offset estimation
|
||||
#define TIME_INT_SAM_OFFS_EST 60 // s
|
||||
|
||||
// length of the moving average buffer for response time measurement
|
||||
#define TIME_MOV_AV_RESPONSE 30 // seconds
|
||||
#define LEN_MOV_AV_RESPONSE ( TIME_MOV_AV_RESPONSE * 1000 / MIN_BLOCK_DURATION_MS )
|
||||
|
|
|
@ -86,7 +86,7 @@ int CResample::Resample ( CVector<double>& vecdInput,
|
|||
// convolution
|
||||
double dy1 = 0.0;
|
||||
double dy2 = 0.0;
|
||||
for (int i = 0; i < NUM_TAPS_PER_PHASE1; i++)
|
||||
for ( int i = 0; i < NUM_TAPS_PER_PHASE1; i++ )
|
||||
{
|
||||
dy1 += fResTaps1[ip1 * INTERP_DECIM_I_D1 + i] * vecdIntBuff[in1 - i];
|
||||
dy2 += fResTaps1[ip2 * INTERP_DECIM_I_D1 + i] * vecdIntBuff[in2 - i];
|
||||
|
@ -134,10 +134,10 @@ void CResample::Init ( const int iNewInputBlockSize )
|
|||
|
||||
|
||||
/******************************************************************************\
|
||||
* Audio Resampler *
|
||||
* Stereo Audio Resampler *
|
||||
\******************************************************************************/
|
||||
void CAudioResample::Resample ( CVector<double>& vecdInput,
|
||||
CVector<double>& vecdOutput )
|
||||
void CStereoAudioResample::Resample ( CVector<double>& vecdInput,
|
||||
CVector<double>& vecdOutput )
|
||||
{
|
||||
int j;
|
||||
|
||||
|
@ -148,50 +148,58 @@ void CAudioResample::Resample ( CVector<double>& vecdInput,
|
|||
}
|
||||
else
|
||||
{
|
||||
const int iTwoTimesNumTaps = 2 * iNumTaps;
|
||||
|
||||
/* move old data from the end to the history part of the buffer and
|
||||
add new data (shift register) */
|
||||
// shift old values
|
||||
int iMovLen = iInputBlockSize;
|
||||
for ( j = 0; j < iNumTaps; j++ )
|
||||
int iMovLen = iStereoInputBlockSize;
|
||||
for ( j = 0; j < iTwoTimesNumTaps; j++ )
|
||||
{
|
||||
vecdIntBuff[j] = vecdIntBuff[iMovLen++];
|
||||
}
|
||||
|
||||
// add new block of data
|
||||
int iBlockEnd = iNumTaps;
|
||||
for ( j = 0; j < iInputBlockSize; j++ )
|
||||
int iBlockEnd = iTwoTimesNumTaps;
|
||||
for ( j = 0; j < iStereoInputBlockSize; j++ )
|
||||
{
|
||||
vecdIntBuff[iBlockEnd++] = vecdInput[j];
|
||||
}
|
||||
|
||||
// main loop
|
||||
for ( j = 0; j < iOutputBlockSize; j++ )
|
||||
for ( j = 0; j < iMonoOutputBlockSize; j++ )
|
||||
{
|
||||
// calculate filter phase
|
||||
const int ip = (int) ( j * iI / dRation ) % iI;
|
||||
|
||||
// sample position in input vector
|
||||
const int in = (int) ( j / dRation ) + iNumTaps - 1;
|
||||
// sample position in stereo input vector
|
||||
const int in = 2 * ( (int) ( j / dRation ) + iNumTaps - 1 );
|
||||
|
||||
// convolution
|
||||
double dy = 0.0;
|
||||
double dyL = 0.0;
|
||||
double dyR = 0.0;
|
||||
for ( int i = 0; i < iNumTaps; i++ )
|
||||
{
|
||||
dy += pFiltTaps[ip + i * iI] * vecdIntBuff[in - i];
|
||||
const double dCurFiltTap = pFiltTaps[ip + i * iI];
|
||||
const int iCurSamplePos = in - 2 * i;
|
||||
|
||||
dyL += dCurFiltTap * vecdIntBuff[iCurSamplePos];
|
||||
dyR += dCurFiltTap * vecdIntBuff[iCurSamplePos + 1];
|
||||
}
|
||||
|
||||
vecdOutput[j] = dy;
|
||||
vecdOutput[2 * j] = dyL;
|
||||
vecdOutput[2 * j + 1] = dyR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAudioResample::Init ( const int iNewInputBlockSize,
|
||||
const int iFrom,
|
||||
const int iTo )
|
||||
void CStereoAudioResample::Init ( const int iNewMonoInputBlockSize,
|
||||
const int iFrom,
|
||||
const int iTo )
|
||||
{
|
||||
dRation = ( (double) iTo ) / iFrom;
|
||||
iInputBlockSize = iNewInputBlockSize;
|
||||
iOutputBlockSize = (int) ( iInputBlockSize * dRation );
|
||||
dRation = ( (double) iTo ) / iFrom;
|
||||
iStereoInputBlockSize = 2 * iNewMonoInputBlockSize;
|
||||
iMonoOutputBlockSize = (int) ( iNewMonoInputBlockSize * dRation );
|
||||
|
||||
// set correct parameters
|
||||
if ( iFrom == SND_CRD_SAMPLE_RATE ) // downsampling case
|
||||
|
@ -205,22 +213,22 @@ void CAudioResample::Init ( const int iNewInputBlockSize,
|
|||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 7 / 12 ): // 48 kHz to 28 kHz
|
||||
pFiltTaps = fResTaps12_7;
|
||||
iNumTaps = INTERP_I_12_7 * NUM_TAPS_PER_PHASE12_7;
|
||||
iI = DECIM_D_12_7;
|
||||
pFiltTaps = fResTaps12_7;
|
||||
iNumTaps = INTERP_I_12_7 * NUM_TAPS_PER_PHASE12_7;
|
||||
iI = DECIM_D_12_7;
|
||||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 2 / 3 ): // 48 kHz to 32 kHz
|
||||
pFiltTaps = fResTaps3_2;
|
||||
iNumTaps = INTERP_I_3_2 * NUM_TAPS_PER_PHASE3_2;
|
||||
iI = DECIM_D_3_2;
|
||||
pFiltTaps = fResTaps3_2;
|
||||
iNumTaps = INTERP_I_3_2 * NUM_TAPS_PER_PHASE3_2;
|
||||
iI = DECIM_D_3_2;
|
||||
break;
|
||||
|
||||
case SND_CRD_SAMPLE_RATE: // 48 kHz to 48 kHz
|
||||
// no resampling needed
|
||||
pFiltTaps = NULL;
|
||||
iNumTaps = 0;
|
||||
iI = 1;
|
||||
pFiltTaps = NULL;
|
||||
iNumTaps = 0;
|
||||
iI = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -234,21 +242,21 @@ void CAudioResample::Init ( const int iNewInputBlockSize,
|
|||
switch ( iFrom )
|
||||
{
|
||||
case ( SND_CRD_SAMPLE_RATE / 2 ): // 24 kHz to 48 kHz
|
||||
pFiltTaps = fResTaps2;
|
||||
iNumTaps = DECIM_D_2 * NUM_TAPS_PER_PHASE2;
|
||||
iI = INTERP_I_2;
|
||||
pFiltTaps = fResTaps2;
|
||||
iNumTaps = DECIM_D_2 * NUM_TAPS_PER_PHASE2;
|
||||
iI = INTERP_I_2;
|
||||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 7 / 12 ): // 28 kHz to 48 kHz
|
||||
pFiltTaps = fResTaps12_7;
|
||||
iNumTaps = DECIM_D_12_7 * NUM_TAPS_PER_PHASE12_7;
|
||||
iI = INTERP_I_12_7;
|
||||
pFiltTaps = fResTaps12_7;
|
||||
iNumTaps = DECIM_D_12_7 * NUM_TAPS_PER_PHASE12_7;
|
||||
iI = INTERP_I_12_7;
|
||||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 2 / 3 ): // 32 kHz to 48 kHz
|
||||
pFiltTaps = fResTaps3_2;
|
||||
iNumTaps = DECIM_D_3_2 * NUM_TAPS_PER_PHASE3_2;
|
||||
iI = INTERP_I_3_2;
|
||||
pFiltTaps = fResTaps3_2;
|
||||
iNumTaps = DECIM_D_3_2 * NUM_TAPS_PER_PHASE3_2;
|
||||
iI = INTERP_I_3_2;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -258,6 +266,8 @@ void CAudioResample::Init ( const int iNewInputBlockSize,
|
|||
}
|
||||
}
|
||||
|
||||
// allocate memory for internal buffer, clear sample history
|
||||
vecdIntBuff.Init ( iInputBlockSize + iNumTaps, 0.0 );
|
||||
// allocate memory for internal buffer, clear sample history (we have
|
||||
// to consider stereo data here -> two times the number of taps of
|
||||
// additional memory is required)
|
||||
vecdIntBuff.Init ( iStereoInputBlockSize + 2 * iNumTaps, 0.0 );
|
||||
}
|
||||
|
|
|
@ -52,27 +52,27 @@ protected:
|
|||
int iInputBlockSize;
|
||||
};
|
||||
|
||||
class CAudioResample
|
||||
class CStereoAudioResample
|
||||
{
|
||||
public:
|
||||
CAudioResample() {}
|
||||
virtual ~CAudioResample() {}
|
||||
CStereoAudioResample() {}
|
||||
virtual ~CStereoAudioResample() {}
|
||||
|
||||
void Init ( const int iNewInputBlockSize, const int iFrom, const int iTo );
|
||||
void Init ( const int iNewMonoInputBlockSize, const int iFrom, const int iTo );
|
||||
void Resample ( CVector<double>& vecdInput, CVector<double>& vecdOutput );
|
||||
|
||||
protected:
|
||||
double dRation;
|
||||
double dRation;
|
||||
|
||||
CVector<double> vecdIntBuff;
|
||||
int iHistorySize;
|
||||
CVector<double> vecdIntBuff;
|
||||
int iHistorySize;
|
||||
|
||||
int iInputBlockSize;
|
||||
int iOutputBlockSize;
|
||||
int iStereoInputBlockSize;
|
||||
int iMonoOutputBlockSize;
|
||||
|
||||
float* pFiltTaps;
|
||||
int iNumTaps;
|
||||
int iI;
|
||||
float* pFiltTaps;
|
||||
int iNumTaps;
|
||||
int iI;
|
||||
};
|
||||
|
||||
|
||||
|
|
38
src/util.cpp
38
src/util.cpp
|
@ -27,10 +27,10 @@
|
|||
|
||||
/* Implementation *************************************************************/
|
||||
// Input level meter implementation --------------------------------------------
|
||||
void CSignalLevelMeter::Update ( CVector<double>& vecdAudio )
|
||||
void CStereoSignalLevelMeter::Update ( CVector<double>& vecdAudio )
|
||||
{
|
||||
// get the vector size
|
||||
const int iVecSize = vecdAudio.Size();
|
||||
// get the stereo vector size
|
||||
const int iStereoVecSize = vecdAudio.Size();
|
||||
|
||||
// Get maximum of current block
|
||||
//
|
||||
|
@ -43,15 +43,29 @@ void CSignalLevelMeter::Update ( CVector<double>& vecdAudio )
|
|||
// special cases but for the average music signals the following code
|
||||
// should give good results.
|
||||
//
|
||||
double dMax = 0.0;
|
||||
for ( int i = 0; i < iVecSize; i += 3 )
|
||||
double dMaxL = 0.0;
|
||||
double dMaxR = 0.0;
|
||||
for ( int i = 0; i < iStereoVecSize; i += 6 ) // 2 * 3 = 6 -> stereo
|
||||
{
|
||||
if ( dMax < vecdAudio[i] )
|
||||
// left channel
|
||||
if ( dMaxL < vecdAudio[i] )
|
||||
{
|
||||
dMax = vecdAudio[i];
|
||||
dMaxL = vecdAudio[i];
|
||||
}
|
||||
|
||||
// right channel
|
||||
if ( dMaxR < vecdAudio[i + 1] )
|
||||
{
|
||||
dMaxR = vecdAudio[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
dCurLevelL = UpdateCurLevel ( dCurLevelL, dMaxL );
|
||||
dCurLevelR = UpdateCurLevel ( dCurLevelR, dMaxR );
|
||||
}
|
||||
|
||||
double CStereoSignalLevelMeter::UpdateCurLevel ( double dCurLevel, const double& dMax )
|
||||
{
|
||||
// decrease max with time
|
||||
if ( dCurLevel >= METER_FLY_BACK )
|
||||
{
|
||||
|
@ -66,13 +80,17 @@ void CSignalLevelMeter::Update ( CVector<double>& vecdAudio )
|
|||
// update current level -> only use maximum
|
||||
if ( dMax > dCurLevel )
|
||||
{
|
||||
dCurLevel = dMax;
|
||||
return dMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dCurLevel;
|
||||
}
|
||||
}
|
||||
|
||||
double CSignalLevelMeter::MicLevel()
|
||||
double CStereoSignalLevelMeter::CalcLogResult ( const double& dLinearLevel )
|
||||
{
|
||||
const double dNormMicLevel = dCurLevel / _MAXSHORT;
|
||||
const double dNormMicLevel = dLinearLevel / _MAXSHORT;
|
||||
|
||||
// logarithmic measure
|
||||
if ( dNormMicLevel > 0 )
|
||||
|
|
23
src/util.h
23
src/util.h
|
@ -356,19 +356,24 @@ public slots:
|
|||
|
||||
|
||||
/* Other Classes **************************************************************/
|
||||
// Signal Level Meter ----------------------------------------------------------
|
||||
class CSignalLevelMeter
|
||||
// Stereo Signal Level Meter ---------------------------------------------------
|
||||
class CStereoSignalLevelMeter
|
||||
{
|
||||
public:
|
||||
CSignalLevelMeter() : dCurLevel ( 0.0 ) {}
|
||||
virtual ~CSignalLevelMeter() {}
|
||||
CStereoSignalLevelMeter() { Reset(); }
|
||||
virtual ~CStereoSignalLevelMeter() {}
|
||||
|
||||
void Update ( CVector<double>& vecdAudio );
|
||||
double MicLevel();
|
||||
void Reset() { dCurLevel = 0.0; }
|
||||
void Update ( CVector<double>& vecdAudio );
|
||||
double MicLevelLeft() { return CalcLogResult ( dCurLevelL ); }
|
||||
double MicLevelRight() { return CalcLogResult ( dCurLevelR ); }
|
||||
void Reset() { dCurLevelL = 0.0; dCurLevelR = 0.0; }
|
||||
|
||||
protected:
|
||||
double dCurLevel;
|
||||
double CalcLogResult ( const double& dLinearLevel );
|
||||
double UpdateCurLevel ( double dCurLevel, const double& dMax );
|
||||
|
||||
double dCurLevelL;
|
||||
double dCurLevelR;
|
||||
};
|
||||
|
||||
class CHostAddress
|
||||
|
@ -409,7 +414,7 @@ class CAudioReverb
|
|||
public:
|
||||
CAudioReverb ( const double rT60 = (double) 5.0 );
|
||||
|
||||
void Clear();
|
||||
void Clear();
|
||||
double ProcessSample ( const double input );
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in a new issue