Commit 68310c6b authored by Rafaël Carré's avatar Rafaël Carré
Browse files

* #6629: simplify AlsaLayer::alsa_set_params()

remove unneeded class members
fix a bug with samplerate
parent cdf78f78
......@@ -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
......
......@@ -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
*/
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment