1
/* speechrate_control.c -- Apply speechrate parameters to a sound script
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"
17
#include "transcription.h"
20
/* Local static data */
22
/* Bottom duration threshold for all voice sounds */
23
static const uint8_t bottom[] =
25
30, 31, 32, 31, 30, 30,
26
31, 32, 31, 30, 15, 15,
27
15, 15, 15, 15, 15, 15,
28
15, 15, 15, 15, 15, 15,
29
15, 15, 15, 15, 15, 15,
30
15, 15, 15, 15, 15, 15,
31
15, 15, 15, 15, 15, 15,
32
15, 15, 15, 15, 15, 15,
33
15, 15, 30, 30, 30, 30,
34
30, 15, 15, 15, 15, 15,
35
30, 30, 30, 30, 30, 15,
36
15, 15, 15, 15, 30, 30,
37
30, 30, 30, 15, 15, 15,
38
15, 15, 30, 30, 30, 30,
39
30, 15, 15, 15, 15, 15,
40
30, 30, 30, 30, 30, 10,
41
11, 12, 11, 10, 10, 11,
42
12, 11, 10, 15, 15, 15,
43
15, 15, 15, 15, 15, 15,
44
15, 15, 15, 15, 15, 15,
45
15, 15, 20, 30, 35, 20,
46
40, 20, 35, 49, 30, 45,
47
20, 40, 50, 40, 50, 60,
48
50, 0, 20, 25, 10, 35,
49
35, 20, 20, 30, 20, 35,
51
25, 20, 20, 30, 20, 20,
52
30, 50, 50, 40, 40, 35,
53
35, 50, 40, 40, 50, 30,
54
30, 30, 30, 40, 50, 60,
55
60, 80, 70, 70, 90, 50,
56
60, 50, 50, 5, 0, 255,
57
255, 0, 255, 255, 255, 255,
61
/* Top duration threshold for all voice sounds */
62
static const uint8_t top[] =
64
75, 78, 80, 78, 75, 55,
65
58, 60, 58, 55, 30, 30,
66
30, 30, 30, 25, 25, 25,
67
25, 25, 30, 30, 30, 30,
68
30, 25, 25, 25, 25, 25,
69
30, 30, 30, 30, 30, 25,
70
25, 25, 25, 25, 30, 30,
71
30, 30, 30, 25, 25, 25,
72
25, 25, 60, 60, 60, 60,
73
60, 25, 25, 25, 25, 25,
74
50, 50, 50, 50, 50, 25,
75
25, 25, 25, 25, 50, 50,
76
50, 50, 50, 25, 25, 25,
77
25, 25, 50, 50, 50, 50,
78
50, 25, 25, 25, 25, 25,
79
60, 60, 60, 60, 60, 50,
80
50, 50, 50, 50, 50, 50,
81
50, 50, 50, 30, 30, 35,
82
30, 35, 30, 30, 30, 30,
83
30, 35, 30, 30, 30, 30,
84
35, 30, 40, 80, 90, 45,
85
110, 50, 90, 100, 50, 110,
86
40, 100, 110, 100, 100,
87
110, 100, 20, 30, 30, 23,
88
80, 40, 30, 30, 50, 35,
89
50, 60, 19, 30, 30, 19,
90
30, 30, 30, 30, 50, 30,
91
30, 50, 110, 100, 80, 100,
92
80, 70, 130, 120, 110, 130,
93
90, 90, 80, 80, 90, 100,
94
150, 150, 160, 170, 170,
95
210, 130, 150, 130, 130,
96
50, 0, 20, 30, 25, 25,
97
40, 50, 15, 255, 55, 255
100
/* Sound duration forming elements */
101
static const uint8_t elements[][6] =
103
{ 20, 20, 0, 0, 0, 0 },
104
{ 50, 25, 25, 0, 0, 0 },
105
{ 10, 2, 1, 0, 0, 0 },
106
{ 20, 10, 0, 0, 0, 0 },
107
{ 60, 30, 0, 0, 0, 0 },
108
{ 30, 15, 0, 0, 0, 0 },
109
{ 50, 40, 20, 0, 0, 0 },
110
{ 20, 12, 6, 0, 0, 0 },
111
{ 0, 8, 12, 40, 0, 0 }
115
/* Global functions */
118
* Initial timing setup for specified speech rate and relative
119
* interclause gap duration expressed as a percentage
120
* of the default value.
122
void timing_setup(timing_t *timing, int speech_rate, int gap_factor)
126
if (speech_rate < 20)
127
timing->rate_factor = 20;
128
else if (speech_rate > 500)
129
timing->rate_factor = 500;
130
else timing->rate_factor = speech_rate;
131
timing->gap_factor = (uint8_t) ((gap_factor << 2) / 5);
132
for (i = 0; i < CLAUSE_SEPARATORS; i++)
133
timing->gaplen[i] = top[i + 191];
137
* Adjust gap duration for specified separator
138
* applying a percentage factor.
140
void adjust_gaplen(timing_t *timing, char separator, int gap_factor)
142
char *s = memchr(punctuations, separator, CLAUSE_SEPARATORS);
145
int i = s - punctuations;
146
int gaplen = top[i + 191] * gap_factor / 100;
148
timing->gaplen[i] = 0;
149
else if (gaplen > 150)
150
timing->gaplen[i] = 150;
151
else timing->gaplen[i] = (uint8_t) gaplen;
156
* Apply speechrate parameters to the soundscript
157
* according to specified timing data.
159
void apply_speechrate(soundscript_t *script, timing_t *timing, time_plan_ptr_t draft)
164
for (i = 0; i < script->length; i++)
166
uint8_t j = script->sounds[i].id;
169
if ((draft[1][n] != 4) || (script->sounds[i].stage != 3))
173
for (k = 0; k < TIME_PLAN_ROWS; k++)
174
s += elements[k][draft[k][n]];
175
s *= top[j] - bottom[j];
177
s += (((uint32_t) bottom[j]) << 14) + 2048;
179
if ((draft[1][n] == 5) && (script->sounds[i].stage == 2))
181
script->sounds[i].duration = (uint16_t)(s * 100 / timing->rate_factor);
183
else script->sounds[i].duration = 0;
184
if (script->sounds[i].stage >= script->sounds[i + 1].stage)
185
if (draft[1][n++] == 5)
187
while ((++i) < script->length)
189
script->sounds[i].duration = 0;
190
if (script->sounds[i].stage >= script->sounds[i + 1].stage)
199
uint8_t gaplen = ((k >= 0) && (k < CLAUSE_SEPARATORS)) ? timing->gaplen[k] : top[j];
200
script->sounds[i].duration = (uint16_t)((unsigned int)timing->gap_factor * gaplen * 100 / timing->rate_factor);