diff --git speech_tools.orig/audio/Makefile speech_tools/audio/Makefile index 6103654..1535faf 100644 --- speech_tools.orig/audio/Makefile +++ speech_tools/audio/Makefile @@ -44,7 +44,7 @@ LOCAL_DEFAULT_LIBRARY = estbase H = audioP.h CPPSRCS = gen_audio.cc nas.cc esd.cc sun16audio.cc \ mplayer.cc win32audio.cc irixaudio.cc os2audio.cc \ - macosxaudio.cc linux_sound.cc + macosxaudio.cc linux_sound.cc sndio.cc SRCS = $(CPPSRCS) OBJS = $(SRCS:.cc=.o) diff --git speech_tools.orig/audio/audioP.h speech_tools/audio/audioP.h index 6d49690..6c86ab1 100644 --- speech_tools.orig/audio/audioP.h +++ speech_tools/audio/audioP.h @@ -43,6 +43,7 @@ int play_nas_wave(EST_Wave &inwave, EST_Option &al); int play_esd_wave(EST_Wave &inwave, EST_Option &al); int play_sun16_wave(EST_Wave &inwave, EST_Option &al); int play_linux_wave(EST_Wave &inwave, EST_Option &al); +int play_sndio_wave(EST_Wave &inwave, EST_Option &al); int play_mplayer_wave(EST_Wave &inwave, EST_Option &al); int play_win32audio_wave(EST_Wave &inwave, EST_Option &al); int play_irix_wave(EST_Wave &inwave, EST_Option &al); @@ -52,5 +53,6 @@ int record_nas_wave(EST_Wave &inwave, EST_Option &al); int record_esd_wave(EST_Wave &inwave, EST_Option &al); int record_sun16_wave(EST_Wave &inwave, EST_Option &al); int record_linux_wave(EST_Wave &inwave, EST_Option &al); +int record_sndio_wave(EST_Wave &inwave, EST_Option &al); #endif /* __AUDIOP_H__ */ diff --git speech_tools.orig/audio/gen_audio.cc speech_tools/audio/gen_audio.cc index 985324a..ec286a4 100644 --- speech_tools.orig/audio/gen_audio.cc +++ speech_tools/audio/gen_audio.cc @@ -97,6 +97,8 @@ int play_wave(EST_Wave &inwave, EST_Option &al) protocol = "win32audio"; else if (mplayer_supported) protocol = "mplayeraudio"; + else if (sndio_supported) + protocol = "sndioaudio"; else protocol = "sunaudio"; } @@ -121,6 +123,8 @@ int play_wave(EST_Wave &inwave, EST_Option &al) else if ((upcase(protocol) == "FREEBSD16AUDIO") || (upcase(protocol) == "LINUX16AUDIO")) return play_linux_wave(*toplay,al); + else if (upcase(protocol) == "SNDIOAUDIO") + return play_sndio_wave(*toplay,al); else if (upcase(protocol) == "IRIXAUDIO") return play_irix_wave(*toplay,al); else if (upcase(protocol) == "MACOSXAUDIO") @@ -263,6 +267,8 @@ EST_String options_supported_audio(void) audios += " win32audio"; if (os2audio_supported) audios += " os2audio"; + if (sndio_supported) + audios += " sndioaudio"; return audios; } @@ -301,6 +307,8 @@ int record_wave(EST_Wave &wave, EST_Option &al) protocol = "win32audio"; else if (mplayer_supported) protocol = "mplayeraudio"; + else if (sndio_supported) + protocol = "sndioaudio"; else protocol = "sunaudio"; } @@ -314,6 +322,8 @@ int record_wave(EST_Wave &wave, EST_Option &al) else if ((upcase(protocol) == "FREEBSD16AUDIO") || (upcase(protocol) == "LINUX16AUDIO")) return record_linux_wave(wave,al); + else if (upcase(protocol) == "SNDIOAUDIO") + return record_sndio_wave(wave,al); else if (upcase(protocol) == "SUNAUDIO") return record_sunau_wave(wave,al); else diff --git speech_tools/audio/sndio.cc speech_tools/audio/sndio.cc new file mode 100644 index 0000000..866f43c --- /dev/null +++ speech_tools/audio/sndio.cc @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2010 Jacob Meuser + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Based on voxware.cc which came with the following copyright notice. */ + +/*************************************************************************/ +/* */ +/* Centre for Speech Technology Research */ +/* University of Edinburgh, UK */ +/* Copyright (c) 1997,1998 */ +/* All Rights Reserved. */ +/* */ +/* Permission is hereby granted, free of charge, to use and distribute */ +/* this software and its documentation without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of this work, and to */ +/* permit persons to whom this work is furnished to do so, subject to */ +/* the following conditions: */ +/* 1. The code must retain the above copyright notice, this list of */ +/* conditions and the following disclaimer. */ +/* 2. Any modifications must be clearly marked as such. */ +/* 3. Original authors' names are not deleted. */ +/* 4. The authors' names are not used to endorse or promote products */ +/* derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */ +/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ +/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ +/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */ +/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ +/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ +/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ +/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ +/* THIS SOFTWARE. */ +/* */ +/*************************************************************************/ +/* Author : Alan W Black */ +/* Date : July 1997 */ +/*-----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "EST_cutils.h" +#include "EST_walloc.h" +#include "EST_Wave.h" +#include "EST_wave_aux.h" +#include "EST_Option.h" +#include "audioP.h" +#include "EST_io_aux.h" +#include "EST_error.h" + +#ifdef SUPPORT_SNDIO +#include +int sndio_supported = TRUE; +static char *aud_sys_name = "sndio"; +static int stereo_only = 0; + + +// Code to block signals while sound is playing. +// Needed inside Java on (at least some) linux systems +// as scheduling interrupts seem to break the writes. + +#ifdef THREAD_SAFETY +#include +#include + +#define THREAD_DECS() \ + sigset_t oldmask \ + +#define THREAD_PROTECT() do { \ + sigset_t newmask; \ + \ + sigfillset(&newmask); \ + \ + pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); \ + } while(0) + +#define THREAD_UNPROTECT() do { \ + pthread_sigmask(SIG_SETMASK, &oldmask, NULL); \ + } while (0) + +#else +#define THREAD_DECS() //empty +#define THREAD_PROTECT() //empty +#define THREAD_UNPROTECT() //empty +#endif + + +#define AUDIOBUFFSIZE 256 +// #define AUDIOBUFFSIZE 20480 + +int +play_sndio_wave(EST_Wave &inwave, EST_Option &al) +{ + struct sio_hdl *hdl; + struct sio_par par; + int sample_rate; + short *waveform; + short *waveform2 = NULL; + int num_samples; + int i, r, n; + char *audiodevice = NULL; + + if (al.present("-audiodevice")) + audiodevice = al.val("-audiodevice"); + + if ((hdl = sio_open(audiodevice, SIO_PLAY, 0)) == NULL) { + cerr << aud_sys_name << ": error opening device" << endl; + return -1; + } + + waveform = inwave.values().memory(); + num_samples = inwave.num_samples(); + sample_rate = inwave.sample_rate(); + + sio_initpar(&par); + + par.rate = sample_rate; + par.pchan = 1; + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + + if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) { + cerr << aud_sys_name << ": error configuring parameters" << endl; + return -1; + } + + if ((par.pchan != 1 && par.pchan != 2) || + !((par.bits == 16 && par.sig == 1) || + (par.bits == 8 && par.sig == 0)) || + par.rate != sample_rate) { + cerr << aud_sys_name << ": could not set appropriate parameters" << endl; + return -1; + } + + if (!sio_start(hdl)) { + cerr << aud_sys_name << ": could not start sudio" << endl; + return -1; + } + + if (par.pchan == 2) + stereo_only = 1; + + if (stereo_only) { + waveform2 = walloc(short, num_samples * 2); + for (i = 0; i < num_samples; i++) { + waveform2[i * 2] = inwave.a(i); + waveform2[(i * 2) + 1] = inwave.a(i); + } + waveform = waveform2; + num_samples *= 2; + } + + THREAD_DECS(); + THREAD_PROTECT(); + + if (par.bits == 8) { + // Its actually 8bit unsigned so convert the buffer; + unsigned char *uchars = walloc(unsigned char,num_samples); + for (i=0; i < num_samples; i++) + uchars[i] = waveform[i] / 256 + 128; + for (i=0; i < num_samples; i += r) { + if (num_samples > i + AUDIOBUFFSIZE) + n = AUDIOBUFFSIZE; + else + n = num_samples - i; + r = sio_write(hdl, &uchars[i], n); + if (r == 0 && sio_eof(hdl)) { + THREAD_UNPROTECT(); + cerr << aud_sys_name << ": failed to write to buffer" << + sample_rate << endl; + sio_close(hdl); + return -1; + } + } + wfree(uchars); + } else { + // 16-bit + int nbuf, c; + short *buf; + + nbuf = par.round * par.bps * par.pchan; + + buf = new short[nbuf]; + + for (i = 0; i < num_samples; i += r / 2) { + if (num_samples > i+nbuf) + n = nbuf; + else + n = num_samples-i; + + for (c = 0; c < n; c++) + buf[c] = waveform[c + i]; + + for(; c < nbuf; c++) + buf[c] = waveform[n - 1]; + + r = sio_write(hdl, buf, nbuf * 2); + if (r == 0 && sio_eof(hdl)) { + THREAD_UNPROTECT(); + EST_warning("%s: failed to write to buffer (sr=%d)", + aud_sys_name, sample_rate ); + sio_close(hdl); + return -1; + } + + } + delete [] buf; + } + + sio_close(hdl); + if (waveform2) + wfree(waveform2); + + THREAD_UNPROTECT(); + return 1; +} + +int +record_sndio_wave(EST_Wave &inwave, EST_Option &al) +{ + struct sio_hdl *hdl; + struct sio_par par; + int sample_rate = 16000; // egcs needs the initialized for some reason + short *waveform; + short *waveform2 = NULL; + int num_samples; + int i,r,n; + char *audiodevice = NULL; + + if (al.present("-audiodevice")) + audiodevice = al.val("-audiodevice"); + + sample_rate = al.ival("-sample_rate"); + + if ((hdl = sio_open(audiodevice, SIO_REC, 0)) == NULL) { + cerr << aud_sys_name << ": error opening device" << endl; + return -1; + } + + sio_initpar(&par); + + par.rate = sample_rate; + par.rchan = 1; + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + + if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) { + cerr << aud_sys_name << ": error configuring parameters" << endl; + return -1; + } + + if ((par.rchan != 1 && par.rchan != 2) || + !((par.bits == 16 && par.sig == 1) || + (par.bits == 8 && par.sig == 0)) || + par.rate != sample_rate) { + cerr << aud_sys_name << ": could not set appropriate parameters" << endl; + return -1; + } + + if (!sio_start(hdl)) { + cerr << aud_sys_name << ": could not start sudio" << endl; + return -1; + } + + if (par.rchan == 2) + stereo_only = 1; + + inwave.resize((int)(sample_rate * al.fval("-time"))); + inwave.set_sample_rate(sample_rate); + num_samples = inwave.num_samples(); + waveform = inwave.values().memory(); + + if (par.bits == 16) { + // We assume that the device returns audio in native byte order + // by default + + if (stereo_only) { + waveform2 = walloc(short, num_samples * 2); + num_samples *= 2; + } else + waveform2 = waveform; + + for (i = 0; i < num_samples; i+= r) { + if (num_samples > i+AUDIOBUFFSIZE) + n = AUDIOBUFFSIZE; + else + n = num_samples-i; + r = sio_read(hdl, &waveform2[i], n * 2); + r /= 2; + if (r == 0 && sio_eof(hdl)) { + cerr << aud_sys_name << ": failed to read from audio device" + << endl; + sio_close(hdl); + return -1; + } + } + } else { + unsigned char *u8wave = walloc(unsigned char, num_samples); + + for (i = 0; i < num_samples; i += r) { + if (num_samples > i+AUDIOBUFFSIZE) + n = AUDIOBUFFSIZE; + else + n = num_samples - i; + r = sio_read(hdl, &u8wave[i], n); + if (r == 0 && sio_eof(hdl)) { + cerr << aud_sys_name << ": failed to read from audio device" + << endl; + sio_close(hdl); + wfree(u8wave); + return -1; + } + + } + uchar_to_short(u8wave, waveform, num_samples); + wfree(u8wave); + } + + if (stereo_only) { + for (i = 0; i < num_samples; i += 2) + waveform[i / 2] = waveform2[i]; + wfree(waveform2); + } + + sio_close(hdl); + return 0; +} + +#else + +int sndio_supported = FALSE; + +int +play_sndio_wave(EST_Wave &inwave, EST_Option &al) +{ + (void)inwave; + (void)al; + cerr << "Audio: sndio not compiled in this version" << endl; + return -1; +} + +int +record_sndio_wave(EST_Wave &inwave, EST_Option &al) +{ + (void)inwave; + (void)al; + cerr << "Audio: sndio not compiled in this version" << endl; + return -1; +} + +#endif diff --git speech_tools.orig/config/modules/Makefile speech_tools/config/modules/Makefile index c937c64..6bfb6d3 100644 --- speech_tools.orig/config/modules/Makefile +++ speech_tools/config/modules/Makefile @@ -42,7 +42,7 @@ RULESETS = efence.mak dmalloc.mak debugging.mak \ freebsd16_audio.mak irix_audio.mak linux16_audio.mak \ sun16_audio.mak win32_audio.mak macosx_audio.mak \ mplayer_audio.mak nas_audio.mak esd_audio.mak \ - siod_python.mak + siod_python.mak sndio_audio.mak FILES = Makefile descriptions $(RULESETS) diff --git speech_tools/config/modules/sndio_audio.mak speech_tools/config/modules/sndio_audio.mak new file mode 100644 index 0000000..1f5d7d2 --- /dev/null +++ speech_tools/config/modules/sndio_audio.mak @@ -0,0 +1,8 @@ + +INCLUDE_SNDIO_AUDIO=1 + +MOD_DESC_SNDIO_AUDIO=(from EST) Audio module for sndio audio support + +AUDIO_DEFINES += -DSUPPORT_SNDIO + +MODULE_LIBS += -lsndio diff --git speech_tools.orig/config/systems/Linux.mak speech_tools/config/systems/Linux.mak index 1fbba94..62a3d7b 100644 --- speech_tools.orig/config/systems/Linux.mak +++ speech_tools/config/systems/Linux.mak @@ -44,7 +44,7 @@ TCL_LIBRARY = -ltcl OS_LIBS = -ldl -lncurses ## the native audio module for this type of system -NATIVE_AUDIO_MODULE = LINUX16 +NATIVE_AUDIO_MODULE = SNDIO ## echo -n doesn't work ECHO_N = /usr/bin/printf "%s" diff --git speech_tools.orig/include/EST_audio.h speech_tools/include/EST_audio.h index 2b1df88..29891b8 100644 --- speech_tools.orig/include/EST_audio.h +++ speech_tools/include/EST_audio.h @@ -46,6 +46,7 @@ extern int nas_supported; extern int esd_supported; extern int sun16_supported; extern int freebsd16_supported; +extern int sndio_supported; extern int linux16_supported; extern int mplayer_supported; extern int win32audio_supported; diff --git speech_tools.orig/lib/siod/init.scm speech_tools/lib/siod/init.scm index a149f96..37acb24 100644 --- speech_tools.orig/lib/siod/init.scm +++ speech_tools/lib/siod/init.scm @@ -78,8 +78,10 @@ (Parameter.def 'Audio_Method 'os2audio)) ((member 'mplayeraudio *modules*) (Parameter.def 'Audio_Method 'mplayeraudio)) - (t ;; can't find direct support so guess that /dev/audio for 8k ulaw exists - (Parameter.def 'Audio_Method 'sunaudio))) + ((member 'sndioaudio *modules*) + (Parameter.def 'Audio_Method 'sndioaudio)) + (t ;; stupid crappy software. default to only supported "protocol" + (Parameter.def 'Audio_Method 'sndioaudio))) ;;; If you have an external program to play audio add its definition ;;; in siteinit.scm