ru_tts

Форк
0
/
soundproducer.c 
229 строк · 6.4 Кб
1
/* soundproducer.c -- Output sound stream generator
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

14
#include "soundscript.h"
15
#include "voice.h"
16
#include "sink.h"
17

18

19
/* Local data */
20

21
/* Control data used to generate fully synthetic sounds */
22
static const int16_t synth_ctrl_data[][2] =
23
  {
24
    { 0, -1 },
25
    { 0, -1 },
26
    { 0, -1 },
27
    { 0, -1 },
28
    { 0, -1 },
29
    { 0, -1 },
30
    { 0, -1 },
31
    { 0, -1 },
32
    { 0x930C, 0 },
33
    { 0x0CF74, 1 },
34
    { 2, 0x8002 },
35
    { 0x930C, 1 },
36
    { 2, 1 },
37
    { 2, 0x8003 },
38
    { 0x930C, 0 },
39
    { 0x0CF74, 1 },
40
    { 0x308C, 1 },
41
    { 0x0B8B, 2 },
42
    { 0x502E, 1 },
43
    { 0x66F0, 1 },
44
    { 0, -1 },
45
    { 0, -1 },
46
    { 0, -1 },
47
    { 0, -1 },
48
    { 0, -1 },
49
    { 0, -1 },
50
    { 0, -1 },
51
    { 0, -1 },
52
    { 0, -1 },
53
    { 0, -1 },
54
    { 0, -1 },
55
    { 0, -1 },
56
    { 0, -1 }
57
  };
58

59

60
/* Local subroutines */
61

62
/* Evaluate speech parameters according to the specified stage */
63
static int16_t eval(icb_t *icb)
64
{
65
  int16_t res = (icb->stretch >> 1);
66
  if (!(--icb->count))
67
    {
68
      icb->stretch += icb->delta;
69
      icb->count = icb->period;
70
    }
71
  return res;
72
}
73

74
/*
75
 * Make a silence of specified length.
76
 * Returns length.
77
 */
78
static uint16_t silence(sink_t *consumer, uint16_t length)
79
{
80
  uint16_t i;
81
  for (i = 0; i < length; i++)
82
    sink_put(consumer, 0);
83
  return length;
84
}
85

86
/*
87
 * Make fading from specified sample index in the voice data.
88
 * Returns number of generated samples.
89
 */
90
static uint16_t fading(sink_t *consumer, const voice_t *voice, uint16_t sidx)
91
{
92
  uint16_t i;
93
  int8_t sample = voice->samples[sidx - 1];
94
  for (i = 0; i < 3; i++)
95
    {
96
      sample >>= 1;
97
      sink_put(consumer, sample);
98
    }
99
  return 3;
100
}
101

102

103
/* Global entry point */
104

105
/* Generate sound stream and feed it to the specified sink */
106
void make_sound(soundscript_t *script, sink_t *consumer)
107
{
108
  int i;
109

110
  sink_put(consumer, 0);
111
  for (i = 0; (i < script->length) && !consumer->status; i++)
112
    {
113
      int16_t l = script->sounds[i].duration;
114
      uint16_t j = ((uint16_t)(script->sounds[i].id)) & 0xFF;
115
      uint16_t k;
116
      if (j >= 169)
117
        {
118
          /* Fully synthetic sounds that are not voice dependent */
119
          int16_t bx;
120
          int16_t cx;
121
          j -= 169;
122
          bx = synth_ctrl_data[j][0];
123
          cx = synth_ctrl_data[j][1];
124
          if (cx != -1)
125
            {
126
              uint16_t ax = 205;
127
              int16_t sample_shift = (cx & 0xFF) + 8;
128
              int16_t var1 = 0;
129
              int16_t var2 = 0;
130
              int16_t var3 = 0;
131
              for (k = 0; k <= l; k++)
132
                {
133
                  int16_t si;
134
                  int16_t tmp = ax & 0x2D;
135
                  tmp ^= tmp >> 4;
136
                  tmp &= 0x0F;
137
                  if ((0x6996 >> tmp) & 0x01)
138
                    ax |= 0x8000;
139
                  ax >>= 1;
140
                  tmp = ax;
141
                  ax >>= 2;
142
                  var3 >>= 1;
143
                  var3 += var3 >> 2;
144
                  if (cx >= 0)
145
                    var3 += var3 >> 2;
146
                  si = var3;
147
                  var3 = (var2 << 1) - var1;
148
                  var1 = ax;
149
                  ax = (uint16_t)((((int32_t)var3) * ((int32_t)bx)) >> 15);
150
                  ax += var1 - si;
151
                  var3 = var2;
152
                  var2 = ax;
153
                  sink_put(consumer, (int8_t)(var2 >> sample_shift));
154
                  ax = tmp;
155
                }
156
            }
157
          else silence(consumer, l);
158
        }
159
      else if (l) /* Non-zero sound length check */
160
        {
161
          int16_t ax = 0;
162
          uint16_t sidx = script->voice->sound_offsets[j];
163
          uint16_t scnt = script->voice->sound_lengths[j];
164
          uint8_t stage = script->sounds[i].stage;
165
          if (scnt > VOICE_THRESHOLD)
166
            {
167
              /* Simply copy prepared pattern from the voice data */
168
              do sink_put(consumer, script->voice->samples[sidx++]);
169
              while ((--scnt) && (--l));
170
            }
171
          else if (j >= 132)
172
            {
173
              /* Make a transition of a prepared pattern */
174
              while (l > ax)
175
                {
176
                  k = script->icb[stage].stretch;
177
                  do
178
                    {
179
                      sink_put(consumer, script->voice->samples[sidx++]);
180
                      l--;
181
                    }
182
                  while ((--k) && (--scnt));
183
                  if (k)
184
                    l -= silence(consumer, k);
185
                  else if (scnt > 1)
186
                    l -= fading(consumer, script->voice, sidx);
187
                  ax = eval(&(script->icb[stage]));
188
                  sidx = script->voice->sound_offsets[j];
189
                  scnt = script->voice->sound_lengths[j];
190
                }
191
            }
192
          else
193
            {
194
              /* Mixed and transitional sounds */
195
              int16_t dx = 0;
196
              while (l >= ax)
197
                {
198
                  uint16_t next_pattern_offset;
199
                  k = script->icb[stage].stretch;
200
                  j = ((uint16_t)(script->sounds[i + 1].id)) & 0xFF;
201
                  next_pattern_offset = script->voice->sound_offsets[j + 1];
202
                  j = script->voice->sound_offsets[j];
203
                  sink_put(consumer, 0);
204
                  ax = (int16_t)(script->voice->samples[j]);
205
                  do
206
                    {
207
                      ax -= (int16_t)(script->voice->samples[sidx]);
208
                      ax = (int16_t)(((int32_t)ax) * ((int32_t)(dx++)) / ((int32_t)l));
209
                      ax += (int16_t)(script->voice->samples[sidx++]);
210
                      sink_put(consumer, (int8_t)ax);
211
                      ax = ((++j) < next_pattern_offset) ? ((int16_t)(script->voice->samples[j])) : 0;
212
                    }
213
                  while ((--k) && (--scnt));
214
                  if (k)
215
                    dx += silence(consumer, k);
216
                  else if (scnt > 1)
217
                    dx += fading(consumer, script->voice, sidx);
218
                  ax = dx + eval(&(script->icb[stage]));
219
                  j = ((uint16_t)(script->sounds[i].id)) & 0xFF;
220
                  sidx = script->voice->sound_offsets[j];
221
                  scnt = script->voice->sound_lengths[j];
222
                }
223
            }
224
        }
225
    }
226

227
  /* Flush output buffer */
228
  sink_flush(consumer);
229
}
230

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

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

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

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