1
/* time_planner.c -- Make up speech time layout
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
15
#include "soundscript.h"
16
#include "transcription.h"
20
#define MIN(x, y) ((x < y) ? x : y)
21
#define DISCRIMINANT(x, y) ((x != y) ? ((x != 1) ? 3 : 2) : 1)
24
/* Scratch data structure */
39
/* Phoncode sets for classification */
40
static const uint8_t set0[] = { 44, 45, 48, 49, 46, 47, 50, 51 };
41
static const uint8_t set1[] = { 10, 15, 18, 16, 19, 8, 13, 14, 17 };
42
static const uint8_t set2[] = { 6, 11, 7, 12, 9 };
43
static const uint8_t set3[] = { 20, 23, 21, 24, 22, 25 };
44
static const uint8_t set4[] = { 34, 37, 35, 38, 32, 36, 39, 33, 40, 41 };
45
static const uint8_t set5[] = { 26, 29, 27, 30, 28, 31 };
46
static const uint8_t set6[] = { 10, 14, 17, 15, 18, 16, 19, 8, 13 };
47
static const uint8_t set7[] = { 6, 11, 7, 12, 9, 20, 23, 21, 24, 22, 25 };
48
static const uint8_t set8[] = { 20, 23, 26, 29, 15, 18, 6, 11, 34, 37 };
49
static const uint8_t set9[] = { 21, 24, 27, 30, 14, 17, 16, 19, 7, 12, 35, 38, 36, 39, 32, 33, 9 };
50
static const uint8_t set10[] = { 22, 25, 28, 31, 40, 41 };
53
/* Local subroutines */
55
/* Define rank for specified phoncode */
56
static uint8_t rank(uint8_t phoncode)
59
if (memchr(set1, phoncode, sizeof(set1)))
61
else if (memchr(set2, phoncode, sizeof(set2)))
63
else if (memchr(set3, phoncode, sizeof(set3)))
65
else if (memchr(set4, phoncode, sizeof(set4)))
67
else if (memchr(set5, phoncode, sizeof(set5)))
72
/* Prepare next iteration */
73
static void next_iteration(workspace_t *scratch)
75
scratch->area[3][++(scratch->ndx2)] = scratch->value;
78
scratch->area[2][scratch->ndx1] += scratch->delta;
84
/* Global entry point */
87
* Fill timing draft for specified phonetic transcription.
89
* This draft is used for speechrate applying.
91
* Returns non-zero value if the draft is successively filled.
93
time_plan_ptr_t plan_time(uint8_t *transcription)
95
time_plan_ptr_t draft;
98
uint8_t check_prev_trigger = 0;
99
uint8_t check_prev = 0;
100
uint8_t skip_itercount = 1;
103
draft = calloc(TIME_PLAN_ROWS, sizeof(*draft));
107
scratch = malloc(sizeof(workspace_t));
113
memset(scratch, 0, sizeof(workspace_t));
115
for (i = TRANSCRIPTION_START; i < TRANSCRIPTION_BUFFER_SIZE; i++)
116
if (transcription[i] > 5)
118
if (transcription[i] != 43)
120
uint8_t *found = memchr(set0, transcription[i], sizeof(set0));
124
uint8_t values[TIME_PLAN_ROWS];
129
uint8_t k = found - set0;
135
memset(values, 0, TIME_PLAN_ROWS);
139
next_iteration(scratch);
141
scratch->area[4][++nitems] = scratch->itercount;
142
scratch->itercount = 0;
143
for (k = scratch->ndx2; k > 0; k--)
144
scratch->area[1][k] = 0;
147
for (item = 1; item <= nitems; item++)
150
for (i = 1; i <= scratch->area[4][item]; i++)
154
for (ndx3 = 1; ndx3 <= scratch->area[3][scratch->ndx2]; ndx3++)
155
if (scratch->area[0][++(scratch->ndx1)])
158
if (scratch->area[0][scratch->ndx1] == 1)
159
scratch->area[1][scratch->ndx2] = 1;
160
else if (scratch->area[0][scratch->ndx1] != 0xFF)
162
n = scratch->ndx1 - 2;
163
for (l = scratch->ndx1 - ndx3 + 1; l <= n; l++)
164
scratch->area[0][l] = 3;
166
scratch->area[0][scratch->ndx1 - 1] = 2;
167
n = scratch->area[3][scratch->ndx2] + scratch->ndx1 - ndx3;
168
for (l = scratch->ndx1 + 2; l <= n; l++)
169
scratch->area[0][l] = 5;
170
if (scratch->area[3][scratch->ndx2] != ndx3)
171
scratch->area[0][scratch->ndx1 + 1] = 4;
172
scratch->area[0][scratch->ndx1] = 1;
176
k = scratch->area[4][item];
177
for (i = 1; i <= k; i++)
178
if (scratch->area[1][++(scratch->ndx2)] == 1)
181
for (l = scratch->ndx2 - i + 1; l < scratch->ndx2; l++)
182
scratch->area[1][l] = 2;
183
n = scratch->area[4][item] + scratch->ndx2 - i;
184
for (l = scratch->ndx2 + 1; l <= n; l++)
185
scratch->area[1][l] = 3;
186
scratch->area[1][scratch->ndx2] = 1;
192
values[7] = MIN(nitems, 4);
193
i = TRANSCRIPTION_START - 1;
194
for (item = 1; item <= nitems; item++)
197
values[3] = DISCRIMINANT(item, nitems);
198
for (ndx4 = 1; ndx4 <= scratch->area[4][item]; ndx4++, ndx2++)
202
values[6] = MIN(scratch->area[3][ndx2], 4);
203
for (ndx5 = 1; ndx5 <= scratch->area[3][ndx2]; ndx5++, ndx1++)
206
values[2] = DISCRIMINANT(ndx5, scratch->area[3][ndx2]);
207
for (j = 1; (j <= scratch->area[2][ndx1]) && (m < sizeof(*draft)); j++, m++)
209
uint8_t phoncode_cur = transcription[i];
210
uint8_t phoncode_prev = phoncode_cur;
213
phoncode_cur = transcription[++i];
214
if ((phoncode_cur < 6) || memchr(set6, phoncode_cur, sizeof(set6)))
216
else if (memchr(set7, phoncode_cur, sizeof(set7)))
218
else if ((phoncode_cur > 25) && (phoncode_cur < 42))
220
else if ((phoncode_cur > 43) && (phoncode_cur < 52))
222
i = TRANSCRIPTION_START;
236
else tmp = values[1];
240
phoncode_prev = phoncode_cur;
242
values[4] = scratch->area[0][scratch->ndx1];
243
values[5] = scratch->area[1][scratch->ndx2];
244
for (k = 2; k < TIME_PLAN_ROWS; k++)
245
draft[k][m] = values[k] ? (values[k] - 1) : 0;
246
if ((phoncode_prev > 5) &&
247
(phoncode_prev < 43) &&
248
(phoncode_prev == phoncode_cur))
250
else if ((memchr(set8, phoncode_prev, 4) && memchr(set8, phoncode_cur, sizeof(set8))) ||
251
(memchr(set9, phoncode_prev, 4) && memchr(set9, phoncode_cur, sizeof(set9))) ||
252
(memchr(set10, phoncode_prev, 4) && memchr(set10, phoncode_cur, sizeof(set10))))
255
draft[1][m] = values[1] - 1;
256
else draft[1][m] = 0;
257
draft[0][m] = values[0] ? (values[0] - 1) : 3;
270
if (transcription[i - 1] != 43)
275
rank_prev = rank(transcription[i - 1]);
278
rank_cur = rank(transcription[i]);
281
if (rank_prev <= rank_cur)
282
scratch->area[2][scratch->ndx1]++;
283
else scratch->delta++;
286
else scratch->delta++;
288
else scratch->delta++;
289
if (check_prev_trigger)
292
check_prev_trigger = 0;
296
else next_iteration(scratch);
302
scratch->area[2][scratch->ndx1 + 1] = scratch->delta;
303
if (transcription[i + 1] != 53)
305
if (transcription[i + 1] != 54)
306
scratch->area[0][scratch->ndx1 + 1] = 0;
309
scratch->area[0][scratch->ndx1 + 1] = 0xFF;
315
scratch->area[0][scratch->ndx1 + 1] = 1;
320
scratch->area[4][++nitems] = scratch->itercount;
321
scratch->itercount = 0;
328
check_prev_trigger = 1;