ru_tts

Форк
0
/
time_planner.c 
335 строк · 12.3 Кб
1
/* time_planner.c -- Make up speech time layout
2
 *
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>
7
 *
8
 * SPDX-License-Identifier: MIT
9
 */
10

11
#include <stdint.h>
12
#include <stdlib.h>
13
#include <string.h>
14

15
#include "soundscript.h"
16
#include "transcription.h"
17

18

19
/* Local macros */
20
#define MIN(x, y) ((x < y) ? x : y)
21
#define DISCRIMINANT(x, y) ((x != y) ? ((x != 1) ? 3 : 2) : 1)
22

23

24
/* Scratch data structure */
25
typedef struct
26
{
27
  uint8_t value;
28
  uint8_t delta;
29
  uint8_t flag;
30
  uint8_t ndx1;
31
  uint8_t ndx2;
32
  uint8_t itercount;
33
  uint8_t area[5][50];
34
} workspace_t;
35

36

37
/* Static data */
38

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 };
51

52

53
/* Local subroutines */
54

55
/* Define rank for specified phoncode */
56
static uint8_t rank(uint8_t phoncode)
57
{
58
  uint8_t rc = 0;
59
  if (memchr(set1, phoncode, sizeof(set1)))
60
    rc = 1;
61
  else if (memchr(set2, phoncode, sizeof(set2)))
62
    rc = 2;
63
  else if (memchr(set3, phoncode, sizeof(set3)))
64
    rc = 3;
65
  else if (memchr(set4, phoncode, sizeof(set4)))
66
    rc = 4;
67
  else if (memchr(set5, phoncode, sizeof(set5)))
68
    rc = 5;
69
  return rc;
70
}
71

72
/* Prepare next iteration */
73
static void next_iteration(workspace_t *scratch)
74
{
75
  scratch->area[3][++(scratch->ndx2)] = scratch->value;
76
  scratch->value = 0;
77
  if (scratch->flag)
78
    scratch->area[2][scratch->ndx1] += scratch->delta;
79
  scratch->delta = 0;
80
  scratch->itercount++;
81
}
82

83

84
/* Global entry point */
85

86
/*
87
 * Fill timing draft for specified phonetic transcription.
88
 *
89
 * This draft is used for speechrate applying.
90
 *
91
 * Returns non-zero value if the draft is successively filled.
92
 */
93
time_plan_ptr_t plan_time(uint8_t *transcription)
94
{
95
  time_plan_ptr_t draft;
96
  workspace_t *scratch;
97
  uint16_t i;
98
  uint8_t check_prev_trigger = 0;
99
  uint8_t check_prev = 0;
100
  uint8_t skip_itercount = 1;
101
  uint8_t nitems = 0;
102

103
  draft = calloc(TIME_PLAN_ROWS, sizeof(*draft));
104
  if (!draft)
105
    return NULL;
106

107
  scratch = malloc(sizeof(workspace_t));
108
  if (!scratch)
109
    {
110
      free(draft);
111
      return NULL;
112
    }
113
  memset(scratch, 0, sizeof(workspace_t));
114

115
  for (i = TRANSCRIPTION_START; i < TRANSCRIPTION_BUFFER_SIZE; i++)
116
    if (transcription[i] > 5)
117
      {
118
        if (transcription[i] != 43)
119
          {
120
            uint8_t *found = memchr(set0, transcription[i], sizeof(set0));
121

122
            if (found)
123
              {
124
                uint8_t values[TIME_PLAN_ROWS];
125
                uint8_t restart = 0;
126
                uint8_t setcase = 0;
127
                uint8_t tmp = 0;
128
                uint8_t m = 1;
129
                uint8_t k = found - set0;
130
                uint8_t j;
131
                uint8_t ndx1 = 1;
132
                uint8_t ndx2 =1;
133
                uint8_t item;
134

135
                memset(values, 0, TIME_PLAN_ROWS);
136
                if (k > 3)
137
                  k = 0;
138
                values[8] = k + 1;
139
                next_iteration(scratch);
140
                skip_itercount = 1;
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;
145
                scratch->ndx1 = 0;
146
                scratch->ndx2 = 0;
147
                for (item = 1; item <= nitems; item++)
148
                  {
149
                    j = scratch->ndx2;
150
                    for (i = 1; i <= scratch->area[4][item]; i++)
151
                      {
152
                        uint8_t ndx3;
153
                        scratch->ndx2++;
154
                        for (ndx3 = 1; ndx3 <= scratch->area[3][scratch->ndx2]; ndx3++)
155
                          if (scratch->area[0][++(scratch->ndx1)])
156
                            {
157
                              int8_t l, n;
158
                              if (scratch->area[0][scratch->ndx1] == 1)
159
                                scratch->area[1][scratch->ndx2] = 1;
160
                              else if (scratch->area[0][scratch->ndx1] != 0xFF)
161
                                continue;
162
                              n = scratch->ndx1 - 2;
163
                              for (l = scratch->ndx1 - ndx3 + 1; l <= n; l++)
164
                                scratch->area[0][l] = 3;
165
                              if (ndx3 != 1)
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;
173
                            }
174
                      }
175
                    scratch->ndx2 = j;
176
                    k = scratch->area[4][item];
177
                    for (i = 1; i <= k; i++)
178
                      if (scratch->area[1][++(scratch->ndx2)] == 1)
179
                        {
180
                          int8_t l, n;
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;
187
                        }
188
                  }
189

190
                scratch->ndx1 = 0;
191
                scratch->ndx2 = 0;
192
                values[7] = MIN(nitems, 4);
193
                i = TRANSCRIPTION_START - 1;
194
                for (item = 1; item <= nitems; item++)
195
                  {
196
                    uint8_t ndx4;
197
                    values[3] = DISCRIMINANT(item, nitems);
198
                    for (ndx4 = 1; ndx4 <= scratch->area[4][item]; ndx4++, ndx2++)
199
                      {
200
                        uint8_t ndx5;
201
                        scratch->ndx2++;
202
                        values[6] = MIN(scratch->area[3][ndx2], 4);
203
                        for (ndx5 = 1; ndx5 <= scratch->area[3][ndx2]; ndx5++, ndx1++)
204
                          {
205
                            scratch->ndx1++;
206
                            values[2] = DISCRIMINANT(ndx5, scratch->area[3][ndx2]);
207
                            for (j = 1; (j <= scratch->area[2][ndx1]) && (m < sizeof(*draft)); j++, m++)
208
                              {
209
                                uint8_t phoncode_cur = transcription[i];
210
                                uint8_t phoncode_prev = phoncode_cur;
211
                                while (1)
212
                                  {
213
                                    phoncode_cur = transcription[++i];
214
                                    if ((phoncode_cur < 6) || memchr(set6, phoncode_cur, sizeof(set6)))
215
                                      setcase = 2;
216
                                    else if (memchr(set7, phoncode_cur, sizeof(set7)))
217
                                      setcase = 3;
218
                                    else if ((phoncode_cur > 25) && (phoncode_cur < 42))
219
                                      setcase = 4;
220
                                    else if ((phoncode_cur > 43) && (phoncode_cur < 52))
221
                                      {
222
                                        i = TRANSCRIPTION_START;
223
                                        restart = 1;
224
                                        values[0] = tmp;
225
                                        tmp = values[1];
226
                                        values[1] = 1;
227
                                        break;
228
                                      }
229
                                    else continue;
230
                                    values[0] = tmp;
231
                                    if (restart)
232
                                      {
233
                                        tmp = 0;
234
                                        restart = 0;
235
                                      }
236
                                    else tmp = values[1];
237
                                    values[1] = setcase;
238
                                    if (tmp)
239
                                      break;
240
                                    phoncode_prev = phoncode_cur;
241
                                  }
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))
249
                                  draft[1][m] = 5;
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))))
253
                                  draft[1][m] = 4;
254
                                else if (values[1])
255
                                  draft[1][m] = values[1] - 1;
256
                                else draft[1][m] = 0;
257
                                draft[0][m] = values[0] ? (values[0] - 1) : 3;
258
                              }
259
                          }
260
                      }
261
                  }
262
                free(scratch);
263
                return draft;
264
              }
265
            else
266
              {
267
                scratch->flag = 1;
268
                if (check_prev)
269
                  {
270
                    if (transcription[i - 1] != 43)
271
                      {
272
                        uint8_t rank_prev;
273
                        uint8_t rank_cur;
274
                        check_prev = 0;
275
                        rank_prev = rank(transcription[i - 1]);
276
                        if (!rank_prev)
277
                          break;
278
                        rank_cur = rank(transcription[i]);
279
                        if (!rank_cur)
280
                          break;
281
                        if (rank_prev <= rank_cur)
282
                          scratch->area[2][scratch->ndx1]++;
283
                        else scratch->delta++;
284
                        continue;
285
                      }
286
                    else scratch->delta++;
287
                  }
288
                else scratch->delta++;
289
                if (check_prev_trigger)
290
                  {
291
                    check_prev = 1;
292
                    check_prev_trigger = 0;
293
                  }
294
              }
295
          }
296
        else next_iteration(scratch);
297
      }
298
    else
299
      {
300
        scratch->delta++;
301
        scratch->flag = 0;
302
        scratch->area[2][scratch->ndx1 + 1] = scratch->delta;
303
        if (transcription[i + 1] != 53)
304
          {
305
            if (transcription[i + 1] != 54)
306
              scratch->area[0][scratch->ndx1 + 1] = 0;
307
            else
308
              {
309
                scratch->area[0][scratch->ndx1 + 1] = 0xFF;
310
                i++;
311
              }
312
          }
313
        else
314
          {
315
            scratch->area[0][scratch->ndx1 + 1] = 1;
316
            if (skip_itercount)
317
              skip_itercount = 0;
318
            else
319
              {
320
                scratch->area[4][++nitems] = scratch->itercount;
321
                scratch->itercount = 0;
322
              }
323
            i++;
324
          }
325
        scratch->ndx1++;
326
        scratch->delta = 0;
327
        scratch->value++;
328
        check_prev_trigger = 1;
329
        check_prev = 0;
330
      }
331

332
  free(scratch);
333
  free(draft);
334
  return NULL;
335
}
336

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.