preparations for stereo support
This commit is contained in:
parent
c7f1992890
commit
7173108c77
7 changed files with 272 additions and 75 deletions
|
@ -31,7 +31,8 @@ CChannel::CChannel ( const bool bNIsServer ) :
|
||||||
vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ),
|
vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ),
|
||||||
bIsEnabled ( false ),
|
bIsEnabled ( false ),
|
||||||
iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_DEFAULT ),
|
iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_DEFAULT ),
|
||||||
iNetwFrameSize ( 20 ) // must be > 0 and should be close to a valid size
|
iNetwFrameSize ( 20 ), // must be > 0 and should be close to a valid size
|
||||||
|
iNumAudioChannels ( 1 ) // mono
|
||||||
{
|
{
|
||||||
// initial value for connection time out counter, we calculate the total
|
// initial value for connection time out counter, we calculate the total
|
||||||
// number of samples here and subtract the number of samples of the block
|
// number of samples here and subtract the number of samples of the block
|
||||||
|
@ -132,13 +133,15 @@ void CChannel::SetEnable ( const bool bNEnStat )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChannel::SetNetwFrameSizeAndFact ( const int iNewNetwFrameSize,
|
void CChannel::SetAudioStreamProperties ( const int iNewNetwFrameSize,
|
||||||
const int iNewNetwFrameSizeFact )
|
const int iNewNetwFrameSizeFact,
|
||||||
|
const int iNewNumAudioChannels )
|
||||||
{
|
{
|
||||||
// this function is intended for the server (not the client)
|
// this function is intended for the server (not the client)
|
||||||
QMutexLocker locker ( &Mutex );
|
QMutexLocker locker ( &Mutex );
|
||||||
|
|
||||||
// store new values
|
// store new values
|
||||||
|
iNumAudioChannels = iNewNumAudioChannels;
|
||||||
iNetwFrameSize = iNewNetwFrameSize;
|
iNetwFrameSize = iNewNetwFrameSize;
|
||||||
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
|
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
|
||||||
|
|
||||||
|
@ -291,6 +294,7 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
|
||||||
QMutexLocker locker ( &Mutex );
|
QMutexLocker locker ( &Mutex );
|
||||||
|
|
||||||
// store received parameters
|
// store received parameters
|
||||||
|
iNumAudioChannels = NetworkTransportProps.iNumAudioChannels;
|
||||||
iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact;
|
iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact;
|
||||||
iNetwFrameSize =
|
iNetwFrameSize =
|
||||||
NetworkTransportProps.iBaseNetworkPacketSize;
|
NetworkTransportProps.iBaseNetworkPacketSize;
|
||||||
|
@ -314,10 +318,10 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings()
|
||||||
CNetworkTransportProps NetworkTransportProps (
|
CNetworkTransportProps NetworkTransportProps (
|
||||||
iNetwFrameSize,
|
iNetwFrameSize,
|
||||||
iNetwFrameSizeFact,
|
iNetwFrameSizeFact,
|
||||||
1, // right now we only use mono
|
iNumAudioChannels,
|
||||||
SYSTEM_SAMPLE_RATE,
|
SYSTEM_SAMPLE_RATE,
|
||||||
CT_CELT, // always CELT coding
|
CT_CELT, // always CELT coding
|
||||||
0,
|
0, // version of the codec
|
||||||
0 );
|
0 );
|
||||||
|
|
||||||
// send current network transport properties
|
// send current network transport properties
|
||||||
|
|
|
@ -99,10 +99,12 @@ public:
|
||||||
double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); }
|
double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); }
|
||||||
|
|
||||||
// set/get network out buffer size and size factor
|
// set/get network out buffer size and size factor
|
||||||
void SetNetwFrameSizeAndFact ( const int iNewNetwFrameSize,
|
void SetAudioStreamProperties ( const int iNewNetwFrameSize,
|
||||||
const int iNewNetwFrameSizeFact );
|
const int iNewNetwFrameSizeFact,
|
||||||
|
const int iNewNumAudioChannels );
|
||||||
int GetNetwFrameSizeFact() const { return iNetwFrameSizeFact; }
|
int GetNetwFrameSizeFact() const { return iNetwFrameSizeFact; }
|
||||||
int GetNetwFrameSize() const { return iNetwFrameSize; }
|
int GetNetwFrameSize() const { return iNetwFrameSize; }
|
||||||
|
int GetNumAudioChannels() const { return iNumAudioChannels; }
|
||||||
|
|
||||||
double GetJitterBufferErrorRate() { return SockBuf.GetErrorRate(); }
|
double GetJitterBufferErrorRate() { return SockBuf.GetErrorRate(); }
|
||||||
|
|
||||||
|
@ -161,6 +163,8 @@ protected:
|
||||||
int iNetwFrameSizeFact;
|
int iNetwFrameSizeFact;
|
||||||
int iNetwFrameSize;
|
int iNetwFrameSize;
|
||||||
|
|
||||||
|
int iNumAudioChannels;
|
||||||
|
|
||||||
QMutex Mutex;
|
QMutex Mutex;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -55,15 +55,28 @@ CClient::CClient ( const quint16 iPortNumber ) :
|
||||||
iSndCardMonoBlockSizeSamConvBuff ( 0 )
|
iSndCardMonoBlockSizeSamConvBuff ( 0 )
|
||||||
{
|
{
|
||||||
// init audio endocder/decoder (mono)
|
// init audio endocder/decoder (mono)
|
||||||
CeltMode = celt_mode_create (
|
CeltModeMono = celt_mode_create (
|
||||||
SYSTEM_SAMPLE_RATE, 1, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
SYSTEM_SAMPLE_RATE, 1, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
||||||
|
|
||||||
CeltEncoder = celt_encoder_create ( CeltMode );
|
CeltEncoderMono = celt_encoder_create ( CeltModeMono );
|
||||||
CeltDecoder = celt_decoder_create ( CeltMode );
|
CeltDecoderMono = celt_decoder_create ( CeltModeMono );
|
||||||
|
|
||||||
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
||||||
// set encoder low complexity
|
// set encoder low complexity
|
||||||
celt_encoder_ctl(CeltEncoder,
|
celt_encoder_ctl ( CeltEncoderMono,
|
||||||
|
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// init audio endocder/decoder (stereo)
|
||||||
|
CeltModeStereo = celt_mode_create (
|
||||||
|
SYSTEM_SAMPLE_RATE, 2, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
||||||
|
|
||||||
|
CeltEncoderStereo = celt_encoder_create ( CeltModeStereo );
|
||||||
|
CeltDecoderStereo = celt_decoder_create ( CeltModeStereo );
|
||||||
|
|
||||||
|
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
||||||
|
// set encoder low complexity
|
||||||
|
celt_encoder_ctl ( CeltEncoderStereo,
|
||||||
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -511,8 +524,9 @@ void CClient::Init()
|
||||||
vecbyNetwData.Init ( iCeltNumCodedBytes );
|
vecbyNetwData.Init ( iCeltNumCodedBytes );
|
||||||
|
|
||||||
// set the channel network properties
|
// set the channel network properties
|
||||||
Channel.SetNetwFrameSizeAndFact ( iCeltNumCodedBytes,
|
Channel.SetAudioStreamProperties ( iCeltNumCodedBytes,
|
||||||
iSndCrdFrameSizeFactor );
|
iSndCrdFrameSizeFactor,
|
||||||
|
1 /* only mono right now */ );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::AudioCallback ( CVector<int16_t>& psData, void* arg )
|
void CClient::AudioCallback ( CVector<int16_t>& psData, void* arg )
|
||||||
|
@ -610,18 +624,25 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const double dAttFact =
|
// make sure that in the middle position the two channels are
|
||||||
static_cast<double> ( AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
|
// amplified by 1/2, if the pan is set to one channel, this
|
||||||
AUD_FADER_IN_MIDDLE;
|
// channel should have an amplification of 1
|
||||||
|
const double dAttFact = static_cast<double> (
|
||||||
|
AUD_FADER_IN_MIDDLE - abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
|
||||||
|
AUD_FADER_IN_MIDDLE / 2;
|
||||||
|
|
||||||
|
const double dAmplFact = 0.5 + static_cast<double> (
|
||||||
|
abs ( AUD_FADER_IN_MIDDLE - iAudioInFader ) ) /
|
||||||
|
AUD_FADER_IN_MIDDLE / 2;
|
||||||
|
|
||||||
if ( iAudioInFader > AUD_FADER_IN_MIDDLE )
|
if ( iAudioInFader > AUD_FADER_IN_MIDDLE )
|
||||||
{
|
{
|
||||||
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
||||||
{
|
{
|
||||||
// attenuation on right channel
|
// attenuation on right channel
|
||||||
vecsNetwork[i] =
|
vecsNetwork[i] = Double2Short (
|
||||||
Double2Short ( ( vecdAudioStereo[j] +
|
dAmplFact * vecdAudioStereo[j] +
|
||||||
dAttFact * vecdAudioStereo[j + 1] ) / 2 );
|
dAttFact * vecdAudioStereo[j + 1] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -629,9 +650,9 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 )
|
||||||
{
|
{
|
||||||
// attenuation on left channel
|
// attenuation on left channel
|
||||||
vecsNetwork[i] =
|
vecsNetwork[i] = Double2Short (
|
||||||
Double2Short ( ( vecdAudioStereo[j + 1] +
|
dAmplFact * vecdAudioStereo[j + 1] +
|
||||||
dAttFact * vecdAudioStereo[j] ) / 2 );
|
dAttFact * vecdAudioStereo[j] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,7 +660,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
for ( i = 0; i < iSndCrdFrameSizeFactor; i++ )
|
for ( i = 0; i < iSndCrdFrameSizeFactor; i++ )
|
||||||
{
|
{
|
||||||
// encode current audio frame with CELT encoder
|
// encode current audio frame with CELT encoder
|
||||||
celt_encode ( CeltEncoder,
|
celt_encode ( CeltEncoderMono,
|
||||||
&vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES],
|
&vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES],
|
||||||
NULL,
|
NULL,
|
||||||
&vecCeltData[0],
|
&vecCeltData[0],
|
||||||
|
@ -670,7 +691,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
// CELT decoding
|
// CELT decoding
|
||||||
if ( bReceiveDataOk )
|
if ( bReceiveDataOk )
|
||||||
{
|
{
|
||||||
celt_decode ( CeltDecoder,
|
celt_decode ( CeltDecoderMono,
|
||||||
&vecbyNetwData[0],
|
&vecbyNetwData[0],
|
||||||
iCeltNumCodedBytes,
|
iCeltNumCodedBytes,
|
||||||
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
|
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
|
||||||
|
@ -678,7 +699,7 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// lost packet
|
// lost packet
|
||||||
celt_decode ( CeltDecoder,
|
celt_decode ( CeltDecoderMono,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
|
&vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] );
|
||||||
|
|
|
@ -223,9 +223,12 @@ protected:
|
||||||
bool bDoAutoSockBufSize;
|
bool bDoAutoSockBufSize;
|
||||||
|
|
||||||
// audio encoder/decoder
|
// audio encoder/decoder
|
||||||
CELTMode* CeltMode;
|
CELTMode* CeltModeMono;
|
||||||
CELTEncoder* CeltEncoder;
|
CELTEncoder* CeltEncoderMono;
|
||||||
CELTDecoder* CeltDecoder;
|
CELTDecoder* CeltDecoderMono;
|
||||||
|
CELTMode* CeltModeStereo;
|
||||||
|
CELTEncoder* CeltEncoderStereo;
|
||||||
|
CELTDecoder* CeltDecoderStereo;
|
||||||
int iCeltNumCodedBytes;
|
int iCeltNumCodedBytes;
|
||||||
bool bCeltDoHighQuality;
|
bool bCeltDoHighQuality;
|
||||||
CVector<unsigned char> vecCeltData;
|
CVector<unsigned char> vecCeltData;
|
||||||
|
|
|
@ -897,7 +897,8 @@ bool CProtocol::EvaluateNetwTranspPropsMes ( const CVector<uint8_t>& vecData )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// number of channels of the audio signal, e.g. "2" is stereo (1 byte)
|
// number of channels of the audio signal, only mono (1 channel) or
|
||||||
|
// stereo (2 channels) allowed (1 byte)
|
||||||
ReceivedNetwTranspProps.iNumAudioChannels =
|
ReceivedNetwTranspProps.iNumAudioChannels =
|
||||||
static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 1 ) );
|
static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 1 ) );
|
||||||
|
|
||||||
|
|
241
src/server.cpp
241
src/server.cpp
|
@ -175,19 +175,33 @@ CServer::CServer ( const QString& strLoggingFileName,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// create CELT encoder/decoder for each channel (must be done before
|
// create CELT encoder/decoder for each channel (must be done before
|
||||||
// enabling the channels)
|
// enabling the channels), create a mono and stereo encoder/decoder
|
||||||
|
// for each channel
|
||||||
for ( i = 0; i < USED_NUM_CHANNELS; i++ )
|
for ( i = 0; i < USED_NUM_CHANNELS; i++ )
|
||||||
{
|
{
|
||||||
// init audio endocder/decoder (mono)
|
// init audio endocder/decoder (mono)
|
||||||
CeltMode[i] = celt_mode_create (
|
CeltModeMono[i] = celt_mode_create (
|
||||||
SYSTEM_SAMPLE_RATE, 1, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
SYSTEM_SAMPLE_RATE, 1, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
||||||
|
|
||||||
CeltEncoder[i] = celt_encoder_create ( CeltMode[i] );
|
CeltEncoderMono[i] = celt_encoder_create ( CeltModeMono[i] );
|
||||||
CeltDecoder[i] = celt_decoder_create ( CeltMode[i] );
|
CeltDecoderMono[i] = celt_decoder_create ( CeltModeMono[i] );
|
||||||
|
|
||||||
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
||||||
// set encoder low complexity
|
// set encoder low complexity
|
||||||
celt_encoder_ctl(CeltEncoder[i],
|
celt_encoder_ctl ( CeltEncoderMono[i],
|
||||||
|
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// init audio endocder/decoder (stereo)
|
||||||
|
CeltModeStereo[i] = celt_mode_create (
|
||||||
|
SYSTEM_SAMPLE_RATE, 2, SYSTEM_FRAME_SIZE_SAMPLES, NULL );
|
||||||
|
|
||||||
|
CeltEncoderStereo[i] = celt_encoder_create ( CeltModeStereo[i] );
|
||||||
|
CeltDecoderStereo[i] = celt_decoder_create ( CeltModeStereo[i] );
|
||||||
|
|
||||||
|
#ifdef USE_LOW_COMPLEXITY_CELT_ENC
|
||||||
|
// set encoder low complexity
|
||||||
|
celt_encoder_ctl ( CeltEncoderStereo[i],
|
||||||
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
CELT_SET_COMPLEXITY_REQUEST, celt_int32_t ( 1 ) );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -376,6 +390,7 @@ void CServer::OnTimer()
|
||||||
CVector<int> vecChanID;
|
CVector<int> vecChanID;
|
||||||
CVector<CVector<double> > vecvecdGains;
|
CVector<CVector<double> > vecvecdGains;
|
||||||
CVector<CVector<int16_t> > vecvecsData;
|
CVector<CVector<int16_t> > vecvecsData;
|
||||||
|
CVector<int> vecNumAudioChannels;
|
||||||
|
|
||||||
// Get data from all connected clients -------------------------------------
|
// Get data from all connected clients -------------------------------------
|
||||||
bool bChannelIsNowDisconnected = false;
|
bool bChannelIsNowDisconnected = false;
|
||||||
|
@ -399,17 +414,24 @@ void CServer::OnTimer()
|
||||||
const int iNumCurConnChan = vecChanID.Size();
|
const int iNumCurConnChan = vecChanID.Size();
|
||||||
|
|
||||||
// init temporary vectors
|
// init temporary vectors
|
||||||
vecvecdGains.Init ( iNumCurConnChan );
|
vecvecdGains.Init ( iNumCurConnChan );
|
||||||
vecvecsData.Init ( iNumCurConnChan );
|
vecvecsData.Init ( iNumCurConnChan );
|
||||||
|
vecNumAudioChannels.Init ( iNumCurConnChan );
|
||||||
|
|
||||||
for ( i = 0; i < iNumCurConnChan; i++ )
|
for ( i = 0; i < iNumCurConnChan; i++ )
|
||||||
{
|
{
|
||||||
// get actual ID of current channel
|
// get actual ID of current channel
|
||||||
const int iCurChanID = vecChanID[i];
|
const int iCurChanID = vecChanID[i];
|
||||||
|
|
||||||
|
// get and store number of audio channels
|
||||||
|
const int iCurNumAudChan =
|
||||||
|
vecChannels[iCurChanID].GetNumAudioChannels();
|
||||||
|
|
||||||
|
vecNumAudioChannels[i] = iCurNumAudChan;
|
||||||
|
|
||||||
// init vectors storing information of all channels
|
// init vectors storing information of all channels
|
||||||
vecvecdGains[i].Init ( iNumCurConnChan );
|
vecvecdGains[i].Init ( iNumCurConnChan );
|
||||||
vecvecsData[i].Init ( SYSTEM_FRAME_SIZE_SAMPLES );
|
vecvecsData[i].Init ( iCurNumAudChan * SYSTEM_FRAME_SIZE_SAMPLES );
|
||||||
|
|
||||||
// get gains of all connected channels
|
// get gains of all connected channels
|
||||||
for ( j = 0; j < iNumCurConnChan; j++ )
|
for ( j = 0; j < iNumCurConnChan; j++ )
|
||||||
|
@ -442,18 +464,42 @@ void CServer::OnTimer()
|
||||||
// CELT decode received data stream
|
// CELT decode received data stream
|
||||||
if ( eGetStat == GS_BUFFER_OK )
|
if ( eGetStat == GS_BUFFER_OK )
|
||||||
{
|
{
|
||||||
celt_decode ( CeltDecoder[iCurChanID],
|
if ( iCurNumAudChan == 1 )
|
||||||
&vecbyData[0],
|
{
|
||||||
iCeltNumCodedBytes,
|
// mono
|
||||||
&vecvecsData[i][0] );
|
celt_decode ( CeltDecoderMono[iCurChanID],
|
||||||
|
&vecbyData[0],
|
||||||
|
iCeltNumCodedBytes,
|
||||||
|
&vecvecsData[i][0] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
celt_decode ( CeltDecoderStereo[iCurChanID],
|
||||||
|
&vecbyData[0],
|
||||||
|
iCeltNumCodedBytes,
|
||||||
|
&vecvecsData[i][0] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// lost packet
|
// lost packet
|
||||||
celt_decode ( CeltDecoder[iCurChanID],
|
if ( iCurNumAudChan == 1 )
|
||||||
NULL,
|
{
|
||||||
0,
|
// mono
|
||||||
&vecvecsData[i][0] );
|
celt_decode ( CeltDecoderMono[iCurChanID],
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&vecvecsData[i][0] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
celt_decode ( CeltDecoderStereo[iCurChanID],
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&vecvecsData[i][0] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send message for get status (for GUI)
|
// send message for get status (for GUI)
|
||||||
|
@ -491,7 +537,10 @@ void CServer::OnTimer()
|
||||||
|
|
||||||
// generate a sparate mix for each channel
|
// generate a sparate mix for each channel
|
||||||
// actual processing of audio data -> mix
|
// actual processing of audio data -> mix
|
||||||
vecsSendData = ProcessData ( vecvecsData, vecvecdGains[i] );
|
vecsSendData = ProcessData ( i,
|
||||||
|
vecvecsData,
|
||||||
|
vecvecdGains[i],
|
||||||
|
vecNumAudioChannels );
|
||||||
|
|
||||||
// get current number of CELT coded bytes
|
// get current number of CELT coded bytes
|
||||||
const int iCeltNumCodedBytes =
|
const int iCeltNumCodedBytes =
|
||||||
|
@ -500,11 +549,24 @@ void CServer::OnTimer()
|
||||||
// CELT encoding
|
// CELT encoding
|
||||||
CVector<unsigned char> vecCeltData ( iCeltNumCodedBytes );
|
CVector<unsigned char> vecCeltData ( iCeltNumCodedBytes );
|
||||||
|
|
||||||
celt_encode ( CeltEncoder[iCurChanID],
|
if ( vecChannels[iCurChanID].GetNumAudioChannels() == 1 )
|
||||||
&vecsSendData[0],
|
{
|
||||||
NULL,
|
// mono
|
||||||
&vecCeltData[0],
|
celt_encode ( CeltEncoderMono[iCurChanID],
|
||||||
iCeltNumCodedBytes );
|
&vecsSendData[0],
|
||||||
|
NULL,
|
||||||
|
&vecCeltData[0],
|
||||||
|
iCeltNumCodedBytes );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
celt_encode ( CeltEncoderStereo[iCurChanID],
|
||||||
|
&vecsSendData[0],
|
||||||
|
NULL,
|
||||||
|
&vecCeltData[0],
|
||||||
|
iCeltNumCodedBytes );
|
||||||
|
}
|
||||||
|
|
||||||
// send separate mix to current clients
|
// send separate mix to current clients
|
||||||
Socket.SendPacket (
|
Socket.SendPacket (
|
||||||
|
@ -523,39 +585,136 @@ void CServer::OnTimer()
|
||||||
CycleTimeVariance.Update();
|
CycleTimeVariance.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector<int16_t> CServer::ProcessData ( CVector<CVector<int16_t> >& vecvecsData,
|
CVector<int16_t> CServer::ProcessData ( const int iCurIndex,
|
||||||
CVector<double>& vecdGains )
|
CVector<CVector<int16_t> >& vecvecsData,
|
||||||
|
CVector<double>& vecdGains,
|
||||||
|
CVector<int>& vecNumAudioChannels )
|
||||||
{
|
{
|
||||||
int i;
|
int i, j, k;
|
||||||
|
|
||||||
|
// get number of audio channels of current channel
|
||||||
|
const int iCurNumAudChan = vecNumAudioChannels[iCurIndex];
|
||||||
|
|
||||||
|
// number of samples for output vector
|
||||||
|
const int iNumOutSamples = iCurNumAudChan * SYSTEM_FRAME_SIZE_SAMPLES;
|
||||||
|
|
||||||
// init return vector with zeros since we mix all channels on that vector
|
// init return vector with zeros since we mix all channels on that vector
|
||||||
|
CVector<int16_t> vecsOutData ( iNumOutSamples, 0 );
|
||||||
// TODO speed optimization: avoid using the zero vector, use the first valid
|
|
||||||
// data vector for initialization instead (take care of gain of this data, too!)
|
|
||||||
|
|
||||||
CVector<int16_t> vecsOutData ( SYSTEM_FRAME_SIZE_SAMPLES, 0 );
|
|
||||||
|
|
||||||
const int iNumClients = vecvecsData.Size();
|
const int iNumClients = vecvecsData.Size();
|
||||||
|
|
||||||
// mix all audio data from all clients together
|
// mix all audio data from all clients together
|
||||||
for ( int j = 0; j < iNumClients; j++ )
|
if ( iCurNumAudChan == 1 )
|
||||||
{
|
{
|
||||||
// if channel gain is 1, avoid multiplication for speed optimization
|
// Mono target channel -------------------------------------------------
|
||||||
if ( vecdGains[j] == static_cast<double> ( 1.0 ) )
|
for ( j = 0; j < iNumClients; j++ )
|
||||||
{
|
{
|
||||||
for ( i = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++ )
|
// if channel gain is 1, avoid multiplication for speed optimization
|
||||||
|
if ( vecdGains[j] == static_cast<double> ( 1.0 ) )
|
||||||
{
|
{
|
||||||
vecsOutData[i] =
|
if ( vecNumAudioChannels[j] == 1 )
|
||||||
Double2Short ( vecsOutData[i] + vecvecsData[j][i] );
|
{
|
||||||
|
// mono
|
||||||
|
for ( i = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++ )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] + vecvecsData[j][i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo: apply stereo-to-mono attenuation
|
||||||
|
for ( i = 0, k = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++, k += 2 )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] +
|
||||||
|
( vecvecsData[j][k] + vecvecsData[j][k + 1] ) / 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( vecNumAudioChannels[j] == 1 )
|
||||||
|
{
|
||||||
|
// mono
|
||||||
|
for ( i = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++ )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] +
|
||||||
|
vecvecsData[j][i] * vecdGains[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo: apply stereo-to-mono attenuation
|
||||||
|
for ( i = 0, k = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++, k += 2 )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] + vecdGains[j] *
|
||||||
|
( vecvecsData[j][k] + vecvecsData[j][k + 1] ) / 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stereo target channel -----------------------------------------------
|
||||||
|
for ( j = 0; j < iNumClients; j++ )
|
||||||
{
|
{
|
||||||
for ( i = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++ )
|
// if channel gain is 1, avoid multiplication for speed optimization
|
||||||
|
if ( vecdGains[j] == static_cast<double> ( 1.0 ) )
|
||||||
{
|
{
|
||||||
vecsOutData[i] =
|
if ( vecNumAudioChannels[j] == 1 )
|
||||||
Double2Short ( vecsOutData[i] +
|
{
|
||||||
vecvecsData[j][i] * vecdGains[j] );
|
// mono: copy same mono data in both out stereo audio channels
|
||||||
|
for ( i = 0, k = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++, k += 2 )
|
||||||
|
{
|
||||||
|
// left channel
|
||||||
|
vecsOutData[k] =
|
||||||
|
Double2Short ( vecsOutData[k] + vecvecsData[j][i] );
|
||||||
|
|
||||||
|
// right channel
|
||||||
|
vecsOutData[k + 1] =
|
||||||
|
Double2Short ( vecsOutData[k + 1] + vecvecsData[j][i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
for ( i = 0; i < iNumOutSamples; i++ )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] + vecvecsData[j][i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( vecNumAudioChannels[j] == 1 )
|
||||||
|
{
|
||||||
|
// mono: copy same mono data in both out stereo audio channels
|
||||||
|
for ( i = 0, k = 0; i < SYSTEM_FRAME_SIZE_SAMPLES; i++, k += 2 )
|
||||||
|
{
|
||||||
|
// left channel
|
||||||
|
vecsOutData[k] = Double2Short (
|
||||||
|
vecsOutData[k] + vecvecsData[j][i] * vecdGains[j] );
|
||||||
|
|
||||||
|
// right channel
|
||||||
|
vecsOutData[k + 1] = Double2Short (
|
||||||
|
vecsOutData[k + 1] + vecvecsData[j][i] * vecdGains[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// stereo
|
||||||
|
for ( i = 0; i < iNumOutSamples; i++ )
|
||||||
|
{
|
||||||
|
vecsOutData[i] =
|
||||||
|
Double2Short ( vecsOutData[i] +
|
||||||
|
vecvecsData[j][i] * vecdGains[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
src/server.h
15
src/server.h
|
@ -140,8 +140,10 @@ protected:
|
||||||
const QString& strChatText );
|
const QString& strChatText );
|
||||||
void WriteHTMLChannelList();
|
void WriteHTMLChannelList();
|
||||||
|
|
||||||
CVector<int16_t> ProcessData ( CVector<CVector<int16_t> >& vecvecsData,
|
CVector<int16_t> ProcessData ( const int iCurIndex,
|
||||||
CVector<double>& vecdGains );
|
CVector<CVector<int16_t> >& vecvecsData,
|
||||||
|
CVector<double>& vecdGains,
|
||||||
|
CVector<int>& vecNumAudioChannels );
|
||||||
|
|
||||||
virtual void customEvent ( QEvent* Event );
|
virtual void customEvent ( QEvent* Event );
|
||||||
|
|
||||||
|
@ -151,9 +153,12 @@ protected:
|
||||||
QMutex Mutex;
|
QMutex Mutex;
|
||||||
|
|
||||||
// audio encoder/decoder
|
// audio encoder/decoder
|
||||||
CELTMode* CeltMode[MAX_NUM_CHANNELS];
|
CELTMode* CeltModeMono[MAX_NUM_CHANNELS];
|
||||||
CELTEncoder* CeltEncoder[MAX_NUM_CHANNELS];
|
CELTEncoder* CeltEncoderMono[MAX_NUM_CHANNELS];
|
||||||
CELTDecoder* CeltDecoder[MAX_NUM_CHANNELS];
|
CELTDecoder* CeltDecoderMono[MAX_NUM_CHANNELS];
|
||||||
|
CELTMode* CeltModeStereo[MAX_NUM_CHANNELS];
|
||||||
|
CELTEncoder* CeltEncoderStereo[MAX_NUM_CHANNELS];
|
||||||
|
CELTDecoder* CeltDecoderStereo[MAX_NUM_CHANNELS];
|
||||||
|
|
||||||
CVector<QString> vstrChatColors;
|
CVector<QString> vstrChatColors;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue