76 #include <alsa/asoundlib.h>
85 #define AUDIO_FORMAT SND_PCM_SFMT_S16_LE
86 #define INPUT_GAIN (85)
87 #define SPS_EPSILON 200
90 setparams(int32 sps, snd_pcm_t * handle)
92 snd_pcm_hw_params_t *hwparams;
93 unsigned int out_sps, buffer_time, period_time;
96 snd_pcm_hw_params_alloca(&hwparams);
97 err = snd_pcm_hw_params_any(handle, hwparams);
99 fprintf(stderr,
"Can not configure this PCM device: %s\n",
105 snd_pcm_hw_params_set_access(handle, hwparams,
106 SND_PCM_ACCESS_RW_INTERLEAVED);
109 "Failed to set PCM device to interleaved: %s\n",
115 snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16);
118 "Failed to set PCM device to 16-bit signed PCM: %s\n",
123 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
125 fprintf(stderr,
"Failed to set PCM device to mono: %s\n",
132 snd_pcm_hw_params_set_rate_near(handle, hwparams, &out_sps, NULL);
134 fprintf(stderr,
"Failed to set sampling rate: %s\n",
138 if (abs(out_sps - sps) > SPS_EPSILON) {
140 "Available samping rate %d is too far from requested %d\n",
146 err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0);
147 period_time = buffer_time / 4;
148 err = snd_pcm_hw_params_set_period_time_near(handle, hwparams,
151 fprintf(stderr,
"Failed to set period time to %u: %s\n",
152 period_time, snd_strerror(err));
155 err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams,
158 fprintf(stderr,
"Failed to set buffer time to %u: %s\n",
159 buffer_time, snd_strerror(err));
163 err = snd_pcm_hw_params(handle, hwparams);
165 fprintf(stderr,
"Failed to set hwparams: %s\n", snd_strerror(err));
169 err = snd_pcm_nonblock(handle, 1);
171 fprintf(stderr,
"Failed to set non-blocking mode: %s\n",
179 setlevels(
const char *dev)
182 snd_mixer_selem_id_t *sid;
183 snd_mixer_elem_t *elem;
188 if ((err = snd_mixer_open(&handle, 0)) < 0) {
189 fprintf(stderr,
"Mixer open failed: %s\n", snd_strerror(err));
193 mixer_dev = strdup(dev);
194 if (strncmp(mixer_dev,
"plug", 4) == 0)
195 memmove(mixer_dev, mixer_dev + 4, strlen(mixer_dev) - 4 + 1);
196 if ((c = strchr(mixer_dev,
',')))
198 if ((err = snd_mixer_attach(handle, mixer_dev)) < 0) {
199 fprintf(stderr,
"Mixer attach to %s failed: %s\n",
200 mixer_dev, snd_strerror(err));
202 snd_mixer_close(handle);
206 if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
207 fprintf(stderr,
"Mixer register failed: %s\n", snd_strerror(err));
208 snd_mixer_close(handle);
211 if ((err = snd_mixer_load(handle)) < 0) {
212 fprintf(stderr,
"Mixer load failed: %s\n", snd_strerror(err));
213 snd_mixer_close(handle);
216 snd_mixer_selem_id_alloca(&sid);
217 snd_mixer_selem_id_set_name(sid,
"Mic");
218 if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) {
219 fprintf(stderr,
"Warning: Could not find Mic element\n");
222 if (snd_mixer_selem_has_capture_switch(elem)) {
223 if ((err = snd_mixer_selem_set_capture_switch_all(elem, 1)) < 0) {
225 "Failed to enable microphone capture: %s\n",
227 snd_mixer_close(handle);
232 snd_mixer_selem_id_set_name(sid,
"Capture");
233 if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) {
234 fprintf(stderr,
"Warning: Could not find Capture element\n");
237 if (snd_mixer_selem_has_capture_switch(elem)) {
238 if ((err = snd_mixer_selem_set_capture_switch_all(elem, 1)) < 0) {
240 "Failed to enable microphone capture: %s\n",
242 snd_mixer_close(handle);
260 dev = DEFAULT_DEVICE;
262 err = snd_pcm_open(&dspH, dev, SND_PCM_STREAM_CAPTURE, 0);
265 "Error opening audio device %s for capture: %s\n",
266 dev, snd_strerror(err));
270 if (setparams(sps, dspH) < 0) {
273 if (setlevels(dev) < 0) {
277 fprintf(stderr,
"calloc(%d) failed\n", (
int)
sizeof(
ad_rec_t));
282 handle->recording = 0;
284 handle->
bps =
sizeof(int16);
305 if (handle->dspH == NULL)
306 return AD_ERR_NOT_OPEN;
308 if (handle->recording) {
309 if (ad_stop_rec(handle) < 0)
312 snd_pcm_close(handle->dspH);
324 if (handle->dspH == NULL)
325 return AD_ERR_NOT_OPEN;
327 if (handle->recording)
330 err = snd_pcm_prepare(handle->dspH);
332 fprintf(stderr,
"snd_pcm_prepare failed: %s\n", snd_strerror(err));
335 err = snd_pcm_start(handle->dspH);
337 fprintf(stderr,
"snd_pcm_start failed: %s\n", snd_strerror(err));
340 handle->recording = 1;
351 if (handle->dspH == NULL)
352 return AD_ERR_NOT_OPEN;
354 if (!handle->recording)
357 err = snd_pcm_drop(handle->dspH);
359 fprintf(stderr,
"snd_pcm_drop failed: %s\n", snd_strerror(err));
362 handle->recording = 0;
369 ad_read(
ad_rec_t * handle, int16 * buf, int32 max)
373 if (!handle->recording) {
374 fprintf(stderr,
"Recording is stopped, start recording with ad_start_rec\n");
378 length = snd_pcm_readi(handle->dspH, buf, max);
379 if (length == -EAGAIN) {
382 else if (length == -EPIPE) {
383 fprintf(stderr,
"Input overrun, read calls are too rare (non-fatal)\n");
384 err = snd_pcm_prepare(handle->dspH);
386 fprintf(stderr,
"Can't recover from underrun: %s\n",
392 else if (length == -ESTRPIPE) {
393 fprintf(stderr,
"Resuming sound driver (non-fatal)\n");
394 while ((err = snd_pcm_resume(handle->dspH)) == -EAGAIN)
397 err = snd_pcm_prepare(handle->dspH);
399 fprintf(stderr,
"Can't recover from underrun: %s\n",
406 else if (length < 0) {
407 fprintf(stderr,
"Audio read error: %s\n",
408 snd_strerror(length));
Basic type definitions used in Sphinx.
SPHINXBASE_EXPORT ad_rec_t * ad_open(void)
Open the default audio device.
generic live audio interface for recording and playback
SPHINXBASE_EXPORT ad_rec_t * ad_open_dev(const char *dev, int32 samples_per_sec)
Open a specific audio device for recording.
SPHINXBASE_EXPORT ad_rec_t * ad_open_sps(int32 samples_per_sec)
Open the default audio device with a given sampling rate.