synthdata.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. /*
  2. * Copyright (C) 2005 to 2014 by Jonathan Duddington
  3. * email: jonsd@users.sourceforge.net
  4. * Copyright (C) 2015-2017 Reece H. Dunn
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, see: <http://www.gnu.org/licenses/>.
  18. */
  19. #include "config.h"
  20. #include <ctype.h>
  21. #include <errno.h>
  22. #include <stdbool.h>
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "espeak_ng.h"
  28. #include "encoding.h"
  29. #include "error.h"
  30. #include "speech.h"
  31. #include "synthesize.h"
  32. #include "translate.h"
  33. const char *version_string = PACKAGE_VERSION;
  34. const int version_phdata = 0x014801;
  35. // copy the current phoneme table into here
  36. int n_phoneme_tab;
  37. int current_phoneme_table;
  38. PHONEME_TAB *phoneme_tab[N_PHONEME_TAB];
  39. unsigned char phoneme_tab_flags[N_PHONEME_TAB]; // bit 0: not inherited
  40. USHORT *phoneme_index = NULL;
  41. char *phondata_ptr = NULL;
  42. unsigned char *wavefile_data = NULL;
  43. static unsigned char *phoneme_tab_data = NULL;
  44. int n_phoneme_tables;
  45. PHONEME_TAB_LIST phoneme_tab_list[N_PHONEME_TABS];
  46. int phoneme_tab_number = 0;
  47. int wavefile_ix; // a wavefile to play along with the synthesis
  48. int wavefile_amp;
  49. int wavefile_ix2;
  50. int wavefile_amp2;
  51. int seq_len_adjust;
  52. int vowel_transition[4];
  53. int vowel_transition0;
  54. int vowel_transition1;
  55. int FormantTransition2(frameref_t *seq, int *n_frames, unsigned int data1, unsigned int data2, PHONEME_TAB *other_ph, int which);
  56. static espeak_ng_STATUS ReadPhFile(void **ptr, const char *fname, int *size, espeak_ng_ERROR_CONTEXT *context)
  57. {
  58. if (!ptr) return static_cast<espeak_ng_STATUS> (EINVAL);
  59. FILE *f_in;
  60. int length;
  61. char buf[sizeof(path_home)+40];
  62. sprintf(buf, "%s%c%s", path_home, PATHSEP, fname);
  63. length = GetFileLength(buf);
  64. if (length < 0) // length == -errno
  65. return create_file_error_context(context, static_cast<espeak_ng_STATUS> (-length), buf);
  66. if ((f_in = fopen(buf, "rb")) == NULL)
  67. return create_file_error_context(context, static_cast<espeak_ng_STATUS> (errno), buf);
  68. if (*ptr != NULL)
  69. free(*ptr);
  70. if ((*ptr = malloc(length)) == NULL) {
  71. fclose(f_in);
  72. return static_cast<espeak_ng_STATUS> (ENOMEM);
  73. }
  74. if (fread(*ptr, 1, length, f_in) != length) {
  75. int error = errno;
  76. fclose(f_in);
  77. free(*ptr);
  78. return create_file_error_context(context, static_cast<espeak_ng_STATUS> (error), buf);
  79. }
  80. fclose(f_in);
  81. if (size != NULL)
  82. *size = length;
  83. return ENS_OK;
  84. }
  85. espeak_ng_STATUS LoadPhData(int *srate, espeak_ng_ERROR_CONTEXT *context)
  86. {
  87. int ix;
  88. int n_phonemes;
  89. int version;
  90. int length = 0;
  91. int rate;
  92. unsigned char *p;
  93. espeak_ng_STATUS status;
  94. if ((status = ReadPhFile((void **)&phoneme_tab_data, "phontab", NULL, context)) != ENS_OK)
  95. return status;
  96. if ((status = ReadPhFile((void **)&phoneme_index, "phonindex", NULL, context)) != ENS_OK)
  97. return status;
  98. if ((status = ReadPhFile((void **)&phondata_ptr, "phondata", NULL, context)) != ENS_OK)
  99. return status;
  100. if ((status = ReadPhFile((void **)&tunes, "intonations", &length, context)) != ENS_OK)
  101. return status;
  102. wavefile_data = (unsigned char *)phondata_ptr;
  103. n_tunes = length / sizeof(TUNE);
  104. // read the version number and sample rate from the first 8 bytes of phondata
  105. version = get_int32_le ((char *) wavefile_data); // bytes 0-3, version number
  106. rate = get_int32_le ((char *) (wavefile_data + 4)); // bytes 4-7, sample rate
  107. if (version != version_phdata)
  108. return create_version_mismatch_error_context(context, path_home, version, version_phdata);
  109. // set up phoneme tables
  110. p = phoneme_tab_data;
  111. n_phoneme_tables = p[0];
  112. p += 4;
  113. for (ix = 0; ix < n_phoneme_tables; ix++) {
  114. n_phonemes = p[0];
  115. phoneme_tab_list[ix].n_phonemes = p[0];
  116. phoneme_tab_list[ix].includes = p[1];
  117. p += 4;
  118. memcpy(phoneme_tab_list[ix].name, p, N_PHONEME_TAB_NAME);
  119. p += N_PHONEME_TAB_NAME;
  120. phoneme_tab_list[ix].phoneme_tab_ptr = (PHONEME_TAB *)p;
  121. p += (n_phonemes * sizeof(PHONEME_TAB));
  122. }
  123. if (phoneme_tab_number >= n_phoneme_tables)
  124. phoneme_tab_number = 0;
  125. if (srate != NULL)
  126. *srate = rate;
  127. return ENS_OK;
  128. }
  129. void FreePhData(void)
  130. {
  131. free(phoneme_tab_data);
  132. free(phoneme_index);
  133. free(phondata_ptr);
  134. free(tunes);
  135. phoneme_tab_data = NULL;
  136. phoneme_index = NULL;
  137. phondata_ptr = NULL;
  138. tunes = NULL;
  139. }
  140. int PhonemeCode(unsigned int mnem)
  141. {
  142. int ix;
  143. for (ix = 0; ix < n_phoneme_tab; ix++) {
  144. if (phoneme_tab[ix] == NULL)
  145. continue;
  146. if (phoneme_tab[ix]->mnemonic == mnem)
  147. return phoneme_tab[ix]->code;
  148. }
  149. return 0;
  150. }
  151. int LookupPhonemeString(const char *string)
  152. {
  153. int ix;
  154. unsigned char c;
  155. unsigned int mnem;
  156. // Pack up to 4 characters into a word
  157. mnem = 0;
  158. for (ix = 0; ix < 4; ix++) {
  159. if (string[ix] == 0) break;
  160. c = string[ix];
  161. mnem |= (c << (ix*8));
  162. }
  163. return PhonemeCode(mnem);
  164. }
  165. frameref_t *LookupSpect(PHONEME_TAB *this_ph, int which, FMT_PARAMS *fmt_params, int *n_frames, PHONEME_LIST *plist)
  166. {
  167. int ix;
  168. int nf;
  169. int nf1;
  170. int seq_break;
  171. frameref_t *frames;
  172. int length1;
  173. int length_std;
  174. int length_factor;
  175. SPECT_SEQ *seq, *seq2;
  176. SPECT_SEQK *seqk, *seqk2;
  177. frame_t *frame;
  178. static frameref_t frames_buf[N_SEQ_FRAMES];
  179. seq = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt_addr]);
  180. seqk = (SPECT_SEQK *)seq;
  181. nf = seq->n_frames;
  182. if (nf >= N_SEQ_FRAMES)
  183. nf = N_SEQ_FRAMES - 1;
  184. seq_len_adjust = fmt_params->fmt2_lenadj + fmt_params->fmt_length;
  185. seq_break = 0;
  186. for (ix = 0; ix < nf; ix++) {
  187. if (seq->frame[0].frflags & FRFLAG_KLATT)
  188. frame = &seqk->frame[ix];
  189. else
  190. frame = (frame_t *)&seq->frame[ix];
  191. frames_buf[ix].frame = frame;
  192. frames_buf[ix].frflags = frame->frflags;
  193. frames_buf[ix].length = frame->length;
  194. if (frame->frflags & FRFLAG_VOWEL_CENTRE)
  195. seq_break = ix;
  196. }
  197. frames = &frames_buf[0];
  198. if (seq_break > 0) {
  199. if (which == 1)
  200. nf = seq_break + 1;
  201. else {
  202. frames = &frames_buf[seq_break]; // body of vowel, skip past initial frames
  203. nf -= seq_break;
  204. }
  205. }
  206. // do we need to modify a frame for blending with a consonant?
  207. if ((this_ph->type == phVOWEL) && (fmt_params->fmt2_addr == 0) && (fmt_params->use_vowelin))
  208. seq_len_adjust += FormantTransition2(frames, &nf, fmt_params->transition0, fmt_params->transition1, NULL, which);
  209. length1 = 0;
  210. nf1 = nf - 1;
  211. for (ix = 0; ix < nf1; ix++)
  212. length1 += frames[ix].length;
  213. if (fmt_params->fmt2_addr != 0) {
  214. // a secondary reference has been returned, which is not a wavefile
  215. // add these spectra to the main sequence
  216. seq2 = (SPECT_SEQ *)(&phondata_ptr[fmt_params->fmt2_addr]);
  217. seqk2 = (SPECT_SEQK *)seq2;
  218. // first frame of the addition just sets the length of the last frame of the main seq
  219. nf--;
  220. for (ix = 0; ix < seq2->n_frames; ix++) {
  221. if (seq2->frame[0].frflags & FRFLAG_KLATT)
  222. frame = &seqk2->frame[ix];
  223. else
  224. frame = (frame_t *)&seq2->frame[ix];
  225. frames[nf].length = frame->length;
  226. if (ix > 0) {
  227. frames[nf].frame = frame;
  228. frames[nf].frflags = frame->frflags;
  229. }
  230. nf++;
  231. }
  232. wavefile_ix = 0;
  233. }
  234. if (length1 > 0) {
  235. if (which == 2) {
  236. // adjust the length of the main part to match the standard length specified for the vowel
  237. // less the front part of the vowel and any added suffix
  238. length_std = fmt_params->std_length + seq_len_adjust - 45;
  239. if (length_std < 10)
  240. length_std = 10;
  241. if (plist->synthflags & SFLAG_LENGTHEN)
  242. length_std += (phoneme_tab[phonLENGTHEN]->std_length * 2); // phoneme was followed by an extra : symbol
  243. // can adjust vowel length for stressed syllables here
  244. length_factor = (length_std * 256)/ length1;
  245. for (ix = 0; ix < nf1; ix++)
  246. frames[ix].length = (frames[ix].length * length_factor)/256;
  247. } else {
  248. if (which == 1) {
  249. // front of a vowel
  250. if (fmt_params->fmt_control == 1) {
  251. // This is the default start of a vowel.
  252. // Allow very short vowels to have shorter front parts
  253. if (fmt_params->std_length < 130)
  254. frames[0].length = (frames[0].length * fmt_params->std_length)/130;
  255. }
  256. } else {
  257. // not a vowel
  258. if (fmt_params->std_length > 0)
  259. seq_len_adjust += (fmt_params->std_length - length1);
  260. }
  261. if (seq_len_adjust != 0) {
  262. length_factor = ((length1 + seq_len_adjust) * 256)/length1;
  263. for (ix = 0; ix < nf1; ix++)
  264. frames[ix].length = (frames[ix].length * length_factor)/256;
  265. }
  266. }
  267. }
  268. *n_frames = nf;
  269. return frames;
  270. }
  271. unsigned char *GetEnvelope(int index)
  272. {
  273. if (index == 0) {
  274. fprintf(stderr, "espeak: No envelope\n");
  275. return envelope_data[0]; // not found, use a default envelope
  276. }
  277. return (unsigned char *)&phondata_ptr[index];
  278. }
  279. static void SetUpPhonemeTable(int number, bool recursing)
  280. {
  281. int ix;
  282. int includes;
  283. int ph_code;
  284. PHONEME_TAB *phtab;
  285. if (recursing == false)
  286. memset(phoneme_tab_flags, 0, sizeof(phoneme_tab_flags));
  287. if ((includes = phoneme_tab_list[number].includes) > 0) {
  288. // recursively include base phoneme tables
  289. SetUpPhonemeTable(includes-1, true);
  290. }
  291. // now add the phonemes from this table
  292. phtab = phoneme_tab_list[number].phoneme_tab_ptr;
  293. for (ix = 0; ix < phoneme_tab_list[number].n_phonemes; ix++) {
  294. ph_code = phtab[ix].code;
  295. phoneme_tab[ph_code] = &phtab[ix];
  296. if (ph_code > n_phoneme_tab)
  297. n_phoneme_tab = ph_code;
  298. if (recursing == 0)
  299. phoneme_tab_flags[ph_code] |= 1; // not inherited
  300. }
  301. }
  302. void SelectPhonemeTable(int number)
  303. {
  304. n_phoneme_tab = 0;
  305. SetUpPhonemeTable(number, false); // recursively for included phoneme tables
  306. n_phoneme_tab++;
  307. current_phoneme_table = number;
  308. }
  309. int LookupPhonemeTable(const char *name)
  310. {
  311. int ix;
  312. for (ix = 0; ix < n_phoneme_tables; ix++) {
  313. if (strcmp(name, phoneme_tab_list[ix].name) == 0) {
  314. phoneme_tab_number = ix;
  315. break;
  316. }
  317. }
  318. if (ix == n_phoneme_tables)
  319. return -1;
  320. return ix;
  321. }
  322. int SelectPhonemeTableName(const char *name)
  323. {
  324. // Look up a phoneme set by name, and select it if it exists
  325. // Returns the phoneme table number
  326. int ix;
  327. if ((ix = LookupPhonemeTable(name)) == -1)
  328. return -1;
  329. SelectPhonemeTable(ix);
  330. return ix;
  331. }
  332. void LoadConfig(void)
  333. {
  334. // Load configuration file, if one exists
  335. char buf[sizeof(path_home)+10];
  336. FILE *f;
  337. int ix;
  338. char c1;
  339. char string[200];
  340. for (ix = 0; ix < N_SOUNDICON_SLOTS; ix++) {
  341. soundicon_tab[ix].filename = NULL;
  342. soundicon_tab[ix].data = NULL;
  343. }
  344. sprintf(buf, "%s%c%s", path_home, PATHSEP, "config");
  345. if ((f = fopen(buf, "r")) == NULL)
  346. return;
  347. while (fgets(buf, sizeof(buf), f) != NULL) {
  348. if (buf[0] == '/') continue;
  349. if (memcmp(buf, "tone", 4) == 0)
  350. ReadTonePoints(&buf[5], tone_points);
  351. else if (memcmp(buf, "soundicon", 9) == 0) {
  352. ix = sscanf(&buf[10], "_%c %s", &c1, string);
  353. if (ix == 2) {
  354. soundicon_tab[n_soundicon_tab].name = c1;
  355. soundicon_tab[n_soundicon_tab].filename = strdup(string);
  356. soundicon_tab[n_soundicon_tab++].length = 0;
  357. }
  358. }
  359. }
  360. fclose(f);
  361. }
  362. PHONEME_DATA this_ph_data;
  363. static void InvalidInstn(PHONEME_TAB *ph, int instn)
  364. {
  365. fprintf(stderr, "Invalid instruction %.4x for phoneme '%s'\n", instn, WordToString(ph->mnemonic));
  366. }
  367. static bool StressCondition(Translator *tr, PHONEME_LIST *plist, int condition, int control)
  368. {
  369. int stress_level;
  370. PHONEME_LIST *pl;
  371. static int condition_level[4] = { 1, 2, 4, 15 };
  372. if (phoneme_tab[plist[0].phcode]->type == phVOWEL)
  373. pl = plist;
  374. else {
  375. // consonant, get stress from the following vowel
  376. if (phoneme_tab[plist[1].phcode]->type == phVOWEL)
  377. pl = &plist[1];
  378. else
  379. return false; // no stress elevel for this consonant
  380. }
  381. stress_level = pl->stresslevel & 0xf;
  382. if (tr != NULL) {
  383. if ((control & 1) && (plist->synthflags & SFLAG_DICTIONARY) && ((tr->langopts.param[LOPT_REDUCE] & 1) == 0)) {
  384. // change phoneme. Don't change phonemes which are given for the word in the dictionary.
  385. return false;
  386. }
  387. if ((tr->langopts.param[LOPT_REDUCE] & 0x2) && (stress_level >= pl->wordstress)) {
  388. // treat the most stressed syllable in an unstressed word as stressed
  389. stress_level = STRESS_IS_PRIMARY;
  390. }
  391. }
  392. if (condition == STRESS_IS_PRIMARY)
  393. return stress_level >= pl->wordstress;
  394. if (condition == STRESS_IS_SECONDARY) {
  395. if (stress_level > STRESS_IS_SECONDARY)
  396. return true;
  397. } else {
  398. if (stress_level < condition_level[condition])
  399. return true;
  400. }
  401. return false;
  402. }
  403. static int CountVowelPosition(PHONEME_LIST *plist)
  404. {
  405. int count = 0;
  406. for (;;) {
  407. if (plist->ph->type == phVOWEL)
  408. count++;
  409. if (plist->sourceix != 0)
  410. break;
  411. plist--;
  412. }
  413. return count;
  414. }
  415. static bool InterpretCondition(Translator *tr, int control, PHONEME_LIST *plist, USHORT *p_prog, WORD_PH_DATA *worddata)
  416. {
  417. int which;
  418. int ix;
  419. unsigned int data;
  420. int instn;
  421. int instn2;
  422. int check_endtype = 0;
  423. PHONEME_TAB *ph;
  424. PHONEME_LIST *plist_this;
  425. // instruction: 2xxx, 3xxx
  426. // bits 8-10 = 0 to 5, which phoneme, =6 the 'which' information is in the next instruction.
  427. // bit 11 = 0, bits 0-7 are a phoneme code
  428. // bit 11 = 1, bits 5-7 type of data, bits 0-4 data value
  429. // bits 8-10 = 7, other conditions
  430. instn = (*p_prog) & 0xfff;
  431. data = instn & 0xff;
  432. instn2 = instn >> 8;
  433. if (instn2 < 14) {
  434. plist_this = plist;
  435. which = (instn2) % 7;
  436. if (which == 6) {
  437. // the 'which' code is in the next instruction
  438. p_prog++;
  439. which = (*p_prog);
  440. }
  441. if (which == 4) {
  442. // nextPhW not word boundary
  443. if (plist[1].sourceix)
  444. return false;
  445. }
  446. if (which == 5) {
  447. // prevPhW, not word boundary
  448. if (plist[0].sourceix)
  449. return false;
  450. }
  451. if (which == 6) {
  452. // next2PhW, not word boundary
  453. if (plist[1].sourceix || plist[2].sourceix)
  454. return false;
  455. }
  456. switch (which)
  457. {
  458. case 0: // prevPh
  459. case 5: // prevPhW
  460. plist--;
  461. check_endtype = 1;
  462. break;
  463. case 1: // thisPh
  464. break;
  465. case 2: // nextPh
  466. case 4: // nextPhW
  467. plist++;
  468. break;
  469. case 3: // next2Ph
  470. case 6: // next2PhW
  471. plist += 2;
  472. break;
  473. case 7:
  474. // nextVowel, not word boundary
  475. for (which = 1;; which++) {
  476. if (plist[which].sourceix)
  477. return false;
  478. if (phoneme_tab[plist[which].phcode]->type == phVOWEL) {
  479. plist = &plist[which];
  480. break;
  481. }
  482. }
  483. break;
  484. case 8: // prevVowel in this word
  485. if ((worddata == NULL) || (worddata->prev_vowel.ph == NULL))
  486. return false; // no previous vowel
  487. plist = &(worddata->prev_vowel);
  488. check_endtype = 1;
  489. break;
  490. case 9: // next3PhW
  491. for (ix = 1; ix <= 3; ix++) {
  492. if (plist[ix].sourceix)
  493. return false;
  494. }
  495. plist = &plist[3];
  496. break;
  497. case 10: // prev2PhW
  498. if ((plist[0].sourceix) || (plist[-1].sourceix))
  499. return false;
  500. plist -= 2;
  501. check_endtype = 1;
  502. break;
  503. }
  504. if ((which == 0) || (which == 5)) {
  505. if (plist->phcode == 1) {
  506. // This is a NULL phoneme, a phoneme has been deleted so look at the previous phoneme
  507. plist--;
  508. }
  509. }
  510. if (control & 0x100) {
  511. // "change phonemes" pass
  512. plist->ph = phoneme_tab[plist->phcode];
  513. }
  514. ph = plist->ph;
  515. if (instn2 < 7) {
  516. // 'data' is a phoneme number
  517. if ((phoneme_tab[data]->mnemonic == ph->mnemonic) == true)
  518. return true;
  519. // not an exact match, check for a vowel type (eg. #i )
  520. if ((check_endtype) && (ph->type == phVOWEL))
  521. return data == ph->end_type; // prevPh() match on end_type
  522. return data == ph->start_type; // thisPh() or nextPh(), match on start_type
  523. }
  524. data = instn & 0x1f;
  525. switch (instn & 0xe0)
  526. {
  527. case CONDITION_IS_PHONEME_TYPE:
  528. return ph->type == data;
  529. case CONDITION_IS_PLACE_OF_ARTICULATION:
  530. return ((ph->phflags >> 16) & 0xf) == data;
  531. case CONDITION_IS_PHFLAG_SET:
  532. return (ph->phflags & (1 << data)) != 0;
  533. case CONDITION_IS_OTHER:
  534. switch (data)
  535. {
  536. case STRESS_IS_DIMINISHED:
  537. case STRESS_IS_UNSTRESSED:
  538. case STRESS_IS_NOT_STRESSED:
  539. case STRESS_IS_SECONDARY:
  540. case STRESS_IS_PRIMARY:
  541. return StressCondition(tr, plist, data, 0);
  542. case isBreak:
  543. return (ph->type == phPAUSE) || (plist_this->synthflags & SFLAG_NEXT_PAUSE);
  544. case isWordStart:
  545. return plist->sourceix != 0;
  546. case isWordEnd:
  547. return plist[1].sourceix || (plist[1].ph->type == phPAUSE);
  548. case isAfterStress:
  549. if (plist->sourceix != 0)
  550. return false;
  551. do {
  552. plist--;
  553. if ((plist->stresslevel & 0xf) >= 4)
  554. return true;
  555. } while (plist->sourceix == 0);
  556. break;
  557. case isNotVowel:
  558. return ph->type != phVOWEL;
  559. case isFinalVowel:
  560. for (;;) {
  561. plist++;
  562. if (plist->sourceix != 0)
  563. return true; // start of next word, without finding another vowel
  564. if (plist->ph->type == phVOWEL)
  565. return false;
  566. }
  567. case isVoiced:
  568. return (ph->type == phVOWEL) || (ph->type == phLIQUID) || (ph->phflags & phVOICED);
  569. case isFirstVowel:
  570. return CountVowelPosition(plist) == 1;
  571. case isSecondVowel:
  572. return CountVowelPosition(plist) == 2;
  573. case isTranslationGiven:
  574. return (plist->synthflags & SFLAG_DICTIONARY) != 0;
  575. }
  576. break;
  577. }
  578. return false;
  579. } else if (instn2 == 0xf) {
  580. // Other conditions
  581. switch (data)
  582. {
  583. case 1: // PreVoicing
  584. return control & 1;
  585. case 2: // KlattSynth
  586. return voice->klattv[0] != 0;
  587. case 3: // MbrolaSynth
  588. return mbrola_name[0] != 0;
  589. }
  590. }
  591. return false;
  592. }
  593. static void SwitchOnVowelType(PHONEME_LIST *plist, PHONEME_DATA *phdata, USHORT **p_prog, int instn_type)
  594. {
  595. USHORT *prog;
  596. int voweltype;
  597. signed char x;
  598. if (instn_type == 2) {
  599. phdata->pd_control |= pd_FORNEXTPH;
  600. voweltype = plist[1].ph->start_type; // SwitchNextVowelType
  601. } else
  602. voweltype = plist[-1].ph->end_type; // SwitchPrevVowelType
  603. voweltype -= phonVOWELTYPES;
  604. if ((voweltype >= 0) && (voweltype < 6)) {
  605. prog = *p_prog + voweltype*2;
  606. phdata->sound_addr[instn_type] = (((prog[1] & 0xf) << 16) + prog[2]) * 4;
  607. x = (prog[1] >> 4) & 0xff;
  608. phdata->sound_param[instn_type] = x; // sign extend
  609. }
  610. *p_prog += 12;
  611. }
  612. int NumInstnWords(USHORT *prog)
  613. {
  614. int instn;
  615. int instn2;
  616. int instn_type;
  617. int n;
  618. int type2;
  619. static const char n_words[16] = { 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 4, 0, 0, 0, 0, 0 };
  620. instn = *prog;
  621. instn_type = instn >> 12;
  622. if ((n = n_words[instn_type]) > 0)
  623. return n;
  624. switch (instn_type)
  625. {
  626. case 0:
  627. if (((instn & 0xf00) >> 8) == i_IPA_NAME) {
  628. n = ((instn & 0xff) + 1) / 2;
  629. return n+1;
  630. }
  631. return 1;
  632. case 6:
  633. type2 = (instn & 0xf00) >> 9;
  634. if ((type2 == 5) || (type2 == 6))
  635. return 12; // switch on vowel type
  636. return 1;
  637. case 2:
  638. case 3:
  639. // a condition, check for a 2-word instruction
  640. if (((n = instn & 0x0f00) == 0x600) || (n == 0x0d00))
  641. return 2;
  642. return 1;
  643. default:
  644. // instn_type 11 to 15, 2 words
  645. instn2 = prog[2];
  646. if ((instn2 >> 12) == 0xf) {
  647. // This instruction is followed by addWav(), 2 more words
  648. return 4;
  649. }
  650. if (instn2 == INSTN_CONTINUE)
  651. return 3;
  652. return 2;
  653. }
  654. }
  655. void InterpretPhoneme(Translator *tr, int control, PHONEME_LIST *plist, PHONEME_DATA *phdata, WORD_PH_DATA *worddata)
  656. {
  657. // control:
  658. // bit 0: PreVoicing
  659. // bit 8: change phonemes
  660. PHONEME_TAB *ph;
  661. USHORT *prog;
  662. USHORT instn;
  663. int instn2;
  664. int or_flag;
  665. bool truth;
  666. bool truth2;
  667. int data;
  668. int end_flag;
  669. int ix;
  670. signed char param_sc;
  671. #define N_RETURN 10
  672. int n_return = 0;
  673. USHORT *return_addr[N_RETURN]; // return address stack
  674. ph = plist->ph;
  675. if ((worddata != NULL) && (plist->sourceix)) {
  676. // start of a word, reset word data
  677. worddata->prev_vowel.ph = NULL;
  678. }
  679. memset(phdata, 0, sizeof(PHONEME_DATA));
  680. phdata->pd_param[i_SET_LENGTH] = ph->std_length;
  681. phdata->pd_param[i_LENGTH_MOD] = ph->length_mod;
  682. if (ph->program == 0)
  683. return;
  684. end_flag = 0;
  685. for (prog = &phoneme_index[ph->program]; end_flag != 1; prog++) {
  686. instn = *prog;
  687. instn2 = (instn >> 8) & 0xf;
  688. switch (instn >> 12)
  689. {
  690. case 0: // 0xxx
  691. data = instn & 0xff;
  692. if (instn2 == 0) {
  693. // instructions with no operand
  694. switch (data)
  695. {
  696. case INSTN_RETURN:
  697. end_flag = 1;
  698. break;
  699. case INSTN_CONTINUE:
  700. break;
  701. default:
  702. InvalidInstn(ph, instn);
  703. break;
  704. }
  705. } else if (instn2 == i_APPEND_IFNEXTVOWEL) {
  706. if (phoneme_tab[plist[1].phcode]->type == phVOWEL)
  707. phdata->pd_param[i_APPEND_PHONEME] = data;
  708. } else if (instn2 == i_ADD_LENGTH) {
  709. if (data & 0x80) {
  710. // a negative value, do sign extension
  711. data = -(0x100 - data);
  712. }
  713. phdata->pd_param[i_SET_LENGTH] += data;
  714. } else if (instn2 == i_IPA_NAME) {
  715. // followed by utf-8 characters, 2 per instn word
  716. for (ix = 0; (ix < data) && (ix < 16); ix += 2) {
  717. prog++;
  718. phdata->ipa_string[ix] = prog[0] >> 8;
  719. phdata->ipa_string[ix+1] = prog[0] & 0xff;
  720. }
  721. phdata->ipa_string[ix] = 0;
  722. } else if (instn2 < N_PHONEME_DATA_PARAM) {
  723. phdata->pd_param[instn2] = data;
  724. if ((instn2 == i_CHANGE_PHONEME) && (control & 0x100)) {
  725. // found ChangePhoneme() in PhonemeList mode, exit
  726. end_flag = 1;
  727. }
  728. } else
  729. InvalidInstn(ph, instn);
  730. break;
  731. case 1:
  732. if (tr == NULL)
  733. break; // ignore if in synthesis stage
  734. if (instn2 < 8) {
  735. // ChangeIf
  736. if (StressCondition(tr, plist, instn2 & 7, 1) == true) {
  737. phdata->pd_param[i_CHANGE_PHONEME] = instn & 0xff;
  738. end_flag = 1; // change phoneme, exit
  739. }
  740. }
  741. break;
  742. case 2:
  743. case 3:
  744. // conditions
  745. or_flag = 0;
  746. truth = true;
  747. while ((instn & 0xe000) == 0x2000) {
  748. // process a sequence of conditions, using boolean accumulator
  749. truth2 = InterpretCondition(tr, control, plist, prog, worddata);
  750. prog += NumInstnWords(prog);
  751. if (*prog == i_NOT) {
  752. truth2 = truth2 ^ 1;
  753. prog++;
  754. }
  755. if (or_flag)
  756. truth = truth || truth2;
  757. else
  758. truth = truth && truth2;
  759. or_flag = instn & 0x1000;
  760. instn = *prog;
  761. }
  762. if (truth == false) {
  763. if ((instn & 0xf800) == i_JUMP_FALSE)
  764. prog += instn & 0xff;
  765. else {
  766. // instruction after a condition is not JUMP_FALSE, so skip the instruction.
  767. prog += NumInstnWords(prog);
  768. if ((prog[0] & 0xfe00) == 0x6000)
  769. prog++; // and skip ELSE jump
  770. }
  771. }
  772. prog--;
  773. break;
  774. case 6:
  775. // JUMP
  776. switch (instn2 >> 1)
  777. {
  778. case 0:
  779. prog += (instn & 0xff) - 1;
  780. break;
  781. case 4:
  782. // conditional jumps should have been processed in the Condition section
  783. break;
  784. case 5: // NexttVowelStarts
  785. SwitchOnVowelType(plist, phdata, &prog, 2);
  786. break;
  787. case 6: // PrevVowelTypeEndings
  788. SwitchOnVowelType(plist, phdata, &prog, 3);
  789. break;
  790. }
  791. break;
  792. case 9:
  793. data = ((instn & 0xf) << 16) + prog[1];
  794. prog++;
  795. switch (instn2)
  796. {
  797. case 1:
  798. // call a procedure or another phoneme
  799. if (n_return < N_RETURN) {
  800. return_addr[n_return++] = prog;
  801. prog = &phoneme_index[data] - 1;
  802. }
  803. break;
  804. case 2:
  805. // pitch envelope
  806. phdata->pitch_env = data;
  807. break;
  808. case 3:
  809. // amplitude envelope
  810. phdata->amp_env = data;
  811. break;
  812. }
  813. break;
  814. case 10: // Vowelin, Vowelout
  815. if (instn2 == 1)
  816. ix = 0;
  817. else
  818. ix = 2;
  819. phdata->vowel_transition[ix] = ((prog[0] & 0xff) << 16) + prog[1];
  820. phdata->vowel_transition[ix+1] = (prog[2] << 16) + prog[3];
  821. prog += 3;
  822. break;
  823. case 11: // FMT
  824. case 12: // WAV
  825. case 13: // VowelStart
  826. case 14: // VowelEnd
  827. case 15: // addWav
  828. instn2 = (instn >> 12) - 11;
  829. phdata->sound_addr[instn2] = ((instn & 0xf) << 18) + (prog[1] << 2);
  830. param_sc = phdata->sound_param[instn2] = (instn >> 4) & 0xff;
  831. prog++;
  832. if (prog[1] != INSTN_CONTINUE) {
  833. if (instn2 < 2) {
  834. // FMT() and WAV() imply Return
  835. end_flag = 1;
  836. if ((prog[1] >> 12) == 0xf) {
  837. // Return after the following addWav()
  838. end_flag = 2;
  839. }
  840. } else if (instn2 == pd_ADDWAV) {
  841. // addWav(), return if previous instruction was FMT() or WAV()
  842. end_flag--;
  843. }
  844. if ((instn2 == pd_VWLSTART) || (instn2 == pd_VWLEND)) {
  845. // VowelStart or VowelEnding.
  846. phdata->sound_param[instn2] = param_sc; // sign extend
  847. }
  848. }
  849. break;
  850. default:
  851. InvalidInstn(ph, instn);
  852. break;
  853. }
  854. if ((end_flag == 1) && (n_return > 0)) {
  855. // return from called procedure or phoneme
  856. end_flag = 0;
  857. prog = return_addr[--n_return];
  858. }
  859. }
  860. if ((worddata != NULL) && (plist->type == phVOWEL))
  861. memcpy(&worddata->prev_vowel, &plist[0], sizeof(PHONEME_LIST));
  862. plist->std_length = phdata->pd_param[i_SET_LENGTH];
  863. if (phdata->sound_addr[0] != 0) {
  864. plist->phontab_addr = phdata->sound_addr[0]; // FMT address
  865. plist->sound_param = phdata->sound_param[0];
  866. } else {
  867. plist->phontab_addr = phdata->sound_addr[1]; // WAV address
  868. plist->sound_param = phdata->sound_param[1];
  869. }
  870. }
  871. void InterpretPhoneme2(int phcode, PHONEME_DATA *phdata)
  872. {
  873. // Examine the program of a single isolated phoneme
  874. int ix;
  875. PHONEME_LIST plist[4];
  876. memset(plist, 0, sizeof(plist));
  877. for (ix = 0; ix < 4; ix++) {
  878. plist[ix].phcode = phonPAUSE;
  879. plist[ix].ph = phoneme_tab[phonPAUSE];
  880. }
  881. plist[1].phcode = phcode;
  882. plist[1].ph = phoneme_tab[phcode];
  883. plist[2].sourceix = 1;
  884. InterpretPhoneme(NULL, 0, &plist[1], phdata, NULL);
  885. }