Skip to content

Commit a0a9eaa

Browse files
committed
Speech: Trim some surplus length off data structures. Now use less than 2k of heap.
1 parent c33b256 commit a0a9eaa

File tree

6 files changed

+57
-41
lines changed

6 files changed

+57
-41
lines changed

source/lib/sam/reciter.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,15 @@ int TextToPhonemes(reciter_memory* mem) // Code36484
7373
mem->inputtemp[X] = A;
7474
X++;
7575
Y++;
76-
} while (Y != 255);
76+
} while (Y != INPUT_PHONEMES-1);
7777

78-
79-
X = 255;
80-
mem->inputtemp[X] = 27;
81-
mem61 = 255;
78+
mem->inputtemp[INPUT_PHONEMES-1] = 27;
79+
mem61 = 255; // -1
8280

8381

8482
pos36550:
8583
A = 255;
86-
mem56 = 255;
84+
mem56 = 255; // -1
8785

8886

8987
pos36554:

source/lib/sam/reciter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
//int TextToPhonemes(char *input, char *output);
55

66
typedef struct _reciter_memory {
7-
char input[256];
8-
unsigned char inputtemp[256]; // secure copy of input tab36096
7+
char input[128];
8+
unsigned char inputtemp[128]; // secure copy of input tab36096
99
} reciter_memory;
1010

1111
int TextToPhonemes(reciter_memory *mem);

source/lib/sam/render.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ do
404404
phase2--;
405405
} while(phase2 != 0);
406406
mem44++;
407-
} while(mem44 != 0);
407+
} while(mem44 != RENDER_FRAMES);
408408

409409

410410
// -------------------
@@ -708,7 +708,7 @@ do
708708
if (!sam->common.singmode)
709709
{
710710
// iterate through the buffer
711-
for(i=0; i<256; i++) {
711+
for(i=0; i<RENDER_FRAMES; i++) {
712712
// subtract half the frequency of the formant 1.
713713
// this adds variety to the voice
714714
sam->render.pitch[i] -= (sam->render.freq_amp[i].freq1 >> 1);
@@ -727,7 +727,7 @@ do
727727
//
728728

729729
//amplitude rescaling
730-
for(i=255; i>=0; i--)
730+
for(i=RENDER_FRAMES-1; i>=0; i--)
731731
{
732732
sam->render.freq_amp[i].amp1 = amplitudeRescale[sam->render.freq_amp[i].amp1];
733733
sam->render.freq_amp[i].amp2 = amplitudeRescale[sam->render.freq_amp[i].amp2];
@@ -742,7 +742,7 @@ do
742742

743743
if (debug)
744744
{
745-
PrintOutput(sam->render.flags, sam->render.freq_amp, sam->render.pitch);
745+
PrintOutput(sam->render.flags, sam->render.freq_amp, sam->render.pitch, mem48);
746746
}
747747

748748
// PROCESS THE FRAMES

source/lib/sam/sam.c

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include "render.h"
77
#include "SamTabs.h"
88

9-
//standard sam sound
109
extern int debug;
1110

1211
const unsigned char mem59=0;
@@ -19,11 +18,8 @@ int bufferpos=0;
1918

2019
void SetInput(sam_memory* sam, const char *_input, unsigned int l)
2120
{
22-
int i;
23-
if (l > 254) l = 254;
24-
for(i=0; i<l; i++)
25-
sam->prepare.input[i] = _input[i];
26-
sam->prepare.input[l] = 0;
21+
sam->prepare.input = _input;
22+
sam->prepare.input_length = l;
2723
}
2824

2925
void Init(sam_memory* sam);
@@ -76,19 +72,19 @@ void Init(sam_memory* sam)
7672
ampl3data = &mem[45456];
7773
*/
7874

79-
for(i=0; i<256; i++)
75+
for(i=0; i<INPUT_PHONEMES; i++)
8076
{
8177
sam->prepare.phoneme_input[i].stress = 0;
8278
sam->prepare.phoneme_input[i].length = 0;
8379
}
8480

85-
for(i=0; i<60; i++)
81+
for(i=0; i<OUTPUT_PHONEMES; i++)
8682
{
8783
sam->common.phoneme_output[i].index = 0;
8884
sam->common.phoneme_output[i].stress = 0;
8985
sam->common.phoneme_output[i].length = 0;
9086
}
91-
sam->prepare.phoneme_input[255].index = PHONEME_END; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs
87+
sam->prepare.phoneme_input[INPUT_PHONEMES-1].index = PHONEME_END; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs
9288

9389
}
9490

@@ -194,9 +190,9 @@ void InsertBreath(sam_memory* sam)
194190
if (index == PHONEME_END) return;
195191
mem55 += sam->prepare.phoneme_input[X].length;
196192

197-
if (mem55 < 232)
193+
if (mem55 < RENDER_FRAMES-24)
198194
{
199-
if (index != 254) // ML : Prevents an index out of bounds problem
195+
if (index != PHONEME_END_BREATH) // ML : Prevents an index out of bounds problem
200196
{
201197
A = flags2[index]&1;
202198
if(A != 0)
@@ -287,11 +283,9 @@ void CopyStress(sam_memory* sam)
287283
void Insert(sam_memory* sam, unsigned char position/*var57*/, unsigned char index, unsigned char length, unsigned char stress)
288284
{
289285
int i;
290-
for(i=253; i >= position; i--) // ML : always keep last safe-guarding 255
286+
for(i=INPUT_PHONEMES-3; i >= position; i--) // ML : always keep last safe-guarding.
291287
{
292-
sam->prepare.phoneme_input[i+1].index = sam->prepare.phoneme_input[i].index;
293-
sam->prepare.phoneme_input[i+1].length = sam->prepare.phoneme_input[i].length;
294-
sam->prepare.phoneme_input[i+1].stress = sam->prepare.phoneme_input[i].stress;
288+
sam->prepare.phoneme_input[i] = sam->prepare.phoneme_input[i];
295289
}
296290

297291
sam->prepare.phoneme_input[position].index = index;
@@ -362,27 +356,38 @@ int Parser1(sam_memory* sam)
362356
Y = 0;
363357

364358
// CLEAR THE STRESS TABLE
365-
for(i=0; i<256; i++)
359+
for(i=0; i<INPUT_PHONEMES; i++)
366360
sam->prepare.phoneme_input[i].stress = 0;
367361

368362
// THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
369363
// pos41078:
370364
while(1)
371365
{
372-
// GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
373-
sign1 = sam->prepare.input[X];
374-
// TEST FOR 0 -- END OF STRING MARKER
375-
if (sign1 == 0)
366+
if (position >= INPUT_PHONEMES) {
367+
// Run out of space for phonemes -- This won't happen with a string from the reciter,
368+
// but can happen with manually created phonetic input.
369+
return 0;
370+
}
371+
// TEST FOR END OF STRING
372+
if (X >= sam->prepare.input_length)
376373
{
377374
// MARK ENDPOINT AND RETURN
378375
sam->prepare.phoneme_input[position].index = PHONEME_END; //mark endpoint
379376
// REACHED END OF PHONEMES, SO EXIT
380377
return 1; //all ok
381378
}
382-
379+
380+
// GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
381+
sign1 = sam->prepare.input[X];
382+
383383
// GET THE NEXT CHARACTER FROM THE BUFFER
384384
X++;
385-
sign2 = sam->prepare.input[X];
385+
if (X == sam->prepare.input_length)
386+
{
387+
sign2 = 0;
388+
} else {
389+
sign2 = sam->prepare.input[X];
390+
}
386391

387392
// NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME
388393

source/lib/sam/sam.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,25 @@ enum {
1919
PHONEME_END_BREATH=126
2020
};
2121

22+
#define RENDER_FRAMES 224
23+
24+
#define INPUT_PHONEMES 128
25+
#define OUTPUT_PHONEMES (RENDER_FRAMES/4)
26+
2227
typedef struct _prepare_memory {
23-
char input[256];
24-
phoneme_t phoneme_input[256];
28+
const char *input;
29+
unsigned int input_length;
30+
phoneme_t phoneme_input[INPUT_PHONEMES];
2531
} prepare_memory;
2632

33+
2734
typedef struct _common_memory {
2835
unsigned char speed;
2936
unsigned char pitch;
3037
unsigned char mouth;
3138
unsigned char throat;
3239
int singmode;
33-
phoneme_t phoneme_output[60];
40+
phoneme_t phoneme_output[OUTPUT_PHONEMES];
3441
} common_memory;
3542

3643
typedef struct _render_freq_amp_t {
@@ -43,9 +50,9 @@ typedef struct _render_freq_amp_t {
4350
} render_freq_amp_t;
4451

4552
typedef struct _render_memory {
46-
render_freq_amp_t freq_amp[256];
47-
unsigned char pitch[256];
48-
unsigned char flags[256];
53+
render_freq_amp_t freq_amp[RENDER_FRAMES];
54+
unsigned char pitch[RENDER_FRAMES];
55+
unsigned char flags[RENDER_FRAMES];
4956
} render_memory;
5057

5158
typedef struct _sam_memory {

source/microbit/modspeech.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ static mp_obj_t make_speech_iter(void) {
115115
static mp_obj_t pronounce(mp_obj_t words) {
116116
mp_uint_t len, outlen;
117117
const char *txt = mp_obj_str_get_data(words, &len);
118-
if (len > 254) {
118+
// Reciter truncates *output* at about 120 characters.
119+
// So to avoid that we must disallow any input that will exceed that.
120+
if (len > 80) {
119121
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "text too long."));
120122
}
121123
reciter_memory *mem = m_new(reciter_memory, 1);
@@ -139,6 +141,8 @@ static mp_obj_t pronounce(mp_obj_t words) {
139141
return res;
140142
}MP_DEFINE_CONST_FUN_OBJ_1(pronounce_obj, pronounce);
141143

144+
extern int debug;
145+
142146
static mp_obj_t say(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
143147

144148
static const mp_arg_t allowed_args[] = {
@@ -147,6 +151,7 @@ static mp_obj_t say(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
147151
{ MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPEED} },
148152
{ MP_QSTR_mouth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_MOUTH} },
149153
{ MP_QSTR_throat, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_THROAT} },
154+
{ MP_QSTR_debug, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
150155
};
151156

152157
// parse args
@@ -162,6 +167,7 @@ static mp_obj_t say(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_arg
162167
sam->common.speed = args[2].u_int;
163168
sam->common.mouth = args[3].u_int;
164169
sam->common.throat = args[4].u_int;
170+
debug = args[5].u_bool;
165171

166172
mp_uint_t len;
167173
const char *input = mp_obj_str_get_data(pos_args[0], &len);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy