00001
00057
00058
00059
00060
00061
00062
00063
00064 #include <sent/stddefs.h>
00065 #include <sent/adin.h>
00066
00067 #include <sys/ioctl.h>
00068 #include <sys/types.h>
00069 #include <sys/stat.h>
00070 #include <sys/time.h>
00071 #include <fcntl.h>
00072
00073
00074 #include <sys/soundcard.h>
00075
00077 #define DEFAULT_DEVICE "/dev/dsp"
00078
00079 #define FREQALLOWRANGE 200
00080 #define MAXPOLLINTERVAL 300
00081
00088 #define MAX_FRAGMENT_MSEC 50
00089
00093 #define MIN_FRAGMENT_SIZE 256
00094
00095 static int audio_fd;
00096 static boolean need_swap;
00097 static int frag_size;
00098 static boolean stereo_rec;
00099
00108 boolean
00109 adin_mic_standby(int sfreq, void *dummy)
00110 {
00111 int fmt, fmt_can, fmt1, fmt2, rfmt;
00112 int samplerate;
00113 char *defaultdev = DEFAULT_DEVICE;
00114 char *devname;
00115 int frag;
00116 int frag_msec;
00117 char *env;
00118
00119
00120 if ((devname = getenv("AUDIODEV")) == NULL) {
00121 devname = defaultdev;
00122 jlog("Stat: adin_oss: device name = %s\n", devname);
00123 } else {
00124 jlog("Stat: adin_oss: device name obtained from AUDIODEV: %s\n", devname);
00125 }
00126
00127
00128 if ((audio_fd = open(devname, O_RDONLY|O_NONBLOCK)) == -1) {
00129 jlog("Error: adin_oss: failed to open %s\n", devname);
00130 return(FALSE);
00131 }
00132
00133
00134
00135 if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt_can) == -1) {
00136 jlog("Error: adin_oss: failed to get formats from audio device\n");
00137 return(FALSE);
00138 }
00139 #ifdef WORDS_BIGENDIAN
00140 fmt1 = AFMT_S16_BE;
00141 fmt2 = AFMT_S16_LE;
00142 #else
00143 fmt1 = AFMT_S16_LE;
00144 fmt2 = AFMT_S16_BE;
00145 #endif
00146
00147 if (fmt_can & fmt1) {
00148 fmt = fmt1;
00149 need_swap = FALSE;
00150 } else if (fmt_can & fmt2) {
00151 fmt = fmt2;
00152 need_swap = TRUE;
00153 } else {
00154 jlog("Error: adin_oss: 16bit recording not supported on this device\n");
00155 return FALSE;
00156 }
00157 #ifdef DEBUG
00158 if (need_swap) {
00159 jlog("Stat: adin_oss: samples need swap\n");
00160 } else {
00161 jlog("Stat: adin_oss: samples need not swap\n");
00162 }
00163 #endif
00164
00165 if (close(audio_fd) != 0) return FALSE;
00166
00167
00168
00169 if ((audio_fd = open(devname, O_RDONLY)) == -1) {
00170 jlog("Error: adin_oss: failed to open %s", devname);
00171 return(FALSE);
00172 }
00173
00174
00175
00176
00177 {
00178 int arg;
00179 int f, f2;
00180
00181
00182
00183 if ((env = getenv("LATENCY_MSEC")) == NULL) {
00184 frag_msec = MAX_FRAGMENT_MSEC;
00185 } else {
00186 frag_msec = atoi(env);
00187 }
00188
00189
00190 f = 0;
00191 f2 = 1;
00192 while (f2 * 1000 / (sfreq * sizeof(SP16)) <= frag_msec
00193 || f2 < MIN_FRAGMENT_SIZE) {
00194 f++;
00195 f2 *= 2;
00196 }
00197 frag = f - 1;
00198
00199
00200 arg = 0x7fff0000 | frag;
00201 if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg)) {
00202 jlog("Stat: adin_oss: set fragment size to 2^%d=%d bytes (%d msec)\n", frag, 2 << (frag-1), (2 << (frag-1)) * 1000 / (sfreq * sizeof(SP16)));
00203 }
00204 }
00205
00206
00207 rfmt = fmt;
00208 if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rfmt) == -1) {
00209 jlog("Error: adin_oss: failed to get available formats from device\n");
00210 return(FALSE);
00211 }
00212 if (rfmt != fmt) {
00213 jlog("Error: adin_oss: 16bit recording is not supported on this device\n");
00214 return FALSE;
00215 }
00216
00217 {
00218
00219 int channels;
00220 int stereo;
00221 boolean ok_p = FALSE;
00222
00223 stereo = 0;
00224 if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
00225
00226 jlog("Stat: adin_oss: sndctl_dsp_stereo not supported, going to try another...\n");
00227 } else {
00228 if (stereo != 0) {
00229
00230 jlog("Stat: adin_oss: failed to set monaural recording by sndctl_dsp_stereo\n");
00231 jlog("Stat: adin_oss: going to try another...\n");
00232 } else {
00233
00234
00235 stereo_rec = FALSE;
00236 ok_p = TRUE;
00237 }
00238 }
00239 if (! ok_p) {
00240
00241 channels = 1;
00242 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
00243
00244 jlog("Stat: adin_oss: sndctl_dsp_channels not supported, try another...\n");
00245 } else {
00246 if (channels != 1) {
00247
00248 jlog("Stat: adin_oss: failed to set monaural recording by sndctl_dsp_channels\n");
00249 jlog("Stat: adin_oss: going to try another...\n");
00250 } else {
00251
00252
00253 stereo_rec = FALSE;
00254 ok_p = TRUE;
00255 }
00256 }
00257 }
00258 if (! ok_p) {
00259
00260 jlog("Warning: adin_oss: failed to setup monaural recording, trying to use the left channel of stereo input\n");
00261 stereo = 1;
00262 if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
00263
00264 jlog("Stat: adin_oss: failed to set stereo input using sndctl_dsp_stereo\n");
00265 } else {
00266 if (stereo != 1) {
00267
00268 jlog("Stat: adin_oss: failed to set stereo input using sndctl_dsp_stereo\n");
00269 } else {
00270
00271 jlog("Stat: adin_oss: recording now set to stereo, using left channel\n");
00272 stereo_rec = TRUE;
00273 ok_p = TRUE;
00274 }
00275 }
00276 }
00277 if (! ok_p) {
00278
00279 channels = 2;
00280 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
00281
00282 jlog("Stat: adin_oss: failed to set stereo input using sndctl_dsp_channels\n");
00283 } else {
00284 if (channels != 2) {
00285
00286 jlog("Stat: adin_oss: failed to set stereo input using sndctl_dsp_channels\n");
00287 } else {
00288
00289 jlog("Stat: adin_oss: recording now set to stereo, using left channel\n");
00290 stereo_rec = TRUE;
00291 ok_p = TRUE;
00292 }
00293 }
00294 }
00295 if (! ok_p) {
00296 jlog("Error: adin_oss: failed to setup recording channels\n");
00297 return FALSE;
00298 }
00299 }
00300
00301 samplerate = sfreq;
00302 if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &samplerate) == -1) {
00303 jlog("Erorr: adin_oss: failed to set sample rate to %dHz\n", sfreq);
00304 return(FALSE);
00305 }
00306 if (samplerate < sfreq - FREQALLOWRANGE || samplerate > sfreq + FREQALLOWRANGE) {
00307 jlog("Error: adin_oss: failed to set sampling rate to near %dHz. (%d)\n", sfreq, samplerate);
00308 return FALSE;
00309 }
00310 if (samplerate != sfreq) {
00311 jlog("Warning: adin_oss: specified sampling rate was %dHz but set to %dHz, \n", sfreq, samplerate);
00312 }
00313 jlog("Stat: adin_oss: sampling rate = %dHz\n", samplerate);
00314
00315
00316 if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
00317 jlog("Error: adin_oss: failed to get fragment size\n");
00318 return(FALSE);
00319 }
00320 if (env == NULL) {
00321 jlog("Stat: adin_oss: going to set latency to %d msec\n", frag_msec);
00322 } else {
00323 jlog("Stat: adin_oss: going to set latency to %d msec (from env LATENCY_MSEC)\n", frag_msec);
00324 }
00325 jlog("Stat: adin_oss: audio I/O Latency = %d msec (fragment size = %d samples)\n", frag_size * 1000/ (sfreq * sizeof(SP16)), frag_size / sizeof(SP16));
00326
00327 return TRUE;
00328 }
00329
00335 boolean
00336 adin_mic_begin()
00337 {
00338 char buf[4];
00339
00340
00341 if (stereo_rec) {
00342 read(audio_fd, buf, 4);
00343 } else {
00344 read(audio_fd, buf, 2);
00345 }
00346 return(TRUE);
00347 }
00348
00354 boolean
00355 adin_mic_end()
00356 {
00357
00358
00359
00360
00361
00362
00363 return TRUE;
00364 }
00365
00383 int
00384 adin_mic_read(SP16 *buf, int sampnum)
00385 {
00386 int size,cnt,i;
00387 audio_buf_info info;
00388 fd_set rfds;
00389 struct timeval tv;
00390 int status;
00391
00392
00393
00394
00395
00396 FD_ZERO(&rfds);
00397 FD_SET(audio_fd, &rfds);
00398 tv.tv_sec = 0;
00399 tv.tv_usec = MAXPOLLINTERVAL * 1000;
00400 status = select(audio_fd+1, &rfds, NULL, NULL, &tv);
00401 if (status < 0) {
00402
00403 jlog("Error: adin_oss: failed to poll device\n");
00404 return(-2);
00405 }
00406 if (FD_ISSET(audio_fd, &rfds)) {
00407
00408 if (ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
00409 jlog("Error: adin_oss: failed to get number of samples in the buffer\n");
00410 return(-2);
00411 }
00412
00413 size = sampnum * sizeof(SP16);
00414 if (size > info.bytes) size = info.bytes;
00415 if (size < frag_size) size = frag_size;
00416 size &= ~ 1;
00417 cnt = read(audio_fd, buf, size);
00418 if ( cnt < 0 ) {
00419 jlog("Error: adin_oss: failed to read samples\n");
00420 return ( -2 );
00421 }
00422 cnt /= sizeof(short);
00423
00424 if (stereo_rec) {
00425
00426 for(i=1;i<cnt;i+=2) buf[(i-1)/2]=buf[i];
00427 cnt/=2;
00428 }
00429
00430 if (need_swap) swap_sample_bytes(buf, cnt);
00431 } else {
00432 jlog("Warning: adin_oss: no data fragment after %d msec?\n", MAXPOLLINTERVAL);
00433 cnt = 0;
00434 }
00435
00436 return(cnt);
00437 }