54 #include "EST_cutils.h"
55 #include "EST_walloc.h"
57 #include "EST_wave_aux.h"
58 #include "EST_Option.h"
60 #include "EST_io_aux.h"
61 #include "EST_error.h"
63 #ifdef SUPPORT_FREEBSD16
64 #include <sys/soundcard.h>
66 int freebsd16_supported = TRUE;
67 int linux16_supported = FALSE;
68 static char *aud_sys_name =
"FreeBSD";
71 #ifdef SUPPORT_VOXWARE
73 #include <sys/ioctl.h>
74 #include <sys/soundcard.h>
75 #include <sys/types.h>
78 int linux16_supported = TRUE;
79 int freebsd16_supported = FALSE;
80 static const char *aud_sys_name =
"Linux";
81 static int stereo_only = 0;
87 #if defined(SUPPORT_LINUX16) || defined(SUPPORT_FREEBSD16)
92 #define THREAD_DECS() \
95 #define THREAD_PROTECT() do { \
98 sigfillset(&newmask); \
100 pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); \
103 #define THREAD_UNPROTECT() do { \
104 pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \
108 #define THREAD_DECS() //empty
109 #define THREAD_PROTECT() //empty
110 #define THREAD_UNPROTECT() //empty
113 static int sb_set_sample_rate(
int sbdevice,
int samp_rate)
121 ioctl(sbdevice,SNDCTL_DSP_RESET,0);
122 ioctl(sbdevice,SNDCTL_DSP_SPEED,&samp_rate);
124 ioctl(sbdevice,SNDCTL_DSP_STEREO,&sstereo);
126 if (sstereo != stereo)
128 ioctl(sbdevice,SNDCTL_DSP_CHANNELS,&channels);
129 ioctl(sbdevice,SNDCTL_DSP_GETFMTS,&sfmts);
131 if (sfmts == AFMT_U8)
133 else if (EST_LITTLE_ENDIAN)
138 ioctl(sbdevice,SNDCTL_DSP_SETFMT,&fmt);
143 #define AUDIOBUFFSIZE 256
150 short *waveform2 = 0;
152 int audio,actual_fmt;
154 const char *audiodevice;
156 if (al.
present(
"-audiodevice"))
157 audiodevice = al.
val(
"-audiodevice");
159 audiodevice =
"/dev/dsp";
161 if ((audio = open(audiodevice,O_WRONLY)) == -1)
163 cerr << aud_sys_name <<
": can't open " << audiodevice << endl;
169 waveform = inwave.values().
memory();
173 actual_fmt = sb_set_sample_rate(audio,sample_rate);
177 waveform2 = walloc(
short,num_samples*2);
178 for (i=0; i<num_samples; i++)
180 waveform2[i*2] = inwave.
a(i);
181 waveform2[(i*2)+1] = inwave.
a(i);
183 waveform = waveform2;
190 if (sb_set_sample_rate(audio,sample_rate) == AFMT_U8)
193 unsigned char *uchars = walloc(
unsigned char,num_samples);
194 for (i=0; i < num_samples; i++)
195 uchars[i] = waveform[i]/256+128;
196 for (i=0; i < num_samples; i += r)
198 if (num_samples > i+AUDIOBUFFSIZE)
203 r = write(audio,&uchars[i], n);
207 cerr << aud_sys_name <<
": failed to write to buffer" <<
215 else if ((actual_fmt == AFMT_S16_LE) ||
216 (actual_fmt == AFMT_S16_BE))
218 int blksize, nbuf, c;
221 ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &blksize);
225 for (i=0; i < num_samples; i += r/2)
227 if (num_samples > i+nbuf)
233 buf[c]=waveform[c+i];
236 buf[c]=waveform[n-1];
240 r=write(audio, buf, nbuf*2);
244 EST_warning(
"%s: failed to write to buffer (sr=%d)",aud_sys_name, sample_rate );
256 cerr << aud_sys_name <<
": unable to set sample rate " <<
275 int sample_rate=16000;
279 int audio=-1,actual_fmt;
281 const char *audiodevice;
283 if (al.
present(
"-audiodevice"))
284 audiodevice = al.
val(
"-audiodevice");
286 audiodevice =
"/dev/dsp";
288 sample_rate = al.
ival(
"-sample_rate");
290 if ((audio = open(audiodevice,O_RDONLY)) == -1)
292 cerr << aud_sys_name <<
": can't open " << audiodevice
293 <<
"for reading" << endl;
297 actual_fmt = sb_set_sample_rate(audio,sample_rate);
299 if ((actual_fmt == AFMT_S16_LE) ||
300 (actual_fmt == AFMT_S16_BE))
304 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
307 waveform = inwave.values().
memory();
311 waveform2 = walloc(
short,num_samples*2);
315 waveform2 = waveform;
317 for (i=0; i < num_samples; i+= r)
319 if (num_samples > i+AUDIOBUFFSIZE)
323 r = read(audio,&waveform2[i], n*2);
327 cerr << aud_sys_name <<
": failed to read from audio device"
335 else if (actual_fmt == AFMT_U8)
337 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
340 waveform = inwave.values().
memory();
341 unsigned char *u8wave = walloc(
unsigned char,num_samples);
343 for (i=0; i < num_samples; i+= r)
345 if (num_samples > i+AUDIOBUFFSIZE)
349 r = read(audio,&u8wave[i],n);
352 cerr << aud_sys_name <<
": failed to read from audio device"
360 uchar_to_short(u8wave,waveform,num_samples);
365 cerr << aud_sys_name <<
": unknown audio format from device: " <<
373 for (i=0; i<num_samples; i+=2)
374 waveform[i/2] = waveform2[i];
393 #ifdef SUPPORT_ALSALINUX
394 #include <sys/ioctl.h>
395 #include <alsa/asoundlib.h>
396 #include <sys/types.h>
397 #include <sys/stat.h>
399 static const char *aud_sys_name =
"ALSALINUX";
405 int linux16_supported = TRUE;
406 int freebsd16_supported = FALSE;
412 #define THREAD_DECS() \
415 #define THREAD_PROTECT() do { \
418 sigfillset(&newmask); \
420 pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); \
423 #define THREAD_UNPROTECT() do { \
424 pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \
428 #define THREAD_DECS() //empty
429 #define THREAD_PROTECT() //empty
430 #define THREAD_UNPROTECT() //empty
433 static const char *pcm_dev_name =
"default";
436 CST_AUDIO_LINEAR16 = 0,
441 typedef struct cst_audiodev_struct {
443 int channels, real_channels;
444 cst_audiofmt fmt, real_fmt;
450 static int audio_bps(cst_audiofmt fmt)
454 case CST_AUDIO_LINEAR16:
456 case CST_AUDIO_LINEAR8:
457 case CST_AUDIO_MULAW:
463 static inline void print_pcm_state(snd_pcm_t *handle,
char *msg)
465 fprintf(stderr,
"PCM state at %s = %s\n", msg,
466 snd_pcm_state_name(snd_pcm_state(handle)));
469 cst_audiodev *audio_open_alsa(
int sps,
int channels, cst_audiofmt fmt)
472 unsigned int real_rate;
476 snd_pcm_t *pcm_handle;
477 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
478 snd_pcm_hw_params_t *hwparams;
479 snd_pcm_format_t format;
480 snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;
483 snd_pcm_hw_params_alloca(&hwparams);
486 err = snd_pcm_open(&pcm_handle, pcm_dev_name, stream, 0);
489 EST_warning(
"audio_open_alsa: failed to open audio device %s. %s\n",
490 pcm_dev_name, snd_strerror(err));
495 err = snd_pcm_hw_params_any(pcm_handle, hwparams);
498 snd_pcm_close(pcm_handle);
499 EST_warning(
"audio_open_alsa: failed to get hardware parameters from audio device. %s\n", snd_strerror(err));
504 err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, access);
507 snd_pcm_close(pcm_handle);
508 EST_warning(
"audio_open_alsa: failed to set access mode. %s.\n", snd_strerror(err));
517 case CST_AUDIO_LINEAR16:
518 if (EST_LITTLE_ENDIAN)
519 format = SND_PCM_FORMAT_S16_LE;
521 format = SND_PCM_FORMAT_S16_BE;
523 case CST_AUDIO_LINEAR8:
524 format = SND_PCM_FORMAT_U8;
526 case CST_AUDIO_MULAW:
527 format = SND_PCM_FORMAT_MU_LAW;
530 snd_pcm_close(pcm_handle);
531 EST_warning(
"audio_open_alsa: failed to find suitable format.\n");
537 err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format);
540 snd_pcm_close(pcm_handle);
541 EST_warning(
"audio_open_alsa: failed to set format. %s.\n", snd_strerror(err));
547 err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &real_rate, 0);
550 snd_pcm_close(pcm_handle);
551 EST_warning(
"audio_open_alsa: failed to set sample rate near %d. %s.\n", sps, snd_strerror(err));
557 err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels);
560 snd_pcm_close(pcm_handle);
561 EST_warning(
"audio_open_alsa: failed to set number of channels to %d. %s.\n", channels, snd_strerror(err));
566 err = snd_pcm_hw_params(pcm_handle, hwparams);
569 snd_pcm_close(pcm_handle);
570 EST_warning(
"audio_open_alsa: failed to set hw parameters. %s.\n", snd_strerror(err));
575 assert(snd_pcm_state(pcm_handle) == SND_PCM_STATE_PREPARED);
578 ad = walloc(cst_audiodev, 1);
580 ad->real_sps = ad->sps = sps;
581 ad->real_channels = ad->channels = channels;
582 ad->real_fmt = ad->fmt = fmt;
583 ad->platform_data = (
void *) pcm_handle;
588 int audio_close_alsa(cst_audiodev *ad)
591 snd_pcm_t *pcm_handle;
596 pcm_handle = (snd_pcm_t *) ad->platform_data;
598 snd_pcm_drain(pcm_handle);
600 result = snd_pcm_close(pcm_handle);
603 EST_warning(
"audio_close_alsa: Error: %s.\n", snd_strerror(result));
610 static int recover_from_error(snd_pcm_t *pcm_handle, ssize_t res)
614 res = snd_pcm_prepare(pcm_handle);
618 EST_warning(
"recover_from_write_error: failed to recover from xrun. %s\n.", snd_strerror(res));
622 else if (res == -ESTRPIPE)
624 while ((res = snd_pcm_resume(pcm_handle)) == -EAGAIN)
626 snd_pcm_wait(pcm_handle, 1000);
630 res = snd_pcm_prepare(pcm_handle);
634 EST_warning(
"audio_recover_from_write_error: failed to resume after suspend. %s\n.", snd_strerror(res));
642 EST_warning(
"audio_recover_from_write_error: %s.\n", snd_strerror(res));
648 int audio_write_alsa(cst_audiodev *ad,
void *samples,
int num_bytes)
651 ssize_t num_frames, res;
652 snd_pcm_t *pcm_handle;
653 char *buf = (
char *) samples;
656 frame_size = audio_bps(ad->real_fmt) * ad->real_channels;
658 assert((num_bytes % frame_size) == 0);
659 num_frames = num_bytes / frame_size;
660 pcm_handle = (snd_pcm_t *) ad->platform_data;
662 while (num_frames > 0)
664 res = snd_pcm_writei(pcm_handle, buf, num_frames);
665 if (res != num_frames)
667 if (res == -EAGAIN || (res > 0 && res < num_frames))
669 snd_pcm_wait(pcm_handle, 100);
671 else if (recover_from_error(pcm_handle, res) < 0)
680 buf += res * frame_size;
686 int audio_flush_alsa(cst_audiodev *ad)
689 result = snd_pcm_drain((snd_pcm_t *) ad->platform_data);
692 EST_warning(
"audio_flush_alsa: Error: %s.\n", snd_strerror(result));
695 result = snd_pcm_prepare((snd_pcm_t *) ad->platform_data);
698 EST_warning(
"audio_flush_alsa: Error: %s.\n", snd_strerror(result));
703 int audio_drain_alsa(cst_audiodev *ad)
706 result = snd_pcm_drop((snd_pcm_t *) ad->platform_data);
709 EST_warning(
"audio_drain_alsa: Error: %s.\n", snd_strerror(result));
712 result = snd_pcm_prepare((snd_pcm_t *) ad->platform_data);
715 EST_warning(
"audio_drain_alsa: Error: %s.\n", snd_strerror(result));
720 #define AUDIOBUFFSIZE 256
728 const char *audiodevice;
731 if (al.
present(
"-audiodevice"))
732 audiodevice = al.
val(
"-audiodevice");
734 audiodevice =
"/dev/dsp";
736 waveform = inwave.values().
memory();
740 ad = audio_open_alsa(sample_rate,1,CST_AUDIO_LINEAR16);
745 audio_write_alsa(ad,waveform,num_samples*
sizeof(
short));
747 audio_close_alsa(ad);
756 int sample_rate=16000;
760 int audio=-1,actual_fmt;
764 if (al.
present(
"-audiodevice"))
765 audiodevice = al.
val(
"-audiodevice");
767 audiodevice =
"/dev/dsp";
769 sample_rate = al.
ival(
"-sample_rate");
771 if ((audio = open(audiodevice,O_RDONLY)) == -1)
773 cerr << aud_sys_name <<
": can't open " << audiodevice
774 <<
"for reading" << endl;
778 actual_fmt = sb_set_sample_rate(audio,sample_rate);
780 if ((actual_fmt == AFMT_S16_LE) ||
781 (actual_fmt == AFMT_S16_BE))
785 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
788 waveform = inwave.values().
memory();
792 waveform2 = walloc(
short,num_samples*2);
796 waveform2 = waveform;
798 for (i=0; i < num_samples; i+= r)
800 if (num_samples > i+AUDIOBUFFSIZE)
804 r = read(audio,&waveform2[i], n*2);
808 cerr << aud_sys_name <<
": failed to read from audio device"
816 else if (actual_fmt == AFMT_U8)
818 inwave.
resize((
int)(sample_rate*al.
fval(
"-time")));
821 waveform = inwave.values().
memory();
822 unsigned char *u8wave = walloc(
unsigned char,num_samples);
824 for (i=0; i < num_samples; i+= r)
826 if (num_samples > i+AUDIOBUFFSIZE)
830 r = read(audio,&u8wave[i],n);
833 cerr << aud_sys_name <<
": failed to read from audio device"
841 uchar_to_short(u8wave,waveform,num_samples);
846 cerr << aud_sys_name <<
": unknown audio format from device: " <<
854 for (i=0; i<num_samples; i+=2)
855 waveform[i/2] = waveform2[i];
866 #ifdef SUPPORT_PULSEAUDIO
867 #include <pulse/simple.h>
869 int freebsd16_supported = FALSE;
870 int linux16_supported = TRUE;
872 static const char *aud_sys_name =
"PULSEAUDIO";
874 #define AUDIOBUFFSIZE 256
885 ss = walloc(pa_sample_spec,1);
890 ss->format = PA_SAMPLE_S16BE;
892 ss->format = PA_SAMPLE_S16LE;
907 waveform = inwave.values().
memory();
910 for (i=0; i < num_samples; i += AUDIOBUFFSIZE/2)
912 if (i + AUDIOBUFFSIZE/2 < num_samples)
913 pa_simple_write(s,&waveform[i],(
size_t)AUDIOBUFFSIZE,&err);
915 pa_simple_write(s,&waveform[i],(
size_t)(num_samples-i)*2,&err);
918 pa_simple_drain(s,&err);
932 int freebsd16_supported = FALSE;
933 int linux16_supported = FALSE;
939 cerr <<
"MacOS X audio support not compiled." << endl;
946 cerr <<
"MacOS X audio support not compiled." << endl;