Welcome from the Palm Developer blog! Looking for binaries?
Having trouble posting your app or an update to your app using the provided sdltts? Either you're missing features or you want/need a callback from the method when it's done, or maybe you want only a few text strings in your app and don't want to keep generating them? If you use the provided sdltts, there isn't much you can do about most of your problems.
So I worked a little on re-creating the binary myself, I like doing these sort of exploratory projects. I'll put the diff and necessary scripts below, but first, here's the status:
On Touchpad:
- Runs just like the given binary when used in their provided app in place of the sdltts binary.
- Update 10/12/11: Runs in separate thread, thanks to unwiredben.
On Emulator:
- WORKS inside the application. (As of 10/9/11 11:48AM)
Code
Download the library's source for release 1.4 and make these changes.
main/Makefile diff:
diff -ur flite-1.4-release/main/Makefile flite-1.4-webos/main/Makefile
--- flite-1.4-release/main/Makefile 2009-08-14 14:11:07.000000000 -0700
+++ flite-1.4-webos//main/Makefile 2011-10-08 01:21:54.012426846 -0700
@@ -38,13 +38,13 @@
DIRNAME=main
BUILD_DIRS =
ALL_DIRS=
-SRCS = flite_main.c flite_time_main.c t2p_main.c compile_regexes.c
+SRCS = flite_main.c sdltts.c flite_time_main.c t2p_main.c compile_regexes.c
OBJS = $(SRCS:.c=.o) flite_voice_list.o
FILES = Makefile $(SRCS)
LOCAL_INCLUDES =
ALL = shared_libs \
- $(BINDIR)/flite$(EXEEXT) \
+ $(BINDIR)/sdltts$(EXEEXT) \
$(BINDIR)/t2p$(EXEEXT) $(BINDIR)/compile_regexes$(EXEEXT) \
flite_voice_list.c each $(EXTRABINS)
@@ -70,6 +70,7 @@
flite_time_LIBS_deps = $(flite_time_LIBS:%=$(LIBDIR)/lib%.a)
LOCAL_CLEAN = $(BINDIR)/flite$(EXEEXT) $(BINDIR)/flite_time$(EXEEXT) \
+ $(BINDIR)/sdltts$(EXEEXT) \
$(BINDIR)/t2p$(EXEEXT) \
$(SHAREDARLIBS) $(SHAREDLIBS) $(VERSIONSHAREDLIBS) \
$(flite_LIBS_deps) $(VOICES:%=$(BINDIR)/flite_%)
@@ -81,6 +82,12 @@
shared_libs: nothing
endif
+$(BINDIR)/sdltts$(EXEEXT): sdltts.o $(flite_LIBS_deps)
+ $(TOP)/tools/make_voice_list $(VOICES)
+ rm -f flite_voice_list.o
+ $(MAKE) flite_voice_list.o
+ $(CC) $(CFLAGS) -o $@ sdltts.o flite_voice_list.o $(flite_LIBS_flags) $(LDFLAGS)
+
$(BINDIR)/flite$(EXEEXT): flite_main.o $(flite_LIBS_deps)
$(TOP)/tools/make_voice_list $(VOICES)
rm -f flite_voice_list.o
@@ -103,11 +111,11 @@
$(MAKE) VOICE=$$i $(BINDIR)/flite_$$i ; \
done
-$(BINDIR)/flite_${VOICE}: flite_main.o $(flite_LIBS_deps)
+$(BINDIR)/flite_${VOICE}: sdltts.o $(flite_LIBS_deps)
$(TOP)/tools/make_voice_list $(VOICE)
rm -f flite_voice_list.o
$(MAKE) flite_voice_list.o
- $(CC) $(CFLAGS) -o $@ flite_main.o flite_voice_list.o $(flite_LIBS_flags) $(LDFLAGS)
+ $(CC) $(CFLAGS) -o $@ sdltts.o flite_voice_list.o $(flite_LIBS_flags) $(LDFLAGS)
install:
# The basic binaries
tools/Makefile.flite diff:
Use this diff too if you want to use only one voice at a time. It outputs smaller binaries next to sdltts.
diff -ur flite-1.4-release/tools/Makefile.flite flite-1.4-webos/tools/Makefile.flite
--- flite-1.4-release/tools/Makefile.flite 2009-08-22 11:24:37.000000000 -0700
+++ flite-1.4-webos//tools/Makefile.flite 2011-10-09 04:29:37.264633493 -0700
@@ -102,8 +102,8 @@
$(VOICENAME)_mcep.o: $(VOICENAME)_mcep.c
$(CC) -I. -I$(FLITEDIR)/include -c -o $@ $<
-flite_$(VOICENAME): flite_main.o flite_voice_list.o $(FLITELIBS) lib$(VOICENAME).a
- $(CC) $(CFLAGS) -o $@ flite_main.o flite_voice_list.o $(LOCAL_LIBS) $(LOCAL_LANGLEX_LIBS) $(FLITELIBFLAGS) $(LDFLAGS)
+flite_$(VOICENAME): sdltts.o flite_voice_list.o $(FLITELIBS) lib$(VOICENAME).a
+ $(CC) $(CFLAGS) -o $@ sdltts.o flite_voice_list.o $(LOCAL_LIBS) $(LOCAL_LANGLEX_LIBS) $(FLITELIBFLAGS) $(LDFLAGS)
.build_lib: $(OBJS)
@ $(AR) cruv $(LIBDIR)/lib$(VOICENAME).a $(OBJS)
new main/sdltts.c file:
Update 10/12/11: It might be late for most of you, but unwiredben just sent an updated sdltts.c. It runs the audio in a separate thread so your javascript can continue unabated. Thanks Ben!
His version (it doesn't compile) is at https://gist.github.com/1281621. The one below compiles and is available down at the bottom.
/*************************************************************************/
/* */
/* Language Technologies Institute */
/* Carnegie Mellon University */
/* Copyright (c) 2001 */
/* All Rights Reserved. */
/* */
/* Fahrzin Hemmati */
/* Copyright (c) 2011 */
/* */
/* 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. */
/* 5. Modifications must be sent back to the author at their provided */
/* email address. */
/* */
/* CARNEGIE MELLON UNIVERSITY 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 CARNEGIE MELLON UNIVERSITY 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: Fahrzin Hemmati (fahhem@fahhem.com) */
/* Date: October 2011 */
/*************************************************************************/
/* */
/* Flite as a Hybrid PDK plugin */
/* */
/*************************************************************************/
#include "flite.h"
#include "flite_version.h"
#include "SDL.h"
#include "SDL_mixer.h"
#include "PDL.h"
extern cst_val *flite_set_voice_list(void);
void playText(const char * text) {
cst_wave * w;
w = flite_text_to_wave(text, flite_voice_select(NULL));
if(Mix_OpenAudio(w->sample_rate, AUDIO_S16SYS, w->num_channels, 4096))
exit(1);
Mix_Chunk * sound = Mix_QuickLoad_RAW((Uint8*)w->samples,w->num_samples*sizeof(short));
if(sound == NULL)
exit(2);
int channel = Mix_PlayChannel(-1, sound, 0);
if(channel == -1)
exit(3);
while(Mix_Playing(channel) != 0);
Mix_FreeChunk(sound);
Mix_CloseAudio();
}
PDL_bool playAudio(PDL_JSParameters * parms) {
const char * text = PDL_GetJSParamString(parms,0);
/* since we don't process this in the method thread, instead post a
* SDL event that will be received in the main thread and used to
* launch the code. */
SDL_Event event;
event.user.type = SDL_USEREVENT;
event.user.code = 0;
event.user.data1 = strdup(text);
SDL_PushEvent(&event);
PDL_JSReply(parms, "{}");
return 0;
}
void TTS_Init() {
flite_init();
flite_voice_list = flite_set_voice_list();
}
int main(int argc, char ** argv) {
if(argc==2)
{
// don't do SDL loop
flite_init();
flite_voice_list = flite_set_voice_list();
playText(argv[1]);
exit(0);
return 0;
}
// Initializes the video subsystem
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0) {
exit(1);
}
PDL_Init(0);
TTS_Init();
atexit(SDL_Quit);
atexit(PDL_Quit);
PDL_RegisterJSHandler("playAudio",playAudio);
PDL_JSRegistrationComplete();
PDL_CallJS("ready", NULL, 0);
SDL_Event Event;
while (1) {
SDL_WaitEvent(&Event);
if(Event.type == SDL_USEREVENT && Event.user.code == 0) {
playText((const char *)Event.user.data1);
PDL_CallJS("playbackComplete", NULL, 0);
free(Event.user.data1);
}
if(Event.type == SDL_QUIT) exit(0);
}
}
new make_for_dev.sh script:
export CFLAGS="-I/opt/PalmPDK/include/ -I/opt/PalmPDK/include/SDL/"
export LDFLAGS="-L/opt/PalmPDK/device/lib/ -lSDL -lSDL_mixer -lpdl -Wl,--allow-shlib-undefined"
export PATH=$PATH:/opt/PalmPDK/arm-gcc/bin
if [ x$1 != xclean ]; then
./configure --host=arm-none-linux-gnueabi
fi
make $*
new make_for_emu.sh script:
export CFLAGS="-I/opt/PalmPDK/include -I/opt/PalmPDK/include/SDL"
export LDFLAGS="-L/opt/PalmPDK/emulator/lib/ -lSDL -lSDL_mixer -lpdl -Wl,--allow-shlib-undefined"
export PATH=$PATH:/home/fahhem/projects/widk/sourcery/ia32-2010.09/bin/
if [ x$1 != xclean ]; then
./configure --host=i686-pc-linux-gnu
fi
make $*
Move the ttstest_plugin_appinfo.json to sdltts_plugin_appinfo.json inside the given app/ because that was misnamed.
Compiling and running
With those files in place, just run make_for_dev.sh
or make_for_emu.sh
and you'll have your new binary as bin/sdltts
. If you want to use only one voice at a time, you can use any of the bin/flite_$(VOICE)
binaries instead, and they're smaller as a result. Now run this script after compiling in order to send it to your device/emulator:
cp ../flite-1.4-webos/bin/sdltts app/sdltts # or copy bin/flite_cmu_us_kal to match the binary from HP
cp -r app app-pkg
# remove provided sdl app
rm app-pkg/arm_sdltts
# palm-package
palm-package app-pkg
# install ipk
palm-install com.joshondesign.webos.ttstest_1.0.0_all.ipk
rm -r app-pkg
That's it. It'll install it to whatever palm-install sends to.
On the device, you can just open the app and click the button and everything works fine. You can also run it via novaterm or ssh-ing in (if you ran pdk-device-install) by sending the text over the command line, triggering the if(argc==2) branch of main(), bypassing the SDL loop.
/media/cryptofs/apps/usr/palm/applications/com.joshondesign.webos.ttstest/sdltts "text to say"
The emulator is basically the same as the device, except you have to chmod it.
chmod +x /media/cryptofs/apps/usr/palm/applications/com.joshondesign.webos.ttstest/sdltts
/media/cryptofs/apps/usr/palm/applications/com.joshondesign.webos.ttstest/sdltts "text to say"
Conclusion
Now you have the source to your own binary and can build any extensions that you want. My only request is, according to part 5 of the license, is that you send me your changes to the code (I'll post it online unless you request otherwise). I didn't do this to win the contest since I already have a Touchpad, so the least you could do if you use my code to enter the contest (or for your own app in general) is to share back.
Update 10/9/11 11:48AM: I got it working on the emulator. Here are binaries for the single voice that HP gives for both the Touchpad and the emulator. You can use the instructions above to get those exact binaries (they will be at bin/flite_cmu_us_kal) or just download those to use.
Binaries:
You can download any of the following voices, choose the right platform and rename it to sdltts (or change your code):
Voice | MD5 Touchpad | MD5 Emulator | ||
cmu\_us\_kal\* | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_us_kal) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_us_kal) | f94548eb870e474e5cb435043fbef9bc | 35dd88db5f670674274257d04785472e |
cmu\_time\_awb | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_time_awb) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_time_awb) | 563409f4f00805fc17acc88ab399445c | baef75b0d8f1524a7bc8ee5fee05d622 |
cmu\_us\_awb | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_us_awb) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_us_awb) | 853b66b94dcf5e3beb265f6559034872 | 76cb6e33daaebfd6e51a880a710f4ed9 |
cmu\_us\_kal16 | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_us_kal16) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_us_kal16) | 1885f3383126bffaa9d767e2f3ed2186 | 38ec555a367c00c80645a87f4d614a43 |
cmu\_us\_rms | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_us_rms) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_us_rms) | 0c9538b69f0daa00970e48986f3112de | 88b812f0bc941d0347721759d1d55024 |
cmu\_us\_slt | [Touchpad](http://fahhem.com/webos/arm/flite_cmu_us_slt) | [Emulator](http://fahhem.com/webos/x86/flite_cmu_us_slt) | 4c85a417f3b81ad151431b12a5e8876d | 92804c22df06922d3d266dd60d7ff56f |
* HP gave everyone cmu_us_kal, so you can use any of the others if you want a little more distinction
Update 10/12/11: These binaries now play the audio in a background thread and call "playbackComplete" when finished.