Julius 4.2
libsent/src/adin/adin_mic_freebsd.c
説明を見る。
00001 
00045 /*
00046  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00047  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00048  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00049  * All rights reserved
00050  */
00051 
00052 /* Thanks to Kentaro Nagatomo for information */
00053 /* All functions are the same as OSS version, except the header filename */
00054 
00055 #include <sent/stddefs.h>
00056 #include <sent/adin.h>
00057 
00058 #include <sys/ioctl.h>
00059 #include <sys/types.h>
00060 #include <sys/stat.h>
00061 #include <fcntl.h>
00062 #include <poll.h>
00063 
00064 /* sound header */
00065 #if defined(HAVE_SYS_SOUNDCARD_H)
00066 #include <sys/soundcard.h>
00067 #elif defined(HAVE_MACHINE_SOUNDCARD_H)
00068 #include <machine/soundcard.h>
00069 #endif
00070 
00072 #define DEFAULT_DEVICE "/dev/dsp"
00073 
00074 static int srate;               
00075 static int audio_fd;            
00076 static boolean need_swap;       
00077 struct pollfd fds[1];           
00078 
00079 #define FREQALLOWRANGE 200      ///< Acceptable width of sampling frequency
00080 #define POLLINTERVAL 200        ///< Polling interval in miliseconds
00081 
00082 static char *defaultdev = DEFAULT_DEVICE; 
00083 static char devname[MAXPATHLEN];                
00084 
00093 boolean
00094 adin_mic_standby(int sfreq, void *arg)
00095 {
00096   /* store required sampling rate for checking after opening device */
00097   srate = sfreq;
00098   return TRUE;
00099 }
00100 
00108 static boolean
00109 adin_mic_open(char *devstr)
00110 {
00111   int fmt, fmt_can, fmt1, fmt2, rfmt; /* sampling format */
00112   int samplerate;               /* actual sampling rate */
00113   int stereo;           /* mono */
00114   char *p;
00115 
00116   /* open device */
00117   if ((audio_fd = open(devstr, O_RDONLY)) == -1) {
00118     jlog("Error: adin_freebsd: failed to open %s\n", devstr);
00119     return(FALSE);
00120   }
00121 
00122   /* check whether soundcard can record 16bit data */
00123   /* and set fmt */
00124   if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt_can) == -1) {
00125     jlog("Error: adin_freebsd: failed to get formats from audio device\n");
00126     return(FALSE);
00127   }
00128 #ifdef WORDS_BIGENDIAN
00129   fmt1 = AFMT_S16_BE;
00130   fmt2 = AFMT_S16_LE;
00131 #else
00132   fmt1 = AFMT_S16_LE;               /* 16bit signed (little endian) */
00133   fmt2 = AFMT_S16_BE;               /* (big endian) */
00134 #endif /* WORDS_BIGENDIAN */
00135   /* fmt2 needs byte swap */
00136   if (fmt_can & fmt1) {
00137     fmt = fmt1;
00138     need_swap = FALSE;
00139   } else if (fmt_can & fmt2) {
00140     fmt = fmt2;
00141     need_swap = TRUE;
00142   } else {
00143     jlog("Error: adin_freebsd: 16bit recording not supported on this device\n");
00144     return FALSE;
00145   }
00146 #ifdef DEBUG
00147   if (need_swap) {
00148     jlog("Stat: adin_freebsd: samples need swap\n");
00149   } else {
00150     jlog("Stat: adin_freebsd: samples need not swap\n");
00151   }
00152 #endif
00153   
00154   if (close(audio_fd) != 0) return FALSE;
00155 
00156   /* re-open for recording */
00157   /* open device */
00158   if ((audio_fd = open(devstr, O_RDONLY)) == -1) {
00159     jlog("Error: adin_freebsd: failed to open %s", devstr);
00160     return(FALSE);
00161   }
00162   /* set format, samplerate, channels */
00163   rfmt = fmt;
00164   if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rfmt) == -1) {
00165     jlog("Error: adin_freebsd: failed to get available formats from device\n");
00166     return(FALSE);
00167   }
00168   if (rfmt != fmt) {
00169     jlog("Error: adin_freebsd: 16bit recording is not supported on this device\n");
00170     return FALSE;
00171   }
00172 
00173   stereo = 0;                   /* mono */
00174   if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) {
00175     jlog("Error: adin_freebsd: failed to set monoral recording\n");
00176     return(FALSE);
00177   }
00178   if (stereo != 0) {
00179     jlog("Error: adin_freebsd: monoral recording not supported on this device\n");
00180     return FALSE;
00181   }
00182 
00183   samplerate = srate;
00184   if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &samplerate) == -1) {
00185     jlog("Erorr: adin_freebsd: failed to set sample rate to %dHz\n", srate);
00186     return(FALSE);
00187   }
00188   if (samplerate < srate - FREQALLOWRANGE || samplerate > srate + FREQALLOWRANGE) {
00189     jlog("Error: adin_freebsd: failed to set sampling rate to near %dHz. (%d)\n", srate, samplerate);
00190     return FALSE;
00191   }
00192   if (samplerate != srate) {
00193     jlog("Warning: adin_freebsd: specified sampling rate was %dHz but set to %dHz, \n", srate, samplerate);
00194   }
00195 
00196   /* set polling status */
00197   fds[0].fd = audio_fd;
00198   fds[0].events = POLLIN;
00199   
00200   return TRUE;
00201 }
00202 
00203 
00211 boolean
00212 adin_mic_begin(char *pathname)
00213 {
00214   /* set device name */
00215   if (pathname != NULL) {
00216     strncpy(devname, pathname, MAXPATHLEN);
00217     jlog("Stat: adin_freebsd: device name = %s (from argument)\n", devname);
00218   } else if ((p = getenv("AUDIODEV")) != NULL) {
00219     strncpy(devname, p, MAXPATHLEN);
00220     jlog("Stat: adin_freebsd: device name = %s (from AUDIODEV)\n", devname);
00221   } else {
00222     strncpy(devname, defaultdev, MAXPATHLEN);
00223     jlog("Stat: adin_freebsd: device name = %s (application default)\n", devname);
00224   }
00225 
00226   /* open the device */
00227   return(adin_mic_open(devname));
00228 }
00229 
00235 boolean
00236 adin_mic_end()
00237 {
00238   if (close(audio_fd) != 0) return FALSE;
00239   return TRUE;
00240 }
00241 
00254 int
00255 adin_mic_read(SP16 *buf, int sampnum)
00256 {
00257   int size,cnt;
00258   audio_buf_info info;
00259 
00260   /* wait till at least one sample can be read */
00261   poll(fds, 1, POLLINTERVAL);
00262   /* get actual sample num in the device buffer */
00263   if (ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
00264     jlog("Error: adin_freebsd: adin_mic_read: sndctl_dsp_getispace");
00265     return(-2);
00266   }
00267   
00268   /* get them as much as possible */
00269   size = sampnum * sizeof(SP16);
00270   if (size > info.bytes) size = info.bytes;
00271   cnt = read(audio_fd, buf, size);
00272   if ( cnt < 0 ) {
00273     jlog("Error: adin_freebsd: adin_mic_read: read error\n");
00274     return ( -2 );
00275   }
00276   cnt /= sizeof(short);
00277   if (need_swap) swap_sample_bytes(buf, cnt);
00278   return(cnt);
00279 }
00280 
00288 char *
00289 adin_mic_input_name()
00290 {
00291   return(devname);
00292 }