63 #include <sys/soundcard.h>
64 #include <sys/ioctl.h>
72 #define AUDIO_FORMAT AFMT_S16_LE
73 #define INPUT_GAIN (80)
75 #define SPS_EPSILON 200
76 #define SAMPLERATE_TOLERANCE 0.01
83 int32 nonBlocking = 1, sourceMic = SOUND_MASK_MIC, inputGain =
84 INPUT_GAIN, devMask = 0;
85 int32 audioFormat = AUDIO_FORMAT;
88 int32 numberChannels = 1;
96 if ((dspFD = open(dev, O_RDONLY)) < 0) {
98 fprintf(stderr,
"%s(%d): Audio device(%s) busy\n",
99 __FILE__, __LINE__, dev);
102 "%s(%d): Failed to open audio device(%s): %s\n",
103 __FILE__, __LINE__, dev, strerror(errno));
107 if (ioctl(dspFD, SNDCTL_DSP_SYNC, 0) < 0) {
108 fprintf(stderr,
"Audio ioctl(SYNC) failed: %s\n", strerror(errno));
113 if (ioctl(dspFD, SNDCTL_DSP_RESET, 0) < 0) {
114 fprintf(stderr,
"Audio ioctl(RESET) failed: %s\n",
120 if (ioctl(dspFD, SNDCTL_DSP_SETFMT, &audioFormat) < 0) {
121 fprintf(stderr,
"Audio ioctl(SETFMT 0x%x) failed: %s\n",
122 audioFormat, strerror(errno));
126 if (audioFormat != AUDIO_FORMAT) {
128 "Audio ioctl(SETFMT): 0x%x, expected: 0x%x\n",
129 audioFormat, AUDIO_FORMAT);
134 if (ioctl(dspFD, SNDCTL_DSP_SPEED, &sampleRate) < 0) {
135 fprintf(stderr,
"Audio ioctl(SPEED %d) failed %s\n",
136 sampleRate, strerror(errno));
140 if (sampleRate != sps) {
141 if (abs(sampleRate - sps) <= (sampleRate * SAMPLERATE_TOLERANCE)) {
143 "Audio ioctl(SPEED) not perfect, but is acceptable. "
144 "(Wanted %d, but got %d)\n", sampleRate, sps);
148 "Audio ioctl(SPEED): %d, expected: %d\n",
155 if (ioctl(dspFD, SNDCTL_DSP_CHANNELS, &numberChannels) < 0) {
156 fprintf(stderr,
"Audio ioctl(CHANNELS %d) failed %s\n",
157 numberChannels, strerror(errno));
162 if (ioctl(dspFD, SNDCTL_DSP_NONBLOCK, &nonBlocking) < 0) {
163 fprintf(stderr,
"ioctl(NONBLOCK) failed: %s\n", strerror(errno));
168 if (ioctl(dspFD, SNDCTL_DSP_GETCAPS, &dspCaps) < 0) {
169 fprintf(stderr,
"ioctl(GETCAPS) failed: %s\n", strerror(errno));
174 printf(
"DSP Revision %d:\n", dspCaps & DSP_CAP_REVISION);
175 printf(
"DSP %s duplex capability.\n",
176 (dspCaps & DSP_CAP_DUPLEX) ?
"has" :
"does not have");
177 printf(
"DSP %s real time capability.\n",
178 (dspCaps & DSP_CAP_REALTIME) ?
"has" :
"does not have");
179 printf(
"DSP %s batch capability.\n",
180 (dspCaps & DSP_CAP_BATCH) ?
"has" :
"does not have");
181 printf(
"DSP %s coprocessor capability.\n",
182 (dspCaps & DSP_CAP_COPROC) ?
"has" :
"does not have");
183 printf(
"DSP %s trigger capability.\n",
184 (dspCaps & DSP_CAP_TRIGGER) ?
"has" :
"does not have");
185 printf(
"DSP %s memory map capability.\n",
186 (dspCaps & DSP_CAP_MMAP) ?
"has" :
"does not have");
189 if ((dspCaps & DSP_CAP_DUPLEX)
190 && (ioctl(dspFD, SNDCTL_DSP_SETDUPLEX, 0) < 0))
191 fprintf(stderr,
"ioctl(SETDUPLEX) failed: %s\n", strerror(errno));
199 if ((mixerFD = open(
"/dev/mixer", O_RDONLY)) < 0) {
200 if (errno == EBUSY) {
201 fprintf(stderr,
"%s %d: mixer device busy.\n",
203 fprintf(stderr,
"%s %d: Using current setting.\n",
207 fprintf(stderr,
"%s %d: %s\n", __FILE__, __LINE__,
214 if (ioctl(mixerFD, SOUND_MIXER_WRITE_RECSRC, &sourceMic) < 0) {
217 "%s %d: can't set mic source for this device.\n",
221 "%s %d: mixer set to mic: %s\n",
222 __FILE__, __LINE__, strerror(errno));
228 inputGain = inputGain << 8 | inputGain;
233 if (ioctl(mixerFD, SOUND_MIXER_READ_DEVMASK, &devMask) < 0) {
235 "%s %d: failed to read device mask: %s\n",
236 __FILE__, __LINE__, strerror(errno));
239 if (devMask & SOUND_MASK_IGAIN) {
240 if (ioctl(mixerFD, SOUND_MIXER_WRITE_IGAIN, &inputGain) < 0) {
242 "%s %d: mixer input gain to %d: %s\n",
243 __FILE__, __LINE__, inputGain, strerror(errno));
247 else if (devMask & SOUND_MASK_RECLEV) {
248 if (ioctl(mixerFD, SOUND_MIXER_WRITE_RECLEV, &inputGain) < 0) {
250 "%s %d: mixer record level to %d: %s\n",
251 __FILE__, __LINE__, inputGain, strerror(errno));
257 "%s %d: can't set input gain/recording level for this device.\n",
265 fprintf(stderr,
"calloc(%ld) failed\n",
sizeof(
ad_rec_t));
269 handle->dspFD = dspFD;
270 handle->recording = 0;
272 handle->
bps =
sizeof(int16);
292 if (handle->dspFD < 0)
293 return AD_ERR_NOT_OPEN;
295 if (handle->recording) {
296 if (ad_stop_rec(handle) < 0)
300 close(handle->dspFD);
309 if (handle->dspFD < 0)
310 return AD_ERR_NOT_OPEN;
312 if (handle->recording)
321 handle->recording = 1;
331 if (handle->dspFD < 0)
332 return AD_ERR_NOT_OPEN;
334 if (!handle->recording)
337 if (ioctl(handle->dspFD, SNDCTL_DSP_SYNC, 0) < 0) {
338 fprintf(stderr,
"Audio ioctl(SYNC) failed: %s\n", strerror(errno));
342 handle->recording = 0;
348 ad_read(
ad_rec_t * handle, int16 * buf, int32 max)
352 length = max * handle->
bps;
354 if ((length = read(handle->dspFD, buf, length)) > 0) {
356 if ((length % handle->
bps) != 0)
358 "Audio read returned non-integral #sample bytes (%d)\n",
361 length /= handle->
bps;
365 if (errno != EAGAIN) {
366 fprintf(stderr,
"Audio read error");
374 if ((length == 0) && (!handle->recording))
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.