1
/* synth.c -- Phonetic transcription to speech transformation
3
* Copyright (C) 1990, 1991 Speech Research Laboratory, Minsk
4
* Copyright (C) 2005 Igor Poretsky <poretsky@mlbox.ru>
5
* Copyright (C) 2021 Boris Lobanov <lobbormef@gmail.com>
6
* Copyright (C) 2021 Alexander Ivanov <ivalex01@gmail.com>
8
* SPDX-License-Identifier: MIT
16
#include "soundscript.h"
17
#include "transcription.h"
23
static const uint8_t seqlist1[] =
58
static const uint8_t seqlist2[] =
100
6, 35, 11, 3, 8, 40, 2,
112
static const uint8_t seqlist3[] =
124
static const uint8_t seqlist4[] =
140
static const uint8_t seqlist5[] =
153
/* Local subroutines */
156
* Test a phoncode sequence pointed by ptr against specified list.
157
* Returns non-zero when succeeded.
159
static int test_list(const uint8_t *ptr, const uint8_t *lst)
162
for (item = lst; item[0] && memcmp(ptr, item + 1, item[0]); item += item[0] + 1);
163
return (item[0] != 0) && (ptr[item[0]] > 42) && (ptr[item[0]] < 53);
166
/* Shift clause transcription one point left */
167
static void shift(uint8_t *buf)
175
while ((buf[i] < 44) || (buf[i] > 52));
180
* Advance transcription up to the specified point.
181
* Returns pointer to the transcription start.
183
static uint8_t *transcription_advance(uint8_t *transcription, uint8_t *point)
185
if (point > (transcription + TRANSCRIPTION_START))
187
size_t length = (point < (transcription + TRANSCRIPTION_BUFFER_SIZE)) ? (transcription + TRANSCRIPTION_BUFFER_SIZE - point) : 0;
189
memmove(transcription + TRANSCRIPTION_START, point, length);
190
memset(transcription + TRANSCRIPTION_START + length, 43, TRANSCRIPTION_BUFFER_SIZE - TRANSCRIPTION_START - length);
192
return transcription + TRANSCRIPTION_START;
195
/* Synthesize speech for specified clause phonetic transcription */
196
static void synth_clause(uint8_t *transcription, ttscb_t *ttscb, uint8_t clause_type)
198
soundscript_t *soundscript = malloc(sizeof(soundscript_t));
201
time_plan_ptr_t draft;
202
memset(soundscript, 0, sizeof(soundscript_t));
203
soundscript->voice = (ttscb->flags & USE_ALTERNATIVE_VOICE) ? &female : ♂
204
build_utterance(transcription, soundscript);
205
draft = plan_time(transcription);
208
apply_speechrate(soundscript, &(ttscb->timing), draft);
211
apply_intonation(transcription, soundscript, &(ttscb->modulation), clause_type);
212
make_sound(soundscript, &(ttscb->wave_consumer));
217
/* Synthesize speech clause by clause for specified phonetic transcription */
218
static void synth(uint8_t *transcription, ttscb_t *ttscb)
221
uint8_t *sptr = transcription + TRANSCRIPTION_START;
225
for (tptr = transcription + TRANSCRIPTION_START; tptr < transcription + TRANSCRIPTION_BUFFER_SIZE; tptr++)
230
if (test_list(tptr, seqlist1))
235
synth_clause(transcription, ttscb, 0);
236
tptr = transcription_advance(transcription, tptr);
244
else if (test_list(tptr, seqlist2))
249
else if (test_list(tptr, seqlist3) &&
250
(tptr > (transcription + TRANSCRIPTION_START)) &&
261
if ((*tptr > 43) && (*tptr < 53))
263
synth_clause(transcription, ttscb, ttscb->transcription_state.clause_type);
272
else if (((++count) != 3) || test_list(tptr + 1, seqlist1))
280
uint8_t perspective = 20;
282
if ((!test_list(tptr - 3, seqlist4)) && (!test_list(tptr - 2, seqlist5)))
284
next = memchr(tptr + 1, 43, perspective);
286
perspective = (++next) - tptr;
287
else next = tptr + perspective + 1;
288
for (k = 1; k <= perspective; k++)
289
if ((tptr[k] > 43) && (tptr[k] < 53))
291
if ((k > perspective) && !test_list(next, seqlist1))
294
synth_clause(transcription, ttscb, 0);
295
tptr = transcription_advance(transcription, sptr + 1) - 1;
306
/* Global entry point */
309
* Transcription callback function.
311
* Finalizes provided transcription and performs speech synthesis for it.
313
* The buffer pointed by the first argument should contain a transcription
314
* of length specified by the second argument. The last argument
315
* should point to the corresponding ttscb structure.
317
int synth_function(void *buffer, size_t length, void *user_data)
319
ttscb_t *ttscb = user_data;
320
if (length > TRANSCRIPTION_START)
322
if (ttscb->transcription_state.flags & CLAUSE_DONE)
323
ttscb->transcription_state.flags &= ~CLAUSE_DONE;
326
((uint8_t *)buffer)[length] = 50;
327
ttscb->transcription_state.clause_type = 0;
329
synth(buffer, ttscb);
331
return ttscb->wave_consumer.status;