66 #ifdef SUPPORT_FREEBSD16 67 #include <sys/soundcard.h> 71 static char *aud_sys_name =
"FreeBSD";
74 #ifdef SUPPORT_VOXWARE 76 #include <sys/ioctl.h> 77 #include <sys/soundcard.h> 78 #include <sys/types.h> 83 static const char *aud_sys_name =
"Linux";
84 static int stereo_only = 0;
90 #if defined(SUPPORT_LINUX16) || defined(SUPPORT_FREEBSD16) 95 #define THREAD_DECS() \ 98 #define THREAD_PROTECT() do { \ 101 sigfillset(&newmask); \ 103 pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); \ 106 #define THREAD_UNPROTECT() do { \ 107 pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \ 111 #define THREAD_DECS() //empty 112 #define THREAD_PROTECT() //empty 113 #define THREAD_UNPROTECT() //empty 116 static int sb_set_sample_rate(
int sbdevice,
int samp_rate)
124 ioctl(sbdevice,SNDCTL_DSP_RESET,0);
125 ioctl(sbdevice,SNDCTL_DSP_SPEED,&samp_rate);
127 ioctl(sbdevice,SNDCTL_DSP_STEREO,&sstereo);
129 if (sstereo != stereo)
131 ioctl(sbdevice,SNDCTL_DSP_CHANNELS,&channels);
132 ioctl(sbdevice,SNDCTL_DSP_GETFMTS,&sfmts);
134 if (sfmts == AFMT_U8)
141 ioctl(sbdevice,SNDCTL_DSP_SETFMT,&fmt);
146 #define AUDIOBUFFSIZE 256 153 short *waveform2 = 0;
155 int audio,actual_fmt;
157 const char *audiodevice;
159 if (al.
present(
"-audiodevice"))
160 audiodevice = al.
val(
"-audiodevice");
162 audiodevice =
"/dev/dsp";
164 if ((audio =
open(audiodevice,O_WRONLY)) == -1)
166 cerr << aud_sys_name <<
": can't open " << audiodevice << endl;
176 actual_fmt = sb_set_sample_rate(audio,sample_rate);
180 waveform2 =
walloc(
short,num_samples*2);
181 for (i=0; i<num_samples; i++)
183 waveform2[i*2] = inwave.
a(i);
184 waveform2[(i*2)+1] = inwave.
a(i);
186 waveform = waveform2;
193 if (sb_set_sample_rate(audio,sample_rate) == AFMT_U8)
196 unsigned char *uchars =
walloc(
unsigned char,num_samples);
197 for (i=0; i < num_samples; i++)
198 uchars[i] = waveform[i]/256+128;
199 for (i=0; i < num_samples; i += r)
201 if (num_samples > i+AUDIOBUFFSIZE)
206 r = write(audio,&uchars[i], n);
210 cerr << aud_sys_name <<
": failed to write to buffer" <<
218 else if ((actual_fmt == AFMT_S16_LE) ||
219 (actual_fmt == AFMT_S16_BE))
221 int blksize, nbuf, c;
224 ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &blksize);
228 for (i=0; i < num_samples; i += r/2)
230 if (num_samples > i+nbuf)
236 buf[c]=waveform[c+i];
239 buf[c]=waveform[n-1];
243 r=write(audio, buf, nbuf*2);
247 EST_warning(
"%s: failed to write to buffer (sr=%d)",aud_sys_name, sample_rate );
260 cerr << aud_sys_name <<
": unable to set sample rate " <<
263 if (waveform2 != waveform)
282 int sample_rate=16000;
286 int audio=-1,actual_fmt;
288 const char *audiodevice;
290 if (al.
present(
"-audiodevice"))
291 audiodevice = al.
val(
"-audiodevice");
293 audiodevice =
"/dev/dsp";
295 sample_rate = al.
ival(
"-sample_rate");
297 if ((audio =
open(audiodevice,O_RDONLY)) == -1)
299 cerr << aud_sys_name <<
": can't open " << audiodevice
300 <<
"for reading" << endl;
304 actual_fmt = sb_set_sample_rate(audio,sample_rate);
306 if ((actual_fmt == AFMT_S16_LE) ||
307 (actual_fmt == AFMT_S16_BE))
311 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
318 waveform2 =
walloc(
short,num_samples*2);
322 waveform2 = waveform;
324 for (i=0; i < num_samples; i+= r)
326 if (num_samples > i+AUDIOBUFFSIZE)
330 r = read(audio,&waveform2[i], n*2);
334 cerr << aud_sys_name <<
": failed to read from audio device" 343 else if (actual_fmt == AFMT_U8)
345 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
349 unsigned char *u8wave =
walloc(
unsigned char,num_samples);
351 for (i=0; i < num_samples; i+= r)
353 if (num_samples > i+AUDIOBUFFSIZE)
357 r = read(audio,&u8wave[i],n);
360 cerr << aud_sys_name <<
": failed to read from audio device" 373 cerr << aud_sys_name <<
": unknown audio format from device: " <<
381 for (i=0; i<num_samples; i+=2)
382 waveform[i/2] = waveform2[i];
401 #ifdef SUPPORT_ALSALINUX 402 #include <sys/ioctl.h> 403 #include <alsa/asoundlib.h> 404 #include <sys/types.h> 405 #include <sys/stat.h> 420 #define THREAD_DECS() \ 423 #define THREAD_PROTECT() do { \ 426 sigfillset(&newmask); \ 428 pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); \ 431 #define THREAD_UNPROTECT() do { \ 432 pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \ 436 #define THREAD_DECS() //empty 437 #define THREAD_PROTECT() //empty 438 #define THREAD_UNPROTECT() //empty 441 static const char *pcm_dev_name =
"default";
444 CST_AUDIO_LINEAR16 = 0,
449 typedef struct cst_audiodev_struct {
451 int channels, real_channels;
452 cst_audiofmt fmt, real_fmt;
458 static int audio_bps(cst_audiofmt fmt)
462 case CST_AUDIO_LINEAR16:
464 case CST_AUDIO_LINEAR8:
465 case CST_AUDIO_MULAW:
471 static inline void print_pcm_state(snd_pcm_t *handle,
char *msg)
473 fprintf(stderr,
"PCM state at %s = %s\n", msg,
474 snd_pcm_state_name(snd_pcm_state(handle)));
477 cst_audiodev *audio_open_alsa(
int sps,
int channels, cst_audiofmt fmt)
480 unsigned int real_rate;
484 snd_pcm_t *pcm_handle;
485 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
486 snd_pcm_hw_params_t *hwparams;
487 snd_pcm_format_t format;
488 snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;
491 snd_pcm_hw_params_alloca(&hwparams);
494 err = snd_pcm_open(&pcm_handle, pcm_dev_name, stream, 0);
497 EST_warning(
"audio_open_alsa: failed to open audio device %s. %s\n",
498 pcm_dev_name, snd_strerror(err));
503 err = snd_pcm_hw_params_any(pcm_handle, hwparams);
506 snd_pcm_close(pcm_handle);
507 EST_warning(
"audio_open_alsa: failed to get hardware parameters from audio device. %s\n", snd_strerror(err));
512 err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, access);
515 snd_pcm_close(pcm_handle);
516 EST_warning(
"audio_open_alsa: failed to set access mode. %s.\n", snd_strerror(err));
525 case CST_AUDIO_LINEAR16:
527 format = SND_PCM_FORMAT_S16_LE;
529 format = SND_PCM_FORMAT_S16_BE;
531 case CST_AUDIO_LINEAR8:
532 format = SND_PCM_FORMAT_U8;
534 case CST_AUDIO_MULAW:
535 format = SND_PCM_FORMAT_MU_LAW;
538 snd_pcm_close(pcm_handle);
539 EST_warning(
"audio_open_alsa: failed to find suitable format.\n");
545 err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format);
548 snd_pcm_close(pcm_handle);
549 EST_warning(
"audio_open_alsa: failed to set format. %s.\n", snd_strerror(err));
555 err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &real_rate, 0);
558 snd_pcm_close(pcm_handle);
559 EST_warning(
"audio_open_alsa: failed to set sample rate near %d. %s.\n", sps, snd_strerror(err));
565 err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels);
568 snd_pcm_close(pcm_handle);
569 EST_warning(
"audio_open_alsa: failed to set number of channels to %d. %s.\n", channels, snd_strerror(err));
574 err = snd_pcm_hw_params(pcm_handle, hwparams);
577 snd_pcm_close(pcm_handle);
578 EST_warning(
"audio_open_alsa: failed to set hw parameters. %s.\n", snd_strerror(err));
583 assert(snd_pcm_state(pcm_handle) == SND_PCM_STATE_PREPARED);
586 ad =
walloc(cst_audiodev, 1);
588 ad->real_sps = ad->sps = sps;
589 ad->real_channels = ad->channels = channels;
590 ad->real_fmt = ad->fmt = fmt;
591 ad->platform_data = (
void *) pcm_handle;
596 int audio_close_alsa(cst_audiodev *ad)
599 snd_pcm_t *pcm_handle;
604 pcm_handle = (snd_pcm_t *) ad->platform_data;
606 snd_pcm_drain(pcm_handle);
608 result = snd_pcm_close(pcm_handle);
611 EST_warning(
"audio_close_alsa: Error: %s.\n", snd_strerror(result));
618 static int recover_from_error(snd_pcm_t *pcm_handle,
ssize_t res)
622 EST_warning(
"xrun has occured. This suggests ALSA buffer is " 623 "underflowing. Possibly change audio output methods " 624 "or use a faster or more lightly loaded device");
625 res = snd_pcm_prepare(pcm_handle);
629 EST_warning(
"recover_from_write_error: failed to recover from xrun. %s\n.", snd_strerror(res));
633 else if (res == -ESTRPIPE)
635 while ((res = snd_pcm_resume(pcm_handle)) == -EAGAIN)
637 snd_pcm_wait(pcm_handle, 1000);
641 res = snd_pcm_prepare(pcm_handle);
645 EST_warning(
"audio_recover_from_write_error: failed to resume after suspend. %s\n.", snd_strerror(res));
653 EST_warning(
"audio_recover_from_write_error: %s.\n", snd_strerror(res));
659 int audio_write_alsa(cst_audiodev *ad,
void *samples,
int num_bytes)
663 snd_pcm_t *pcm_handle;
664 char *buf = (
char *) samples;
667 frame_size = audio_bps(ad->real_fmt) * ad->real_channels;
669 assert((num_bytes % frame_size) == 0);
670 num_frames = num_bytes / frame_size;
671 pcm_handle = (snd_pcm_t *) ad->platform_data;
673 while (num_frames > 0)
675 res = snd_pcm_writei(pcm_handle, buf, num_frames);
676 if (res != num_frames)
678 if (res == -EAGAIN || (res > 0 && res < num_frames))
680 snd_pcm_wait(pcm_handle, 100);
682 else if (recover_from_error(pcm_handle, res) < 0)
691 buf += res * frame_size;
697 int audio_flush_alsa(cst_audiodev *ad)
700 result = snd_pcm_drain((snd_pcm_t *) ad->platform_data);
703 EST_warning(
"audio_flush_alsa: Error: %s.\n", snd_strerror(result));
706 result = snd_pcm_prepare((snd_pcm_t *) ad->platform_data);
709 EST_warning(
"audio_flush_alsa: Error: %s.\n", snd_strerror(result));
714 int audio_drain_alsa(cst_audiodev *ad)
717 result = snd_pcm_drop((snd_pcm_t *) ad->platform_data);
720 EST_warning(
"audio_drain_alsa: Error: %s.\n", snd_strerror(result));
723 result = snd_pcm_prepare((snd_pcm_t *) ad->platform_data);
726 EST_warning(
"audio_drain_alsa: Error: %s.\n", snd_strerror(result));
731 #define AUDIOBUFFSIZE 256 752 ad = audio_open_alsa(sample_rate,1,CST_AUDIO_LINEAR16);
757 audio_write_alsa(ad,waveform,num_samples*
sizeof(
short));
759 audio_close_alsa(ad);
768 int sample_rate=16000;
772 int audio=-1,actual_fmt;
776 if (al.
present(
"-audiodevice"))
777 audiodevice = al.
val(
"-audiodevice");
779 audiodevice =
"/dev/dsp";
781 sample_rate = al.
ival(
"-sample_rate");
783 if ((audio =
open(audiodevice,O_RDONLY)) == -1)
785 cerr << aud_sys_name <<
": can't open " << audiodevice
786 <<
"for reading" << endl;
790 actual_fmt = sb_set_sample_rate(audio,sample_rate);
792 if ((actual_fmt == AFMT_S16_LE) ||
793 (actual_fmt == AFMT_S16_BE))
797 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
804 waveform2 =
walloc(
short,num_samples*2);
808 waveform2 = waveform;
810 for (i=0; i < num_samples; i+= r)
812 if (num_samples > i+AUDIOBUFFSIZE)
816 r = read(audio,&waveform2[i], n*2);
820 cerr << aud_sys_name <<
": failed to read from audio device" 828 else if (actual_fmt == AFMT_U8)
830 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
834 unsigned char *u8wave =
walloc(
unsigned char,num_samples);
836 for (i=0; i < num_samples; i+= r)
838 if (num_samples > i+AUDIOBUFFSIZE)
842 r = read(audio,&u8wave[i],n);
845 cerr << aud_sys_name <<
": failed to read from audio device" 858 cerr << aud_sys_name <<
": unknown audio format from device: " <<
866 for (i=0; i<num_samples; i+=2)
867 waveform[i/2] = waveform2[i];
888 cerr <<
"ALSA audio support not compiled." << endl;
895 cerr <<
"ALSA audio support not compiled." << endl;
A class for storing digital waveforms. The waveform is stored as an array of 16 bit shorts...
void set_sample_rate(const int n)
Set sampling rate to n
#define walloc(TYPE, SIZE)
Utility IO Function header file.
void uchar_to_short(const unsigned char *chars, short *data, int length)
int ival(const EST_String &rkey, int m=1) const
float fval(const EST_String &rkey, int m=1) const
ssize_t num_samples() const
return the number of samples in the waveform
short & a(ssize_t i, ssize_t channel=0)
void err(const char *message, LISP x) EST_NORETURN
const EST_SMatrix & values() const
int play_linux_wave(EST_Wave &inwave, EST_Option &al)
#define EST_LITTLE_ENDIAN
const V & val(const K &rkey, bool m=0) const
return value according to key (const)
void resize(int num_samples, int num_channels=EST_ALL, int set=1)
resize the waveform
int sample_rate() const
return the sampling rate (frequency)
int record_linux_wave(EST_Wave &inwave, EST_Option &al)
int present(const K &rkey) const
Returns true if key is present.
FILE16 *(* open)(const char *, const char *, int, const char *, const char *)