diff --git a/src/client.cpp b/src/client.cpp index 038e725a..a877af2c 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -176,10 +176,11 @@ void CClient::Init() iMonoBlockSizeSam = MIN_BLOCK_SIZE_SAMPLES; iStereoBlockSizeSam = 2 * MIN_BLOCK_SIZE_SAMPLES; - vecsAudioSndCrd.Init ( iSndCrdStereoBlockSizeSam ); - vecdAudioSndCrd.Init ( iSndCrdStereoBlockSizeSam ); + vecsAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam ); + vecdAudioSndCrdMono.Init ( iSndCrdMonoBlockSizeSam ); + vecdAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam ); - vecdAudio.Init ( iStereoBlockSizeSam ); + vecdAudioStereo.Init ( iStereoBlockSizeSam ); Sound.InitRecording(); Sound.InitPlayback(); @@ -250,7 +251,7 @@ void CClient::run() while ( bRun ) { // get audio from sound card (blocking function) - if ( Sound.Read ( vecsAudioSndCrd ) ) + if ( Sound.Read ( vecsAudioSndCrdStereo ) ) { PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED ); } @@ -262,14 +263,14 @@ void CClient::run() // convert data from short to double for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ ) { - vecdAudioSndCrd[i] = (double) vecsAudioSndCrd[i]; + vecdAudioSndCrdStereo[i] = (double) vecsAudioSndCrdStereo[i]; } // resample data for each channel seaparately - ResampleObjDown.Resample ( vecdAudioSndCrd, vecdAudio ); + ResampleObjDown.ResampleStereo ( vecdAudioSndCrdStereo, vecdAudioStereo ); // update stereo signal level meter - SignalLevelMeter.Update ( vecdAudio ); + SignalLevelMeter.Update ( vecdAudioStereo ); // add reverberation effect if activated if ( iReverbLevel != 0 ) @@ -282,8 +283,8 @@ void CClient::run() for ( i = 0; i < iStereoBlockSizeSam; i += 2 ) { // left channel - vecdAudio[i] += - dRevLev * AudioReverb.ProcessSample ( vecdAudio[i] ); + vecdAudioStereo[i] += + dRevLev * AudioReverb.ProcessSample ( vecdAudioStereo[i] ); } } else @@ -291,25 +292,24 @@ void CClient::run() for ( i = 1; i < iStereoBlockSizeSam; i += 2 ) { // right channel - vecdAudio[i] += - dRevLev * AudioReverb.ProcessSample ( vecdAudio[i] ); + vecdAudioStereo[i] += + dRevLev * AudioReverb.ProcessSample ( vecdAudioStereo[i] ); } } } // mix both signals depending on the fading setting - const int iMiddleOfFader = AUD_FADER_IN_MAX / 2; const double dAttFact = - (double) ( iMiddleOfFader - abs ( iMiddleOfFader - iAudioInFader ) ) / - iMiddleOfFader; + (double) ( AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) / + AUD_FADER_IN_MIDDLE; - if ( iAudioInFader > iMiddleOfFader ) + if ( iAudioInFader > AUD_FADER_IN_MIDDLE ) { for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 ) { // attenuation on right channel vecsNetwork[i] = - Double2Short ( vecdAudio[j] + dAttFact * vecdAudio[j + 1] ); + Double2Short ( vecdAudioStereo[j] + dAttFact * vecdAudioStereo[j + 1] ); } } else @@ -318,7 +318,7 @@ void CClient::run() { // attenuation on left channel vecsNetwork[i] = - Double2Short ( vecdAudio[j + 1] + dAttFact * vecdAudio[j] ); + Double2Short ( vecdAudioStereo[j + 1] + dAttFact * vecdAudioStereo[j] ); } } @@ -352,29 +352,25 @@ fflush(pFileDelay); // check if channel is connected if ( Channel.IsConnected() ) { - // write mono input signal in both sound-card channels - for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 ) + // resample data + ResampleObjUp.ResampleMono ( vecdNetwData, vecdAudioSndCrdMono ); + + // convert data from double to short type and copy mono + // received data in both sound card channels + for ( i = 0, j = 0; i < iSndCrdMonoBlockSizeSam; i++, j += 2 ) { - vecdAudio[j] = vecdAudio[j + 1] = vecdNetwData[i]; + vecsAudioSndCrdStereo[j] = vecsAudioSndCrdStereo[j + 1] = + Double2Short ( vecdAudioSndCrdMono[i] ); } } else { // if not connected, clear data - vecdAudio.Reset ( 0.0 ); - } - - // resample data - ResampleObjUp.Resample ( vecdAudio, vecdAudioSndCrd ); - - // convert data from double to short type - for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ ) - { - vecsAudioSndCrd[i] = Double2Short ( vecdAudioSndCrd[i] ); + vecsAudioSndCrdStereo.Reset ( 0 ); } // play the new block - if ( Sound.Write ( vecsAudioSndCrd ) ) + if ( Sound.Write ( vecsAudioSndCrdStereo ) ) { PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED ); } diff --git a/src/client.h b/src/client.h index f8ad6ed6..911c8c3b 100755 --- a/src/client.h +++ b/src/client.h @@ -49,7 +49,9 @@ /* Definitions ****************************************************************/ // audio in fader range +#define AUD_FADER_IN_MIN 0 #define AUD_FADER_IN_MAX 100 +#define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 ) // audio reverberation range #define AUD_REVERB_MAX 100 @@ -176,9 +178,10 @@ protected: bool bOpenChatOnNewMessage; - CVector vecsAudioSndCrd; - CVector vecdAudioSndCrd; - CVector vecdAudio; + CVector vecsAudioSndCrdStereo; + CVector vecdAudioSndCrdMono; + CVector vecdAudioSndCrdStereo; + CVector vecdAudioStereo; CVector vecsNetwork; // resample objects diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp index 2c556bf2..1edd53df 100755 --- a/src/llconclientdlg.cpp +++ b/src/llconclientdlg.cpp @@ -115,7 +115,7 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent, // init slider controls --- // audio in fader - SliderAudInFader->setRange ( 0, AUD_FADER_IN_MAX ); + SliderAudInFader->setRange ( AUD_FADER_IN_MIN, AUD_FADER_IN_MAX ); const int iCurAudInFader = pClient->GetAudioInFader(); SliderAudInFader->setValue ( iCurAudInFader ); SliderAudInFader->setTickInterval ( AUD_FADER_IN_MAX / 9 ); diff --git a/src/resample.cpp b/src/resample.cpp index ee8b0be9..40fac8a3 100755 --- a/src/resample.cpp +++ b/src/resample.cpp @@ -35,109 +35,11 @@ #include "resample.h" -/******************************************************************************\ -* General Resampler * -\******************************************************************************/ -int CResample::Resample ( CVector& vecdInput, - CVector& vecdOutput, - const double dRation ) -{ - int i; - - /* 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 ( i = 0; i < iHistorySize; i++ ) - { - vecdIntBuff[i] = vecdIntBuff[iMovLen++]; - } - - // add new block of data - int iBlockEnd = iHistorySize; - for ( i = 0; i < iInputBlockSize; i++ ) - { - vecdIntBuff[iBlockEnd++] = vecdInput[i]; - } - - /* sample-interval of new sample frequency in relation to interpolated - sample-interval */ - dTStep = (double) INTERP_DECIM_I_D1 / dRation; - - // init output counter - int im = 0; - - // main loop - do - { - // quantize output-time to interpolated time-index - const int ik = (int) dtOut; - - - /* Calculate convolutions for the two interpolation-taps ------------ */ - // phase for the linear interpolation-taps - const int ip1 = ik % INTERP_DECIM_I_D1; - const int ip2 = ( ik + 1 ) % INTERP_DECIM_I_D1; - - // sample positions in input vector - const int in1 = (int) ( ik / INTERP_DECIM_I_D1 ); - const int in2 = (int) ( ( ik + 1 ) / INTERP_DECIM_I_D1 ); - - // convolution - double dy1 = 0.0; - double dy2 = 0.0; - 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]; - } - - - /* Linear interpolation --------------------------------------------- */ - // get numbers after the comma - const double dxInt = dtOut - (int) dtOut; - vecdOutput[im] = ( dy2 - dy1 ) * dxInt + dy1; - - - // increase output counter - im++; - - // increase output-time and index one step - dtOut = dtOut + dTStep; - } - while ( dtOut < dBlockDuration ); - - // set rtOut back - dtOut -= iInputBlockSize * INTERP_DECIM_I_D1; - - return im; -} - -void CResample::Init ( const int iNewInputBlockSize ) -{ - iInputBlockSize = iNewInputBlockSize; - - /* history size must be one sample larger, because we use always TWO - convolutions */ - iHistorySize = NUM_TAPS_PER_PHASE1 + 1; - - // calculate block duration - dBlockDuration = ( iInputBlockSize + iHistorySize - 1 ) * INTERP_DECIM_I_D1; - - // allocate memory for internal buffer, clear sample history - vecdIntBuff.Init ( iInputBlockSize + iHistorySize, 0.0 ); - - // init absolute time for output stream (at the end of the history part - dtOut = (double) ( iHistorySize - 1 ) * INTERP_DECIM_I_D1; -} - - - /******************************************************************************\ * Stereo Audio Resampler * \******************************************************************************/ -void CStereoAudioResample::Resample ( CVector& vecdInput, - CVector& vecdOutput ) +void CStereoAudioResample::ResampleStereo ( CVector& vecdInput, + CVector& vecdOutput ) { int j; @@ -156,14 +58,14 @@ void CStereoAudioResample::Resample ( CVector& vecdInput, int iMovLen = iStereoInputBlockSize; for ( j = 0; j < iTwoTimesNumTaps; j++ ) { - vecdIntBuff[j] = vecdIntBuff[iMovLen++]; + vecdIntBuffStereo[j] = vecdIntBuffStereo[iMovLen++]; } // add new block of data int iBlockEnd = iTwoTimesNumTaps; for ( j = 0; j < iStereoInputBlockSize; j++ ) { - vecdIntBuff[iBlockEnd++] = vecdInput[j]; + vecdIntBuffStereo[iBlockEnd++] = vecdInput[j]; } // main loop @@ -183,8 +85,8 @@ void CStereoAudioResample::Resample ( CVector& vecdInput, const double dCurFiltTap = pFiltTaps[ip + i * iI]; const int iCurSamplePos = in - 2 * i; - dyL += dCurFiltTap * vecdIntBuff[iCurSamplePos]; - dyR += dCurFiltTap * vecdIntBuff[iCurSamplePos + 1]; + dyL += dCurFiltTap * vecdIntBuffStereo[iCurSamplePos]; + dyR += dCurFiltTap * vecdIntBuffStereo[iCurSamplePos + 1]; } vecdOutput[2 * j] = dyL; @@ -193,11 +95,61 @@ void CStereoAudioResample::Resample ( CVector& vecdInput, } } +void CStereoAudioResample::ResampleMono ( CVector& vecdInput, + CVector& vecdOutput ) +{ + int j; + + if ( dRation == 1.0 ) + { + // if ratio is 1, no resampling is needed, just copy vector + vecdOutput = vecdInput; + } + else + { + /* move old data from the end to the history part of the buffer and + add new data (shift register) */ + // shift old values + int iMovLen = iMonoInputBlockSize; + for ( j = 0; j < iNumTaps; j++ ) + { + vecdIntBuffMono[j] = vecdIntBuffMono[iMovLen++]; + } + + // add new block of data + int iBlockEnd = iNumTaps; + for ( j = 0; j < iMonoInputBlockSize; j++ ) + { + vecdIntBuffMono[iBlockEnd++] = vecdInput[j]; + } + + // main loop + 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; + + // convolution + double dy = 0.0; + for ( int i = 0; i < iNumTaps; i++ ) + { + dy += pFiltTaps[ip + i * iI] * vecdIntBuffMono[in - i]; + } + + vecdOutput[j] = dy; + } + } +} + void CStereoAudioResample::Init ( const int iNewMonoInputBlockSize, const int iFrom, const int iTo ) { dRation = ( (double) iTo ) / iFrom; + iMonoInputBlockSize = iNewMonoInputBlockSize; iStereoInputBlockSize = 2 * iNewMonoInputBlockSize; iMonoOutputBlockSize = (int) ( iNewMonoInputBlockSize * dRation ); @@ -266,8 +218,9 @@ void CStereoAudioResample::Init ( const int iNewMonoInputBlockSize, } } - // allocate memory for internal buffer, clear sample history (we have - // to consider stereo data here -> two times the number of taps of + // allocate memory for internal buffer, clear sample history (for + // the stereo case we have to consider that two times the number of taps of // additional memory is required) - vecdIntBuff.Init ( iStereoInputBlockSize + 2 * iNumTaps, 0.0 ); + vecdIntBuffMono.Init ( iMonoInputBlockSize + iNumTaps, 0.0 ); + vecdIntBuffStereo.Init ( iStereoInputBlockSize + 2 * iNumTaps, 0.0 ); } diff --git a/src/resample.h b/src/resample.h index 8ae54c32..317db96e 100755 --- a/src/resample.h +++ b/src/resample.h @@ -31,27 +31,6 @@ /* Classes ********************************************************************/ -class CResample -{ -public: - CResample() {} - virtual ~CResample() {} - - void Init ( const int iNewInputBlockSize ); - int Resample ( CVector& vecdInput, CVector& vecdOutput, - const double dRation ); - -protected: - double dTStep; - double dtOut; - double dBlockDuration; - - CVector vecdIntBuff; - int iHistorySize; - - int iInputBlockSize; -}; - class CStereoAudioResample { public: @@ -59,14 +38,16 @@ public: virtual ~CStereoAudioResample() {} void Init ( const int iNewMonoInputBlockSize, const int iFrom, const int iTo ); - void Resample ( CVector& vecdInput, CVector& vecdOutput ); + void ResampleMono ( CVector& vecdInput, CVector& vecdOutput ); + void ResampleStereo ( CVector& vecdInput, CVector& vecdOutput ); protected: double dRation; - CVector vecdIntBuff; - int iHistorySize; + CVector vecdIntBuffMono; + CVector vecdIntBuffStereo; + int iMonoInputBlockSize; int iStereoInputBlockSize; int iMonoOutputBlockSize; @@ -75,5 +56,4 @@ protected: int iI; }; - #endif // !defined ( RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_ )