some cleanup

This commit is contained in:
Volker Fischer 2006-10-03 21:16:23 +00:00
parent c5cf24f58e
commit 50eba66c0c
4 changed files with 204 additions and 148 deletions

View file

@ -21,8 +21,10 @@ void CSound::InitRecording(int iNewBufferSize, bool bNewBlocking)
iBufferSizeIn = iNewBufferSize / NUM_IN_OUT_CHANNELS; /* mono size */
/* if recording device was already open, close it first */
if (rhandle != NULL)
snd_pcm_close(rhandle);
if ( rhandle != NULL )
{
snd_pcm_close ( rhandle );
}
/* record device: The most important ALSA interfaces to the PCM devices are
the "plughw" and the "hw" interface. If you use the "plughw" interface,
@ -32,87 +34,82 @@ void CSound::InitRecording(int iNewBufferSize, bool bNewBlocking)
number of channels. With the "hw" interface, you have to check whether
your hardware supports the configuration you would like to use */
/* either "hw:0,0" or "plughw:0,0" */
if (err = snd_pcm_open(&rhandle, "hw:0,0", SND_PCM_STREAM_CAPTURE, 0) != 0)
if ( err = snd_pcm_open ( &rhandle, "hw:0,0", SND_PCM_STREAM_CAPTURE, 0 ) != 0 )
{
qDebug("open error: %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW record");
qDebug ( "open error: %s", snd_strerror ( err ) );
}
/* recording should be blocking */
if (err = snd_pcm_nonblock(rhandle, FALSE) != 0)
if ( err = snd_pcm_nonblock ( rhandle, FALSE ) != 0 )
{
qDebug("cannot set blocking: %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW record");
qDebug ( "cannot set blocking: %s", snd_strerror ( err ) );
}
/* set hardware parameters */
SetHWParams(rhandle, true, iBufferSizeIn, iCurPeriodSizeIn);
SetHWParams ( rhandle, iBufferSizeIn, iCurPeriodSizeIn );
/* sw parameters --------------------------------------------------------- */
snd_pcm_sw_params_t* swparams;
if (err = snd_pcm_sw_params_malloc (&swparams) != 0)
// allocate an invalid snd_pcm_sw_params_t using standard malloc
if ( err = snd_pcm_sw_params_malloc ( &swparams ) != 0 )
{
qDebug("snd_pcm_sw_params_malloc: %s", snd_strerror (err));
// return NULL ;
qDebug ( "snd_pcm_sw_params_malloc: %s", snd_strerror ( err ) );
}
/* Get the current swparams */
if (err = snd_pcm_sw_params_current(rhandle, swparams) < 0)
// get the current swparams
if ( err = snd_pcm_sw_params_current ( rhandle, swparams ) < 0 )
{
qDebug("Unable to determine current swparams : %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
qDebug ( "Unable to determine current swparams : %s", snd_strerror ( err ) );
}
/* Start the transfer when the buffer immediately */
err = snd_pcm_sw_params_set_start_threshold(rhandle, swparams, 0);
if (err < 0) {
qDebug("Unable to set start threshold mode : %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
// start the transfer when the buffer immediately -> no threshold, val: 0
err = snd_pcm_sw_params_set_start_threshold ( rhandle, swparams, 0 );
if ( err < 0 )
{
qDebug ( "Unable to set start threshold mode : %s", snd_strerror ( err ) );
}
/* Align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(rhandle, swparams, 1);
if (err < 0) {
qDebug("Unable to set transfer align : %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
// align all transfers to 1 sample
err = snd_pcm_sw_params_set_xfer_align ( rhandle, swparams, 1 );
if ( err < 0 )
{
qDebug ( "Unable to set transfer align : %s", snd_strerror ( err ) );
}
// set avail min inside a software configuration container
/* Note: This is similar to setting an OSS wakeup point. The valid values
for 'val' are determined by the specific hardware. Most PC sound cards
can only accept power of 2 frame counts (i.e. 512, 1024, 2048). You
cannot use this as a high resolution timer - it is limited to how often
the sound card hardware raises an interrupt. Note that you can greatly
improve the reponses using snd_pcm_sw_params_set_sleep_min where another
timing source is used */
snd_pcm_uframes_t period_size = iBufferSizeIn;
// TEST
/* Allow the transfer when at least period_size samples can be processed */
// /* round up to closest transfer boundary */
// start_threshold = (buffer_size / xfer_align) * xfer_align ;
// if (start_threshold < 1)
// start_threshold = 1 ;
// TEST
snd_pcm_uframes_t period_size = iBufferSizeIn;
err = snd_pcm_sw_params_set_avail_min(rhandle, swparams, period_size);
if (err < 0) {
qDebug("Unable to set avail min : %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
err = snd_pcm_sw_params_set_avail_min ( rhandle, swparams, period_size );
if ( err < 0 )
{
qDebug ( "Unable to set avail min : %s", snd_strerror ( err ) );
}
/* Write the parameters to the record/playback device */
err = snd_pcm_sw_params(rhandle, swparams);
if (err < 0) {
qDebug("Unable to set sw params : %s", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
// write the parameters to the record/playback device
err = snd_pcm_sw_params ( rhandle, swparams );
if ( err < 0 )
{
qDebug ( "Unable to set sw params : %s", snd_strerror ( err ) );
}
/* clean-up */
snd_pcm_sw_params_free(swparams);
// clean-up
snd_pcm_sw_params_free ( swparams );
snd_pcm_reset(rhandle);
snd_pcm_start(rhandle);
qDebug("alsa init record done");
// start record
snd_pcm_reset ( rhandle );
snd_pcm_start ( rhandle );
qDebug ( "alsa init record done" );
}
bool CSound::Read(CVector<short>& psData)
@ -210,34 +207,88 @@ void CSound::InitPlayback ( int iNewBufferSize, bool bNewBlocking )
{
int err;
/* Save buffer size */
iBufferSizeOut = iNewBufferSize / NUM_IN_OUT_CHANNELS; /* mono size */
// save buffer size
iBufferSizeOut = iNewBufferSize / NUM_IN_OUT_CHANNELS; // mono size
/* if playback device was already open, close it first */
// if playback device was already open, close it first
if ( phandle != NULL )
{
snd_pcm_close ( phandle );
}
/* playback device */
/* either "hw:0,0" or "plughw:0,0" */
if ( err = snd_pcm_open ( &phandle, "hw:0,0", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) != 0)
// playback device (either "hw:0,0" or "plughw:0,0")
if ( err = snd_pcm_open ( &phandle, "hw:0,0",
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) != 0)
{
qDebug ( "open error: %s", snd_strerror ( err ) );
// throw CGenErr("alsa CSound::Init_HW playback");
}
/* non-blocking playback */
// non-blocking playback
if ( err = snd_pcm_nonblock ( phandle, TRUE ) != 0 )
{
qDebug ( "cannot set blocking: %s", snd_strerror ( err ) );
// throw CGenErr("alsa CSound::Init_HW record");
}
/* set hardware parameters */
SetHWParams ( phandle, false, iBufferSizeOut, iCurPeriodSizeOut );
// set hardware parameters
SetHWParams ( phandle, iBufferSizeOut, iCurPeriodSizeOut );
#if 0
/* sw parameters --------------------------------------------------------- */
snd_pcm_sw_params_t* swparams;
// TEST
// allocate an invalid snd_pcm_sw_params_t using standard malloc
if ( err = snd_pcm_sw_params_malloc ( &swparams ) != 0 )
{
qDebug ( "snd_pcm_sw_params_malloc: %s", snd_strerror ( err ) );
}
/* get the current swparams */
err = snd_pcm_sw_params_current(phandle, swparams);
if (err < 0)
{
qDebug("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
}
/* start the transfer when the buffer is almost full: */
/* (buffer_size / avail_min) * avail_min */
err = snd_pcm_sw_params_set_start_threshold(phandle, swparams, iCurPeriodSizeOut - 1);
if (err < 0) {
qDebug("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
}
/* allow the transfer when at least period_size samples can be processed */
err = snd_pcm_sw_params_set_avail_min(phandle, swparams, iBufferSizeOut);
if (err < 0) {
qDebug("Unable to set avail min for playback: %s\n", snd_strerror(err));
}
/* align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(phandle, swparams, 1);
if (err < 0) {
qDebug("Unable to set transfer align for playback: %s\n", snd_strerror(err));
}
/* write the parameters to the playback device */
err = snd_pcm_sw_params(phandle, swparams);
if (err < 0) {
qDebug("Unable to set sw params for playback: %s\n", snd_strerror(err));
}
// clean-up
snd_pcm_sw_params_free ( swparams );
#endif
// start playback
snd_pcm_start ( phandle );
qDebug ( "alsa init playback done" );
}
@ -263,17 +314,7 @@ bool CSound::Write ( CVector<short>& psData )
if ( ret < 0 )
{
if ( ret == -EAGAIN )
{
if ( ( ret = snd_pcm_wait ( phandle, 1 ) ) < 0 )
{
qDebug ( "poll failed (%s)", snd_strerror ( ret ) );
break;
}
continue;
}
else if ( ret == -EPIPE )
if ( ret == -EPIPE )
{
/* under-run */
qDebug ( "wunderrun" );
@ -284,6 +325,16 @@ bool CSound::Write ( CVector<short>& psData )
{
qDebug ( "Can't recover from underrun, prepare failed: %s", snd_strerror ( ret ) );
}
continue;
}
else if ( ret == -EAGAIN )
{
if ( ( ret = snd_pcm_wait ( phandle, 1 ) ) < 0 )
{
qDebug ( "poll failed (%s)", snd_strerror ( ret ) );
break;
}
continue;
}
else if ( ret == -ESTRPIPE )
@ -310,9 +361,8 @@ bool CSound::Write ( CVector<short>& psData )
else
{
qDebug ( "Write error: %s", snd_strerror ( ret ) );
// throw CGenErr ( "Write error" );
}
break; /* skip one period */
break; // skip one period
}
size -= ret;
@ -340,60 +390,59 @@ void CSound::SetOutNumBuf(int iNewNum)
/* common **********************************************************************/
bool CSound::SetHWParams(snd_pcm_t* handle, const bool bIsRecord,
const int iBufferSizeIn, const int iNumPeriodBlocks)
bool CSound::SetHWParams(snd_pcm_t* handle, const int iBufferSizeIn,
const int iNumPeriodBlocks)
{
int err;
snd_pcm_hw_params_t* hwparams;
if (err = snd_pcm_hw_params_malloc(&hwparams) < 0)
// allocate an invalid snd_pcm_hw_params_t using standard malloc
if ( err = snd_pcm_hw_params_malloc ( &hwparams ) < 0 )
{
qDebug("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
qDebug ( "cannot allocate hardware parameter structure (%s)\n", snd_strerror ( err ) );
return true;
}
if (err = snd_pcm_hw_params_any(handle, hwparams) < 0)
// fill params with a full configuration space for a PCM
if ( err = snd_pcm_hw_params_any ( handle, hwparams ) < 0 )
{
qDebug("cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
qDebug ( "cannot initialize hardware parameter structure (%s)\n", snd_strerror ( err ) );
return true;
}
/* get configuration */
if (err = snd_pcm_hw_params_any(handle, hwparams) < 0)
// restrict a configuration space to contain only one access type:
// set the interleaved read/write format
if ( err = snd_pcm_hw_params_set_access ( handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED ) < 0 )
{
qDebug("Broken configuration : no configurations available: %s", snd_strerror(err));
qDebug ( "Access type not available : %s", snd_strerror ( err ) );
return true;
}
/* Set the interleaved read/write format */
if (err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
// restrict a configuration space to contain only one format:
// set the sample format PCM, 16 bit
if ( err = snd_pcm_hw_params_set_format ( handle, hwparams, SND_PCM_FORMAT_S16 ) < 0 )
{
qDebug("Access type not available : %s", snd_strerror(err));
qDebug ( "Sample format not available : %s", snd_strerror ( err ) );
return true;
}
/* Set the sample format */
if (err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16) < 0)
// restrict a configuration space to contain only one channels count:
// set the count of channels (usually stereo, 2 channels)
if ( err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_IN_OUT_CHANNELS ) < 0 )
{
qDebug("Sample format not available : %s", snd_strerror(err));
qDebug ( "Channels count (%i) not available s: %s", NUM_IN_OUT_CHANNELS, snd_strerror ( err ) );
return true;
}
/* Set the count of channels */
if (err = snd_pcm_hw_params_set_channels(handle, hwparams, NUM_IN_OUT_CHANNELS) < 0)
{
qDebug("Channels count (%i) not available s: %s", NUM_IN_OUT_CHANNELS, snd_strerror(err));
return true;
}
/* Set the sample-rate */
// restrict a configuration space to have rate nearest to a target:
// set the sample-rate
unsigned int rrate = SND_CRD_SAMPLE_RATE;
if ( err = snd_pcm_hw_params_set_rate_near ( handle, hwparams, &rrate, 0 ) < 0 )
{
qDebug("Rate %iHz not available : %s", rrate, snd_strerror(err));
qDebug ( "Rate %iHz not available : %s", rrate, snd_strerror ( err ) );
return true;
}
if ( rrate != SND_CRD_SAMPLE_RATE )
if ( rrate != SND_CRD_SAMPLE_RATE ) // check if rate is possible
{
qDebug ( "Rate doesn't match (requested %iHz, get %iHz)", rrate, err );
return true;
@ -433,46 +482,46 @@ snd_pcm_uframes_t PeriodSize = iBufferSizeIn;
return true;
}
/* check period and buffer size */
qDebug("desired block size: %d / desired buffer size: %d", iBufferSizeIn, iBufferSizeIn * iNumPeriodBlocks);
// TEST
/* check period and buffer size */
snd_pcm_uframes_t buffer_size;
if (err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size) < 0) {
qDebug("Unable to get buffer size for playback: %s\n", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
}
qDebug("buffer size %d", buffer_size);
qDebug("buffer size: %d (desired: %d)", buffer_size, iBufferSizeIn * iNumPeriodBlocks);
snd_pcm_uframes_t period_size;
err = snd_pcm_hw_params_get_period_size(hwparams, &period_size, 0);
if (err < 0)
{
qDebug("Unable to get period size for playback: %s\n", snd_strerror(err));
// throw CGenErr("alsa CSound::Init_HW ");
}
qDebug("period size %d", period_size);
qDebug("frame size: %d (desired: %d)", period_size, iBufferSizeIn);
/* clean-up */
snd_pcm_hw_params_free(hwparams);
snd_pcm_hw_params_free ( hwparams );
return false;
}
void CSound::Close()
void CSound::Close ()
{
/* read */
if (rhandle != NULL)
snd_pcm_close(rhandle);
if ( rhandle != NULL )
{
snd_pcm_close ( rhandle );
}
rhandle = NULL;
/* playback */
if (phandle != NULL)
snd_pcm_close(phandle);
if ( phandle != NULL )
{
snd_pcm_close ( phandle );
}
phandle = NULL;
}

View file

@ -47,7 +47,8 @@ public:
CSound()
#if WITH_SOUND
: rhandle(NULL), phandle(NULL), iCurPeriodSizeIn(NUM_PERIOD_BLOCKS_IN),
iCurPeriodSizeOut(NUM_PERIOD_BLOCKS_OUT)
iCurPeriodSizeOut(NUM_PERIOD_BLOCKS_OUT), bChangParamIn(true),
bChangParamOut(true)
#endif
{}
virtual ~CSound() {Close();}
@ -78,8 +79,8 @@ protected:
snd_pcm_t* rhandle;
snd_pcm_t* phandle;
bool SetHWParams(snd_pcm_t* handle, const bool bIsRecord,
const int iBufferSizeIn, const int iNumPeriodBlocks);
bool SetHWParams(snd_pcm_t* handle, const int iBufferSizeIn,
const int iNumPeriodBlocks);
int iBufferSizeOut;
int iBufferSizeIn;

View file

@ -130,13 +130,15 @@ void CClient::run()
/* Set thread priority (The working thread should have a higher
priority than the GUI) */
#ifdef _WIN32
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
SetThreadPriority ( GetCurrentThread (), THREAD_PRIORITY_ABOVE_NORMAL );
#else
/* set the process to realtime privs */
/* 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);
memset ( &schp, 0, sizeof ( schp ) );
schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
sched_setscheduler ( 0, SCHED_FIFO, &schp );
#endif
/* init object */

View file

@ -205,41 +205,45 @@ void CLlconClientDlg::closeEvent ( QCloseEvent * Event )
Event->accept();
}
void CLlconClientDlg::OnConnectDisconBut()
void CLlconClientDlg::OnConnectDisconBut ()
{
/* start/stop client, set button text */
if (pClient->IsRunning())
if ( pClient->IsRunning () )
{
pClient->Stop();
PushButtonConnect->setText(CON_BUT_CONNECTTEXT);
pClient->Stop ();
PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
/* stop timer for level meter bars and reset them */
TimerSigMet.stop();
ProgressBarInputLevelL->setProgress(0);
ProgressBarInputLevelR->setProgress(0);
TimerSigMet.stop ();
ProgressBarInputLevelL->setProgress ( 0 );
ProgressBarInputLevelR->setProgress ( 0 );
/* immediately update status bar */
OnTimerStatus();
OnTimerStatus ();
}
else
{
/* set address and check if address is valid */
if (pClient->SetServerAddr(LineEditServerAddr->text()))
if ( pClient->SetServerAddr ( LineEditServerAddr->text () ) )
{
pClient->start();
PushButtonConnect->setText(CON_BUT_DISCONNECTTEXT);
#if ( QT_VERSION > 300 )
pClient->start ( QThread::TimeCriticalPriority );
#else
pClient->start ();
#endif
PushButtonConnect->setText ( CON_BUT_DISCONNECTTEXT );
/* start timer for level meter bar */
TimerSigMet.start(LEVELMETER_UPDATE_TIME);
TimerSigMet.start ( LEVELMETER_UPDATE_TIME );
}
else
{
/* Restart timer to ensure that the text is visible at
least the time for one complete interval */
TimerStatus.changeInterval(STATUSBAR_UPDATE_TIME);
TimerStatus.changeInterval ( STATUSBAR_UPDATE_TIME );
/* show the error in the status bar */
TextLabelStatus->setText(tr("invalid address"));
TextLabelStatus->setText ( tr ( "invalid address" ) );
}
}
}