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
78 #define DEFAULT_DEVICE "/dev/dsp"
95 int32 nonBlocking = 1, sourceMic = SOUND_MASK_MIC, inputGain =
96 INPUT_GAIN, devMask = 0;
97 int32 audioFormat = AUDIO_FORMAT;
100 int32 numberChannels = 1;
105 dev = DEFAULT_DEVICE;
108 if ((dspFD = open(dev, O_RDONLY)) < 0) {
110 fprintf(stderr,
"%s(%d): Audio device(%s) busy\n",
111 __FILE__, __LINE__, dev);
114 "%s(%d): Failed to open audio device(%s): %s\n",
115 __FILE__, __LINE__, dev, strerror(errno));
119 if (ioctl(dspFD, SNDCTL_DSP_SYNC, 0) < 0) {
120 fprintf(stderr,
"Audio ioctl(SYNC) failed: %s\n", strerror(errno));
125 if (ioctl(dspFD, SNDCTL_DSP_RESET, 0) < 0) {
126 fprintf(stderr,
"Audio ioctl(RESET) failed: %s\n",
132 if (ioctl(dspFD, SNDCTL_DSP_SETFMT, &audioFormat) < 0) {
133 fprintf(stderr,
"Audio ioctl(SETFMT 0x%x) failed: %s\n",
134 audioFormat, strerror(errno));
138 if (audioFormat != AUDIO_FORMAT) {
140 "Audio ioctl(SETFMT): 0x%x, expected: 0x%x\n",
141 audioFormat, AUDIO_FORMAT);
146 if (ioctl(dspFD, SNDCTL_DSP_SPEED, &sampleRate) < 0) {
147 fprintf(stderr,
"Audio ioctl(SPEED %d) failed %s\n",
148 sampleRate, strerror(errno));
152 if (sampleRate != sps) {
153 if (abs(sampleRate - sps) <= (sampleRate * SAMPLERATE_TOLERANCE)) {
155 "Audio ioctl(SPEED) not perfect, but is acceptable. "
156 "(Wanted %d, but got %d)\n", sampleRate, sps);
160 "Audio ioctl(SPEED): %d, expected: %d\n",
167 if (ioctl(dspFD, SNDCTL_DSP_CHANNELS, &numberChannels) < 0) {
168 fprintf(stderr,
"Audio ioctl(CHANNELS %d) failed %s\n",
169 numberChannels, strerror(errno));
174 if (ioctl(dspFD, SNDCTL_DSP_NONBLOCK, &nonBlocking) < 0) {
175 fprintf(stderr,
"ioctl(NONBLOCK) failed: %s\n", strerror(errno));
180 if (ioctl(dspFD, SNDCTL_DSP_GETCAPS, &dspCaps) < 0) {
181 fprintf(stderr,
"ioctl(GETCAPS) failed: %s\n", strerror(errno));
186 printf(
"DSP Revision %d:\n", dspCaps & DSP_CAP_REVISION);
187 printf(
"DSP %s duplex capability.\n",
188 (dspCaps & DSP_CAP_DUPLEX) ?
"has" :
"does not have");
189 printf(
"DSP %s real time capability.\n",
190 (dspCaps & DSP_CAP_REALTIME) ?
"has" :
"does not have");
191 printf(
"DSP %s batch capability.\n",
192 (dspCaps & DSP_CAP_BATCH) ?
"has" :
"does not have");
193 printf(
"DSP %s coprocessor capability.\n",
194 (dspCaps & DSP_CAP_COPROC) ?
"has" :
"does not have");
195 printf(
"DSP %s trigger capability.\n",
196 (dspCaps & DSP_CAP_TRIGGER) ?
"has" :
"does not have");
197 printf(
"DSP %s memory map capability.\n",
198 (dspCaps & DSP_CAP_MMAP) ?
"has" :
"does not have");
201 if ((dspCaps & DSP_CAP_DUPLEX)
202 && (ioctl(dspFD, SNDCTL_DSP_SETDUPLEX, 0) < 0))
203 fprintf(stderr,
"ioctl(SETDUPLEX) failed: %s\n", strerror(errno));
211 if ((mixerFD = open(
"/dev/mixer", O_RDONLY)) < 0) {
212 if (errno == EBUSY) {
213 fprintf(stderr,
"%s %d: mixer device busy.\n",
215 fprintf(stderr,
"%s %d: Using current setting.\n",
219 fprintf(stderr,
"%s %d: %s\n", __FILE__, __LINE__,
226 if (ioctl(mixerFD, SOUND_MIXER_WRITE_RECSRC, &sourceMic) < 0) {
229 "%s %d: can't set mic source for this device.\n",
233 "%s %d: mixer set to mic: %s\n",
234 __FILE__, __LINE__, strerror(errno));
240 inputGain = inputGain << 8 | inputGain;
245 if (ioctl(mixerFD, SOUND_MIXER_READ_DEVMASK, &devMask) < 0) {
247 "%s %d: failed to read device mask: %s\n",
248 __FILE__, __LINE__, strerror(errno));
251 if (devMask & SOUND_MASK_IGAIN) {
252 if (ioctl(mixerFD, SOUND_MIXER_WRITE_IGAIN, &inputGain) < 0) {
254 "%s %d: mixer input gain to %d: %s\n",
255 __FILE__, __LINE__, inputGain, strerror(errno));
259 else if (devMask & SOUND_MASK_RECLEV) {
260 if (ioctl(mixerFD, SOUND_MIXER_WRITE_RECLEV, &inputGain) < 0) {
262 "%s %d: mixer record level to %d: %s\n",
263 __FILE__, __LINE__, inputGain, strerror(errno));
269 "%s %d: can't set input gain/recording level for this device.\n",
277 fprintf(stderr,
"calloc(%ld) failed\n",
sizeof(
ad_rec_t));
281 handle->dspFD = dspFD;
282 handle->recording = 0;
284 handle->bps =
sizeof(int16);
304 if (handle->dspFD < 0)
305 return AD_ERR_NOT_OPEN;
307 if (handle->recording) {
308 if (ad_stop_rec(handle) < 0)
312 close(handle->dspFD);
321 if (handle->dspFD < 0)
322 return AD_ERR_NOT_OPEN;
324 if (handle->recording)
333 handle->recording = 1;
343 if (handle->dspFD < 0)
344 return AD_ERR_NOT_OPEN;
346 if (!handle->recording)
349 if (ioctl(handle->dspFD, SNDCTL_DSP_SYNC, 0) < 0) {
350 fprintf(stderr,
"Audio ioctl(SYNC) failed: %s\n", strerror(errno));
354 handle->recording = 0;
360 ad_read(
ad_rec_t * handle, int16 * buf, int32 max)
364 length = max * handle->bps;
366 if ((length = read(handle->dspFD, buf, length)) > 0) {
368 if ((length % handle->bps) != 0)
370 "Audio read returned non-integral #sample bytes (%d)\n",
373 length /= handle->bps;
377 if (errno != EAGAIN) {
378 fprintf(stderr,
"Audio read error");
386 if ((length == 0) && (!handle->recording))
Audio recording structure.
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.
Audio recording structure.