From 668ea0f309ced8f2681dbd620991cc705a3aaf86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 10 Jan 2011 17:24:22 +0000 Subject: working espeak external svn path=/trunk/externals/espeak/; revision=14696 --- espeak~.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 espeak~.c (limited to 'espeak~.c') diff --git a/espeak~.c b/espeak~.c new file mode 100644 index 0000000..16a7fbf --- /dev/null +++ b/espeak~.c @@ -0,0 +1,204 @@ +/****************************************************** + * + * espeak - implementation file + * + * (c) copyright 2011 IOhannes m zmölnig + * (c) copyright 2011 Matthias Kronlachner + * (c) copyright 2011 Marian Weger + * + * within the course: Künstlerisches Gestalten mit Klang 2010/2011 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +#include "m_pd.h" +#include +#include + +/* general */ + +static int espeak_rate=0; +#define ESPEAK_BUFFER 50000 + + +typedef struct _espeak +{ + t_object x_obj; + + short*x_buffer; /* buffer of synth'ed samples */ + unsigned int x_buflen; /* length of the buffer */ + + unsigned int x_position; /* playback position for perform-routine */ + + int x_ready; /* flag: if true, start playback */ + + + t_outlet*x_infoout; +} t_espeak; + +/* ------------------------ espeak~ ----------------------------- */ + +static t_class *espeak_class; + +static t_int *espeak_perform(t_int *w){ + t_espeak *x = (t_espeak *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int n = (int)(w[3]); + + if(x->x_ready) { + // got data to play back + n=n/2; + + short*in=x->x_buffer+x->x_position; + + x->x_position+=n; + if(x->x_position>=x->x_buflen) + x->x_ready=0; + + + while(n--) { + t_sample f=(*in++)/32768.; + *out++ = f; + *out++ = f; + } + + } else { + while(n--) { + *out++=0.f; + } + } + + return (w+4); +} + +static void espeak_dsp(t_espeak *x, t_signal **sp){ + + t_signal*sig=sp[0]; + + + dsp_add(espeak_perform, 3, + x, + sp[0]->s_vec, + sp[0]->s_n); +} + +static int espeak_callback(short *wav, int numsamples, espeak_EVENT *events) { + int i=0; + + verbose(1, "get %d samples", numsamples); + + if(numsamples) { + t_espeak*x = (t_espeak*)events[0].user_data; + if(NULL==x) + return 1; + + memset(x->x_buffer, 0, x->x_buflen*sizeof(short)); + memcpy(x->x_buffer, wav, numsamples*sizeof(short)); + x->x_ready = 1; + x->x_position = 0; + } + + return 0; +} + +static void espeak_text(t_espeak *x, t_symbol*s, int argc, t_atom*argv) { + t_binbuf*bb=binbuf_new(); + int size=0; + char*text=NULL; + + binbuf_add(bb, argc, argv); + binbuf_gettext(bb, &text, &size); + binbuf_free(bb); + + text[size]=0; + + verbose(1, "speak '%s'", text); + + espeak_Synth(text, + strlen(text), + 0, + POS_CHARACTER, + 0, + espeakCHARS_AUTO, + NULL, + x); +} + + +static void espeak_info(t_espeak*x){ + const espeak_VOICE**voices=espeak_ListVoices(NULL); + int i=0; + + while(voices[i]) { + + t_atom ap[3]; + SETSYMBOL(ap+0, gensym(voices[i]->name)); + SETSYMBOL(ap+1, gensym(voices[i]->languages)); + SETSYMBOL(ap+2, gensym(voices[i]->identifier)); + + outlet_anything(x->x_infoout, gensym("voice"), 3, ap); + + i++; + } +} + + +static void espeak_voice(t_espeak*x, t_symbol*s){ + espeak_ERROR err= espeak_SetVoiceByName(s->s_name); +} + +static void espeak_free(t_espeak*x){ + freebytes(x->x_buffer, x->x_buflen*sizeof(short)); + if(x->x_infoout) + outlet_free(x->x_infoout); + +} + +static void *espeak_new(void){ + t_espeak *x = (t_espeak *)pd_new(espeak_class); + + x->x_buflen = espeak_rate*ESPEAK_BUFFER/1000; + x->x_buffer = (short*)getbytes(x->x_buflen*sizeof(short)); + + outlet_new(&x->x_obj, gensym("signal")); + x->x_infoout=outlet_new(&x->x_obj, NULL); + + return (x); +} + +void espeak_tilde_setup(void){ + + int result=espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, + ESPEAK_BUFFER, + NULL, + 0); + + + if(result<0) { + error("couldn't initialize eSpeak"); + return; + } + + espeak_SetSynthCallback(espeak_callback); + espeak_rate=result; + + post("eSpeak running at %d Hz", result); + + espeak_class = class_new(gensym("espeak~"), (t_newmethod)espeak_new, 0, sizeof(t_espeak), 0, 0); + + class_addmethod(espeak_class, (t_method)espeak_dsp, gensym("dsp"), 0); + + class_addmethod(espeak_class, (t_method)espeak_text, gensym("speak"), A_GIMME, 0); + + + class_addmethod(espeak_class, (t_method)espeak_voice, gensym("voice"), A_SYMBOL, 0); + + + class_addbang(espeak_class, (t_method)espeak_info); + +} -- cgit v1.2.1