some cleanup and preperations for callback based audio interface

This commit is contained in:
Volker Fischer 2009-02-21 17:37:15 +00:00
parent 5917ead5e6
commit 71598931e2
3 changed files with 199 additions and 183 deletions

View file

@ -170,6 +170,101 @@ void CClient::OnProtocolStatus ( bool bOk )
}
}
void CClient::Start()
{
// init object
try
{
Init();
}
catch ( CGenErr generr )
{
// TODO better error management -> should be catched in main thread
// problem: how to catch errors in a different thread...?
// quick hack solution
QMessageBox::critical ( 0, APP_NAME, generr.GetErrorText(), "Quit", 0 );
exit ( 0 );
}
// enable channel
Channel.SetEnable ( true );
// start the audio working thread with hightest possible priority
start ( QThread::TimeCriticalPriority );
}
void CClient::Stop()
{
// set flag so that thread can leave the main loop
bRun = false;
// give thread some time to terminate
wait ( 5000 );
// disable channel
Channel.SetEnable ( false );
// disable sound interface
Sound.Close();
// reset current signal level and LEDs
SignalLevelMeter.Reset();
PostWinMessage ( MS_RESET_ALL, 0 );
}
void CClient::run()
{
// Set thread priority (The working thread should have a higher
// priority than the GUI)
#ifdef _WIN32
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#else
/*
// 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
struct sched_param schp;
memset ( &schp, 0, sizeof ( schp ) );
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
sched_setscheduler ( 0, SCHED_FIFO, &schp );
*/
#endif
// main loop of working thread
bRun = true;
while ( bRun )
{
// get audio from sound card (blocking function)
if ( Sound.Read ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
}
// process audio data
ProcessAudioData ( vecsAudioSndCrdStereo );
// play the new block
if ( Sound.Write ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
}
}
}
void CClient::Init()
{
// set block size (in samples)
@ -205,65 +300,14 @@ void CClient::Init()
AudioReverb.Clear();
}
void CClient::run()
void CClient::ProcessAudioData ( CVector<short>& vecsStereoSndCrd )
{
int i, j;
// Set thread priority (The working thread should have a higher
// priority than the GUI)
#ifdef _WIN32
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#else
/*
// 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
struct sched_param schp;
memset ( &schp, 0, sizeof ( schp ) );
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
sched_setscheduler ( 0, SCHED_FIFO, &schp );
*/
#endif
// init object
try
{
Init();
}
catch ( CGenErr generr )
{
// TODO better error management -> should be catched in main thread
// problem: how to catch errors in a different thread...?
// quick hack solution
QMessageBox::critical ( 0, APP_NAME, generr.GetErrorText(), "Quit", 0 );
exit ( 0 );
}
// runtime phase -----------------------------------------------------------
// enable channel
Channel.SetEnable ( true );
bRun = true;
// main loop of working thread
while ( bRun )
{
// get audio from sound card (blocking function)
if ( Sound.Read ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
}
// convert data from short to double
for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ )
{
vecdAudioSndCrdStereo[i] = (double) vecsAudioSndCrdStereo[i];
vecdAudioSndCrdStereo[i] = (double) vecsStereoSndCrd[i];
}
// resample data for each channel seaparately
@ -372,24 +416,14 @@ fflush(pFileDelay);
// received data in both sound card channels
for ( i = 0, j = 0; i < iSndCrdMonoBlockSizeSam; i++, j += 2 )
{
vecsAudioSndCrdStereo[j] = vecsAudioSndCrdStereo[j + 1] =
vecsStereoSndCrd[j] = vecsStereoSndCrd[j + 1] =
Double2Short ( vecdAudioSndCrdMono[i] );
}
}
else
{
// if not connected, clear data
vecsAudioSndCrdStereo.Reset ( 0 );
}
// play the new block
if ( Sound.Write ( vecsAudioSndCrdStereo ) )
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
}
else
{
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
vecsStereoSndCrd.Reset ( 0 );
}
// update response time measurement and socket buffer size
@ -397,26 +431,6 @@ fflush(pFileDelay);
UpdateSocketBufferSize();
}
// disable channel
Channel.SetEnable ( false );
// disable sound interface
Sound.Close();
// reset current signal level and LEDs
SignalLevelMeter.Reset();
PostWinMessage ( MS_RESET_ALL, 0 );
}
bool CClient::Stop()
{
// set flag so that thread can leave the main loop
bRun = false;
// give thread some time to terminate, return status
return wait ( 5000 );
}
void CClient::UpdateTimeResponseMeasurement()
{
// add time difference

View file

@ -66,8 +66,8 @@ public:
CClient ( const quint16 iPortNumber );
virtual ~CClient() {}
void Init();
bool Stop();
void Start();
void Stop();
bool IsRunning() { return bRun; }
bool SetServerAddr ( QString strNAddr );
double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); }
@ -149,7 +149,9 @@ public:
QString strName;
protected:
void Init();
virtual void run();
void ProcessAudioData ( CVector<short>& vecsStereoSndCrd );
void UpdateTimeResponseMeasurement();
void UpdateSocketBufferSize();

View file

@ -267,28 +267,12 @@ void CLlconClientDlg::OnSliderAudInFader ( int value )
void CLlconClientDlg::OnConnectDisconBut()
{
// start/stop client, set button text
if ( pClient->IsRunning() )
{
pClient->Stop();
PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
// stop timer for level meter bars and reset them
TimerSigMet.stop();
ProgressBarInputLevelL->setValue ( 0 );
ProgressBarInputLevelR->setValue ( 0 );
// immediately update status bar
OnTimerStatus();
// clear mixer board (remove all faders)
MainMixerBoard->HideAll();
}
else
if ( !pClient->IsRunning() )
{
// set address and check if address is valid
if ( pClient->SetServerAddr ( LineEditServerAddr->text() ) )
{
pClient->start ( QThread::TimeCriticalPriority );
pClient->Start();
PushButtonConnect->setText ( CON_BUT_DISCONNECTTEXT );
@ -305,6 +289,22 @@ void CLlconClientDlg::OnConnectDisconBut()
TextLabelStatus->setText ( tr ( "invalid address" ) );
}
}
else
{
pClient->Stop();
PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
// stop timer for level meter bars and reset them
TimerSigMet.stop();
ProgressBarInputLevelL->setValue ( 0 );
ProgressBarInputLevelR->setValue ( 0 );
// immediately update status bar
OnTimerStatus();
// clear mixer board (remove all faders)
MainMixerBoard->HideAll();
}
}
void CLlconClientDlg::OnOpenGeneralSettings()