make the source compilable under Windows, no working functionality yet
This commit is contained in:
parent
548c8df2c7
commit
f53d28fc11
16 changed files with 35 additions and 1440 deletions
|
@ -1,554 +0,0 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2009
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer, Erik de Castro Lopo
|
||||
*
|
||||
* This code is based on the Open-Source implementation of IMA-ADPCM / MS-ADPCM
|
||||
* written by Erik de Castro Lopo <erikd[at-#]mega-nerd[dot*]com> in 1999-2004
|
||||
*
|
||||
* Changes:
|
||||
* - only support for one channel
|
||||
* - put 2 audio samples in header to get even number of audio samples encoded
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#include "audiocompr.h"
|
||||
|
||||
|
||||
/* Implementation *************************************************************/
|
||||
int CAudioCompression::Init ( const int iNewAudioLen,
|
||||
const EAudComprType eNewAuCoTy )
|
||||
{
|
||||
eAudComprType = eNewAuCoTy;
|
||||
|
||||
switch ( eNewAuCoTy )
|
||||
{
|
||||
case CT_NONE:
|
||||
return iCodeSize = 2 * iNewAudioLen; // short = 2 * byte
|
||||
|
||||
case CT_IMAADPCM:
|
||||
return ImaAdpcm.Init ( iNewAudioLen );
|
||||
|
||||
case CT_MSADPCM:
|
||||
return MsAdpcm.Init ( iNewAudioLen );
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CVector<uint8_t> CAudioCompression::Encode ( const CVector<short>& vecsAudio )
|
||||
{
|
||||
if ( eAudComprType == CT_NONE )
|
||||
{
|
||||
// no compression, simply ship pure samples
|
||||
CVector<uint8_t> vecbyOut ( iCodeSize );
|
||||
const int iAudSize = iCodeSize / 2;
|
||||
|
||||
for ( int i = 0; i < iAudSize; i++ )
|
||||
{
|
||||
vecbyOut[2 * i] = vecsAudio[i] & 0xFF;
|
||||
vecbyOut[2 * i + 1] = ( vecsAudio[i] >> 8 ) & 0xFF;
|
||||
}
|
||||
return vecbyOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( eAudComprType )
|
||||
{
|
||||
case CT_IMAADPCM:
|
||||
return ImaAdpcm.Encode ( vecsAudio ); // IMA-ADPCM
|
||||
|
||||
case CT_MSADPCM:
|
||||
return MsAdpcm.Encode ( vecsAudio ); // MS-ADPCM
|
||||
|
||||
default:
|
||||
return CVector<uint8_t> ( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CVector<short> CAudioCompression::Decode ( const CVector<uint8_t>& vecbyAdpcm )
|
||||
{
|
||||
if ( eAudComprType == CT_NONE )
|
||||
{
|
||||
// no compression, reassemble pure samples
|
||||
const int iAudSize = iCodeSize / 2;
|
||||
CVector<short> vecsOut ( iAudSize );
|
||||
|
||||
for ( int i = 0; i < iAudSize; i++ )
|
||||
{
|
||||
int current = vecbyAdpcm[2 * i] | ( vecbyAdpcm[2 * i + 1] << 8 );
|
||||
if ( current & 0x8000 )
|
||||
{
|
||||
current -= 0x10000;
|
||||
}
|
||||
|
||||
vecsOut[i] = (short) current;
|
||||
}
|
||||
return vecsOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( eAudComprType )
|
||||
{
|
||||
case CT_IMAADPCM:
|
||||
return ImaAdpcm.Decode ( vecbyAdpcm ); // IMA-ADPCM
|
||||
|
||||
case CT_MSADPCM:
|
||||
return MsAdpcm.Decode ( vecbyAdpcm ); // MS-ADPCM
|
||||
|
||||
default:
|
||||
return CVector<short> ( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
* IMA-ADPCM implementation *
|
||||
\******************************************************************************/
|
||||
int CImaAdpcm::Init ( const int iNewAudioLen )
|
||||
{
|
||||
// set lengths for audio and compressed data
|
||||
iAudSize = iNewAudioLen;
|
||||
iAdpcmSize = 4 /* bytes header */ + (int) ceil (
|
||||
(double) ( iAudSize - 2 /* first two samples are in header */ ) / 2 );
|
||||
|
||||
iStepindEnc = 0;
|
||||
|
||||
return iAdpcmSize;
|
||||
}
|
||||
|
||||
CVector<uint8_t> CImaAdpcm::Encode ( const CVector<short>& vecsAudio )
|
||||
{
|
||||
int i;
|
||||
CVector<uint8_t> vecbyAdpcm;
|
||||
CVector<uint8_t> vecbyAdpcmTemp;
|
||||
|
||||
// init size
|
||||
vecbyAdpcm.Init ( iAdpcmSize );
|
||||
vecbyAdpcmTemp.Init ( iAudSize );
|
||||
|
||||
|
||||
/* Encode the block header ---------------------------------------------- */
|
||||
vecbyAdpcm[0] = vecsAudio[0] & 0xFF;
|
||||
vecbyAdpcm[1] = ( vecsAudio[0] >> 8 ) & 0xFF;
|
||||
vecbyAdpcm[2] = iStepindEnc;
|
||||
|
||||
int iPrevAudio = vecsAudio[0];
|
||||
|
||||
|
||||
/* Encode the samples as 4 bit ------------------------------------------ */
|
||||
for ( i = 1; i < iAudSize; i++ )
|
||||
{
|
||||
// init diff and step
|
||||
int diff = vecsAudio[i] - iPrevAudio;
|
||||
|
||||
Q_ASSERT ( iStepindEnc < IMA_STEP_SIZE_TAB_LEN );
|
||||
int step = ima_step_size[iStepindEnc];
|
||||
|
||||
short bytecode = 0;
|
||||
|
||||
int vpdiff = step >> 3;
|
||||
if ( diff < 0 )
|
||||
{
|
||||
bytecode = 8;
|
||||
diff = -diff;
|
||||
}
|
||||
short mask = 4;
|
||||
while ( mask )
|
||||
{
|
||||
if ( diff >= step )
|
||||
{
|
||||
bytecode |= mask;
|
||||
diff -= step;
|
||||
vpdiff += step;
|
||||
}
|
||||
step >>= 1;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
if ( bytecode & 8 )
|
||||
{
|
||||
iPrevAudio -= vpdiff;
|
||||
}
|
||||
else
|
||||
{
|
||||
iPrevAudio += vpdiff;
|
||||
}
|
||||
|
||||
// adjust step size
|
||||
Q_ASSERT ( bytecode < IMA_INDX_ADJUST_TAB_LEN );
|
||||
iStepindEnc += ima_indx_adjust[bytecode];
|
||||
|
||||
// check that values do not exceed the bounds
|
||||
iPrevAudio = CheckBounds ( iPrevAudio, _MINSHORT, _MAXSHORT );
|
||||
iStepindEnc = CheckBounds ( iStepindEnc, 0, IMA_STEP_SIZE_TAB_LEN - 1 );
|
||||
|
||||
// use a temporary buffer as an intermediate result buffer
|
||||
vecbyAdpcmTemp[i] = bytecode;
|
||||
}
|
||||
|
||||
|
||||
/* Pack the 4 bit encoded samples --------------------------------------- */
|
||||
// The first encoded audio sample is in header
|
||||
vecbyAdpcm[3] = vecbyAdpcmTemp[1] & 0x0F;
|
||||
|
||||
for ( i = 4; i < iAdpcmSize; i++ )
|
||||
{
|
||||
vecbyAdpcm[i] = vecbyAdpcmTemp[2 * i - 6] & 0x0F;
|
||||
vecbyAdpcm[i] |= ( vecbyAdpcmTemp[2 * i - 5] << 4 ) & 0xF0;
|
||||
}
|
||||
|
||||
return vecbyAdpcm;
|
||||
}
|
||||
|
||||
CVector<short> CImaAdpcm::Decode ( const CVector<uint8_t>& vecbyAdpcm )
|
||||
{
|
||||
int i;
|
||||
CVector<short> vecsAudio;
|
||||
|
||||
vecsAudio.Init ( iAudSize );
|
||||
|
||||
|
||||
/* Read the block header ------------------------------------------------ */
|
||||
int current = vecbyAdpcm[0] | ( vecbyAdpcm[1] << 8 );
|
||||
if ( current & 0x8000 )
|
||||
{
|
||||
current -= 0x10000;
|
||||
}
|
||||
|
||||
// get and bound step index
|
||||
int iStepindDec = CheckBounds ( vecbyAdpcm[2], 0, IMA_STEP_SIZE_TAB_LEN - 1 );
|
||||
|
||||
// set first sample which was delivered in the header
|
||||
vecsAudio[0] = current;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
pull apart the packed 4 bit samples and store them in their correct
|
||||
sample positions */
|
||||
// the first encoded audio sample is in header
|
||||
vecsAudio[1] = vecbyAdpcm[3] & 0x0F;
|
||||
|
||||
for ( i = 4; i < iAdpcmSize; i++ )
|
||||
{
|
||||
const short bytecode = vecbyAdpcm[i];
|
||||
vecsAudio[2 * i - 6] = bytecode & 0x0F;
|
||||
vecsAudio[2 * i - 5] = ( bytecode >> 4 ) & 0x0F;
|
||||
}
|
||||
|
||||
|
||||
/* Decode the encoded 4 bit samples ------------------------------------- */
|
||||
for ( i = 1; i < iAudSize; i++ )
|
||||
{
|
||||
const short bytecode = vecsAudio[i] & 0xF;
|
||||
|
||||
Q_ASSERT ( iStepindDec < IMA_STEP_SIZE_TAB_LEN );
|
||||
|
||||
short step = ima_step_size[iStepindDec];
|
||||
int current = vecsAudio[i - 1];
|
||||
|
||||
int diff = step >> 3;
|
||||
if ( bytecode & 1 )
|
||||
{
|
||||
diff += step >> 2;
|
||||
}
|
||||
if ( bytecode & 2 )
|
||||
{
|
||||
diff += step >> 1;
|
||||
}
|
||||
if ( bytecode & 4 )
|
||||
{
|
||||
diff += step;
|
||||
}
|
||||
if ( bytecode & 8 )
|
||||
{
|
||||
diff = -diff;
|
||||
}
|
||||
|
||||
current += diff;
|
||||
|
||||
Q_ASSERT ( bytecode < IMA_INDX_ADJUST_TAB_LEN );
|
||||
iStepindDec += ima_indx_adjust[bytecode];
|
||||
|
||||
// check that values do not exceed the bounds
|
||||
current = CheckBounds ( current, _MINSHORT, _MAXSHORT );
|
||||
iStepindDec = CheckBounds ( iStepindDec, 0, IMA_STEP_SIZE_TAB_LEN - 1 );
|
||||
|
||||
vecsAudio[i] = current;
|
||||
}
|
||||
|
||||
return vecsAudio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
* MS-ADPCM implementation *
|
||||
\******************************************************************************/
|
||||
/*
|
||||
MS ADPCM block layout:
|
||||
byte purpose
|
||||
0 block predictor [0..6]
|
||||
1,2 initial idelta (positive)
|
||||
3,4 sample 1
|
||||
5,6 sample 0
|
||||
7..n packed bytecodes
|
||||
*/
|
||||
int CMsAdpcm::Init ( const int iNewAudioLen )
|
||||
{
|
||||
// set lengths for audio and compressed data
|
||||
iAudSize = iNewAudioLen;
|
||||
iAdpcmSize = 7 /* bytes header */ + (int) ceil (
|
||||
(double) ( iAudSize - 2 /* first two samples are in header */ ) / 2 );
|
||||
|
||||
return iAdpcmSize;
|
||||
}
|
||||
|
||||
CVector<uint8_t> CMsAdpcm::Encode ( const CVector<short>& vecsAudio )
|
||||
{
|
||||
CVector<short> vecsAudioTemp;
|
||||
CVector<uint8_t> vecbyAdpcm;
|
||||
|
||||
// init size
|
||||
vecsAudioTemp.Init ( iAudSize );
|
||||
vecbyAdpcm.Init ( iAdpcmSize );
|
||||
|
||||
// copy input vector (because we want to overwrite it)
|
||||
vecsAudioTemp = vecsAudio;
|
||||
|
||||
// choose predictor
|
||||
int bpred;
|
||||
int idelta;
|
||||
ChoosePredictor ( vecsAudio, bpred, idelta );
|
||||
|
||||
|
||||
/* Encode the block header ---------------------------------------------- */
|
||||
vecbyAdpcm[0] = bpred;
|
||||
vecbyAdpcm[1] = idelta & 0xFF;
|
||||
vecbyAdpcm[2] = ( idelta >> 8 ) & 0xFF;
|
||||
vecbyAdpcm[3] = vecsAudio[1] & 0xFF;
|
||||
vecbyAdpcm[4] = ( vecsAudio[1] >> 8 ) & 0xFF;
|
||||
vecbyAdpcm[5] = vecsAudio[0] & 0xFF;
|
||||
vecbyAdpcm[6] = ( vecsAudio[0] >> 8 ) & 0xFF;
|
||||
|
||||
|
||||
/* Encode the samples as 4 bit ------------------------------------------ */
|
||||
unsigned int blockindx = 7;
|
||||
uint8_t byte = 0;
|
||||
|
||||
for ( int k = 2; k < iAudSize; k++ )
|
||||
{
|
||||
const int predict = ( vecsAudioTemp[k - 1] * ms_AdaptCoeff1[bpred] +
|
||||
vecsAudioTemp[k - 2] * ms_AdaptCoeff2[bpred] ) >> 8;
|
||||
|
||||
int errordelta = ( vecsAudio[k] - predict ) / idelta;
|
||||
|
||||
if ( errordelta < -8 )
|
||||
{
|
||||
errordelta = -8 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errordelta > 7)
|
||||
{
|
||||
errordelta = 7;
|
||||
}
|
||||
}
|
||||
int newsamp = predict + ( idelta * errordelta );
|
||||
|
||||
if ( newsamp > 32767 )
|
||||
{
|
||||
newsamp = 32767;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( newsamp < -32768 )
|
||||
{
|
||||
newsamp = -32768;
|
||||
}
|
||||
}
|
||||
if ( errordelta < 0 )
|
||||
{
|
||||
errordelta += 0x10;
|
||||
}
|
||||
|
||||
byte = ( byte << 4 ) | ( errordelta & 0xF );
|
||||
|
||||
if ( k % 2 )
|
||||
{
|
||||
vecbyAdpcm[blockindx++] = byte;
|
||||
byte = 0;
|
||||
}
|
||||
|
||||
idelta = ( idelta * ms_AdaptationTable[errordelta] ) >> 8;
|
||||
|
||||
if ( idelta < 16 )
|
||||
{
|
||||
idelta = 16;
|
||||
}
|
||||
vecsAudioTemp[k] = newsamp;
|
||||
}
|
||||
|
||||
return vecbyAdpcm;
|
||||
}
|
||||
|
||||
CVector<short> CMsAdpcm::Decode ( const CVector<uint8_t>& vecbyAdpcm )
|
||||
{
|
||||
CVector<short> vecsAudio;
|
||||
short bytecode;
|
||||
|
||||
vecsAudio.Init ( iAudSize );
|
||||
|
||||
|
||||
/* Read the block header ------------------------------------------------ */
|
||||
short bpred = vecbyAdpcm[0];
|
||||
|
||||
if ( bpred >= 7 )
|
||||
{
|
||||
// no valid MS ADPCM stream, do not decode
|
||||
return vecsAudio;
|
||||
}
|
||||
|
||||
short chan_idelta = vecbyAdpcm[1] | ( vecbyAdpcm[2] << 8 );
|
||||
|
||||
vecsAudio[1] = vecbyAdpcm[3] | ( vecbyAdpcm[4] << 8 );
|
||||
vecsAudio[0] = vecbyAdpcm[5] | ( vecbyAdpcm[6] << 8 );
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
pull apart the packed 4 bit samples and store them in their correct
|
||||
sample positions */
|
||||
for ( int i = 7; i < iAdpcmSize; i++ )
|
||||
{
|
||||
bytecode = vecbyAdpcm[i];
|
||||
vecsAudio[2 * i - 12] = ( bytecode >> 4 ) & 0x0F;
|
||||
vecsAudio[2 * i - 11] = bytecode & 0x0F;
|
||||
}
|
||||
|
||||
|
||||
/* Decode the encoded 4 bit samples ------------------------------------- */
|
||||
for ( int k = 2; k < iAudSize; k ++ )
|
||||
{
|
||||
bytecode = vecsAudio[k] & 0xF;
|
||||
|
||||
// compute next Adaptive Scale Factor (ASF)
|
||||
int idelta = chan_idelta;
|
||||
|
||||
// => / 256 => FIXED_POINT_ADAPTATION_BASE == 256
|
||||
chan_idelta = ( ms_AdaptationTable[bytecode] * idelta ) >> 8;
|
||||
|
||||
if ( chan_idelta < 16 )
|
||||
{
|
||||
chan_idelta = 16;
|
||||
}
|
||||
|
||||
if ( bytecode & 0x8 )
|
||||
{
|
||||
bytecode -= 0x10;
|
||||
}
|
||||
|
||||
// => / 256 => FIXED_POINT_COEFF_BASE == 256
|
||||
const int predict = ( ( vecsAudio[k - 1] * ms_AdaptCoeff1[bpred] ) +
|
||||
( vecsAudio[k - 2] * ms_AdaptCoeff2[bpred] ) ) >> 8;
|
||||
|
||||
int current = ( bytecode * idelta ) + predict;
|
||||
|
||||
if ( current > 32767 )
|
||||
{
|
||||
current = 32767;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( current < -32768 )
|
||||
{
|
||||
current = -32768;
|
||||
}
|
||||
}
|
||||
|
||||
vecsAudio[k] = current;
|
||||
}
|
||||
|
||||
return vecsAudio;
|
||||
}
|
||||
|
||||
void CMsAdpcm::ChoosePredictor ( const CVector<short>& vecsAudio,
|
||||
int& block_pred,
|
||||
int& idelta )
|
||||
{
|
||||
/*
|
||||
Choosing the block predictor:
|
||||
Each block requires a predictor and an idelta for each channel. The
|
||||
predictor is in the range [0..6] which is an index into the two AdaptCoeff
|
||||
tables. The predictor is chosen by trying all of the possible predictors on
|
||||
a small set of samples at the beginning of the block. The predictor with the
|
||||
smallest average abs (idelta) is chosen as the best predictor for this
|
||||
block. The value of idelta is chosen to to give a 4 bit code value of +/- 4
|
||||
(approx. half the max. code value). If the average abs (idelta) is zero, the
|
||||
sixth predictor is chosen. If the value of idelta is less then 16 it is set
|
||||
to 16.
|
||||
*/
|
||||
unsigned int best_bpred = 0;
|
||||
unsigned int best_idelta = 0;
|
||||
|
||||
/* Microsoft uses an IDELTA_COUNT (number of sample pairs used to choose
|
||||
best predictor) value of 3. The best possible results would be obtained
|
||||
by using all the samples to choose the predictor. */
|
||||
unsigned int idelta_count = min ( MSADPCM_IDELTA_COUNT, vecsAudio.Size() - 1 );
|
||||
|
||||
for ( unsigned int bpred = 0; bpred < MSADPCM_ADAPT_COEFF_COUNT; bpred++ )
|
||||
{
|
||||
unsigned int idelta_sum = 0;
|
||||
|
||||
for ( unsigned int k = 2; k < 2 + idelta_count; k++ )
|
||||
{
|
||||
idelta_sum += abs ( vecsAudio[k] -
|
||||
( ( vecsAudio[k - 1] * ms_AdaptCoeff1[bpred] +
|
||||
vecsAudio[k - 2] * ms_AdaptCoeff2[bpred] ) >> 8 ) );
|
||||
}
|
||||
idelta_sum /= ( 4 * idelta_count );
|
||||
|
||||
if ( bpred == 0 || idelta_sum < best_idelta )
|
||||
{
|
||||
best_bpred = bpred;
|
||||
best_idelta = idelta_sum;
|
||||
}
|
||||
|
||||
if ( !idelta_sum )
|
||||
{
|
||||
best_bpred = bpred;
|
||||
best_idelta = 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( best_idelta < 16 )
|
||||
{
|
||||
best_idelta = 16;
|
||||
}
|
||||
|
||||
block_pred = best_bpred;
|
||||
idelta = best_idelta;
|
||||
|
||||
return;
|
||||
}
|
154
src/audiocompr.h
154
src/audiocompr.h
|
@ -1,154 +0,0 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2009
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer, Erik de Castro Lopo
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#if !defined ( AUDIOCOMPR_H_OIHGE76GEKJH3249_GEG98EG3_43441912__INCLUDED_ )
|
||||
#define AUDIOCOMPR_H_OIHGE76GEKJH3249_GEG98EG3_43441912__INCLUDED_
|
||||
|
||||
#include "util.h"
|
||||
#include "global.h"
|
||||
#include "buffer.h"
|
||||
|
||||
|
||||
/* Definitions ****************************************************************/
|
||||
// tables IMA-ADPCM
|
||||
#define IMA_INDX_ADJUST_TAB_LEN 16
|
||||
static int ima_indx_adjust[IMA_INDX_ADJUST_TAB_LEN] =
|
||||
{
|
||||
-1, -1, -1, -1, /* +0 - +3, decrease the step size */
|
||||
2, 4, 6, 8, /* +4 - +7, increase the step size */
|
||||
-1, -1, -1, -1, /* -0 - -3, decrease the step size */
|
||||
2, 4, 6, 8, /* -4 - -7, increase the step size */
|
||||
};
|
||||
|
||||
#define IMA_STEP_SIZE_TAB_LEN 89
|
||||
static int ima_step_size[IMA_STEP_SIZE_TAB_LEN] =
|
||||
{
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
|
||||
253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
|
||||
1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
|
||||
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
|
||||
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
||||
32767
|
||||
};
|
||||
|
||||
// tables MS-ADPCM
|
||||
#define MSADPCM_IDELTA_COUNT 20
|
||||
|
||||
#define MSADPCM_ADAPT_COEFF_COUNT 7
|
||||
static int ms_AdaptCoeff1[MSADPCM_ADAPT_COEFF_COUNT] =
|
||||
{
|
||||
256, 512, 0, 192, 240, 460, 392
|
||||
};
|
||||
|
||||
static int ms_AdaptCoeff2[MSADPCM_ADAPT_COEFF_COUNT] =
|
||||
{
|
||||
0, -256, 0, 64, 0, -208, -232
|
||||
};
|
||||
|
||||
static int ms_AdaptationTable[] =
|
||||
{
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
|
||||
|
||||
/* Classes ********************************************************************/
|
||||
/* IMA-ADPCM ---------------------------------------------------------------- */
|
||||
class CImaAdpcm
|
||||
{
|
||||
public:
|
||||
CImaAdpcm() : iStepindEnc ( 0 ) {}
|
||||
virtual ~CImaAdpcm() {}
|
||||
|
||||
int Init ( const int iNewAudioLen );
|
||||
CVector<uint8_t> Encode ( const CVector<short>& vecsAudio );
|
||||
CVector<short> Decode ( const CVector<uint8_t>& vecbyAdpcm );
|
||||
|
||||
protected:
|
||||
int iAudSize;
|
||||
int iAdpcmSize;
|
||||
int iStepindEnc;
|
||||
|
||||
// inline functions must be declared in the header
|
||||
inline int CheckBounds ( const int iData, const int iMin, const int iMax )
|
||||
{
|
||||
if ( iData > iMax )
|
||||
{
|
||||
return iMax;
|
||||
}
|
||||
|
||||
if ( iData < iMin )
|
||||
{
|
||||
return iMin;
|
||||
}
|
||||
|
||||
return iData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* MS-ADPCM ----------------------------------------------------------------- */
|
||||
class CMsAdpcm
|
||||
{
|
||||
public:
|
||||
CMsAdpcm() {}
|
||||
virtual ~CMsAdpcm() {}
|
||||
|
||||
int Init ( const int iNewAudioLen );
|
||||
CVector<uint8_t> Encode ( const CVector<short>& vecsAudio );
|
||||
CVector<short> Decode ( const CVector<uint8_t>& vecbyAdpcm );
|
||||
|
||||
protected:
|
||||
int iAudSize;
|
||||
int iAdpcmSize;
|
||||
|
||||
void ChoosePredictor ( const CVector<short>& vecsAudio,
|
||||
int& block_pred,
|
||||
int& idelta );
|
||||
};
|
||||
|
||||
|
||||
/* Audio compression class -------------------------------------------------- */
|
||||
class CAudioCompression
|
||||
{
|
||||
public:
|
||||
CAudioCompression() {}
|
||||
virtual ~CAudioCompression() {}
|
||||
|
||||
int Init ( const int iNewAudioLen,
|
||||
const EAudComprType eNewAuCoTy );
|
||||
CVector<uint8_t> Encode ( const CVector<short>& vecsAudio );
|
||||
CVector<short> Decode ( const CVector<uint8_t>& vecbyAdpcm );
|
||||
|
||||
EAudComprType GetType() { return eAudComprType; }
|
||||
|
||||
protected:
|
||||
EAudComprType eAudComprType;
|
||||
CImaAdpcm ImaAdpcm;
|
||||
CMsAdpcm MsAdpcm;
|
||||
int iCodeSize;
|
||||
};
|
||||
|
||||
#endif /* !defined ( AUDIOCOMPR_H_OIHGE76GEKJH3249_GEG98EG3_43441912__INCLUDED_ ) */
|
139
src/channel.cpp
139
src/channel.cpp
|
@ -244,86 +244,6 @@ int CChannelSet::GetFreeChan()
|
|||
return INVALID_CHANNEL_ID;
|
||||
}
|
||||
|
||||
void CChannelSet::SetOutputParameters()
|
||||
{
|
||||
// The strategy is as follows: Change the parameters for each channel
|
||||
// until the total upload rate is lower than the limit. We first set the
|
||||
// audio compression from None to MS-ADPCM for each channel and if this
|
||||
// is not enough, we start to increase the buffer size factor out.
|
||||
bool bUploadRateIsBelowLimit = false;
|
||||
|
||||
// first initialize all channels with the first parameter set (highest
|
||||
// upload data rate)
|
||||
for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
|
||||
{
|
||||
if ( vecChannels[i].IsConnected() )
|
||||
{
|
||||
// set new parameters
|
||||
vecChannels[i].SetNetwBufSizeFactOut ( 1 );
|
||||
vecChannels[i].SetAudioCompressionOut ( CT_NONE );
|
||||
}
|
||||
}
|
||||
|
||||
// calculate and check total upload rate (maybe the initialization already
|
||||
// gives desired upload rate)
|
||||
bUploadRateIsBelowLimit =
|
||||
( CalculateTotalUploadRateKbps() <= iUploadRateLimitKbps );
|
||||
|
||||
// try other parameter sets if required
|
||||
const int iNumTrials = 3;
|
||||
EAudComprType eCurAudComprType;
|
||||
int iCurBlockSizeFact;
|
||||
|
||||
int iCurTrialIdx = 0;
|
||||
while ( ( iCurTrialIdx < iNumTrials ) && ( !bUploadRateIsBelowLimit ) )
|
||||
{
|
||||
switch ( iCurTrialIdx )
|
||||
{
|
||||
case 0:
|
||||
// using other audio compression gives most reduction
|
||||
eCurAudComprType = CT_MSADPCM;
|
||||
iCurBlockSizeFact = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// trying to use larger block size factor to further reduce rate
|
||||
eCurAudComprType = CT_MSADPCM;
|
||||
iCurBlockSizeFact = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// trying to use larger block size factor to further reduce rate
|
||||
eCurAudComprType = CT_MSADPCM;
|
||||
iCurBlockSizeFact = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// we try to set the worst parameters to the clients which connected
|
||||
// the latest to the server, therefore we apply the new parameters to
|
||||
// the last channels first
|
||||
int iCurCh = USED_NUM_CHANNELS - 1;
|
||||
while ( ( iCurCh >= 0 ) && ( !bUploadRateIsBelowLimit ) )
|
||||
{
|
||||
if ( vecChannels[iCurCh].IsConnected() )
|
||||
{
|
||||
// set new parameters
|
||||
vecChannels[iCurCh].SetNetwBufSizeFactOut ( iCurBlockSizeFact );
|
||||
vecChannels[iCurCh].SetAudioCompressionOut ( eCurAudComprType );
|
||||
|
||||
// calculate and check total upload rate
|
||||
bUploadRateIsBelowLimit =
|
||||
( CalculateTotalUploadRateKbps() <= iUploadRateLimitKbps );
|
||||
}
|
||||
|
||||
// next channel (backwards counting)
|
||||
iCurCh--;
|
||||
}
|
||||
|
||||
// next trial index
|
||||
iCurTrialIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
int CChannelSet::CheckAddr ( const CHostAddress& Addr )
|
||||
{
|
||||
CHostAddress InetAddr;
|
||||
|
@ -431,9 +351,6 @@ bAudioOK = true;
|
|||
// requested
|
||||
if ( bNewChannelReserved && bAudioOK )
|
||||
{
|
||||
// update output network parameters for all connected clients
|
||||
SetOutputParameters();
|
||||
|
||||
// send message about new channel
|
||||
emit ChannelConnected ( HostAdr );
|
||||
|
||||
|
@ -529,9 +446,6 @@ const EGetDataStat eGetStat=GS_BUFFER_OK;//TEST
|
|||
// a channel is now disconnected, take action on it
|
||||
if ( bChannelIsNowDisconnected )
|
||||
{
|
||||
// update output network parameters for all connected clients
|
||||
SetOutputParameters();
|
||||
|
||||
// update channel list for all currently connected clients
|
||||
CreateAndSendChanListForAllConChannels();
|
||||
}
|
||||
|
@ -542,8 +456,7 @@ const EGetDataStat eGetStat=GS_BUFFER_OK;//TEST
|
|||
void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
|
||||
CVector<QString>& vecsName,
|
||||
CVector<int>& veciJitBufSize,
|
||||
CVector<int>& veciNetwOutBlSiFact,
|
||||
CVector<EAudComprType>& veceAudComprType )
|
||||
CVector<int>& veciNetwOutBlSiFact )
|
||||
{
|
||||
CHostAddress InetAddr;
|
||||
|
||||
|
@ -552,7 +465,6 @@ void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
|
|||
vecsName.Init ( USED_NUM_CHANNELS );
|
||||
veciJitBufSize.Init ( USED_NUM_CHANNELS );
|
||||
veciNetwOutBlSiFact.Init ( USED_NUM_CHANNELS );
|
||||
veceAudComprType.Init ( USED_NUM_CHANNELS );
|
||||
|
||||
// check all possible channels
|
||||
for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
|
||||
|
@ -564,7 +476,6 @@ void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
|
|||
vecsName[i] = vecChannels[i].GetName();
|
||||
veciJitBufSize[i] = vecChannels[i].GetSockBufSize();
|
||||
veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut();
|
||||
veceAudComprType[i] = vecChannels[i].GetAudioCompressionOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -651,7 +562,7 @@ CChannel::CChannel ( const bool bNIsServer ) :
|
|||
sName ( "" ),
|
||||
vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ),
|
||||
bIsEnabled ( false ),
|
||||
iCurNetwOutBlSiFact ( DEF_NET_BLOCK_SIZE_FACTOR )
|
||||
iCurNetwOutBlSiFact ( 0 )
|
||||
{
|
||||
// init network input properties
|
||||
NetwBufferInProps.iAudioBlockSize = 0;
|
||||
|
@ -669,6 +580,7 @@ CChannel::CChannel ( const bool bNIsServer ) :
|
|||
SetSockBufSize ( DEF_NET_BUF_SIZE_NUM_BL );
|
||||
|
||||
// set initial output block size factors
|
||||
/*
|
||||
if ( bIsServer )
|
||||
{
|
||||
SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR );
|
||||
|
@ -677,9 +589,7 @@ CChannel::CChannel ( const bool bNIsServer ) :
|
|||
{
|
||||
SetNetwBufSizeOut ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
|
||||
}
|
||||
|
||||
// set initial audio compression format for output
|
||||
SetAudioCompressionOut ( CT_MSADPCM );
|
||||
*/
|
||||
|
||||
|
||||
// connections -------------------------------------------------------------
|
||||
|
@ -772,26 +682,7 @@ void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut )
|
|||
iAudComprSizeOut = iNewNetwBlSiFactOut * SYSTEM_BLOCK_SIZE_SAMPLES;
|
||||
|
||||
// init conversion buffer
|
||||
ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES );
|
||||
}
|
||||
|
||||
void CChannel::SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut )
|
||||
{
|
||||
// store new value
|
||||
eAudComprTypeOut = eNewAudComprTypeOut;
|
||||
|
||||
if ( bIsServer )
|
||||
{
|
||||
// call "set network buffer size factor" function because its
|
||||
// initialization depends on the audio compression format and
|
||||
// implicitely, the audio compression is initialized
|
||||
SetNetwBufSizeFactOut ( iCurNetwOutBlSiFact );
|
||||
}
|
||||
else
|
||||
{
|
||||
// for client set arbitrary block size
|
||||
SetNetwBufSizeOut ( iCurAudioBlockSizeOut );
|
||||
}
|
||||
ConvBuf.Init ( iNewNetwBlSiFactOut * SYSTEM_BLOCK_SIZE_SAMPLES );
|
||||
}
|
||||
|
||||
bool CChannel::SetSockBufSize ( const int iNumBlocks )
|
||||
|
@ -806,7 +697,7 @@ bool CChannel::SetSockBufSize ( const int iNumBlocks )
|
|||
|
||||
// the network block size is a multiple of the internal minimal
|
||||
// block size
|
||||
SockBuf.Init ( MIN_SERVER_BLOCK_SIZE_SAMPLES, iNumBlocks );
|
||||
SockBuf.Init ( SYSTEM_BLOCK_SIZE_SAMPLES, iNumBlocks );
|
||||
|
||||
return false; // -> no error
|
||||
}
|
||||
|
@ -924,7 +815,6 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
|
|||
|
||||
// apply received parameters to internal data struct
|
||||
NetwBufferInProps.iAudioBlockSize = NetworkTransportProps.iMonoAudioBlockSize;
|
||||
NetwBufferInProps.eAudComprType = NetworkTransportProps.eAudioCodingType;
|
||||
NetwBufferInProps.iNetwInBufSize = NetworkTransportProps.iNetworkPacketSize;
|
||||
|
||||
// re-initialize cycle time variance measurement if necessary
|
||||
|
@ -950,7 +840,7 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings()
|
|||
{
|
||||
CNetworkTransportProps NetworkTransportProps (
|
||||
iAudComprSizeOut,
|
||||
iCurAudioBlockSizeOut,
|
||||
0, // TODO
|
||||
1, // right now we only use mono
|
||||
SYSTEM_SAMPLE_RATE, // right now only one sample rate is supported
|
||||
CT_CELT, // always CELT coding
|
||||
|
@ -1130,14 +1020,14 @@ CVector<uint8_t> CChannel::PrepSendPacket ( const CVector<short>& vecsNPacket )
|
|||
{
|
||||
// a packet is ready, compress audio
|
||||
vecbySendBuf.Init ( iAudComprSizeOut );
|
||||
vecbySendBuf = AudioCompressionOut.Encode ( ConvBuf.Get() );
|
||||
// vecbySendBuf = AudioCompressionOut.Encode ( ConvBuf.Get() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// a packet is ready, compress audio
|
||||
vecbySendBuf.Init ( iAudComprSizeOut );
|
||||
vecbySendBuf = AudioCompressionOut.Encode ( vecsNPacket );
|
||||
// vecbySendBuf = AudioCompressionOut.Encode ( vecsNPacket );
|
||||
}
|
||||
|
||||
return vecbySendBuf;
|
||||
|
@ -1145,16 +1035,7 @@ CVector<uint8_t> CChannel::PrepSendPacket ( const CVector<short>& vecsNPacket )
|
|||
|
||||
int CChannel::GetUploadRateKbps()
|
||||
{
|
||||
int iAudioSizeOut;
|
||||
|
||||
if ( bIsServer )
|
||||
{
|
||||
iAudioSizeOut = iCurNetwOutBlSiFact * MIN_SERVER_BLOCK_SIZE_SAMPLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
iAudioSizeOut = iCurAudioBlockSizeOut;
|
||||
}
|
||||
const int iAudioSizeOut = iCurNetwOutBlSiFact * SYSTEM_BLOCK_SIZE_SAMPLES;
|
||||
|
||||
// we assume that the UDP packet which is transported via IP has an
|
||||
// additional header size of
|
||||
|
|
|
@ -103,9 +103,6 @@ public:
|
|||
bool SetSockBufSize ( const int iNumBlocks );
|
||||
int GetSockBufSize() { return iCurSockBufSize; }
|
||||
|
||||
void SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut );
|
||||
int GetNetwBufSizeOut() { return iCurAudioBlockSizeOut; }
|
||||
|
||||
int GetAudioBlockSizeIn() { return NetwBufferInProps.iAudioBlockSize; }
|
||||
int GetUploadRateKbps();
|
||||
|
||||
|
@ -114,9 +111,6 @@ public:
|
|||
void SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut );
|
||||
int GetNetwBufSizeFactOut() { return iCurNetwOutBlSiFact; }
|
||||
|
||||
void SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut );
|
||||
EAudComprType GetAudioCompressionOut() { return eAudComprTypeOut; }
|
||||
|
||||
// network protocol interface
|
||||
void CreateJitBufMes ( const int iJitBufSize )
|
||||
{
|
||||
|
@ -180,7 +174,6 @@ protected:
|
|||
bool bIsServer;
|
||||
|
||||
int iCurNetwOutBlSiFact;
|
||||
int iCurAudioBlockSizeOut;
|
||||
|
||||
QMutex Mutex;
|
||||
|
||||
|
@ -191,8 +184,6 @@ protected:
|
|||
};
|
||||
sNetwProperties NetwBufferInProps;
|
||||
|
||||
EAudComprType eAudComprTypeOut;
|
||||
|
||||
public slots:
|
||||
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
|
||||
void OnJittBufSizeChange ( int iNewJitBufSize );
|
||||
|
@ -238,8 +229,7 @@ public:
|
|||
void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
|
||||
CVector<QString>& vecsName,
|
||||
CVector<int>& veciJitBufSize,
|
||||
CVector<int>& veciNetwOutBlSiFact,
|
||||
CVector<EAudComprType>& veceAudComprType );
|
||||
CVector<int>& veciNetwOutBlSiFact );
|
||||
|
||||
// access functions for actual channels
|
||||
bool IsConnected ( const int iChanNum )
|
||||
|
@ -262,7 +252,6 @@ protected:
|
|||
void CreateAndSendChanListForThisChan ( const int iCurChanID );
|
||||
void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, const QString& strChatText );
|
||||
void WriteHTMLChannelList();
|
||||
void SetOutputParameters();
|
||||
|
||||
/* do not use the vector class since CChannel does not have appropriate
|
||||
copy constructor/operator */
|
||||
|
|
|
@ -302,7 +302,7 @@ void CClient::Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate )
|
|||
vecbyNetwData.Init ( iCeltNumCodedBytes );
|
||||
|
||||
// the channel works on the audio coded block size
|
||||
Channel.SetNetwBufSizeOut ( iCeltNumCodedBytes );
|
||||
// Channel.SetNetwBufSizeOut ( iCeltNumCodedBytes );
|
||||
}
|
||||
|
||||
void CClient::ProcessAudioData ( CVector<int16_t>& vecsStereoSndCrd )
|
||||
|
@ -497,7 +497,7 @@ void CClient::UpdateSocketBufferSize()
|
|||
// one block in the jitter buffer
|
||||
const double dEstCurBufSet = ( dAudioBufferDurationMs +
|
||||
3.3 * ( Channel.GetTimingStdDev() + CycleTimeVariance.GetStdDev() ) ) /
|
||||
MIN_SERVER_BLOCK_DURATION_MS + 0.5;
|
||||
SYSTEM_BLOCK_DURATION_MS_FLOAT + 0.5;
|
||||
|
||||
// upper/lower hysteresis decision
|
||||
const int iUpperHystDec = LlconMath().round ( dEstCurBufSet - dHysteresis );
|
||||
|
|
12
src/client.h
12
src/client.h
|
@ -109,7 +109,6 @@ public:
|
|||
}
|
||||
int GetSockBufSize() { return Channel.GetSockBufSize(); }
|
||||
|
||||
int GetNetwBufSizeOut() { return Channel.GetNetwBufSizeOut(); }
|
||||
int GetAudioBlockSizeIn() { return Channel.GetAudioBlockSizeIn(); }
|
||||
int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); }
|
||||
|
||||
|
@ -126,17 +125,6 @@ public:
|
|||
{ return iSndCrdPreferredMonoBlSizeIndex; }
|
||||
int GetSndCrdActualMonoBlSize() { return iMonoBlockSizeSam; }
|
||||
|
||||
void SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut )
|
||||
{
|
||||
Channel.SetAudioCompressionOut ( eNewAudComprTypeOut );
|
||||
|
||||
// tell the server that audio coding has changed (it
|
||||
// is important to call this function AFTER we have applied
|
||||
// the new setting to the channel!)
|
||||
Channel.CreateNetTranspPropsMessFromCurrentSettings();
|
||||
}
|
||||
EAudComprType GetAudioCompressionOut() { return Channel.GetAudioCompressionOut(); }
|
||||
|
||||
void SetRemoteChanGain ( const int iId, const double dGain )
|
||||
{ Channel.SetRemoteChanGain ( iId, dGain ); }
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
|
|||
}
|
||||
|
||||
// audio compression type
|
||||
/*
|
||||
switch ( pClient->GetAudioCompressionOut() )
|
||||
{
|
||||
case CT_NONE:
|
||||
|
@ -103,6 +104,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
|
|||
radioButtonMS_ADPCM->setChecked ( true );
|
||||
break;
|
||||
}
|
||||
*/
|
||||
AudioCompressionButtonGroup.addButton ( radioButtonNoAudioCompr );
|
||||
AudioCompressionButtonGroup.addButton ( radioButtonIMA_ADPCM );
|
||||
AudioCompressionButtonGroup.addButton ( radioButtonMS_ADPCM );
|
||||
|
@ -259,6 +261,7 @@ void CClientSettingsDlg::OnOpenChatOnNewMessageStateChanged ( int value )
|
|||
|
||||
void CClientSettingsDlg::OnAudioCompressionButtonGroupClicked ( QAbstractButton* button )
|
||||
{
|
||||
/*
|
||||
if ( button == radioButtonNoAudioCompr )
|
||||
{
|
||||
pClient->SetAudioCompressionOut ( CT_NONE );
|
||||
|
@ -273,6 +276,7 @@ void CClientSettingsDlg::OnAudioCompressionButtonGroupClicked ( QAbstractButton*
|
|||
{
|
||||
pClient->SetAudioCompressionOut ( CT_MSADPCM );
|
||||
}
|
||||
*/
|
||||
UpdateDisplay();
|
||||
}
|
||||
|
||||
|
@ -291,7 +295,7 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime )
|
|||
- consider the jitter buffer on the server side, too
|
||||
*/
|
||||
|
||||
const int iTotalJitterBufferDelayMS = MIN_SERVER_BLOCK_DURATION_MS *
|
||||
const int iTotalJitterBufferDelayMS = SYSTEM_BLOCK_DURATION_MS_FLOAT *
|
||||
( 2 /* buffer at client and server */ * pClient->GetSockBufSize() ) / 2;
|
||||
|
||||
// we assume that we have two period sizes for the input and one for the
|
||||
|
@ -301,9 +305,11 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime )
|
|||
3 * pClient->GetSndCrdActualMonoBlSize() *
|
||||
1000 / SYSTEM_SAMPLE_RATE;
|
||||
|
||||
const int iDelayToFillNetworkPackets =
|
||||
( pClient->GetNetwBufSizeOut() + pClient->GetAudioBlockSizeIn() ) *
|
||||
1000 / SYSTEM_SAMPLE_RATE;
|
||||
|
||||
// TODO
|
||||
const int iDelayToFillNetworkPackets =0;// TEST
|
||||
// ( pClient->GetNetwBufSizeOut() + pClient->GetAudioBlockSizeIn() ) *
|
||||
// 1000 / SYSTEM_SAMPLE_RATE;
|
||||
|
||||
const int iTotalBufferDelay = iDelayToFillNetworkPackets +
|
||||
iTotalJitterBufferDelayMS + iTotalSoundCardDelayMS;
|
||||
|
|
|
@ -62,6 +62,10 @@
|
|||
// All other block sizes must be a multiple of this size
|
||||
#define SYSTEM_BLOCK_SIZE_SAMPLES 128
|
||||
|
||||
#define SYSTEM_BLOCK_DURATION_MS_FLOAT \
|
||||
( static_cast<double> ( SYSTEM_BLOCK_SIZE_SAMPLES ) / \
|
||||
SYSTEM_SAMPLE_RATE * 1000 )
|
||||
|
||||
// define the maximum mono audio buffer size at a sample rate
|
||||
// of 48 kHz, this is important for defining the maximum number
|
||||
// of bytes to be expected from the network interface
|
||||
|
|
|
@ -107,7 +107,7 @@ void CLlconServerDlg::OnTimer()
|
|||
// out network block size
|
||||
vecpListViewItems[i]->setText ( 5,
|
||||
QString().setNum (
|
||||
double ( veciNetwOutBlSiFact[i] * MIN_SERVER_BLOCK_DURATION_MS ), 'f', 2 ) );
|
||||
static_cast<double> ( veciNetwOutBlSiFact[i] * SYSTEM_BLOCK_DURATION_MS_FLOAT ), 'f', 2 ) );
|
||||
|
||||
// output audio compression
|
||||
switch ( veceAudComprType[i] )
|
||||
|
|
207
src/resample.cpp
207
src/resample.cpp
|
@ -1,207 +0,0 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2009
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
* The polyphase filter is calculated with Matlab, the associated file
|
||||
* is ResampleFilter.m.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#include "resample.h"
|
||||
|
||||
|
||||
/******************************************************************************\
|
||||
* Stereo Audio Resampler *
|
||||
\******************************************************************************/
|
||||
void CStereoAudioResample::ResampleStereo ( CVector<double>& vecdInput,
|
||||
CVector<double>& vecdOutput )
|
||||
{
|
||||
int j;
|
||||
|
||||
if ( dRation == 1.0 )
|
||||
{
|
||||
// if ratio is 1, no resampling is needed, just copy vector
|
||||
vecdOutput = 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 = iStereoInputBlockSize;
|
||||
for ( j = 0; j < iTwoTimesNumTaps; j++ )
|
||||
{
|
||||
vecdIntBuffStereo[j] = vecdIntBuffStereo[iMovLen++];
|
||||
}
|
||||
|
||||
// add new block of data
|
||||
int iBlockEnd = iTwoTimesNumTaps;
|
||||
for ( j = 0; j < iStereoInputBlockSize; j++ )
|
||||
{
|
||||
vecdIntBuffStereo[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 stereo input vector
|
||||
const int in = 2 * ( (int) ( j / dRation ) + iNumTaps - 1 );
|
||||
|
||||
// convolution
|
||||
double dyL = 0.0;
|
||||
double dyR = 0.0;
|
||||
for ( int i = 0; i < iNumTaps; i++ )
|
||||
{
|
||||
const double dCurFiltTap = pFiltTaps[ip + i * iI];
|
||||
const int iCurSamplePos = in - 2 * i;
|
||||
|
||||
dyL += dCurFiltTap * vecdIntBuffStereo[iCurSamplePos];
|
||||
dyR += dCurFiltTap * vecdIntBuffStereo[iCurSamplePos + 1];
|
||||
}
|
||||
|
||||
vecdOutput[2 * j] = dyL;
|
||||
vecdOutput[2 * j + 1] = dyR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CStereoAudioResample::ResampleMono ( CVector<double>& vecdInput,
|
||||
CVector<double>& 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 );
|
||||
|
||||
// set correct parameters
|
||||
if ( iFrom >= iTo ) // downsampling case
|
||||
{
|
||||
switch ( iTo )
|
||||
{
|
||||
case ( SND_CRD_SAMPLE_RATE / 2 ): // 48 kHz to 24 kHz
|
||||
pFiltTaps = fResTaps2;
|
||||
iNumTaps = INTERP_I_2 * NUM_TAPS_PER_PHASE2;
|
||||
iI = DECIM_D_2;
|
||||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 11 / 16 ): // 48 kHz to 33 kHz
|
||||
pFiltTaps = fResTaps16_11;
|
||||
iNumTaps = INTERP_I_16_11 * NUM_TAPS_PER_PHASE16_11;
|
||||
iI = DECIM_D_16_11;
|
||||
break;
|
||||
|
||||
case SND_CRD_SAMPLE_RATE: // 48 kHz to 48 kHz
|
||||
// no resampling needed
|
||||
pFiltTaps = NULL;
|
||||
iNumTaps = 0;
|
||||
iI = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
// resample ratio not defined, throw error
|
||||
throw 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // upsampling case (assumption: iTo == SND_CRD_SAMPLE_RATE)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
|
||||
case ( SND_CRD_SAMPLE_RATE * 11 / 16 ): // 33 kHz to 48 kHz
|
||||
pFiltTaps = fResTaps16_11;
|
||||
iNumTaps = DECIM_D_16_11 * NUM_TAPS_PER_PHASE16_11;
|
||||
iI = INTERP_I_16_11;
|
||||
break;
|
||||
|
||||
default:
|
||||
// resample ratio not defined, throw error
|
||||
throw 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
vecdIntBuffMono.Init ( iMonoInputBlockSize + iNumTaps, 0.0 );
|
||||
vecdIntBuffStereo.Init ( iStereoInputBlockSize + 2 * iNumTaps, 0.0 );
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/******************************************************************************\
|
||||
* Copyright (c) 2004-2009
|
||||
*
|
||||
* Author(s):
|
||||
* Volker Fischer
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
\******************************************************************************/
|
||||
|
||||
#if !defined ( RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_ )
|
||||
#define RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_
|
||||
|
||||
#include "util.h"
|
||||
#include "resamplefilter.h"
|
||||
#include "global.h"
|
||||
|
||||
|
||||
/* Classes ********************************************************************/
|
||||
class CStereoAudioResample
|
||||
{
|
||||
public:
|
||||
CStereoAudioResample() {}
|
||||
virtual ~CStereoAudioResample() {}
|
||||
|
||||
void Init ( const int iNewMonoInputBlockSize, const int iFrom, const int iTo );
|
||||
void ResampleMono ( CVector<double>& vecdInput, CVector<double>& vecdOutput );
|
||||
void ResampleStereo ( CVector<double>& vecdInput, CVector<double>& vecdOutput );
|
||||
|
||||
protected:
|
||||
double dRation;
|
||||
|
||||
CVector<double> vecdIntBuffMono;
|
||||
CVector<double> vecdIntBuffStereo;
|
||||
|
||||
int iMonoInputBlockSize;
|
||||
int iStereoInputBlockSize;
|
||||
int iMonoOutputBlockSize;
|
||||
|
||||
float* pFiltTaps;
|
||||
int iNumTaps;
|
||||
int iI;
|
||||
};
|
||||
|
||||
#endif // !defined ( RESAMPLE_H__3B0FEUFE7876F_FE8FE_CA63_4344_1912__INCLUDED_ )
|
|
@ -1,145 +0,0 @@
|
|||
/* Automatically generated file with MATLAB */
|
||||
/* File name: "ResampleFilter.m" */
|
||||
/* Filter taps in time-domain */
|
||||
|
||||
#ifndef _RESAMPLEFILTER_H_
|
||||
#define _RESAMPLEFILTER_H_
|
||||
|
||||
#define NUM_TAPS_PER_PHASE2 4
|
||||
#define NUM_TAPS_PER_PHASE16_11 4
|
||||
#define NUM_TAPS_PER_PHASE1 4
|
||||
#define INTERP_I_2 2
|
||||
#define DECIM_D_2 1
|
||||
#define INTERP_I_16_11 16
|
||||
#define DECIM_D_16_11 11
|
||||
#define INTERP_DECIM_I_D1 10
|
||||
|
||||
|
||||
|
||||
// Filter for ratio 2
|
||||
static float fResTaps2[INTERP_I_2 * DECIM_D_2 * NUM_TAPS_PER_PHASE2] = {
|
||||
-0.00543278438387929850f,
|
||||
-0.04267524016158903000f,
|
||||
0.20891570602538878000f,
|
||||
0.83952404734744124000f,
|
||||
0.83952404734744124000f,
|
||||
0.20891570602538878000f,
|
||||
-0.04267524016158903000f,
|
||||
-0.00543278438387929850f
|
||||
};
|
||||
|
||||
|
||||
// Filter for ratio 16 / 11
|
||||
static float fResTaps16_11[INTERP_I_16_11 * DECIM_D_16_11 * NUM_TAPS_PER_PHASE16_11] = {
|
||||
-0.00389889725874395950f,
|
||||
-0.00683214543790156090f,
|
||||
-0.01072680249202097000f,
|
||||
-0.01553896779709462000f,
|
||||
-0.02111182416262372800f,
|
||||
-0.02715802026999649900f,
|
||||
-0.03324873986594503000f,
|
||||
-0.03881136024854929500f,
|
||||
-0.04313717468451081600f,
|
||||
-0.04540006283235589100f,
|
||||
-0.04468627284754060600f,
|
||||
-0.04003467459491787100f,
|
||||
-0.03048601148793385700f,
|
||||
-0.01513888135261078900f,
|
||||
0.00679052165107026960f,
|
||||
0.03590841121927474500f,
|
||||
0.07258699462937284700f,
|
||||
0.11691555417711026000f,
|
||||
0.16866274617280169000f,
|
||||
0.22725337385053512000f,
|
||||
0.29176217038299262000f,
|
||||
0.36092619189350539000f,
|
||||
0.43317632432273434000f,
|
||||
0.50668722287057033000f,
|
||||
0.57944380845094834000f,
|
||||
0.64932132566729828000f,
|
||||
0.71417500205550644000f,
|
||||
0.77193461070469982000f,
|
||||
0.82069878531213381000f,
|
||||
0.85882380658614410000f,
|
||||
0.88500178763806503000f,
|
||||
0.89832372561302798000f,
|
||||
0.89832372561302798000f,
|
||||
0.88500178763806503000f,
|
||||
0.85882380658614410000f,
|
||||
0.82069878531213381000f,
|
||||
0.77193461070469982000f,
|
||||
0.71417500205550644000f,
|
||||
0.64932132566729828000f,
|
||||
0.57944380845094834000f,
|
||||
0.50668722287057033000f,
|
||||
0.43317632432273434000f,
|
||||
0.36092619189350539000f,
|
||||
0.29176217038299262000f,
|
||||
0.22725337385053512000f,
|
||||
0.16866274617280169000f,
|
||||
0.11691555417711026000f,
|
||||
0.07258699462937284700f,
|
||||
0.03590841121927474500f,
|
||||
0.00679052165107026960f,
|
||||
-0.01513888135261078900f,
|
||||
-0.03048601148793385700f,
|
||||
-0.04003467459491787100f,
|
||||
-0.04468627284754060600f,
|
||||
-0.04540006283235589100f,
|
||||
-0.04313717468451081600f,
|
||||
-0.03881136024854929500f,
|
||||
-0.03324873986594503000f,
|
||||
-0.02715802026999649900f,
|
||||
-0.02111182416262372800f,
|
||||
-0.01553896779709462000f,
|
||||
-0.01072680249202097000f,
|
||||
-0.00683214543790156090f,
|
||||
-0.00389889725874395950f
|
||||
};
|
||||
|
||||
// Filter for ratios close to 1
|
||||
static float fResTaps1[INTERP_DECIM_I_D1 * NUM_TAPS_PER_PHASE1] = {
|
||||
-0.00200330615661920140f,
|
||||
-0.00657158284969252320f,
|
||||
-0.01434325067267541500f,
|
||||
-0.02515649349164660000f,
|
||||
-0.03781954301370460400f,
|
||||
-0.04991380271447259900f,
|
||||
-0.05780029046175797600f,
|
||||
-0.05688089663877354800f,
|
||||
-0.04212153837626786400f,
|
||||
-0.00879070792017156400f,
|
||||
0.04668529656863164300f,
|
||||
0.12588850452342773000f,
|
||||
0.22775132810044491000f,
|
||||
0.34821676223650200000f,
|
||||
0.48031735951868820000f,
|
||||
0.61470848494637820000f,
|
||||
0.74061377477860824000f,
|
||||
0.84706508415438742000f,
|
||||
0.92426036786924715000f,
|
||||
0.96483311873999922000f,
|
||||
0.96483311873999922000f,
|
||||
0.92426036786924715000f,
|
||||
0.84706508415438742000f,
|
||||
0.74061377477860824000f,
|
||||
0.61470848494637820000f,
|
||||
0.48031735951868820000f,
|
||||
0.34821676223650200000f,
|
||||
0.22775132810044491000f,
|
||||
0.12588850452342773000f,
|
||||
0.04668529656863164300f,
|
||||
-0.00879070792017156400f,
|
||||
-0.04212153837626786400f,
|
||||
-0.05688089663877354800f,
|
||||
-0.05780029046175797600f,
|
||||
-0.04991380271447259900f,
|
||||
-0.03781954301370460400f,
|
||||
-0.02515649349164660000f,
|
||||
-0.01434325067267541500f,
|
||||
-0.00657158284969252320f,
|
||||
-0.00200330615661920140f
|
||||
};
|
||||
|
||||
|
||||
#endif /* _RESAMPLEFILTER_H_ */
|
|
@ -1,121 +0,0 @@
|
|||
% /****************************************************************************\
|
||||
% * Copyright (c) 2004-2009
|
||||
% *
|
||||
% * Author(s):
|
||||
% * Volker Fischer
|
||||
% *
|
||||
% \****************************************************************************/
|
||||
|
||||
function resamplefilter()
|
||||
|
||||
% Number of taps per poly phase for different resampling types
|
||||
GlobalNoTaps = 4; % use global value for all types
|
||||
|
||||
NoTapsP2 = GlobalNoTaps; % 24 kHz
|
||||
NoTapsP16_11 = GlobalNoTaps; % 33 kHz
|
||||
NoTapsP1 = GlobalNoTaps; % 48 kHz
|
||||
|
||||
|
||||
% Filter for ratio 2 -----------------------------------------------------------
|
||||
% I and D
|
||||
I2 = 2;
|
||||
D2 = 1;
|
||||
|
||||
% filter design
|
||||
h2 = DesignFilter(NoTapsP2, I2, 0.97);
|
||||
|
||||
|
||||
% Filter for ratio 16 / 11 -----------------------------------------------------
|
||||
% I and D
|
||||
I16_11 = 16;
|
||||
D16_11 = 11;
|
||||
|
||||
% filter design
|
||||
h16_11 = DesignFilter(NoTapsP16_11, I16_11, 0.90);
|
||||
|
||||
|
||||
% Filter for ratios close to 1 -------------------------------------------------
|
||||
% Fixed for sample-rate conversiones of R ~ 1
|
||||
I1 = 10; % D = I in this mode
|
||||
|
||||
% MMSE filter-design and windowing
|
||||
h1 = DesignFilter(NoTapsP1, I1, 0.97);
|
||||
|
||||
|
||||
% Export coefficiants to file ****************************************
|
||||
fid = fopen('resamplefilter.h', 'w');
|
||||
|
||||
fprintf(fid, '/* Automatically generated file with MATLAB */\n');
|
||||
fprintf(fid, '/* File name: "ResampleFilter.m" */\n');
|
||||
fprintf(fid, '/* Filter taps in time-domain */\n\n');
|
||||
|
||||
fprintf(fid, '#ifndef _RESAMPLEFILTER_H_\n');
|
||||
fprintf(fid, '#define _RESAMPLEFILTER_H_\n\n');
|
||||
|
||||
fprintf(fid, '#define NUM_TAPS_PER_PHASE2 ');
|
||||
fprintf(fid, int2str(NoTapsP2));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define NUM_TAPS_PER_PHASE16_11 ');
|
||||
fprintf(fid, int2str(NoTapsP16_11));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define NUM_TAPS_PER_PHASE1 ');
|
||||
fprintf(fid, int2str(NoTapsP1));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define INTERP_I_2 ');
|
||||
fprintf(fid, int2str(I2));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define DECIM_D_2 ');
|
||||
fprintf(fid, int2str(D2));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define INTERP_I_16_11 ');
|
||||
fprintf(fid, int2str(I16_11));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define DECIM_D_16_11 ');
|
||||
fprintf(fid, int2str(D16_11));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '#define INTERP_DECIM_I_D1 ');
|
||||
fprintf(fid, int2str(I1));
|
||||
fprintf(fid, '\n');
|
||||
fprintf(fid, '\n\n');
|
||||
|
||||
% Write filter taps
|
||||
fprintf(fid, '\n// Filter for ratio 2\n');
|
||||
ExportFilterTaps(fid, 'fResTaps2[INTERP_I_2 * DECIM_D_2 * NUM_TAPS_PER_PHASE2]', h2);
|
||||
|
||||
fprintf(fid, '\n// Filter for ratio 16 / 11\n');
|
||||
ExportFilterTaps(fid, 'fResTaps16_11[INTERP_I_16_11 * DECIM_D_16_11 * NUM_TAPS_PER_PHASE16_11]', h16_11);
|
||||
|
||||
fprintf(fid, '// Filter for ratios close to 1\n');
|
||||
ExportFilterTaps(fid, 'fResTaps1[INTERP_DECIM_I_D1 * NUM_TAPS_PER_PHASE1]', h1);
|
||||
|
||||
fprintf(fid, '\n#endif /* _RESAMPLEFILTER_H_ */\n');
|
||||
fclose(fid);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
function h = DesignFilter(NoTapsPIn, I, cutofffactor)
|
||||
|
||||
% number of taps, consider interpolation factor
|
||||
NoTapsP = NoTapsPIn * I;
|
||||
|
||||
% Cut-off frequency (normlized)
|
||||
fc = cutofffactor / I;
|
||||
|
||||
% MMSE filter design with Kaiser window, consider interpolation factor
|
||||
h = I * firls(NoTapsP - 1, [0 fc fc 1], [1 1 0 0]) .* kaiser(NoTapsP, 5)';
|
||||
|
||||
return;
|
||||
|
||||
|
||||
function ExportFilterTaps(f, name, h)
|
||||
|
||||
% Write filter taps
|
||||
fprintf(f, ['static float ' name ' = {\n']);
|
||||
fprintf(f, ' %.20ff,\n', h(1:end - 1));
|
||||
fprintf(f, ' %.20ff\n', h(end));
|
||||
fprintf(f, '};\n\n');
|
||||
|
||||
return;
|
||||
|
||||
|
|
@ -96,7 +96,9 @@ void CServer::Start()
|
|||
if ( !IsRunning() )
|
||||
{
|
||||
// start main timer
|
||||
Timer.start ( MIN_SERVER_BLOCK_DURATION_MS );
|
||||
|
||||
// TEST
|
||||
Timer.start ( static_cast<int> ( ceil ( SYSTEM_BLOCK_DURATION_MS_FLOAT ) ) );
|
||||
|
||||
// init time for response time evaluation
|
||||
CycleTimeVariance.Reset();
|
||||
|
|
|
@ -59,8 +59,10 @@ public:
|
|||
CVector<int>& veciNetwOutBlSiFact,
|
||||
CVector<EAudComprType>& veceAudComprType )
|
||||
{
|
||||
ChannelSet.GetConCliParam ( vecHostAddresses, vecsName,
|
||||
veciJitBufSize, veciNetwOutBlSiFact, veceAudComprType );
|
||||
ChannelSet.GetConCliParam ( vecHostAddresses,
|
||||
vecsName,
|
||||
veciJitBufSize,
|
||||
veciNetwOutBlSiFact );
|
||||
}
|
||||
|
||||
bool GetTimingStdDev ( double& dCurTiStdDev );
|
||||
|
|
|
@ -133,26 +133,6 @@ void CSettings::ReadIniFile ( const QString& sFileName )
|
|||
{
|
||||
pClient->SetOpenChatOnNewMessage ( bValue );
|
||||
}
|
||||
|
||||
// audio compression type (check CAudioCompression::EAudComprType definition
|
||||
// for integer numbers!)
|
||||
if ( GetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 0, 2, iValue ) )
|
||||
{
|
||||
switch ( iValue )
|
||||
{
|
||||
case 0:
|
||||
pClient->SetAudioCompressionOut ( CT_NONE );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pClient->SetAudioCompressionOut ( CT_IMAADPCM );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
break;
|
||||
pClient->SetAudioCompressionOut ( CT_MSADPCM );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSettings::WriteIniFile ( const QString& sFileName )
|
||||
|
@ -206,23 +186,6 @@ void CSettings::WriteIniFile ( const QString& sFileName )
|
|||
SetFlagIniSet ( IniXMLDocument, "client", "openchatonnewmessage",
|
||||
pClient->GetOpenChatOnNewMessage() );
|
||||
|
||||
// audio compression type (check CAudioCompression::EAudComprType definition
|
||||
// for integer numbers!)
|
||||
switch ( pClient->GetAudioCompressionOut() )
|
||||
{
|
||||
case CT_NONE:
|
||||
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 0 );
|
||||
break;
|
||||
|
||||
case CT_IMAADPCM:
|
||||
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 1 );
|
||||
break;
|
||||
|
||||
case CT_MSADPCM:
|
||||
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 2 );
|
||||
break;
|
||||
}
|
||||
|
||||
// prepare file name for storing initialization data in XML file
|
||||
QString sCurFileName = sFileName;
|
||||
if ( sCurFileName.isEmpty() )
|
||||
|
|
Loading…
Reference in a new issue