diff --git a/platforms/big_endian/Makefile b/platforms/big_endian/Makefile new file mode 100644 index 00000000..36f0ca11 --- /dev/null +++ b/platforms/big_endian/Makefile @@ -0,0 +1,11 @@ +CC = gcc + +CFLAGS += -g -Wall + +all: espeak-phoneme-data + +espeak-phoneme-data: espeak-phoneme-data.c + $(CC) $(CFLAGS) -o $@ $< + +clean: + rm -f espeak-phoneme-data diff --git a/platforms/big_endian/README b/platforms/big_endian/README new file mode 100644 index 00000000..7ac358c0 --- /dev/null +++ b/platforms/big_endian/README @@ -0,0 +1,18 @@ +espeak-utils +============ + +A utility to convert the phonindex, phontab and phondata to +big-endian form if necessary. + +* espeak-phoneme-data + + This is the little-endian to big-endian conversion tool. It uses an + external file (by default called 'phondata-manifest') in order to convert + the phondata file. + +The 'phondata-manifest' file is produced by espeakedit when it compiles +the phoneme data. If it is not present here, find it in the espeak-data directory. + +--- +To contact the author of these utilities, please send an e-mail to + diff --git a/platforms/big_endian/espeak-phoneme-data.c b/platforms/big_endian/espeak-phoneme-data.c new file mode 100644 index 00000000..b27e3cd1 --- /dev/null +++ b/platforms/big_endian/espeak-phoneme-data.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include + +#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN +#define IS_BIG_ENDIAN 1 +#else +#define IS_BIG_ENDIAN 0 +#endif + + +#if IS_BIG_ENDIAN + +# define SWAP_USHORT(val) ((unsigned short) ( \ + (unsigned short) ((unsigned short) (val) >> 8) | \ + (unsigned short) ((unsigned short) (val) << 8))) + +# define SWAP_UINT(val) ((unsigned int) ( \ + (((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \ + (((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \ + (((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \ + (((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24))) + +#else + +# define SWAP_USHORT(val) (val) +# define SWAP_UINT(val) (val) + +#endif + + + +#define N_PHONEME_TAB_NAME 32 + +typedef struct { + unsigned int mnemonic; + unsigned int phflags; + + unsigned short std_length; + unsigned short spect; + unsigned short before; + unsigned short after; + + unsigned char code; + unsigned char type; + unsigned char start_type; + unsigned char end_type; + + unsigned char length_mod; + unsigned char reduce_to; + unsigned char alternative_ph; + unsigned char link_out; +} PHONEME_TAB; + + +typedef struct { + short frflags; + unsigned char length; + unsigned char rms; + short ffreq[9]; + unsigned char fheight[9]; + unsigned char fwidth[6]; + unsigned char fright[6]; +} frame_t; + +#define N_SEQ_FRAMES 25 + +typedef struct { + short length; + unsigned char n_frames; + unsigned char flags; + frame_t frame[N_SEQ_FRAMES]; +} SPECT_SEQ; + + +void swap_phondata (const char *infile, const char *outfile, + const char *manifest); +void swap_phonindex (const char *infile, const char *outfile); +void swap_phontab (const char *infile, const char *outfile); + +void usage (const char *program_name); + + + +int +main (int argc, char *argv[]) +{ + const char *indir = "/usr/share/espeak-data"; + const char *outdir = "."; + const char *manifest = "phondata-manifest"; + char *f1, *f2; + + + if (argc > 4) + usage (argv[0]); + + if (argc > 1) { + if (strcmp (argv[1], "-h") == 0 || + strcmp (argv[1], "--help") == 0) + usage (argv[0]); + + indir = argv[1]; + } + + if (argc > 2) + outdir = argv[2]; + + if (argc > 3) + manifest = argv[3]; + + f1 = (char *) malloc (strlen (indir) + 20); + if (f1 == NULL) { + fprintf (stderr, "Unable to allocate memory\n"); + exit (1); + } + f2 = (char *) malloc (strlen (outdir) + 20); + if (f2 == NULL) { + fprintf (stderr, "Unable to allocate memory\n"); + exit (1); + } + +#if IS_BIG_ENDIAN + printf ("Host seems to be big-endian ..\n"); +#else + printf ("Host seems to be little-endian ..\n"); +#endif + + sprintf (f1, "%s/phontab", indir); + sprintf (f2, "%s/temp_1", outdir); + + printf ("Processing phontab ..\n"); + swap_phontab (f1, f2); + sprintf (f1, "%s/phontab", outdir); + rename (f2, f1); + + sprintf (f1, "%s/phonindex", indir); + sprintf (f2, "%s/temp_1", outdir); + + printf ("Processing phonindex ..\n"); + swap_phonindex (f1, f2); + sprintf (f1, "%s/phonindex", outdir); + rename (f2, f1); + + sprintf (f1, "%s/phondata", indir); + sprintf (f2, "%s/temp_1", outdir); + + printf ("Processing phondata ..\n"); + swap_phondata (f1, f2, manifest); + sprintf (f1, "%s/phondata", outdir); + rename (f2, f1); + + free (f1); + free (f2); + + printf ("Done.\n"); + + return 0; +} + +void +swap_phondata (const char *infile, const char *outfile, + const char *manifest) +{ + FILE *in, *mfest, *out; + char line[1024]; + unsigned char buf_4[4]; + + in = fopen (infile, "rb"); + if (in == NULL) { + fprintf (stderr, "Unable to read from file %s\n", infile); + exit (1); + } + + mfest = fopen (manifest, "rb"); + if (mfest == NULL) { + fprintf (stderr, "Unable to read from file %s\n", manifest); + exit (1); + } + + out = fopen (outfile, "wb"); + if (out == NULL) { + fprintf (stderr, "Unable to open file %s for writing\n", outfile); + exit (1); + } + + fread (buf_4, 4, 1, in); + fwrite (buf_4, 4, 1, out); + + while (fgets (line, 1024, mfest)) { + if (line[0] == 'S') { + SPECT_SEQ buf_spect; + size_t ix; + int n; + + fread (&buf_spect.length, 2, 1, in); + fread (&buf_spect.n_frames, 1, 1, in); + fseek (in, -3, SEEK_CUR); + + ix = (char *)(&buf_spect.frame[buf_spect.n_frames]) - + (char *)(&buf_spect); + ix = (ix+3) & 0xfffc; + + fread (&buf_spect, ix, 1, in); + + buf_spect.length = (short) SWAP_USHORT (buf_spect.length); + for (n = 0; n < buf_spect.n_frames; n++) { + int k; + + buf_spect.frame[n].frflags = (short) + SWAP_USHORT (buf_spect.frame[n].frflags); + + for (k = 0; k < 9; k++) { + buf_spect.frame[n].ffreq[k] = (short) + SWAP_USHORT (buf_spect.frame[n].ffreq[k]); + } + } + + fwrite (&buf_spect, ix, 1, out); + } + else if (line[0] == 'W') { + long pos; + int length; + char *wave_data; + + fread (buf_4, 4, 1, in); + fwrite (buf_4, 4, 1, out); + + length = buf_4[1] * 256 + buf_4[0]; + + wave_data = (char *) malloc (length); + if (wave_data == NULL) { + fprintf (stderr, "Memory allocation error\n"); + exit (1); + } + + fread (wave_data, 1, length, in); + fwrite (wave_data, 1, length, out); + + pos = ftell (in); + while((pos & 3) != 0) { + fgetc (in); + pos++; + } + + pos = ftell (out); + while((pos & 3) != 0) { + fputc (0, out); + pos++; + } + + free (wave_data); + } + else if (line[0] == 'E') { + char env_buf[128]; + + fread (env_buf, 1, 128, in); + fwrite (env_buf, 1, 128, out); + } + } + + fclose (in); + fclose (out); + fclose (mfest); +} + +void +swap_phonindex (const char *infile, const char *outfile) +{ + FILE *in, *out; + unsigned int val; + + in = fopen (infile, "rb"); + if (in == NULL) { + fprintf (stderr, "Unable to read from file %s\n", infile); + exit (1); + } + + out = fopen (outfile, "wb"); + if (out == NULL) { + fprintf (stderr, "Unable to open file %s for writing\n", outfile); + exit (1); + } + + while (! feof (in)) { + size_t n; + + n = fread (&val, 4, 1, in); + if (n != 1) + break; + + val = SWAP_UINT (val); + fwrite (&val, 4, 1, out); + } + + fclose (in); + fclose (out); +} + +void +swap_phontab (const char *infile, const char *outfile) +{ + FILE *in, *out; + char buf_4[4]; + int i, n_phoneme_tables; + + in = fopen (infile, "rb"); + if (in == NULL) { + fprintf (stderr, "Unable to read from file %s\n", infile); + exit (1); + } + + out = fopen (outfile, "wb"); + if (out == NULL) { + fprintf (stderr, "Unable to open file %s for writing\n", outfile); + exit (1); + } + + fread (buf_4, 4, 1, in); + fwrite (buf_4, 4, 1, out); + n_phoneme_tables = buf_4[0]; + + for (i = 0; i < n_phoneme_tables; i++) { + int n_phonemes, j; + char tab_name[N_PHONEME_TAB_NAME]; + + fread (buf_4, 4, 1, in); + fwrite (buf_4, 4, 1, out); + + n_phonemes = buf_4[0]; + + fread (tab_name, N_PHONEME_TAB_NAME, 1, in); + fwrite (tab_name, N_PHONEME_TAB_NAME, 1, out); + + for (j = 0; j < n_phonemes; j++) { + PHONEME_TAB table; + + fread (&table, sizeof (PHONEME_TAB), 1, in); + + table.mnemonic = SWAP_UINT (table.mnemonic); + table.phflags = SWAP_UINT (table.phflags); + + table.std_length = SWAP_USHORT (table.std_length); + table.spect = SWAP_USHORT (table.spect); + table.before = SWAP_USHORT (table.before); + table.after = SWAP_USHORT (table.after); + + fwrite (&table, sizeof (PHONEME_TAB), 1, out); + } + } + + fclose (in); + fclose (out); +} + +void +usage (const char *program_name) +{ + fprintf (stderr, +"This program copies the phontab, phonindex and phondata files from a given\n" +"directory, swapping values to big-endian form if necessary.\n\n" +"Usage:\n" +" %s [INPUT_DIR] [OUTPUT_DIR] [MANIFEST_FILE]\n\n" +"By default, the MANIFEST_FILE used is a file called 'phondata-manifest' in\n" +"the current directory. The default INPUT_DIR is /usr/share/espeak-data and\n" +"OUTPUT_DIR is the current directory.\n", program_name); + exit (1); +} diff --git a/platforms/dos/MAKEFILE.DJ b/platforms/dos/MAKEFILE.DJ new file mode 100644 index 00000000..35b175fe --- /dev/null +++ b/platforms/dos/MAKEFILE.DJ @@ -0,0 +1,61 @@ +BINDIR=/usr/bin +INCDIR=/usr/include/espeak +LIBDIR=/usr/lib +DATADIR=espeak-data + +RELEASE = 1.28 +BIN_NAME = speak + +INSTALL = /usr/bin/install +LN_SF = /bin/ln -sf +MKDIR = mkdir -p + +speak_SOURCES = speak.cpp compiledict.cpp dictionary.cpp intonation.cpp \ + readclause.cpp setlengths.cpp numbers.cpp synth_mbrola.cpp \ + synthdata.cpp synthesize.cpp translate.cpp tr_english.cpp \ + tr_languages.cpp voices.cpp wavegen.cpp phonemelist.cpp + +SRCS1=$(speak_SOURCES) +OBJS1=$(patsubst %.cpp,%.o,$(SRCS1)) +LIBS1= + + +CXXFLAGS=-O2 + + +all: $(BIN_NAME) + +.cpp.o: + $(CXX) $(CXXFLAGS) -D PATH_ESPEAK_DATA=\"$(DATADIR)\" -Wall -pedantic -I. -c -fno-exceptions $< + +$(BIN_NAME): $(OBJS1) + $(CXX) -o $@ $(OBJS1) $(LIBS1) + +clean: + rm -f *.o *.a *~ + +distclean: clean + rm -f $(BIN_NAME) + rm -f $(BIN2_NAME) + rm -f $(LIB_NAME)* + +install: all + # Create directories + rm -rf $(DESTDIR)$(DATADIR) + $(MKDIR) $(DESTDIR)$(BINDIR) + $(MKDIR) $(DESTDIR)$(LIBDIR) + $(MKDIR) $(DESTDIR)$(INCDIR) + $(MKDIR) $(DESTDIR)$(DATADIR) + # Install espeak executable + $(INSTALL) -m 755 $(BIN2_NAME) $(DESTDIR)$(BINDIR) + # Install shared library + $(INSTALL) -m 755 $(LIB_NAME).$(LIBTAG) $(DESTDIR)$(LIBDIR) + # Install static library + $(INSTALL) -m 755 $(STATIC_LIB_NAME) $(DESTDIR)$(LIBDIR) + $(LN_SF) $(LIB_NAME).$(LIBTAG) $(DESTDIR)$(LIBDIR)/$(LIB_NAME).$(LIB_VERSION) + $(LN_SF) $(LIB_NAME).$(LIB_VERSION) $(DESTDIR)$(LIBDIR)/$(LIB_NAME) + # Install development headers + $(INSTALL) -pm 644 speak_lib.h $(DESTDIR)$(INCDIR) + # Install data files + cp -prf ../espeak-data/* $(DESTDIR)$(DATADIR) + diff --git a/platforms/dos/SPEECH.H b/platforms/dos/SPEECH.H new file mode 100644 index 00000000..3db1fc8f --- /dev/null +++ b/platforms/dos/SPEECH.H @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2005 to 2007 by Jonathan Duddington * + * email: jonsd@users.sourceforge.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License * + * along with this program; if not, write see: * + * . * + ***************************************************************************/ + + +#include + +// conditional compilation options + +#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN +#define ARCH_BIG +#endif + +#define PLATFORM_DOS +#define NEED_WCHAR_FUNCTIONS +#define NEED_GETOPT +typedef unsigned int uint32_t; + +#define PATHSEP '\\' +//#define USE_PORTAUDIO +#define USE_NANOSLEEP +#define __cdecl +#define ESPEAK_API extern "C" + +#ifdef LIBRARY +#define USE_ASYNC +//#define USE_MBROLA_LIB +#endif + +#ifdef _ESPEAKEDIT +#define USE_ASYNC +#define LOG_FRAMES // write keyframe info to log-espeakedit +#endif + +// will look for espeak_data directory here, and also in user's home directory +#ifndef PATH_ESPEAK_DATA + #define PATH_ESPEAK_DATA "/usr/share/espeak-data" +#endif + + +#ifdef PLATFORM_DOS +int iswalpha(int c); +int iswdigit(int c); +int iswalnum(int c); +int towlower(int c); +int iswupper(int c); +int iswlower(int c); +int iswspace(int c); +int iswpunct(int c); +const wchar_t *wcschr(const wchar_t *str, int c); +const int wcslen(const wchar_t *str); +float wcstod(const wchar_t *str, wchar_t **tailptr); +int towupper(int c); +#endif + + + +typedef unsigned short USHORT; +typedef unsigned char UCHAR; +typedef double DOUBLEX; + + + + +typedef struct { + const char *mnem; + int value; +} MNEM_TAB; +int LookupMnem(MNEM_TAB *table, char *string); + + + +#define N_PATH_HOME 120 +extern char path_home[N_PATH_HOME]; // this is the espeak-data directory + +extern void strncpy0(char *to,const char *from, int size); +int GetFileLength(const char *filename); +char *Alloc(int size); +void Free(void *ptr); + diff --git a/platforms/dos/readme.dos b/platforms/dos/readme.dos new file mode 100644 index 00000000..f99b1227 --- /dev/null +++ b/platforms/dos/readme.dos @@ -0,0 +1,24 @@ +Building speak.exe with djgpp: + +1. +unzip the source with the unzip32.exe utility from djgpp. + +2. +change into the src directory. +copy the makefile.dj and the speech.h file into the src directory +type in the src directory make -f makefile.dj + +3. +copy the speak.exe into the main directory (cp speak.exe ..\speak.exe + +Now you can use speak.exe to produce wave-files: + +speak -v de -f test.txt -w test.wav + +or you can produce phonemes for mbrola: + +speak -v mb\mb-de4 -f test.txt >test.pho + + +speak --voices will list all voices. +Test it and enjoy. diff --git a/platforms/riscos/!Help b/platforms/riscos/!Help new file mode 100644 index 00000000..d70c0968 --- /dev/null +++ b/platforms/riscos/!Help @@ -0,0 +1,122 @@ +eSpeak - RISCOS Version +======================== + +NOTE: The contents of the files in the espeak-dat directory, + and the format of their contents has changed for this version. + Please delete your old espeak-dat directory and replace it + with the new one in this package. + + +Requirements +============ + +RISCOS 3.6 or later with 16 bit sound system enabled. + +On my 200MHz StrongArm, it takes 51 sec to process 6m 3s of speech output, +so it will probably run OK on an ARM7 processor also. + + + +Installation and Use +==================== + +1. Copy the !eSpeak directory onto your harddrive. + +2. To load the Speak module: double-click on !eSpeak. + + This sets the system variable, and then runs + the "speakmod" file to load the Speak module. + + Note, refers to the directory that contains the + espeak-dat directory, which contains the speech data. It must + be set before the module is loaded. + + +3. Example commands: + + *help speak + should now show version 3.10 + + *speak -h + shows the available commands + + *speak "this is some text" + speaks the string "this is some text" + + *speak -v en-f "this is some text" + speaks with a different voice + + *speak -f textfile + speaks the text from file "textfile" + + *speak -a30 "this is some text" + speaks more quietly (range 0 to 200) + + *speak -s200 "this is some text" + speaks more quickly (200 words per minute) + + The improvement in speech quality over Speak v.2 are most clearly + heard when listening through a good sound system (eg. domestic + stereo system) rather than small computer speakers. + + +4. Adding words to the pronunciation dictionary + + The directory "data" contains pronunciation rules and exceptions + lists. To add words, add the word and its pronunciation + phonemes to en_extra and then do the speak command + + speak --compile=en + + from within the data directory. This will recompile the files: + en_dict in the espeak_dat directory. + + Details of the phoneme codes are given in docs.phonemes/html + + You can see the translated phoneme codes for a word by + speak -x "word" + + + +Use with Pluto +============== + + !Pluto will use the new module if speakmod has already + been run. Pluto's Speak dialog should show the new voices. + If you wish, you can give them more meaningful names by + renaming the files in espeak-dat.voices + + To install permanently in Pluto, you can copy "speakmod" into + !Pluto to replace the old speakmod for Speak version 2. + + Note that the system variable must be set before + speakmod is loaded. This can be done by either: + + a. Making sure that !eSpeak is seen by the RISC OS filer + before Pluto is run. + or + b. Putting the line: + Set eSpeak$dir + in the !Pluto.!Run file and copying the espeak-dat directory + into !Pluto + + Re-select the voices that Pluto uses. These may have changed. + + +To Re-Compile the Speak Module +============================== + + Download the "speak-*-source.zip" package and follow the instruction + int the ReadMe file in the "riscos" directory. + + +Problems +======== + +1. It uses the sound system directly rather than through the + SharedSound module, would allow the system volume control apply + to speech. + +2. There is no session management implemented, so changes to speed, + amplitude etc by one user of the module will affect the others. + \ No newline at end of file diff --git a/platforms/riscos/Makefile b/platforms/riscos/Makefile new file mode 100644 index 00000000..2cd3b0da --- /dev/null +++ b/platforms/riscos/Makefile @@ -0,0 +1,65 @@ +# Project: Speak3 + + +# Toolflags: +CCflags = -c -C90 -depend !Depend -IC: -throwback -zM +C++flags = -c -depend !Depend -IC: -throwback -zM +Linkflags = -rmf -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -o $@ +Squeezeflags = -o $@ + + +# Final targets: +@.speakmod: @.o.speak_riscos @.o.compiledict @.o.dictionary \ + @.o.intonation @.o.readclause @.o.setlengths @.o.synthdata \ + @.o.synthesize @.o.translate @.o.tr_languages @.o.numbers \ + @.o.synth_mbrola @.o.phonemelist \ + @.o.tr_english @.o.wavegen @.o.voices @.o.assemb @.o.cmhgfile + Link $(Linkflags) C:o.stubs C:o.c++lib @.o.speak_riscos @.o.compiledict \ + @.o.dictionary @.o.intonation @.o.readclause @.o.setlengths \ + @.o.synthdata @.o.synthesize @.o.numbers @.o.synth_mbrola \ + @.o.translate @.o.tr_english @.o.wavegen @.o.tr_languages \ + @.o.voices @.o.phonemelist @.o.assemb @.o.cmhgfile + + +# User-editable dependencies: + +# Static dependencies: +@.o.speak_riscos: @.cpp.speak_riscos + c++ $(c++flags) -o @.o.speak_riscos @.cpp.speak_riscos +@.o.compiledict: @.cpp.compiledict + c++ $(c++flags) -o @.o.compiledict @.cpp.compiledict +@.o.dictionary: @.CPP.dictionary + c++ $(c++flags) -o @.o.dictionary @.CPP.dictionary +@.o.intonation: @.CPP.intonation + c++ $(c++flags) -o @.o.intonation @.CPP.intonation +@.o.numbers: @.CPP.numbers + c++ $(c++flags) -o @.o.numbers @.CPP.numbers +@.o.phonemelist: @.CPP.phonemelist + c++ $(c++flags) -o @.o.phonemelist @.CPP.phonemelist +@.o.readclause: @.CPP.readclause + c++ $(c++flags) -o @.o.readclause @.CPP.readclause +@.o.setlengths: @.CPP.setlengths + c++ $(c++flags) -o @.o.setlengths @.CPP.setlengths +@.o.synthdata: @.CPP.synthdata + c++ $(c++flags) -o @.o.synthdata @.CPP.synthdata +@.o.synth_mbrola: @.CPP.synth_mbrola + c++ $(c++flags) -o @.o.synth_mbrola @.CPP.synth_mbrola +@.o.synthesize: @.CPP.synthesize + c++ $(c++flags) -o @.o.synthesize @.CPP.synthesize +@.o.translate: @.CPP.translate + c++ $(c++flags) -o @.o.translate @.CPP.translate +@.o.tr_english: @.CPP.tr_english + c++ $(c++flags) -o @.o.tr_english @.CPP.tr_english +@.o.tr_languages: @.CPP.tr_languages + c++ $(c++flags) -o @.o.tr_languages @.CPP.tr_languages +@.o.voices: @.CPP.voices + c++ $(c++flags) -o @.o.voices @.CPP.voices +@.o.wavegen: @.CPP.wavegen + c++ $(c++flags) -o @.o.wavegen @.CPP.wavegen +@.o.assemb: @.s.assemb + objasm $(objasmflags) -from @.s.assemb -to @.o.assemb + +# Dynamic dependencies: diff --git a/platforms/riscos/ReadMe b/platforms/riscos/ReadMe new file mode 100644 index 00000000..806a4171 --- /dev/null +++ b/platforms/riscos/ReadMe @@ -0,0 +1,14 @@ +These files are for a version for RISC OS computers (formerly +known as "Acorn" computers), which use ARM processors. + + +To compile the speakmod module for RISC OS. + +1. Run the "copysource" script to copy the source files from the + general source.src directory into the riscos.cpp and + riscos.h directories. These already contain the RISC OS + specific files. + +2. Run the Makefile to compile and link and produce the + "speakmod" module. + I used the AcornC/C++ compiler. diff --git a/platforms/riscos/copysource b/platforms/riscos/copysource new file mode 100644 index 00000000..13698cce --- /dev/null +++ b/platforms/riscos/copysource @@ -0,0 +1,24 @@ +copy .^.src.compiledict/cpp .cpp.compiledict fq~c +copy .^.src.dictionary/cpp .cpp.dictionary fq~c +copy .^.src.intonation/cpp .cpp.intonation fq~c +copy .^.src.numbers/cpp .cpp.numbers fq~c +copy .^.src.phonemelist/cpp .cpp.phonemelist fq~c +copy .^.src.readclause/cpp .cpp.readclause fq~c +copy .^.src.setlengths/cpp .cpp.setlengths fq~c +copy .^.src.synthdata/cpp .cpp.synthdata fq~c +copy .^.src.synth_mbrola/cpp .cpp.synth_mbrola fq~c +copy .^.src.synthesize/cpp .cpp.synthesize fq~c +copy .^.src.translate/cpp .cpp.translate fq~c +copy .^.src.tr_english/cpp .cpp.tr_english fq~c +copy .^.src.tr_languages/cpp .cpp.tr_languages fq~c +copy .^.src.voices/cpp .cpp.voices fq~c +copy .^.src.wavegen/cpp .cpp.wavegen fq~c + +copy .^.src.phoneme/h .h.phoneme fq~c +copy .^.src.sintab/h .h.sintab fq~c +copy .^.src.speak_lib/h .h.speak_lib fq~c +copy .^.src.synthesize/h .h.synthesize fq~c +copy .^.src.translate/h .h.translate fq~c +copy .^.src.tr_languages/h .h.tr_languages fq~c +copy .^.src.voice/h .h.voice fq~c +copy .^.src.wave/h .h.wave fq~c diff --git a/platforms/riscos/cpp/speak_riscos b/platforms/riscos/cpp/speak_riscos new file mode 100644 index 00000000..03ae69fc --- /dev/null +++ b/platforms/riscos/cpp/speak_riscos @@ -0,0 +1,1228 @@ + +/************************************************************************** +* Copyright (C) 2005,2006 by Jonathan Duddington * +* jonsd@users.sourceforge.net * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#define USE_MODULE + +#include +#include +#include +#include +#include +#include "kernel.h" + +#include "speech.h" +#include "speak_lib.h" +#include "voice.h" +#include "phoneme.h" +#include "synthesize.h" +#include "translate.h" + +#define os_X 0x20000 + +// interface to the assembler section +extern "C" { +extern void DMA_Handler(void); + + +// used from the cmhgfile +extern _kernel_oserror *user_init(char *cmd_fail, int podule_base, void *pw); +extern _kernel_oserror *swi_handler(int swi_no, int *r, void *pw); +extern _kernel_oserror *command_handler(char *arg_string, int argc, int cmd_no, void *pw); +extern int callback_handler(_kernel_swi_regs *r, void *pw); +extern int callback_entry(_kernel_swi_regs *r, void *pw); +extern int sound_handler(_kernel_swi_regs *r, void *pw); +extern int sound_entry(_kernel_swi_regs *r, void *pw); + +} + +extern int Generate(PHONEME_LIST *phoneme_list, int *n_ph, int resume); +extern void RiscosOpenSound(); +extern int WcmdqUsed(); +extern void FreePhData(); +extern void FreeDictionary(); + +extern int wcmdq_head; +extern int wcmdq_tail; +extern int current_source_index; + +FILE *f_text; +int (* uri_callback)(int, const char *, const char *) = NULL; + +int amp = 8; // default + +char path_home[80] = ""; +char wavefile[120]; +char textbuffile[L_tmpnam]; +int sample_rate_index; // current value +int current_voice_num=0; +int n_voice_files = 0; + +// output sound buffer, 2 bytes per sample +static unsigned short SoundBuf[4096]; +static void *module_data; +static int callback_inhibit = 0; +static int more_text=0; + +#define N_VOICE_NAMES 40 +static char *voice_names[40]; + +#define N_STATIC_BUF 8000 +static char static_buf[N_STATIC_BUF]; +static _kernel_oserror errblk; + + + +USHORT voice_pcnt[N_PEAKS+1][3]; +voice_t voice_data; +voice_t *voice; + +static const char *help_text = +"\nspeak [options] [\"\"]\n\n" +"-f Text file to speak\n" +"--stdin Read text input from stdin instead of a file\n\n" +"If neither -f nor --stdin, are spoken, or if none then text is\n" +"spoken from stdin, each line separately.\n\n" +"-a \n" +"\t Amplitude, 0 to 200, default is 100\n" +"-l \n" +"\t Line length. If not zero (which is the default), consider\n" +"\t lines less than this length as end-of-clause\n" +"-p \n" +"\t Pitch adjustment, 0 to 99, default is 50\n" +"-s \n" +"\t Speed in words per minute 80 to 370, default is 170\n" +"-v \n" +"\t Use voice file of this name from espeak-data/voices\n" +"-w \n" +"\t Write output to this WAV file, rather than speaking it directly\n" +"-b\t Input text is 8-bit encoding\n" +"-m\t Interpret SSML markup, and ignore other < > tags\n" +"-q\t Quiet, don't produce any speech (may be useful with -x)\n" +"-x\t Write phoneme mnemonics to stdout\n" +"-X\t Write phonemes mnemonics and translation trace to stdout\n" +"--stdout Write speech output to stdout\n" +"--compile=\n" +"\t Compile the pronunciation rules and dictionary in the current\n" +"\t directory. = is optional and specifies which language\n" +"--punct=\"\"\n" +"\t Speak the names of punctuation characters during speaking. If\n" +"\t = is omitted, all punctuation is spoken.\n" +"--voices=\n" +"\t List the available voices for the specified language.\n" +"\t If is omitted, then list all voices.\n"; + + +// additional Latin characters beyond the Latin1 character set +#define MAX_WALPHA 0x233 +// indexed by character - 0x100 +// 0=not alphabetic, 0xff=lower case, other=value to add to upper case to convert to lower case +static unsigned char walpha_tab[MAX_WALPHA-0xff] = { + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 100 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 110 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 120 + 0xff,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1, // 130 + 0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, // 140 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 150 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 160 + 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, // 170 + 0xff, 210, 1,0xff, 1,0xff, 206, 1,0xff, 205, 205, 1,0xff,0xff, 79, 202, // 180 + 203, 1,0xff, 205, 207,0xff, 211, 209, 1,0xff,0xff,0xff, 211, 213,0xff, 214, // 190 + 1,0xff, 1,0xff, 1,0xff, 218, 1,0xff, 218,0xff,0xff, 1,0xff, 218, 1, // 1a0 + 0xff, 217, 217, 1,0xff, 1,0xff, 219, 1,0xff,0xff,0xff, 1,0xff,0xff,0xff, // 1b0 + 0xff,0xff,0xff,0xff, 2, 1,0xff, 2, 1,0xff, 2, 1,0xff, 1,0xff, 1, // 1c0 + 0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff,0xff, 1,0xff, // 1d0 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1e0 + 0xff, 2, 1,0xff, 1,0xff,0xff,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 1f0 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 200 + 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 210 + 0xff, 0, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, 1,0xff, // 220 + 1,0xff, 1,0xff }; // 230 + +// use ctype.h functions for Latin1 (character < 0x100) +int iswalpha(int c) +{ + if(c < 0x100) + return(isalpha(c)); + if(c > MAX_WALPHA) + return(0); + return(walpha_tab[c-0x100]); +} + +int iswdigit(int c) +{ + if(c < 0x100) + return(isdigit(c)); + return(0); +} + +int iswalnum(int c) +{ + if(iswdigit(c)) + return(1); + return(iswalpha(c)); +} + +int towlower(int c) +{ + int x; + if(c < 0x100) + return(tolower(c)); + if((c > MAX_WALPHA) || ((x = walpha_tab[c-0x100])==0xff)) + return(c); // already lower case + return(c + x); // convert to lower case +} + +int iswupper(int c) +{ + int x; + if(c < 0x100) + return(isupper(c)); + if(((c > MAX_WALPHA) || (x = walpha_tab[c-0x100])==0) || (x == 0xff)) + return(0); + return(1); +} + +int iswlower(int c) +{ + if(c < 0x100) + return(islower(c)); + if((c > MAX_WALPHA) || (walpha_tab[c-0x100] != 0xff)) + return(0); + return(1); +} + +int iswspace(int c) +{ + if(c < 0x100) + return(isspace(c)); + return(0); +} + +int iswpunct(int c) +{ + if(c < 0x100) + return(ispunct(c)); + return(0); +} + +const wchar_t *wcschr(const wchar_t *str, int c) +{ + while(*str != 0) + { + if(*str == c) + return(str); + str++; + } + return(NULL); +} + +const int wcslen(const wchar_t *str) +{ + int ix=0; + + while(*str != 0) + { + ix++; + } + return(ix); +} + + +int GetFileLength(const char *filename) +{//==================================== + int length=0; + int type; + _kernel_swi_regs regs; + _kernel_oserror *error; + + regs.r[0] = 5; + regs.r[1] = (int)filename; + regs.r[2] = 0; + regs.r[3] = 0; + regs.r[4] = 0; + regs.r[5] = 0; + + error = _kernel_swi(0x20008,®s,®s); + if(error) + return(0); + + type = regs.r[0]; + length = regs.r[4]; + + if(type==2) + return(-2); // a directory + if((type!=1) && (type!=3)) + return(0); /* not a file */ + + return(length); +} /* end of GetFileLength */ + + + +void ReadVoiceNames2(char *directory) +{//================================== + int len; + int *type; + char *p; + _kernel_swi_regs regs; + _kernel_oserror *error; + char buf[80]; + char directory2[80]; + + regs.r[0] = 10; + regs.r[1] = (int)directory; + regs.r[2] = (int)buf; + regs.r[3] = 1; + regs.r[4] = 0; + regs.r[5] = sizeof(buf); + regs.r[6] = 0; + + while(regs.r[3] > 0) + { + error = _kernel_swi(0x0c+os_X,®s,®s); /* OS_GBPB 10, read directory entries */ + if((error != NULL) || (regs.r[3] == 0)) + { + break; + } + type = (int *)(&buf[16]); + len = strlen(&buf[20]); + + if(*type == 2) + { + // a sub-directory + sprintf(directory2,"%s.%s",directory,&buf[20]); + ReadVoiceNames2(directory2); + } + else + { + p = Alloc(len+1); + strcpy(p,&buf[20]); + voice_names[n_voice_files++] = p; + if(n_voice_files >= (N_VOICE_NAMES-1)) + break; + } + } +} + + +void ReadVoiceNames() +{//=================== + char directory[80]; + + for(n_voice_files=0; n_voice_files sizeof(SoundBuf)) + size = sizeof(SoundBuf); + + out_ptr = (unsigned char *)(&SoundBuf[0]); + out_end = (unsigned char *)(&SoundBuf[size]); + WavegenFill(1); +} + + + +int initialise(void) +{//================= + sprintf(path_home,"%s.espeak-data",""); + if(GetFileLength(path_home) != -2) + { + // not found, try the 10 character version of the directory name + sprintf(path_home,"%s.espeak-dat",""); + } + if(GetFileLength(path_home) != -2) + { + // still can't find data directory + sprintf(errblk.errmess,"Speak: Can't find data directory: '%s'\n",path_home); + return(-1); + } + + WavegenInit(22050,0); + LoadPhData(); + SynthesizeInit(); + return(0); +} + + + +void speak_text_string(char *data, int terminator, int len, int wait, int voice_num) +/**********************************************************************************/ +/* 'wait' indictes wait until speaking is finished before returning */ +{ + int c; + int ix; + static static_length=0; + static int user_token=0; /* increment for each call of translate() */ + _kernel_swi_regs regs; + + regs.r[0] = (int)callback_entry; + regs.r[1] = (int)module_data; + _kernel_swi(0x5f, ®s, ®s); + + + if((voice_num >= 0) && (voice_num != current_voice_num) && (voice_num < N_VOICE_NAMES)) + { + LoadVoice(voice_names[voice_num],0); + WavegenSetVoice(voice); + } + current_voice_num = voice_num; + + /* don't count CR as terminator if length is specified */ + if(len > 0) terminator = 0; + + ix = 0; + if(more_text == 0) + static_length = 0; + else + { + strcat(&static_buf[static_length]," : "); + static_length+=3; + } + + if(terminator == 0) + { + while(((c = data[ix++]) != 0) && (static_length < N_STATIC_BUF-4)) + { + static_buf[static_length++] = c; + if(ix == len) + break; + } + } + else + { + while(((c = data[ix++]) != '\r') && (c != '\n') && (c != 0) && (static_length < N_STATIC_BUF-3)) + { + static_buf[static_length++] = c; + if(ix == len) + break; + } + } + static_buf[static_length] = 0; + + if(option_waveout==0) + { + if(more_text == 0) + { + InitText(0); + RiscosOpenSound(); + more_text = SpeakNextClause(NULL,(void *)static_buf,0); + } + + while(wait) + { + if((more_text==0) && (wcmdq_head == wcmdq_tail)) + break; + + //we need to block to allow the callback handler to run + regs.r[0] = 129; // wait for key press + regs.r[1] = 10; + regs.r[2] = 0; + _kernel_swi(0x06, ®s, ®s); // OS_Byte + } + } + else + { + more_text = 0; + SpeakNextClause(NULL,(void *)static_buf,0); + + for(;;) + { + if(WavegenFile() != 0) + break; // finished, wavegen command queue is empty + + if(Generate(phoneme_list,&n_phoneme_list,1)==0) + SpeakNextClause(NULL,NULL,1); + } + + CloseWaveFile(samplerate); + } + +} /* end of speak_text_string */ + + + + +void speak_file(char *fname) +{//========================= + FILE *f_in; + char buf[120]; + + f_in = fopen(fname,"r"); + if(f_in == NULL) + { + fprintf(stderr,"Can't read file: '%s'",fname); + return; + } + more_text = 1; + + if(option_waveout == 0) + { + RiscosOpenSound(); + SpeakNextClause(f_in,NULL,0); + } + else + { + more_text = 0; + SpeakNextClause(f_in,NULL,0); + + for(;;) + { + if(WavegenFile() != 0) + break; // finished, wavegen command queue is empty + + if(Generate(phoneme_list,&n_phoneme_list,1)==0) + SpeakNextClause(NULL,NULL,1); + } + + CloseWaveFile(samplerate); + } +} + + + +void set_say_options(int reg2, int reg3) +/**************************************/ +/* Sets options from information in 'say' SWI */ +/* R3 bits 0-7 stress indicator character + bit 8 inhibit unpronouncable check */ +{ + option_linelength = 0; + option_phonemes = 0; + option_waveout = 0; + option_harmonic1 = 8; + option_multibyte = 0; // auto + option_capitals = 0; + option_punctuation = 0; + option_punctlist[0] = 0; +} /* end of set_say_options */ + + + +void jsd_swi_functions(int *r) +/****************************/ +{ + switch(r[0]) + { + case 0: /* major version */ + r[0] = 3; + break; + + case 1: /* register user */ + break; + + case 2: /* deregister user */ + break; + + case 3: +// r[0] = (int)speech_to_phonemes((char *)r[1]); + break; + + case 4: +// r[0] = reload_word_dict(NULL); + break; + + case 5: /* get table of voice names */ + r[0] = (int)voice_names; + break; + + case 6: /* update voice data, r1 = voice_number */ + if(r[1] < N_VOICE_NAMES) + { + LoadVoice(voice_names[r[1]],0); + current_voice_num = r[1]; + WavegenSetVoice(voice); + } + break; + + case 7: /* load voice data */ +// init_voice((char *)r[1]); + break; + + default: + r[0] = 0; + r[1] = 0; + break; + } +} /* end of jsd_swi_functions */ + + + + +_kernel_oserror *swi_handler(int swi_no, int *r, void *pw) +/*********************************************************/ +{ + int value; + int q_length; + int speed; + int amp; + value = r[0]; + + switch(swi_no) + { + + case 0: // ready ? + // returns the index into the source text of the currently speaking word + if(current_source_index > 0) + r[1] = current_source_index-1; + else + r[1] = current_source_index; /* source index */ + r[2] = 0; /* source tag */ + r[3] = 0; /* for future expansion */ + r[4] = 0; + r[5] = 0; + + if(wcmdq_head == wcmdq_tail) + { + r[0] = -1; /* ready, or nearly */ + } + else + r[0] = 0; + break; + + case 1: /* restore old sound channel. DO NOTHING */ + break; + + case 2: /* miscellaneous functions */ + jsd_swi_functions(r); + break; + + case 3: /* speak text */ +// _kernel_irqs_on(); + set_say_options(r[2],r[3]); + speak_text_string((char *)r[0],'\r',r[1],0,r[2]); + break; + + case 4: /* speak text and wait */ +// _kernel_irqs_on(); /* enable interrupts */ + set_say_options(r[2],r[3]); + speak_text_string((char *)r[0],'\r',r[1],1,r[2]); + break; + + case 5: /* stop speaking */ + SpeakNextClause(NULL,NULL,2); + more_text = 0; + break; + + case 7: /* pitch */ + // not implemented + break; + + case 8: /* speed */ + speed = (value * 160)/140; + SetParameter(espeakRATE,speed,0); + break; + + case 9: /* word_gap */ + // not implemented + break; + + case 10: /* pitch_range */ + // not implemented + break; + + case 12: /* reset */ + // not implemented + break; + + case 13: /* volume */ + amp = (value*45)/100; + SetParameter(espeakVOLUME,amp,0); + WavegenSetVoice(voice); + break; + } + return(NULL); +} /* end of swi_handler */ + + + +void PitchAdjust(int pitch_adjustment) +{//=================================== + int ix, factor; + voice_t *voice = &voice_data; + extern unsigned char pitch_adjust_tab[100]; + + voice->pitch_base = (voice->pitch_base * pitch_adjust_tab[pitch_adjustment])/128; + + // adjust formants to give better results for a different voice pitch + factor = 256 + (25 * (pitch_adjustment - 50))/50; + for(ix=0; ix<=5; ix++) + { + voice->freq[ix] = (voice->freq2[ix] * factor)/256; + } +} // end of PitchAdjustment + + + +char *param_string(char **argp) +{//============================ + char *p; + int ix=0; + static char buf[80]; + + p = *argp; + while(*p == ' ') p++; + while(!isspace(*p)) + buf[ix++] = *p++; + buf[ix]=0; + + *argp = p; + return(buf); +} + +int param_number(char **argp) +{//========================== + int value; + char *p; + + p = *argp; + while(*p == ' ') p++; + + value = atoi(p); + while(!isspace(*p)) p++; + *argp = p; + return(value); +} + +void command_line(char *arg_string, int wait) +{//========================================== + + int option_index = 0; + int c; + int value; + int speed; + int amp; + int speaking = 0; + int flag_stdin = 0; + int flag_compile = 0; + int error; + int pitch_adjustment = 50; + char filename[80]; + char voicename[40]; + char command[80]; + char *p; + int ix; + + voicename[0] = 0; + wavefile[0] = 0; + filename[0] = 0; + option_linelength = 0; + option_phonemes = 0; + option_waveout = 0; + option_quiet = 0; + option_harmonic1 = 8; + option_multibyte = 0; // auto + option_capitals = 0; + option_punctuation = 0; + option_punctlist[0] = 0; + + f_trans = stdout; + + p = arg_string; + + for(;;) + { + while(*p==' ') p++; // skip spaces + if(*p == '\r') break; // end of line + + if(*p == '-') + { + // a command line argument + p++; + switch(*p++) + { + case 'h': + printf("\n"); + printf("speak text-to-speech: %s\n%s",version_string,help_text); + return; + + case 'a': + amp = param_number(&p); + SetParameter(espeakVOLUME,amp,0); + break; + + case 'f': + strcpy(filename,param_string(&p)); + break; + + case 'k': + option_capitals = param_number(&p); + SetParameter(espeakCAPITALS,option_capitals,0); + break; + + case 'l': + option_linelength = param_number(&p); + break; + + case 'p': + pitch_adjustment = param_number(&p); + break; + + case 'q': + option_quiet = 1; + break; + + case 's': + speed = param_number(&p); + SetParameter(espeakRATE,speed,0); + break; + + case 'v': + strcpy(voicename,param_string(&p)); + break; + + case 'w': + option_waveout=1; + strcpy(wavefile,param_string(&p)); + break; + + case 'x': + option_phonemes = 1; + break; + + case 'X': + option_phonemes = 2; + break; + + case '-': + strcpy(command,param_string(&p)); + if(memcmp(command,"compile=",8)==0) + { + CompileDictionary(NULL,&command[8],NULL,NULL); + return; + } + else + if(strcmp(command,"help")==0) + { + printf("\n%s\n%s",version_string,help_text); + return; + } + else + if(memcmp(command,"punct",5)==0) + { + option_punctuation = 1; + if((command[5]=='=') && (command[6]=='"')) + { + ix = 0; + while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = command[ix+7]) != 0)) ix++; + option_punctlist[N_PUNCTLIST-1] = 0; + option_punctuation = 2; + } + SetParameter(espeakPUNCTUATION,option_punctuation,0); + } + else + { + printf("Command not recognised\n"); + } + break; + + default: + printf("Command not recognised\n"); + break; + } + + } + else + { + break; + } + } + + LoadVoice(voicename,0); + + if((filename[0]==0) && (p[0]=='\r')) + { + // nothing to speak + if(option_quiet) + { + SpeakNextClause(NULL,NULL,2); // stop speaking + more_text = 0; + } + } + + if(option_waveout || option_quiet) + { + // write speech to a WAV file + if(option_quiet) + { + OpenWaveFile(NULL,samplerate); + option_waveout = 2; + } + else + { + if(OpenWaveFile(wavefile,samplerate) != 0) + { + fprintf(stderr,"Can't write to output file '%s'\n'",wavefile); + return; + } + } + } + + if(pitch_adjustment != 50) + { + PitchAdjust(pitch_adjustment); + } + WavegenSetVoice(voice); + + if(filename[0]==0) + speak_text_string(p,'\r',0,wait,-1); + else + speak_file(filename); +} + + + +_kernel_oserror *command_handler(char *arg_string, int argc, int cmd_no, void *pw) +/********************************************************************************/ +{ + switch(cmd_no) + { + case 0: /* Say */ + command_line(arg_string,0); // for compatibility with speak V2 + break; + + case 1: /* Sayw ] */ + command_line(arg_string,0); + break; + + } + return(NULL); +} /* end of cmd_handler */ + + +// sound handler data +int current_sound_handler=0; +int prev_sound_handler=0; +int prev_sound_data=0; +int prev_sound_rate=13; +int sound_handler_changed=0; + + +void RiscosCloseSound() +{//==================== +_kernel_swi_regs regs; + if((sound_handler_changed) && (prev_sound_handler != (int)DMA_Handler)) + { + // check whether current handler is ours + regs.r[0]=0; + _kernel_swi(0x40145,®s,®s); + if(regs.r[1] == (int)DMA_Handler) + { + regs.r[0]=1; + regs.r[1]=prev_sound_handler; + regs.r[2]=prev_sound_data; + _kernel_swi(0x40145,®s,®s); // Sound LinearHandler 1 + + // reset to the previous sample rate + regs.r[0]=3; + regs.r[1]=prev_sound_rate; + _kernel_swi(0x40146,®s,®s); // Sound_SampleRate 3 + + current_sound_handler = prev_sound_handler; + sound_handler_changed = 0; + } + } +} // end of RiscosCloseSound + + + +void RiscosOpenSound() +{//=================== + _kernel_swi_regs regs; + + if(current_sound_handler != (int)DMA_Handler) + { + // register the sound handler + regs.r[0]=1; + regs.r[1]=(int)DMA_Handler; + regs.r[2]=(int)module_data; + _kernel_swi(0x40145,®s,®s); // Sound_LinearHandler 1 + prev_sound_handler = regs.r[1]; + prev_sound_data = regs.r[2]; + + // set the sample rate + regs.r[0]=3; + regs.r[1]=sample_rate_index; + regs.r[2]=0; + _kernel_swi(0x40146,®s,®s); // Sound_SampleRate + prev_sound_rate = regs.r[1]; + + current_sound_handler = (int)DMA_Handler; + sound_handler_changed = 1; + } +} // end of RiscosOpenSound + + + + + +int callback_handler(_kernel_swi_regs *r, void *pw) +/*************************************************/ +{ + if(Generate(phoneme_list,&n_phoneme_list,1)==0) + { + more_text = SpeakNextClause(NULL,NULL,1); + } + + if((WcmdqUsed() == 0) && (more_text == 0)) + { + RiscosCloseSound(); + } + callback_inhibit = 0; + + return(1); +} /* end of callback_handler */ + + + +int sound_handler(_kernel_swi_regs *r, void *pw) +/**********************************************/ +{ + int n_queue; + int size; + int *dma_buf; + int x; + int ix; + + module_data = (int *)pw; + dma_buf = (int *)r->r[1]; + size = (r->r[2] - r->r[1])/4; + FillSoundBuf(size); + + for(ix=0; ixr[0] = 0; + if(callback_inhibit == 0) + { + // set a callback either: + // - queue is low and there is more text to be processed + // - queue is empty and no more text, so callback handler will remove the sound handler + if(((n_queue < 20) && (more_text != 0)) || + ((n_queue==0) && (more_text == 0))) + { + callback_inhibit = 1; + r->r[0] = 1; + r->r[1] = (int)pw; + } + } + return(1); +} + + + + +int InitSound16(int sample_rate) +/******************************/ +/* Find sample rate index */ +{ + int current_rate_index; // current value + + int sound_mode; + int sound_config; + int srate; + int n_srix; + int ix; + _kernel_swi_regs regs; + _kernel_oserror *error; + + sound_mode = 0; + regs.r[0] = 0; + error = _kernel_swi(0x40144+os_X,®s,®s); + sound_mode = regs.r[0]; + sound_config = regs.r[1]; + + if((error == NULL) && (sound_mode == 1)) + { + /* 16 bit sound, find sample rate index */ + regs.r[0] = 0; + regs.r[1] = 0; + _kernel_swi(0x40146,®s,®s); + n_srix = regs.r[1]; + + regs.r[0] = 1; + regs.r[1] = 0; + _kernel_swi(0x40146,®s,®s); + current_rate_index = regs.r[1]; // current sample rate index + srate = regs.r[2]; + for(ix=1; ix<=n_srix; ix++) + { + regs.r[0] = 2; + regs.r[1] = ix; + _kernel_swi(0x40146,®s,®s); + srate = regs.r[2]; + if(srate >= (sample_rate*1024)) + { + return(ix); + } + } + } + return(14); // this was the index for 22050 +} // end of InitSound16 + + + +void RemoveCallback() +/*******************/ +{ + _kernel_swi_regs regs; + + regs.r[0] = (int)callback_entry; + regs.r[1] = (int)module_data; + _kernel_swi(0x5f, ®s, ®s); +} + + +void terminate_module(void) +/*************************/ +{ + RiscosCloseSound(); + RemoveCallback(); + delete translator; + FreePhData(); +} /* end of terminate_module */ + + +void kill_module(void) +/********************/ +{ + _kernel_swi_regs regs; + regs.r[0]=4; + regs.r[1]=(int)"Speak"; + _kernel_swi(0x1e,®s,®s); /* RMKill */ +} + + +_kernel_oserror *user_init(char *cmd_fail, int podule_base, void *pw) +/*******************************************************************/ +{ + _kernel_swi_regs regs; + _kernel_oserror *error; + int param; + + // It seems that the wctype functions don't work until the locale has been set + // to something other than the default "C". Then, not only Latin1 but also the + // other characters give the correct results with iswalpha() etc. + + static char *locale = "ISO8859-1"; + setlocale(LC_CTYPE,locale); + + module_data = pw; + + sample_rate_index = InitSound16(22050); + + if(initialise() < 0) + { + // exit module, errblk.errmess is set by initialise() + errblk.errnum = 0x101; + return(&errblk); + } + + ReadVoiceNames(); + LoadVoice("default",0); + + for(param=0; param> 5] + MOV r9,r9,LSL #16 + MOV r9,r9,ASR #16 + LDR ip,[r3,r7,LSL #2] ; harmspect[h] + MLA r6,r9,ip,r6 + + ADD r8,r8,r0 ; theta += waveph + ADD r7,r7,#1 ; h++ + CMP r7,r1 + BLE as1 + + RSB r6,r6,#0 ; change sign + +as2 + MOV ip,r8,LSR #21 + LDR r9,[r5,ip,LSL #1] ; sin_tab[theta >> 5] + MOV r9,r9,LSL #16 + MOV r9,r9,ASR #16 + LDR ip,[r3,r7,LSL #2] ; harmspect[h] + MLA r6,r9,ip,r6 + + ADD r8,r8,r0 ; theta += waveph + ADD r7,r7,#1 ; h++ + CMP r7,r2 + BLE as2 + + MOV r0,r6 + LDMFD sp, {r5-r9,sp,pc} + END diff --git a/platforms/riscos/s/cmhgfile b/platforms/riscos/s/cmhgfile new file mode 100644 index 00000000..2d590fc8 --- /dev/null +++ b/platforms/riscos/s/cmhgfile @@ -0,0 +1,22 @@ + + +initialisation-code: user_init + +title-string: Speak +help-string: Speak 3.25 Text to Speech (32 bit) + +swi-chunk-base-number: &4ad80 +swi-handler-code: swi_handler +swi-decoding-table: Speak, + Ready,X,Misc,Say,Sayw,Stop,X,Pitch,Speed,WordGap,PitchRange,X,X,Volume + +vector-handlers: callback_entry/callback_handler +vector-handlers: sound_entry/sound_handler + +command-keyword-table: command_handler + SAY(min-args: 1, max-args: 255, + help-text: "Says English string \n"), + SAYW(min-args: 1, max-args: 255, + help-text: "Says English string \n"), + SPEAK(min-args: 1, max-args: 255, + help-text: "Says English string \n") diff --git a/windows/espeakedit/PAStaticWMME.lib b/platforms/windows/espeakedit/PAStaticWMME.lib similarity index 100% rename from windows/espeakedit/PAStaticWMME.lib rename to platforms/windows/espeakedit/PAStaticWMME.lib diff --git a/windows/espeakedit/ReadMe.txt b/platforms/windows/espeakedit/ReadMe.txt similarity index 100% rename from windows/espeakedit/ReadMe.txt rename to platforms/windows/espeakedit/ReadMe.txt diff --git a/windows/espeakedit/espeakedit.dsp b/platforms/windows/espeakedit/espeakedit.dsp similarity index 100% rename from windows/espeakedit/espeakedit.dsp rename to platforms/windows/espeakedit/espeakedit.dsp diff --git a/windows/espeakedit/espeakedit.dsw b/platforms/windows/espeakedit/espeakedit.dsw similarity index 100% rename from windows/espeakedit/espeakedit.dsw rename to platforms/windows/espeakedit/espeakedit.dsw diff --git a/windows/espeakedit/espeakedit.opt b/platforms/windows/espeakedit/espeakedit.opt similarity index 100% rename from windows/espeakedit/espeakedit.opt rename to platforms/windows/espeakedit/espeakedit.opt diff --git a/windows/espeakedit/espeakedit.plg b/platforms/windows/espeakedit/espeakedit.plg similarity index 100% rename from windows/espeakedit/espeakedit.plg rename to platforms/windows/espeakedit/espeakedit.plg diff --git a/windows/espeakedit/mondrian.icns b/platforms/windows/espeakedit/mondrian.icns similarity index 100% rename from windows/espeakedit/mondrian.icns rename to platforms/windows/espeakedit/mondrian.icns diff --git a/windows/espeakedit/mondros2.ico b/platforms/windows/espeakedit/mondros2.ico similarity index 100% rename from windows/espeakedit/mondros2.ico rename to platforms/windows/espeakedit/mondros2.ico diff --git a/windows/espeakedit/src_copy/StdAfx.h b/platforms/windows/espeakedit/src/StdAfx.h similarity index 100% rename from windows/espeakedit/src_copy/StdAfx.h rename to platforms/windows/espeakedit/src/StdAfx.h diff --git a/windows/espeakedit/src/speech.h b/platforms/windows/espeakedit/src/speech.h similarity index 100% rename from windows/espeakedit/src/speech.h rename to platforms/windows/espeakedit/src/speech.h diff --git a/windows/espeakedit/src/stdint.h b/platforms/windows/espeakedit/src/stdint.h similarity index 100% rename from windows/espeakedit/src/stdint.h rename to platforms/windows/espeakedit/src/stdint.h diff --git a/windows/windows_sapi/src/StdAfx.h b/platforms/windows/espeakedit/src_copy/StdAfx.h similarity index 100% rename from windows/windows_sapi/src/StdAfx.h rename to platforms/windows/espeakedit/src_copy/StdAfx.h diff --git a/windows/espeakedit/src_copy/speech.h b/platforms/windows/espeakedit/src_copy/speech.h similarity index 100% rename from windows/espeakedit/src_copy/speech.h rename to platforms/windows/espeakedit/src_copy/speech.h diff --git a/windows/make_espeak.iss b/platforms/windows/make_espeak.iss similarity index 100% rename from windows/make_espeak.iss rename to platforms/windows/make_espeak.iss diff --git a/windows/make_espeakedit.iss b/platforms/windows/make_espeakedit.iss similarity index 100% rename from windows/make_espeakedit.iss rename to platforms/windows/make_espeakedit.iss diff --git a/windows/windows_cmd/!ReadMe.txt b/platforms/windows/windows_cmd/!ReadMe.txt similarity index 89% rename from windows/windows_cmd/!ReadMe.txt rename to platforms/windows/windows_cmd/!ReadMe.txt index d1d456f9..d6a6fbd4 100755 --- a/windows/windows_cmd/!ReadMe.txt +++ b/platforms/windows/windows_cmd/!ReadMe.txt @@ -7,5 +7,5 @@ of eSpeak for Windows. Copy the source files from the Linux "src" directory into this "src" directory, EXCEPT for speech.h. Keep the original Windows -command-line version iof speech.h. +command-line version of speech.h. diff --git a/windows/windows_cmd/PAStaticWMME.lib b/platforms/windows/windows_cmd/PAStaticWMME.lib similarity index 100% rename from windows/windows_cmd/PAStaticWMME.lib rename to platforms/windows/windows_cmd/PAStaticWMME.lib diff --git a/windows/windows_cmd/StdAfx.cpp b/platforms/windows/windows_cmd/StdAfx.cpp similarity index 100% rename from windows/windows_cmd/StdAfx.cpp rename to platforms/windows/windows_cmd/StdAfx.cpp diff --git a/windows/windows_cmd/StdAfx.h b/platforms/windows/windows_cmd/StdAfx.h similarity index 100% rename from windows/windows_cmd/StdAfx.h rename to platforms/windows/windows_cmd/StdAfx.h diff --git a/windows/windows_cmd/espeak.dsp b/platforms/windows/windows_cmd/espeak.dsp similarity index 100% rename from windows/windows_cmd/espeak.dsp rename to platforms/windows/windows_cmd/espeak.dsp diff --git a/windows/windows_cmd/espeak.dsw b/platforms/windows/windows_cmd/espeak.dsw similarity index 100% rename from windows/windows_cmd/espeak.dsw rename to platforms/windows/windows_cmd/espeak.dsw diff --git a/windows/windows_cmd/src/speech.h b/platforms/windows/windows_cmd/src/speech.h similarity index 100% rename from windows/windows_cmd/src/speech.h rename to platforms/windows/windows_cmd/src/speech.h diff --git a/windows/windows_cmd/src/stdint.h b/platforms/windows/windows_cmd/src/stdint.h similarity index 100% rename from windows/windows_cmd/src/stdint.h rename to platforms/windows/windows_cmd/src/stdint.h diff --git a/windows/windows_dll/!ReadMe.txt b/platforms/windows/windows_dll/!ReadMe.txt similarity index 100% rename from windows/windows_dll/!ReadMe.txt rename to platforms/windows/windows_dll/!ReadMe.txt diff --git a/windows/windows_dll/StdAfx.cpp b/platforms/windows/windows_dll/StdAfx.cpp similarity index 100% rename from windows/windows_dll/StdAfx.cpp rename to platforms/windows/windows_dll/StdAfx.cpp diff --git a/windows/windows_dll/StdAfx.h b/platforms/windows/windows_dll/StdAfx.h similarity index 100% rename from windows/windows_dll/StdAfx.h rename to platforms/windows/windows_dll/StdAfx.h diff --git a/windows/windows_dll/espeak.dsp b/platforms/windows/windows_dll/espeak.dsp similarity index 100% rename from windows/windows_dll/espeak.dsp rename to platforms/windows/windows_dll/espeak.dsp diff --git a/windows/windows_dll/espeak.dsw b/platforms/windows/windows_dll/espeak.dsw similarity index 100% rename from windows/windows_dll/espeak.dsw rename to platforms/windows/windows_dll/espeak.dsw diff --git a/windows/windows_dll/src/StdAfx.h b/platforms/windows/windows_dll/src/StdAfx.h similarity index 100% rename from windows/windows_dll/src/StdAfx.h rename to platforms/windows/windows_dll/src/StdAfx.h diff --git a/windows/windows_dll/src/speak_lib.h b/platforms/windows/windows_dll/src/speak_lib.h similarity index 100% rename from windows/windows_dll/src/speak_lib.h rename to platforms/windows/windows_dll/src/speak_lib.h diff --git a/windows/windows_dll/src/speech.h b/platforms/windows/windows_dll/src/speech.h similarity index 100% rename from windows/windows_dll/src/speech.h rename to platforms/windows/windows_dll/src/speech.h diff --git a/windows/windows_dll/src/stdint.h b/platforms/windows/windows_dll/src/stdint.h similarity index 100% rename from windows/windows_dll/src/stdint.h rename to platforms/windows/windows_dll/src/stdint.h diff --git a/windows/windows_sapi/!ReadMe.txt b/platforms/windows/windows_sapi/!ReadMe.txt similarity index 100% rename from windows/windows_sapi/!ReadMe.txt rename to platforms/windows/windows_sapi/!ReadMe.txt diff --git a/windows/windows_sapi/TtsEng.aps b/platforms/windows/windows_sapi/TtsEng.aps similarity index 100% rename from windows/windows_sapi/TtsEng.aps rename to platforms/windows/windows_sapi/TtsEng.aps diff --git a/windows/windows_sapi/TtsEng.h b/platforms/windows/windows_sapi/TtsEng.h similarity index 100% rename from windows/windows_sapi/TtsEng.h rename to platforms/windows/windows_sapi/TtsEng.h diff --git a/windows/windows_sapi/TtsEng.tlb b/platforms/windows/windows_sapi/TtsEng.tlb similarity index 100% rename from windows/windows_sapi/TtsEng.tlb rename to platforms/windows/windows_sapi/TtsEng.tlb diff --git a/windows/windows_sapi/TtsEng_i.c b/platforms/windows/windows_sapi/TtsEng_i.c similarity index 100% rename from windows/windows_sapi/TtsEng_i.c rename to platforms/windows/windows_sapi/TtsEng_i.c diff --git a/windows/windows_sapi/resource.h b/platforms/windows/windows_sapi/resource.h similarity index 100% rename from windows/windows_sapi/resource.h rename to platforms/windows/windows_sapi/resource.h diff --git a/windows/windows_sapi/sapi.lib b/platforms/windows/windows_sapi/sapi.lib similarity index 100% rename from windows/windows_sapi/sapi.lib rename to platforms/windows/windows_sapi/sapi.lib diff --git a/platforms/windows/windows_sapi/src/StdAfx.h b/platforms/windows/windows_sapi/src/StdAfx.h new file mode 100755 index 00000000..c9a526fd --- /dev/null +++ b/platforms/windows/windows_sapi/src/StdAfx.h @@ -0,0 +1,3 @@ +// This is a dummy file. +// A file of this name is needed on Windows + diff --git a/windows/windows_sapi/src/speech.h b/platforms/windows/windows_sapi/src/speech.h similarity index 100% rename from windows/windows_sapi/src/speech.h rename to platforms/windows/windows_sapi/src/speech.h diff --git a/windows/windows_sapi/src/stdint.h b/platforms/windows/windows_sapi/src/stdint.h similarity index 100% rename from windows/windows_sapi/src/stdint.h rename to platforms/windows/windows_sapi/src/stdint.h diff --git a/windows/windows_sapi/stdafx.cpp b/platforms/windows/windows_sapi/stdafx.cpp similarity index 100% rename from windows/windows_sapi/stdafx.cpp rename to platforms/windows/windows_sapi/stdafx.cpp diff --git a/windows/windows_sapi/stdafx.h b/platforms/windows/windows_sapi/stdafx.h similarity index 100% rename from windows/windows_sapi/stdafx.h rename to platforms/windows/windows_sapi/stdafx.h diff --git a/windows/windows_sapi/ttseng.cpp b/platforms/windows/windows_sapi/ttseng.cpp similarity index 100% rename from windows/windows_sapi/ttseng.cpp rename to platforms/windows/windows_sapi/ttseng.cpp diff --git a/windows/windows_sapi/ttseng.def b/platforms/windows/windows_sapi/ttseng.def similarity index 100% rename from windows/windows_sapi/ttseng.def rename to platforms/windows/windows_sapi/ttseng.def diff --git a/windows/windows_sapi/ttseng.dsp b/platforms/windows/windows_sapi/ttseng.dsp similarity index 100% rename from windows/windows_sapi/ttseng.dsp rename to platforms/windows/windows_sapi/ttseng.dsp diff --git a/windows/windows_sapi/ttseng.dsw b/platforms/windows/windows_sapi/ttseng.dsw similarity index 100% rename from windows/windows_sapi/ttseng.dsw rename to platforms/windows/windows_sapi/ttseng.dsw diff --git a/windows/windows_sapi/ttseng.idl b/platforms/windows/windows_sapi/ttseng.idl similarity index 100% rename from windows/windows_sapi/ttseng.idl rename to platforms/windows/windows_sapi/ttseng.idl diff --git a/windows/windows_sapi/ttseng.rc b/platforms/windows/windows_sapi/ttseng.rc similarity index 100% rename from windows/windows_sapi/ttseng.rc rename to platforms/windows/windows_sapi/ttseng.rc diff --git a/windows/windows_sapi/ttsengobj.cpp b/platforms/windows/windows_sapi/ttsengobj.cpp similarity index 100% rename from windows/windows_sapi/ttsengobj.cpp rename to platforms/windows/windows_sapi/ttsengobj.cpp diff --git a/windows/windows_sapi/ttsengobj.h b/platforms/windows/windows_sapi/ttsengobj.h similarity index 100% rename from windows/windows_sapi/ttsengobj.h rename to platforms/windows/windows_sapi/ttsengobj.h diff --git a/windows/windows_sapi/ttsengobj.rgs b/platforms/windows/windows_sapi/ttsengobj.rgs similarity index 100% rename from windows/windows_sapi/ttsengobj.rgs rename to platforms/windows/windows_sapi/ttsengobj.rgs diff --git a/windows/windows_sapi/ttsengver.h b/platforms/windows/windows_sapi/ttsengver.h similarity index 100% rename from windows/windows_sapi/ttsengver.h rename to platforms/windows/windows_sapi/ttsengver.h diff --git a/windows/windows_sapi/version.rc2 b/platforms/windows/windows_sapi/version.rc2 similarity index 100% rename from windows/windows_sapi/version.rc2 rename to platforms/windows/windows_sapi/version.rc2