diff -ruN speechd/configure.in myspeechd/configure.in --- speechd/configure.in 2009-12-16 11:47:43.000000000 +0100 +++ myspeechd/configure.in 2009-12-16 11:49:25.000000000 +0100 @@ -203,6 +203,25 @@ AM_CONDITIONAL(nas_support, test $nas_aud = "true") +AC_CHECK_LIB(ao, + ao_play, + libao_aud="true";echo "Compiling with libao support.";, + libao_aud="false";echo "*** libao library missing. Compiling without libao support! See INSTALL.";) + +AC_ARG_WITH(libao, AS_HELP_STRING(--with-libao, Compile with libao support), + if test $withval = "no"; then + echo "Forced compilation without libao support."; + libao_aud="false"; + else + if test $libao_aud = "false"; then + echo "libao support is not available. Sorry."; exit 1; + fi + fi + echo "") + +AM_CONDITIONAL(libao_support, test $libao_aud = "true") + + AC_CHECK_LIB(asound, snd_pcm_open, alsa_aud="true";echo "Compiling with ALSA support.";, diff -ruN speechd/src/audio/Makefile.am myspeechd/src/audio/Makefile.am --- speechd/src/audio/Makefile.am 2009-12-16 11:47:43.000000000 +0100 +++ myspeechd/src/audio/Makefile.am 2009-12-16 11:49:25.000000000 +0100 @@ -18,12 +18,16 @@ ALSA_FLAGS = -DWITH_ALSA ALSA_LIBS = -lasound endif +if libao_support +LIBAO_FLAGS = -DWITH_LIBAO +LIBAO_LIBS = -lao +endif -EXTRA_DIST = alsa.c oss.c nas.c pulse.c +EXTRA_DIST = alsa.c libao.c oss.c nas.c pulse.c -AM_CFLAGS = $(am_cflags) $(NAS_FLAGS) $(PULSE_FLAGS) $(ALSA_FLAGS) -libsdaudio_la_LDFLAGS = -version-info @LIB_SDAUDIO_CURRENT@:@LIB_SDAUDIO_REVISION@:@LIB_SDAUDIO_AGE@ -lpthread $(NAS_LIBS) $(PULSE_LIBS) $(ALSA_LIBS) +AM_CFLAGS = $(am_cflags) $(NAS_FLAGS) $(PULSE_FLAGS) $(ALSA_FLAGS) $(LIBAO_FLAGS) +libsdaudio_la_LDFLAGS = -version-info @LIB_SDAUDIO_CURRENT@:@LIB_SDAUDIO_REVISION@:@LIB_SDAUDIO_AGE@ -lpthread $(NAS_LIBS) $(PULSE_LIBS) $(ALSA_LIBS) $(LIBAO_LIBS) spdlib_LTLIBRARIES = libsdaudio.la diff -ruN speechd/src/audio/libao.c myspeechd/src/audio/libao.c --- speechd/src/audio/libao.c 1970-01-01 01:00:00.000000000 +0100 +++ myspeechd/src/audio/libao.c 2009-12-16 11:50:50.000000000 +0100 @@ -0,0 +1,191 @@ +/* + * libao.c -- The libao backend for the spd_audio library. + * + * Author: Marco Skambraks + * Date: 2009-12-15 + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU Leser General Public License as published by the Free + * Software Foundation; either version 2.1, or (at your option) any later + * version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this package; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include +#include +#include +#include + +/* send a packet of XXX bytes to the sound device */ +#define AO_SEND_BYTES 256 +/* Put a message into the logfile (stderr) */ +#define MSG(level, arg...) \ + if(level <= log_level){ \ + time_t t; \ + struct timeval tv; \ + char *tstr; \ + t = time(NULL); \ + tstr = strdup(ctime(&t)); \ + tstr[strlen(tstr)-1] = 0; \ + gettimeofday(&tv,NULL); \ + fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \ + fprintf(stderr," libao:: "); \ + fprintf(stderr,arg); \ + fprintf(stderr,"\n"); \ + fflush(stderr); \ + xfree(tstr); \ + } + +#define ERR(arg...) \ + { \ + time_t t; \ + struct timeval tv; \ + char *tstr; \ + t = time(NULL); \ + tstr = strdup(ctime(&t)); \ + tstr[strlen(tstr)-1] = 0; \ + gettimeofday(&tv,NULL); \ + fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \ + fprintf(stderr," libao ERROR: "); \ + fprintf(stderr,arg); \ + fprintf(stderr,"\n"); \ + fflush(stderr); \ + xfree(tstr); \ + } + +int libao_stop (AudioID * id); + +int libao_open (AudioID * id, void **pars); + +int libao_close (AudioID * id); + +int libao_play (AudioID * id, AudioTrack track); + +int libao_set_volume (AudioID * id, int volume); + +static volatile int ao_stop_playback = 0; + +static int default_driver; + +ao_device *device = NULL; + +int libao_open (AudioID * id, void **pars) +{ + + ao_initialize (); + default_driver = ao_default_driver_id (); + return 0; +} + +int libao_play (AudioID * id, AudioTrack track) +{ + int bytes_per_sample; + + int num_bytes; + + int outcnt = 0; + + signed short *output_samples; + + int i; + + ao_sample_format format; + + if (id == NULL) + return -1; + if (track.samples == NULL || track.num_samples <= 0) + return 0; + + /* Choose the correct format */ + format.bits = track.bits; + if (track.bits == 16) + bytes_per_sample = 2; + else if (track.bits == 8) + bytes_per_sample = 1; + else + { + ERR ("Audio: Unrecognized sound data format.\n"); + return -10; + } + format.channels = track.num_channels; + format.rate = track.sample_rate; + format.byte_format = AO_FMT_LITTLE; + MSG (3, "Starting playback"); + output_samples = track.samples; + num_bytes = track.num_samples * bytes_per_sample; + if (device == NULL) + device = ao_open_live (default_driver, &format, NULL); + if (device == NULL) + { + ERR ("error opening libao dev"); + return -2; + } + MSG (3, "bytes to play: %d, (%f secs)", num_bytes, + (((float) (num_bytes) / 2) / (float) track.sample_rate)); + + ao_stop_playback = 0; + outcnt = 0; + i = 0; + + while ((outcnt < num_bytes) && !ao_stop_playback) + { + if ((num_bytes - outcnt) > AO_SEND_BYTES) + i = AO_SEND_BYTES; + else + i = (num_bytes - outcnt); + + if (!ao_play (device, (char *) output_samples + outcnt, i)) + { + ao_close (device); + device = NULL; + ERR ("Audio: ao_play() - closing device - re-open it in next run\n"); + } + outcnt += i; + } + + return 0; + +} + +/* stop the libao_play() loop */ +int libao_stop (AudioID * id) +{ + + ao_stop_playback = 1; + return 0; +} + +int libao_close (AudioID * id) +{ + + if (device != NULL) + ao_close (device); + device = NULL; + + ao_shutdown (); + id = NULL; + + return 0; +} + +int libao_set_volume (AudioID * id, int volume) +{ + return 0; +} + +/* Provide the libao backend. */ +AudioFunctions libao_functions = + { libao_open, libao_play, libao_stop, libao_close, libao_set_volume }; + +#undef MSG +#undef ERR diff -ruN speechd/src/audio/spd_audio.c myspeechd/src/audio/spd_audio.c --- speechd/src/audio/spd_audio.c 2009-12-16 11:47:43.000000000 +0100 +++ myspeechd/src/audio/spd_audio.c 2009-12-16 11:49:25.000000000 +0100 @@ -27,7 +27,7 @@ * playing 8 or 16 bit data, immediate stop and synchronization. This library * currently provides OSS, NAS, ALSA and PulseAudio backend. The available backends are * specified at compile-time using the directives WITH_OSS, WITH_NAS, WITH_ALSA, - * WITH_PULSE, but the user program is allowed to switch between them at run-time. + * WITH_PULSE, WITH_LIBAO but the user program is allowed to switch between them at run-time. */ #include "spd_audio.h" @@ -47,6 +47,9 @@ #ifdef WITH_OSS #include "oss.c" #endif +#ifdef WITH_LIBAO +#include "libao.c" +#endif /* The NAS backend */ #ifdef WITH_NAS @@ -116,6 +119,7 @@ *error = strdup("The sound library wasn't compiled with OSS support."); return NULL; #endif + } else if (type == AUDIO_ALSA){ #ifdef WITH_ALSA @@ -180,6 +184,27 @@ return NULL; #endif } + else if (type == AUDIO_LIBAO){ +#ifdef WITH_LIBAO + id->function = (Funct*) &libao_functions; + + if (id->function->open != NULL){ + ret = id->function->open(id, pars); + if (ret != 0){ + *error = (char*) strdup("Couldn't open libao"); + return NULL; + } + } + else{ + *error = (char*) strdup("Couldn't open libao module."); + return NULL; + } + id->type = AUDIO_LIBAO; +#else + *error = strdup("The sound library wasn't compiled with libao support."); + return NULL; +#endif + } else{ *error = (char*) strdup("Unknown device"); return NULL; diff -ruN speechd/src/audio/spd_audio.h myspeechd/src/audio/spd_audio.h --- speechd/src/audio/spd_audio.h 2009-12-16 11:47:43.000000000 +0100 +++ myspeechd/src/audio/spd_audio.h 2009-12-16 11:49:25.000000000 +0100 @@ -54,7 +54,7 @@ #define AUDIO_BUF_SIZE 4096 -typedef enum{AUDIO_OSS = 0, AUDIO_NAS = 1, AUDIO_ALSA=2, AUDIO_PULSE=3} AudioOutputType; +typedef enum{AUDIO_OSS = 0, AUDIO_NAS = 1, AUDIO_ALSA=2, AUDIO_PULSE=3, AUDIO_LIBAO=4} AudioOutputType; typedef enum{SPD_AUDIO_LE, SPD_AUDIO_BE} AudioFormat; AudioFormat spd_audio_endian; diff -ruN speechd/src/modules/module_utils.c myspeechd/src/modules/module_utils.c --- speechd/src/modules/module_utils.c 2009-12-16 11:47:43.000000000 +0100 +++ myspeechd/src/modules/module_utils.c 2009-12-16 11:49:25.000000000 +0100 @@ -1150,6 +1150,15 @@ module_audio_output_method = AUDIO_OSS; audio_output_set = 1; } + } else if (len == 5 && strncmp("libao", outputs, len) == 0){ + DBG("Using libao audio output method"); + module_audio_pars[0] = NULL; + module_audio_pars[1] = NULL; + module_audio_id = spd_audio_open(AUDIO_LIBAO, (void**) module_audio_pars, &error); + if (module_audio_id){ + module_audio_output_method = AUDIO_LIBAO; + audio_output_set = 1; + } } else if (len == 4 && strncmp("alsa", outputs, len) == 0){ DBG("Using Alsa audio output method"); module_audio_pars[0] = audio_settings.audio_alsa_device;