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 --- Makefile | 154 ++++++++++++++++++++++++++++++++++++++++++ espeak~-help.pd | 94 ++++++++++++++++++++++++++ espeak~.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 Makefile create mode 100644 espeak~-help.pd create mode 100644 espeak~.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b3528b2 --- /dev/null +++ b/Makefile @@ -0,0 +1,154 @@ +# Makefile +# (c) 2006 IOhannes m zmölnig + +# path to pd +## change this according to your setup! +PDROOT=../../../../pd +#PDROOT=/home/zmoelnig/src/pd/ + +# here we find the sources of pd (and evtl. the pd.lib) +PDSRCDIR=$(PDROOT)/src +PDLIBDIR=$(PDROOT)/bin + +# this is the filename-extension +# people have to specify it at the cmdline: eg "make pd_linux" +EXTENSION=$(MAKECMDGOALS) + +# if no filename-extension is supplied by the user +# try to guess one, based on what "uname" tells us +UNAME := $(shell uname -s) +ifeq ($(UNAME),Linux) + DEFAULTEXTENSION= pd_linux +else + ifeq ($(UNAME),Darwin) + DEFAULTEXTENSION= pd_darwin + else + ifeq (MINGW,$(findstring MINGW,$(UNAME))) + DEFAULTEXTENSION= pd_nt + else + ifeq ($(UNAME),IRIX) + UNAMEV := $(shell uname -R) + ifeq (6.,$(findstring 6.,$(UNAMEV))) + DEFAULTEXTENSION= pd_irix6 + else + DEFAULTEXTENSION= pd_irix5 + endif + else + DEFAULTEXTENSION=help + endif + endif + endif +endif + +# if no extension is given, call "make" again with a guessed extension +auto: + make $(DEFAULTEXTENSION) + +# just a stupid fallback +help: + @echo "choose one command: make pd_linux (linux), make pd_darwin (osX), make pd_irix5 (IRIX5), make pd_irix6 (IRIX6), make dll (MSVC), make pd_nt (MinWG)" + +# delete old build files +clean: + -rm -f *.dll *.pd_* *.o *.obj *~ + +# we want to compile all C-files we find in the current directory +SOURCES=$(sort $(filter %.c, $(wildcard *.c))) +# each C-files maps will become an external with the given filename-extension +TARGETS=$(SOURCES:.c=.$(EXTENSION)) + + +# ----------------------- Linux ----------------------- + +pd_linux: $(TARGETS) + +LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +LINUXLDFLAGS = -export-dynamic -shared -lc -lm -lespeak + +LINUXINCLUDE = -I$(PDSRCDIR) + +%.pd_linux: %.c + $(CC) $(LINUXLDFLAGS) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.pd_linux $*.c + strip --strip-unneeded $*.pd_linux + + + +# ----------------------- Mac OSX ----------------------- + +pd_darwin: $(TARGETS) + +DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \ + -Wno-unused -Wno-parentheses -Wno-switch + +DARWININCLUDE = -I$(PDSRCDIR) + +DARWINLDFLAGS = -bundle -undefined suppress -flat_namespace + +%.pd_darwin: %.c + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) $(DARWINLDFLAGS) -o $*.pd_darwin $*.c + + +# ----------------------- IRIX 5.x ----------------------- +pd_irix5: $(TARGETS) + +SGICFLAGS5 = -o32 -DPD -DSGI -O2 + +SGIINCLUDE = -I$(PDSRCDIR) + +SGILDFLAGS = -elf -shared -rdata_shared + +%.pd_irix5: %.c + $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c + $(LD) $(SGILDFLAGS) -o $*.pd_irix5 $*.o + rm $*.o + + +# ----------------------- IRIX 6.x ----------------------- +pd_irix6: $(TARGETS) + +SGICFLAGS6 = -DPD -DSGI -n32 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -Ofast=ip32 + +%.pd_irix6: %.c + $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c + $(LD) $(SGILDFLAGS) -o $*.pd_irix6 $*.o + rm $*.o + + +# ----------------------- NT ----------------------- +dll: $(TARGETS) + +PDNTCFLAGS = /W3 /WX /DPD /DNT /D__WIN32__ /DMSW /nologo + +VC="C:\Programme\Microsoft Visual Studio\Vc98" + +PDNTINCLUDE = /I. /I$(PDROOT)\tcl\include /I$(PDSRCDIR)\src /I$(VC)\include + +PDNTLDIR = $(VC)\lib + +PDNTLIB = $(PDNTLDIR)\libc.lib \ + $(PDNTLDIR)\oldnames.lib \ + $(PDNTLDIR)\kernel32.lib \ + $(PDLIBDIR)\pd.lib + +%.dll: %.c + cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c + link /dll /export:$*_setup $*.obj $(PDNTLIB) + + +pd_nt: $(TARGETS) + +MINGWCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch -mms-bitfields + +MINGWLDFLAGS = -export_dynamic -shared -lm -lkernel32 -lcoldname -lcrtdll -lpd -L$(PDLIBDIR) + +MINGWINCLUDE = -I$(PDSRCDIR) + +%.pd_nt: %.c + $(CC) $(MINGWLDFLAGS) $(MINGWCFLAGS) $(MINGWINCLUDE) -o $*.dll $*.c diff --git a/espeak~-help.pd b/espeak~-help.pd new file mode 100644 index 0000000..d396340 --- /dev/null +++ b/espeak~-help.pd @@ -0,0 +1,94 @@ +#N canvas 811 359 866 452 10; +#X obj 112 142 espeak~; +#X obj 65 188 env~; +#X floatatom 65 209 5 0 0 0 - - -; +#X obj 112 184 dac~; +#X obj 36 47 metro 5000; +#X obj 35 19 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X msg 328 32 \; pd dsp 1; +#X obj 111 80 list prepend; +#X obj 111 101 list prepend speak; +#X obj 111 122 list trim; +#X obj 113 55 t b a; +#X msg 202 125 bang; +#X obj 177 165 print info; +#X msg 319 102 voice serbian; +#X msg 241 67 dosvi denje; +#X msg 305 158 voice \$1; +#X symbolatom 305 128 0 0 0 0 - - -; +#X msg 353 218 bang; +#X msg 211 31 dobro; +#X msg 114 23 na wie geths; +#X symbolatom 236 9 0 0 0 0 - - -; +#X floatatom 71 17 5 0 0 0 - - -; +#X obj 515 148 espeak~; +#X obj 468 194 env~; +#X floatatom 468 215 5 0 0 0 - - -; +#X obj 515 190 dac~; +#X obj 439 53 metro 5000; +#X obj 438 25 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 514 86 list prepend; +#X obj 514 107 list prepend speak; +#X obj 514 128 list trim; +#X obj 516 61 t b a; +#X msg 605 131 bang; +#X obj 580 171 print info; +#X msg 722 108 voice serbian; +#X msg 644 73 dosvi denje; +#X msg 708 164 voice \$1; +#X symbolatom 708 134 0 0 0 0 - - -; +#X msg 756 224 bang; +#X msg 614 37 dobro; +#X msg 517 29 na wie geths; +#X symbolatom 639 15 0 0 0 0 - - -; +#X floatatom 474 23 5 0 0 0 - - -; +#X msg 127 364 das ist ein ganz schon langer text ich weiss auch nicht +mehr was ich jetzt noch schreiben soll; +#X msg 145 308 das ist ein ganz schon langer text ich weiss auch nicht +; +#X connect 0 0 1 0; +#X connect 0 0 3 0; +#X connect 0 1 12 0; +#X connect 1 0 2 0; +#X connect 4 0 7 0; +#X connect 5 0 4 0; +#X connect 7 0 8 0; +#X connect 8 0 9 0; +#X connect 9 0 0 0; +#X connect 10 0 7 0; +#X connect 10 1 7 1; +#X connect 11 0 0 0; +#X connect 13 0 0 0; +#X connect 14 0 10 0; +#X connect 15 0 0 0; +#X connect 16 0 15 0; +#X connect 17 0 16 0; +#X connect 18 0 10 0; +#X connect 19 0 10 0; +#X connect 20 0 10 0; +#X connect 21 0 4 1; +#X connect 22 0 23 0; +#X connect 22 0 25 0; +#X connect 22 1 33 0; +#X connect 23 0 24 0; +#X connect 26 0 28 0; +#X connect 27 0 26 0; +#X connect 28 0 29 0; +#X connect 29 0 30 0; +#X connect 30 0 22 0; +#X connect 31 0 28 0; +#X connect 31 1 28 1; +#X connect 32 0 22 0; +#X connect 34 0 22 0; +#X connect 35 0 31 0; +#X connect 36 0 22 0; +#X connect 37 0 36 0; +#X connect 38 0 37 0; +#X connect 39 0 31 0; +#X connect 40 0 31 0; +#X connect 41 0 31 0; +#X connect 42 0 26 1; +#X connect 43 0 10 0; +#X connect 44 0 10 0; 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