Arduino SAM
All Classes Files Functions Enumerations Pages
sam_arduino.h
Go to the documentation of this file.
1 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15 #include <string.h>
16 #include "sam_arduino_out.h"
17 #include "SamData.h"
18 
19 
24 class SAM {
25 
26  public:
28  enum Voice {
29  Elf,
30  LittleRobot,
31  StuffyGuy,
32  LittleOldLaydy,
33  ExtraTerrestrial,
34  Sam,
35  };
36 
38  SAM(){
39  SAM_LOG("SAM");
40  setOutput(new SAMPrintStream(Serial));
41  setVoice(Sam);
42  }
43 
45  SAM(sam_callback cb){
46  SAM_LOG("SAM callback");
47  setOutput(new SAMOutputCallback(cb));
48  setVoice(Sam);
49  }
50 
52  SAM(Print &stream, bool as_text=false){
53  SAM_LOG("SAM Stream");
54  if (as_text){
55  setOutput(new SAMPrintStream(stream));
56  } else {
57  setOutput(new SAMOutputStream(stream));
58  }
59  setVoice(Sam);
60  }
61 
64  SAM_LOG("SAM SAMOutputBase");
65  setOutput(&out);
66  setVoice(Sam);
67  }
68 
71  SAM_LOG("SAM SAMOutputBase");
72  setOutput(out);
73  setVoice(Sam);
74  }
75 
76 #if defined(ESP32) && LEGACY_ESP_I2S
78  SAM(i2s_port_t i2s_num){
79  SAM_LOG("SAM i2s");
80  setOutput(new SAMOutputI2S(i2s_num));
81  setVoice(Sam);
82  }
83 #endif
84 
89  ~SAM(){
90  SAM_LOG("~SAM");
91  end();
92  }
93 
94  void setPitch(uint8_t pitch) {
95  SetPitch(pitch);
96  }
97 
98  void setSpeed(uint8_t speed) {
99  SetSpeed(speed);
100  }
101 
102  void setMouth(uint8_t mouth) {
103  SetMouth(mouth);
104  }
105 
106  void setThroat(uint8_t th) {
107  SetThroat(th);
108  }
109 
110  void setSingMode(bool sing){
111  EnableSingmode(sing);
112  }
113 
124  void setVoice(Voice voice) {
125  SAM_LOG("setVoice: %d", voice);
126  switch(voice) {
127  case Elf:
128  setSpeed(72);
129  setPitch(64);
130  setThroat(110);
131  setMouth(160);
132  break;
133  case LittleRobot:
134  setSpeed(92);
135  setPitch(60);
136  setThroat(190);
137  setMouth(190);
138  break;
139  case StuffyGuy:
140  setSpeed(82);
141  setPitch(72);
142  setThroat(110);
143  setMouth(105);
144  break;
145  case LittleOldLaydy:
146  setSpeed(82);
147  setPitch(32);
148  setThroat(145);
149  setMouth(145);
150  break;
151  case ExtraTerrestrial:
152  setSpeed(100);
153  setPitch(64);
154  setThroat(150);
155  setMouth(200);
156  break;
157  case Sam:
158  setSpeed(72);
159  setPitch(64);
160  setThroat(128);
161  setMouth(128);
162  break;
163  }
164  };
165 
167  bool say(const char* text){
168  SAM_LOG("say: %s",text);
169  return textToSpeach(text, false);
170  }
171 
173  bool sayPhone(const char* text){
174  SAM_LOG("sayPhone: %s",text);
175  return textToSpeach(text, true);
176  }
177 
180  return arduino_output;
181  }
182 
184  void end() {
185  SAM_LOG("end");
186  if(arduino_output!=nullptr && arduino_output->isOpen()){
187  arduino_output->close();
188  }
189  }
190 
192  void setOutputChannels(int channel_count){
193  SAM_LOG("setOutputChannels: %d", channel_count);
194  if (channel_count > 0){
195  // fixed channels are not enforced
196  this->channel_count = channel_count;
197  arduino_output->setChannels(channel_count);
198  } else {
199  SAM_LOG("Channels is not supported for this output type");
200  }
201  }
202 
203 
205  static int sampleRate() {
206  return SAMOutputBase::sampleRate();
207  }
208 
211  return bits_per_sample;
212  }
213 
215  int channels() {
216  return channel_count;
217  }
218 
220  void setVolume(uint8_t volPercent){
221  volume = static_cast<float>(volPercent) / 100.0;
222  if (volPercent> 100) volume = 1.0;
223  }
224 
225  protected:
226  SAMOutputBase *arduino_output=nullptr;
227  int bits_per_sample = 16;
228  int channel_count = 1;
229  float volume = 1.0;
230 
232  static void outputByteCallback(void *cbdata, unsigned char b) {
233  SAM_LOG("outputByteCallback: %d", b);
234 
235  SAM *sam = static_cast<SAM*>(cbdata);
236  sam->write(b);
237  }
238 
239  void setOutput(SAMOutputBase *out){
240  SAM_LOG("setOutput");
241  arduino_output = out;
242 
243  // synchronize channels definition with arduino_output: I2S must be 2 therefore we try to get it from arduino_output first
244  if (arduino_output->channels()!=-1){
245  this->channel_count = arduino_output->channels();
246  } else {
247  arduino_output->setChannels(channel_count);
248  }
249  SAM_LOG("-> channel_count: %d",this->channel_count);
250  SAM_LOG("-> bits_per_sample: %d",this->bits_per_sample);
251  }
252 
254  void write(uint8_t in) {
255  SAM_LOG("SAM::write bps:%d / channels:%d",bits_per_sample, channel_count);
256  int16_t data[channel_count];
257  int16_t sample = in;
258  // convert unsinged 8 bit to signed 16 bits
259  sample -= 128;
260  sample *= 128;
261  // apply volume
262  sample = sample * volume;
263  // mono to stereo
264  for (int j = 0; j<channel_count; j++){
265  data[j] = sample;
266  }
267  arduino_output->write((byte*)data, sizeof(data));
268  // SAM_LOG("writing to %s", arduino_output->name());
269  }
270 
271  bool textToSpeach(const char *str, bool is_phonetic) {
272  SAM_LOG("textToSpeach: %s",str);
273 
274  if (!str || strlen(str)>254) return false; // Only can speak up to 1 page worth of data...
275  samdata = new SamData();
276  if (samdata == nullptr){
277  // allocation failed!
278  return false;
279  }
280  arduino_output->open();
281 
282  // Input massaging
283  char input[256];
284  for (int i=0; str[i]; i++)
285  input[i] = toupper((int)str[i]);
286  input[strlen(str)] = 0;
287  SAM_LOG("input copied");
288 
289  // To phonemes
290  if (is_phonetic) {
291  strncat(input, "\x9b", 255);
292  } else {
293  SAM_LOG("TextToPhonemes");
294  strncat(input, "[", 255);
295  if (!TextToPhonemes(input)) return false; // ERROR
296  }
297  // Say it!
298  SAM_LOG("SetInput: %s", input);
299  SetInput(input);
300 
301  SAM_LOG("SAMMain");
302  SAMMain(outputByteCallback, (void*)this);
303  SAM_LOG("SAMMain - done");
304 
305  // close the processing
306  SAM_LOG("SAM done!");
307  arduino_output->close();
308 
309  // Release SamData
310  delete samdata;
311 
312  return true;
313  }
314 };
315 
316 void printLog(char* msg){
317  Serial.println(msg);
318 }
319 
324 struct PitchedStr {
325  int pitch;
326  char* str;
327 };
Arduino API for SAM Text to Speach Engine.
Definition: sam_arduino.h:24
SAM()
Constructor - for text output to Serial.
Definition: sam_arduino.h:38
void setOutputChannels(int channel_count)
Defines the number of output channels (default 1)
Definition: sam_arduino.h:192
~SAM()
Destroy the SAM object.
Definition: sam_arduino.h:89
static void outputByteCallback(void *cbdata, unsigned char b)
Used to feed the audio result back to this class.
Definition: sam_arduino.h:232
void setVoice(Voice voice)
Set the Voice object DESCRIPTION SPEED PITCH THROAT MOUTH Elf 72 64 110 160 Little Robot 92 60 190 19...
Definition: sam_arduino.h:124
SAM(i2s_port_t i2s_num)
Deactivated: Legacy Constructor - for obsolete ESP32 I2S.
Definition: sam_arduino.h:78
SAMOutputBase * getOutput()
provides access to output information
Definition: sam_arduino.h:179
void write(uint8_t in)
Writes the data to the output. The data is provided on 1 channel as unsinged byte of int16 values.
Definition: sam_arduino.h:254
bool say(const char *text)
Process text input.
Definition: sam_arduino.h:167
SAM(SAMOutputBase &out)
Constructor - for output with a SAMOutputBase class.
Definition: sam_arduino.h:63
bool sayPhone(const char *text)
Process text input.
Definition: sam_arduino.h:173
void end()
Delete voice and cst_audio_streaming_info.
Definition: sam_arduino.h:184
SAM(sam_callback cb)
Constructor - for output to callback.
Definition: sam_arduino.h:45
SAM(Print &stream, bool as_text=false)
Constructor - for output to a stream.
Definition: sam_arduino.h:52
SAM(SAMOutputBase *out)
Constructor - for output with a SAMOutputBase class.
Definition: sam_arduino.h:70
static int sampleRate()
Provides the sample rate (44100)
Definition: sam_arduino.h:205
int channels()
Provides the number of channels.
Definition: sam_arduino.h:215
void setVolume(uint8_t volPercent)
set the Volume range 0-100;
Definition: sam_arduino.h:220
Voice
SAM Voices.
Definition: sam_arduino.h:28
int bitsPerSample()
Provides the bits per sample.
Definition: sam_arduino.h:210
Base Output Class with common functionality.
Definition: sam_arduino_out.h:32
Output via Callback method.
Definition: sam_arduino_out.h:78
Output to I2S for ESP32: This class is obsolete and has been deactivated in the sam_config....
Definition: sam_arduino_out.h:116
Output to Arduino Stream.
Definition: sam_arduino_out.h:248
Write readable string to Arduino Stream.
Definition: sam_arduino_out.h:276
string and pitch - this can be used to build a song
Definition: sam_arduino.h:324