Moved the Windows build files together with DOS and others into a new directory: "platforms". git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@76 d46cf337-b52f-0410-862d-fd96e6ae7743master
| 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 |
| 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 | |||||
| <[email protected]> |
| #include <stdio.h> | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include <sys/types.h> | |||||
| #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); | |||||
| } |
| 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) | |||||
| /*************************************************************************** | |||||
| * Copyright (C) 2005 to 2007 by Jonathan Duddington * | |||||
| * email: [email protected] * | |||||
| * * | |||||
| * 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: * | |||||
| * <http://www.gnu.org/licenses/>. * | |||||
| ***************************************************************************/ | |||||
| #include <sys/types.h> | |||||
| // 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); | |||||
| 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. |
| 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 <eSpeak$Dir> system variable, and then runs | |||||
| the "speakmod" file to load the Speak module. | |||||
| Note, <eSpeak$Dir> 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 <eSpeak$dir> 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 <obey$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. | |||||
| # 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: |
| 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. |
| copy <obey$dir>.^.src.compiledict/cpp <obey$dir>.cpp.compiledict fq~c | |||||
| copy <obey$dir>.^.src.dictionary/cpp <obey$dir>.cpp.dictionary fq~c | |||||
| copy <obey$dir>.^.src.intonation/cpp <obey$dir>.cpp.intonation fq~c | |||||
| copy <obey$dir>.^.src.numbers/cpp <obey$dir>.cpp.numbers fq~c | |||||
| copy <obey$dir>.^.src.phonemelist/cpp <obey$dir>.cpp.phonemelist fq~c | |||||
| copy <obey$dir>.^.src.readclause/cpp <obey$dir>.cpp.readclause fq~c | |||||
| copy <obey$dir>.^.src.setlengths/cpp <obey$dir>.cpp.setlengths fq~c | |||||
| copy <obey$dir>.^.src.synthdata/cpp <obey$dir>.cpp.synthdata fq~c | |||||
| copy <obey$dir>.^.src.synth_mbrola/cpp <obey$dir>.cpp.synth_mbrola fq~c | |||||
| copy <obey$dir>.^.src.synthesize/cpp <obey$dir>.cpp.synthesize fq~c | |||||
| copy <obey$dir>.^.src.translate/cpp <obey$dir>.cpp.translate fq~c | |||||
| copy <obey$dir>.^.src.tr_english/cpp <obey$dir>.cpp.tr_english fq~c | |||||
| copy <obey$dir>.^.src.tr_languages/cpp <obey$dir>.cpp.tr_languages fq~c | |||||
| copy <obey$dir>.^.src.voices/cpp <obey$dir>.cpp.voices fq~c | |||||
| copy <obey$dir>.^.src.wavegen/cpp <obey$dir>.cpp.wavegen fq~c | |||||
| copy <obey$dir>.^.src.phoneme/h <obey$dir>.h.phoneme fq~c | |||||
| copy <obey$dir>.^.src.sintab/h <obey$dir>.h.sintab fq~c | |||||
| copy <obey$dir>.^.src.speak_lib/h <obey$dir>.h.speak_lib fq~c | |||||
| copy <obey$dir>.^.src.synthesize/h <obey$dir>.h.synthesize fq~c | |||||
| copy <obey$dir>.^.src.translate/h <obey$dir>.h.translate fq~c | |||||
| copy <obey$dir>.^.src.tr_languages/h <obey$dir>.h.tr_languages fq~c | |||||
| copy <obey$dir>.^.src.voice/h <obey$dir>.h.voice fq~c | |||||
| copy <obey$dir>.^.src.wave/h <obey$dir>.h.wave fq~c |
| ; h.RegNames | |||||
| ; | |||||
| ; This header file for GETting from assembler source defines register names | |||||
| ; | |||||
| ;************************************************************************** | |||||
| ; | |||||
| ; Use the RN directive to define ARM register names | |||||
| ; | |||||
| r0 RN 0 | |||||
| r1 RN 1 | |||||
| r2 RN 2 | |||||
| r3 RN 3 | |||||
| r4 RN 4 | |||||
| r5 RN 5 | |||||
| r6 RN 6 | |||||
| r7 RN 7 | |||||
| r8 RN 8 | |||||
| r9 RN 9 | |||||
| r10 RN 10 | |||||
| sl RN 10 | |||||
| r11 RN 11 | |||||
| fp RN 11 | |||||
| r12 RN 12 | |||||
| ip RN 12 | |||||
| r13 RN 13 | |||||
| sp RN 13 | |||||
| r14 RN 14 | |||||
| lr RN r14 ; Note: register names can be defined from each other | |||||
| r15 RN 15 | |||||
| pc RN r15 | |||||
| ; Use the FN directive to define floating point register names | |||||
| f0 FN 0 | |||||
| f1 FN 1 | |||||
| f2 FN 2 | |||||
| f3 FN 3 | |||||
| f4 FN 4 | |||||
| f5 FN 5 | |||||
| f6 FN 6 | |||||
| f7 FN 7 | |||||
| END | |||||
| /*************************************************************************** | |||||
| * Copyright (C) 2005,2006 by Jonathan Duddington * | |||||
| * [email protected] * | |||||
| * * | |||||
| * 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. * | |||||
| ***************************************************************************/ | |||||
| // Header file for RISCOS build | |||||
| #define N_PEAKS 9 | |||||
| #define N_MARKERS 7 | |||||
| // comment this out when compiling the "speak" process | |||||
| //#define SPECT_EDITOR | |||||
| #define PATHSEP '.' | |||||
| #define USE_ASSEMBLER_1 | |||||
| #define PLATFORM_RISCOS | |||||
| #define NEED_WCHAR_FUNCTIONS | |||||
| #define __cdecl // define as null, needed for Borland compiler | |||||
| #define ESPEAK_API | |||||
| typedef unsigned short USHORT; | |||||
| typedef unsigned char UCHAR; | |||||
| typedef int DOUBLEX; | |||||
| typedef struct { | |||||
| const char *mnem; | |||||
| int value; | |||||
| } MNEM_TAB; | |||||
| int LookupMnem(MNEM_TAB *table, char *string); | |||||
| typedef struct { | |||||
| short pkfreq; | |||||
| short pkheight; | |||||
| short pkwidth; | |||||
| short pkright; | |||||
| } peak_t; | |||||
| typedef struct { | |||||
| short frflags; | |||||
| unsigned char length; | |||||
| unsigned char rms; | |||||
| short ffreq[9]; | |||||
| unsigned char fheight[9]; | |||||
| unsigned char fwidth[6]; // width/4 | |||||
| unsigned char fright[6]; // width/4 | |||||
| } frame_t; | |||||
| extern int GetFileLength(const char *filename); | |||||
| extern char *Alloc(int size); | |||||
| extern void Free(void *ptr); | |||||
| extern void strncpy0(char *to,const char *from, int size); | |||||
| extern char path_home[]; | |||||
| extern const char *version_string; | |||||
| extern const int version_phdata; | |||||
| const int wcslen(const wchar_t *str); | |||||
| extern "C" { | |||||
| // optional assembler routine to speed-up Wavegen() | |||||
| int AddSineWaves(int waveph, int h_switch_sign, int maxh, int *harmspect); | |||||
| } | |||||
| #define strcasecmp(a,b) strcmp(a,b) | |||||
| const wchar_t *wcschr(const wchar_t *str, int c); | |||||
| typedef int wchar_t; | |||||
| 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); | |||||
| ; 32 bit version | |||||
| ; SWI numbers | |||||
| OS_File * &8 | |||||
| OS_Module * &1e | |||||
| XOS_AddCallBack * &20054 | |||||
| XOS_RemoveCallBack * &2005f | |||||
| GET h.RegNames | |||||
| EXPORT DMA_Handler | |||||
| EXPORT AddSineWaves | |||||
| IMPORT |callback_entry| | |||||
| IMPORT |sound_entry| | |||||
| IMPORT |sin_tab| | |||||
| AREA Assemb , CODE, READONLY | |||||
| ; pointers to data items | |||||
| ADR_callback_entry | |||||
| DCD callback_entry | |||||
| ADR_sound_entry | |||||
| DCD sound_entry | |||||
| ADR_sin_tab | |||||
| DCD sin_tab | |||||
| DMA_Handler | |||||
| ;********** | |||||
| ; fill the sound buffer of the linear sound handler | |||||
| ; preserve r11,r12,r13 (fp,ip,sp) | |||||
| MOV r5,ip ; need to save ip | |||||
| MOV ip,sp ;set up a stack | |||||
| STMFD sp!, {fp,ip,lr} | |||||
| STMFD sp!, {r5} | |||||
| MOV r12,r0 ; put the module_data word in r12 | |||||
| BL sound_entry ; call C function through veneer in CMHG | |||||
| ; returns with r0=1 set callback, r1=module_data address | |||||
| CMP r0,#1 | |||||
| BNE DMA_return | |||||
| ;--------- | |||||
| TEQ pc,pc | |||||
| MRSEQ r8, CPSR ; 32bit version of call SWI from IRQ mode | |||||
| MOVNE r8,pc | |||||
| ORR r9,r8,#3 | |||||
| MSREQ CPSR_c, r9 | |||||
| TEQNEP r9,#0 | |||||
| NOP | |||||
| STR r14, [r13,#-4]! | |||||
| ;--------- | |||||
| ; r1=module_data address | |||||
| LDR r0,ADR_callback_entry ; call C function through CMHG veneer | |||||
| SWI XOS_AddCallBack | |||||
| ;--------- | |||||
| LDR r14, [r13],#4 ; 32bit version of 'reenter original processor mode' | |||||
| TEQ pc,pc | |||||
| MSREQ CPSR_c, r8 | |||||
| TEQNEP r8,#0 | |||||
| NOP | |||||
| ;--------- | |||||
| DMA_return | |||||
| LDMFD sp!,{ip} | |||||
| LDMFD sp, {fp,sp,pc} | |||||
| AddSineWaves | |||||
| ;total += AddSineWaves(waveph, h_switch_sign, maxh, harmspect); | |||||
| ; using this assembler routine increases overall speed by about 7.5% | |||||
| ; define the USE_ASSEMBLER_1 macro in speech.h to enable this routine | |||||
| ; input: r0=waveph r1=h_switch_sign r2=maxh r3=harmspect | |||||
| ; local: r5=sin_tab r6=total r7=h r8=theta | |||||
| ; return(total) | |||||
| MOV ip,sp | |||||
| STMFD sp!, {r5-r9,ip,lr} | |||||
| LDR r5,ADR_sin_tab | |||||
| MOV r6,#0 ; total = 0 | |||||
| MOV r0,r0,LSL #16 | |||||
| MOV r8,r0 ; theta = waveph | |||||
| MOV r7,#1 | |||||
| as1 | |||||
| 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,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 |
| 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 <string>\n"), | |||||
| SAYW(min-args: 1, max-args: 255, | |||||
| help-text: "Says English string <string>\n"), | |||||
| SPEAK(min-args: 1, max-args: 255, | |||||
| help-text: "Says English string <string>\n") |
| Copy the source files from the Linux "src" directory into this | Copy the source files from the Linux "src" directory into this | ||||
| "src" directory, EXCEPT for speech.h. Keep the original Windows | "src" directory, EXCEPT for speech.h. Keep the original Windows | ||||
| command-line version iof speech.h. | |||||
| command-line version of speech.h. | |||||
| // This is a dummy file. | |||||
| // A file of this name is needed on Windows | |||||