eSpeak NG is an open source speech synthesizer that supports more than hundred languages and accents.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

espeak-phoneme-data.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // 13.02.10 jonsd: Changed for eSpeak version 1.43
  2. // 13.08.10 jonsd: Added Q lines. Use Address to set the displacement in phondata file.
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
  9. #define IS_BIG_ENDIAN 1
  10. #else
  11. #define IS_BIG_ENDIAN 0
  12. #endif
  13. #if IS_BIG_ENDIAN
  14. # define SWAP_USHORT(val) ((unsigned short) ( \
  15. (unsigned short) ((unsigned short) (val) >> 8) | \
  16. (unsigned short) ((unsigned short) (val) << 8)))
  17. # define SWAP_UINT(val) ((unsigned int) ( \
  18. (((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \
  19. (((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \
  20. (((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \
  21. (((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24)))
  22. #else
  23. # define SWAP_USHORT(val) (val)
  24. # define SWAP_UINT(val) (val)
  25. #endif
  26. #define N_PHONEME_TAB_NAME 32
  27. // This is a new format for eSpeak 1.43
  28. typedef struct {
  29. unsigned int mnemonic; // 1st char is in the l.s.byte
  30. unsigned int phflags; // bits 16-19 place of articulation
  31. unsigned short program;
  32. unsigned char code; // the phoneme number
  33. unsigned char type; // phVOWEL, phPAUSE, phSTOP etc
  34. unsigned char start_type;
  35. unsigned char end_type;
  36. unsigned char std_length; // for vowels, in mS/2; for phSTRESS, the stress/tone type
  37. unsigned char length_mod; // a length_mod group number, used to access length_mod_tab
  38. } PHONEME_TAB;
  39. // This is a new format for eSpeak 1.41
  40. typedef struct { // 44 bytes
  41. short frflags;
  42. short ffreq[7];
  43. unsigned char length;
  44. unsigned char rms;
  45. unsigned char fheight[8];
  46. unsigned char fwidth[6]; // width/4 f0-5
  47. unsigned char fright[3]; // width/4 f0-2
  48. unsigned char bw[4]; // Klatt bandwidth BNZ /2, f1,f2,f3
  49. unsigned char klattp[5]; // AV, FNZ, Tilt, Aspr, Skew
  50. unsigned char klattp2[5]; // continuation of klattp[], Avp, Fric, FricBP, Turb
  51. unsigned char klatt_ap[7]; // Klatt parallel amplitude
  52. unsigned char klatt_bp[7]; // Klatt parallel bandwidth /2
  53. } frame_t; // with extra Klatt parameters for parallel resonators
  54. #ifdef deleted
  55. // This is the previous format for versions before 1.41
  56. typedef struct {
  57. short frflags;
  58. unsigned char length;
  59. unsigned char rms;
  60. short ffreq[9];
  61. unsigned char fheight[9];
  62. unsigned char fwidth[6];
  63. unsigned char fright[6];
  64. } frame_t;
  65. #endif
  66. #define N_SEQ_FRAMES 25
  67. typedef struct {
  68. short length;
  69. unsigned char n_frames;
  70. unsigned char flags;
  71. frame_t frame[N_SEQ_FRAMES];
  72. } SPECT_SEQ;
  73. void swap_phondata (const char *infile, const char *outfile,
  74. const char *manifest);
  75. void swap_phonindex (const char *infile, const char *outfile);
  76. void swap_phontab (const char *infile, const char *outfile);
  77. void usage (const char *program_name);
  78. int xread; // prevent compiler warning from fread()
  79. int main (int argc, char *argv[])
  80. {//==============================
  81. const char *indir = "/usr/share/espeak-data";
  82. const char *outdir = ".";
  83. const char *manifest = "phondata-manifest";
  84. char *f1, *f2;
  85. if (argc > 4)
  86. usage (argv[0]);
  87. if (argc > 1) {
  88. if (strcmp (argv[1], "-h") == 0 ||
  89. strcmp (argv[1], "--help") == 0)
  90. usage (argv[0]);
  91. indir = argv[1];
  92. }
  93. if (argc > 2)
  94. outdir = argv[2];
  95. if (argc > 3)
  96. manifest = argv[3];
  97. f1 = (char *) malloc (strlen (indir) + 20);
  98. if (f1 == NULL) {
  99. fprintf (stderr, "Unable to allocate memory\n");
  100. exit (1);
  101. }
  102. f2 = (char *) malloc (strlen (outdir) + 20);
  103. if (f2 == NULL) {
  104. fprintf (stderr, "Unable to allocate memory\n");
  105. exit (1);
  106. }
  107. #if IS_BIG_ENDIAN
  108. printf ("Host seems to be big-endian ..\n");
  109. #else
  110. printf ("Host seems to be little-endian ..\n");
  111. #endif
  112. sprintf (f1, "%s/phontab", indir);
  113. sprintf (f2, "%s/temp_1", outdir);
  114. printf ("Processing phontab ..\n");
  115. swap_phontab (f1, f2);
  116. sprintf (f1, "%s/phontab", outdir);
  117. rename (f2, f1);
  118. sprintf (f1, "%s/phonindex", indir);
  119. sprintf (f2, "%s/temp_1", outdir);
  120. printf ("Processing phonindex ..\n");
  121. swap_phonindex (f1, f2);
  122. sprintf (f1, "%s/phonindex", outdir);
  123. rename (f2, f1);
  124. sprintf (f1, "%s/phondata", indir);
  125. sprintf (f2, "%s/temp_1", outdir);
  126. printf ("Processing phondata ..\n");
  127. swap_phondata (f1, f2, manifest);
  128. sprintf (f1, "%s/phondata", outdir);
  129. rename (f2, f1);
  130. free (f1);
  131. free (f2);
  132. printf ("Done.\n");
  133. return 0;
  134. } // end of main
  135. void swap_phondata (const char *infile, const char *outfile,
  136. const char *manifest)
  137. {//==========================================================
  138. FILE *in, *mfest, *out;
  139. int displ;
  140. char line[1024];
  141. unsigned char buf_4[4];
  142. in = fopen (infile, "rb");
  143. if (in == NULL) {
  144. fprintf (stderr, "Unable to read from file %s\n", infile);
  145. exit (1);
  146. }
  147. mfest = fopen (manifest, "rb");
  148. if (mfest == NULL) {
  149. fprintf (stderr, "Unable to read from file %s\n", manifest);
  150. exit (1);
  151. }
  152. out = fopen (outfile, "wb");
  153. if (out == NULL) {
  154. fprintf (stderr, "Unable to open file %s for writing\n", outfile);
  155. exit (1);
  156. }
  157. xread = fread(buf_4, 4, 1, in);
  158. fwrite(buf_4, 4, 1, out);
  159. while (fgets (line, sizeof(line), mfest))
  160. {
  161. if(!isupper(line[0])) continue;
  162. sscanf(&line[2],"%x",&displ);
  163. fseek(in, displ, SEEK_SET);
  164. if (line[0] == 'S') {
  165. SPECT_SEQ buf_spect;
  166. size_t ix;
  167. int n;
  168. xread = fread (&buf_spect.length, 2, 1, in);
  169. xread = fread (&buf_spect.n_frames, 1, 1, in);
  170. fseek (in, -3, SEEK_CUR);
  171. ix = (char *)(&buf_spect.frame[buf_spect.n_frames]) -
  172. (char *)(&buf_spect);
  173. ix = (ix+3) & 0xfffc;
  174. xread = fread (&buf_spect, ix, 1, in);
  175. buf_spect.length = (short) SWAP_USHORT (buf_spect.length);
  176. for (n = 0; n < buf_spect.n_frames; n++) {
  177. int k;
  178. buf_spect.frame[n].frflags = (short)
  179. SWAP_USHORT (buf_spect.frame[n].frflags);
  180. // Changed for eSpeak 1.41
  181. for (k = 0; k < 7; k++) {
  182. buf_spect.frame[n].ffreq[k] = (short)
  183. SWAP_USHORT (buf_spect.frame[n].ffreq[k]);
  184. }
  185. }
  186. fwrite (&buf_spect, ix, 1, out);
  187. }
  188. else if (line[0] == 'W') {
  189. long pos;
  190. int length;
  191. char *wave_data;
  192. xread = fread (buf_4, 4, 1, in);
  193. fwrite (buf_4, 4, 1, out);
  194. length = buf_4[1] * 256 + buf_4[0];
  195. wave_data = (char *) malloc (length);
  196. if (wave_data == NULL) {
  197. fprintf (stderr, "Memory allocation error\n");
  198. exit (1);
  199. }
  200. xread = fread (wave_data, 1, length, in);
  201. fwrite (wave_data, 1, length, out);
  202. pos = ftell (in);
  203. while((pos & 3) != 0) {
  204. fgetc (in);
  205. pos++;
  206. }
  207. pos = ftell (out);
  208. while((pos & 3) != 0) {
  209. fputc (0, out);
  210. pos++;
  211. }
  212. free (wave_data);
  213. }
  214. else if (line[0] == 'E') {
  215. char env_buf[128];
  216. xread = fread (env_buf, 1, 128, in);
  217. fwrite (env_buf, 1, 128, out);
  218. }
  219. }
  220. fclose (in);
  221. fclose (out);
  222. fclose (mfest);
  223. } // end of swap_phondata
  224. void swap_phonindex (const char *infile, const char *outfile)
  225. {//==========================================================
  226. FILE *in, *out;
  227. char buf_4[4];
  228. unsigned short val;
  229. in = fopen (infile, "rb");
  230. if (in == NULL) {
  231. fprintf (stderr, "Unable to read from file %s\n", infile);
  232. exit (1);
  233. }
  234. out = fopen (outfile, "wb");
  235. if (out == NULL) {
  236. fprintf (stderr, "Unable to open file %s for writing\n", outfile);
  237. exit (1);
  238. }
  239. xread = fread (buf_4, 4, 1, in); // skip first 4 bytes
  240. fwrite(buf_4, 4, 1, out);
  241. while (! feof (in)) {
  242. size_t n;
  243. n = fread (&val, 2, 1, in);
  244. if (n != 1)
  245. break;
  246. val = SWAP_USHORT (val);
  247. fwrite (&val, 2, 1, out);
  248. }
  249. fclose (in);
  250. fclose (out);
  251. } // end of swap_phonindex
  252. void swap_phontab (const char *infile, const char *outfile)
  253. {//========================================================
  254. FILE *in, *out;
  255. char buf_8[8];
  256. int i, n_phoneme_tables;
  257. in = fopen (infile, "rb");
  258. if (in == NULL) {
  259. fprintf (stderr, "Unable to read from file %s\n", infile);
  260. exit (1);
  261. }
  262. out = fopen (outfile, "wb");
  263. if (out == NULL) {
  264. fprintf (stderr, "Unable to open file %s for writing\n", outfile);
  265. exit (1);
  266. }
  267. xread = fread (buf_8, 4, 1, in);
  268. fwrite (buf_8, 4, 1, out);
  269. n_phoneme_tables = buf_8[0];
  270. for (i = 0; i < n_phoneme_tables; i++) {
  271. int n_phonemes, j;
  272. char tab_name[N_PHONEME_TAB_NAME];
  273. xread = fread (buf_8, 8, 1, in);
  274. fwrite (buf_8, 8, 1, out);
  275. n_phonemes = buf_8[0];
  276. xread = fread (tab_name, N_PHONEME_TAB_NAME, 1, in);
  277. fwrite (tab_name, N_PHONEME_TAB_NAME, 1, out);
  278. for (j = 0; j < n_phonemes; j++) {
  279. PHONEME_TAB table;
  280. xread = fread (&table, sizeof (PHONEME_TAB), 1, in);
  281. table.mnemonic = SWAP_UINT (table.mnemonic);
  282. table.phflags = SWAP_UINT (table.phflags);
  283. table.program = SWAP_USHORT (table.program);
  284. fwrite (&table, sizeof (PHONEME_TAB), 1, out);
  285. }
  286. }
  287. fclose (in);
  288. fclose (out);
  289. } // end of swap_phontab
  290. void
  291. usage (const char *program_name)
  292. {
  293. fprintf (stderr,
  294. "This program copies the phontab, phonindex and phondata files from a given\n"
  295. "directory, swapping values to big-endian form if necessary.\n\n"
  296. "Usage:\n"
  297. " %s [INPUT_DIR] [OUTPUT_DIR] [MANIFEST_FILE]\n\n"
  298. "By default, the MANIFEST_FILE used is a file called 'phondata-manifest' in\n"
  299. "the current directory. The default INPUT_DIR is /usr/share/espeak-data and\n"
  300. "OUTPUT_DIR is the current directory.\n", program_name);
  301. exit (1);
  302. }