new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+TARGETS=player src
+
+all:
+ @for i in $(TARGETS); \
+ do \
+ make --no-print-directory -C $$i all; \
+ done
+
+.PHONY: clean distclean
+
+clean:
+ @for i in $(TARGETS); \
+ do \
+ make --no-print-directory -C $$i clean; \
+ done
+ @rm -f *~ include/*~
+
+distclean:
+ @for i in $(TARGETS); \
+ do \
+ make --no-print-directory -C $$i distclean; \
+ done
+
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+Projekt VirtualReader
+
+Authors : Klaus_Dieter, bordi, mbroeker
+Maintainer : mbroeker
+
+LINKS:
+http://www.atip.de/index.php?option=com_content&task=view&id=46&Itemid=74
+MBrola Project: http://tcts.fpms.ac.be/synthesis/mbrola.html
+ - http://www.ikp.uni-bonn.de/dt/forsch/phonetik/hadifix/txt2pho.zip
+Festival Synth: http://www.cstr.ed.ac.uk/projects/festival
+ - install festival and copy text2wave to /usr/local/bin
+
+Requirements:
+ 1. MBROLA, FESTIVAL or Proser TTS-System
+ 2. txt2phpo, preproc and pipeflt for mbrola,
+ text2wave for festival
+ 3. SDL-1.2.x
+
+Directory Structure for /opt/mbrola
+drwxr-xr-x 2 root root 144 2007-12-20 09:24 bin
+drwxr-xr-x 2 root root 840 2007-08-23 17:56 data
+drwxr-xr-x 3 root root 152 2002-11-07 11:48 de5
+drwxr-xr-x 2 root root 80 2007-08-23 17:54 doc
+-rw-r--r-- 1 root root 5836 2007-08-23 17:57 Rules.lst
new file mode 100755
--- /dev/null
+++ b/bin/festival_write_wav
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+file=$1
+
+eval "cat $file |\
+text2wave - -o $2"
+
+
+
new file mode 100755
--- /dev/null
+++ b/bin/mbrola_write_wav
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+ROOT=/opt/mbrola # Where are the needed files?
+VOICE=$ROOT/de5/de5 # Path to the mbrola-voice
+SEX=f # m/f Which sex has your voice?
+
+file=$1
+
+eval "cat $file |\
+$ROOT/bin/pipefilt |\
+$ROOT/bin/preproc $ROOT/Rules.lst $ROOT/data/hadifix.abk |\
+$ROOT/bin/txt2pho -$SEX -p $ROOT/data/ |\
+$ROOT/bin/mbrola $VOICE - $2"
new file mode 100644
--- /dev/null
+++ b/include/MBrola.h
@@ -0,0 +1,9 @@
+/**
+ * $Id: MBrola.h 48 2008-01-09 23:59:19Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/MBrola.h $
+ */
+
+#ifndef MBROLA_H
+#define MBROLA_H
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/audioplayer.h
@@ -0,0 +1,54 @@
+/**
+ * $Id: audioplayer.h 48 2008-01-09 23:59:19Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/audioplayer.h $
+ */
+
+#ifndef __AUDIOPLAYER_H__
+#define __AUDIOPLAYER_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <SDL/SDL.h>
+
+/* audioplayer(filename, milliseconds, position) */
+int audioplayer (char *, Uint32);
+
+/* initializes the sdl-soundsystem and prepares local structures */
+int audio_init ();
+
+/* closes the sdl-soundsystem and frees local structures */
+void audio_shutdown ();
+
+/* audioplayer_getwavelength(filename) */
+Uint32 audioplayer_getwavelength (char *);
+
+/* returns the bitrate of the wave-file */
+int audioplayer_getbitrate ();
+
+/* stopps playback immediately */
+void audioplayer_stop ();
+
+/* returns the current time in ms */
+Uint32 audioplayer_gettime ();
+
+/* sets the current position in ms */
+void audioplayer_settime (long);
+
+/* returns the length of the RIFF in ms */
+Uint32 audioplayer_getsoundlen ();
+
+/* returns the current position */
+Uint32 audioplayer_getposition ();
+
+/* wait replaces sdl_delay */
+void audioplayer_delay (Uint32);
+
+/* switches verbosity on/off */
+void audioplayer_setverbose (int);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/festival_interface.h
@@ -0,0 +1,31 @@
+/**
+ * $Id: festival_interface.h 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/festival_interface.h $
+ */
+
+#ifndef __FESTIVAL_INTERFACE_H__
+#define __FESTIVAL_INTERFACE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+
+typedef struct {
+ char *TextFile;
+ char *AudioFile;
+ char *Voice;
+ char *Path;
+} tts_options;
+
+typedef struct {
+} ttshandles;
+
+tts_options interface_get_cl_opts (int, char **);
+
+int interface_write_to_wav (char *, char *, ttshandles, tts_options);
+ttshandles interface_init (tts_options);
+long *interface_get_timing (ttshandles, char *);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/interface.h
@@ -0,0 +1,21 @@
+/**
+ * $Id: interface.h 48 2008-01-09 23:59:19Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/interface.h $
+ */
+
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#ifdef PROSER
+#include <proser_interface.h>
+#endif
+
+#ifdef MBROLA
+#include <mbrola_interface.h>
+#endif
+
+#ifdef FESTIVAL
+#include <festival_interface.h>
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/keyboard.h
@@ -0,0 +1,18 @@
+/**
+ * $Id: keyboard.h 48 2008-01-09 23:59:19Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/keyboard.h $
+ */
+
+#ifndef __KEYBOARD_H__
+#define __KEYBOARD_H__
+
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#ifdef DEBUG
+#include <ctype.h>
+#endif
+
+char getSingleKey (void);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/mbrola_interface.h
@@ -0,0 +1,31 @@
+/**
+ * $Id: mbrola_interface.h 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/mbrola_interface.h $
+ */
+
+#ifndef __MBROLA_INTERFACE_H__
+#define __MBROLA_INTERFACE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <MBrola.h>
+
+typedef struct {
+ char *TextFile;
+ char *AudioFile;
+ char *Voice;
+ char *Path;
+} tts_options;
+
+typedef struct {
+} ttshandles;
+
+tts_options interface_get_cl_opts (int, char **);
+
+int interface_write_to_wav (char *, char *, ttshandles, tts_options);
+ttshandles interface_init (tts_options);
+long *interface_get_timing (ttshandles, char *);
+#endif
new file mode 100644
--- /dev/null
+++ b/include/proser_interface.h
@@ -0,0 +1,37 @@
+/**
+ * $Id: proser_interface.h 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/proser_interface.h $
+ */
+
+#ifndef __PROSER_INTERFACE_H__
+#define __PROSER_INTERFACE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <Proser.h>
+
+typedef struct {
+ char *TextFile;
+ char *AudioFile;
+ char *Voice;
+ char *Path;
+ float PreEmphasis;
+ float Speed;
+ AudioType Stype;
+ OUTTYPE FileType;
+ // nicht ganz so schön, aber funktioniert
+ PROOPT ProserOpt;
+} tts_options;
+
+typedef struct {
+ NLPBLOCK GermanNlp;
+} ttshandles;
+
+tts_options interface_get_cl_opts (int, char **);
+
+int interface_write_to_wav (char *, char *, ttshandles, tts_options);
+ttshandles interface_init (tts_options);
+long *interface_get_timing (ttshandles, char *);
+#endif
new file mode 100644
--- /dev/null
+++ b/include/sentence.h
@@ -0,0 +1,28 @@
+/**
+ * $Id: sentence.h 48 2008-01-09 23:59:19Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/sentence.h $
+ */
+
+#ifndef __SENTENCE_H__
+#define __SENTENCE_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/* prepares the text */
+int *parse (char *);
+
+/* reads a textfile */
+char *readbuffer (char *);
+
+/* extracts a substring from a buffer */
+char *getSentence (char *, int, int);
+
+/* counts the words of a string */
+int words (char *);
+
+char **getstrings (char *, int *);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/thread.h
@@ -0,0 +1,37 @@
+/**
+ * $Id: thread.h 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/include/thread.h $
+ */
+
+#ifndef __THREAD_H__
+#define __THREAD_H__
+
+#include <pthread.h>
+#include <sentence.h>
+#include <interface.h>
+#include <audioplayer.h>
+
+#ifndef TIMEOUT
+#define TIMEOUT 186
+#endif
+
+typedef struct {
+ int satz;
+ int items;
+ char *fname;
+ tts_options ttsopt;
+ ttshandles ttsh;
+ char **sentences;
+ long **timings;
+} ThreadData;
+
+/* reads the wavefiles from disk */
+void readtext (ThreadData *);
+
+/* stores the data on the harddisk */
+void writewav (ThreadData *);
+
+/* (re)starts a thread */
+int p_thread_restart (pthread_t, void *, ThreadData *);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/player/Makefile
@@ -0,0 +1,34 @@
+ CC = gcc
+CFLAGS = -Wall -O2 -DLINUX -DWINAPI="" $(shell sdl-config --cflags)
+INCLUDE= -I../include
+LDFLAGS = -Wl,-rpath,lib $(shell sdl-config --libs)
+ DEBUG = -g -ggdb
+TARGET = ../bin/audioplayer
+OBJECTS = \
+ main.o \
+ audioplayer.o
+
+.c.o:
+ @$(CC) -c $(CFLAGS) $(INCLUDE) $(DEBUG) -o $@ $<
+ @echo "CC $<"
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ @$(CC) $(OBJECTS) $(LDFLAGS) -o $@
+ @echo "LD OBJECTS -o $@"
+
+.PHONY: clean distclean
+
+clean:
+ @rm -f *.o *~
+ @echo "CLEANING $$PWD"
+
+distclean:
+ @make clean
+ @rm -f $(TARGET)
+ @echo "WIPING $$PWD OUT"
+
+install: $(TARGET)
+ install -m 755 $(TARGET) ~/bin/
+
new file mode 100644
--- /dev/null
+++ b/player/audioplayer.c
@@ -0,0 +1,228 @@
+/**
+ * $Id: audioplayer.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/player/audioplayer.c $
+ */
+
+#include <audioplayer.h>
+
+typedef struct {
+ SDL_AudioSpec spec; // internal structure
+ Uint8 *sound_buffer; // malloced pointer from sdl
+ Uint32 sound_pos; // position
+ Uint32 sound_len; // length in bytes
+ Uint32 length; // Length in Milliseconds
+
+ int opened; // bool opened
+ int loaded; // bool loaded
+ int verbose; // verbose messages
+ int timeout; // timeout
+ int timer; // bool timer
+} AudioDevice;
+
+AudioDevice AD;
+
+int audio_init ()
+{
+ // initialize SDL for audio output
+ if (SDL_Init (SDL_INIT_AUDIO) < 0) {
+ fprintf (stderr, "audio_init: Cannot initialize SDL-Subsystem\n");
+ return -1;
+ }
+
+ AD.sound_buffer = 0;
+ AD.sound_pos = 0;
+ AD.sound_len = 0;
+
+ AD.opened = 0;
+ AD.loaded = 0;
+ AD.verbose = 0;
+
+ AD.timeout = 0;
+ AD.timer = 0;
+
+ return 0;
+}
+
+void audio_shutdown ()
+{
+ // quit sdl
+ SDL_AudioQuit ();
+ SDL_Quit ();
+}
+
+static void Callback (void *userdata, Uint8 * stream, int len)
+{
+ Uint8 *waveptr = NULL;
+
+ /*
+ * loaded = 0 Segmentation fault
+ * len = 0 nothing to play
+ */
+ if (!(AD.loaded && len))
+ return;
+
+ waveptr = AD.sound_buffer + AD.sound_pos;
+ SDL_MixAudio (stream, waveptr, len, SDL_MIX_MAXVOLUME);
+ AD.sound_pos += len; // bereits gespielt
+
+ if (audioplayer_gettime () > (AD.length - AD.timeout)) {
+ AD.sound_pos = AD.length;
+ AD.sound_len = 0;
+ AD.timer = 0;
+ }
+}
+
+Uint32 audioplayer_getsoundlen ()
+{
+ return AD.sound_len;
+}
+
+void audioplayer_media_info (char *fname)
+{
+ AD.length = audioplayer_getwavelength (fname);
+
+ printf ("Playing %s: %d Hz, %d Bit Audio, %d Channel(s), %3.2d ms\n",
+ fname, AD.spec.freq, audioplayer_getbitrate (), AD.spec.channels, AD.length);
+}
+
+int audioplayer_getbitrate ()
+{
+ int bitrate = 0;
+
+ switch (AD.spec.format) {
+ case AUDIO_U8:
+ case AUDIO_S8:
+ bitrate = 8;
+ break;
+ case AUDIO_S16LSB:
+ case AUDIO_S16MSB:
+ case AUDIO_U16LSB:
+ case AUDIO_U16MSB:
+ bitrate = 16;
+ break;
+ }
+
+ return bitrate;
+}
+
+Uint32 audioplayer_getwavelength (char *fname)
+{
+ struct stat info;
+ Uint32 value = 0;
+
+ if (fname == NULL)
+ return AD.length;
+
+ if (stat (fname, &info) == 0)
+ /*
+ * the value is really big, so be carefull
+ * changes in the order result in different values
+ * the storage type isn`t well choosen...
+ */
+ value = ((info.st_size) / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0);
+
+ return (value);
+}
+
+Uint32 audioplayer_getposition ()
+{
+ return AD.sound_pos;
+}
+
+Uint32 audioplayer_gettime ()
+{
+ Uint32 ret;
+
+ ret = AD.sound_pos / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0;
+
+ return ret;
+}
+
+void audioplayer_settime (long tm)
+{
+ AD.sound_pos = tm / 1000.0 * (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0));
+
+ /*
+ * Eine Adresse ...
+ */
+ while ((AD.sound_pos % 2) != 0)
+ AD.sound_pos++;
+
+ if (AD.verbose)
+ printf ("\e[31m[ATTENTION]\e[37m [#%d/#%d] = %d ms\n", AD.sound_pos, AD.sound_len, audioplayer_gettime ());
+}
+
+void audioplayer_stop ()
+{
+ /*
+ * stops the callback function
+ */
+ SDL_PauseAudio (1);
+ AD.spec.callback = NULL;
+
+ if (AD.loaded == 1)
+ SDL_FreeWAV (AD.sound_buffer);
+
+ AD.loaded = 0;
+ AD.timer = 0;
+}
+
+void audioplayer_delay (Uint32 milliseconds)
+{
+ struct timespec tm;
+
+ tm.tv_sec = 0;
+ tm.tv_nsec = milliseconds * 1000;
+
+ while (AD.timer)
+ nanosleep (&tm, NULL);
+}
+
+void audioplayer_setverbose (int verbose)
+{
+ AD.verbose = verbose;
+}
+
+int audioplayer (char *fname, Uint32 timeout)
+{
+ if (SDL_LoadWAV (fname, &AD.spec, &AD.sound_buffer, &AD.sound_len) == NULL) {
+ printf ("SDL: %s\n", SDL_GetError ());
+ return -1;
+ }
+
+ AD.loaded = 1;
+
+ if (!AD.opened) {
+ AD.spec.callback = Callback;
+ if (SDL_OpenAudio (&AD.spec, NULL) < 0) {
+ fprintf (stderr, "Cannot open audio device: %s\n", SDL_GetError ());
+ return -1;
+ }
+ AD.opened = 1;
+ }
+
+ /*
+ * calls implicitly getwavelength
+ */
+ audioplayer_media_info (fname);
+
+ AD.sound_pos = 0;
+
+ /*
+ * starts playback via Callback function
+ */
+ SDL_PauseAudio (0);
+
+ /*
+ * initializes the timeout mechanism
+ */
+ AD.timer = 1;
+ AD.timeout = timeout;
+
+ /*
+ * controlled delay
+ */
+ audioplayer_delay (timeout);
+
+ return 0;
+}
new file mode 100644
--- /dev/null
+++ b/player/main.c
@@ -0,0 +1,50 @@
+/**
+ * $Id: main.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/player/main.c $
+ */
+
+#include <audioplayer.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#define TIMEOUT 186
+
+void help (char *prgname)
+{
+ printf ("Usage: %s [-h] sndfile1,[sndfile2,...]\n", prgname);
+ printf ("\t sndfile\t: a valid wave file\n");
+ printf ("\t-h help \t: shows this screen\n");
+}
+
+int main (int argc, char **argv)
+{
+ int i;
+
+ while ((i = getopt (argc, argv, "h")) > 0) {
+ switch (i) {
+ case 'h':
+ help (argv[0]);
+ exit (0);
+ break;
+ default:
+ printf ("Unknown Option %c\n", i);
+ help (argv[0]);
+ exit (0);
+ }
+ }
+
+ if (argc == optind) {
+ help (argv[0]);
+ exit (0);
+ }
+
+ audio_init ();
+
+ for (i = optind; i < argc; i++) {
+ audioplayer (argv[i], TIMEOUT);
+ audioplayer_stop ();
+ }
+
+ audio_shutdown ();
+ return 0;
+}
new file mode 100755
--- /dev/null
+++ b/run
@@ -0,0 +1,68 @@
+#!/bin/bash
+# $Header: /work/c/VirtualReader/run-20070320,v 1.3 2007/03/20 20:00:00 bordi $
+
+VALGRIND="$(which valgrind)"
+STRACE="$(which strace)"
+GDB="$(which gdb)"
+DDD="$(which ddd)"
+SPLINT="$(which splint)"
+BUILD="make -C src"
+PROG="bin/vreader"
+FILE="test.txt"
+OPTIONS="-i ${FILE} -v voice/De_Carla_22kHz -p data -format WAV -o test.wav"
+
+$BUILD
+if [ $? == 0 ]
+ then
+ echo
+ echo " VirtualReader - Version 0.1"
+ echo
+ echo " Navigation Keys:"
+ echo " ##############################"
+ echo " # i: next word #"
+ echo " # j: previous sentence #"
+ echo " # k: previous word #"
+ echo " # l: next sentence #"
+ echo " # p: print position #"
+ echo " # q: quit #"
+ echo " # r: reset to first position #"
+ echo " # s: print current sentence #"
+ echo " # v: switch verbosity on/off #"
+ echo " ##############################"
+ echo " Press ENTER to Start"
+ read
+ case $1 in
+ valgrind)
+ $VALGRIND $PROG $OPTIONS
+ ;;
+ strace)
+ $STRACE $PROG $OPTIONS
+ ;;
+ gdb)
+ echo "break 67">gdb.exec
+ echo "r $OPTIONS" >> gdb.exec
+ DEBUG=1 $GDB -x gdb.exec $PROG
+ rm -f gdb.exec
+ ;;
+ ddd)
+ echo "break 67">gdb.exec
+ echo "r $OPTIONS" >> gdb.exec
+ $DDD -x gdb.exec $PROG
+ rm -f gdb.exec
+ ;;
+ splint)
+ $SPLINT -Iinclude -DMBROLA -warnposix src/main.c
+ ;;
+ help)
+ echo "Usage: run [commands]"
+ echo "valid commands are: strace, gdb, \
+ddd, valgrind and help"
+ exit 0
+ ;;
+ *)
+ $PROG $OPTIONS
+ ;;
+ esac
+fi
+
+rm -f audio/*.wav;
new file mode 100644
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,62 @@
+###### USER CONFIG ###############
+TARGET = ../bin/vreader #
+MBROLA = /opt/mbrola/bin/mbrola #
+FESTIVAL= /usr/bin/festival #
+INSTDIR = ~/bin #
+##### USER CONFIG ENDS ###########
+
+ CC = gcc
+MCFLAGS = -Wall -O2 -DMBROLA $(shell sdl-config --cflags)
+FCFLAGS = -Wall -O2 -DFESTIVAL $(shell sdl-config --cflags)
+PCFLAGS = -Wall -O2 -DPROSER -DLINUX -DWINAPI="" $(shell sdl-config --cflags)
+INCLUDE = -I../include
+LDFLAGS = -Wl,-rpath,lib -L../lib $(shell sdl-config --libs)
+ DEBUG = -g -ggdb
+OBJECTS = \
+ main.o \
+ sentence.o \
+ keyboard.o \
+ thread.o \
+ audioplayer.o \
+ proser_interface.o \
+ mbrola_interface.o \
+ festival_interface.o
+
+.c.o:
+ @if [ -f ../lib/libProserGerman.a ]; \
+ then \
+ $(CC) -c $(PCFLAGS) $(INCLUDE) $(DEBUG) -o $@ $<; \
+ elif [ -x $(MBROLA) ]; \
+ then \
+ $(CC) -c $(MCFLAGS) $(INCLUDE) $(DEBUG) -o $@ $<; \
+ elif [ -x $(FESTIVAL) ]; \
+ then \
+ $(CC) -c $(FCFLAGS) $(INCLUDE) $(DEBUG) -o $@ $<; \
+ else \
+ echo "Cannot find any TTS-System on your Machine"; \
+ fi;
+ @echo "CC $<"
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ @if [ -f ../lib/libProserGerman.a ]; \
+ then \
+ $(CC) $(OBJECTS) $(LDFLAGS) -lProserGerman -o $@; \
+ else \
+ $(CC) $(OBJECTS) $(LDFLAGS) -o $@; fi
+ @echo "LD OBJECTS -o $@"
+
+.PHONY: clean distclean
+
+clean:
+ @rm -f *.o *~
+ @echo "CLEANING $$PWD"
+
+distclean:
+ @make clean
+ @rm -f $(TARGET)
+ @echo "WIPING $$PWD OUT"
+
+install: $(TARGET)
+ install -m 755 $(TARGET) $(INSTDIR)
new file mode 100644
--- /dev/null
+++ b/src/audioplayer.c
@@ -0,0 +1,232 @@
+/**
+ * $Id: audioplayer.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/audioplayer.c $
+ */
+
+#include <audioplayer.h>
+
+typedef struct {
+ SDL_AudioSpec spec; // internal structure
+ Uint8 *sound_buffer; // malloced pointer from sdl
+ Uint32 sound_pos; // position
+ Uint32 sound_len; // length in bytes
+ Uint32 length; // Length in Milliseconds
+
+ int opened; // bool opened
+ int loaded; // bool loaded
+ int verbose; // verbose messages
+ int timeout; // timeout
+ int timer; // bool timer
+} AudioDevice;
+
+AudioDevice AD;
+
+int audio_init ()
+{
+ /*
+ * initialize SDL for audio output
+ */
+ if (SDL_Init (SDL_INIT_AUDIO) < 0) {
+ fprintf (stderr, "audio_init: Cannot initialize SDL-Subsystem\n");
+ return -1;
+ }
+
+ AD.sound_buffer = 0;
+ AD.sound_pos = 0;
+ AD.sound_len = 0;
+
+ AD.opened = 0;
+ AD.loaded = 0;
+ AD.verbose = 0;
+
+ AD.timeout = 0;
+ AD.timer = 0;
+
+ return 0;
+}
+
+void audio_shutdown ()
+{
+ /*
+ * quit sdl
+ */
+ SDL_AudioQuit ();
+ SDL_Quit ();
+}
+
+static void Callback (void *userdata, Uint8 * stream, int len)
+{
+ Uint8 *waveptr = NULL;
+
+ /*
+ * loaded = 0 Segmentation fault
+ * len = 0 nothing to play
+ */
+ if (!(AD.loaded && len))
+ return;
+
+ waveptr = AD.sound_buffer + AD.sound_pos;
+ SDL_MixAudio (stream, waveptr, len, SDL_MIX_MAXVOLUME);
+ AD.sound_pos += len; /* bereits gespielt */
+
+ if (audioplayer_gettime () > (AD.length - AD.timeout)) {
+ AD.sound_pos = AD.length;
+ AD.sound_len = 0;
+ AD.timer = 0;
+ }
+}
+
+Uint32 audioplayer_getsoundlen ()
+{
+ return AD.sound_len;
+}
+
+void audioplayer_media_info (char *fname)
+{
+ AD.length = audioplayer_getwavelength (fname);
+
+ printf ("Playing %s: %d Hz, %d Bit Audio, %d Channel(s), %3.2d ms\n",
+ fname, AD.spec.freq, audioplayer_getbitrate (), AD.spec.channels, AD.length);
+}
+
+int audioplayer_getbitrate ()
+{
+ int bitrate = 0;
+
+ switch (AD.spec.format) {
+ case AUDIO_U8:
+ case AUDIO_S8:
+ bitrate = 8;
+ break;
+ case AUDIO_S16LSB:
+ case AUDIO_S16MSB:
+ case AUDIO_U16LSB:
+ case AUDIO_U16MSB:
+ bitrate = 16;
+ break;
+ }
+
+ return bitrate;
+}
+
+Uint32 audioplayer_getwavelength (char *fname)
+{
+ struct stat info;
+ Uint32 value = 0;
+
+ if (fname == NULL)
+ return AD.length;
+
+ if (stat (fname, &info) == 0)
+ /*
+ * the value is really big, so be carefull
+ * changes in the order result in different values
+ * the storage type isn`t well choosen...
+ */
+ value = ((info.st_size) / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0);
+
+ return (value);
+}
+
+Uint32 audioplayer_getposition ()
+{
+ return AD.sound_pos;
+}
+
+Uint32 audioplayer_gettime ()
+{
+ Uint32 ret;
+
+ ret = AD.sound_pos / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0;
+
+ return ret;
+}
+
+void audioplayer_settime (long tm)
+{
+ AD.sound_pos = tm / 1000.0 * (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0));
+
+ /*
+ * Eine Adresse ...
+ */
+ while ((AD.sound_pos % 2) != 0)
+ AD.sound_pos++;
+
+ if (AD.verbose)
+ printf ("\e[31m[ATTENTION]\e[37m [#%d/#%d] = %d ms\n", AD.sound_pos, AD.sound_len, audioplayer_gettime ());
+}
+
+void audioplayer_stop ()
+{
+ /*
+ * stops the callback function
+ */
+ SDL_PauseAudio (1);
+ AD.spec.callback = NULL;
+
+ if (AD.loaded == 1)
+ SDL_FreeWAV (AD.sound_buffer);
+
+ AD.loaded = 0;
+ AD.timer = 0;
+}
+
+void audioplayer_delay (Uint32 milliseconds)
+{
+ struct timespec tm;
+
+ tm.tv_sec = 0;
+ tm.tv_nsec = milliseconds * 1000;
+
+ while (AD.timer)
+ nanosleep (&tm, NULL);
+}
+
+void audioplayer_setverbose (int verbose)
+{
+ AD.verbose = verbose;
+}
+
+int audioplayer (char *fname, Uint32 timeout)
+{
+ if (SDL_LoadWAV (fname, &AD.spec, &AD.sound_buffer, &AD.sound_len) == NULL) {
+ printf ("SDL: %s\n", SDL_GetError ());
+ return -1;
+ }
+
+ AD.loaded = 1;
+
+ if (!AD.opened) {
+ AD.spec.callback = Callback;
+ if (SDL_OpenAudio (&AD.spec, NULL) < 0) {
+ fprintf (stderr, "Cannot open audio device: %s\n", SDL_GetError ());
+ return -1;
+ }
+ AD.opened = 1;
+ }
+
+ /*
+ * calls implicitly getwavelength
+ */
+ audioplayer_media_info (fname);
+
+ AD.sound_pos = 0;
+
+ /*
+ * starts playback via Callback function
+ */
+ SDL_PauseAudio (0);
+
+ /*
+ * initializes the timeout mechanism
+ */
+ AD.timer = 1;
+ AD.timeout = timeout;
+
+ /*
+ * controlled delay
+ */
+ audioplayer_delay (timeout);
+
+ return 0;
+}
new file mode 100644
--- /dev/null
+++ b/src/festival_interface.c
@@ -0,0 +1,75 @@
+/**
+ * $Id: festival_interface.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/festival_interface.c $
+ */
+
+#ifdef FESTIVAL
+#include <festival_interface.h>
+
+ttshandles interface_init (tts_options t_options)
+{
+ ttshandles handle;
+
+ return handle;
+}
+
+long *interface_get_timing (ttshandles tts, char *text)
+{
+ int i;
+ long *t = NULL;
+
+ for (i = 0; i < strlen (text); i++) {
+ t = realloc (t, (i + 2) * sizeof (long));
+ t[i] = i * 20 + 10;
+ }
+
+ t[i] = 0;
+ return t;
+};
+
+int interface_write_to_wav (char *fname, char *text, ttshandles t_handles, tts_options t_options)
+{
+ char *s = NULL;
+
+ if ((s = malloc (strlen (text) + 80)) == NULL)
+ return -1;
+
+ sprintf (s, "printf \"%s\" | bin/festival_write_wav - %s", text, fname);
+#ifdef DEBUG
+ printf ("Writing %s\n", fname);
+#endif
+ system (s);
+
+ if (s != NULL)
+ free (s);
+ return 0;
+}
+
+tts_options interface_get_cl_opts (int num, char **arguments)
+{
+ tts_options options = { 0, 0, 0, 0 };
+ int c;
+
+ while ((c = getopt (num, arguments, "p:v:i:")) > 0) {
+ switch (c) {
+ case 'p':
+ options.Path = optarg;
+ break;
+ case 'v':
+ options.Voice = optarg;
+ break;
+ case 'i':
+ options.TextFile = optarg;
+ break;
+ }
+ }
+
+ if (options.TextFile == NULL) {
+ fprintf (stderr, "It's substantial to give a text file by -i <text file>!\n");
+ exit (0);
+ }
+
+ return options;
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/src/keyboard.c
@@ -0,0 +1,36 @@
+/**
+ * $Id: keyboard.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/keyboard.c $
+ */
+
+#include <keyboard.h>
+
+char getSingleKey ()
+{
+ // read and return single key with 1 second timeout
+
+ struct termios new_settings;
+ struct termios stored_settings;
+ int timeout = 1; // 1 sec timeout
+ char c;
+
+ tcgetattr (0, &stored_settings);
+ new_settings = stored_settings;
+
+ new_settings.c_lflag &= ~(ICANON | ECHO);
+
+ new_settings.c_cc[VTIME] = timeout * 10;
+ new_settings.c_cc[VMIN] = 0;
+ tcsetattr (0, TCSANOW, &new_settings);
+
+ fflush (stdout);
+ c = getchar ();
+
+ tcsetattr (0, TCSANOW, &stored_settings);
+
+#ifdef DEBUG
+ if (isalpha (c))
+ printf ("received keypress: %c\n", c);
+#endif
+ return c;
+}
new file mode 100644
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,223 @@
+/**
+ * $Id: main.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/main.c $
+ */
+
+#include <sentence.h>
+#include <keyboard.h>
+#include <thread.h>
+#include <audioplayer.h>
+#include <interface.h>
+
+#define STARTWRITER 0
+#define WRITER 1
+#define READER 2
+
+#define STEP 2 // jump back n-steps
+
+void find_next (ThreadData * data)
+{
+ long tm = (long)audioplayer_gettime ();
+ long position;
+ int i, max;
+
+ max = words (data->sentences[data->satz]);
+
+ for (i = 0; i < max; i++) {
+ if (data->timings[data->satz][i] > tm)
+ break;
+ }
+
+ position = data->timings[data->satz][i];
+ audioplayer_settime (position);
+}
+
+void find_prev (ThreadData * data)
+{
+ long tm = (long)audioplayer_gettime ();
+ long position;
+ int i, max;
+
+ max = words (data->sentences[data->satz]);
+
+ for (i = STEP; i < max; i++) {
+ if (data->timings[data->satz][i] > tm)
+ break;
+ }
+
+ position = data->timings[data->satz][i - STEP];
+ audioplayer_settime (position);
+}
+
+int main (int argc, char **argv)
+{
+ char **sentences = NULL; // to store an array of strings
+ char *Text = NULL; // to store the content of a textfile
+ long **timings = NULL; // to store the timings
+ int i, count; // sentence counter
+ int verbose = 0;
+
+ pthread_t p_thread, w_thread;
+
+ ThreadData *data[3]; // independent thread data
+
+ tts_options ttsopt = interface_get_cl_opts (argc, argv);
+ ttshandles ttsh = interface_init (ttsopt);
+
+ if ((Text = readbuffer (ttsopt.TextFile)) != NULL) {
+ sentences = getstrings (Text, &count);
+ free (Text);
+ } else {
+ printf ("ERROR: Textfile %s is corrupt.\n", ttsopt.TextFile);
+ free (ttsopt.TextFile);
+ free (ttsopt.AudioFile);
+ free (ttsopt.Voice);
+ free (ttsopt.Path);
+
+ return EXIT_SUCCESS;
+ }
+
+ // Timinganalyse des Textes
+ if ((timings = calloc ((size_t) count, sizeof (long *) + 1)) == NULL) {
+ free (ttsopt.TextFile);
+ free (ttsopt.AudioFile);
+ free (ttsopt.Voice);
+ free (ttsopt.Path);
+
+ return EXIT_SUCCESS;
+ }
+
+ for (i = 0; i < count; i++) {
+ timings[i] = interface_get_timing (ttsh, sentences[i]);
+ }
+
+ /*
+ * Initialize Sound
+ */
+ if (audio_init ())
+ fprintf (stderr, "AUDIO ERROR\n");
+
+ for (i = 0; i < 3; i++) {
+ data[i] = malloc (sizeof (ThreadData) + 1);
+ if (data[i] == NULL)
+ exit (0);
+ data[i]->ttsopt = ttsopt;
+ data[i]->ttsh = ttsh;
+ data[i]->fname = ttsopt.TextFile;
+ data[i]->sentences = sentences;
+ data[i]->timings = timings;
+ }
+
+ /*
+ * write sentences from 0-1 :)
+ */
+ data[STARTWRITER]->satz = 0;
+ data[STARTWRITER]->items = 1;
+
+ pthread_create (&w_thread, NULL, (void *)writewav, data[STARTWRITER]);
+ pthread_join (w_thread, NULL);
+
+ /*
+ * write sentences from 1-count :)
+ */
+ data[WRITER]->satz = 1;
+ data[WRITER]->items = count;
+ pthread_create (&w_thread, NULL, (void *)writewav, data[WRITER]);
+
+ data[READER]->satz = 0;
+ data[READER]->items = count;
+ pthread_create (&p_thread, NULL, (void *)readtext, data[READER]);
+
+ while (data[READER]->satz < data[READER]->items) {
+ switch (getSingleKey ()) {
+ case 'i':
+ // next word
+ if (data[READER]->satz < data[READER]->items)
+ find_next (data[READER]);
+ else
+ printf ("ERROR: Cannot seek anymore\n");
+ break;
+
+ case 'j':
+ // previous sentence
+ if (data[READER]->satz > 0) {
+ data[READER]->satz--;
+ p_thread_restart (p_thread, readtext, data[READER]);
+ }
+ break;
+
+ case 'k':
+ // previous word
+ find_prev (data[READER]);
+ break;
+
+ case 'l':
+ // next sentence
+ if (data[READER]->satz < data[READER]->items) {
+ data[READER]->satz++;
+ p_thread_restart (p_thread, readtext, data[READER]);
+ }
+ break;
+
+ case 'p':
+ // print useful informations
+ printf ("Current Position: [%5d/%5d]ms = #%d\n",
+ audioplayer_gettime (), audioplayer_getwavelength (NULL), audioplayer_getposition ());
+ break;
+
+ case 'q':
+ // quit
+ pthread_cancel (w_thread);
+ pthread_cancel (p_thread);
+ data[READER]->satz = data[READER]->items;
+ break;
+
+ case 'r':
+ // reset player
+ pthread_cancel (p_thread);
+ if (!pthread_join (p_thread, NULL))
+ printf ("RESET\n");
+ break;
+ case 's':
+ printf ("S[%d]: %s\n", data[READER]->satz, sentences[data[READER]->satz]);
+ break;
+ case 'v':
+ verbose ^= 1;
+ audioplayer_setverbose (verbose);
+ break;
+
+ default:
+ /*
+ * unknown command
+ */
+ break;
+ }
+ }
+
+ if (!pthread_join (p_thread, NULL))
+ printf ("The last thread exited\n");
+
+ // cleanup memory
+ for (i = 0; i < count; i++) {
+ if (sentences[i] != NULL)
+ free (sentences[i]);
+ if (timings[i] != NULL)
+ free (timings[i]);
+ }
+
+ if (sentences != NULL)
+ free (sentences);
+
+ if (timings != NULL)
+ free (timings);
+
+ for (i = 0; i < 3; i++)
+ if (data[i] != NULL)
+ free (data[i]);
+
+ /*
+ * Cleanup sound
+ */
+ audio_shutdown ();
+ pthread_exit (NULL);
+}
new file mode 100644
--- /dev/null
+++ b/src/mbrola_interface.c
@@ -0,0 +1,79 @@
+/**
+ * $Id: mbrola_interface.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/mbrola_interface.c $
+ */
+
+#ifdef MBROLA
+#include <mbrola_interface.h>
+
+ttshandles interface_init (tts_options t_options)
+{
+ ttshandles handle;
+
+ return handle;
+}
+
+long *interface_get_timing (ttshandles tts, char *text)
+{
+ long *t = NULL;
+ int i = 0;
+
+ for (i = 0; i < strlen (text); i++) {
+ t = realloc (t, (i + 2) * sizeof (long));
+ t[i] = i * 20 + 10;
+ }
+#ifdef DEBUG
+ printf ("\nTiming analysis ends\n");
+#endif
+
+ t[i] = 0;
+
+ return t;
+};
+
+int interface_write_to_wav (char *fname, char *text, ttshandles t_handles, tts_options t_options)
+{
+ char *s = NULL;
+
+ if ((s = malloc (strlen (text) + 80)) == NULL)
+ return -1;
+
+ sprintf (s, "printf \"%s\" | bin/mbrola_write_wav - %s", text, fname);
+#ifdef DEBUG
+ printf ("Writing %s\n", fname);
+#endif
+ system (s);
+
+ if (s != NULL)
+ free (s);
+ return 0;
+}
+
+tts_options interface_get_cl_opts (int num, char **arguments)
+{
+ tts_options options = { 0, 0, 0, 0 };
+ int c;
+
+ while ((c = getopt (num, arguments, "p:v:i:")) > 0) {
+ switch (c) {
+ case 'p':
+ options.Path = optarg;
+ break;
+ case 'v':
+ options.Voice = optarg;
+ break;
+ case 'i':
+ options.TextFile = optarg;
+ break;
+ }
+ }
+
+ if (options.TextFile == NULL) {
+ fprintf (stderr, "It's substantial to give a text file by -i <text file>!\n");
+ exit (0);
+ }
+
+ return options;
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/src/proser_interface.c
@@ -0,0 +1,167 @@
+/**
+ * $Id: proser_interface.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/proser_interface.c $
+ */
+
+#ifdef PROSER
+#include <proser_interface.h>
+
+ttshandles interface_init (tts_options propt)
+{
+
+ ttshandles pr_handle;
+
+ // initialize Proser options and set default values for a given voice
+ if (init_ProserOpt (&propt.ProserOpt, propt.Voice)) {
+ fprintf (stderr, "Fatal error occurred in set_ProserOpt: %s\n", GetLastNlpErrorDescription (NULL));
+ exit (-1);
+ }
+ // the path to the TTS input data like dictionaries and prosodic stuff has to be set
+
+ propt.ProserOpt.Path = strdup (propt.Path);
+
+ // here some more manipulations of the standard settings can be done
+
+ propt.ProserOpt.PreEmphasis = propt.PreEmphasis;
+ propt.ProserOpt.Speed = propt.Speed;
+
+ // initialize channel //
+ if (!(pr_handle.GermanNlp = OpenNlp (&propt.ProserOpt))) {
+ fprintf (stderr, "Fatal error occurred in OpenNlp: %s (%d)\n",
+ GetLastNlpErrorDescription (pr_handle.GermanNlp), (int)GetLastNlpError (pr_handle.GermanNlp));
+ exit (-1);
+ }
+ // delete structure for Proser Options //
+ if (delete_ProserOpt (&propt.ProserOpt)) {
+ fprintf (stderr, "Fatal error occurred in delete_ProserOpt: %s\n", GetLastNlpErrorDescription (NULL));
+ exit (-1);
+ }
+ return pr_handle;
+}
+
+int interface_write_to_wav (char *Filename, char *Text, ttshandles prosh, tts_options propt)
+{
+ // write Text to a file
+ if (ProserSynthText (prosh.GermanNlp, Text, Filename, propt.FileType, propt.Stype)) {
+ fprintf (stderr, "Fatal error occurred in ProserSynthText: %s\n", GetLastNlpErrorDescription (prosh.GermanNlp));
+ return (-1);
+ }
+ return (0);
+}
+
+long *interface_get_timing (ttshandles prosh, char *Text)
+{
+ // analyze given text, return array with long values containing
+ // time in ms when each word of the given text will start in the
+ // output
+ long *timings = NULL;
+ LPPHONEME PhoneticSentenceDescription;
+ long NumberOfPhoneticUnits;
+ int i = 0, WordNum = 0;
+
+ PhoneticSentenceDescription = TextToPho (prosh.GermanNlp, Text, &NumberOfPhoneticUnits);
+#ifdef DEBUG
+ printf ("\n[S] %s\n", Text);
+#endif
+ while (i < (NumberOfPhoneticUnits - 1)) {
+ if (PhoneticSentenceDescription[i + 1].Event != 0) {
+ timings = realloc (timings, (WordNum + 2) * sizeof (long));
+ timings[WordNum] = PhoneticSentenceDescription[i + 1].Offset;
+#ifdef DEBUG
+ printf ("Wort:\t %i \t Time: %ld ms\n", WordNum, PhoneticSentenceDescription[i + 1].Offset);
+#endif
+ WordNum++;
+ }
+ i++;
+ }
+ timings[WordNum] = 0;
+ return timings;
+}
+
+tts_options interface_get_cl_opts (int argc, char **argv)
+{
+ int i, j;
+ tts_options propt;
+
+ propt.TextFile = propt.AudioFile = propt.Voice = propt.Path = NULL;
+
+ j = 0;
+ propt.PreEmphasis = 0.0f;
+ propt.Speed = 1.0f;
+ propt.Stype = LIN16;
+ propt.FileType = WAV;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp (argv[i], "-i")) {
+ propt.TextFile = argv[++i];
+ continue;
+ } else if (!strcmp (argv[i], "-o")) {
+ propt.AudioFile = argv[++i];
+ continue;
+ } else if (!strcmp (argv[i], "-v")) {
+ propt.Voice = argv[++i];
+ continue;
+ } else if (!strcmp (argv[i], "-p")) {
+ propt.Path = argv[++i];
+ continue;
+ } else if (!strcmp (argv[i], "-pre")) {
+ propt.PreEmphasis = atof (argv[++i]);
+ continue;
+ } else if (!strcmp (argv[i], "-speed")) {
+ propt.Speed = atof (argv[++i]);
+ continue;
+ } else if (!strcmp (argv[i], "-format")) {
+ i++;
+ for (j = 0; j < (int)strlen (argv[i]); j++)
+ argv[i][j] = toupper (argv[i][j]);
+ if (!strcmp (argv[i], "RAW")) {
+ propt.FileType = RAW;
+ continue;
+ } else if (!strcmp (argv[i], "WAV")) {
+ propt.FileType = WAV;
+ continue;
+ } else if (!strcmp (argv[i], "AU")) {
+ propt.FileType = AU;
+ continue;
+ } else {
+ fprintf (stderr, "Unknown output type %s\n", argv[i]);
+ fprintf (stderr, "Supported output types: RAW - AU - WAV\n");
+ exit (-1);
+ }
+ }
+ if (strcmp (argv[i], "-audio") == 0) {
+ i++;
+ for (j = 0; j < strlen (argv[i]); j++)
+ argv[i][j] = toupper (argv[i][j]);
+ if (!strcmp (argv[i], "LIN16")) {
+ propt.Stype = LIN16;
+ continue;
+ } else if (!strcmp (argv[i], "LIN8")) {
+ propt.Stype = LIN8;
+ continue;
+ } else if (!strcmp (argv[i], "ULAW")) {
+ propt.Stype = ULAW;
+ continue;
+ } else if (!strcmp (argv[i], "ALAW")) {
+ propt.Stype = ALAW;
+ continue;
+ }
+ } else {
+ fprintf (stderr, "Unknown option: %s\n", argv[i]);
+ exit (-1);
+ }
+ }
+
+ if (!propt.TextFile) {
+ fprintf (stderr, "It's substantial to give a text file by -i <text file>!\n");
+ exit (-1);
+ } else if (!propt.Voice) {
+ fprintf (stderr, "It's substantial to give a voice database by -v <voice>!\n");
+ exit (-1);
+ } else if (!propt.Path) {
+ fprintf (stderr, "It's substantial to give a path for the prosodic stuff by -p <path>!\n");
+ exit (-1);
+ }
+ return (propt);
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/src/sentence.c
@@ -0,0 +1,164 @@
+/**
+ * $Id: sentence.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/sentence.c $
+ */
+
+#include <sentence.h>
+
+int words (char *ptr)
+{
+ char *buffer = NULL;
+ char *token;
+ int count = 0;
+
+ if (ptr != NULL)
+ buffer = strdup (ptr);
+
+ if (buffer == NULL)
+ return -1;
+
+ token = strtok (buffer, " ");
+ while (token != NULL) {
+ token = strtok (NULL, " ");
+ count++;
+ }
+
+ if (buffer != NULL)
+ free (buffer);
+
+ return count;
+}
+
+int *parse (char *buf)
+{
+ int count = 0;
+ int i;
+ int *s_ptr = NULL;
+
+ s_ptr = malloc (2 * sizeof (int));
+ s_ptr[count++] = 0;
+
+ for (i = 0; i < strlen (buf); i++)
+ switch (buf[i]) {
+ case '\n':
+ case '\t':
+ case '"':
+ case '\'':
+ buf[i] = ' ';
+ break;
+ case '.':
+ case '!':
+ case '?':
+ s_ptr = realloc (s_ptr, (count + 2) * sizeof (int));
+ if (s_ptr == NULL) {
+ printf ("Not enough memory\n");
+ return NULL;
+ }
+ s_ptr[count++] = ++i;
+ break;
+ default:
+ break;
+ }
+
+ s_ptr[count] = 0;
+
+ return s_ptr;
+}
+
+char *readbuffer (char *fname)
+{
+ FILE *f;
+ char *text = NULL;
+ char buffer[201];
+
+ if ((f = fopen (fname, "r")) == NULL) {
+ fprintf (stderr, "ERROR: Cannot open %s for reading!\n", fname);
+ return NULL;
+ }
+
+ text = malloc (2);
+ *text = 0;
+
+ while (fgets (buffer, 200, f) != 0) {
+ if ((text = realloc (text, strlen (text) + strlen (buffer) + 1)) == NULL) {
+ printf ("Not enough memory\n");
+ return NULL;
+ };
+ strcat (text, buffer);
+ *buffer = 0;
+ }
+
+ fclose (f);
+ return text;
+}
+
+char *getSentence (char *text, int start, int end)
+{
+ int i;
+ char *value = NULL;
+
+ if ((i = end - start) < 0)
+ return NULL;
+
+ value = malloc (i + 1);
+ if (value == NULL)
+ return NULL;
+
+ i = 1;
+ while (i) {
+ switch (text[start]) {
+ case '.':
+ case ',':
+ case '!':
+ case '?':
+ case '(':
+ case ')':
+ case '\n':
+ case ' ':
+ start++;
+ break;
+ default:
+ i = 0;
+ break;
+ }
+ }
+
+ for (i = start; i < end; i++) {
+ value[i - start] = text[i];
+ }
+
+ value[i - start] = 0;
+
+ return value;
+}
+
+char **getstrings (char *Text, int *value)
+{
+ char *ptr;
+ int i = 0;
+ int count = 0;
+ char **sentences = NULL;
+ int *s_ptr;
+
+ if ((s_ptr = parse (Text)) == NULL)
+ return NULL;
+
+ while (s_ptr[i + 1] > 0) {
+ if ((ptr = getSentence (Text, s_ptr[i], s_ptr[i + 1])) == NULL)
+ return NULL;
+ if (strlen (ptr) > 0) {
+ if ((sentences = realloc (sentences, (count + 1) * sizeof (char *) + 1)) == NULL)
+ return NULL;
+ sentences[count++] = strdup (ptr);
+ }
+ if (ptr != NULL)
+ free (ptr);
+ i++;
+ }
+
+ if (s_ptr)
+ free (s_ptr);
+
+ *value = count;
+ return sentences;
+}
new file mode 100644
--- /dev/null
+++ b/src/thread.c
@@ -0,0 +1,60 @@
+/**
+ * $Id: thread.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/thread.c $
+ */
+
+#include <thread.h>
+
+int p_thread_restart (pthread_t p_thread, void *func, ThreadData * data)
+{
+ // stops a thread, waits for it to exit and then restarts it using
+ // the current data structure
+ int ret;
+
+ pthread_cancel (p_thread);
+ if (pthread_join (p_thread, NULL))
+ printf ("RESTART: Cannot find a suitable thread :)\n");
+
+ ret = pthread_create (&p_thread, NULL, (void *)func, data);
+
+ /*
+ * TODO: Error Handling
+ */
+ return ret;
+}
+
+void readtext (ThreadData * data)
+{
+ // read the current sentence using the audio player
+ // TODO - test for existence (completeness?) of file before read
+ char fname[80];
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ pthread_cleanup_push (audioplayer_stop, NULL);
+
+ for (; data->satz < data->items; data->satz++) {
+ sprintf (fname, "audio/%s-%i.wav", data->fname, data->satz);
+ if ((audioplayer (fname, TIMEOUT)) != -1)
+ audioplayer_stop ();
+ else
+ pthread_exit (NULL);
+ }
+
+ pthread_exit (NULL);
+ pthread_cleanup_pop (1);
+}
+
+void writewav (ThreadData * data)
+{
+ // write wav file for each sentence between data->satz adn
+ // data->items
+ char fname[80];
+ int i;
+
+ for (i = data->satz; i < data->items; i++) {
+ sprintf (fname, "audio/%s-%i.wav", data->fname, i);
+ interface_write_to_wav (fname, data->sentences[i], data->ttsh, data->ttsopt);
+ }
+
+ pthread_exit (NULL);
+}
new file mode 100644
--- /dev/null
+++ b/test.txt
@@ -0,0 +1,111 @@
+Einst herrschte ein großer starker Pirat über die sieben Weltmeere.
+Überall war "er verhasst und bekannt. Er riss Alles an sich, was nicht
+Niet- und Nagelfest war und erschreckte Alle durch seine angsteinflößede
+Art und durch sein Aussehen. Seine Besatzung hatte sich nach und nach
+aus dem Staube" gemacht, wei der Pirat Alles für sich haben wollte und
+ungerecht zu ihnen war. Er machte ihnen das Leben an Bord stets zur
+Hölle. Das Schiff des Piratens wurde immer prunkvoller und schöner. Die
+Segel waren aus goldener Seide, die Masten aus Elfenbein, das Holz aus
+Teak, die Schrauben und Muttern, die alles fest hielten aus feinem
+Silber. Das Glas in den Fenstern war aus schillerndem Perlmutt und
+glitzerte mit dem Meer um die Wette. Zufrieden spazierte der Pirat über
+sein Schiff, welches ein einzig großer Schatz war. Er liebte seinen
+Reichtum und wollte immer mehr davon. BEkam er das, was er wollte, war
+er ein paar Tage glücklich, doch dann wurde der Drang nach etwas noch
+Größerem und noch Schönerem immer größer. Irgendetwas fehlte da, was ihn
+unendlich glücklich machen würde. Doch kein Rubin der Welt, keine
+goldene Krone, kein silberner Taler schaffte es ihn länger als 3 Tage
+glücklich zu machen. Somit musste er, um seine Zufriedenheit zu erhalten
+sehr oft auf Raubzug gehen.
+Eines Tages kam er an eine kleine Insel. Schon von weitem sah er die
+kleine Truppe von Eingeborenen, die um ein Lagerfeuer saßen, trommelten,
+aßen und lachten.
+Sie hatten nichts bei sich, außer ihre Baströckchen, ihre Instrumente
+und ihr spärliches Mahl –
+und doch machten sie einen glücklicheren Eindruck, als er sich je
+vorstellen konnte.
+Er hatte selten Menschen gesehen, die so glücklich und zufrieden waren
+wie diese.
+Er fragte sich, welche Schätze sie wohl zu Hause versteckt hielten. Denn
+ohne einen großen Reichtum ließe sich in seinem Piratenkopf die große
+Glückseeligkeit nicht erklären.
+Als er den Anker warf und an Land ging, stürmte der Stamm der
+Eingeborenen hastig von Dannen, bis auf ein kleiner Junge. Der Pirat
+fragte den Jungen, warum sie anderen weggelaufen sind und was es denn
+bei ihm im Dorf schönes zu holen gäbe.
+Der kleine Junge antwortete munter und fürchtete sich kein bisschen vor
+dem Pirat, auch wenn dieser furcht erregend aussah. In seinen Augen
+nämlich sah der Junge Unsicherheit, Traurigkeit und Einsamkeit. Außerdem
+bemerkte der Junge das Holzbein des Piraten. Damit hätte er ihm nie so
+flink folgen können. Der Junge erzählte dem Pirat von seinem Dorf, den
+Blätter und Strohhütten und von seiner Familien und seinen Freunden.
+„Freunde?“ fragte der Pirat. Er konnte sich nichts darunter vorstellen
+unter diesem Begriff.
+Der kleine Junge versuchte ihm zu erklären, was Freundschaft ist und der
+Pirat staunte nicht schlecht. Nun wollte er unbedingt einen Freund
+haben, denn der Junge meinte, ein Freund sei der größte Schatz der Welt.
+Das machte den Piraten neugierig.
+Doch so einfach war das nicht. Ein Freund ist unbezahlbar und das
+verstand der Pirat nicht.
+Man konnte einen Freund nicht einfach kaufen oder stibitzen.
+Andere Dinge zählten. Dinge, von denen der Pirat noch nie in seinem
+Leben gehört hatte.
+Der kleine Junge wollte dem Pirat zeigen, was Freundschaft ist und sie
+trafen sich jeden Tag, redeten, lachten und machten Feuer. Der Junge
+zeigte dem Pirat wie man Fische fängt und der Pirat zeigte dem Jungen,
+in welchen Muscheln man dir größten Perlen findet.
+Nach und nach verloren auch die anderen vom Stamm die Furcht vor dem
+Piraten und abends wurde am Lagerfeuer getanzt, gesungen und gelacht.
+Der Pirat fühlte sich wohler als je zuvor und hatte durch den kleinen
+Jungen erfahren, was es bedeutet, Freunde zu finden.
+Er wurde von Tag zu Tag glücklicher und zufriedener und ihm stand wenig
+Sinn nach seinen Räuberzügen.
+Eines Tages jedoch wurde der kleine Junge sehr krank. Keine Heilpflanze
+konnte ihm helfen, kein Schamane konnte Wunder bewirken, keiner der im
+Tanz und Klang herbeigerufenen Geister halfen ihm. Ein wichtiges
+Medikament von einem anderen Kontinent wurde benötigt.
+Somit machte sich der Pirat sofort auf die Reise, dieses Medikament zu
+besorgen. Die Zeit war knapp. Es blieben dem Jungen nur noch wenige
+Wochen, vielleicht sogar nur Tage.
+Der Stamm war dem Piraten sehr dankbar und sie beteten und hofften auf
+eine baldige Rückkehr mit dem Medikament. Der Pirat fuhr drei Tage und
+drei Nächte durch Wind und Wetter und kam endlich an seinem Zielort an.
+Er machte sich große Sorgen um seinen Freund. Das Medikament war sehr
+teuer. Der Pirat wollte es mit Kanonenschuss und Messerwurf erwerben,
+doch irgendetwas hielt ihn zurück. Er konnte seine Boshaftigkeit nicht
+mehr zeigen, denn wenn er in die Gesichter von den Menschen schaute,
+ihre Blicke sah, dann musste er an seinen Freund denken und an seinen
+Stamm, der ihn so freundlich aufgenommen hatte.
+Also beschloss er das Medikament zu kaufen. Er gab sehr viel von seinem
+Reichtum ab und verkaufte ebenso einen Teil davon, um ein paar Geschenke
+und Nahrungsmittel für den Stamm mitzubringen. Nun war sein Schiff gar
+nicht mehr so pompös, wie zuvor, aber es störte ihn seltsamerweise nicht
+weiter. Für ihn zählte nur das Leben seines Freundes, dem kleinen
+Jungen. Auf dem Weg zu ihm kam er an einer kleinen einsamen Insel
+vorbei, auf der eine Familie gestrandet war. Sie flehten um Hilfe, dass
+er sie mitnehme. Da der Pirat jedoch schnellst möglich in eine andere
+Richtung musste, um zur Insel seines Freundes zu gelangen, blieb ihm
+nichts anderes übrig als ihnen das große Schiff zu überlassen. Er selbst
+fuhr mit dem kleinen Beiboot zur Insel, die nicht mehr so weit entfernt
+war.
+Ein wenig seltsam war es schon, alles abgegeben zu haben, doch mit dem
+Seufzer kam auch eine seltsame Erleichterung. Wie eine tonnenschwere
+Last, die abgeworfen wurde.
+Als der Pirat an der Insel ankam, wurde er schon erwartet. Der Junge war
+noch schlechter zurecht als zuvor und der Guru hatte schon das letzte
+Gebet ausgesprochen und ihn einbalsamiert. Das Medikament jedoch half
+ihm in allerletzter Sekunde und er wurde von Tag zu Tag gesünder. Nach
+einer Woche konnte er wieder aufstehen und mit den anderen Kindern
+spielen. Während sein Vater einen Arm um den Pirat legte und „Mnumbai, y
+zmuni“ – Danke, mein Freund, sagte, schaute der Pirat glücklich zu. Der
+Junge hatte sein Leben zurückbekommen, Dank ihm. Und er hatte wahre
+Freunde gefunden. Das hatte er dem Jungen zu verdanken. Der Pirat hatte
+ebenfalls bewiesen, dass ihm ein Freund mehr wert ist, als alle Schätze
+der Welt. Er wurde damit belohnt, dass er nicht weiter einsam war.
+Der Stamm nahm den Pirat für immer bei sich auf und er war glücklich und
+zufrieden bis an sein Lebensende. Sein kleiner Freund wuchs heran und
+wurde irgendwann ein weiser Häuptling. Er erzählte seinen Kindern und
+Kindeskindern am Lagerfeuer von seinem treuen Piratenfreund. Immer, wenn
+er ein Piratenschiff am Horizont vorbeifahren sah, dachte er an seinen
+Freund zurück, dem er sein Leben zu verdanken hatte.
+