diff --git a/daemon/src/audio/alsa/alsalayer.cpp b/daemon/src/audio/alsa/alsalayer.cpp index a9ffb4ea16da12cb872aadda78dedff5a28868d1..b4afbe660dbdca7844cda6c37a538ac595c9c931 100644 --- a/daemon/src/audio/alsa/alsalayer.cpp +++ b/daemon/src/audio/alsa/alsalayer.cpp @@ -80,7 +80,6 @@ AlsaLayer::AlsaLayer () , playbackHandle_ (NULL) , ringtoneHandle_ (NULL) , captureHandle_ (NULL) - , periodSize_ (160) , audioPlugin_ (audioPref.getPlugin()) , IDSoundCards_ () , is_playback_prepared_ (false) @@ -314,115 +313,45 @@ void AlsaLayer::preparePlaybackStream (void) bool AlsaLayer::alsa_set_params (snd_pcm_t *pcm_handle) { - snd_pcm_hw_params_t *hwparams = NULL; - snd_pcm_sw_params_t *swparams = NULL; - int format; - int periods = 4; - int periodsize = 160; - - /* Allocate the snd_pcm_hw_params_t struct */ - snd_pcm_hw_params_malloc (&hwparams); - - periodSize_ = periodsize; - /* Full configuration space */ - - int err; - if ((err = snd_pcm_hw_params_any (pcm_handle, hwparams)) < 0) { - _debug ("Audio: Error: Cannot initialize hardware parameter structure (%s)", snd_strerror (err)); - return false; - } - - if ((err = snd_pcm_hw_params_set_access (pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { - _debug ("Audio: Error: Cannot set access type (%s)", snd_strerror (err)); - return false; - } - - /* Set sample format */ - format = SND_PCM_FORMAT_S16_LE; - - if ((err = snd_pcm_hw_params_set_format (pcm_handle, hwparams, (snd_pcm_format_t) format)) < 0) { - _debug ("Audio: Error: Cannot set sample format (%s)", snd_strerror (err)); - return false; - } - - /* Set sample rate. If we can't set to the desired exact value, we set to the nearest acceptable */ - int dir = 0; - - unsigned int exact_ivalue = audioSampleRate_; - - if ((err = snd_pcm_hw_params_set_rate_near (pcm_handle, hwparams, &exact_ivalue, &dir) < 0)) { - _error("Alsa: Cannot set sample rate (%s)", snd_strerror (err)); - return false; - } else - _debug ("Alsa: Set audio rate to %d", audioSampleRate_); - - if (dir != 0) { - _error("Alsa: The chosen rate %d Hz is not supported by your hardware.Using %d Hz instead. ", audioSampleRate_, exact_ivalue); - //audioSampleRate_ = exact_ivalue; - // FIXME - } - - /* Set the number of channels */ - if ((err = snd_pcm_hw_params_set_channels (pcm_handle, hwparams, 1)) < 0) { - _debug ("Audio: Error: Cannot set channel count (%s)", snd_strerror (err)); - return false; - } - - /* Set the buffer size in frames */ - unsigned long exact_lvalue = periodsize; - - dir = 0; +#define TRY(call, error) do { \ + int err = call; \ + if (err < 0) { \ + _error("ALSA: Cannot set "error": %s", snd_strerror(err)); \ + return false; \ + } \ + } while(0) + + snd_pcm_hw_params_t *hwparams; + snd_pcm_hw_params_alloca(&hwparams); + + snd_pcm_uframes_t periodSize = 160; + unsigned int periods = 4; + +#define HW pcm_handle, hwparams /* hardware parameters */ + TRY(snd_pcm_hw_params_any (HW), "hwparams init"); + TRY(snd_pcm_hw_params_set_access (HW, SND_PCM_ACCESS_RW_INTERLEAVED), "access type"); + TRY(snd_pcm_hw_params_set_format (HW, SND_PCM_FORMAT_S16_LE), "sample format"); + TRY(snd_pcm_hw_params_set_rate_near (HW, &audioSampleRate_, NULL), "sample rate"); + TRY(snd_pcm_hw_params_set_channels (HW, 1), "channel count"); + TRY(snd_pcm_hw_params_set_period_size_near (HW, &periodSize, NULL), "period time"); + TRY(snd_pcm_hw_params_set_periods_near (HW, &periods, NULL), "periods number"); + TRY(snd_pcm_hw_params (HW), "hwparams"); +#undef HW + + _debug ("ALSA: Using sampling rate %dHz", audioSampleRate_); - if ((err = snd_pcm_hw_params_set_period_size_near (pcm_handle, hwparams, &exact_lvalue, &dir)) < 0) { - _debug ("Audio: Error: Cannot set period time (%s)", snd_strerror (err)); - return false; - } - - if (dir != 0) - _warn("Alsa: The chosen period size %lu bytes is not supported by your hardware.Using %lu instead. ", periodsize, exact_lvalue); - - periodSize_ = exact_lvalue; - /* Set the number of fragments */ - exact_ivalue = periods; - dir = 0; - - if ((err = snd_pcm_hw_params_set_periods_near (pcm_handle, hwparams, &exact_ivalue, &dir)) < 0) { - _debug ("Audio: Error: Cannot set periods number (%s)", snd_strerror (err)); - return false; - } - - if (dir != 0) - _debug ("Audio: Warning: The chosen period number %i bytes is not supported by your hardware.Using %i instead. ", periods, exact_ivalue); - - periods = exact_ivalue; - - /* Set the hw parameters */ - - if ((err = snd_pcm_hw_params (pcm_handle, hwparams)) < 0) { - _debug ("Audio: Error: Cannot set hw parameters (%s)", snd_strerror (err)); - return false; - } - - snd_pcm_hw_params_free (hwparams); - - /* Set the sw parameters */ - snd_pcm_sw_params_malloc (&swparams); - snd_pcm_sw_params_current (pcm_handle, swparams); - - /* Set the start threshold */ - - if ((err = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, periodSize_ * 2)) < 0) { - _debug ("Audio: Error: Cannot set start threshold (%s)", snd_strerror (err)); - return false; - } + snd_pcm_sw_params_t *swparams = NULL; + snd_pcm_sw_params_alloca(&swparams); - if ((err = snd_pcm_sw_params (pcm_handle, swparams)) < 0) { - _debug ("Audio: Error: Cannot set sw parameters (%s)", snd_strerror (err)); - return false; - } +#define SW pcm_handle, swparams /* software parameters */ + snd_pcm_sw_params_current (SW); + TRY(snd_pcm_sw_params_set_start_threshold (SW, periodSize * 2), "start threshold"); + TRY(snd_pcm_sw_params (SW), "sw parameters"); +#undef SW - snd_pcm_sw_params_free (swparams); return true; + +#undef TRY } //TODO first frame causes broken pipe (underrun) because not enough data are send --> make the handle wait to be ready diff --git a/daemon/src/audio/alsa/alsalayer.h b/daemon/src/audio/alsa/alsalayer.h index d81997e6f4cc07ccdd6883449c7c2ce3c0d17d5a..9c14a1e6c2abc8e39a86f0543ac076975c3de385 100644 --- a/daemon/src/audio/alsa/alsalayer.h +++ b/daemon/src/audio/alsa/alsalayer.h @@ -44,6 +44,9 @@ class AlsaThread; * @brief Main sound class. Manages the data transfers between the application and the hardware. */ +/** Associate a sound card index to its string description */ +typedef std::pair<int , std::string> HwIDPair; + class AlsaLayer : public AudioLayer { public: @@ -71,14 +74,6 @@ class AlsaLayer : public AudioLayer */ void stopStream (void); - /** - * Get data from the capture device - * @param buffer The buffer for data - * @param toCopy The number of bytes to get - * @return int The number of bytes acquired ( 0 if an error occured) - */ - int getMic (void * buffer, int toCopy); - /** * Concatenate two strings. Used to build a valid pcm device name. * @param plugin the alsa PCM name @@ -116,14 +111,6 @@ class AlsaLayer : public AudioLayer */ int soundCardGetIndex (const std::string &description); - /** - * Get the current audio plugin. - * @return std::string The name of the audio plugin - */ - std::string getAudioPlugin (void) const { - return audioPlugin_; - } - void playback(int maxSamples); void capture(void); @@ -176,9 +163,6 @@ class AlsaLayer : public AudioLayer */ int indexRing_; - /** Associate a sound card index to its string description */ - typedef std::pair<int , std::string> HwIDPair; - // Copy Constructor AlsaLayer (const AlsaLayer& rh); @@ -237,11 +221,6 @@ class AlsaLayer : public AudioLayer */ snd_pcm_t* captureHandle_; - /** - * Alsa parameter - Size of a period in the hardware ring buffer - */ - snd_pcm_uframes_t periodSize_; - /** * name of the alsa audio plugin used */ diff --git a/daemon/src/audio/audiolayer.h b/daemon/src/audio/audiolayer.h index f6e348b0d49fbfa51807c704366d56e3185e79f0..850922758f4418c7bfcc58cb5d8b63376b7563e5 100644 --- a/daemon/src/audio/audiolayer.h +++ b/daemon/src/audio/audiolayer.h @@ -157,7 +157,7 @@ class AudioLayer * Sample Rate SFLphone should send sound data to the sound card * The value can be set in the user config file- now: 44100HZ */ - const unsigned int audioSampleRate_; + unsigned int audioSampleRate_; /** * Lock for the entire audio layer