31 #include <alsa/asoundlib.h> 34 #include <boost/format.hpp> 40 #define ALSA_USE_SIMPLE_SETUP 46 unsigned int _sample_count_hint,
47 std::string audio_port_name) :
48 AudioIfc(_sample_rate, _fmt, _sample_count_hint,
"AudioALSA ALSA Interface") {
51 setupPlayback(audio_port_name);
53 setupCapture(audio_port_name);
56 void AudioALSA::setupPlayback(std::string audio_port_name)
58 (void) audio_port_name;
60 char pcm_name[] =
"default";
64 if(snd_pcm_open(&pcm_out, pcm_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
65 std::cerr << boost::format(
"can't open Alsa PCM device [%s] for output ... Crap.\n") % pcm_name;
69 #ifdef ALSA_USE_SIMPLE_SETUP 70 checkStatus(snd_pcm_set_params(pcm_out,
72 SND_PCM_ACCESS_RW_INTERLEAVED,
77 "Failed to do simple set params for output.",
true);
79 setupParams(pcm_out, hw_out_params);
83 void AudioALSA::setupCapture(std::string audio_port_name)
86 const char *pcm_cap_name = audio_port_name.c_str();
87 snd_pcm_stream_t instream = SND_PCM_STREAM_CAPTURE;
88 if(snd_pcm_open(&pcm_in, pcm_cap_name, instream, 0) < 0) {
89 std::cerr << boost::format(
"can't open Alsa PCM device [%s] for input... Crap.\n") % pcm_cap_name;
93 #ifdef ALSA_USE_SIMPLE_SETUP 94 checkStatus(snd_pcm_set_params(pcm_in,
96 SND_PCM_ACCESS_RW_INTERLEAVED,
101 "Failed to do simple set params for output.",
true);
103 setupParams(pcm_in, hw_in_params);
107 void AudioALSA::setupParams(snd_pcm_t * dev, snd_pcm_hw_params_t * & hw_params_ptr)
109 snd_pcm_hw_params_t * hw_paramsp;
111 snd_pcm_hw_params_alloca(&hw_paramsp);
113 hw_params_ptr = hw_paramsp;
115 checkStatus(snd_pcm_hw_params_any (dev, hw_paramsp),
"setupParams init parm block",
true);
117 checkStatus(snd_pcm_hw_params_set_access (dev, hw_paramsp, SND_PCM_ACCESS_RW_INTERLEAVED),
118 "setupParams set access",
true);
120 checkStatus(snd_pcm_hw_params_set_format (dev, hw_paramsp, translateFormat(
format)),
121 "setupParams set format",
true);
123 checkStatus(snd_pcm_hw_params_set_rate_near (dev, hw_paramsp, &
sample_rate, 0),
124 "setupParams set sample rate",
true);
126 checkStatus(snd_pcm_hw_params_set_channels (dev, hw_paramsp, 1),
127 "setupParams set number of channels",
true);
129 checkStatus(snd_pcm_hw_params_set_buffer_size (dev, hw_paramsp,
131 "setupParams set buffer size",
true);
133 checkStatus(snd_pcm_hw_params (dev, hw_paramsp),
134 "setupParams set parameter block",
true);
136 checkStatus(snd_pcm_prepare (dev),
137 "setupParams prepare audio interface",
true);
142 snd_pcm_sframes_t sframes_ready = snd_pcm_avail(pcm_in);
143 if(sframes_ready == -EPIPE) {
146 if((err = snd_pcm_recover(pcm_in, sframes_ready, 1)) < 0) {
147 checkStatus(err,
"recvBufferReady got EPIPE, tried recovery",
false);
149 sframes_ready = snd_pcm_avail(pcm_in);
152 if(sframes_ready < 0) {
153 checkStatus(sframes_ready,
"recvBufferReady",
false);
155 return sframes_ready >= len;
159 snd_pcm_sframes_t sframes_ready;
162 sframes_ready= snd_pcm_avail(pcm_out);
164 if(sframes_ready == -EPIPE) {
169 if((err = snd_pcm_recover(pcm_out, sframes_ready, 1)) < 0) {
170 checkStatus(err,
"sendBufferReady got EPIPE, tried recovery",
false);
172 if((err = snd_pcm_start(pcm_out)) < 0) {
174 SoDaException((boost::format(
"AudioALSA::wakeOut() Failed to wake after sleepOut() -- %s")
175 % snd_strerror(err)).str(),
this);
179 checkStatus(sframes_ready,
"sendBufferReady",
false);
183 return sframes_ready >= len;
190 char * cbuf = (
char *) buf;
192 err = snd_pcm_writei(pcm_out, cbuf, len);
194 if(err == (
int) len)
return len;
195 else if(err == -EAGAIN)
continue;
196 else if(err == -EPIPE) {
198 if((err = snd_pcm_recover(pcm_out, err, 1)) < 0) {
199 checkStatus(err,
"send got EPIPE, tried recovery",
false);
203 checkStatus(err,
"send",
true);
205 else if(err != (
int)len) {
219 char * cbuf = (
char *) buf;
221 err = snd_pcm_readi(pcm_in, cbuf, len);
223 if(err == (
int)len)
return len;
224 else if(err == -EAGAIN)
continue;
226 checkStatus(err,
"recv",
true);
228 else if(err != (
int)len) {
240 case FLOAT:
return SND_PCM_FORMAT_FLOAT;
242 case DFLOAT:
return SND_PCM_FORMAT_FLOAT64;
244 case INT32:
return SND_PCM_FORMAT_S32;
246 case INT16:
return SND_PCM_FORMAT_S16;
248 case INT8:
return SND_PCM_FORMAT_S8;
251 return SND_PCM_FORMAT_S16_LE;
256 unsigned int _sample_count_hint,
257 std::string audio_port_name) :
258 AudioIfc(_sample_rate, _fmt, _sample_count_hint,
"AudioALSA ALSA Interface")
260 std::cerr <<
"ALSA Sound Library is not enabled in this build version.";
263 #endif // HAVE_LIBASOUND
int send(void *buf, unsigned int len)
send – send a buffer to the audio output
bool sendBufferReady(unsigned int len)
sendBufferReady – is there enough space in the audio device send buffer for a call from send...
The SoDa Exception class.
unsigned int sample_count_hint
bool recvBufferReady(unsigned int len)
recvBufferReady – are there samples waiting in the audio device?
Generic Audio Interface Class.
int recv(void *buf, unsigned int len, bool block=true)
recv – get a buffer of data from the audio input
AudioALSA(unsigned int _sample_rate, AudioIfc::DataFormat _fmt, unsigned int _sample_count_hint=1024, std::string audio_port_name=std::string("default"))
constructor