11 #include "Vocab_Special.h"
12 #include "Vocab_US_Large.h"
16 #define LENGT_OF_FLOAT_STRING 14
29 TalkiePCM(Print& out,
int channelCount = 1) {
31 channels = channelCount;
38 void say(
const uint8_t* address) {
45 int samples = 8000 * ms / 1000;
46 for (
int j = 0; j < samples; j++) {
51 void sayPause() {
say(spPAUSE1); }
53 void sayDigit(
char aDigit) {
return sayNumber(aDigit -
'0'); }
55 void sayVoltageMilliVolts(
long aMilliVolt) {
61 void sayVoltageVolts(
float aVolt) {
62 sayFloat(aVolt, 2,
true,
true);
76 }
else if (aNumber == 0) {
79 if (aNumber >= 1000) {
80 int thousands = aNumber / 1000;
84 if ((aNumber > 0) && (aNumber < 100))
say(sp2_AND);
87 int hundreds = aNumber / 100;
91 if (aNumber > 0)
say(sp2_AND);
94 int tens = aNumber / 10;
199 void sayFloat(
float aFloat,
int aDecimalPlaces,
bool aSuppressLeadingZero,
200 bool aSuppressTrailingZero) {
202 long tIntegerPart = aFloat;
203 if (tIntegerPart != 0 || !aSuppressLeadingZero) {
206 if (aDecimalPlaces > 0) {
209 char tFloatString[LENGT_OF_FLOAT_STRING];
210 dtostrf(aFloat, 8, aDecimalPlaces, tFloatString);
213 for (i = 0; i < (LENGT_OF_FLOAT_STRING - 1); ++i) {
214 if (tFloatString[i] ==
'.') {
220 if (i < LENGT_OF_FLOAT_STRING - 2) {
222 for (
int j = 0; j < aDecimalPlaces; ++j) {
224 if (!(tFloatString[i] ==
'0' && aSuppressTrailingZero &&
225 j == aDecimalPlaces - 1)) {
229 if (tFloatString[i] ==
'\0') {
258 Print* p_print =
nullptr;
260 uint16_t channels = 1;
261 bool isOutputText =
false;
262 const uint8_t* ptrAddr =
nullptr;
265 int16_t synthK1, synthK2;
266 int8_t synthK3, synthK4, synthK5, synthK6, synthK7, synthK8, synthK9,
269 void (*data_callback)(int16_t* data,
int len) =
nullptr;
271 uint8_t tmsEnergy[0x10] = {0x00, 0x02, 0x03, 0x04, 0x05, 0x07, 0x0a, 0x0f,
272 0x14, 0x20, 0x29, 0x39, 0x51, 0x72, 0xa1, 0xff};
273 uint8_t tmsPeriod[0x40] = {
274 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
275 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
276 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2D, 0x2F, 0x31, 0x33,
277 0x35, 0x36, 0x39, 0x3B, 0x3D, 0x3F, 0x42, 0x45, 0x47, 0x49, 0x4D,
278 0x4F, 0x51, 0x55, 0x57, 0x5C, 0x5F, 0x63, 0x66, 0x6A, 0x6E, 0x73,
279 0x77, 0x7B, 0x80, 0x85, 0x8A, 0x8F, 0x95, 0x9A, 0xA0};
280 uint16_t tmsK1[0x20] = {
281 0x82C0, 0x8380, 0x83C0, 0x8440, 0x84C0, 0x8540, 0x8600, 0x8780,
282 0x8880, 0x8980, 0x8AC0, 0x8C00, 0x8D40, 0x8F00, 0x90C0, 0x92C0,
283 0x9900, 0xA140, 0xAB80, 0xB840, 0xC740, 0xD8C0, 0xEBC0, 0x0000,
284 0x1440, 0x2740, 0x38C0, 0x47C0, 0x5480, 0x5EC0, 0x6700, 0x6D40};
285 uint16_t tmsK2[0x20] = {
286 0xAE00, 0xB480, 0xBB80, 0xC340, 0xCB80, 0xD440, 0xDDC0, 0xE780,
287 0xF180, 0xFBC0, 0x0600, 0x1040, 0x1A40, 0x2400, 0x2D40, 0x3600,
288 0x3E40, 0x45C0, 0x4CC0, 0x5300, 0x5880, 0x5DC0, 0x6240, 0x6640,
289 0x69C0, 0x6CC0, 0x6F80, 0x71C0, 0x73C0, 0x7580, 0x7700, 0x7E80};
290 uint8_t tmsK3[0x10] = {0x92, 0x9F, 0xAD, 0xBA, 0xC8, 0xD5, 0xE3, 0xF0,
291 0xFE, 0x0B, 0x19, 0x26, 0x34, 0x41, 0x4F, 0x5C};
292 uint8_t tmsK4[0x10] = {0xAE, 0xBC, 0xCA, 0xD8, 0xE6, 0xF4, 0x01, 0x0F,
293 0x1D, 0x2B, 0x39, 0x47, 0x55, 0x63, 0x71, 0x7E};
294 uint8_t tmsK5[0x10] = {0xAE, 0xBA, 0xC5, 0xD1, 0xDD, 0xE8, 0xF4, 0xFF,
295 0x0B, 0x17, 0x22, 0x2E, 0x39, 0x45, 0x51, 0x5C};
296 uint8_t tmsK6[0x10] = {0xC0, 0xCB, 0xD6, 0xE1, 0xEC, 0xF7, 0x03, 0x0E,
297 0x19, 0x24, 0x2F, 0x3A, 0x45, 0x50, 0x5B, 0x66};
298 uint8_t tmsK7[0x10] = {0xB3, 0xBF, 0xCB, 0xD7, 0xE3, 0xEF, 0xFB, 0x07,
299 0x13, 0x1F, 0x2B, 0x37, 0x43, 0x4F, 0x5A, 0x66};
300 uint8_t tmsK8[0x08] = {0xC0, 0xD8, 0xF0, 0x07, 0x1F, 0x37, 0x4F, 0x66};
301 uint8_t tmsK9[0x08] = {0xC0, 0xD4, 0xE8, 0xFC, 0x10, 0x25, 0x39, 0x4D};
302 uint8_t tmsK10[0x08] = {0xCD, 0xDF, 0xF1, 0x04, 0x16, 0x20, 0x3B, 0x4D};
303 uint8_t chirp[CHIRP_SIZE] = {
304 0x00, 0x2a, 0xd4, 0x32, 0xb2, 0x12, 0x25, 0x14, 0x02, 0xe1, 0xc5,
305 0x02, 0x5f, 0x5a, 0x05, 0x0f, 0x26, 0xfc, 0xa5, 0xa5, 0xd6, 0xdd,
306 0xdc, 0xfc, 0x25, 0x2b, 0x22, 0x21, 0x0f, 0xff, 0xf8, 0xee, 0xed,
307 0xef, 0xf7, 0xf6, 0xfa, 0x00, 0x03, 0x02, 0x01};
308 int16_t nextSample = 0;
309 uint8_t periodCounter = 0;
312 void wait() { calculateSamples(); }
314 void setPtr(
const uint8_t* addr) {
321 uint8_t rev(uint8_t a) {
323 a = (a >> 4) | (a << 4);
325 a = ((a & 0xcc) >> 2) | ((a & 0x33) << 2);
327 a = ((a & 0xaa) >> 1) | ((a & 0x55) << 1);
332 uint8_t getBits(uint8_t bits) {
334 if (ptrAddr ==
nullptr)
return 0;
337 data = rev(*(ptrAddr)) << 8;
338 if (ptrBit + bits > 8) {
339 data |= rev(*(ptrAddr + 1));
342 value = data >> (16 - bits);
351 int clip(
int value,
int min,
int max) {
352 if (value < min)
return min;
353 if (value > max)
return max;
357 void writeSample(int16_t sample) {
361 outSample = clip(
static_cast<int>(sample) << 6, -32768, 32767);
363 outSample = clip(volume * (
static_cast<int>(sample) << 6), -32768, 32767);
367 int16_t out[channels] = {0};
368 for (
int j = 0; j < channels; j++) out[j] = outSample;
369 data_callback(out, channels);
377 for (
int j = 0; j < channels; j++) {
378 if (j > 0) p_print->print(
", ");
379 p_print->print(outSample);
383 int16_t out[channels] = {0};
384 for (
int j = 0; j < channels; j++) out[j] = outSample;
385 p_print->write((uint8_t*)&(out[0]),
sizeof(out));
401 void processEnergy(uint16_t synthEnergy) {
405 writeSample(nextSample);
409 if (periodCounter < synthPeriod) {
414 if (periodCounter < CHIRP_SIZE) {
415 u[10] = ((chirp[periodCounter]) * (uint32_t)synthEnergy) >> 8;
421 static uint16_t synthRand = 1;
422 synthRand = (synthRand >> 1) ^ ((synthRand & 1) ? 0xB800 : 0);
423 u[10] = (synthRand & 1) ? synthEnergy : -synthEnergy;
426 u[9] = u[10] - (((int16_t)synthK10 * x[9]) >> 7);
427 u[8] = u[9] - (((int16_t)synthK9 * x[8]) >> 7);
428 u[7] = u[8] - (((int16_t)synthK8 * x[7]) >> 7);
429 u[6] = u[7] - (((int16_t)synthK7 * x[6]) >> 7);
430 u[5] = u[6] - (((int16_t)synthK6 * x[5]) >> 7);
431 u[4] = u[5] - (((int16_t)synthK5 * x[4]) >> 7);
432 u[3] = u[4] - (((int16_t)synthK4 * x[3]) >> 7);
433 u[2] = u[3] - (((int16_t)synthK3 * x[2]) >> 7);
434 u[1] = u[2] - (((int32_t)synthK2 * x[1]) >> 15);
435 u[0] = u[1] - (((int32_t)synthK1 * x[0]) >> 15);
438 u[0] = clip(u[0], -512, 511);
441 x[9] = x[8] + (((int16_t)synthK9 * u[8]) >> 7);
442 x[8] = x[7] + (((int16_t)synthK8 * u[7]) >> 7);
443 x[7] = x[6] + (((int16_t)synthK7 * u[6]) >> 7);
444 x[6] = x[5] + (((int16_t)synthK6 * u[5]) >> 7);
445 x[5] = x[4] + (((int16_t)synthK5 * u[4]) >> 7);
446 x[4] = x[3] + (((int16_t)synthK4 * u[3]) >> 7);
447 x[3] = x[2] + (((int16_t)synthK3 * u[2]) >> 7);
448 x[2] = x[1] + (((int32_t)synthK2 * u[1]) >> 15);
449 x[1] = x[0] + (((int32_t)synthK1 * u[0]) >> 15);
456 void calculateSamples() {
458 uint16_t synthEnergy = 0;
466 }
else if (energy == 0xf) {
480 synthEnergy = tmsEnergy[energy];
481 bool repeat = getBits(1);
482 synthPeriod = tmsPeriod[getBits(6)];
486 synthK1 = tmsK1[getBits(5)];
487 synthK2 = tmsK2[getBits(5)];
488 synthK3 = tmsK3[getBits(4)];
489 synthK4 = tmsK4[getBits(4)];
492 synthK5 = tmsK5[getBits(4)];
493 synthK6 = tmsK6[getBits(4)];
494 synthK7 = tmsK7[getBits(4)];
495 synthK8 = tmsK8[getBits(3)];
496 synthK9 = tmsK9[getBits(3)];
497 synthK10 = tmsK10[getBits(3)];
502 for (
int j=0;j<200;j++)
503 processEnergy(synthEnergy);
504 }
while (energy != 0xf);
Talkie is a software implementation of the Texas Instruments speech synthesis architecture (Linear Pr...
Definition: TalkiePCM.h:25
void setOutput(Print &out)
Defines the Arduino data target.
Definition: TalkiePCM.h:240
void silence(uint16_t ms)
outputs silence for the indicated milliseconds
Definition: TalkiePCM.h:44
void setDataCallback(void(*cb)(int16_t *data, int len))
Defines the data callback that receives the generated samples.
Definition: TalkiePCM.h:244
void setOutputAsText(bool flag)
converts samples to csv string format
Definition: TalkiePCM.h:35
void say(const uint8_t *address)
converts the provided word into samples
Definition: TalkiePCM.h:38
void setChannels(uint16_t ch)
Definition: TalkiePCM.h:250
void sayNumber(long aNumber)
say any number between -999,999 and 999,999
Definition: TalkiePCM.h:72
void setVolume(float vol)
Definition: TalkiePCM.h:254