finished separate mix implementation for each connected client of the server

This commit is contained in:
Volker Fischer 2006-12-06 20:22:41 +00:00
parent cb9de2b952
commit e335718eb5
5 changed files with 149 additions and 99 deletions

View file

@ -37,11 +37,11 @@ CChannelSet::CChannelSet()
QObject::connect(&vecChannels[2],SIGNAL(MessReadyForSending(CVector<uint8_t>)),this,SLOT(OnSendProtMessCh2(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[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>)));
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
QObject::connect(&vecChannels[0],SIGNAL(NewConnection()),this,SLOT(OnNewConnectionCh0()));
@ -49,11 +49,11 @@ CChannelSet::CChannelSet()
QObject::connect(&vecChannels[2],SIGNAL(NewConnection()),this,SLOT(OnNewConnectionCh2()));
QObject::connect(&vecChannels[3],SIGNAL(NewConnection()),this,SLOT(OnNewConnectionCh3()));
QObject::connect(&vecChannels[4],SIGNAL(NewConnection()),this,SLOT(OnNewConnectionCh4()));
// 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()));
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()));
}
void CChannelSet::CreateAndSendChanListForAllConClients()
@ -142,9 +142,22 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
iCurChanID = GetFreeChan();
if ( iCurChanID != INVALID_CHANNEL_ID )
{
{
// initialize current channel by storing the calling host
// address
vecChannels[iCurChanID].SetAddress ( HostAdr );
// reset the channel gains of current channel, at the same
// time reset gains of this channel ID for all other channels
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{
vecChannels[iCurChanID].SetGain ( i, (double) 1.0 );
// other channels (we do not distinguish the case if
// i == iCurChanID for simplicity)
vecChannels[i].SetGain ( iCurChanID, (double) 1.0 );
}
// a new client connected to the server, set flag to create and
// send all clients the updated channel list, we cannot create
// the message here since the received data has to be put to the
@ -198,42 +211,41 @@ bool CChannelSet::PutData ( const CVector<unsigned char>& vecbyRecBuf,
return bRet;
}
void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
void CChannelSet::GetBlockAllConC ( CVector<int>& vecChanID,
CVector<CVector<double> >& vecvecdData,
CVector<double>& vecdGains )
{
/* init temporal data vector and clear input buffers */
CVector<CVector<double> >& vecvecdGains )
{
int i, j;
// init temporal data vector and clear input buffers
CVector<double> vecdData ( MIN_BLOCK_SIZE_SAMPLES );
vecChanID.Init ( 0 );
vecvecdData.Init ( 0 );
vecdGains.Init ( 0 );
vecChanID.Init ( 0 );
vecvecdData.Init ( 0 );
vecvecdGains.Init ( 0 );
/* make put and get calls thread safe. Do not forget to unlock mutex
afterwards! */
// make put and get calls thread safe. Do not forget to unlock mutex
// afterwards!
Mutex.lock();
{
/* Check all possible channels */
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
// check all possible channels
for ( i = 0; i < MAX_NUM_CHANNELS; i++ )
{
/* read out all input buffers to decrease timeout counter on
disconnected channels */
// read out all input buffers to decrease timeout counter on
// disconnected channels
const bool bGetOK = vecChannels[i].GetData ( vecdData );
if ( vecChannels[i].IsConnected() )
{
/* add ID, gain and data */
// add ID and data
vecChanID.Add ( i );
// TEST
vecdGains.Add ( 1.0);//vecChannels[i].GetGain() );
const int iOldSize = vecvecdData.Size();
vecvecdData.Enlarge ( 1 );
vecvecdData[iOldSize].Init ( vecdData.Size() );
vecvecdData[iOldSize] = vecdData;
/* send message for get status (for GUI) */
// send message for get status (for GUI)
if ( bGetOK )
{
PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_GREEN, i );
@ -243,23 +255,40 @@ vecdGains.Add ( 1.0);//vecChannels[i].GetGain() );
PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED, i );
}
}
}
// now that we know the IDs of the connected clients, get gains
const int iNumCurConnChan = vecChanID.Size();
vecvecdGains.Init ( iNumCurConnChan );
for ( i = 0; i < iNumCurConnChan; i++ )
{
vecvecdGains[i].Init ( iNumCurConnChan );
for ( j = 0; j < iNumCurConnChan; j++ )
{
// The second index of "vecvecdGains" does not represent
// the channel ID! Therefore we have to use "vecChanID" to
// query the IDs of the currently connected channels
vecvecdGains[i][j] = vecChannels[i].GetGain( vecChanID[j] );
}
}
}
Mutex.unlock(); /* release mutex */
Mutex.unlock(); // release mutex
}
void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CVector<int>& veciJitBufSize,
CVector<int>& veciNetwOutBlSiFact,
CVector<int>& veciNetwInBlSiFact )
CVector<int>& veciJitBufSize,
CVector<int>& veciNetwOutBlSiFact,
CVector<int>& veciNetwInBlSiFact )
{
CHostAddress InetAddr;
/* init return values */
vecHostAddresses.Init ( MAX_NUM_CHANNELS );
veciJitBufSize.Init ( MAX_NUM_CHANNELS );
vecHostAddresses.Init ( MAX_NUM_CHANNELS );
veciJitBufSize.Init ( MAX_NUM_CHANNELS );
veciNetwOutBlSiFact.Init ( MAX_NUM_CHANNELS );
veciNetwInBlSiFact.Init ( MAX_NUM_CHANNELS );
veciNetwInBlSiFact.Init ( MAX_NUM_CHANNELS );
/* Check all possible channels */
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
@ -267,10 +296,10 @@ void CChannelSet::GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
if ( vecChannels[i].GetAddress ( InetAddr ) )
{
/* get requested data */
vecHostAddresses[i] = InetAddr;
veciJitBufSize[i] = vecChannels[i].GetSockBufSize ();
vecHostAddresses[i] = InetAddr;
veciJitBufSize[i] = vecChannels[i].GetSockBufSize ();
veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut ();
veciNetwInBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactIn ();
veciNetwInBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactIn ();
}
}
}
@ -310,16 +339,20 @@ CChannel::CChannel() : sName ( "" ),
SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ),
this, SLOT ( OnSendProtMessage ( CVector<uint8_t> ) ) );
QObject::connect ( &Protocol, SIGNAL ( ChangeJittBufSize ( int ) ),
QObject::connect ( &Protocol,
SIGNAL ( ChangeJittBufSize ( int ) ),
this, SLOT ( OnJittBufSizeChange ( int ) ) );
QObject::connect ( &Protocol, SIGNAL ( ReqJittBufSize() ),
QObject::connect ( &Protocol,
SIGNAL ( ReqJittBufSize() ),
SIGNAL ( ReqJittBufSize() ) );
QObject::connect ( &Protocol, SIGNAL ( ConClientListMesReceived ( CVector<CChannelShortInfo> ) ),
QObject::connect ( &Protocol,
SIGNAL ( ConClientListMesReceived ( CVector<CChannelShortInfo> ) ),
SIGNAL ( ConClientListMesReceived ( CVector<CChannelShortInfo> ) ) );
QObject::connect ( &Protocol, SIGNAL ( ChangeNetwBlSiFact ( int ) ),
QObject::connect ( &Protocol,
SIGNAL ( ChangeNetwBlSiFact ( int ) ),
this, SLOT ( OnNetwBlSiFactChange ( int ) ) );
}
@ -355,14 +388,6 @@ void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut )
ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_BLOCK_SIZE_SAMPLES );
}
void CChannel::OnNetwBlSiFactChange ( int iNewNetwBlSiFact )
{
// TEST
//qDebug ( "new network block size factor: %d", iNewNetwBlSiFact );
SetNetwBufSizeFactOut ( iNewNetwBlSiFact );
}
void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage )
{
// only send messages if we are connected, otherwise delete complete queue
@ -397,6 +422,14 @@ void CChannel::SetSockBufSize ( const int iNumBlocks )
Mutex.unlock();
}
void CChannel::OnNetwBlSiFactChange ( int iNewNetwBlSiFact )
{
// TEST
//qDebug ( "new network block size factor: %d", iNewNetwBlSiFact );
SetNetwBufSizeFactOut ( iNewNetwBlSiFact );
}
void CChannel::OnJittBufSizeChange ( int iNewJitBufSize )
{
// TEST
@ -405,6 +438,14 @@ void CChannel::OnJittBufSizeChange ( int iNewJitBufSize )
SetSockBufSize ( iNewJitBufSize );
}
void CChannel::OnChangeChanGain ( int iChanID, double dNewGain )
{
ASSERT ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) );
// set value
vecdGains[iChanID] = dNewGain;
}
bool CChannel::GetAddress(CHostAddress& RetAddr)
{
if ( IsConnected() )

View file

@ -43,7 +43,7 @@
/* maximum number of internet connections (channels) */
// if you want to change this paramter, change the connections in this class, too!
#define MAX_NUM_CHANNELS 5//10 /* max number channels for server */
#define MAX_NUM_CHANNELS 10 /* max number channels for server */
/* no valid channel number */
#define INVALID_CHANNEL_ID (MAX_NUM_CHANNELS + 1)
@ -165,6 +165,7 @@ public slots:
void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnJittBufSizeChange ( int iNewJitBufSize );
void OnNetwBlSiFactChange ( int iNewNetwBlSiFact );
void OnChangeChanGain ( int iChanID, double dNewGain );
signals:
void MessReadyForSending ( CVector<uint8_t> vecMessage );
@ -193,7 +194,7 @@ public:
void GetBlockAllConC ( CVector<int>& vecChanID,
CVector<CVector<double> >& vecvecdData,
CVector<double>& vecdGains );
CVector<CVector<double> >& vecvecdGains );
void GetConCliParam ( CVector<CHostAddress>& vecHostAddresses,
CVector<int>& veciJitBufSize,

View file

@ -70,20 +70,20 @@ void CClient::OnReqJittBufSize()
Channel.CreateNetwBlSiFactMes ( iNetwBufSizeFactIn );
}
bool CClient::SetServerAddr(QString strNAddr)
bool CClient::SetServerAddr ( QString strNAddr )
{
QHostAddress InetAddr;
if (InetAddr.setAddress(strNAddr))
if ( InetAddr.setAddress ( strNAddr ) )
{
/* The server port is fixed and always the same */
Channel.SetAddress(CHostAddress(InetAddr, LLCON_PORT_NUMBER));
// the server port is fixed and always the same
Channel.SetAddress ( CHostAddress ( InetAddr, LLCON_PORT_NUMBER ) );
return true;
}
else
{
return false; /* invalid address */
return false; // invalid address
}
}

View file

@ -82,10 +82,10 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent,
"red color." ) );
/* init server address line edit */
LineEditServerAddr->setText ( pClient->strIPAddress.c_str () );
LineEditServerAddr->setText ( pClient->strIPAddress.c_str() );
/* init status label */
OnTimerStatus ();
OnTimerStatus();
/* init connection button text */
PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
@ -98,26 +98,27 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent,
/* init slider controls --- */
/* audio in fader */
SliderAudInFader->setRange(0, AUD_FADER_IN_MAX);
// audio in fader
SliderAudInFader->setRange ( 0, AUD_FADER_IN_MAX );
const int iCurAudInFader = pClient->GetAudioInFader();
SliderAudInFader->setValue(iCurAudInFader);
SliderAudInFader->setTickInterval(AUD_FADER_IN_MAX / 9);
SliderAudInFader->setValue ( iCurAudInFader );
SliderAudInFader->setTickInterval ( AUD_FADER_IN_MAX / 9 );
/* audio reverberation */
SliderAudReverb->setRange(0, AUD_REVERB_MAX);
// audio reverberation
SliderAudReverb->setRange ( 0, AUD_REVERB_MAX );
const int iCurAudReverb = pClient->GetReverbLevel();
SliderAudReverb->setValue ( AUD_REVERB_MAX - iCurAudReverb );
SliderAudReverb->setTickInterval(AUD_REVERB_MAX / 9);
SliderAudReverb->setTickInterval ( AUD_REVERB_MAX / 9 );
/* set radio buttons --- */
/* reverb channel */
// reverb channel
if (pClient->IsReverbOnLeftChan())
RadioButtonRevSelL->setChecked(true);
else
RadioButtonRevSelR->setChecked(true);
/* Settings menu ------------------------------------------------------- */
pSettingsMenu = new QPopupMenu ( this );
CHECK_PTR ( pSettingsMenu );
@ -139,23 +140,23 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent,
/* connections ---------------------------------------------------------- */
/* push-buttons */
// push-buttons
QObject::connect(PushButtonConnect, SIGNAL(clicked()),
this, SLOT(OnConnectDisconBut()));
/* timers */
// timers
QObject::connect(&TimerSigMet, SIGNAL(timeout()),
this, SLOT(OnTimerSigMet()));
QObject::connect(&TimerStatus, SIGNAL(timeout()),
this, SLOT(OnTimerStatus()));
/* sliders */
// sliders
QObject::connect(SliderAudInFader, SIGNAL(valueChanged(int)),
this, SLOT(OnSliderAudInFader(int)));
QObject::connect(SliderAudReverb, SIGNAL(valueChanged(int)),
this, SLOT(OnSliderAudReverb(int)));
/* radio buttons */
// radio buttons
QObject::connect(RadioButtonRevSelL, SIGNAL(clicked()),
this, SLOT(OnRevSelL()));
QObject::connect(RadioButtonRevSelR, SIGNAL(clicked()),
@ -167,7 +168,7 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent,
/* timers --------------------------------------------------------------- */
/* start timer for status bar */
// start timer for status bar
TimerStatus.start(STATUSBAR_UPDATE_TIME);
@ -176,7 +177,7 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, QWidget* parent,
//vecpChanFader.Init(0);
//vecpChanFader.Add(new CLlconClientDlg::CChannelFader(FrameAudioFaders, FrameAudioFadersLayout, "test"));
//FrameAudioFadersLayout->addWidget(new QLabel ( "test", FrameAudioFaders ));
/*
for ( int z = 0; z < 100; z++)
{
@ -256,7 +257,7 @@ void CLlconClientDlg::OnOpenGeneralSettings()
}
void CLlconClientDlg::OnTimerSigMet ()
{
{
/* get current input levels */
double dCurSigLevelL = pClient->MicLevelL ();
double dCurSigLevelR = pClient->MicLevelR ();
@ -292,6 +293,14 @@ void CLlconClientDlg::OnConClientListMesReceived ( CVector<CChannelShortInfo> ve
{
int i;
//FrameAudioFadersLayout->addWidget(new QLabel ( "test", FrameAudioFaders ));
// TODO
// remove old controls
@ -310,7 +319,7 @@ for ( i = 0; i < vecChanInfo.Size(); i++ )
vecpChanFader[i] = new CLlconClientDlg::CChannelFader ( FrameAudioFaders,
FrameAudioFadersLayout, addrTest.toString() );
}
//FrameAudioFadersLayout->addWidget(new QLabel ( "test", FrameAudioFaders ));
}

View file

@ -30,10 +30,10 @@ CServer::CServer() : Socket ( &ChannelSet, this )
{
vecsSendData.Init ( MIN_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 );
/* connect timer timeout signal */
// connect timer timeout signal
QObject::connect ( &Timer, SIGNAL ( timeout() ),
this, SLOT ( OnTimer() ) );
@ -67,17 +67,17 @@ void CServer::Start()
{
if ( !IsRunning() )
{
/* start main timer */
// start main timer
Timer.start ( MIN_BLOCK_DURATION_MS );
/* init time for response time evaluation */
// init time for response time evaluation
TimeLastBlock = QTime::currentTime();
}
}
void CServer::Stop()
{
/* stop main timer */
// stop main timer
Timer.stop();
qDebug ( CLogTimeDate::toString() + "Server stopped" );
@ -87,23 +87,22 @@ void CServer::OnTimer()
{
CVector<int> vecChanID;
CVector<CVector<double> > vecvecdData ( MIN_BLOCK_SIZE_SAMPLES );
CVector<double> vecdGains;
CVector<CVector<double> > vecvecdGains;
/* get data from all connected clients */
ChannelSet.GetBlockAllConC ( vecChanID, vecvecdData, vecdGains );
// get data from all connected clients
ChannelSet.GetBlockAllConC ( vecChanID, vecvecdData, vecvecdGains );
const int iNumClients = vecChanID.Size();
/* Check if at least one client is connected. If not, stop server until
one client is connected */
// Check if at least one client is connected. If not, stop server until
// one client is connected
if ( iNumClients != 0 )
{
for ( int i = 0; i < iNumClients; i++ )
{
// TODO generate a sparate mix for each channel
// generate a sparate mix for each channel
// actual processing of audio data -> mix
vecsSendData = ProcessData ( vecvecdData, vecvecdGains[i] );
// actual processing of audio data -> mix
vecsSendData = ProcessData ( vecvecdData, vecdGains );
// send separate mix to current clients
Socket.SendPacket (
ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ),
@ -111,18 +110,18 @@ vecsSendData = ProcessData ( vecvecdData, vecdGains );
}
/* update response time measurement --------------------------------- */
/* add time difference */
// update response time measurement ------------------------------------
// add time difference
const QTime CurTime = QTime::currentTime ();
/* we want to calculate the standard deviation (we assume that the mean
is correct at the block period time) */
// we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time)
const double dCurAddVal = ( (double) TimeLastBlock.msecsTo ( CurTime ) -
MIN_BLOCK_DURATION_MS );
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); /* add squared value */
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value
/* store old time value */
// store old time value
TimeLastBlock = CurTime;
}
else
@ -147,7 +146,7 @@ CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
// 3 dB offset to avoid overload if all clients are set to gain 1
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++ )
{
double dMixedData = 0.0;
@ -157,7 +156,7 @@ CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
dMixedData += vecvecdData[j][i] * vecdGains[j];
}
/* normalization and truncating to short */
// normalization and truncating to short
vecsOutData[i] = Double2Short ( dMixedData / dNorm );
}
@ -166,7 +165,7 @@ CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
bool CServer::GetTimingStdDev ( double& dCurTiStdDev )
{
dCurTiStdDev = 0.0; /* init return value */
dCurTiStdDev = 0.0; // init return value
/* only return value if server is active and the actual measurement is
updated */