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 9.4KB

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