2006-01-28 12:29:22 +01:00
|
|
|
/******************************************************************************\
|
|
|
|
* Copyright (c) 2004-2006
|
|
|
|
*
|
|
|
|
* Author(s):
|
2006-11-25 15:46:57 +01:00
|
|
|
* Volker Fischer
|
2006-01-28 12:29:22 +01:00
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
\******************************************************************************/
|
|
|
|
|
|
|
|
#include "client.h"
|
|
|
|
|
|
|
|
|
2006-02-26 11:50:47 +01:00
|
|
|
/* Implementation *************************************************************/
|
2006-12-07 19:57:26 +01:00
|
|
|
CClient::CClient() : bRun ( false ), Socket ( &Channel ),
|
2006-11-25 15:46:57 +01:00
|
|
|
iAudioInFader ( AUD_FADER_IN_MAX / 2 ),
|
|
|
|
iReverbLevel ( AUD_REVERB_MAX / 6 ),
|
|
|
|
bReverbOnLeftChan ( false ),
|
|
|
|
iNetwBufSizeFactIn ( DEF_NET_BLOCK_SIZE_FACTOR )
|
2006-02-26 11:50:47 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
// connection for protocol
|
2006-12-07 19:57:26 +01:00
|
|
|
QObject::connect ( &Channel,
|
|
|
|
SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ),
|
2006-11-25 15:46:57 +01:00
|
|
|
this, SLOT ( OnSendProtMessage ( CVector<uint8_t> ) ) );
|
2006-03-07 22:26:40 +01:00
|
|
|
|
2006-11-25 15:46:57 +01:00
|
|
|
QObject::connect ( &Channel, SIGNAL ( ReqJittBufSize() ),
|
|
|
|
this, SLOT ( OnReqJittBufSize() ) );
|
2006-11-05 11:09:32 +01:00
|
|
|
|
2006-11-25 15:46:57 +01:00
|
|
|
QObject::connect ( &Channel, SIGNAL ( ProtocolStatus ( bool ) ),
|
|
|
|
this, SLOT ( OnProtocolStatus ( bool ) ) );
|
2006-11-26 22:25:56 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
QObject::connect ( &Channel,
|
|
|
|
SIGNAL ( ConClientListMesReceived ( CVector<CChannelShortInfo> ) ),
|
2006-11-26 22:25:56 +01:00
|
|
|
SIGNAL ( ConClientListMesReceived ( CVector<CChannelShortInfo> ) ) );
|
2006-02-26 11:50:47 +01:00
|
|
|
}
|
|
|
|
|
2006-03-01 20:46:44 +01:00
|
|
|
void CClient::OnSendProtMessage ( CVector<uint8_t> vecMessage )
|
2006-02-26 11:50:47 +01:00
|
|
|
{
|
2006-03-01 20:46:44 +01:00
|
|
|
|
|
|
|
// convert unsigned uint8_t in char, TODO convert all buffers in uint8_t
|
2006-12-07 19:57:26 +01:00
|
|
|
CVector<unsigned char> vecbyDataConv ( vecMessage.Size() );
|
|
|
|
for ( int i = 0; i < vecMessage.Size(); i++ ) {
|
2006-11-25 15:46:57 +01:00
|
|
|
vecbyDataConv[i] = static_cast<unsigned char> ( vecMessage[i] );
|
2006-03-01 20:46:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-25 15:46:57 +01:00
|
|
|
// the protocol queries me to call the function to send the message
|
|
|
|
// send it through the network
|
2006-12-07 19:57:26 +01:00
|
|
|
Socket.SendPacket ( vecbyDataConv, Channel.GetAddress() );
|
2006-02-26 11:50:47 +01:00
|
|
|
}
|
2006-03-12 13:24:42 +01:00
|
|
|
|
|
|
|
void CClient::OnReqJittBufSize()
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
Channel.CreateJitBufMes ( Channel.GetSockBufSize() );
|
2006-03-13 21:23:05 +01:00
|
|
|
|
|
|
|
// FIXME: we set the network buffer size factor here, too -> in the
|
|
|
|
// future a separate request function for this parameter should be created
|
2006-11-25 15:46:57 +01:00
|
|
|
Channel.CreateNetwBlSiFactMes ( iNetwBufSizeFactIn );
|
2006-03-12 13:24:42 +01:00
|
|
|
}
|
2006-02-26 11:50:47 +01:00
|
|
|
|
2006-12-06 21:22:41 +01:00
|
|
|
bool CClient::SetServerAddr ( QString strNAddr )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
QHostAddress InetAddr;
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-06 21:22:41 +01:00
|
|
|
if ( InetAddr.setAddress ( strNAddr ) )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-06 21:22:41 +01:00
|
|
|
// the server port is fixed and always the same
|
|
|
|
Channel.SetAddress ( CHostAddress ( InetAddr, LLCON_PORT_NUMBER ) );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-11-25 15:46:57 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-06 21:22:41 +01:00
|
|
|
return false; // invalid address
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-11-05 11:09:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CClient::OnProtocolStatus ( bool bOk )
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
// show protocol status in GUI
|
|
|
|
if ( bOk )
|
|
|
|
{
|
|
|
|
PostWinMessage ( MS_PROTOCOL, MUL_COL_LED_RED );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PostWinMessage ( MS_PROTOCOL, MUL_COL_LED_GREEN );
|
|
|
|
}
|
2006-11-05 11:09:32 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
void CClient::Init()
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// set block sizes (in samples)
|
2006-11-25 15:46:57 +01:00
|
|
|
iBlockSizeSam = MIN_BLOCK_SIZE_SAMPLES;
|
|
|
|
iSndCrdBlockSizeSam = MIN_SND_CRD_BLOCK_SIZE_SAMPLES;
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
vecsAudioSndCrd.Init ( iSndCrdBlockSizeSam * 2 ); // stereo
|
|
|
|
vecdAudioSndCrdL.Init ( iSndCrdBlockSizeSam );
|
|
|
|
vecdAudioSndCrdR.Init ( iSndCrdBlockSizeSam );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
vecdAudioL.Init ( iBlockSizeSam );
|
|
|
|
vecdAudioR.Init ( iBlockSizeSam );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
Sound.InitRecording ( iSndCrdBlockSizeSam * 2 ); // stereo
|
|
|
|
Sound.InitPlayback ( iSndCrdBlockSizeSam * 2 ); // stereo
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// resample objects are always initialized with the input block size
|
|
|
|
// record
|
|
|
|
ResampleObjDownL.Init ( iSndCrdBlockSizeSam, SND_CRD_SAMPLE_RATE, SAMPLE_RATE );
|
|
|
|
ResampleObjDownR.Init ( iSndCrdBlockSizeSam, SND_CRD_SAMPLE_RATE, SAMPLE_RATE );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// playback
|
|
|
|
ResampleObjUpL.Init ( iBlockSizeSam, SAMPLE_RATE, SND_CRD_SAMPLE_RATE );
|
|
|
|
ResampleObjUpR.Init ( iBlockSizeSam, SAMPLE_RATE, SND_CRD_SAMPLE_RATE );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// init network buffers
|
|
|
|
vecsNetwork.Init ( iBlockSizeSam );
|
|
|
|
vecdNetwData.Init ( iBlockSizeSam );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// init moving average buffer for response time evaluation
|
|
|
|
RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// init time for response time evaluation
|
2006-11-25 15:46:57 +01:00
|
|
|
TimeLastBlock = QTime::currentTime();
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-11-25 15:46:57 +01:00
|
|
|
AudioReverb.Clear();
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CClient::run()
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
int i, iInCnt;
|
2006-02-26 11:50:47 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// Set thread priority (The working thread should have a higher
|
|
|
|
// priority than the GUI)
|
2006-01-28 12:29:22 +01:00
|
|
|
#ifdef _WIN32
|
2006-12-07 19:57:26 +01:00
|
|
|
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL );
|
2006-01-28 12:29:22 +01:00
|
|
|
#else
|
2006-12-07 19:57:26 +01:00
|
|
|
// set the process to realtime privs, taken from
|
|
|
|
// "http://www.gardena.net/benno/linux/audio" but does not seem to work,
|
|
|
|
// maybe a problem with user rights
|
2006-11-25 15:46:57 +01:00
|
|
|
struct sched_param schp;
|
|
|
|
memset ( &schp, 0, sizeof ( schp ) );
|
|
|
|
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
|
|
|
|
sched_setscheduler ( 0, SCHED_FIFO, &schp );
|
2006-01-28 12:29:22 +01:00
|
|
|
#endif
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// init object
|
2006-11-25 15:46:57 +01:00
|
|
|
Init();
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// runtime phase ------------------------------------------------------------
|
2006-11-25 15:46:57 +01:00
|
|
|
bRun = true;
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// main loop of working thread
|
|
|
|
while ( bRun )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// get audio from sound card (blocking function)
|
|
|
|
if ( Sound.Read ( vecsAudioSndCrd ) )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// copy data from one stereo buffer in two separate buffers
|
2006-11-25 15:46:57 +01:00
|
|
|
iInCnt = 0;
|
2006-12-07 19:57:26 +01:00
|
|
|
for ( i = 0; i < iSndCrdBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
vecdAudioSndCrdL[i] = (double) vecsAudioSndCrd[iInCnt++];
|
|
|
|
vecdAudioSndCrdR[i] = (double) vecsAudioSndCrd[iInCnt++];
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// resample data for each channel seaparately
|
|
|
|
ResampleObjDownL.Resample ( vecdAudioSndCrdL, vecdAudioL );
|
|
|
|
ResampleObjDownR.Resample ( vecdAudioSndCrdR, vecdAudioR );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// update signal level meters
|
|
|
|
SignalLevelMeterL.Update ( vecdAudioL );
|
|
|
|
SignalLevelMeterR.Update ( vecdAudioR );
|
2006-11-25 15:46:57 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// add reverberation effect if activated
|
|
|
|
if ( iReverbLevel != 0 )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// first attenuation amplification factor
|
2006-11-25 15:46:57 +01:00
|
|
|
const double dRevLev = (double) iReverbLevel / AUD_REVERB_MAX / 2;
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
if ( bReverbOnLeftChan )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
for (i = 0; i < iBlockSizeSam; i++)
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// left channel
|
2006-11-25 15:46:57 +01:00
|
|
|
vecdAudioL[i] +=
|
2006-12-07 19:57:26 +01:00
|
|
|
dRevLev * AudioReverb.ProcessSample ( vecdAudioL[i] );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
for ( i = 0; i < iBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// right channel
|
2006-11-25 15:46:57 +01:00
|
|
|
vecdAudioR[i] +=
|
2006-12-07 19:57:26 +01:00
|
|
|
dRevLev * AudioReverb.ProcessSample ( vecdAudioR[i] );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// mix both signals depending on the fading setting
|
2006-11-25 15:46:57 +01:00
|
|
|
const int iMiddleOfFader = AUD_FADER_IN_MAX / 2;
|
|
|
|
const double dAttFact =
|
2006-12-07 19:57:26 +01:00
|
|
|
(double) ( iMiddleOfFader - abs ( iMiddleOfFader - iAudioInFader ) ) /
|
2006-11-25 15:46:57 +01:00
|
|
|
iMiddleOfFader;
|
2006-12-07 19:57:26 +01:00
|
|
|
|
|
|
|
for ( i = 0; i < iBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
double dMixedSignal;
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
if ( iAudioInFader > iMiddleOfFader )
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
dMixedSignal = vecdAudioL[i] + dAttFact * vecdAudioR[i];
|
2006-12-07 19:57:26 +01:00
|
|
|
}
|
2006-11-25 15:46:57 +01:00
|
|
|
else
|
2006-12-07 19:57:26 +01:00
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
dMixedSignal = vecdAudioR[i] + dAttFact * vecdAudioL[i];
|
2006-12-07 19:57:26 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
vecsNetwork[i] = Double2Short ( dMixedSignal );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// send it through the network
|
2006-11-25 15:46:57 +01:00
|
|
|
Socket.SendPacket ( Channel.PrepSendPacket ( vecsNetwork ),
|
|
|
|
Channel.GetAddress () );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// receive a new block
|
|
|
|
if ( Channel.GetData ( vecdNetwData ) )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_GREEN );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
#ifdef _DEBUG_
|
|
|
|
#if 0
|
|
|
|
#if 0
|
|
|
|
/* Determine network delay. We can do this very simple if only this client is
|
|
|
|
connected to the server. In this case, exactly the same audio material is
|
|
|
|
coming back and we can simply compare the samples */
|
|
|
|
/* store send data instatic buffer (may delay is 100 ms) */
|
|
|
|
const int iMaxDelaySamples = (int) ((float) 0.3 /*0.1*/ * SAMPLE_RATE);
|
|
|
|
static CVector<short> vecsOutBuf(iMaxDelaySamples);
|
|
|
|
|
|
|
|
/* update buffer */
|
|
|
|
const int iBufDiff = iMaxDelaySamples - iBlockSizeSam;
|
|
|
|
for (i = 0; i < iBufDiff; i++)
|
2006-11-25 15:46:57 +01:00
|
|
|
vecsOutBuf[i + iBlockSizeSam] = vecsOutBuf[i];
|
2006-01-28 12:29:22 +01:00
|
|
|
for (i = 0; i < iBlockSizeSam; i++)
|
2006-11-25 15:46:57 +01:00
|
|
|
vecsOutBuf[i] = vecsNetwork[i];
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* now search for equal samples */
|
|
|
|
int iDelaySamples = 0;
|
|
|
|
for (i = 0; i < iMaxDelaySamples - 1; i++)
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
/* compare two successive samples */
|
|
|
|
if ((vecsOutBuf[i] == (short) vecdNetwData[0]) &&
|
|
|
|
(vecsOutBuf[i + 1] == (short) vecdNetwData[1]))
|
|
|
|
{
|
|
|
|
iDelaySamples = i;
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static FILE* pFileDelay = fopen("delay.dat", "w");
|
|
|
|
fprintf(pFileDelay, "%d\n", iDelaySamples);
|
|
|
|
fflush(pFileDelay);
|
|
|
|
#else
|
|
|
|
/* just store both, input and output, streams */
|
|
|
|
// fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid);
|
|
|
|
static FILE* pFileDelay = fopen("v.dat", "wb");
|
|
|
|
short sData[2];
|
|
|
|
for (i = 0; i < iBlockSizeSam; i++)
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
sData[0] = vecsNetwork[i];
|
|
|
|
sData[1] = (short) vecdNetwData[i];
|
|
|
|
fwrite(&sData, size_t(2), size_t(2), pFileDelay);
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
fflush(pFileDelay);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
// fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid);
|
|
|
|
static FILE* pFileDelay = fopen("v.dat", "wb");
|
|
|
|
short sData[2];
|
|
|
|
for (i = 0; i < iBlockSizeSam; i++)
|
|
|
|
{
|
2006-11-25 15:46:57 +01:00
|
|
|
sData[0] = (short) vecdNetwData[i];
|
|
|
|
fwrite(&sData, size_t(2), size_t(1), pFileDelay);
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
fflush(pFileDelay);
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// check if channel is connected
|
|
|
|
if ( Channel.IsConnected() )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// write mono input signal in both sound-card channels
|
|
|
|
for ( i = 0; i < iBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
vecdAudioL[i] = vecdAudioR[i] = vecdNetwData[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// if not connected, clear data
|
|
|
|
for ( i = 0; i < iBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
|
|
|
vecdAudioL[i] = vecdAudioR[i] = 0.0;
|
|
|
|
}
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// resample data for each channel separately
|
|
|
|
ResampleObjUpL.Resample ( vecdAudioL, vecdAudioSndCrdL );
|
|
|
|
ResampleObjUpR.Resample ( vecdAudioR, vecdAudioSndCrdR );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// copy data from one stereo buffer in two separate buffers
|
2006-11-25 15:46:57 +01:00
|
|
|
iInCnt = 0;
|
2006-12-07 19:57:26 +01:00
|
|
|
for ( i = 0; i < iSndCrdBlockSizeSam; i++ )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
vecsAudioSndCrd[iInCnt++] = Double2Short ( vecdAudioSndCrdL[i] );
|
|
|
|
vecsAudioSndCrd[iInCnt++] = Double2Short ( vecdAudioSndCrdR[i] );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// play the new block
|
|
|
|
if ( Sound.Write ( vecsAudioSndCrd ) )
|
2006-11-25 15:46:57 +01:00
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
|
2006-11-25 15:46:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// update response time measurement ------------------------------------
|
|
|
|
// add time difference
|
2006-11-25 15:46:57 +01:00
|
|
|
const QTime CurTime = QTime::currentTime();
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// we want to calculate the standard deviation (we assume that the mean
|
|
|
|
// is correct at the block period time)
|
2006-11-25 15:46:57 +01:00
|
|
|
const double dCurAddVal =
|
|
|
|
( (double) TimeLastBlock.msecsTo ( CurTime ) - MIN_BLOCK_DURATION_MS );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
// TEST
|
|
|
|
static FILE* pFileTest = fopen("sti.dat", "w");
|
|
|
|
fprintf(pFileTest, "%e\n", dCurAddVal);
|
|
|
|
fflush(pFileTest);
|
|
|
|
*/
|
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// store old time value
|
2006-11-25 15:46:57 +01:00
|
|
|
TimeLastBlock = CurTime;
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// reset current signal level and LEDs
|
2006-11-25 15:46:57 +01:00
|
|
|
SignalLevelMeterL.Reset();
|
|
|
|
SignalLevelMeterR.Reset();
|
2006-12-07 19:57:26 +01:00
|
|
|
PostWinMessage ( MS_RESET_ALL, 0 );
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CClient::Stop()
|
|
|
|
{
|
2006-12-07 19:57:26 +01:00
|
|
|
// set flag so that thread can leave the main loop
|
2006-11-25 15:46:57 +01:00
|
|
|
bRun = false;
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-12-07 19:57:26 +01:00
|
|
|
// give thread some time to terminate, return status
|
|
|
|
return wait ( 5000 );
|
2006-02-26 11:50:47 +01:00
|
|
|
}
|