1
/* soundproducer.c -- Output sound stream generator
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
14
#include "soundscript.h"
21
/* Control data used to generate fully synthetic sounds */
22
static const int16_t synth_ctrl_data[][2] =
60
/* Local subroutines */
62
/* Evaluate speech parameters according to the specified stage */
63
static int16_t eval(icb_t *icb)
65
int16_t res = (icb->stretch >> 1);
68
icb->stretch += icb->delta;
69
icb->count = icb->period;
75
* Make a silence of specified length.
78
static uint16_t silence(sink_t *consumer, uint16_t length)
81
for (i = 0; i < length; i++)
82
sink_put(consumer, 0);
87
* Make fading from specified sample index in the voice data.
88
* Returns number of generated samples.
90
static uint16_t fading(sink_t *consumer, const voice_t *voice, uint16_t sidx)
93
int8_t sample = voice->samples[sidx - 1];
94
for (i = 0; i < 3; i++)
97
sink_put(consumer, sample);
103
/* Global entry point */
105
/* Generate sound stream and feed it to the specified sink */
106
void make_sound(soundscript_t *script, sink_t *consumer)
110
sink_put(consumer, 0);
111
for (i = 0; (i < script->length) && !consumer->status; i++)
113
int16_t l = script->sounds[i].duration;
114
uint16_t j = ((uint16_t)(script->sounds[i].id)) & 0xFF;
118
/* Fully synthetic sounds that are not voice dependent */
122
bx = synth_ctrl_data[j][0];
123
cx = synth_ctrl_data[j][1];
127
int16_t sample_shift = (cx & 0xFF) + 8;
131
for (k = 0; k <= l; k++)
134
int16_t tmp = ax & 0x2D;
137
if ((0x6996 >> tmp) & 0x01)
147
var3 = (var2 << 1) - var1;
149
ax = (uint16_t)((((int32_t)var3) * ((int32_t)bx)) >> 15);
153
sink_put(consumer, (int8_t)(var2 >> sample_shift));
157
else silence(consumer, l);
159
else if (l) /* Non-zero sound length check */
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)
167
/* Simply copy prepared pattern from the voice data */
168
do sink_put(consumer, script->voice->samples[sidx++]);
169
while ((--scnt) && (--l));
173
/* Make a transition of a prepared pattern */
176
k = script->icb[stage].stretch;
179
sink_put(consumer, script->voice->samples[sidx++]);
182
while ((--k) && (--scnt));
184
l -= silence(consumer, k);
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];
194
/* Mixed and transitional sounds */
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]);
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;
213
while ((--k) && (--scnt));
215
dx += silence(consumer, k);
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];
227
/* Flush output buffer */
228
sink_flush(consumer);