[ANNOUNCE] libao support for speechdispatcher (with working pulseaudio :-) )



Hi,
Please use attached diff for (speechd from Luke's git repo) to add libao
support.
Libao is a cross platform audio library for playing sound.
Marco Skambraks has written a libao driver for speechd which works out
of box with pulse.
Use libao as audiooutputmethod in spechd.conf.
libao uses pulse if
default_driver=pulse
is set in /etc/libao.conf
It supports also oss alsa sun irix ...

FEDBACK TO:
marco openblinux de
halim openblinux de

I have tested libao with it's pulseaudio plugin and it works great.
A crash of pulseaudio doesn't affect speechd.
After a resume of pa speech comes back.


Have a lot of fun.

Halim

-- 
----------------------
Halim Sahin
The OpenBlinux Project


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 <marco openblinux de>
+ * 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 <sys/time.h>
+#include <time.h>
+#include <string.h>
+#include <ao/ao.h>
+
+/* 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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]