ru_tts

Форк
0
/
synth.c 
332 строки · 7.8 Кб
1
/* synth.c -- Phonetic transcription to speech transformation
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 "synth.h"
16
#include "soundscript.h"
17
#include "transcription.h"
18
#include "ru_tts.h"
19

20

21
/* Local data */
22

23
static const uint8_t seqlist1[] =
24
  {
25
    1, 2,
26
    5, 6, 8, 1, 24, 3,
27
    4, 21, 2, 25, 3,
28
    2, 21, 2,
29
    5, 10, 3, 21, 6, 2,
30
    5, 10, 3, 35, 17, 5,
31
    3, 5, 17, 5,
32
    4, 5, 27, 2, 28,
33
    5, 5, 16, 2, 33, 3,
34
    1, 5,
35
    3, 28, 2, 28,
36
    4, 17, 5, 20, 1,
37
    2, 16, 1,
38
    3, 8, 2, 35,
39
    5, 27, 2, 28, 25, 3,
40
    3, 27, 2, 28,
41
    3, 30, 3, 15,
42
    4, 27, 1, 25, 3,
43
    3, 40, 1, 30,
44
    3, 33, 3, 15,
45
    5, 33, 27, 1, 20, 4,
46
    4, 33, 27, 1, 26,
47
    3, 33, 27, 1,
48
    4, 5, 27, 2, 22,
49
    3, 28, 2, 22,
50
    3, 8, 2, 7,
51
    3, 27, 2, 22,
52
    3, 40, 1, 24,
53
    4, 33, 27, 1, 20,
54
    2, 27, 1,
55
    0
56
  };
57

58
static const uint8_t seqlist2[] =
59
  {
60
    3, 23, 3, 35,
61
    3, 23, 3, 7,
62
    4, 6, 21, 1, 17,
63
    4, 20, 17, 5, 35,
64
    4, 20, 17, 5, 7,
65
    5, 6, 8, 1, 24, 3,
66
    5, 6, 1, 7, 17, 3,
67
    5, 6, 11, 5, 21, 0,
68
    3, 6, 19, 3,
69
    2, 6, 1,
70
    1, 6,
71
    1, 34,
72
    3, 21, 17, 2,
73
    2, 21, 1,
74
    2, 5, 35,
75
    2, 5, 7,
76
    2, 28, 1,
77
    1, 28,
78
    1, 22,
79
    5, 18, 3, 9, 21, 0,
80
    3, 16, 2, 21,
81
    3, 16, 2, 27,
82
    2, 16, 2,
83
    2, 19, 3,
84
    2, 1, 27,
85
    2, 1, 21,
86
    2, 1, 20,
87
    2, 1, 26,
88
    1, 1,
89
    5, 29, 3, 13, 3, 21,
90
    5, 29, 3, 13, 3, 27,
91
    5, 26, 1, 35, 17, 3,
92
    3, 26, 1, 21,
93
    3, 26, 1, 27,
94
    3, 26, 13, 5,
95
    3, 26, 8, 1,
96
    2, 26, 1,
97
    4, 8, 2, 24, 5,
98
    5, 35, 28, 6, 1, 38,
99
    5, 35, 28, 6, 1, 12,
100
    6, 35, 11, 3, 8, 40, 2,
101
    2, 35, 1,
102
    1, 35,
103
    5, 7, 7, 2, 24, 5,
104
    1, 0,
105
    5, 33, 3, 13, 3, 35,
106
    5, 33, 3, 13, 3, 7,
107
    2, 7, 2,
108
    1, 7,
109
    0
110
  };
111

112
static const uint8_t seqlist3[] =
113
  {
114
    2, 20, 4,
115
    1, 20,
116
    2, 9, 3,
117
    1, 9,
118
    5, 19, 5, 20, 0, 24,
119
    1, 26,
120
    2, 27, 1,
121
    0
122
  };
123

124
static const uint8_t seqlist4[] =
125
  {
126
    3, 2, 6, 2,
127
    3, 3, 6, 2,
128
    3, 2, 15, 0,
129
    3, 3, 15, 0,
130
    3, 5, 18, 5,
131
    3, 2, 10, 3,
132
    3, 2, 10, 2,
133
    3, 5, 10, 3,
134
    3, 0, 10, 0,
135
    4, 1, 53, 6, 2,
136
    4, 3, 6, 1, 53,
137
    0
138
  };
139

140
static const uint8_t seqlist5[] =
141
  {
142
    2, 5, 10,
143
    3, 1, 53, 10,
144
    2, 3, 10,
145
    2, 5, 40,
146
    2, 5, 15,
147
    3, 1, 53, 15,
148
    2, 3, 15,
149
    0
150
  };
151

152

153
/* Local subroutines */
154

155
/*
156
 * Test a phoncode sequence pointed by ptr against specified list.
157
 * Returns non-zero when succeeded.
158
 */
159
static int test_list(const uint8_t *ptr, const uint8_t *lst)
160
{
161
  const uint8_t *item;
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);
164
}
165

166
/* Shift clause transcription one point left */
167
static void shift(uint8_t *buf)
168
{
169
  size_t i = 0;
170
  do
171
    {
172
      buf[i] = buf[i + 1];
173
      i++;
174
    }
175
  while ((buf[i] < 44) || (buf[i] > 52));
176
  buf[i] = 43;
177
}
178

179
/*
180
 * Advance transcription up to the specified point.
181
 * Returns pointer to the transcription start.
182
 */
183
static uint8_t *transcription_advance(uint8_t *transcription, uint8_t *point)
184
{
185
  if (point > (transcription + TRANSCRIPTION_START))
186
    {
187
      size_t length = (point < (transcription + TRANSCRIPTION_BUFFER_SIZE)) ? (transcription + TRANSCRIPTION_BUFFER_SIZE - point) : 0;
188
      if (length)
189
        memmove(transcription + TRANSCRIPTION_START, point, length);
190
      memset(transcription + TRANSCRIPTION_START + length, 43, TRANSCRIPTION_BUFFER_SIZE - TRANSCRIPTION_START - length);
191
    }
192
  return transcription + TRANSCRIPTION_START;
193
}
194

195
/* Synthesize speech for specified clause phonetic transcription */
196
static void synth_clause(uint8_t *transcription, ttscb_t *ttscb, uint8_t clause_type)
197
{
198
  soundscript_t *soundscript = malloc(sizeof(soundscript_t));
199
  if (soundscript)
200
    {
201
      time_plan_ptr_t draft;
202
      memset(soundscript, 0, sizeof(soundscript_t));
203
      soundscript->voice = (ttscb->flags & USE_ALTERNATIVE_VOICE) ? &female : &male;
204
      build_utterance(transcription, soundscript);
205
      draft = plan_time(transcription);
206
      if (draft)
207
        {
208
          apply_speechrate(soundscript, &(ttscb->timing), draft);
209
          free(draft);
210
        }
211
      apply_intonation(transcription, soundscript, &(ttscb->modulation), clause_type);
212
      make_sound(soundscript, &(ttscb->wave_consumer));
213
      free(soundscript);
214
    }
215
}
216

217
/* Synthesize speech clause by clause for specified phonetic transcription */
218
static void synth(uint8_t *transcription, ttscb_t *ttscb)
219
{
220
  uint8_t *tptr;
221
  uint8_t *sptr = transcription + TRANSCRIPTION_START;
222
  uint8_t count = 0;
223
  uint8_t flags = 4;
224

225
  for (tptr = transcription + TRANSCRIPTION_START; tptr < transcription + TRANSCRIPTION_BUFFER_SIZE; tptr++)
226
    {
227
      if (flags & 4)
228
        {
229
          flags &= ~4;
230
          if (test_list(tptr, seqlist1))
231
            {
232
              if (flags & 1)
233
                {
234
                  *sptr = 50;
235
                  synth_clause(transcription, ttscb, 0);
236
                  tptr = transcription_advance(transcription, tptr);
237
                  count = 0;
238
                  flags &= ~1;
239
                  sptr = tptr;
240
                }
241
              flags |= 2;
242
              continue;
243
            }
244
          else if (test_list(tptr, seqlist2))
245
            {
246
              flags |= 2;
247
              continue;
248
            }
249
          else if (test_list(tptr, seqlist3) &&
250
                   (tptr > (transcription + TRANSCRIPTION_START)) &&
251
                   (*(tptr - 1) == 43))
252
            {
253
              sptr = --tptr;
254
              shift(sptr);
255
              flags &= ~2;
256
              continue;
257
            }
258
        }
259
      if (*tptr != 43)
260
        {
261
          if ((*tptr > 43) && (*tptr < 53))
262
            {
263
              synth_clause(transcription, ttscb, ttscb->transcription_state.clause_type);
264
              break;
265
            }
266
        }
267
      else if (flags & 2)
268
        {
269
          shift(tptr--);
270
          flags = 4;
271
        }
272
      else if (((++count) != 3) || test_list(tptr + 1, seqlist1))
273
        {
274
          sptr = tptr;
275
          flags |= 5;
276
        }
277
      else
278
        {
279
          uint8_t *next;
280
          uint8_t perspective = 20;
281
          uint8_t k;
282
          if ((!test_list(tptr - 3, seqlist4)) && (!test_list(tptr - 2, seqlist5)))
283
            sptr = tptr;
284
          next = memchr(tptr + 1, 43, perspective);
285
          if (next)
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))
290
              break;
291
          if ((k > perspective) && !test_list(next, seqlist1))
292
            {
293
              *sptr = 50;
294
              synth_clause(transcription, ttscb, 0);
295
              tptr = transcription_advance(transcription, sptr + 1) - 1;
296
              count = 0;
297
              flags &= ~2;
298
            }
299
          flags |= 5;
300
          sptr = tptr;
301
        }
302
    }
303
}
304

305

306
/* Global entry point */
307

308
/*
309
 * Transcription callback function.
310
 *
311
 * Finalizes provided transcription and performs speech synthesis for it.
312
 *
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.
316
 */
317
int synth_function(void *buffer, size_t length, void *user_data)
318
{
319
  ttscb_t *ttscb = user_data;
320
  if (length > TRANSCRIPTION_START)
321
    {
322
      if (ttscb->transcription_state.flags & CLAUSE_DONE)
323
        ttscb->transcription_state.flags &= ~CLAUSE_DONE;
324
      else
325
        {
326
          ((uint8_t *)buffer)[length] = 50;
327
          ttscb->transcription_state.clause_type = 0;
328
        }
329
      synth(buffer, ttscb);
330
    }
331
  return ttscb->wave_consumer.status;
332
}
333

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

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

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

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