Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

adin_mic_linux_oss.c

Go to the documentation of this file.
00001 
00056 /*
00057  * Copyright (c) 1991-2006 Kawahara Lab., Kyoto University
00058  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00059  * Copyright (c) 2005-2006 Julius project team, Nagoya Institute of Technology, Nagoya Institute of Technology
00060  * All rights reserved
00061  */
00062 
00063 #include <sent/stddefs.h>
00064 #include <sent/adin.h>
00065 
00066 #include <sys/ioctl.h>
00067 #include <sys/types.h>
00068 #include <sys/stat.h>
00069 #include <sys/time.h>
00070 #include <fcntl.h>
00071 
00072 /* sound header */
00073 #include <sys/soundcard.h>
00074 
00076 #define DEFAULT_DEVICE "/dev/dsp"
00077 
00078 #define FREQALLOWRANGE 200      
00079 #define MAXPOLLINTERVAL 300     
00080 
00086 #define FRAGMENT_POWER 10
00087 
00088 static int audio_fd;            
00089 static boolean need_swap;       
00090 static int frag_size;           
00091 static boolean stereo_rec;      
00092 
00101 boolean
00102 adin_mic_standby(int sfreq, void *dummy)
00103 {
00104   int fmt, fmt_can, fmt1, fmt2, rfmt; /* sampling format */
00105   int samplerate;       /* 16kHz */
00106   char *defaultdev = DEFAULT_DEVICE; /* default device */
00107   char *devname;
00108 
00109   /* set device name */
00110   if ((devname = getenv("AUDIODEV")) == NULL) {
00111     devname = defaultdev;
00112   }
00113 
00114   /* open device */
00115   if ((audio_fd = open(devname, O_RDONLY|O_NONBLOCK)) == -1) {
00116     j_printerr("adin_mic_standby: device=%s\n", devname);
00117     perror("adin_mic_standby: open device");
00118     return(FALSE);
00119   }
00120 
00121   /* check whether soundcard can record 16bit data */
00122   /* and set fmt */
00123   if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt_can) == -1) {
00124     perror("adin_mic_standby: sndctl_dsp_getfmts");
00125     return(FALSE);
00126   }
00127 #ifdef WORDS_BIGENDIAN
00128   fmt1 = AFMT_S16_BE;
00129   fmt2 = AFMT_S16_LE;
00130 #else
00131   fmt1 = AFMT_S16_LE;               /* 16bit signed (little endian) */
00132   fmt2 = AFMT_S16_BE;               /* (big endian) */
00133 #endif /* WORDS_BIGENDIAN */
00134   /* fmt2 needs byte swap */
00135   if (fmt_can & fmt1) {
00136     fmt = fmt1;
00137     need_swap = FALSE;
00138   } else if (fmt_can & fmt2) {
00139     fmt = fmt2;
00140     need_swap = TRUE;
00141   } else {
00142     fprintf(stderr, "adin_mic_standby: 16bit recording not supported\n");
00143     return FALSE;
00144   }
00145 #ifdef DEBUG
00146   if (need_swap) {
00147     j_printf("samples need swap\n");
00148   } else {
00149     j_printf("samples need not swap\n");
00150   }
00151 #endif
00152   
00153   if (close(audio_fd) != 0) return FALSE;
00154 
00155   /* re-open for recording */
00156   /* open device */
00157   if ((audio_fd = open(devname, O_RDONLY)) == -1) {
00158     j_printerr("adin_mic_standby: device=%s\n", devname);
00159     perror("adin_mic_standby: open device");
00160     return(FALSE);
00161   }
00162 
00163   /* try to set a small fragment size to minimize delay, */
00164   /* although many devices use static fragment size... */
00165   /* (and smaller fragment causes busy buffering) */
00166   {
00167     int arg;
00168     arg = 0x7fff0000 | FRAGMENT_POWER;
00169     if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &arg)) {
00170       fprintf(stderr, "adin_mic_standby: set fragment size to 2^%d=%d bytes (%d msec)\n", FRAGMENT_POWER, 2 << (FRAGMENT_POWER-1), (2 << (FRAGMENT_POWER-1)) * 1000 / (sfreq * sizeof(SP16)));
00171     }
00172   }
00173   
00174   /* set format, samplerate, channels */
00175   rfmt = fmt;
00176   if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rfmt) == -1) {
00177     perror("adin_mic_standby: sndctl_dsp_setfmt");
00178     return(FALSE);
00179   }
00180   if (rfmt != fmt) {
00181     fprintf(stderr, "adin_mic_standby: 16bit recording not supported\n");
00182     return FALSE;
00183   }
00184 
00185   {
00186     /* try SNDCTL_DSP_STEREO, SNDCTL_DSP_CHANNELS, monaural, stereo */
00187     int channels;
00188     int stereo;
00189     boolean ok_p = FALSE;
00190 
00191     stereo = 0;                 /* mono */
00192     if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
00193       /* failed: SNDCTL_DSP_STEREO not supported */
00194       perror("adin_mic_standby: sndctl_dsp_stereo (mono)");
00195     } else {
00196       if (stereo != 0) {
00197         /* failed to set monaural recording by SNDCTL_DSP_STEREO */
00198         fprintf(stderr, "adin_mic_standby: failed to set monaural recording by SNDCTL_DSP_STEREO\n");
00199       } else {
00200         /* succeeded to set monaural recording by SNDCTL_DSP_STEREO */
00201         stereo_rec = FALSE;
00202         ok_p = TRUE;
00203       }
00204     }
00205     if (! ok_p) {               /* not setup yet */
00206       /* try using sndctl_dsp_channels */
00207       channels = 1;
00208       if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
00209         /* failed: SNDCTL_DSP_CHANNELS not supported */
00210         perror("adin_mic_standby: sndctl_dsp_channels (channels = 1)");
00211       } else {
00212         if (channels != 1) {
00213           /* failed to set monaural recording by SNDCTL_DSP_CHANNELS */
00214           fprintf(stderr, "adin_mic_standby: failed to set monaural recording by SNDCTL_DSP_CHANNELS\n");
00215         } else {
00216           /* succeeded to set monaural recording by SNDCTL_DSP_CHANNELS */
00217           fprintf(stderr, "adin_mic_standby: SNDCTL_DSP_CHANNELS used for monaural record setting\n");
00218           stereo_rec = FALSE;
00219           ok_p = TRUE;
00220         }
00221       }
00222     }
00223     if (! ok_p) {
00224       /* try using stereo input */
00225       fprintf(stderr, "adin_mic_standby: monaural recording failed, use stereo left channel\n");
00226       stereo = 1;                       /* stereo */
00227       if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
00228         /* failed: SNDCTL_DSP_STEREO not supported */
00229         perror("adin_mic_standby: sndctl_dsp_stereo (stereo)");
00230       } else {
00231         if (stereo != 1) {
00232           /* failed to set stereo recording by SNDCTL_DSP_STEREO */
00233           fprintf(stderr, "adin_mic_standby: failed to set stereo recording by SNDCTL_DSP_STEREO\n");
00234         } else {
00235           /* succeeded to set stereo recording by SNDCTL_DSP_STEREO */
00236           stereo_rec = TRUE;
00237           ok_p = TRUE;
00238         }
00239       }
00240     }
00241     if (! ok_p) {               /* not setup yet */
00242       /* try using stereo input with sndctl_dsp_channels */
00243       channels = 2;
00244       if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {
00245         /* failed: SNDCTL_DSP_CHANNELS not supported */
00246         perror("adin_mic_standby: sndctl_dsp_channels (channels = 2)");
00247       } else {
00248         if (channels != 2) {
00249           /* failed to set stereo recording by SNDCTL_DSP_CHANNELS */
00250           fprintf(stderr, "adin_mic_standby: failed to set stereo recording by SNDCTL_DSP_CHANNELS\n");
00251         } else {
00252           /* succeeded to set stereo recording by SNDCTL_DSP_CHANNELS */
00253           fprintf(stderr, "adin_mic_standby: SNDCTL_DSP_CHANNELS used for stereo record setting\n");
00254           stereo_rec = TRUE;
00255           ok_p = TRUE;
00256         }
00257       }
00258     }
00259     if (! ok_p) {               /* all failed */
00260       fprintf(stderr,"adin_mic_standby: give up setting record channels\n");
00261       return FALSE;
00262     }
00263   }
00264 
00265   samplerate = sfreq;
00266   if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &samplerate) == -1) {
00267     fprintf(stderr, "adin_mic_standby: sndctl_dsp_speed (%dHz)\n", sfreq);
00268     return(FALSE);
00269   }
00270   if (samplerate < sfreq - FREQALLOWRANGE || samplerate > sfreq + FREQALLOWRANGE) {
00271     fprintf(stderr,"adin_mic_standby: couldn't set sampling rate to near %dHz. (%d)\n", sfreq, samplerate);
00272     return FALSE;
00273   }
00274   if (samplerate != sfreq) {
00275     fprintf(stderr,"adin_mic_standby: set sampling rate to %dHz\n", samplerate);
00276   }
00277 
00278   /* get actual fragment size */
00279   if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1) {
00280     fprintf(stderr, "adin_mic_standby: failed to get fragment size\n");
00281     return(FALSE);
00282   }
00283   j_printf("fragment size = %d bytes (%d msec)", frag_size, frag_size * 1000/ (sfreq * sizeof(SP16)));
00284   if (frag_size !=  2 << (FRAGMENT_POWER-1)) {
00285     j_printf(" (tried = %d bytes)", 2 << (FRAGMENT_POWER-1));
00286   }
00287   j_printf("\n");
00288 
00289   return TRUE;
00290 }
00291  
00297 boolean
00298 adin_mic_start()
00299 {
00300   char buf[4];
00301   /* Read 1 sample (and ignore it) to tell the audio device start recording.
00302      (If you knows better way, teach me...) */
00303   if (stereo_rec) {
00304     read(audio_fd, buf, 4);
00305   } else {
00306     read(audio_fd, buf, 2);
00307   }
00308 
00309   return(TRUE);
00310 }
00311 
00317 boolean
00318 adin_mic_stop()
00319 {
00320   /*
00321    * Not reset device on each end of speech, just let the buffer overrun...
00322    * Resetting and restarting of recording device sometimes causes
00323    * hawling noises at the next recording.
00324    * I don't now why, so take the easy way... :-(
00325    */
00326   return TRUE;
00327 }
00328 
00346 int
00347 adin_mic_read(SP16 *buf, int sampnum)
00348 {
00349   int size,cnt,i;
00350   audio_buf_info info;
00351   fd_set rfds;
00352   struct timeval tv;
00353   int status;
00354 
00355   /* check for incoming samples in device buffer */
00356   /* if there is at least one sample fragment, go next */
00357   /* if not exist, wait for the data to come for at most MAXPOLLINTERVAL msec */
00358   /* if no sample fragment has come in the MAXPOLLINTERVAL period, go next */
00359   FD_ZERO(&rfds);
00360   FD_SET(audio_fd, &rfds);
00361   tv.tv_sec = 0;
00362   tv.tv_usec = MAXPOLLINTERVAL * 1000;
00363   status = select(audio_fd+1, &rfds, NULL, NULL, &tv);
00364   if (status < 0) {
00365     /* select() failed */
00366     j_printerr("adin_mic_read: device polling failed\n");
00367     return(-2);                 /* error */
00368   }
00369   if (FD_ISSET(audio_fd, &rfds)) { /* has some data */
00370     /* get sample num that can be read without blocking */
00371     if (ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
00372       perror("adin_mic_read: sndctl_dsp_getispace");
00373       return(-2);
00374     }
00375     /* get them as much as possible */
00376     size = sampnum * sizeof(SP16);
00377     if (size > info.bytes) size = info.bytes;
00378     if (size < frag_size) size = frag_size;
00379     size &= ~ 1;                /* Force 16bit alignment */
00380     cnt = read(audio_fd, buf, size);
00381     if ( cnt < 0 ) {
00382       perror("adin_mic_read: read error\n");
00383       return ( -2 );
00384     }
00385     cnt /= sizeof(short);
00386 
00387     if (stereo_rec) {
00388       /* remove R channel */
00389       for(i=1;i<cnt;i+=2) buf[(i-1)/2]=buf[i];
00390       cnt/=2;
00391     }
00392     
00393     if (need_swap) swap_sample_bytes(buf, cnt);
00394   } else {                      /* no data after waiting */
00395     j_printerr("adin_mic_read: no data fragment after %d msec?\n", MAXPOLLINTERVAL);
00396     cnt = 0;
00397   }
00398 
00399   return(cnt);
00400 }

Generated on Tue Mar 28 16:01:39 2006 for Julius by  doxygen 1.4.2