big changes on software structure, intermediate backup checkin -> NOT WORKING correctly right now

This commit is contained in:
Volker Fischer 2009-03-01 11:17:35 +00:00
parent 8843e94822
commit 91071384d2
26 changed files with 557 additions and 1236 deletions

View File

@ -48,12 +48,12 @@ class CSound : public CSoundBase
public: public:
CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) : CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
#if WITH_SOUND #if WITH_SOUND
CSoundBase ( fpNewCallback, arg ), rhandle ( NULL ), CSoundBase ( false, fpNewCallback, arg ), rhandle ( NULL ),
phandle ( NULL ), iCurPeriodSizeIn ( NUM_PERIOD_BLOCKS_IN ), phandle ( NULL ), iCurPeriodSizeIn ( NUM_PERIOD_BLOCKS_IN ),
iCurPeriodSizeOut ( NUM_PERIOD_BLOCKS_OUT ), bChangParamIn ( true ), iCurPeriodSizeOut ( NUM_PERIOD_BLOCKS_OUT ), bChangParamIn ( true ),
bChangParamOut ( true ) {} bChangParamOut ( true ) {}
#else #else
CSoundBase ( fpNewCallback, arg ) {} CSoundBase ( false, fpNewCallback, arg ) {}
#endif #endif
virtual ~CSound() { Close(); } virtual ~CSound() { Close(); }

View File

@ -134,13 +134,6 @@ protected:
class CAudioCompression class CAudioCompression
{ {
public: public:
enum EAudComprType
{
CT_NONE = 0,
CT_IMAADPCM = 1,
CT_MSADPCM = 2
};
CAudioCompression() {} CAudioCompression() {}
virtual ~CAudioCompression() {} virtual ~CAudioCompression() {}

View File

@ -128,18 +128,22 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags f ) : QFra
// connections ------------------------------------------------------------- // connections -------------------------------------------------------------
// CODE TAG: MAX_NUM_CHANNELS_TAG // CODE TAG: MAX_NUM_CHANNELS_TAG
// make sure we have MAX_NUM_CHANNELS connections!!! // make sure we have MAX_NUM_CHANNELS connections!!!
QObject::connect(vecpChanFader[0],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh0(double))); QObject::connect ( vecpChanFader[0], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh0 ( double ) ) );
QObject::connect(vecpChanFader[1],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh1(double))); QObject::connect ( vecpChanFader[1], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh1 ( double ) ) );
QObject::connect(vecpChanFader[2],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh2(double))); QObject::connect ( vecpChanFader[2], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh2 ( double ) ) );
QObject::connect(vecpChanFader[3],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh3(double))); QObject::connect ( vecpChanFader[3], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh3 ( double ) ) );
QObject::connect(vecpChanFader[4],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh4(double))); QObject::connect ( vecpChanFader[4], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh4 ( double ) ) );
QObject::connect(vecpChanFader[5],SIGNAL(valueChanged(double)),this,SLOT(OnValueChangedCh5(double))); QObject::connect ( vecpChanFader[5], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh5 ( double ) ) );
QObject::connect ( vecpChanFader[6], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh6 ( double ) ) );
QObject::connect ( vecpChanFader[7], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh7 ( double ) ) );
QObject::connect ( vecpChanFader[8], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh8 ( double ) ) );
QObject::connect ( vecpChanFader[9], SIGNAL ( valueChanged ( double ) ), this, SLOT ( OnValueChangedCh9 ( double ) ) );
} }
void CAudioMixerBoard::HideAll() void CAudioMixerBoard::HideAll()
{ {
// make old controls invisible // make old controls invisible
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
vecpChanFader[i]->Hide(); vecpChanFader[i]->Hide();
} }
@ -149,7 +153,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelShortInfo>& vecCh
{ {
// search for channels with are already present and preserver their gain // search for channels with are already present and preserver their gain
// setting, for all other channels, reset gain // setting, for all other channels, reset gain
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
bool bFaderIsUsed = false; bool bFaderIsUsed = false;

View File

@ -105,6 +105,10 @@ public slots:
void OnValueChangedCh3 ( double dValue ) { emit ChangeChanGain ( 3, dValue ); } void OnValueChangedCh3 ( double dValue ) { emit ChangeChanGain ( 3, dValue ); }
void OnValueChangedCh4 ( double dValue ) { emit ChangeChanGain ( 4, dValue ); } void OnValueChangedCh4 ( double dValue ) { emit ChangeChanGain ( 4, dValue ); }
void OnValueChangedCh5 ( double dValue ) { emit ChangeChanGain ( 5, dValue ); } void OnValueChangedCh5 ( double dValue ) { emit ChangeChanGain ( 5, dValue ); }
void OnValueChangedCh6 ( double dValue ) { emit ChangeChanGain ( 6, dValue ); }
void OnValueChangedCh7 ( double dValue ) { emit ChangeChanGain ( 7, dValue ); }
void OnValueChangedCh8 ( double dValue ) { emit ChangeChanGain ( 8, dValue ); }
void OnValueChangedCh9 ( double dValue ) { emit ChangeChanGain ( 9, dValue ); }
signals: signals:
void ChangeChanGain ( int iId, double dGain ); void ChangeChanGain ( int iId, double dGain );

View File

@ -32,10 +32,9 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
bWriteStatusHTMLFile ( false ) bWriteStatusHTMLFile ( false )
{ {
// enable all channels and set server flag // enable all channels and set server flag
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
vecChannels[i].SetEnable ( true ); vecChannels[i].SetEnable ( true );
vecChannels[i].SetIsServer ( true );
vecChannels[i].SetForceLowUploadRate ( bForceLowUploadRate ); vecChannels[i].SetForceLowUploadRate ( bForceLowUploadRate );
} }
@ -57,6 +56,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh3 ( CVector<uint8_t> ) ) ); QObject::connect ( &vecChannels[3], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh3 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[4], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh4 ( CVector<uint8_t> ) ) ); QObject::connect ( &vecChannels[4], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh4 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[5], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh5 ( CVector<uint8_t> ) ) ); QObject::connect ( &vecChannels[5], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh5 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[6], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh6 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[7], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh7 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[8], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh8 ( CVector<uint8_t> ) ) );
QObject::connect ( &vecChannels[9], SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), this, SLOT ( OnSendProtMessCh9 ( CVector<uint8_t> ) ) );
// request jitter buffer size // request jitter buffer size
QObject::connect ( &vecChannels[0], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh0() ) ); QObject::connect ( &vecChannels[0], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh0() ) );
@ -65,6 +68,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh3() ) ); QObject::connect ( &vecChannels[3], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh3() ) );
QObject::connect ( &vecChannels[4], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh4() ) ); QObject::connect ( &vecChannels[4], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh4() ) );
QObject::connect ( &vecChannels[5], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh5() ) ); QObject::connect ( &vecChannels[5], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh5() ) );
QObject::connect ( &vecChannels[6], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh6() ) );
QObject::connect ( &vecChannels[7], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh7() ) );
QObject::connect ( &vecChannels[8], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh8() ) );
QObject::connect ( &vecChannels[9], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh9() ) );
// request connected clients list // request connected clients list
QObject::connect ( &vecChannels[0], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh0() ) ); QObject::connect ( &vecChannels[0], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh0() ) );
@ -73,6 +80,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh3() ) ); QObject::connect ( &vecChannels[3], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh3() ) );
QObject::connect ( &vecChannels[4], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh4() ) ); QObject::connect ( &vecChannels[4], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh4() ) );
QObject::connect ( &vecChannels[5], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh5() ) ); QObject::connect ( &vecChannels[5], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh5() ) );
QObject::connect ( &vecChannels[6], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh6() ) );
QObject::connect ( &vecChannels[7], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh7() ) );
QObject::connect ( &vecChannels[8], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh8() ) );
QObject::connect ( &vecChannels[9], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh9() ) );
// channel name has changed // channel name has changed
QObject::connect ( &vecChannels[0], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh0() ) ); QObject::connect ( &vecChannels[0], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh0() ) );
@ -81,6 +92,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh3() ) ); QObject::connect ( &vecChannels[3], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh3() ) );
QObject::connect ( &vecChannels[4], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh4() ) ); QObject::connect ( &vecChannels[4], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh4() ) );
QObject::connect ( &vecChannels[5], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh5() ) ); QObject::connect ( &vecChannels[5], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh5() ) );
QObject::connect ( &vecChannels[6], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh6() ) );
QObject::connect ( &vecChannels[7], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh7() ) );
QObject::connect ( &vecChannels[8], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh8() ) );
QObject::connect ( &vecChannels[9], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh9() ) );
// chat text received // chat text received
QObject::connect ( &vecChannels[0], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh0 ( QString ) ) ); QObject::connect ( &vecChannels[0], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh0 ( QString ) ) );
@ -89,6 +104,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh3 ( QString ) ) ); QObject::connect ( &vecChannels[3], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh3 ( QString ) ) );
QObject::connect ( &vecChannels[4], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh4 ( QString ) ) ); QObject::connect ( &vecChannels[4], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh4 ( QString ) ) );
QObject::connect ( &vecChannels[5], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh5 ( QString ) ) ); QObject::connect ( &vecChannels[5], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh5 ( QString ) ) );
QObject::connect ( &vecChannels[6], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh6 ( QString ) ) );
QObject::connect ( &vecChannels[7], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh7 ( QString ) ) );
QObject::connect ( &vecChannels[8], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh8 ( QString ) ) );
QObject::connect ( &vecChannels[9], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh9 ( QString ) ) );
// ping message received // ping message received
QObject::connect ( &vecChannels[0], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh0 ( int ) ) ); QObject::connect ( &vecChannels[0], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh0 ( int ) ) );
@ -97,6 +116,10 @@ CChannelSet::CChannelSet ( const bool bForceLowUploadRate ) :
QObject::connect ( &vecChannels[3], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh3 ( int ) ) ); QObject::connect ( &vecChannels[3], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh3 ( int ) ) );
QObject::connect ( &vecChannels[4], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh4 ( int ) ) ); QObject::connect ( &vecChannels[4], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh4 ( int ) ) );
QObject::connect ( &vecChannels[5], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh5 ( int ) ) ); QObject::connect ( &vecChannels[5], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh5 ( int ) ) );
QObject::connect ( &vecChannels[6], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh6 ( int ) ) );
QObject::connect ( &vecChannels[7], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh7 ( int ) ) );
QObject::connect ( &vecChannels[8], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh8 ( int ) ) );
QObject::connect ( &vecChannels[9], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh9 ( int ) ) );
} }
CVector<CChannelShortInfo> CChannelSet::CreateChannelList() CVector<CChannelShortInfo> CChannelSet::CreateChannelList()
@ -104,7 +127,7 @@ CVector<CChannelShortInfo> CChannelSet::CreateChannelList()
CVector<CChannelShortInfo> vecChanInfo ( 0 ); CVector<CChannelShortInfo> vecChanInfo ( 0 );
// look for free channels // look for free channels
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -125,7 +148,7 @@ void CChannelSet::CreateAndSendChanListForAllConChannels()
CVector<CChannelShortInfo> vecChanInfo ( CChannelSet::CreateChannelList() ); CVector<CChannelShortInfo> vecChanInfo ( CChannelSet::CreateChannelList() );
// now send connected channels list to all connected clients // now send connected channels list to all connected clients
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -148,7 +171,7 @@ void CChannelSet::CreateAndSendChanListForAllExceptThisChan ( const int iCurChan
// now send connected channels list to all connected clients except for // now send connected channels list to all connected clients except for
// the channel with the ID "iCurChanID" // the channel with the ID "iCurChanID"
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( ( vecChannels[i].IsConnected() ) && ( i != iCurChanID ) ) if ( ( vecChannels[i].IsConnected() ) && ( i != iCurChanID ) )
{ {
@ -196,7 +219,7 @@ void CChannelSet::CreateAndSendChatTextForAllConChannels ( const int iCurChanID,
// send chat text to all connected clients --------------------------------- // send chat text to all connected clients ---------------------------------
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -209,7 +232,7 @@ void CChannelSet::CreateAndSendChatTextForAllConChannels ( const int iCurChanID,
int CChannelSet::GetFreeChan() int CChannelSet::GetFreeChan()
{ {
// look for a free channel // look for a free channel
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( !vecChannels[i].IsConnected() ) if ( !vecChannels[i].IsConnected() )
{ {
@ -226,7 +249,7 @@ int CChannelSet::CheckAddr ( const CHostAddress& Addr )
CHostAddress InetAddr; CHostAddress InetAddr;
// check for all possible channels if IP is already in use // check for all possible channels if IP is already in use
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].GetAddress ( InetAddr ) ) if ( vecChannels[i].GetAddress ( InetAddr ) )
{ {
@ -246,8 +269,8 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
const int iNumBytesRead, const int iNumBytesRead,
const CHostAddress& HostAdr ) const CHostAddress& HostAdr )
{ {
bool bRet = false; bool bAudioOK = false;
bool bCreateChanList = false; bool bNewChannelReserved = false;
Mutex.lock(); Mutex.lock();
{ {
@ -270,7 +293,7 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
// reset the channel gains of current channel, at the same // reset the channel gains of current channel, at the same
// time reset gains of this channel ID for all other channels // time reset gains of this channel ID for all other channels
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
vecChannels[iCurChanID].SetGain ( i, (double) 1.0 ); vecChannels[iCurChanID].SetGain ( i, (double) 1.0 );
@ -279,14 +302,8 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
vecChannels[i].SetGain ( iCurChanID, (double) 1.0 ); vecChannels[i].SetGain ( iCurChanID, (double) 1.0 );
} }
// a new client connected to the server, set flag to create and // set flag for new reserved channel
// send all clients the updated channel list, we cannot create bNewChannelReserved = true;
// the message here since the received data has to be put to the
// channel first so that this channel is marked as connected
bCreateChanList = true;
// send message about new channel
emit ChannelConnected ( HostAdr );
} }
else else
{ {
@ -309,25 +326,36 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
{ {
case PS_AUDIO_OK: case PS_AUDIO_OK:
PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_GREEN, iCurChanID ); PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_GREEN, iCurChanID );
bRet = true; // in case we have an audio packet, return true bAudioOK = true; // in case we have an audio packet, return true
break; break;
case PS_AUDIO_ERR: case PS_AUDIO_ERR:
PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_RED, iCurChanID ); PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_RED, iCurChanID );
bRet = true; // in case we have an audio packet, return true bAudioOK = true; // in case we have an audio packet, return true
break; break;
case PS_PROT_ERR: case PS_PROT_ERR:
PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_YELLOW, iCurChanID ); PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_YELLOW, iCurChanID );
// TEST
bAudioOK = true;
break; break;
} }
} }
// after data is put in channel buffer, create channel list message if // after data is put in channel buffer, create channel list message if
// requested // requested
if ( bCreateChanList ) if ( bNewChannelReserved && bAudioOK )
{ {
// send message about new channel
emit ChannelConnected ( HostAdr );
// A new client connected to the server, create and
// send all clients the updated channel list (the list has to
// be created after the received data has to be put to the
// channel first so that this channel is marked as connected)
//
// connected clients list is only send for new connected clients after // connected clients list is only send for new connected clients after
// request, only the already connected clients get the list // request, only the already connected clients get the list
// automatically, because they don't know when new clients connect // automatically, because they don't know when new clients connect
@ -336,7 +364,7 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
} }
Mutex.unlock(); Mutex.unlock();
return bRet; return bAudioOK;
} }
void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID, void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
@ -347,7 +375,7 @@ void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
bool bCreateChanList = false; bool bCreateChanList = false;
// init temporal data vector and clear input buffers // init temporal data vector and clear input buffers
CVector<double> vecdData ( MIN_BLOCK_SIZE_SAMPLES ); CVector<double> vecdData ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
vecChanID.Init ( 0 ); vecChanID.Init ( 0 );
vecvecdData.Init ( 0 ); vecvecdData.Init ( 0 );
@ -358,7 +386,7 @@ void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
Mutex.lock(); Mutex.lock();
{ {
// check all possible channels // check all possible channels
for ( i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
// read out all input buffers to decrease timeout counter on // read out all input buffers to decrease timeout counter on
// disconnected channels // disconnected channels
@ -424,20 +452,18 @@ void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses, void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CVector<QString>& vecsName, CVector<QString>& vecsName,
CVector<int>& veciJitBufSize, CVector<int>& veciJitBufSize,
CVector<int>& veciNetwOutBlSiFact, CVector<int>& veciNetwOutBlSiFact )
CVector<int>& veciNetwInBlSiFact )
{ {
CHostAddress InetAddr; CHostAddress InetAddr;
// init return values // init return values
vecHostAddresses.Init ( MAX_NUM_CHANNELS ); vecHostAddresses.Init ( USED_NUM_CHANNELS );
vecsName.Init ( MAX_NUM_CHANNELS ); vecsName.Init ( USED_NUM_CHANNELS );
veciJitBufSize.Init ( MAX_NUM_CHANNELS ); veciJitBufSize.Init ( USED_NUM_CHANNELS );
veciNetwOutBlSiFact.Init ( MAX_NUM_CHANNELS ); veciNetwOutBlSiFact.Init ( USED_NUM_CHANNELS );
veciNetwInBlSiFact.Init ( MAX_NUM_CHANNELS );
// check all possible channels // check all possible channels
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].GetAddress ( InetAddr ) ) if ( vecChannels[i].GetAddress ( InetAddr ) )
{ {
@ -446,7 +472,6 @@ void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
vecsName[i] = vecChannels[i].GetName(); vecsName[i] = vecChannels[i].GetName();
veciJitBufSize[i] = vecChannels[i].GetSockBufSize(); veciJitBufSize[i] = vecChannels[i].GetSockBufSize();
veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut(); veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut();
veciNetwInBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactIn();
} }
} }
} }
@ -482,7 +507,7 @@ void CChannelSet::WriteHTMLChannelList()
// get the number of connected clients // get the number of connected clients
int iNumConnClients = 0; int iNumConnClients = 0;
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -499,7 +524,7 @@ void CChannelSet::WriteHTMLChannelList()
else else
{ {
// write entry for each connected client // write entry for each connected client
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( vecChannels[i].IsConnected() ) if ( vecChannels[i].IsConnected() )
{ {
@ -530,13 +555,10 @@ void CChannelSet::WriteHTMLChannelList()
/******************************************************************************\ /******************************************************************************\
* CChannel * * CChannel *
\******************************************************************************/ \******************************************************************************/
CChannel::CChannel() : sName ( "" ), CChannel::CChannel ( const bool bNIsServer ) : bIsServer ( bNIsServer ),
vecdGains ( MAX_NUM_CHANNELS, (double) 1.0 ), bIsServer ( false ), sName ( "" ), vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ),
bForceLowUploadRate ( false ), bIsEnabled ( false ), bForceLowUploadRate ( false ),
// it is important to give the following parameters meaningful initial iCurNetwOutBlSiFact ( DEF_NET_BLOCK_SIZE_FACTOR )
// values because they are dependend on each other
iCurSockBufSize ( DEF_NET_BUF_SIZE_NUM_BL ),
iCurNetwInBlSiFact ( DEF_NET_BLOCK_SIZE_FACTOR )
{ {
// query all possible network in buffer sizes for determining if an // query all possible network in buffer sizes for determining if an
// audio packet was received (the following code only works if all // audio packet was received (the following code only works if all
@ -549,11 +571,11 @@ CChannel::CChannel() : sName ( "" ),
// init special mode // init special mode
// TEST -> 64 // TEST -> 128
vecNetwBufferInProps[0].iBlockSizeFactor = 1; vecNetwBufferInProps[0].iAudioBlockSize = 128;
vecNetwBufferInProps[0].eAudComprType = CAudioCompression::CT_NONE; vecNetwBufferInProps[0].eAudComprType = CT_NONE;
vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init ( vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init (
vecNetwBufferInProps[0].iBlockSizeFactor * 64, vecNetwBufferInProps[0].iAudioBlockSize,
vecNetwBufferInProps[0].eAudComprType ); vecNetwBufferInProps[0].eAudComprType );
@ -567,26 +589,26 @@ vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init (
// network block size factor must start from 1 -> i + 1 // network block size factor must start from 1 -> i + 1
const int iCurNetBlockSizeFact = i + 1; const int iCurNetBlockSizeFact = i + 1;
vecNetwBufferInProps[iNoneIdx].iBlockSizeFactor = iCurNetBlockSizeFact; vecNetwBufferInProps[iNoneIdx].iAudioBlockSize = iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES;
vecNetwBufferInProps[iIMAIdx].iBlockSizeFactor = iCurNetBlockSizeFact; vecNetwBufferInProps[iIMAIdx].iAudioBlockSize = iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES;
vecNetwBufferInProps[iMSIdx].iBlockSizeFactor = iCurNetBlockSizeFact; vecNetwBufferInProps[iMSIdx].iAudioBlockSize = iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES;
// None (no audio compression) // None (no audio compression)
vecNetwBufferInProps[iNoneIdx].eAudComprType = CAudioCompression::CT_NONE; vecNetwBufferInProps[iNoneIdx].eAudComprType = CT_NONE;
vecNetwBufferInProps[iNoneIdx].iNetwInBufSize = AudioCompressionIn.Init ( vecNetwBufferInProps[iNoneIdx].iNetwInBufSize = AudioCompressionIn.Init (
vecNetwBufferInProps[iNoneIdx].iBlockSizeFactor * MIN_BLOCK_SIZE_SAMPLES, vecNetwBufferInProps[iNoneIdx].iAudioBlockSize,
vecNetwBufferInProps[iNoneIdx].eAudComprType ); vecNetwBufferInProps[iNoneIdx].eAudComprType );
// IMA ADPCM // IMA ADPCM
vecNetwBufferInProps[iIMAIdx].eAudComprType = CAudioCompression::CT_IMAADPCM; vecNetwBufferInProps[iIMAIdx].eAudComprType = CT_IMAADPCM;
vecNetwBufferInProps[iIMAIdx].iNetwInBufSize = AudioCompressionIn.Init ( vecNetwBufferInProps[iIMAIdx].iNetwInBufSize = AudioCompressionIn.Init (
vecNetwBufferInProps[iIMAIdx].iBlockSizeFactor * MIN_BLOCK_SIZE_SAMPLES, vecNetwBufferInProps[iIMAIdx].iAudioBlockSize,
vecNetwBufferInProps[iIMAIdx].eAudComprType ); vecNetwBufferInProps[iIMAIdx].eAudComprType );
// MS ADPCM // MS ADPCM
vecNetwBufferInProps[iMSIdx].eAudComprType = CAudioCompression::CT_MSADPCM; vecNetwBufferInProps[iMSIdx].eAudComprType = CT_MSADPCM;
vecNetwBufferInProps[iMSIdx].iNetwInBufSize = AudioCompressionIn.Init ( vecNetwBufferInProps[iMSIdx].iNetwInBufSize = AudioCompressionIn.Init (
vecNetwBufferInProps[iMSIdx].iBlockSizeFactor * MIN_BLOCK_SIZE_SAMPLES, vecNetwBufferInProps[iMSIdx].iAudioBlockSize,
vecNetwBufferInProps[iMSIdx].eAudComprType ); vecNetwBufferInProps[iMSIdx].eAudComprType );
} }
@ -594,11 +616,14 @@ vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init (
SetSockBufSize ( DEF_NET_BUF_SIZE_NUM_BL ); SetSockBufSize ( DEF_NET_BUF_SIZE_NUM_BL );
// set initial input and output block size factors // set initial input and output block size factors
SetNetwInBlSiFactAndCompr ( DEF_NET_BLOCK_SIZE_FACTOR, CAudioCompression::CT_MSADPCM ); SetAudioBlockSizeAndComprIn (
SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR ); MIN_SERVER_BLOCK_SIZE_SAMPLES * DEF_NET_BLOCK_SIZE_FACTOR,
CT_MSADPCM );
SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR );
// set initial audio compression format for output // set initial audio compression format for output
SetAudioCompressionOut ( CAudioCompression::CT_MSADPCM ); SetAudioCompressionOut ( CT_MSADPCM );
// init time-out for the buffer with zero -> no connection // init time-out for the buffer with zero -> no connection
iConTimeOut = 0; iConTimeOut = 0;
@ -640,6 +665,26 @@ vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init (
QObject::connect( &Protocol, SIGNAL ( PingReceived ( int ) ), QObject::connect( &Protocol, SIGNAL ( PingReceived ( int ) ),
this, SIGNAL ( PingReceived ( int ) ) ); this, SIGNAL ( PingReceived ( int ) ) );
QObject::connect ( &Protocol,
SIGNAL ( NetTranspPropsReceived ( CNetworkTransportProps ) ),
this, SLOT ( OnNetTranspPropsReceived ( CNetworkTransportProps ) ) );
}
bool CChannel::ProtocolIsEnabled()
{
// for the server, only enable protocol if the channel is connected, i.e.,
// successfully audio packets are received from a client
// for the client, enable protocol if the channel is enabled, i.e., the
// connection button was hit by the user
if ( bIsServer )
{
return IsConnected();
}
else
{
return bIsEnabled;
}
} }
void CChannel::SetEnable ( const bool bNEnStat ) void CChannel::SetEnable ( const bool bNEnStat )
@ -649,10 +694,11 @@ void CChannel::SetEnable ( const bool bNEnStat )
// set internal parameter // set internal parameter
bIsEnabled = bNEnStat; bIsEnabled = bNEnStat;
// if channel is not enabled, reset time out count // if channel is not enabled, reset time out count and protocol
if ( !bNEnStat ) if ( !bNEnStat )
{ {
iConTimeOut = 0; iConTimeOut = 0;
Protocol.Reset();
} }
} }
@ -669,55 +715,73 @@ void CChannel::SetForceLowUploadRate ( const bool bNFoLoUpRat )
bForceLowUploadRate = bNFoLoUpRat; bForceLowUploadRate = bNFoLoUpRat;
} }
void CChannel::SetNetwInBlSiFactAndCompr ( const int iNewBlockSizeFactor, void CChannel::SetAudioBlockSizeAndComprIn ( const int iNewBlockSize,
const CAudioCompression::EAudComprType eNewAudComprType ) const EAudComprType eNewAudComprType )
{ {
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// store new value // store block size value
iCurNetwInBlSiFact = iNewBlockSizeFactor; iCurAudioBlockSizeIn = iNewBlockSize;
// init audio compression unit // init audio compression unit
AudioCompressionIn.Init ( iNewBlockSizeFactor * MIN_BLOCK_SIZE_SAMPLES, AudioCompressionIn.Init ( iNewBlockSize, eNewAudComprType );
eNewAudComprType );
// initial value for connection time out counter // initial value for connection time out counter
iConTimeOutStartVal = ( CON_TIME_OUT_SEC_MAX * 1000 ) / iConTimeOutStartVal =
( iNewBlockSizeFactor * MIN_BLOCK_DURATION_MS ); ( CON_TIME_OUT_SEC_MAX * SYSTEM_SAMPLE_RATE ) / iNewBlockSize;
}
// socket buffer must be adjusted void CChannel::SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut )
SetSockBufSizeIntern ( GetSockBufSize() ); {
// this function is intended for the client (not the server)
QMutexLocker locker ( &Mutex );
// store new value
iCurAudioBlockSizeOut = iNewAudioBlockSizeOut;
iAudComprSizeOut =
AudioCompressionOut.Init ( iNewAudioBlockSizeOut, eAudComprTypeOut );
} }
void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut ) void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut )
{ {
// this function is intended for the server (not the client)
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
if ( !bForceLowUploadRate ) // use the network block size factor only for the server
if ( ( !bForceLowUploadRate ) && bIsServer )
{ {
// store new value // store new value
iCurNetwOutBlSiFact = iNewNetwBlSiFactOut; iCurNetwOutBlSiFact = iNewNetwBlSiFactOut;
// init audio compression and get audio compression block size // init audio compression and get audio compression block size
iAudComprSizeOut = AudioCompressionOut.Init ( iAudComprSizeOut = AudioCompressionOut.Init (
iNewNetwBlSiFactOut * MIN_BLOCK_SIZE_SAMPLES, eAudComprTypeOut ); iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES, eAudComprTypeOut );
// init conversion buffer // init conversion buffer
ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_BLOCK_SIZE_SAMPLES ); ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES );
} }
} }
void CChannel::SetAudioCompressionOut ( const CAudioCompression::EAudComprType eNewAudComprTypeOut ) void CChannel::SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut )
{ {
if ( !bForceLowUploadRate ) if ( !bForceLowUploadRate )
{ {
// store new value // store new value
eAudComprTypeOut = eNewAudComprTypeOut; eAudComprTypeOut = eNewAudComprTypeOut;
// call "set network buffer size factor" function because its initialization if ( bIsServer )
// depends on the audio compression format and implicitely, the audio compression {
// is initialized // call "set network buffer size factor" function because its
SetNetwBufSizeFactOut ( iCurNetwOutBlSiFact ); // 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 );
}
} }
} }
@ -725,21 +789,11 @@ void CChannel::SetSockBufSize ( const int iNumBlocks )
{ {
QMutexLocker locker ( &Mutex ); // this opperation must be done with mutex QMutexLocker locker ( &Mutex ); // this opperation must be done with mutex
SetSockBufSizeIntern ( iNumBlocks );
}
void CChannel::SetSockBufSizeIntern ( const int iNumBlocks )
{
iCurSockBufSize = iNumBlocks; iCurSockBufSize = iNumBlocks;
// the idea of setting the jitter buffer is as follows: // the network block size is a multiple of the internal minimal
// The network block size is a multiple of the internal minimal // block size
// block size. Therefore, the minimum jitter buffer size must be SockBuf.Init ( MIN_SERVER_BLOCK_SIZE_SAMPLES, iNumBlocks );
// so that it can take one network buffer -> NET_BLOCK_SIZE_FACTOR.
// The actual jitter compensation are then the additional blocks of
// the internal block size, which is set with SetSockBufSize
SockBuf.Init ( MIN_BLOCK_SIZE_SAMPLES,
iNumBlocks + iCurNetwInBlSiFact );
} }
void CChannel::SetGain ( const int iChanID, const double dNewGain ) void CChannel::SetGain ( const int iChanID, const double dNewGain )
@ -747,7 +801,7 @@ void CChannel::SetGain ( const int iChanID, const double dNewGain )
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// set value (make sure channel ID is in range) // set value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) ) if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) )
{ {
vecdGains[iChanID] = dNewGain; vecdGains[iChanID] = dNewGain;
} }
@ -758,7 +812,7 @@ double CChannel::GetGain ( const int iChanID )
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// get value (make sure channel ID is in range) // get value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) ) if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) )
{ {
return vecdGains[iChanID]; return vecdGains[iChanID];
} }
@ -801,8 +855,9 @@ QString CChannel::GetName()
void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage ) void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage )
{ {
// only send messages if we are connected, otherwise delete complete queue // only send messages if protocol is enabled, otherwise delete complete
if ( IsConnected() ) // queue
if ( ProtocolIsEnabled() )
{ {
// emit message to actually send the data // emit message to actually send the data
emit MessReadyForSending ( vecMessage ); emit MessReadyForSending ( vecMessage );
@ -810,7 +865,7 @@ void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage )
else else
{ {
// delete send message queue // delete send message queue
Protocol.DeleteSendMessQueue(); Protocol.Reset();
} }
} }
@ -834,6 +889,26 @@ void CChannel::OnChangeChanName ( QString strName )
SetName ( strName ); SetName ( strName );
} }
void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps )
{
QMutexLocker locker ( &Mutex );
// TEST
// TODO use mutex in Put function
// TODO check possiblity of received parameter -> error checking
vecNetwBufferInProps[0].iAudioBlockSize = NetworkTransportProps.iMonoAudioBlockSize;
vecNetwBufferInProps[0].eAudComprType = NetworkTransportProps.eAudioCodingType;
vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init (
vecNetwBufferInProps[0].iAudioBlockSize,
vecNetwBufferInProps[0].eAudComprType );
}
bool CChannel::GetAddress(CHostAddress& RetAddr) bool CChannel::GetAddress(CHostAddress& RetAddr)
{ {
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
@ -863,8 +938,8 @@ EPutDataStat CChannel::PutData ( const CVector<unsigned char>& vecbyData,
if ( bIsEnabled ) if ( bIsEnabled )
{ {
// first check if this is protocol data // first check if this is protocol data
// only use protocol data if channel is connected // only use protocol data if protocol mechanism is enabled
if ( IsConnected() ) if ( ProtocolIsEnabled() )
{ {
// parse the message assuming this is a protocol message // parse the message assuming this is a protocol message
if ( !Protocol.ParseMessage ( vecbyData, iNumBytes ) ) if ( !Protocol.ParseMessage ( vecbyData, iNumBytes ) )
@ -889,18 +964,18 @@ EPutDataStat CChannel::PutData ( const CVector<unsigned char>& vecbyData,
bIsAudioPacket = true; bIsAudioPacket = true;
// check if we are correctly initialized // check if we are correctly initialized
const int iNewNetwInBlSiFact = const int iNewAudioBlockSize =
vecNetwBufferInProps[i].iBlockSizeFactor; vecNetwBufferInProps[i].iAudioBlockSize;
const CAudioCompression::EAudComprType eNewAudComprType = const EAudComprType eNewAudComprType =
vecNetwBufferInProps[i].eAudComprType; vecNetwBufferInProps[i].eAudComprType;
if ( ( iNewNetwInBlSiFact != iCurNetwInBlSiFact ) || if ( ( iNewAudioBlockSize != iCurAudioBlockSizeIn ) ||
( eNewAudComprType != AudioCompressionIn.GetType() ) ) ( eNewAudComprType != AudioCompressionIn.GetType() ) )
{ {
// re-initialize to new value // re-initialize to new value
SetNetwInBlSiFactAndCompr ( iNewNetwInBlSiFact, SetAudioBlockSizeAndComprIn (
eNewAudComprType ); iNewAudioBlockSize, eNewAudComprType );
} }
// in case of a server channel, use the same audio // in case of a server channel, use the same audio
@ -915,17 +990,18 @@ EPutDataStat CChannel::PutData ( const CVector<unsigned char>& vecbyData,
} }
} }
// only process if packet has correct size Mutex.lock();
if ( bIsAudioPacket )
{ {
Mutex.lock(); // only process audio if packet has correct size
if ( bIsAudioPacket )
{ {
// decompress audio // decompress audio
CVector<short> vecsDecomprAudio ( AudioCompressionIn.Decode ( vecbyData ) ); CVector<short> vecsDecomprAudio ( AudioCompressionIn.Decode ( vecbyData ) );
// convert received data from short to double // convert received data from short to double
CVector<double> vecdDecomprAudio ( iCurNetwInBlSiFact * MIN_BLOCK_SIZE_SAMPLES ); const int iAudioSize = vecsDecomprAudio.Size();
for ( int i = 0; i < iCurNetwInBlSiFact * MIN_BLOCK_SIZE_SAMPLES; i++ ) CVector<double> vecdDecomprAudio ( iAudioSize );
for ( int i = 0; i < iAudioSize; i++ )
{ {
vecdDecomprAudio[i] = static_cast<double> ( vecsDecomprAudio[i] ); vecdDecomprAudio[i] = static_cast<double> ( vecsDecomprAudio[i] );
} }
@ -938,21 +1014,28 @@ EPutDataStat CChannel::PutData ( const CVector<unsigned char>& vecbyData,
{ {
eRet = PS_AUDIO_ERR; eRet = PS_AUDIO_ERR;
} }
// check if channel was not connected, this is a new connection
bNewConnection = !IsConnected();
// reset time-out counter
iConTimeOut = iConTimeOutStartVal;
} }
Mutex.unlock(); else
} {
else // the protocol parsing failed and this was no audio block,
{ // we treat this as protocol error (unkown packet)
// the protocol parsing failed and this was no audio block, eRet = PS_PROT_ERR;
// we treat this as protocol error (unkown packet) }
eRet = PS_PROT_ERR;
// all network packets except of valid llcon protocol messages
// regardless if they are valid or invalid audio packets lead to
// a state change to a connected channel
// this is because protocol messages can only be sent on a
// connected channel and the client has to inform the server
// about the audio packet properties via the protocol
// check if channel was not connected, this is a new connection
bNewConnection = !IsConnected();
// reset time-out counter
iConTimeOut = iConTimeOutStartVal;
} }
Mutex.unlock();
} }
// inform other objects that new connection was established // inform other objects that new connection was established
@ -1008,13 +1091,22 @@ CVector<unsigned char> CChannel::PrepSendPacket ( const CVector<short>& vecsNPac
// tell the following network send routine that nothing should be sent // tell the following network send routine that nothing should be sent
CVector<unsigned char> vecbySendBuf ( 0 ); CVector<unsigned char> vecbySendBuf ( 0 );
// use conversion buffer to convert sound card block size in network if ( bIsServer )
// block size {
if ( ConvBuf.Put ( vecsNPacket ) ) // use conversion buffer to convert sound card block size in network
// block size
if ( ConvBuf.Put ( vecsNPacket ) )
{
// a packet is ready, compress audio
vecbySendBuf.Init ( iAudComprSizeOut );
vecbySendBuf = AudioCompressionOut.Encode ( ConvBuf.Get() );
}
}
else
{ {
// a packet is ready, compress audio // a packet is ready, compress audio
vecbySendBuf.Init ( iAudComprSizeOut ); vecbySendBuf.Init ( iAudComprSizeOut );
vecbySendBuf = AudioCompressionOut.Encode ( ConvBuf.Get() ); vecbySendBuf = AudioCompressionOut.Encode ( vecsNPacket );
} }
return vecbySendBuf; return vecbySendBuf;

View File

@ -64,7 +64,7 @@ enum EGetDataStat
}; };
// low upload data rate settings // low upload data rate settings
#define LOW_UPL_SET_AUDIO_COMPRESSION CAudioCompression::CT_MSADPCM #define LOW_UPL_SET_AUDIO_COMPRESSION CT_MSADPCM
#define LOW_UPL_SET_BLOCK_SIZE_FACTOR_OUT MAX_NET_BLOCK_SIZE_FACTOR #define LOW_UPL_SET_BLOCK_SIZE_FACTOR_OUT MAX_NET_BLOCK_SIZE_FACTOR
@ -75,7 +75,9 @@ class CChannel : public QObject
Q_OBJECT Q_OBJECT
public: public:
CChannel(); // we have to make "server" the default since I do not see a chance to
// use constructor initialization in the server for a vector of channels
CChannel ( const bool bNIsServer = true );
virtual ~CChannel() {} virtual ~CChannel() {}
EPutDataStat PutData ( const CVector<unsigned char>& vecbyData, EPutDataStat PutData ( const CVector<unsigned char>& vecbyData,
@ -87,7 +89,6 @@ public:
bool IsConnected() const { return iConTimeOut > 0; } bool IsConnected() const { return iConTimeOut > 0; }
void SetEnable ( const bool bNEnStat ); void SetEnable ( const bool bNEnStat );
void SetIsServer ( const bool bNIsServer ) { bIsServer = bNIsServer; }
void SetForceLowUploadRate ( const bool bNFoLoUpRat ); void SetForceLowUploadRate ( const bool bNFoLoUpRat );
void SetAddress ( const CHostAddress NAddr ) { InetAddr = NAddr; } void SetAddress ( const CHostAddress NAddr ) { InetAddr = NAddr; }
@ -109,18 +110,19 @@ public:
void SetSockBufSize ( const int iNumBlocks ); void SetSockBufSize ( const int iNumBlocks );
int GetSockBufSize() { return iCurSockBufSize; } int GetSockBufSize() { return iCurSockBufSize; }
// TEST
void SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut );
void SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut ); void SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut );
int GetNetwBufSizeFactOut() { return iCurNetwOutBlSiFact; } int GetNetwBufSizeFactOut() { return iCurNetwOutBlSiFact; }
int GetNetwBufSizeFactIn() { return iCurNetwInBlSiFact; } void SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut );
EAudComprType GetAudioCompressionOut() { return eAudComprTypeOut; }
void SetAudioCompressionOut ( const CAudioCompression::EAudComprType eNewAudComprTypeOut );
CAudioCompression::EAudComprType GetAudioCompressionOut() { return eAudComprTypeOut; }
// network protocol interface // network protocol interface
void CreateJitBufMes ( const int iJitBufSize ) void CreateJitBufMes ( const int iJitBufSize )
{ {
if ( IsConnected() ) if ( ProtocolIsEnabled() )
{ {
Protocol.CreateJitBufMes ( iJitBufSize ); Protocol.CreateJitBufMes ( iJitBufSize );
} }
@ -132,7 +134,7 @@ public:
void CreateNetwBlSiFactMes ( const int iNetwBlSiFact ) void CreateNetwBlSiFactMes ( const int iNetwBlSiFact )
{ {
if ( IsConnected() ) if ( ProtocolIsEnabled() )
{ {
Protocol.CreateNetwBlSiFactMes ( iNetwBlSiFact ); Protocol.CreateNetwBlSiFactMes ( iNetwBlSiFact );
} }
@ -144,10 +146,10 @@ public:
} }
protected: protected:
void SetNetwInBlSiFactAndCompr ( const int iNewBlockSizeFactor, void SetAudioBlockSizeAndComprIn ( const int iNewBlockSize,
const CAudioCompression::EAudComprType eNewAudComprType ); const EAudComprType eNewAudComprType );
void SetSockBufSizeIntern ( const int iNumBlocks ); bool ProtocolIsEnabled();
// audio compression // audio compression
CAudioCompression AudioCompressionIn; CAudioCompression AudioCompressionIn;
@ -180,20 +182,21 @@ protected:
bool bIsServer; bool bIsServer;
bool bForceLowUploadRate; bool bForceLowUploadRate;
int iCurNetwInBlSiFact; int iCurAudioBlockSizeIn;
int iCurNetwOutBlSiFact; int iCurNetwOutBlSiFact;
int iCurAudioBlockSizeOut;
QMutex Mutex; QMutex Mutex;
struct sNetwBufferInProps struct sNetwBufferInProps
{ {
int iNetwInBufSize; int iNetwInBufSize;
int iBlockSizeFactor; int iAudioBlockSize;
CAudioCompression::EAudComprType eAudComprType; EAudComprType eAudComprType;
}; };
CVector<sNetwBufferInProps> vecNetwBufferInProps; CVector<sNetwBufferInProps> vecNetwBufferInProps;
CAudioCompression::EAudComprType eAudComprTypeOut; EAudComprType eAudComprTypeOut;
public slots: public slots:
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); void OnSendProtMessage ( CVector<uint8_t> vecMessage );
@ -201,6 +204,7 @@ public slots:
void OnNetwBlSiFactChange ( int iNewNetwBlSiFact ); void OnNetwBlSiFactChange ( int iNewNetwBlSiFact );
void OnChangeChanGain ( int iChanID, double dNewGain ); void OnChangeChanGain ( int iChanID, double dNewGain );
void OnChangeChanName ( QString strName ); void OnChangeChanName ( QString strName );
void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps );
signals: signals:
void MessReadyForSending ( CVector<uint8_t> vecMessage ); void MessReadyForSending ( CVector<uint8_t> vecMessage );
@ -237,8 +241,7 @@ public:
void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses, void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CVector<QString>& vecsName, CVector<QString>& vecsName,
CVector<int>& veciJitBufSize, CVector<int>& veciJitBufSize,
CVector<int>& veciNetwOutBlSiFact, CVector<int>& veciNetwOutBlSiFact );
CVector<int>& veciNetwInBlSiFact );
// access functions for actual channels // access functions for actual channels
bool IsConnected ( const int iChanNum ) bool IsConnected ( const int iChanNum )
@ -284,6 +287,10 @@ public slots:
void OnSendProtMessCh3 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 3, mess ); } void OnSendProtMessCh3 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 3, mess ); }
void OnSendProtMessCh4 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 4, mess ); } void OnSendProtMessCh4 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 4, mess ); }
void OnSendProtMessCh5 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 5, mess ); } void OnSendProtMessCh5 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 5, mess ); }
void OnSendProtMessCh6 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 6, mess ); }
void OnSendProtMessCh7 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 7, mess ); }
void OnSendProtMessCh8 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 8, mess ); }
void OnSendProtMessCh9 ( CVector<uint8_t> mess ) { emit MessReadyForSending ( 9, mess ); }
void OnNewConnectionCh0() { vecChannels[0].CreateReqJitBufMes(); } void OnNewConnectionCh0() { vecChannels[0].CreateReqJitBufMes(); }
void OnNewConnectionCh1() { vecChannels[1].CreateReqJitBufMes(); } void OnNewConnectionCh1() { vecChannels[1].CreateReqJitBufMes(); }
@ -291,6 +298,10 @@ public slots:
void OnNewConnectionCh3() { vecChannels[3].CreateReqJitBufMes(); } void OnNewConnectionCh3() { vecChannels[3].CreateReqJitBufMes(); }
void OnNewConnectionCh4() { vecChannels[4].CreateReqJitBufMes(); } void OnNewConnectionCh4() { vecChannels[4].CreateReqJitBufMes(); }
void OnNewConnectionCh5() { vecChannels[5].CreateReqJitBufMes(); } void OnNewConnectionCh5() { vecChannels[5].CreateReqJitBufMes(); }
void OnNewConnectionCh6() { vecChannels[6].CreateReqJitBufMes(); }
void OnNewConnectionCh7() { vecChannels[7].CreateReqJitBufMes(); }
void OnNewConnectionCh8() { vecChannels[8].CreateReqJitBufMes(); }
void OnNewConnectionCh9() { vecChannels[9].CreateReqJitBufMes(); }
void OnReqConnClientsListCh0() { CreateAndSendChanListForThisChan ( 0 ); } void OnReqConnClientsListCh0() { CreateAndSendChanListForThisChan ( 0 ); }
void OnReqConnClientsListCh1() { CreateAndSendChanListForThisChan ( 1 ); } void OnReqConnClientsListCh1() { CreateAndSendChanListForThisChan ( 1 ); }
@ -298,6 +309,10 @@ public slots:
void OnReqConnClientsListCh3() { CreateAndSendChanListForThisChan ( 3 ); } void OnReqConnClientsListCh3() { CreateAndSendChanListForThisChan ( 3 ); }
void OnReqConnClientsListCh4() { CreateAndSendChanListForThisChan ( 4 ); } void OnReqConnClientsListCh4() { CreateAndSendChanListForThisChan ( 4 ); }
void OnReqConnClientsListCh5() { CreateAndSendChanListForThisChan ( 5 ); } void OnReqConnClientsListCh5() { CreateAndSendChanListForThisChan ( 5 ); }
void OnReqConnClientsListCh6() { CreateAndSendChanListForThisChan ( 6 ); }
void OnReqConnClientsListCh7() { CreateAndSendChanListForThisChan ( 7 ); }
void OnReqConnClientsListCh8() { CreateAndSendChanListForThisChan ( 8 ); }
void OnReqConnClientsListCh9() { CreateAndSendChanListForThisChan ( 9 ); }
void OnNameHasChangedCh0() { CreateAndSendChanListForAllConChannels(); } void OnNameHasChangedCh0() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh1() { CreateAndSendChanListForAllConChannels(); } void OnNameHasChangedCh1() { CreateAndSendChanListForAllConChannels(); }
@ -305,6 +320,10 @@ public slots:
void OnNameHasChangedCh3() { CreateAndSendChanListForAllConChannels(); } void OnNameHasChangedCh3() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh4() { CreateAndSendChanListForAllConChannels(); } void OnNameHasChangedCh4() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh5() { CreateAndSendChanListForAllConChannels(); } void OnNameHasChangedCh5() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh6() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh7() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh8() { CreateAndSendChanListForAllConChannels(); }
void OnNameHasChangedCh9() { CreateAndSendChanListForAllConChannels(); }
void OnChatTextReceivedCh0 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 0, strChatText ); } void OnChatTextReceivedCh0 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 0, strChatText ); }
void OnChatTextReceivedCh1 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 1, strChatText ); } void OnChatTextReceivedCh1 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 1, strChatText ); }
@ -312,6 +331,10 @@ public slots:
void OnChatTextReceivedCh3 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 3, strChatText ); } void OnChatTextReceivedCh3 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 3, strChatText ); }
void OnChatTextReceivedCh4 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 4, strChatText ); } void OnChatTextReceivedCh4 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 4, strChatText ); }
void OnChatTextReceivedCh5 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 5, strChatText ); } void OnChatTextReceivedCh5 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 5, strChatText ); }
void OnChatTextReceivedCh6 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 6, strChatText ); }
void OnChatTextReceivedCh7 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 7, strChatText ); }
void OnChatTextReceivedCh8 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 8, strChatText ); }
void OnChatTextReceivedCh9 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 9, strChatText ); }
void OnPingReceivedCh0 ( int iMs ) { vecChannels[0].CreatePingMes ( iMs ); } void OnPingReceivedCh0 ( int iMs ) { vecChannels[0].CreatePingMes ( iMs ); }
void OnPingReceivedCh1 ( int iMs ) { vecChannels[1].CreatePingMes ( iMs ); } void OnPingReceivedCh1 ( int iMs ) { vecChannels[1].CreatePingMes ( iMs ); }
@ -319,6 +342,10 @@ public slots:
void OnPingReceivedCh3 ( int iMs ) { vecChannels[3].CreatePingMes ( iMs ); } void OnPingReceivedCh3 ( int iMs ) { vecChannels[3].CreatePingMes ( iMs ); }
void OnPingReceivedCh4 ( int iMs ) { vecChannels[4].CreatePingMes ( iMs ); } void OnPingReceivedCh4 ( int iMs ) { vecChannels[4].CreatePingMes ( iMs ); }
void OnPingReceivedCh5 ( int iMs ) { vecChannels[5].CreatePingMes ( iMs ); } void OnPingReceivedCh5 ( int iMs ) { vecChannels[5].CreatePingMes ( iMs ); }
void OnPingReceivedCh6 ( int iMs ) { vecChannels[6].CreatePingMes ( iMs ); }
void OnPingReceivedCh7 ( int iMs ) { vecChannels[7].CreatePingMes ( iMs ); }
void OnPingReceivedCh8 ( int iMs ) { vecChannels[8].CreatePingMes ( iMs ); }
void OnPingReceivedCh9 ( int iMs ) { vecChannels[9].CreatePingMes ( iMs ); }
signals: signals:
void MessReadyForSending ( int iChID, CVector<uint8_t> vecMessage ); void MessReadyForSending ( int iChID, CVector<uint8_t> vecMessage );

View File

@ -27,6 +27,7 @@
/* Implementation *************************************************************/ /* Implementation *************************************************************/
CClient::CClient ( const quint16 iPortNumber ) : CClient::CClient ( const quint16 iPortNumber ) :
Channel ( false ), /* we need a client channel -> "false" */
Sound ( AudioCallback, this ), Sound ( AudioCallback, this ),
Socket ( &Channel, iPortNumber ), Socket ( &Channel, iPortNumber ),
iAudioInFader ( AUD_FADER_IN_MIDDLE ), iAudioInFader ( AUD_FADER_IN_MIDDLE ),
@ -111,7 +112,7 @@ void CClient::OnReceivePingMessage ( int iMs )
bool CClient::SetServerAddr ( QString strNAddr ) bool CClient::SetServerAddr ( QString strNAddr )
{ {
QHostAddress InetAddr; QHostAddress InetAddr;
quint16 iNetPort = LLCON_PORT_NUMBER; quint16 iNetPort = LLCON_DFAULT_PORT_NUMBER;
// parse input address for the type [IP address]:[port number] // parse input address for the type [IP address]:[port number]
QString strPort = strNAddr.section ( ":", 1, 1 ); QString strPort = strNAddr.section ( ":", 1, 1 );
@ -189,10 +190,13 @@ void CClient::AudioCallback ( CVector<short>& psData, void* arg )
void CClient::Init() void CClient::Init()
{ {
// set block size (in samples) // set block size (in samples)
iMonoBlockSizeSam = MIN_BLOCK_SIZE_SAMPLES;
// TEST
iMonoBlockSizeSam = 128;//64;//MIN_SERVER_BLOCK_SIZE_SAMPLES;
iStereoBlockSizeSam = 2 * iMonoBlockSizeSam; iStereoBlockSizeSam = 2 * iMonoBlockSizeSam;
iSndCrdMonoBlockSizeSam = MIN_BLOCK_DURATION_MS * SND_CRD_SAMPLE_RATE / 1000; iSndCrdMonoBlockSizeSam = iMonoBlockSizeSam * SND_CRD_SAMPLE_RATE / SYSTEM_SAMPLE_RATE;
iSndCrdStereoBlockSizeSam = 2 * iSndCrdMonoBlockSizeSam; iSndCrdStereoBlockSizeSam = 2 * iSndCrdMonoBlockSizeSam;
vecsAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam ); vecsAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam );
@ -203,6 +207,11 @@ void CClient::Init()
Sound.Init ( iSndCrdStereoBlockSizeSam ); Sound.Init ( iSndCrdStereoBlockSizeSam );
// TEST
Channel.SetNetwBufSizeOut ( iMonoBlockSizeSam );
// resample objects are always initialized with the input block size // resample objects are always initialized with the input block size
// record // record
ResampleObjDown.Init ( iSndCrdMonoBlockSizeSam, SND_CRD_SAMPLE_RATE, SYSTEM_SAMPLE_RATE ); ResampleObjDown.Init ( iSndCrdMonoBlockSizeSam, SND_CRD_SAMPLE_RATE, SYSTEM_SAMPLE_RATE );
@ -362,7 +371,7 @@ void CClient::UpdateTimeResponseMeasurement()
// we want to calculate the standard deviation (we assume that the mean // we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time) // is correct at the block period time)
const double dCurAddVal = const double dCurAddVal =
( (double) ( CurTime - TimeLastBlock ) - MIN_BLOCK_DURATION_MS ); ( (double) ( CurTime - TimeLastBlock ) - MIN_SERVER_BLOCK_DURATION_MS );
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value

View File

@ -101,7 +101,8 @@ public:
if ( Channel.GetSockBufSize() != iNumBlocks ) if ( Channel.GetSockBufSize() != iNumBlocks )
{ {
// check for valid values // check for valid values
if ( ( iNumBlocks >= 0 ) && ( iNumBlocks <= MAX_NET_BUF_SIZE_NUM_BL ) ) if ( ( iNumBlocks >= MIN_NET_BUF_SIZE_NUM_BL ) &&
( iNumBlocks <= MAX_NET_BUF_SIZE_NUM_BL ) )
{ {
// set the new socket size // set the new socket size
Channel.SetSockBufSize ( iNumBlocks ); Channel.SetSockBufSize ( iNumBlocks );
@ -125,9 +126,9 @@ public:
{ Channel.SetNetwBufSizeFactOut ( iNetNetwBlSiFact ); } { Channel.SetNetwBufSizeFactOut ( iNetNetwBlSiFact ); }
int GetNetwBufSizeFactOut() { return Channel.GetNetwBufSizeFactOut(); } int GetNetwBufSizeFactOut() { return Channel.GetNetwBufSizeFactOut(); }
void SetAudioCompressionOut ( const CAudioCompression::EAudComprType eNewAudComprTypeOut ) void SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut )
{ Channel.SetAudioCompressionOut ( eNewAudComprTypeOut ); } { Channel.SetAudioCompressionOut ( eNewAudComprTypeOut ); }
CAudioCompression::EAudComprType GetAudioCompressionOut() { return Channel.GetAudioCompressionOut(); } EAudComprType GetAudioCompressionOut() { return Channel.GetAudioCompressionOut(); }
void SetRemoteChanGain ( const int iId, const double dGain ) void SetRemoteChanGain ( const int iId, const double dGain )
{ Channel.SetRemoteChanGain ( iId, dGain ); } { Channel.SetRemoteChanGain ( iId, dGain ); }

View File

@ -52,9 +52,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"for the audio stream bandwidth, audio dropouts occur and the " "for the audio stream bandwidth, audio dropouts occur and the "
"ping time will increase significantly (the connection is stodged)." ); "ping time will increase significantly (the connection is stodged)." );
SliderNetBufSiFactIn->setWhatsThis ( strNetwBlockSize ); SliderNetBufSiFactIn->setWhatsThis ( strNetwBlockSize );
SliderNetBufSiFactOut->setWhatsThis ( strNetwBlockSize );
TextNetBufSiFactIn->setWhatsThis ( strNetwBlockSize ); TextNetBufSiFactIn->setWhatsThis ( strNetwBlockSize );
TextNetBufSiFactOut->setWhatsThis ( strNetwBlockSize );
GroupBoxNetwBuf->setWhatsThis ( strNetwBlockSize ); GroupBoxNetwBuf->setWhatsThis ( strNetwBlockSize );
// init delay information controls // init delay information controls
@ -65,24 +63,8 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
TextLabelOverallDelay->setText ( "" ); TextLabelOverallDelay->setText ( "" );
// init slider controls --- // init slider controls ---
// sound buffer in
#ifdef _WIN32
SliderSndBufIn->setRange ( 1, AUD_SLIDER_LENGTH ); // for ASIO we only need one buffer
#else
SliderSndBufIn->setRange ( 2, AUD_SLIDER_LENGTH );
#endif
UpdateSndBufInSlider ( pClient->GetSndInterface()->GetInNumBuf() );
// sound buffer out
#ifdef _WIN32
SliderSndBufOut->setRange ( 1, AUD_SLIDER_LENGTH ); // for ASIO we only need one buffer
#else
SliderSndBufOut->setRange ( 2, AUD_SLIDER_LENGTH );
#endif
UpdateSndBufOutSlider ( pClient->GetSndInterface()->GetOutNumBuf() );
// network buffer // network buffer
SliderNetBuf->setRange ( 0, MAX_NET_BUF_SIZE_NUM_BL ); SliderNetBuf->setRange ( MIN_NET_BUF_SIZE_NUM_BL, MAX_NET_BUF_SIZE_NUM_BL );
UpdateJitterBufferFrame(); UpdateJitterBufferFrame();
// network buffer size factor in // network buffer size factor in
@ -90,15 +72,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
const int iCurNetBufSiFactIn = pClient->GetNetwBufSizeFactIn(); const int iCurNetBufSiFactIn = pClient->GetNetwBufSizeFactIn();
SliderNetBufSiFactIn->setValue ( iCurNetBufSiFactIn ); SliderNetBufSiFactIn->setValue ( iCurNetBufSiFactIn );
TextNetBufSiFactIn->setText ( "In:\n" + QString().setNum ( TextNetBufSiFactIn->setText ( "In:\n" + QString().setNum (
double ( iCurNetBufSiFactIn * MIN_BLOCK_DURATION_MS ), 'f', 2 ) + double ( iCurNetBufSiFactIn * MIN_SERVER_BLOCK_DURATION_MS ), 'f', 2 ) +
" ms" );
// network buffer size factor out
SliderNetBufSiFactOut->setRange ( 1, MAX_NET_BLOCK_SIZE_FACTOR );
const int iCurNetBufSiFactOut = pClient->GetNetwBufSizeFactOut();
SliderNetBufSiFactOut->setValue ( iCurNetBufSiFactOut );
TextNetBufSiFactOut->setText ( "Out:\n" + QString().setNum (
double ( iCurNetBufSiFactOut * MIN_BLOCK_DURATION_MS), 'f', 2 ) +
" ms" ); " ms" );
// init combo box containing all available sound cards in the system // init combo box containing all available sound cards in the system
@ -122,15 +96,15 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
// audio compression type // audio compression type
switch ( pClient->GetAudioCompressionOut() ) switch ( pClient->GetAudioCompressionOut() )
{ {
case CAudioCompression::CT_NONE: case CT_NONE:
radioButtonNoAudioCompr->setChecked ( true ); radioButtonNoAudioCompr->setChecked ( true );
break; break;
case CAudioCompression::CT_IMAADPCM: case CT_IMAADPCM:
radioButtonIMA_ADPCM->setChecked ( true ); radioButtonIMA_ADPCM->setChecked ( true );
break; break;
case CAudioCompression::CT_MSADPCM: case CT_MSADPCM:
radioButtonMS_ADPCM->setChecked ( true ); radioButtonMS_ADPCM->setChecked ( true );
break; break;
} }
@ -146,19 +120,11 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
QObject::connect ( &TimerPing, SIGNAL ( timeout() ), QObject::connect ( &TimerPing, SIGNAL ( timeout() ),
this, SLOT ( OnTimerPing() ) ); this, SLOT ( OnTimerPing() ) );
// sliders
QObject::connect ( SliderSndBufIn, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnSliderSndBufInChange ( int ) ) );
QObject::connect ( SliderSndBufOut, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnSliderSndBufOutChange ( int ) ) );
QObject::connect ( SliderNetBuf, SIGNAL ( valueChanged ( int ) ), QObject::connect ( SliderNetBuf, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnSliderNetBuf ( int ) ) ); this, SLOT ( OnSliderNetBuf ( int ) ) );
QObject::connect ( SliderNetBufSiFactIn, SIGNAL ( valueChanged ( int ) ), QObject::connect ( SliderNetBufSiFactIn, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnSliderNetBufSiFactIn ( int ) ) ); this, SLOT ( OnSliderNetBufSiFactIn ( int ) ) );
QObject::connect ( SliderNetBufSiFactOut, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnSliderNetBufSiFactOut ( int ) ) );
// check boxes // check boxes
QObject::connect ( cbOpenChatOnNewMessage, SIGNAL ( stateChanged ( int ) ), QObject::connect ( cbOpenChatOnNewMessage, SIGNAL ( stateChanged ( int ) ),
@ -196,18 +162,6 @@ void CClientSettingsDlg::UpdateJitterBufferFrame()
TextNetBuf->setEnabled ( !pClient->GetDoAutoSockBufSize() ); TextNetBuf->setEnabled ( !pClient->GetDoAutoSockBufSize() );
} }
void CClientSettingsDlg::UpdateSndBufInSlider ( const int iCurNumInBuf )
{
SliderSndBufIn->setValue ( iCurNumInBuf );
TextSndBufIn->setText ( "In: " + QString().setNum ( iCurNumInBuf ) );
}
void CClientSettingsDlg::UpdateSndBufOutSlider ( const int iCurNumOutBuf )
{
SliderSndBufOut->setValue ( iCurNumOutBuf );
TextSndBufOut->setText ( "Out: " + QString().setNum ( iCurNumOutBuf ) );
}
void CClientSettingsDlg::showEvent ( QShowEvent* showEvent ) void CClientSettingsDlg::showEvent ( QShowEvent* showEvent )
{ {
// only activate ping timer if window is actually shown // only activate ping timer if window is actually shown
@ -220,20 +174,6 @@ void CClientSettingsDlg::hideEvent ( QHideEvent* hideEvent )
TimerPing.stop(); TimerPing.stop();
} }
void CClientSettingsDlg::OnSliderSndBufInChange ( int value )
{
pClient->GetSndInterface()->SetInNumBuf ( value );
TextSndBufIn->setText ( "In: " + QString().setNum ( value ) );
UpdateDisplay();
}
void CClientSettingsDlg::OnSliderSndBufOutChange ( int value )
{
pClient->GetSndInterface()->SetOutNumBuf ( value );
TextSndBufOut->setText ( "Out: " + QString().setNum ( value ) );
UpdateDisplay();
}
void CClientSettingsDlg::OnSliderNetBuf ( int value ) void CClientSettingsDlg::OnSliderNetBuf ( int value )
{ {
pClient->SetSockBufSize ( value ); pClient->SetSockBufSize ( value );
@ -245,16 +185,7 @@ void CClientSettingsDlg::OnSliderNetBufSiFactIn ( int value )
{ {
pClient->SetNetwBufSizeFactIn ( value ); pClient->SetNetwBufSizeFactIn ( value );
TextNetBufSiFactIn->setText ( "In:\n" + QString().setNum ( TextNetBufSiFactIn->setText ( "In:\n" + QString().setNum (
double ( value * MIN_BLOCK_DURATION_MS ), 'f', 2 ) + double ( value * MIN_SERVER_BLOCK_DURATION_MS ), 'f', 2 ) +
" ms" );
UpdateDisplay();
}
void CClientSettingsDlg::OnSliderNetBufSiFactOut ( int value )
{
pClient->SetNetwBufSizeFactOut ( value );
TextNetBufSiFactOut->setText ( "Out:\n" + QString().setNum (
double ( value * MIN_BLOCK_DURATION_MS ), 'f', 2 ) +
" ms" ); " ms" );
UpdateDisplay(); UpdateDisplay();
} }
@ -294,17 +225,17 @@ void CClientSettingsDlg::OnAudioCompressionButtonGroupClicked ( QAbstractButton*
{ {
if ( button == radioButtonNoAudioCompr ) if ( button == radioButtonNoAudioCompr )
{ {
pClient->SetAudioCompressionOut ( CAudioCompression::CT_NONE ); pClient->SetAudioCompressionOut ( CT_NONE );
} }
if ( button == radioButtonIMA_ADPCM ) if ( button == radioButtonIMA_ADPCM )
{ {
pClient->SetAudioCompressionOut ( CAudioCompression::CT_IMAADPCM ); pClient->SetAudioCompressionOut ( CT_IMAADPCM );
} }
if ( button == radioButtonMS_ADPCM ) if ( button == radioButtonMS_ADPCM )
{ {
pClient->SetAudioCompressionOut ( CAudioCompression::CT_MSADPCM ); pClient->SetAudioCompressionOut ( CT_MSADPCM );
} }
UpdateDisplay(); UpdateDisplay();
} }
@ -322,17 +253,17 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime )
- the mean delay of a cyclic buffer is half the buffer size (since - the mean delay of a cyclic buffer is half the buffer size (since
for the average it is assumed that the buffer is half filled) for the average it is assumed that the buffer is half filled)
- consider the jitter buffer on the server side, too - consider the jitter buffer on the server side, too
- assume that the sound card introduces an additional delay of 2 * MIN_BLOCK_DURATION_MS - assume that the sound card introduces an additional delay of 2 * MIN_SERVER_BLOCK_DURATION_MS
*/ */
const int iTotalJitterBufferDelayMS = MIN_BLOCK_DURATION_MS * const int iTotalJitterBufferDelayMS = MIN_SERVER_BLOCK_DURATION_MS *
( 2 * pClient->GetSockBufSize() + pClient->GetNetwBufSizeFactIn() + ( 2 * pClient->GetSockBufSize() + pClient->GetNetwBufSizeFactIn() +
pClient->GetNetwBufSizeFactOut() ) / 2; pClient->GetNetwBufSizeFactOut() ) / 2;
const int iTotalSoundCardDelayMS = 2 * MIN_BLOCK_DURATION_MS + const int iTotalSoundCardDelayMS = 2 * MIN_SERVER_BLOCK_DURATION_MS +
MIN_BLOCK_DURATION_MS * ( pClient->GetSndInterface()->GetInNumBuf() + MIN_SERVER_BLOCK_DURATION_MS * ( pClient->GetSndInterface()->GetInNumBuf() +
pClient->GetSndInterface()->GetOutNumBuf() ) / 2; pClient->GetSndInterface()->GetOutNumBuf() ) / 2;
const int iDelayToFillNetworkPackets = MIN_BLOCK_DURATION_MS * const int iDelayToFillNetworkPackets = MIN_SERVER_BLOCK_DURATION_MS *
( pClient->GetNetwBufSizeFactIn() + pClient->GetNetwBufSizeFactOut() ); ( pClient->GetNetwBufSizeFactIn() + pClient->GetNetwBufSizeFactOut() );
const int iTotalBufferDelay = iDelayToFillNetworkPackets + const int iTotalBufferDelay = iDelayToFillNetworkPackets +
@ -375,9 +306,7 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime )
void CClientSettingsDlg::UpdateDisplay() void CClientSettingsDlg::UpdateDisplay()
{ {
// update slider controls (settings might have been changed by sound interface) // update slider controls (settings might have been changed)
UpdateSndBufInSlider ( pClient->GetSndInterface()->GetInNumBuf() );
UpdateSndBufOutSlider ( pClient->GetSndInterface()->GetOutNumBuf() );
UpdateJitterBufferFrame(); UpdateJitterBufferFrame();
if ( !pClient->IsRunning() ) if ( !pClient->IsRunning() )
@ -393,6 +322,7 @@ void CClientSettingsDlg::SetStatus ( const int iMessType, const int iStatus )
{ {
switch ( iMessType ) switch ( iMessType )
{ {
/*
case MS_SOUND_IN: case MS_SOUND_IN:
CLEDSoundIn->SetLight ( iStatus ); CLEDSoundIn->SetLight ( iStatus );
break; break;
@ -400,6 +330,7 @@ void CClientSettingsDlg::SetStatus ( const int iMessType, const int iStatus )
case MS_SOUND_OUT: case MS_SOUND_OUT:
CLEDSoundOut->SetLight ( iStatus ); CLEDSoundOut->SetLight ( iStatus );
break; break;
*/
case MS_JIT_BUF_PUT: case MS_JIT_BUF_PUT:
CLEDNetwPut->SetLight ( iStatus ); CLEDNetwPut->SetLight ( iStatus );
@ -410,8 +341,10 @@ void CClientSettingsDlg::SetStatus ( const int iMessType, const int iStatus )
break; break;
case MS_RESET_ALL: case MS_RESET_ALL:
/*
CLEDSoundIn->Reset(); CLEDSoundIn->Reset();
CLEDSoundOut->Reset(); CLEDSoundOut->Reset();
*/
CLEDNetwPut->Reset(); CLEDNetwPut->Reset();
CLEDNetwGet->Reset(); CLEDNetwGet->Reset();
break; break;

View File

@ -72,18 +72,13 @@ protected:
virtual void showEvent ( QShowEvent* showEvent ); virtual void showEvent ( QShowEvent* showEvent );
virtual void hideEvent ( QHideEvent* hideEvent ); virtual void hideEvent ( QHideEvent* hideEvent );
void UpdateSndBufInSlider ( const int iCurNumInBuf );
void UpdateSndBufOutSlider ( const int iCurNumOutBuf );
void UpdateJitterBufferFrame(); void UpdateJitterBufferFrame();
public slots: public slots:
void OnTimerStatus() { UpdateDisplay(); } void OnTimerStatus() { UpdateDisplay(); }
void OnTimerPing(); void OnTimerPing();
void OnSliderSndBufInChange ( int value );
void OnSliderSndBufOutChange ( int value );
void OnSliderNetBuf ( int value ); void OnSliderNetBuf ( int value );
void OnSliderNetBufSiFactIn ( int value ); void OnSliderNetBufSiFactIn ( int value );
void OnSliderNetBufSiFactOut ( int value );
void OnAutoJitBuf ( int value ); void OnAutoJitBuf ( int value );
void OnOpenChatOnNewMessageStateChanged ( int value ); void OnOpenChatOnNewMessageStateChanged ( int value );
void OnAudioCompressionButtonGroupClicked ( QAbstractButton* button ); void OnAudioCompressionButtonGroupClicked ( QAbstractButton* button );

View File

@ -5,8 +5,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>544</width> <width>421</width>
<height>306</height> <height>313</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle" >
@ -286,426 +286,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QLabel" name="TextNetBufSiFactOut" >
<property name="text" >
<string>Size</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSlider" name="SliderNetBufSiFactOut" >
<property name="pageStep" >
<number>1</number>
</property>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="tickPosition" >
<enum>QSlider::TicksBothSides</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="TextLabel2_2" >
<property name="text" >
<string>Check Ping</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="TextLabel2_3" >
<property name="text" >
<string>Time!</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="GroupBoxSoundCardBuffers" >
<property name="title" >
<string>Soundcard Buffers</string>
</property>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLabel" name="TextSndBufOut" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Minimum" hsizetype="MinimumExpanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text" >
<string>Out</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSlider" name="SliderSndBufOut" >
<property name="pageStep" >
<number>1</number>
</property>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="tickPosition" >
<enum>QSlider::TicksBothSides</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="QLabel" name="TextSndBufIn" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Minimum" hsizetype="MinimumExpanding" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text" >
<string>In</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSlider" name="SliderSndBufIn" >
<property name="pageStep" >
<number>1</number>
</property>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="tickPosition" >
<enum>QSlider::TicksBothSides</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="TextLabel1" >
<property name="text" >
<string>Out / In:</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap" >
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="spacing" >
<number>6</number>
</property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item>
<widget class="CMultiColorLED" native="1" name="CLEDSoundOut" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>13</width>
<height>13</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>13</width>
<height>13</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="CMultiColorLED" native="1" name="CLEDSoundIn" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>13</width>
<height>13</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>13</width>
<height>13</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -43,7 +43,7 @@
// version and application name (always use this version) // version and application name (always use this version)
#undef VERSION #undef VERSION
#define VERSION "2.1.5cvs" #define VERSION "2.2.0cvs"
#define APP_NAME "llcon" #define APP_NAME "llcon"
// file name for logging file // file name for logging file
@ -53,7 +53,7 @@
#define DEFAULT_SERVER_ADDRESS "llcon.dyndns.org" #define DEFAULT_SERVER_ADDRESS "llcon.dyndns.org"
// defined port number for client and server // defined port number for client and server
#define LLCON_PORT_NUMBER 22122 #define LLCON_DFAULT_PORT_NUMBER 22122
// system sample rate // system sample rate
#define SYSTEM_SAMPLE_RATE 24000 #define SYSTEM_SAMPLE_RATE 24000
@ -62,11 +62,18 @@
// internal sample rate conversion which might be buggy // internal sample rate conversion which might be buggy
#define SND_CRD_SAMPLE_RATE 48000 #define SND_CRD_SAMPLE_RATE 48000
// minimum block duration - all other buffer durations must be a multiple // minimum server block duration - all other buffer durations must be a multiple
// of this duration // of this duration
#define MIN_BLOCK_DURATION_MS 2 // ms #define MIN_SERVER_BLOCK_DURATION_MS 2 // ms
#define MIN_BLOCK_SIZE_SAMPLES ( MIN_BLOCK_DURATION_MS * SYSTEM_SAMPLE_RATE / 1000 ) #define MIN_SERVER_BLOCK_SIZE_SAMPLES ( MIN_SERVER_BLOCK_DURATION_MS * 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 (we assume
// here that "MAX_NET_BLOCK_SIZE_FACTOR * MIN_SERVER_BLOCK_SIZE_SAMPLES"
// is smaller than this value here)
#define MAX_MONO_AUD_BUFF_SIZE_AT_48KHZ 4096
// maximum value of factor for network block size // maximum value of factor for network block size
#define MAX_NET_BLOCK_SIZE_FACTOR 3 #define MAX_NET_BLOCK_SIZE_FACTOR 3
@ -74,8 +81,9 @@
// default network block size factor // default network block size factor
#define DEF_NET_BLOCK_SIZE_FACTOR 3 #define DEF_NET_BLOCK_SIZE_FACTOR 3
// maximum network buffer size (which can be chosen by slider) // minimum/maximum network buffer size (which can be chosen by slider)
#define MAX_NET_BUF_SIZE_NUM_BL 12 // number of blocks #define MIN_NET_BUF_SIZE_NUM_BL 1 // number of blocks
#define MAX_NET_BUF_SIZE_NUM_BL 20 // number of blocks
// default network buffer size // default network buffer size
#define DEF_NET_BUF_SIZE_NUM_BL 6 // number of blocks #define DEF_NET_BUF_SIZE_NUM_BL 6 // number of blocks
@ -88,17 +96,22 @@
#define MAX_NUMBER_SOUND_CARDS 10 #define MAX_NUMBER_SOUND_CARDS 10
#define INVALID_SNC_CARD_DEVICE -1 #define INVALID_SNC_CARD_DEVICE -1
// maximum number of internet connections (channels) // maximum number of internet connections (channels)
// if you want to change this paramter, there has to be done code modifications // if you want to change this paramter, there has to be done code modifications
// on other places, too! The code tag "MAX_NUM_CHANNELS_TAG" shows these places // on other places, too! The code tag "MAX_NUM_CHANNELS_TAG" shows these places
// (just search for the tag in the entire code) // (just search for the tag in the entire code)
// note: since in the protocol messages the channel ID is only a byte, a #define MAX_NUM_CHANNELS 10 // max number channels for server
// maximum of 8 channels are possible, see e.g. "PROTMESSID_CHANNEL_GAIN"!
#define MAX_NUM_CHANNELS 6 // max number channels for server // actual number of used channels in the server
// this parameter can safely be changed from 1 to MAX_NUM_CHANNELS
// without any other changes in the code
#define USED_NUM_CHANNELS 6 // used number channels for server
// length of the moving average buffer for response time measurement // length of the moving average buffer for response time measurement
#define TIME_MOV_AV_RESPONSE 30 // seconds #define TIME_MOV_AV_RESPONSE 30 // seconds
#define LEN_MOV_AV_RESPONSE ( TIME_MOV_AV_RESPONSE * 1000 / MIN_BLOCK_DURATION_MS ) #define LEN_MOV_AV_RESPONSE ( TIME_MOV_AV_RESPONSE * 1000 / MIN_SERVER_BLOCK_DURATION_MS )
// GUI definition: width/heigth size of LED pixmaps // GUI definition: width/heigth size of LED pixmaps
#define LED_WIDTH_HEIGHT_SIZE_PIXEL 13 #define LED_WIDTH_HEIGHT_SIZE_PIXEL 13

View File

@ -45,22 +45,13 @@ CLlconServerDlg::CLlconServerDlg ( CServer* pNServP, QWidget* parent )
// set up list view for connected clients // set up list view for connected clients
ListViewClients->setColumnWidth ( 0, 170 ); ListViewClients->setColumnWidth ( 0, 170 );
// TODO QT4
// ListViewClients->setColumnAlignment ( 1, Qt::AlignLeft );
ListViewClients->setColumnWidth ( 1, 150 ); ListViewClients->setColumnWidth ( 1, 150 );
// ListViewClients->setColumnAlignment ( 2, Qt::AlignCenter );
// ListViewClients->setColumnAlignment ( 3, Qt::AlignCenter );
// ListViewClients->setColumnAlignment ( 4, Qt::AlignRight );
// ListViewClients->setColumnAlignment ( 5, Qt::AlignRight );
// ListViewClients->setColumnAlignment ( 6, Qt::AlignRight );
ListViewClients->clear(); ListViewClients->clear();
/* insert items in reverse order because in Windows all of them are // insert items in reverse order because in Windows all of them are
always visible -> put first item on the top */ // always visible -> put first item on the top
vecpListViewItems.Init(MAX_NUM_CHANNELS); vecpListViewItems.Init ( USED_NUM_CHANNELS );
for ( int i = MAX_NUM_CHANNELS - 1; i >= 0; i-- ) for ( int i = USED_NUM_CHANNELS - 1; i >= 0; i-- )
{ {
vecpListViewItems[i] = new CServerListViewItem ( ListViewClients ); vecpListViewItems[i] = new CServerListViewItem ( ListViewClients );
vecpListViewItems[i]->setHidden ( true ); vecpListViewItems[i]->setHidden ( true );
@ -94,16 +85,15 @@ void CLlconServerDlg::OnTimer()
CVector<QString> vecsName; CVector<QString> vecsName;
CVector<int> veciJitBufSize; CVector<int> veciJitBufSize;
CVector<int> veciNetwOutBlSiFact; CVector<int> veciNetwOutBlSiFact;
CVector<int> veciNetwInBlSiFact;
double dCurTiStdDev; double dCurTiStdDev;
ListViewMutex.lock(); ListViewMutex.lock();
pServer->GetConCliParam ( vecHostAddresses, vecsName, veciJitBufSize, pServer->GetConCliParam ( vecHostAddresses, vecsName, veciJitBufSize,
veciNetwOutBlSiFact, veciNetwInBlSiFact ); veciNetwOutBlSiFact );
// fill list with connected clients // fill list with connected clients
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ ) for ( int i = 0; i < USED_NUM_CHANNELS; i++ )
{ {
if ( !( vecHostAddresses[i].InetAddr == QHostAddress ( (quint32) 0 ) ) ) if ( !( vecHostAddresses[i].InetAddr == QHostAddress ( (quint32) 0 ) ) )
{ {
@ -119,13 +109,10 @@ void CLlconServerDlg::OnTimer()
vecpListViewItems[i]->setText ( 4, vecpListViewItems[i]->setText ( 4,
QString().setNum ( veciJitBufSize[i] ) ); QString().setNum ( veciJitBufSize[i] ) );
// in/out network block sizes // out network block size
vecpListViewItems[i]->setText ( 5, vecpListViewItems[i]->setText ( 5,
QString().setNum ( QString().setNum (
double ( veciNetwInBlSiFact[i] * MIN_BLOCK_DURATION_MS ), 'f', 2 ) ); double ( veciNetwOutBlSiFact[i] * MIN_SERVER_BLOCK_DURATION_MS ), 'f', 2 ) );
vecpListViewItems[i]->setText ( 6,
QString().setNum (
double ( veciNetwOutBlSiFact[i] * MIN_BLOCK_DURATION_MS ), 'f', 2 ) );
vecpListViewItems[i]->setHidden ( false ); vecpListViewItems[i]->setHidden ( false );
} }

View File

@ -5,8 +5,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>699</width> <width>767</width>
<height>291</height> <height>280</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle" >
@ -19,12 +19,21 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>9</number>
</property>
<property name="topMargin" >
<number>9</number>
</property>
<property name="rightMargin" >
<number>9</number>
</property>
<property name="bottomMargin" >
<number>9</number>
</property>
<item> <item>
<widget class="QTreeWidget" name="ListViewClients" > <widget class="QTreeWidget" name="ListViewClients" >
<property name="rootIsDecorated" > <property name="rootIsDecorated" >
@ -55,11 +64,6 @@
<string>Jitter buffer size</string> <string>Jitter buffer size</string>
</property> </property>
</column> </column>
<column>
<property name="text" >
<string>Block Size In</string>
</property>
</column>
<column> <column>
<property name="text" > <property name="text" >
<string>Block Size Out</string> <string>Block Size Out</string>
@ -69,12 +73,21 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" > <property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin" >
<number>0</number>
</property>
<property name="topMargin" >
<number>0</number>
</property>
<property name="rightMargin" >
<number>0</number>
</property>
<property name="bottomMargin" >
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="TextLabelNameVersion" > <widget class="QLabel" name="TextLabelNameVersion" >
<property name="text" > <property name="text" >

View File

@ -46,7 +46,7 @@ int main ( int argc, char** argv )
bool bIsClient = true; bool bIsClient = true;
bool bUseGUI = true; bool bUseGUI = true;
bool bForceLowUploadRate = false; bool bForceLowUploadRate = false;
quint16 iPortNumber = LLCON_PORT_NUMBER; quint16 iPortNumber = LLCON_DFAULT_PORT_NUMBER;
std::string strIniFileName = ""; std::string strIniFileName = "";
std::string strHTMLStatusFileName = ""; std::string strHTMLStatusFileName = "";
std::string strServerName = ""; std::string strServerName = "";
@ -61,7 +61,7 @@ int main ( int argc, char** argv )
if ( GetFlagArgument ( argc, argv, i, "-s", "--server" ) ) if ( GetFlagArgument ( argc, argv, i, "-s", "--server" ) )
{ {
bIsClient = false; bIsClient = false;
cerr << "server mode chosen" << std::endl; cout << "server mode chosen" << std::endl;
continue; continue;
} }
@ -69,7 +69,7 @@ int main ( int argc, char** argv )
if ( GetFlagArgument ( argc, argv, i, "-n", "--nogui" ) ) if ( GetFlagArgument ( argc, argv, i, "-n", "--nogui" ) )
{ {
bUseGUI = false; bUseGUI = false;
cerr << "no GUI mode chosen" << std::endl; cout << "no GUI mode chosen" << std::endl;
continue; continue;
} }
@ -77,7 +77,7 @@ int main ( int argc, char** argv )
if ( GetStringArgument ( argc, argv, i, "-l", "--log", strArgument ) ) if ( GetStringArgument ( argc, argv, i, "-l", "--log", strArgument ) )
{ {
strLoggingFileName = strArgument; strLoggingFileName = strArgument;
cerr << "logging file name: " << strLoggingFileName << std::endl; cout << "logging file name: " << strLoggingFileName << std::endl;
continue; continue;
} }
@ -85,7 +85,7 @@ int main ( int argc, char** argv )
if ( GetFlagArgument ( argc, argv, i, "-u", "--lowuploadrate" ) ) if ( GetFlagArgument ( argc, argv, i, "-u", "--lowuploadrate" ) )
{ {
bForceLowUploadRate = true; bForceLowUploadRate = true;
cerr << "force low upload rate" << std::endl; cout << "force low upload rate" << std::endl;
continue; continue;
} }
@ -94,7 +94,7 @@ int main ( int argc, char** argv )
0, 65535, rDbleArgument ) ) 0, 65535, rDbleArgument ) )
{ {
iPortNumber = static_cast<quint16> ( rDbleArgument ); iPortNumber = static_cast<quint16> ( rDbleArgument );
cerr << "selected port number: " << iPortNumber << std::endl; cout << "selected port number: " << iPortNumber << std::endl;
continue; continue;
} }
@ -102,14 +102,14 @@ int main ( int argc, char** argv )
if ( GetStringArgument ( argc, argv, i, "-m", "--htmlstatus", strArgument ) ) if ( GetStringArgument ( argc, argv, i, "-m", "--htmlstatus", strArgument ) )
{ {
strHTMLStatusFileName = strArgument; strHTMLStatusFileName = strArgument;
cerr << "HTML status file name: " << strHTMLStatusFileName << std::endl; cout << "HTML status file name: " << strHTMLStatusFileName << std::endl;
continue; continue;
} }
if ( GetStringArgument ( argc, argv, i, "-a", "--servername", strArgument ) ) if ( GetStringArgument ( argc, argv, i, "-a", "--servername", strArgument ) )
{ {
strServerName = strArgument; strServerName = strArgument;
cerr << "server name for HTML status file: " << strServerName << std::endl; cout << "server name for HTML status file: " << strServerName << std::endl;
continue; continue;
} }
@ -117,7 +117,7 @@ int main ( int argc, char** argv )
if ( GetStringArgument ( argc, argv, i, "-i", "--inifile", strArgument ) ) if ( GetStringArgument ( argc, argv, i, "-i", "--inifile", strArgument ) )
{ {
strIniFileName = strArgument; strIniFileName = strArgument;
cerr << "initialization file name: " << strIniFileName << std::endl; cout << "initialization file name: " << strIniFileName << std::endl;
continue; continue;
} }
@ -126,7 +126,7 @@ int main ( int argc, char** argv )
( !strcmp ( argv[i], "-h" ) ) || ( !strcmp ( argv[i], "-?" ) ) ) ( !strcmp ( argv[i], "-h" ) ) || ( !strcmp ( argv[i], "-?" ) ) )
{ {
const std::string strHelp = UsageArguments(argv); const std::string strHelp = UsageArguments(argv);
cerr << strHelp; cout << strHelp;
exit ( 1 ); exit ( 1 );
} }
@ -212,7 +212,7 @@ int main ( int argc, char** argv )
else else
{ {
// only start application without using the GUI // only start application without using the GUI
qDebug() << CAboutDlg::GetVersionAndNameStr ( false ); cout << CAboutDlg::GetVersionAndNameStr ( false ).toStdString();
app.exec(); app.exec();
} }
} }

View File

@ -147,16 +147,28 @@ MESSAGES
/* Implementation *************************************************************/ /* Implementation *************************************************************/
CProtocol::CProtocol() : iCounter ( 0 ), iOldRecID ( PROTMESSID_ILLEGAL ), CProtocol::CProtocol()
iOldRecCnt ( 0 )
{ {
SendMessQueue.clear(); Reset();
// connections // connections
QObject::connect ( &TimerSendMess, SIGNAL ( timeout() ), QObject::connect ( &TimerSendMess, SIGNAL ( timeout() ),
this, SLOT ( OnTimerSendMess() ) ); this, SLOT ( OnTimerSendMess() ) );
} }
void CProtocol::Reset()
{
QMutexLocker locker ( &Mutex );
// prepare internal variables for initial protocol transfer
iCounter = 0;
iOldRecID = PROTMESSID_ILLEGAL;
iOldRecCnt = 0;
// delete complete "send message queue"
SendMessQueue.clear();
}
void CProtocol::EnqueueMessage ( CVector<uint8_t>& vecMessage, void CProtocol::EnqueueMessage ( CVector<uint8_t>& vecMessage,
const int iCnt, const int iCnt,
const int iID ) const int iID )
@ -259,14 +271,6 @@ void CProtocol::CreateAndSendAcknMess ( const int& iID, const int& iCnt )
emit MessReadyForSending ( vecAcknMessage ); emit MessReadyForSending ( vecAcknMessage );
} }
void CProtocol::DeleteSendMessQueue()
{
QMutexLocker locker ( &Mutex );
// delete complete "send message queue"
SendMessQueue.clear();
}
bool CProtocol::ParseMessage ( const CVector<unsigned char>& vecbyData, bool CProtocol::ParseMessage ( const CVector<unsigned char>& vecbyData,
const int iNumBytes ) const int iNumBytes )
{ {
@ -315,18 +319,18 @@ for ( int i = 0; i < iNumBytes; i++ ) {
Mutex.lock(); Mutex.lock();
{ {
// check if this is the correct acknowledgment // check if this is the correct acknowledgment
if ( ( SendMessQueue.front().iCnt == iRecCounter ) && bSendNextMess = false;
( SendMessQueue.front().iID == iData ) ) if ( !SendMessQueue.empty() )
{ {
// message acknowledged, remove from queue if ( ( SendMessQueue.front().iCnt == iRecCounter ) &&
SendMessQueue.pop_front(); ( SendMessQueue.front().iID == iData ) )
{
// message acknowledged, remove from queue
SendMessQueue.pop_front();
// send next message in queue // send next message in queue
bSendNextMess = true; bSendNextMess = true;
} }
else
{
bSendNextMess = false;
} }
} }
Mutex.unlock(); Mutex.unlock();
@ -878,9 +882,9 @@ bool CProtocol::EvaluateNetwTranspPropsMes ( const CVector<uint8_t>& vecData )
const int iRecCodingType = const int iRecCodingType =
static_cast<unsigned short> ( GetValFromStream ( vecData, iPos, 2 ) ); static_cast<unsigned short> ( GetValFromStream ( vecData, iPos, 2 ) );
if ( ( iRecCodingType != CNetworkTransportProps::ACT_NONE ) && if ( ( iRecCodingType != CT_NONE ) &&
( iRecCodingType != CNetworkTransportProps::ACT_IMA_ADPCM ) && ( iRecCodingType != CT_IMAADPCM ) &&
( iRecCodingType != CNetworkTransportProps::ACT_MS_ADPCM ) ) ( iRecCodingType != CT_MSADPCM ) )
{ {
return true; return true;
} }

View File

@ -68,6 +68,8 @@ class CProtocol : public QObject
public: public:
CProtocol(); CProtocol();
void Reset();
void CreateJitBufMes ( const int iJitBufSize ); void CreateJitBufMes ( const int iJitBufSize );
void CreateReqJitBufMes(); void CreateReqJitBufMes();
void CreateNetwBlSiFactMes ( const int iNetwBlSiFact ); void CreateNetwBlSiFactMes ( const int iNetwBlSiFact );
@ -86,8 +88,6 @@ public:
bool ParseMessage ( const CVector<unsigned char>& vecbyData, bool ParseMessage ( const CVector<unsigned char>& vecbyData,
const int iNumBytes ); const int iNumBytes );
void DeleteSendMessQueue();
protected: protected:
class CSendMessage class CSendMessage
{ {

View File

@ -34,7 +34,7 @@ CServer::CServer ( const QString& strLoggingFileName,
Socket ( &ChannelSet, this, iPortNumber ), Socket ( &ChannelSet, this, iPortNumber ),
ChannelSet ( bForceLowUploadRate ) ChannelSet ( bForceLowUploadRate )
{ {
vecsSendData.Init ( MIN_BLOCK_SIZE_SAMPLES ); vecsSendData.Init ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
// init moving average buffer for response time evaluation // init moving average buffer for response time evaluation
RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE ); RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE );
@ -103,7 +103,7 @@ void CServer::Start()
if ( !IsRunning() ) if ( !IsRunning() )
{ {
// start main timer // start main timer
Timer.start ( MIN_BLOCK_DURATION_MS ); Timer.start ( MIN_SERVER_BLOCK_DURATION_MS );
// init time for response time evaluation // init time for response time evaluation
TimeLastBlock = PreciseTime.elapsed(); TimeLastBlock = PreciseTime.elapsed();
@ -137,7 +137,7 @@ void CServer::OnNewChannel ( CHostAddress ChanAddr )
void CServer::OnTimer() void CServer::OnTimer()
{ {
CVector<int> vecChanID; CVector<int> vecChanID;
CVector<CVector<double> > vecvecdData ( MIN_BLOCK_SIZE_SAMPLES ); CVector<CVector<double> > vecvecdData ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
CVector<CVector<double> > vecvecdGains; CVector<CVector<double> > vecvecdGains;
// get data from all connected clients // get data from all connected clients
@ -178,7 +178,7 @@ void CServer::OnTimer()
// we want to calculate the standard deviation (we assume that the mean // we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time) // is correct at the block period time)
const double dCurAddVal = const double dCurAddVal =
( (double) ( CurTime - TimeLastBlock ) - MIN_BLOCK_DURATION_MS ); ( (double) ( CurTime - TimeLastBlock ) - MIN_SERVER_BLOCK_DURATION_MS );
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value
@ -189,7 +189,7 @@ void CServer::OnTimer()
CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData, CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
CVector<double>& vecdGains ) CVector<double>& vecdGains )
{ {
CVector<short> vecsOutData ( MIN_BLOCK_SIZE_SAMPLES ); CVector<short> vecsOutData ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
const int iNumClients = vecvecdData.Size(); const int iNumClients = vecvecdData.Size();
@ -197,7 +197,7 @@ CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
const double dNorm = (double) 2.0; const double dNorm = (double) 2.0;
// mix all audio data from all clients together // mix all audio data from all clients together
for ( int i = 0; i < MIN_BLOCK_SIZE_SAMPLES; i++ ) for ( int i = 0; i < MIN_SERVER_BLOCK_SIZE_SAMPLES; i++ )
{ {
double dMixedData = 0.0; double dMixedData = 0.0;

View File

@ -54,11 +54,10 @@ public:
void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses, void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CVector<QString>& vecsName, CVector<QString>& vecsName,
CVector<int>& veciJitBufSize, CVector<int>& veciNetwOutBlSiFact, CVector<int>& veciJitBufSize, CVector<int>& veciNetwOutBlSiFact )
CVector<int>& veciNetwInBlSiFact )
{ {
ChannelSet.GetConCliParam ( vecHostAddresses, vecsName, ChannelSet.GetConCliParam ( vecHostAddresses, vecsName,
veciJitBufSize, veciNetwOutBlSiFact, veciNetwInBlSiFact ); veciJitBufSize, veciNetwOutBlSiFact );
} }
bool GetTimingStdDev ( double& dCurTiStdDev ); bool GetTimingStdDev ( double& dCurTiStdDev );

View File

@ -112,7 +112,7 @@ void CSettings::ReadIniFile ( const QString& sFileName )
} }
// network jitter buffer size // network jitter buffer size
if ( GetNumericIniSet ( IniXMLDocument, "client", "jitbuf", 0, MAX_NET_BUF_SIZE_NUM_BL, iValue ) ) if ( GetNumericIniSet ( IniXMLDocument, "client", "jitbuf", MIN_NET_BUF_SIZE_NUM_BL, MAX_NET_BUF_SIZE_NUM_BL, iValue ) )
{ {
pClient->SetSockBufSize ( iValue ); pClient->SetSockBufSize ( iValue );
} }
@ -142,16 +142,16 @@ void CSettings::ReadIniFile ( const QString& sFileName )
switch ( iValue ) switch ( iValue )
{ {
case 0: case 0:
pClient->SetAudioCompressionOut ( CAudioCompression::CT_NONE ); pClient->SetAudioCompressionOut ( CT_NONE );
break; break;
case 1: case 1:
pClient->SetAudioCompressionOut ( CAudioCompression::CT_IMAADPCM ); pClient->SetAudioCompressionOut ( CT_IMAADPCM );
break; break;
case 2: case 2:
break; break;
pClient->SetAudioCompressionOut ( CAudioCompression::CT_MSADPCM ); pClient->SetAudioCompressionOut ( CT_MSADPCM );
} }
} }
} }
@ -206,15 +206,15 @@ void CSettings::WriteIniFile ( const QString& sFileName )
// for integer numbers!) // for integer numbers!)
switch ( pClient->GetAudioCompressionOut() ) switch ( pClient->GetAudioCompressionOut() )
{ {
case CAudioCompression::CT_NONE: case CT_NONE:
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 0 ); SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 0 );
break; break;
case CAudioCompression::CT_IMAADPCM: case CT_IMAADPCM:
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 1 ); SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 1 );
break; break;
case CAudioCompression::CT_MSADPCM: case CT_MSADPCM:
SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 2 ); SetNumericIniSet ( IniXMLDocument, "client", "audiocompression", 2 );
break; break;
} }

View File

@ -36,8 +36,9 @@
/* Definitions ****************************************************************/ /* Definitions ****************************************************************/
// Maximum block size for network input buffer. Consider two bytes per sample. // Maximum block size for network input buffer. Consider a maximum sample rate
#define MAX_SIZE_BYTES_NETW_BUF ( MAX_NET_BLOCK_SIZE_FACTOR * MIN_BLOCK_SIZE_SAMPLES * 2 ) // of 48 kHz and two audio channels and two bytes per sample.
#define MAX_SIZE_BYTES_NETW_BUF ( MAX_MONO_AUD_BUFF_SIZE_AT_48KHZ * 4 )
/* Classes ********************************************************************/ /* Classes ********************************************************************/
@ -57,7 +58,7 @@ public:
const CHostAddress& HostAddr ); const CHostAddress& HostAddr );
protected: protected:
void Init ( const quint16 iPortNumber = LLCON_PORT_NUMBER ); void Init ( const quint16 iPortNumber = LLCON_DFAULT_PORT_NUMBER );
QUdpSocket SocketDevice; QUdpSocket SocketDevice;

View File

@ -29,16 +29,24 @@
void CSoundBase::Init ( const int iNewStereoBufferSize ) void CSoundBase::Init ( const int iNewStereoBufferSize )
{ {
// init audio sound card buffer // init audio sound card buffer
vecsAudioSndCrdStereo.Init ( iNewStereoBufferSize ); if ( !bIsCallbackAudioInterface )
{
vecsAudioSndCrdStereo.Init ( iNewStereoBufferSize );
}
} }
void CSoundBase::Start() void CSoundBase::Start()
{ {
bRun = true;
// TODO start audio interface // TODO start audio interface
// start the audio thread // start the audio thread in case we do not have an callback
start(); // based audio interface
if ( !bIsCallbackAudioInterface )
{
start();
}
} }
void CSoundBase::Stop() void CSoundBase::Stop()
@ -47,7 +55,10 @@ void CSoundBase::Stop()
bRun = false; bRun = false;
// give thread some time to terminate // give thread some time to terminate
wait ( 5000 ); if ( !bIsCallbackAudioInterface )
{
wait ( 5000 );
}
// TODO stop audio interface (previously done in Close function, we // TODO stop audio interface (previously done in Close function, we
@ -74,7 +85,6 @@ void CSoundBase::run()
#endif #endif
// main loop of working thread // main loop of working thread
bRun = true;
while ( bRun ) while ( bRun )
{ {
// get audio from sound card (blocking function) // get audio from sound card (blocking function)

View File

@ -34,9 +34,11 @@
class CSoundBase : public QThread class CSoundBase : public QThread
{ {
public: public:
CSoundBase ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), CSoundBase ( const bool bNewIsCallbackAudioInterface,
void (*fpNewCallback) ( CVector<short>& psData, void* arg ),
void* arg ) : fpCallback ( fpNewCallback ), pCallbackArg ( arg ), void* arg ) : fpCallback ( fpNewCallback ), pCallbackArg ( arg ),
bRun ( false ) {} bRun ( false ),
bIsCallbackAudioInterface ( bNewIsCallbackAudioInterface ) {}
virtual ~CSoundBase() {} virtual ~CSoundBase() {}
virtual void Init ( const int iNewStereoBufferSize ); virtual void Init ( const int iNewStereoBufferSize );
@ -50,6 +52,12 @@ protected:
void (*fpCallback) ( CVector<short>& psData, void* arg ); void (*fpCallback) ( CVector<short>& psData, void* arg );
void* pCallbackArg; void* pCallbackArg;
// callback function call for derived classes
void Callback ( CVector<short>& psData )
{
(*fpCallback) ( psData, pCallbackArg );
}
// these functions should be overwritten by derived class for // these functions should be overwritten by derived class for
// non callback based audio interfaces // non callback based audio interfaces
virtual bool Read ( CVector<short>& psData ) { printf ( "no sound!" ); return false; } virtual bool Read ( CVector<short>& psData ) { printf ( "no sound!" ); return false; }
@ -57,6 +65,7 @@ protected:
void run(); void run();
bool bRun; bool bRun;
bool bIsCallbackAudioInterface;
CVector<short> vecsAudioSndCrdStereo; CVector<short> vecsAudioSndCrdStereo;
}; };

View File

@ -407,23 +407,23 @@ public:
QString strName; QString strName;
}; };
enum EAudComprType
{
CT_NONE = 0,
CT_IMAADPCM = 1,
CT_MSADPCM = 2
};
class CNetworkTransportProps class CNetworkTransportProps
{ {
public: public:
enum EAudioCodingType
{
ACT_NONE = 0,
ACT_IMA_ADPCM = 1,
ACT_MS_ADPCM = 2
};
CNetworkTransportProps() : iNetworkPacketSize ( 0 ), iMonoAudioBlockSize ( 0 ), CNetworkTransportProps() : iNetworkPacketSize ( 0 ), iMonoAudioBlockSize ( 0 ),
iNumAudioChannels ( 0 ), iSampleRate ( 0 ), iNumAudioChannels ( 0 ), iSampleRate ( 0 ),
eAudioCodingType ( ACT_NONE ), iAudioCodingArg ( 0 ) {} eAudioCodingType ( CT_NONE ), iAudioCodingArg ( 0 ) {}
CNetworkTransportProps ( const unsigned int iNNPS, const unsigned int iNMABS, CNetworkTransportProps ( const unsigned int iNNPS, const unsigned int iNMABS,
const unsigned int iNNACH, const unsigned int iNSR, const unsigned int iNNACH, const unsigned int iNSR,
const EAudioCodingType eNACT, const int iNACA ) : const EAudComprType eNACT, const int iNACA ) :
iNetworkPacketSize ( iNNPS ), iMonoAudioBlockSize ( iNMABS ), iNetworkPacketSize ( iNNPS ), iMonoAudioBlockSize ( iNMABS ),
iNumAudioChannels ( iNNACH ), iSampleRate ( iNSR ), eAudioCodingType ( eNACT ), iNumAudioChannels ( iNNACH ), iSampleRate ( iNSR ), eAudioCodingType ( eNACT ),
iAudioCodingArg ( iNACA ) {} iAudioCodingArg ( iNACA ) {}
@ -432,7 +432,7 @@ public:
unsigned int iMonoAudioBlockSize; unsigned int iMonoAudioBlockSize;
unsigned int iNumAudioChannels; unsigned int iNumAudioChannels;
unsigned int iSampleRate; unsigned int iSampleRate;
EAudioCodingType eAudioCodingType; EAudComprType eAudioCodingType;
int iAudioCodingArg; int iAudioCodingArg;
}; };

View File

@ -29,15 +29,10 @@
/* Implementation *************************************************************/ /* Implementation *************************************************************/
#include <qmutex.h>
// external references // external references
extern AsioDrivers* asioDrivers; extern AsioDrivers* asioDrivers;
bool loadAsioDriver ( char *name ); bool loadAsioDriver ( char *name );
// mutex
QMutex ASIOMutex;
// TODO the following variables should be in the class definition but we cannot // TODO the following variables should be in the class definition but we cannot
// do it here since we have static callback functions which cannot access the // do it here since we have static callback functions which cannot access the
// class members :-((( // class members :-(((
@ -52,188 +47,12 @@ int iBufferSizeMono;
int iBufferSizeStereo; int iBufferSizeStereo;
int iASIOBufferSizeMono; int iASIOBufferSizeMono;
// event CVector<short> vecsTmpAudioSndCrdStereo;
HANDLE m_ASIOEvent;
// wave in QMutex ASIOMutex;
short* psCaptureBuffer;
int iBufferPosCapture;
bool bCaptureBufferOverrun;
// wave out // TEST
short* psPlayBuffer; CSound* pSound;
int iBufferPosPlay;
bool bPlayBufferUnderrun;
int iMinNumSndBuf;
int iCurNumSndBufIn;
int iCurNumSndBufOut;
int iNewNumSndBufIn;
int iNewNumSndBufOut;
bool bSetNumSndBufToMinimumValue;
// we must implement these functions here to get access to global variables
int CSound::GetOutNumBuf() { return iNewNumSndBufOut; }
int CSound::GetInNumBuf() { return iNewNumSndBufIn; }
/******************************************************************************\
* Wave in *
\******************************************************************************/
bool CSound::Read ( CVector<short>& psData )
{
int i;
bool bError;
// check if device must be opened or reinitialized
if ( bChangParamIn )
{
// reinit sound interface
Init ( iBufferSizeStereo );
// reset flag
bChangParamIn = false;
}
// wait until enough data is available
int iWaitCount = 0;
while ( iBufferPosCapture < iBufferSizeStereo )
{
if ( !bCaptureBufferOverrun )
{
// regular case
WaitForSingleObject ( m_ASIOEvent, INFINITE );
}
else
{
// it seems that the buffers are too small, wait
// just one time to avoid CPU to go up to 100% and
// then leave this function
if ( iWaitCount == 0 )
{
WaitForSingleObject ( m_ASIOEvent, INFINITE );
iWaitCount++;
}
else
{
return true;
}
}
}
ASIOMutex.lock(); // get mutex lock
{
// check for buffer overrun in ASIO thread
bError = bCaptureBufferOverrun;
if ( bCaptureBufferOverrun )
{
// reset flag
bCaptureBufferOverrun = false;
}
// copy data from sound card capture buffer in function output buffer
for ( i = 0; i < iBufferSizeStereo; i++ )
{
psData[i] = psCaptureBuffer[i];
}
// move all other data in buffer
const int iLenCopyRegion = iBufferPosCapture - iBufferSizeStereo;
for ( i = 0; i < iLenCopyRegion; i++ )
{
psCaptureBuffer[i] = psCaptureBuffer[iBufferSizeStereo + i];
}
// adjust "current block to write" pointer
iBufferPosCapture -= iBufferSizeStereo;
// in case more than one buffer was ready, reset event
ResetEvent ( m_ASIOEvent );
}
ASIOMutex.unlock();
return bError;
}
void CSound::SetInNumBuf ( int iNewNum )
{
// check new parameter
if ( ( iNewNum < MAX_SND_BUF_IN ) && ( iNewNum >= iMinNumSndBuf ) )
{
// change only if parameter is different
if ( iNewNum != iNewNumSndBufIn )
{
iNewNumSndBufIn = iNewNum;
bChangParamIn = true;
}
}
}
/******************************************************************************\
* Wave out *
\******************************************************************************/
bool CSound::Write ( CVector<short>& psData )
{
bool bError;
// check if device must be opened or reinitialized
if ( bChangParamOut )
{
// reinit sound interface
Init ( iBufferSizeStereo );
// reset flag
bChangParamOut = false;
}
ASIOMutex.lock(); // get mutex lock
{
// check for buffer underrun in ASIO thread
bError = bPlayBufferUnderrun;
if ( bPlayBufferUnderrun )
{
// reset flag
bPlayBufferUnderrun = false;
}
// first check if enough data in buffer is available
const int iPlayBufferLen = iCurNumSndBufOut * iBufferSizeStereo;
if ( iBufferPosPlay + iBufferSizeStereo > iPlayBufferLen )
{
// buffer overrun, return error
bError = true;
}
else
{
// copy stereo data from function input in soundcard play buffer
for ( int i = 0; i < iBufferSizeStereo; i++ )
{
psPlayBuffer[iBufferPosPlay + i] = psData[i];
}
iBufferPosPlay += iBufferSizeStereo;
}
}
ASIOMutex.unlock();
return bError;
}
void CSound::SetOutNumBuf ( int iNewNum )
{
// check new parameter
if ( ( iNewNum < MAX_SND_BUF_OUT ) && ( iNewNum >= iMinNumSndBuf ) )
{
// change only if parameter is different
if ( iNewNum != iNewNumSndBufOut )
{
iNewNumSndBufOut = iNewNum;
bChangParamOut = true;
}
}
}
/******************************************************************************\ /******************************************************************************\
@ -244,24 +63,11 @@ void CSound::SetDev ( const int iNewDev )
// check if an ASIO driver was already initialized // check if an ASIO driver was already initialized
if ( lCurDev >= 0 ) if ( lCurDev >= 0 )
{ {
// the new driver was not selected before, use default settings for
// buffer sizes
bSetNumSndBufToMinimumValue = true;
// a device was already been initialized and is used, kill working // a device was already been initialized and is used, kill working
// thread and clean up // thread and clean up
// stop driver // stop driver
ASIOStop(); ASIOStop();
// set event to ensure that thread leaves the waiting function
if ( m_ASIOEvent != NULL )
{
SetEvent ( m_ASIOEvent );
}
// wait for the thread to terminate
Sleep ( 500 );
// dispose ASIO buffers // dispose ASIO buffers
ASIODisposeBuffers(); ASIODisposeBuffers();
@ -273,14 +79,6 @@ void CSound::SetDev ( const int iNewDev )
if ( !strErrorMessage.empty() ) if ( !strErrorMessage.empty() )
{ {
// The new driver initializing was not successful, try to preserve
// the old buffer settings -> this is possible, if errornous driver
// had failed before the buffer setting was done. If it failed after
// setting the minimum buffer sizes, the following flag modification
// does not have any effect which means the old settings cannot be
// recovered anymore (TODO better solution)
bSetNumSndBufToMinimumValue = false;
// loading and initializing the new driver failed, go back to original // loading and initializing the new driver failed, go back to original
// driver and display error message // driver and display error message
LoadAndInitializeDriver ( lCurDev ); LoadAndInitializeDriver ( lCurDev );
@ -313,10 +111,6 @@ void CSound::SetDev ( const int iNewDev )
} }
else else
{ {
// the new driver was not selected before, use default settings for
// buffer sizes
bSetNumSndBufToMinimumValue = true;
// try to find one usable driver (select the first valid driver) // try to find one usable driver (select the first valid driver)
if ( !LoadAndInitializeFirstValidDriver() ) if ( !LoadAndInitializeFirstValidDriver() )
{ {
@ -510,40 +304,7 @@ const bool bPreferPowerOfTwoAudioBufferSize = false;
} }
} }
// calculate the minimum required number of soundcard buffers /*
iMinNumSndBuf = static_cast<int> (
ceil ( static_cast<double> ( iASIOBufferSizeMono ) / iBufferSizeMono ) );
// TODO better solution
// For some ASIO buffer sizes, the above calculation seems not to work although
// it should be correct. Maybe there is a misunderstanding or a bug in the
// sound interface implementation. As a workaround, we implement a table here, to
// get working parameters for the most common ASIO buffer settings
// Interesting observation: only 256 samples seems to be wrong, all other tested
// buffer sizes like 192, 512, 384, etc. are correct...
if ( iASIOBufferSizeMono == 256 )
{
iMinNumSndBuf = 4;
}
Q_ASSERT ( iMinNumSndBuf < MAX_SND_BUF_IN );
Q_ASSERT ( iMinNumSndBuf < MAX_SND_BUF_OUT );
// set or just check the sound card buffer sizes
if ( bSetNumSndBufToMinimumValue )
{
// use minimum buffer sizes as default
iNewNumSndBufIn = iMinNumSndBuf;
iNewNumSndBufOut = iMinNumSndBuf;
}
else
{
// correct number of sound card buffers if required
iNewNumSndBufIn = max ( iMinNumSndBuf, iNewNumSndBufIn );
iNewNumSndBufOut = max ( iMinNumSndBuf, iNewNumSndBufOut );
}
iCurNumSndBufIn = iNewNumSndBufIn;
iCurNumSndBufOut = iNewNumSndBufOut;
// display warning in case the ASIO buffer is too big // display warning in case the ASIO buffer is too big
if ( iMinNumSndBuf > 6 ) if ( iMinNumSndBuf > 6 )
{ {
@ -557,6 +318,7 @@ if ( iASIOBufferSizeMono == 256 )
"before you try to change the ASIO driver buffer size all ASIO " "before you try to change the ASIO driver buffer size all ASIO "
"applications including llcon are closed." ), "Ok", 0 ); "applications including llcon are closed." ), "Ok", 0 );
} }
*/
// prepare input channels // prepare input channels
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ ) for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
@ -621,40 +383,11 @@ void CSound::Init ( const int iNewStereoBufferSize )
iBufferSizeStereo = iNewStereoBufferSize; iBufferSizeStereo = iNewStereoBufferSize;
iBufferSizeMono = iBufferSizeStereo / 2; iBufferSizeMono = iBufferSizeStereo / 2;
// store new buffer number values // TEST
iCurNumSndBufIn = iNewNumSndBufIn; PrepareDriver();
iCurNumSndBufOut = iNewNumSndBufOut;
// initialize write block pointer in and overrun flag // create memory for intermediate audio buffer
iBufferPosCapture = 0; vecsTmpAudioSndCrdStereo.Init ( iBufferSizeStereo );
bCaptureBufferOverrun = false;
// create memory for capture buffer
if ( psCaptureBuffer != NULL )
{
delete[] psCaptureBuffer;
}
psCaptureBuffer = new short[iCurNumSndBufIn * iBufferSizeStereo];
// initialize write block pointer out and underrun flag
iBufferPosPlay = 0;
bPlayBufferUnderrun = false;
// create memory for play buffer
if ( psPlayBuffer != NULL )
{
delete[] psPlayBuffer;
}
psPlayBuffer = new short[iCurNumSndBufOut * iBufferSizeStereo];
// clear new buffer
for ( int i = 0; i < iCurNumSndBufOut * iBufferSizeStereo; i++ )
{
psPlayBuffer[i] = 0;
}
// reset event
ResetEvent ( m_ASIOEvent );
} }
ASIOMutex.unlock(); ASIOMutex.unlock();
@ -666,33 +399,15 @@ void CSound::Close()
{ {
// stop driver // stop driver
ASIOStop(); ASIOStop();
// set event to ensure that thread leaves the waiting function
if ( m_ASIOEvent != NULL )
{
SetEvent ( m_ASIOEvent );
}
// wait for the thread to terminate
Sleep ( 500 );
// set flag to open devices the next time it is initialized
bChangParamIn = true;
bChangParamOut = true;
} }
CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) : CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
CSoundBase ( fpNewCallback, arg ) CSoundBase ( true, fpNewCallback, arg )
{ {
// init number of sound buffers
iNewNumSndBufIn = NUM_SOUND_BUFFERS_IN;
iCurNumSndBufIn = NUM_SOUND_BUFFERS_IN;
iNewNumSndBufOut = NUM_SOUND_BUFFERS_OUT;
iCurNumSndBufOut = NUM_SOUND_BUFFERS_OUT;
iMinNumSndBuf = 1;
// should be initialized because an error can occur during init // TEST
m_ASIOEvent = NULL; pSound = this;
// get available ASIO driver names in system // get available ASIO driver names in system
for ( int i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ ) for ( int i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ )
@ -719,19 +434,6 @@ CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), vo
asioCallbacks.sampleRateDidChange = &sampleRateChanged; asioCallbacks.sampleRateDidChange = &sampleRateChanged;
asioCallbacks.asioMessage = &asioMessages; asioCallbacks.asioMessage = &asioMessages;
asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo; asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
// init buffer pointer to zero
psCaptureBuffer = NULL;
psPlayBuffer = NULL;
// we use an event controlled structure
// create event
m_ASIOEvent = CreateEvent ( NULL, FALSE, FALSE, NULL );
// init flags
bChangParamIn = false;
bChangParamOut = false;
bSetNumSndBufToMinimumValue = false;
} }
CSound::~CSound() CSound::~CSound()
@ -741,22 +443,6 @@ CSound::~CSound()
ASIODisposeBuffers(); ASIODisposeBuffers();
ASIOExit(); ASIOExit();
asioDrivers->removeCurrentDriver(); asioDrivers->removeCurrentDriver();
// delete allocated memory
if ( psCaptureBuffer != NULL )
{
delete[] psCaptureBuffer;
}
if ( psPlayBuffer != NULL )
{
delete[] psPlayBuffer;
}
// close the handle for the event
if ( m_ASIOEvent != NULL )
{
CloseHandle ( m_ASIOEvent );
}
} }
// ASIO callbacks ------------------------------------------------------------- // ASIO callbacks -------------------------------------------------------------
@ -774,141 +460,106 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
ASIOMutex.lock(); // get mutex lock ASIOMutex.lock(); // get mutex lock
{ {
// first check buffer state of capture and play buffers
const int iCaptureBufferLen = iCurNumSndBufIn * iBufferSizeStereo;
bCaptureBufferOverrun =
( iBufferPosCapture + 2 * iASIOBufferSizeMono > iCaptureBufferLen );
bPlayBufferUnderrun = ( 2 * iASIOBufferSizeMono > iBufferPosPlay );
// perform the processing for input and output // perform the processing for input and output
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo
{ {
if ( bufferInfos[i].isInput == ASIOTrue ) if ( bufferInfos[i].isInput == ASIOTrue )
{ {
// CAPTURE ----------------------------------------------------- // CAPTURE -----------------------------------------------------
// first check if space in buffer is available // copy new captured block in thread transfer buffer (copy
if ( !bCaptureBufferOverrun ) // mono data interleaved in stereo buffer)
switch ( channelInfos[i].type )
{ {
// copy new captured block in thread transfer buffer (copy case ASIOSTInt16LSB:
// mono data interleaved in stereo buffer) for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
switch ( channelInfos[i].type )
{ {
case ASIOSTInt16LSB: vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] =
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) ( (short*) bufferInfos[i].buffers[index] )[iCurSample];
{ }
psCaptureBuffer[iBufferPosCapture + break;
2 * iCurSample + bufferInfos[i].channelNum] =
( (short*) bufferInfos[i].buffers[index] )[iCurSample];
}
break;
case ASIOSTInt24LSB: case ASIOSTInt24LSB:
// not yet tested, horrible things might happen with the following code ;-) // not yet tested, horrible things might happen with the following code ;-)
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{ {
// convert current sample in 16 bit format // convert current sample in 16 bit format
int iCurSam = 0; int iCurSam = 0;
memcpy ( &iCurSam, ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 ); memcpy ( &iCurSam, ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 );
iCurSam >>= 8; iCurSam >>= 8;
psCaptureBuffer[iBufferPosCapture + vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] =
2 * iCurSample + bufferInfos[i].channelNum] = static_cast<short> ( iCurSam ); static_cast<short> ( iCurSam );
}
break;
case ASIOSTInt32LSB:
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{
// convert to 16 bit
psCaptureBuffer[iBufferPosCapture +
2 * iCurSample + bufferInfos[i].channelNum] =
(((int*) bufferInfos[i].buffers[index])[iCurSample] >> 16);
}
break;
} }
break;
case ASIOSTInt32LSB:
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{
// convert to 16 bit
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] =
(((int*) bufferInfos[i].buffers[index])[iCurSample] >> 16);
}
break;
} }
} }
else }
// call processing callback function
pSound->Callback( vecsTmpAudioSndCrdStereo );
// perform the processing for input and output
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo
{
if ( bufferInfos[i].isInput != ASIOTrue )
{ {
// PLAYBACK ---------------------------------------------------- // PLAYBACK ----------------------------------------------------
if ( !bPlayBufferUnderrun ) // copy data from sound card in output buffer (copy
// interleaved stereo data in mono sound card buffer)
switch ( channelInfos[i].type )
{ {
// copy data from sound card in output buffer (copy case ASIOSTInt16LSB:
// interleaved stereo data in mono sound card buffer) for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
switch ( channelInfos[i].type )
{ {
case ASIOSTInt16LSB: ( (short*) bufferInfos[i].buffers[index] )[iCurSample] =
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum];
{ }
( (short*) bufferInfos[i].buffers[index] )[iCurSample] = break;
psPlayBuffer[2 * iCurSample + bufferInfos[i].channelNum];
}
break;
case ASIOSTInt24LSB: case ASIOSTInt24LSB:
// not yet tested, horrible things might happen with the following code ;-) // not yet tested, horrible things might happen with the following code ;-)
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{ {
// convert current sample in 24 bit format // convert current sample in 24 bit format
int iCurSam = static_cast<int> ( psPlayBuffer[2 * iCurSample + bufferInfos[i].channelNum] ); int iCurSam = static_cast<int> ( vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] );
iCurSam <<= 8; iCurSam <<= 8;
memcpy ( ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 ); memcpy ( ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 );
}
break;
case ASIOSTInt32LSB:
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{
// convert to 32 bit
int iCurSam = static_cast<int> ( psPlayBuffer[2 * iCurSample + bufferInfos[i].channelNum] );
( (int*) bufferInfos[i].buffers[index] )[iCurSample] = ( iCurSam << 16 );
}
break;
} }
break;
case ASIOSTInt32LSB:
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
{
// convert to 32 bit
int iCurSam = static_cast<int> ( vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] );
( (int*) bufferInfos[i].buffers[index] )[iCurSample] = ( iCurSam << 16 );
}
break;
} }
} }
} }
// Manage thread interface buffers for input and output ----------------
// capture
if ( !bCaptureBufferOverrun )
{
iBufferPosCapture += 2 * iASIOBufferSizeMono;
}
// play
if ( !bPlayBufferUnderrun )
{
// move all other data in play buffer
const int iLenCopyRegion = iBufferPosPlay - 2 * iASIOBufferSizeMono;
for ( iCurSample = 0; iCurSample < iLenCopyRegion; iCurSample++ )
{
psPlayBuffer[iCurSample] =
psPlayBuffer[2 * iASIOBufferSizeMono + iCurSample];
}
// adjust "current block to write" pointer
iBufferPosPlay -= 2 * iASIOBufferSizeMono;
}
// finally if the driver supports the ASIOOutputReady() optimization, // finally if the driver supports the ASIOOutputReady() optimization,
// do it here, all data are in place ----------------------------------- // do it here, all data are in place -----------------------------------
if ( bASIOPostOutput ) if ( bASIOPostOutput )
{ {
ASIOOutputReady(); ASIOOutputReady();
} }
// set event
SetEvent ( m_ASIOEvent );
} }
ASIOMutex.unlock(); ASIOMutex.unlock();
} }

View File

@ -28,6 +28,7 @@
#include <windows.h> #include <windows.h>
#include <string> #include <string>
#include <qmutex.h>
#include <qmessagebox.h> #include <qmessagebox.h>
#include "../src/util.h" #include "../src/util.h"
#include "../src/global.h" #include "../src/global.h"
@ -59,8 +60,6 @@ public:
virtual ~CSound(); virtual ~CSound();
virtual void Init ( const int iNewStereoBufferSize ); virtual void Init ( const int iNewStereoBufferSize );
virtual bool Read ( CVector<short>& psData );
virtual bool Write ( CVector<short>& psData );
virtual void Close(); virtual void Close();
int GetNumDev() { return lNumDevs; } int GetNumDev() { return lNumDevs; }
@ -69,10 +68,10 @@ public:
void SetDev ( const int iNewDev ); void SetDev ( const int iNewDev );
int GetDev() { return lCurDev; } int GetDev() { return lCurDev; }
void SetOutNumBuf ( const int iNewNum ); void SetOutNumBuf ( const int iNewNum ) {}
int GetOutNumBuf(); int GetOutNumBuf() { return 1; }
void SetInNumBuf ( const int iNewNum ); void SetInNumBuf ( const int iNewNum ) {}
int GetInNumBuf(); int GetInNumBuf() { return 1; }
protected: protected:
bool LoadAndInitializeFirstValidDriver(); bool LoadAndInitializeFirstValidDriver();
@ -97,9 +96,6 @@ protected:
long lNumDevs; long lNumDevs;
long lCurDev; long lCurDev;
char* cDriverNames[MAX_NUMBER_SOUND_CARDS]; char* cDriverNames[MAX_NUMBER_SOUND_CARDS];
bool bChangParamIn;
bool bChangParamOut;
}; };
#endif // !defined ( AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_ ) #endif // !defined ( AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_ )