├── .gitignore ├── doc └── html │ ├── bc_s.png │ ├── bdwn.png │ ├── doc.png │ ├── open.png │ ├── closed.png │ ├── nav_f.png │ ├── nav_g.png │ ├── nav_h.png │ ├── tab_a.png │ ├── tab_b.png │ ├── tab_h.png │ ├── tab_s.png │ ├── splitbar.png │ ├── sync_off.png │ ├── sync_on.png │ ├── folderopen.png │ ├── folderclosed.png │ ├── search │ ├── search_l.png │ ├── search_m.png │ ├── search_r.png │ ├── classes_0.js │ ├── files_0.js │ ├── pages_0.js │ ├── all_2.js │ ├── all_7.js │ ├── all_8.js │ ├── all_9.js │ ├── all_1.js │ ├── enums_0.js │ ├── functions_2.js │ ├── functions_6.js │ ├── functions_7.js │ ├── all_3.js │ ├── all_0.js │ ├── functions_1.js │ ├── functions_3.js │ ├── all_4.js │ ├── functions_0.js │ ├── functions_4.js │ ├── all_5.js │ ├── pages_1.js │ ├── searchdata.js │ ├── classes_1.js │ ├── nomatches.html │ ├── functions_5.js │ ├── close.svg │ ├── all_0.html │ ├── all_1.html │ ├── all_2.html │ ├── all_3.html │ ├── all_4.html │ ├── all_5.html │ ├── all_6.html │ ├── all_7.html │ ├── all_8.html │ ├── all_9.html │ ├── enums_0.html │ ├── files_0.html │ ├── pages_0.html │ ├── pages_1.html │ ├── classes_0.html │ ├── classes_1.html │ ├── functions_0.html │ ├── functions_1.html │ ├── functions_2.html │ ├── functions_3.html │ ├── functions_4.html │ ├── functions_5.html │ ├── functions_6.html │ ├── functions_7.html │ ├── all_6.js │ ├── mag_sel.svg │ └── search.css │ ├── class_s_a_m_output_base.png │ ├── class_s_a_m_output_i2_s.png │ ├── class_s_a_m_print_stream.png │ ├── class_s_a_m_output_stream.png │ ├── class_s_a_m_output_callback.png │ ├── menudata.js │ ├── functions_enum.html │ ├── menu.js │ ├── pages.html │ ├── struct_pitched_str-members.html │ ├── classes.html │ ├── dir_68267d1309a1af8e8297ef4c3efbcdba.html │ ├── files.html │ ├── functions_func.html │ ├── struct_pitched_str.html │ ├── functions.html │ ├── dynsections.js │ ├── md__p_h_o_n_e_s.html │ ├── annotated.html │ ├── sam__arduino_8h.html │ ├── hierarchy.html │ ├── index.html │ ├── class_s_a_m_output_base-members.html │ ├── tabs.css │ └── class_s_a_m_output_callback-members.html ├── src ├── render.h ├── sam_pgmspace.h ├── reciter.h ├── sam.h ├── sam_debug.h ├── sam_config.h ├── SamData.h ├── sam_debug.c ├── SamTabs.h └── sam_arduino_out.h ├── library.properties ├── examples ├── text_to_speach_stream │ └── text_to_speach_stream.ino ├── text_to_speach_callback │ └── text_to_speach_callback.ino ├── text_to_speach_i2s │ └── text_to_speach_i2s.ino ├── text_to_speach_i2s_analog │ └── text_to_speach_i2s_analog.ino └── sing │ └── sing.ino ├── PHONES.md ├── README.md ├── sing └── SAM.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ -------------------------------------------------------------------------------- /doc/html/bc_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/bc_s.png -------------------------------------------------------------------------------- /doc/html/bdwn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/bdwn.png -------------------------------------------------------------------------------- /doc/html/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/doc.png -------------------------------------------------------------------------------- /doc/html/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/open.png -------------------------------------------------------------------------------- /doc/html/closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/closed.png -------------------------------------------------------------------------------- /doc/html/nav_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/nav_f.png -------------------------------------------------------------------------------- /doc/html/nav_g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/nav_g.png -------------------------------------------------------------------------------- /doc/html/nav_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/nav_h.png -------------------------------------------------------------------------------- /doc/html/tab_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/tab_a.png -------------------------------------------------------------------------------- /doc/html/tab_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/tab_b.png -------------------------------------------------------------------------------- /doc/html/tab_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/tab_h.png -------------------------------------------------------------------------------- /doc/html/tab_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/tab_s.png -------------------------------------------------------------------------------- /doc/html/splitbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/splitbar.png -------------------------------------------------------------------------------- /doc/html/sync_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/sync_off.png -------------------------------------------------------------------------------- /doc/html/sync_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/sync_on.png -------------------------------------------------------------------------------- /doc/html/folderopen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/folderopen.png -------------------------------------------------------------------------------- /doc/html/folderclosed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/folderclosed.png -------------------------------------------------------------------------------- /doc/html/search/search_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/search/search_l.png -------------------------------------------------------------------------------- /doc/html/search/search_m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/search/search_m.png -------------------------------------------------------------------------------- /doc/html/search/search_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/search/search_r.png -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/class_s_a_m_output_base.png -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_i2_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/class_s_a_m_output_i2_s.png -------------------------------------------------------------------------------- /doc/html/class_s_a_m_print_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/class_s_a_m_print_stream.png -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_stream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/class_s_a_m_output_stream.png -------------------------------------------------------------------------------- /doc/html/search/classes_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['pitchedstr_24',['PitchedStr',['../struct_pitched_str.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_callback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pschatzmann/arduino-SAM/HEAD/doc/html/class_s_a_m_output_callback.png -------------------------------------------------------------------------------- /doc/html/search/files_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['sam_5farduino_2eh_31',['sam_arduino.h',['../sam__arduino_8h.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/pages_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['phonetic_20mode_47',['Phonetic Mode',['../md__p_h_o_n_e_s.html',1,'']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['end_2',['end',['../class_s_a_m.html#abd8f41bb5cd03e234a4525f2cda7b2d7',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_7.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['voice_21',['Voice',['../class_s_a_m.html#aed7c08a4d197093d0a5c64847453d1da',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_8.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['write_22',['write',['../class_s_a_m.html#a76afc8eb8c3bc0eec2ca8cdda14998b5',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_9.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['_7esam_23',['~SAM',['../class_s_a_m.html#a2e66c74e52081005cfbb7e5a4ab0e558',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['channels_1',['channels',['../class_s_a_m.html#adc101e2ec76814eb7f1ca9239a19cf2c',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/enums_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['voice_46',['Voice',['../class_s_a_m.html#aed7c08a4d197093d0a5c64847453d1da',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_2.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['end_34',['end',['../class_s_a_m.html#abd8f41bb5cd03e234a4525f2cda7b2d7',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_6.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['write_44',['write',['../class_s_a_m.html#a76afc8eb8c3bc0eec2ca8cdda14998b5',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_7.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['_7esam_45',['~SAM',['../class_s_a_m.html#a2e66c74e52081005cfbb7e5a4ab0e558',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_3.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['getoutput_3',['getOutput',['../class_s_a_m.html#a761d1eae2bd009c3306cf92908a5314a',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /src/render.h: -------------------------------------------------------------------------------- 1 | #ifndef RENDER_H 2 | #define RENDER_H 3 | 4 | void Render(); 5 | void SetMouthThroat(unsigned char mouth, unsigned char throat); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /doc/html/search/all_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['bitspersample_0',['bitsPerSample',['../class_s_a_m.html#af5cf0c4c9c219f04ec31383dafcec6ac',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['channels_33',['channels',['../class_s_a_m.html#adc101e2ec76814eb7f1ca9239a19cf2c',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_3.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['getoutput_35',['getOutput',['../class_s_a_m.html#a761d1eae2bd009c3306cf92908a5314a',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_4.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['outputbytecallback_4',['outputByteCallback',['../class_s_a_m.html#a58fe1a67bfa5317f66f2dfd10dd5aca2',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_0.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['bitspersample_32',['bitsPerSample',['../class_s_a_m.html#af5cf0c4c9c219f04ec31383dafcec6ac',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/functions_4.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['outputbytecallback_36',['outputByteCallback',['../class_s_a_m.html#a58fe1a67bfa5317f66f2dfd10dd5aca2',1,'SAM']]] 4 | ]; 5 | -------------------------------------------------------------------------------- /doc/html/search/all_5.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['phonetic_20mode_5',['Phonetic Mode',['../md__p_h_o_n_e_s.html',1,'']]], 4 | ['pitchedstr_6',['PitchedStr',['../struct_pitched_str.html',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /src/sam_pgmspace.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #if defined(AVR) 4 | #include "avr/pgmspace.h" 5 | #elif __has_include("sys/pgmspace.h.h") 6 | #include "sys/pgmspace.h" 7 | #else 8 | #include "pgmspace.h" 9 | #endif 10 | 11 | //#define PROGMEM 12 | //#define pgm_read_byte(byte) *byte 13 | -------------------------------------------------------------------------------- /src/reciter.h: -------------------------------------------------------------------------------- 1 | #ifndef RECITER_C 2 | #define RECITER_C 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //int TextToPhonemes(char *input, char *output); 9 | 10 | int TextToPhonemes(char *input); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /doc/html/search/pages_1.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['sam_48',['SAM',['../md__s_a_m.html',1,'']]], 4 | ['sam_20_2d_20software_20automatic_20mouth_20_2d_20tiny_20speech_20synthesizer_20_2d_20arduino_20library_49',['SAM - Software Automatic Mouth - Tiny Speech Synthesizer - Arduino Library',['../index.html',1,'']]] 5 | ]; 6 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=tts-SAM 2 | version=0.0.1 3 | author=Phil Schatzmann 4 | maintainer= 5 | sentence=SAM Text to Speach Engine 6 | paragraph=SAM Text to Speach Engine for Arduino 7 | category=Signal Input/Output 8 | url=https://github.com/pschatzmann/arduino-SAM 9 | architectures=* 10 | -------------------------------------------------------------------------------- /examples/text_to_speach_stream/text_to_speach_stream.ino: -------------------------------------------------------------------------------- 1 | #include "sam_arduino.h" 2 | 3 | // as_text=true 4 | SAM sam(Serial,true); 5 | 6 | void setup(){ 7 | Serial.begin(115200); 8 | sam.setVoice(SAM::Sam); 9 | sam.setOutputChannels(1); 10 | } 11 | 12 | 13 | void loop(){ 14 | const char* hallo ="hallo my name is SAM"; 15 | Serial.println(hallo); 16 | sam.say(hallo); 17 | 18 | delay(1000); 19 | } 20 | -------------------------------------------------------------------------------- /doc/html/search/searchdata.js: -------------------------------------------------------------------------------- 1 | var indexSectionsWithContent = 2 | { 3 | 0: "bcegopsvw~", 4 | 1: "ps", 5 | 2: "s", 6 | 3: "bcegosw~", 7 | 4: "v", 8 | 5: "ps" 9 | }; 10 | 11 | var indexSectionNames = 12 | { 13 | 0: "all", 14 | 1: "classes", 15 | 2: "files", 16 | 3: "functions", 17 | 4: "enums", 18 | 5: "pages" 19 | }; 20 | 21 | var indexSectionLabels = 22 | { 23 | 0: "All", 24 | 1: "Classes", 25 | 2: "Files", 26 | 3: "Functions", 27 | 4: "Enumerations", 28 | 5: "Pages" 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/sam.h: -------------------------------------------------------------------------------- 1 | #ifndef SAM_H 2 | #define SAM_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void SetInput(char *_input); 9 | void SetSpeed(unsigned char _speed); 10 | void SetPitch(unsigned char _pitch); 11 | void SetMouth(unsigned char _mouth); 12 | void SetThroat(unsigned char _throat); 13 | void EnableSingmode(int x); 14 | int SAMMain( void (*cb)(void *, unsigned char), void *cbdata ); 15 | int GetBufferLength(); 16 | int SAMPrepare(); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /examples/text_to_speach_callback/text_to_speach_callback.ino: -------------------------------------------------------------------------------- 1 | #include "sam_arduino.h" 2 | 3 | void callback(size_t len, int16_t *data16){ 4 | for (size_t j=0;j 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |
No Matches
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/sam_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | #include "sam_config.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress); 10 | void PrintOutput( 11 | unsigned char *flag, 12 | unsigned char *f1, 13 | unsigned char *f2, 14 | unsigned char *f3, 15 | unsigned char *a1, 16 | unsigned char *a2, 17 | unsigned char *a3, 18 | unsigned char *p); 19 | 20 | void PrintRule(unsigned short offset); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /examples/text_to_speach_i2s/text_to_speach_i2s.ino: -------------------------------------------------------------------------------- 1 | #include "AudioTools.h" // https://github.com/pschatzmann/arduino-audio-tools 2 | #include "sam_arduino.h" 3 | 4 | int channels = 2; 5 | I2SStream out; 6 | SAM sam(out); 7 | 8 | void setup(){ 9 | Serial.begin(115200); 10 | sam.setChannels(channels); 11 | sam.setVoice(SAM::Sam); 12 | 13 | auto cfg = out.defaultConfig(); 14 | cfg.sample_rate = 22050; 15 | cfg.channels = channels; 16 | cfg.bits_per_sample = 16; 17 | out.begin(cfg); 18 | } 19 | 20 | 21 | void loop(){ 22 | sam.say("Can you hear me now?"); 23 | delay(500); 24 | sam.say("I can't hear you!"); 25 | delay(2000); 26 | } -------------------------------------------------------------------------------- /examples/text_to_speach_i2s_analog/text_to_speach_i2s_analog.ino: -------------------------------------------------------------------------------- 1 | #include "AudioTools.h" // https://github.com/pschatzmann/arduino-audio-tools 2 | #include "sam_arduino.h" 3 | 4 | int channels = 2; 5 | AnalogAudioStream out; 6 | SAM sam(out); 7 | 8 | void setup(){ 9 | Serial.begin(115200); 10 | 11 | sam.setChannels(channels); 12 | sam.setVoice(SAM::Sam); 13 | 14 | auto cfg = out.defaultConfig(); 15 | cfg.sample_rate = 22050; 16 | cfg.channels = channels; 17 | cfg.bits_per_sample = 16; 18 | out.begin(cfg); 19 | } 20 | 21 | 22 | void loop(){ 23 | sam.say("Can you hear me now?"); 24 | delay(500); 25 | sam.say("I can't hear you!"); 26 | delay(2000); 27 | } -------------------------------------------------------------------------------- /src/sam_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sam_config.h 3 | * @brief Configuration settings for Arduino 4 | */ 5 | 6 | #pragma once 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define LOG_BUFFER_LEN 512 13 | extern char log_buffer_sam[LOG_BUFFER_LEN]; 14 | void printLog(char* msg); 15 | 16 | // activate/deactivate Logging 17 | #define SAM_LOG_ACTIVE 0 18 | 19 | // activate/deactivate debugging 20 | #define SAM_DEBUG 0 21 | 22 | // generate LOG command only if SAM_LOG_ACTIVE 23 | #if SAM_LOG_ACTIVE 24 | #define SAM_LOG(...) { snprintf(log_buffer_sam, LOG_BUFFER_LEN, __VA_ARGS__); printLog(log_buffer_sam); } 25 | #else 26 | #define SAM_LOG(...) 27 | #endif 28 | 29 | #define LEGACY_ESP_I2S 0 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /doc/html/search/functions_5.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['sam_37',['SAM',['../class_s_a_m.html#a14fc54f233862c3c339abcc16412078c',1,'SAM::SAM()'],['../class_s_a_m.html#abf6e9a6b2e99d553d79fcc9047530785',1,'SAM::SAM(sam_callback cb)'],['../class_s_a_m.html#ac4b451e5894e8141f2943642cb4bd79b',1,'SAM::SAM(Print &stream, bool as_text=false)'],['../class_s_a_m.html#a9ba8ad23a29fb90ac4549fc76bc79d73',1,'SAM::SAM(SAMOutputBase &out)'],['../class_s_a_m.html#ac991209bf69ac96a10e083e40a327764',1,'SAM::SAM(SAMOutputBase *out)'],['../class_s_a_m.html#a6a90bd65bbd8a28975e0537478e3ccde',1,'SAM::SAM(i2s_port_t i2s_num)']]], 4 | ['samplerate_38',['sampleRate',['../class_s_a_m.html#aca811ebb9b52c34129bfa3f735e1cbd3',1,'SAM']]], 5 | ['say_39',['say',['../class_s_a_m.html#a7bbf9c6ef1d3f13f1352c4332ab7ffde',1,'SAM']]], 6 | ['sayphone_40',['sayPhone',['../class_s_a_m.html#ab14c5fc6819aaa8829a16983ca0d9553',1,'SAM']]], 7 | ['setoutputchannels_41',['setOutputChannels',['../class_s_a_m.html#a29716ad3900f5443ccf67c789693e31d',1,'SAM']]], 8 | ['setvoice_42',['setVoice',['../class_s_a_m.html#a61caa881fa69bc7f283d45e8c50b1ca8',1,'SAM']]], 9 | ['setvolume_43',['setVolume',['../class_s_a_m.html#add6ad46a9ef66e8321594a9a62527f97',1,'SAM']]] 10 | ]; 11 | -------------------------------------------------------------------------------- /src/SamData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dataspace.h 3 | * 4 | * Created on: Feb 24, 2019 5 | * Author: chris.l 6 | */ 7 | 8 | #ifndef SAMDATA_H_ 9 | #define SAMDATA_H_ 10 | #define SAMDATA 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef struct s_samdata 17 | { 18 | struct render 19 | { 20 | unsigned char pitches[256]; // tab43008 21 | unsigned char frequency1[256]; 22 | unsigned char frequency2[256]; 23 | unsigned char frequency3[256]; 24 | unsigned char amplitude1[256]; 25 | unsigned char amplitude2[256]; 26 | unsigned char amplitude3[256]; 27 | unsigned char sampledConsonantFlag[256]; // tab44800 28 | } render; 29 | struct reciter { 30 | unsigned char inputtemp[256]; 31 | } reciter; 32 | struct sam 33 | { 34 | char input[256]; //tab39445 35 | unsigned char stress[256]; //numbers from 0 to 8 36 | unsigned char phonemeLength[256]; //tab40160 37 | unsigned char phonemeindex[256]; 38 | unsigned char phonemeIndexOutput[60]; //tab47296 39 | unsigned char stressOutput[60]; //tab47365 40 | unsigned char phonemeLengthOutput[60]; //tab47416 41 | } sam; 42 | } SamData; 43 | 44 | extern SamData* samdata; 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | 51 | 52 | #endif /* SAMDATA_H_ */ 53 | -------------------------------------------------------------------------------- /doc/html/search/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /doc/html/search/all_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/all_9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/enums_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/files_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/pages_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/pages_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/classes_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/classes_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/html/search/functions_7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
Loading...
13 |
14 | 19 |
Searching...
20 |
No Matches
21 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /PHONES.md: -------------------------------------------------------------------------------- 1 | # Phonetic Mode 2 | 3 | ``` 4 | 5 | VOWELS VOICED CONSONANTS 6 | IY f(ee)t R red 7 | IH p(i)n L allow 8 | EH beg W away 9 | AE Sam W whale 10 | AA pot Y you 11 | AH b(u)dget M Sam 12 | AO t(al)k N man 13 | OH cone NX so(ng) 14 | UH book B bad 15 | UX l(oo)t D dog 16 | ER bird G again 17 | AX gall(o)n J judge 18 | IX dig(i)t Z zoo 19 | ZH plea(s)ure 20 | DIPHTHONGS V seven 21 | EY m(a)de DH (th)en 22 | AY h(igh) 23 | OY boy 24 | AW h(ow) UNVOICED CONSONANTS 25 | OW slow S Sam 26 | UW crew Sh fish 27 | F fish 28 | TH thin 29 | SPECIAL PHONEMES P poke 30 | UL sett(le) (=AXL) T talk 31 | UM astron(omy) (=AXM) K cake 32 | UN functi(on) (=AXN) CH speech 33 | Q kitt-en (glottal stop) /H a(h)ead 34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /doc/html/menudata.js: -------------------------------------------------------------------------------- 1 | /* 2 | @licstart The following is the entire license notice for the JavaScript code in this file. 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (C) 1997-2020 by Dimitri van Heesch 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 9 | and associated documentation files (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or 15 | substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | @licend The above is the entire license notice for the JavaScript code in this file 24 | */ 25 | var menudata={children:[ 26 | {text:"Main Page",url:"index.html"}, 27 | {text:"Related Pages",url:"pages.html"}, 28 | {text:"Classes",url:"annotated.html",children:[ 29 | {text:"Class List",url:"annotated.html"}, 30 | {text:"Class Index",url:"classes.html"}, 31 | {text:"Class Hierarchy",url:"hierarchy.html"}, 32 | {text:"Class Members",url:"functions.html",children:[ 33 | {text:"All",url:"functions.html"}, 34 | {text:"Functions",url:"functions_func.html"}, 35 | {text:"Enumerations",url:"functions_enum.html"}]}]}, 36 | {text:"Files",url:"files.html",children:[ 37 | {text:"File List",url:"files.html"}]}]} 38 | -------------------------------------------------------------------------------- /doc/html/search/all_6.js: -------------------------------------------------------------------------------- 1 | var searchData= 2 | [ 3 | ['sam_7',['SAM',['../md__s_a_m.html',1,'(Global Namespace)'],['../class_s_a_m.html',1,'SAM'],['../class_s_a_m.html#a6a90bd65bbd8a28975e0537478e3ccde',1,'SAM::SAM(i2s_port_t i2s_num)'],['../class_s_a_m.html#ac991209bf69ac96a10e083e40a327764',1,'SAM::SAM(SAMOutputBase *out)'],['../class_s_a_m.html#a9ba8ad23a29fb90ac4549fc76bc79d73',1,'SAM::SAM(SAMOutputBase &out)'],['../class_s_a_m.html#ac4b451e5894e8141f2943642cb4bd79b',1,'SAM::SAM(Print &stream, bool as_text=false)'],['../class_s_a_m.html#a14fc54f233862c3c339abcc16412078c',1,'SAM::SAM()'],['../class_s_a_m.html#abf6e9a6b2e99d553d79fcc9047530785',1,'SAM::SAM(sam_callback cb)']]], 4 | ['sam_20_2d_20software_20automatic_20mouth_20_2d_20tiny_20speech_20synthesizer_20_2d_20arduino_20library_8',['SAM - Software Automatic Mouth - Tiny Speech Synthesizer - Arduino Library',['../index.html',1,'']]], 5 | ['sam_5farduino_2eh_9',['sam_arduino.h',['../sam__arduino_8h.html',1,'']]], 6 | ['samoutputbase_10',['SAMOutputBase',['../class_s_a_m_output_base.html',1,'']]], 7 | ['samoutputcallback_11',['SAMOutputCallback',['../class_s_a_m_output_callback.html',1,'']]], 8 | ['samoutputi2s_12',['SAMOutputI2S',['../class_s_a_m_output_i2_s.html',1,'']]], 9 | ['samoutputstream_13',['SAMOutputStream',['../class_s_a_m_output_stream.html',1,'']]], 10 | ['samplerate_14',['sampleRate',['../class_s_a_m.html#aca811ebb9b52c34129bfa3f735e1cbd3',1,'SAM']]], 11 | ['samprintstream_15',['SAMPrintStream',['../class_s_a_m_print_stream.html',1,'']]], 12 | ['say_16',['say',['../class_s_a_m.html#a7bbf9c6ef1d3f13f1352c4332ab7ffde',1,'SAM']]], 13 | ['sayphone_17',['sayPhone',['../class_s_a_m.html#ab14c5fc6819aaa8829a16983ca0d9553',1,'SAM']]], 14 | ['setoutputchannels_18',['setOutputChannels',['../class_s_a_m.html#a29716ad3900f5443ccf67c789693e31d',1,'SAM']]], 15 | ['setvoice_19',['setVoice',['../class_s_a_m.html#a61caa881fa69bc7f283d45e8c50b1ca8',1,'SAM']]], 16 | ['setvolume_20',['setVolume',['../class_s_a_m.html#add6ad46a9ef66e8321594a9a62527f97',1,'SAM']]] 17 | ]; 18 | -------------------------------------------------------------------------------- /src/sam_debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sam_config.h" 3 | 4 | char log_buffer_sam[LOG_BUFFER_LEN] = {0}; 5 | extern unsigned char signInputTable1[]; 6 | extern unsigned char signInputTable2[]; 7 | 8 | void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress) 9 | { 10 | int i = 0; 11 | SAM_LOG("==========================================="); 12 | 13 | SAM_LOG("Internal Phoneme presentation:"); 14 | SAM_LOG(" idx phoneme length stress"); 15 | SAM_LOG("------------------------------"); 16 | 17 | while((phonemeindex[i] != 255) && (i < 255)) 18 | { 19 | if (phonemeindex[i] < 81) 20 | { 21 | SAM_LOG(" %3i %c%c %3i %i", 22 | phonemeindex[i], 23 | signInputTable1[phonemeindex[i]], 24 | signInputTable2[phonemeindex[i]], 25 | phonemeLength[i], 26 | stress[i] 27 | ); 28 | } else 29 | { 30 | SAM_LOG(" %3i ?? %3i %i", phonemeindex[i], phonemeLength[i], stress[i]); 31 | } 32 | i++; 33 | } 34 | SAM_LOG("==========================================="); 35 | SAM_LOG(""); 36 | } 37 | 38 | void PrintOutput( 39 | unsigned char *flag, 40 | unsigned char *f1, 41 | unsigned char *f2, 42 | unsigned char *f3, 43 | unsigned char *a1, 44 | unsigned char *a2, 45 | unsigned char *a3, 46 | unsigned char *p) 47 | { 48 | int i = 0; 49 | SAM_LOG("==========================================="); 50 | SAM_LOG("Final data for speech output:"); 51 | SAM_LOG(" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch"); 52 | SAM_LOG("------------------------------------------------"); 53 | while(i < 255) 54 | { 55 | SAM_LOG("%5i %5i %5i %5i %5i %5i %5i %5i", flag[i], a1[i], f1[i], a2[i], f2[i], a3[i], f3[i], p[i]); 56 | i++; 57 | } 58 | SAM_LOG("==========================================="); 59 | 60 | } 61 | 62 | extern unsigned char GetRuleByte(unsigned short mem62, unsigned char Y); 63 | 64 | void PrintRule(unsigned short offset) 65 | { 66 | unsigned char i = 1; 67 | unsigned char A = 0; 68 | SAM_LOG("Applying rule: "); 69 | do 70 | { 71 | A = GetRuleByte(offset, i); 72 | if ((A&127) == '=') { 73 | SAM_LOG(" -> "); 74 | } else{ 75 | SAM_LOG("%c", A&127); 76 | } 77 | i++; 78 | } while ((A&128)==0); 79 | SAM_LOG(""); 80 | } 81 | -------------------------------------------------------------------------------- /doc/html/search/mag_sel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 57 | 63 | 69 | 74 | 75 | -------------------------------------------------------------------------------- /doc/html/functions_enum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class Members - Enumerations 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | 27 | 28 | 29 |
24 |
Arduino SAM 25 |
26 |
30 |
31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
49 | 50 |
54 |
55 | 56 | 57 |
58 | 61 |
62 | 63 |
64 |  
    65 |
  • Voice 66 | : SAM 67 |
  • 68 |
69 |
70 | 71 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SAM - Software Automatic Mouth - Tiny Speech Synthesizer - Arduino Library 2 | 3 | Sam is a very small Text-To-Speech (TTS) program written in C, that runs on most popular platforms. 4 | It is an adaption to C of the speech software SAM (Software Automatic Mouth) for the Commodore C64 published 5 | in the year 1982 by Don't Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme converter called reciter and a Phoneme-To-Speech routine for the final output. It is so small that it will work also on embedded computers. 6 | 7 | I created this project with the intention to provide SAM as Arduino Library which supports different output alternatives: 8 | 9 | - [Output with a callback method](examples/text_to_speach_callback/text_to_speach_callback.ino) 10 | - [Output to a Arduino Stream](examples/text_to_speach_stream/text_to_speach_stream.ino) 11 | 12 | 13 | ## Installation 14 | 15 | You can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with 16 | ``` 17 | cd ~/Documents/Arduino/libraries 18 | git clone pschatzmann/SAM.git 19 | ``` 20 | 21 | ## Documentation 22 | 23 | - [class documentation for the Arduino API ](https://pschatzmann.github.io/arduino-SAM/doc/html/class_s_a_m.html) 24 | - [supported Phonemes](PHONES.md) 25 | - [the original Readme](SAM.md) 26 | - [the manual of the equivalent Apple II program](http://www.apple-iigs.info/newdoc/sam.pdf) 27 | 28 | 29 | ## Voices 30 | 31 | Voices can be defined by setting the speed, pitch, throat and moth parameters: 32 | 33 | ``` 34 | DESCRIPTION SPEED PITCH THROAT MOUTH 35 | Elf 72 64 110 160 36 | Little Robot 92 60 190 190 37 | Stuffy Guy 82 72 110 105 38 | Little Old Lady 82 32 145 145 39 | Extra-Terrestrial 100 64 150 200 40 | SAM 72 64 128 128 41 | ``` 42 | 43 | You can try out some alternative parameter combinations [here](https://discordier.github.io/sam/). 44 | 45 | ## Output Format 46 | 47 | The autput format is as follows: 48 | 49 | - bits per sample: 16 50 | - sample rate: 22050 51 | - channels: 1 52 | 53 | You can change the channels to 2 by calling ```sam.setOutputChannels(2);``` 54 | 55 | ## Memory Requirements 56 | 57 | 58 | | Memory Type | Used | 59 | |--------------------|--------------| 60 | | Progmem | 225'000 | 61 | | Dynamic Memory | 14'000 | 62 | 63 | The requirements have been determined by compiling the project with an ESP32. The values are rounded up! 64 | 65 | 66 | ## License 67 | 68 | The software is a reverse-engineered version of a commercial software published more than 30 years ago. The current copyright holder is SoftVoice, Inc. (www.text2speech.com) 69 | 70 | Any attempt to contact the company failed. The website was last updated in the year 2009. The status of the original software can therefore best described as Abandonware (http://en.wikipedia.org/wiki/Abandonware) 71 | 72 | As long this is the case we cannot put the code under any specific open source software license: Use it at your own risk. 73 | 74 | -------------------------------------------------------------------------------- /doc/html/menu.js: -------------------------------------------------------------------------------- 1 | /* 2 | @licstart The following is the entire license notice for the JavaScript code in this file. 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (C) 1997-2020 by Dimitri van Heesch 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 9 | and associated documentation files (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or 15 | substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | @licend The above is the entire license notice for the JavaScript code in this file 24 | */ 25 | function initMenu(relPath,searchEnabled,serverSide,searchPage,search) { 26 | function makeTree(data,relPath) { 27 | var result=''; 28 | if ('children' in data) { 29 | result+=''; 36 | } 37 | return result; 38 | } 39 | 40 | $('#main-nav').append(makeTree(menudata,relPath)); 41 | $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); 42 | if (searchEnabled) { 43 | if (serverSide) { 44 | $('#main-menu').append('
  • '); 45 | } else { 46 | $('#main-menu').append('
  • '); 47 | } 48 | } 49 | $('#main-menu').smartmenus(); 50 | } 51 | /* @license-end */ 52 | -------------------------------------------------------------------------------- /doc/html/pages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Related Pages 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    Related Pages
    66 |
    67 |
    68 |
    Here is a list of all related documentation pages:
    69 | 70 | 71 | 72 |
     SAM
     Phonetic Mode
    73 |
    74 |
    75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /doc/html/struct_pitched_str-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Member List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 |
    63 |
    64 |
    65 |
    PitchedStr Member List
    66 |
    67 |
    68 | 69 |

    This is the complete list of members for PitchedStr, including all inherited members.

    70 | 71 | 72 | 73 |
    pitch (defined in PitchedStr)PitchedStr
    str (defined in PitchedStr)PitchedStr
    74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /doc/html/classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class Index 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    Class Index
    66 |
    67 |
    68 |
    P | S
    69 | 77 |
    78 | 79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /doc/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: src Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 | 66 |
    67 |
    68 |
    69 |
    src Directory Reference
    70 |
    71 |
    72 | 73 | 75 | 76 | 77 | 78 |

    74 | Files

    file  sam_arduino.h [code]
     Arduino API for SAM.
     
    79 |
    80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /examples/sing/sing.ino: -------------------------------------------------------------------------------- 1 | #include "sam_arduino.h" 2 | 3 | SAM sam(I2S_NUM_0); 4 | const char *hallo = "sam hello my name is SAM. I will sing the national anthem of the united states of america the star spangled banner" 5 | const PitchedStr song[] = { 6 | {64, "ohohoh"}, 7 | {76, "ohohoh"}, 8 | {96 , "sehehehehehehehehehey"}, 9 | {76 , "kaeaeaeaeaeaeaeaeaen"}, 10 | {64 , "yuxuxuxuxuxuxw"}, 11 | {48 , "siyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy"}, 12 | {38 , "baaaaay"}, 13 | {42 , "dhaaaxaxaxax"}, 14 | {48 , "daoaoaoaoaoaoaonz"}, 15 | {76 , "ererererererer"}, 16 | {68 , "liyiyiyiyiyiyiyiyiy"}, 17 | {64 , "laaaaaaaaaaaaaaaaaaaaaaaaayt"}, 18 | {64 , "whahahaht"}, 19 | {64 , "sohohuw"}, 20 | {38 , "praaaaaaaaaaaaaaaauwd"}, 21 | {42 , "liyiyiy"}, 22 | {48 , "wiyiyiyiyiyiyiyiyiy"}, 23 | {51 , "/heheheheheheheheheheheheheheheheheheyld"}, 24 | {56 , "aeaeaeaet"}, 25 | {51 , "dhaaaxaxaxax"}, 26 | {48 , "twaaaaaaaaaaaaaaiy"}, 27 | {48 , "laaaaaaaaaaaaiyts"}, 28 | {64 , "laeaeaeaeaeaeaeaeaest"}, 29 | {76 , "gliyiyiyiyiyiyiyiyiym"}, 30 | {96 , "mihihihihihihihihihihnx"}, 31 | {64 , "/huxuxuxuxuxuxuxuxuxuxwz"}, 32 | {76 , "braoaoaod"}, 33 | {96 , "straaaaaaaaaaaaiyps"}, 34 | {76 , "aeaeaeaeaeaeaeaeaeaend"}, 35 | {64 , "braaaaaaaaaaaaaaiyt"}, 36 | {48 , "staaaaaaaaaaaaaaaaaaaaaaaaaarz"}, 37 | {38 , "thruxuxw"}, 38 | {42 , "dhaaaxaxaxax"}, 39 | {48 , "pehehehehehehehehehehr"}, 40 | {76 , "rixixixixixixixixixixixixl"}, 41 | {68 , "lahahahahahahahahahs"}, 42 | {64 , "faaaaaaaaaaaaaaaaaaaaaaaaaaiyt"}, 43 | {64 , "ohohohr"}, 44 | {64 , "dhaaaxaxaxax"}, 45 | {38 , "raeaeaeaeaeaeaeaeaeaeaeaem"}, 46 | {42 , "paaaarts"}, 47 | {48 , "wiyiyiyiyiyiyiyiyiy"}, 48 | {51 , "waaaaaaaaaaaaaaaaaaaaaaaaaachd"}, 49 | {56 , "werer"}, 50 | {51 , "sohohw"}, 51 | {48 , "gaeaeaeaeaeaeaeaeaeael"}, 52 | {48 , "lixixixixixixixixixixixixixnt"}, 53 | {64 , "liyiyiyiyiyiyiyiyiy"}, 54 | {76 , "striyiyiyiyiyiyiyiyiym"}, 55 | {96 , "mihihihihihihihihihnx"}, 56 | {38 , "aeaeaeaeaend"}, 57 | {38 , "dhaaaxaxaxax"}, 58 | {38 , "raaaaaaaaaaaak"}, 59 | {36 , "kixixixixixixixixixixixts"}, 60 | {32 , "rehehehehehehehehehd"}, 61 | {32 , "gleheheheheheheheheheheheheheheherer"}, 62 | {36 , "dhaaaxaxaxax"}, 63 | {38 , "baaaamz"}, 64 | {42 , "bererererererst"}, 65 | {38 , "tihihihihihihihihihnx"}, 66 | {36 , "ihihihihihihihihihihn"}, 67 | {36 , "eheheheheheheheheheheheheheheheheheyr"}, 68 | {36 , "geheheheyv"}, 69 | {38 , "pruxuxuxuxuxuxuxuxuxuxuxuxwf"}, 70 | {42 , "thruxuxw"}, 71 | {48 , "dhaaaxaxax"}, 72 | {51 , "naaaaaaaaaaaaaaaaaaaaaaayiyt"}, 73 | {56 , "dhaeaeaeaet"}, 74 | {51 , "aaaaaauwr"}, 75 | {48 , "flaeaeaeaeaeaeaeaeaeg"}, 76 | {76 , "wahahahahahahahahahz"}, 77 | {68 , "stihihihihihihihihihl"}, 78 | {64 , "dhehehehehehehehehehehehehehehehehehehehr"}, 79 | {64 , "ohohohohohohow"}, 80 | {48 , "sehehehehehehehehehey"}, 81 | {48 , "dahahahahahahahahahz"}, 82 | {48 , "dhaeaeae"}, 83 | {51 , "aeaeaet"}, 84 | {56 , "staaaaaaaaaaaar"}, 85 | {56 , "spehehehehehehehehehiynx"}, 86 | {56 , "gaxaxaxaxaxaxaxaxaxaxaxaxld"}, 87 | {42 , "baeaeaeaeaeaeaeaeaen"}, 88 | {36 , "nerer"}, 89 | {38 , "ererer"}, 90 | {42 , "yehehehv 91 | {48 , "ehehehehtv 92 | {48 , "weheheheheheheheheheheh"}, 93 | {51 , "ehehehehehehehiyiyiyv"}, 94 | {64 , "ohohohr"}, 95 | {64 , "dhaaaxaxaxax"}, 96 | {48 , "laeaeaeaeaeaeaeaeaeaeaeae"}, 97 | {42 , "aeaeaend"}, 98 | {38 , "ahahahv"}, 99 | {36 , "dhaaaxaxaxax"}, 100 | {32 , "friyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiyiy"}, 101 | {48 , "aeaeaend"}, 102 | {42 , "dhaaaxaxaxax"}, 103 | {38 , "/hohohohohohohohohowm"}, 104 | {36 , "ahahahahv"}, 105 | {42 , "dhaaaxaxaxaxaxaxaxaxaxaxaxaxax"}, 106 | {48 , "brehehehehehehehehehehiyiyiyv"}}; 107 | 108 | 109 | void setup(){ 110 | Serial.begin(115200); 111 | sam.setSingMode(true); 112 | } 113 | 114 | void loop(){ 115 | Serial.println(hallo); 116 | sam.say(hallo); 117 | for (auto rec in song){ 118 | sam.setPitch(rec.pitch) 119 | sam.sayPhone(rec.str); 120 | } 121 | delay(5000); 122 | } -------------------------------------------------------------------------------- /doc/html/files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: File List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    File List
    66 |
    67 |
    68 |
    Here is a list of all documented files with brief descriptions:
    69 |
    [detail level 12]
    70 | 71 | 72 | 73 |
      src
     sam_arduino.hArduino API for SAM
     sam_arduino_out.h
    74 |
    75 |
    76 | 77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /doc/html/functions_func.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class Members - Functions 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |  
      65 |
    • bitsPerSample() 66 | : SAM 67 |
    • 68 |
    • channels() 69 | : SAM 70 |
    • 71 |
    • end() 72 | : SAM 73 |
    • 74 |
    • getOutput() 75 | : SAM 76 |
    • 77 |
    • outputByteCallback() 78 | : SAM 79 |
    • 80 |
    • SAM() 81 | : SAM 82 |
    • 83 |
    • sampleRate() 84 | : SAM 85 |
    • 86 |
    • say() 87 | : SAM 88 |
    • 89 |
    • sayPhone() 90 | : SAM 91 |
    • 92 |
    • setOutputChannels() 93 | : SAM 94 |
    • 95 |
    • setVoice() 96 | : SAM 97 |
    • 98 |
    • setVolume() 99 | : SAM 100 |
    • 101 |
    • write() 102 | : SAM 103 |
    • 104 |
    • ~SAM() 105 | : SAM 106 |
    • 107 |
    108 |
    109 | 110 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /doc/html/struct_pitched_str.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: PitchedStr Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 |
    63 |
    64 | 67 |
    68 |
    PitchedStr Struct Reference
    69 |
    70 |
    71 | 72 |

    string and pitch - this can be used to build a song 73 | More...

    74 | 75 |

    #include <sam_arduino.h>

    76 | 77 | 79 | 81 | 82 | 84 | 85 |

    78 | Public Attributes

    80 | int pitch
     
    83 | char * str
     
    86 |

    Detailed Description

    87 |

    string and pitch - this can be used to build a song

    88 |

    The documentation for this struct was generated from the following file: 91 |
    92 | 93 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /doc/html/functions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class Members 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    Here is a list of all documented class members with links to the class documentation for each member:
      65 |
    • bitsPerSample() 66 | : SAM 67 |
    • 68 |
    • channels() 69 | : SAM 70 |
    • 71 |
    • end() 72 | : SAM 73 |
    • 74 |
    • getOutput() 75 | : SAM 76 |
    • 77 |
    • outputByteCallback() 78 | : SAM 79 |
    • 80 |
    • SAM() 81 | : SAM 82 |
    • 83 |
    • sampleRate() 84 | : SAM 85 |
    • 86 |
    • say() 87 | : SAM 88 |
    • 89 |
    • sayPhone() 90 | : SAM 91 |
    • 92 |
    • setOutputChannels() 93 | : SAM 94 |
    • 95 |
    • setVoice() 96 | : SAM 97 |
    • 98 |
    • setVolume() 99 | : SAM 100 |
    • 101 |
    • Voice 102 | : SAM 103 |
    • 104 |
    • write() 105 | : SAM 106 |
    • 107 |
    • ~SAM() 108 | : SAM 109 |
    • 110 |
    111 |
    112 | 113 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /doc/html/dynsections.js: -------------------------------------------------------------------------------- 1 | /* 2 | @licstart The following is the entire license notice for the JavaScript code in this file. 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (C) 1997-2020 by Dimitri van Heesch 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 9 | and associated documentation files (the "Software"), to deal in the Software without restriction, 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or 15 | substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | @licend The above is the entire license notice for the JavaScript code in this file 24 | */ 25 | function toggleVisibility(linkObj) 26 | { 27 | var base = $(linkObj).attr('id'); 28 | var summary = $('#'+base+'-summary'); 29 | var content = $('#'+base+'-content'); 30 | var trigger = $('#'+base+'-trigger'); 31 | var src=$(trigger).attr('src'); 32 | if (content.is(':visible')===true) { 33 | content.hide(); 34 | summary.show(); 35 | $(linkObj).addClass('closed').removeClass('opened'); 36 | $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); 37 | } else { 38 | content.show(); 39 | summary.hide(); 40 | $(linkObj).removeClass('closed').addClass('opened'); 41 | $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); 42 | } 43 | return false; 44 | } 45 | 46 | function updateStripes() 47 | { 48 | $('table.directory tr'). 49 | removeClass('even').filter(':visible:even').addClass('even'); 50 | } 51 | 52 | function toggleLevel(level) 53 | { 54 | $('table.directory tr').each(function() { 55 | var l = this.id.split('_').length-1; 56 | var i = $('#img'+this.id.substring(3)); 57 | var a = $('#arr'+this.id.substring(3)); 58 | if (l 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Phonetic Mode 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 |
    63 |
    64 |
    65 |
    Phonetic Mode
    66 |
    67 |
    68 |
    VOWELS VOICED CONSONANTS
    69 |
    IY f(ee)t R red
    70 |
    IH p(i)n L allow
    71 |
    EH beg W away
    72 |
    AE Sam W whale
    73 |
    AA pot Y you
    74 |
    AH b(u)dget M Sam
    75 |
    AO t(al)k N man
    76 |
    OH cone NX so(ng)
    77 |
    UH book B bad
    78 |
    UX l(oo)t D dog
    79 |
    ER bird G again
    80 |
    AX gall(o)n J judge
    81 |
    IX dig(i)t Z zoo
    82 |
    ZH plea(s)ure
    83 |
    DIPHTHONGS V seven
    84 |
    EY m(a)de DH (th)en
    85 |
    AY h(igh)
    86 |
    OY boy
    87 |
    AW h(ow) UNVOICED CONSONANTS
    88 |
    OW slow S Sam
    89 |
    UW crew Sh fish
    90 |
    F fish
    91 |
    TH thin
    92 |
    SPECIAL PHONEMES P poke
    93 |
    UL sett(le) (=AXL) T talk
    94 |
    UM astron(omy) (=AXM) K cake
    95 |
    UN functi(on) (=AXN) CH speech
    96 |
    Q kitt-en (glottal stop) /H a(h)ead
    97 |
    98 |
    99 | 100 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /doc/html/annotated.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    Class List
    66 |
    67 |
    68 |
    Here are the classes, structs, unions and interfaces with brief descriptions:
    69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
     CPitchedStrString and pitch - this can be used to build a song
     CSAMArduino API for SAM Text to Speach Engine
     CSAMOutputBaseBase Output Class with common functionality
     CSAMOutputCallbackOutput via Callback method
     CSAMOutputI2SOutput to I2S for ESP32: This class is obsolete and has been deactivated in the sam_config.h since the related API is not longer supported by Espressif. Use the I2S functionality provided by your core or the AudioTools library instread
     CSAMOutputStreamOutput to Arduino Stream
     CSAMPrintStreamWrite readable string to Arduino Stream
    78 |
    79 |
    80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /doc/html/search/search.css: -------------------------------------------------------------------------------- 1 | /*---------------- Search Box */ 2 | 3 | #MSearchBox { 4 | white-space : nowrap; 5 | background: white; 6 | border-radius: 0.65em; 7 | box-shadow: inset 0.5px 0.5px 3px 0px #555; 8 | z-index: 102; 9 | } 10 | 11 | #MSearchBox .left { 12 | display: inline-block; 13 | vertical-align: middle; 14 | height: 1.4em; 15 | } 16 | 17 | #MSearchSelect { 18 | display: inline-block; 19 | vertical-align: middle; 20 | height: 1.4em; 21 | padding: 0 0 0 0.3em; 22 | margin: 0; 23 | } 24 | 25 | #MSearchField { 26 | display: inline-block; 27 | vertical-align: middle; 28 | width: 7.5em; 29 | height: 1.1em; 30 | margin: 0 0.15em; 31 | padding: 0; 32 | line-height: 1em; 33 | border:none; 34 | color: #909090; 35 | outline: none; 36 | font-family: Arial, Verdana, sans-serif; 37 | -webkit-border-radius: 0px; 38 | border-radius: 0px; 39 | background: none; 40 | } 41 | 42 | 43 | #MSearchBox .right { 44 | display: inline-block; 45 | vertical-align: middle; 46 | width: 1.4em; 47 | height: 1.4em; 48 | } 49 | 50 | #MSearchClose { 51 | display: none; 52 | font-size: inherit; 53 | background : none; 54 | border: none; 55 | margin: 0; 56 | padding: 0; 57 | outline: none; 58 | 59 | } 60 | 61 | #MSearchCloseImg { 62 | height: 1.4em; 63 | padding: 0.3em; 64 | margin: 0; 65 | } 66 | 67 | .MSearchBoxActive #MSearchField { 68 | color: #000000; 69 | } 70 | 71 | #main-menu > li:last-child { 72 | /* This
  • object is the parent of the search bar */ 73 | display: flex; 74 | justify-content: center; 75 | align-items: center; 76 | height: 36px; 77 | margin-right: 1em; 78 | } 79 | 80 | /*---------------- Search filter selection */ 81 | 82 | #MSearchSelectWindow { 83 | display: none; 84 | position: absolute; 85 | left: 0; top: 0; 86 | border: 1px solid #90A5CE; 87 | background-color: #F9FAFC; 88 | z-index: 10001; 89 | padding-top: 4px; 90 | padding-bottom: 4px; 91 | -moz-border-radius: 4px; 92 | -webkit-border-top-left-radius: 4px; 93 | -webkit-border-top-right-radius: 4px; 94 | -webkit-border-bottom-left-radius: 4px; 95 | -webkit-border-bottom-right-radius: 4px; 96 | -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); 97 | } 98 | 99 | .SelectItem { 100 | font: 8pt Arial, Verdana, sans-serif; 101 | padding-left: 2px; 102 | padding-right: 12px; 103 | border: 0px; 104 | } 105 | 106 | span.SelectionMark { 107 | margin-right: 4px; 108 | font-family: monospace; 109 | outline-style: none; 110 | text-decoration: none; 111 | } 112 | 113 | a.SelectItem { 114 | display: block; 115 | outline-style: none; 116 | color: #000000; 117 | text-decoration: none; 118 | padding-left: 6px; 119 | padding-right: 12px; 120 | } 121 | 122 | a.SelectItem:focus, 123 | a.SelectItem:active { 124 | color: #000000; 125 | outline-style: none; 126 | text-decoration: none; 127 | } 128 | 129 | a.SelectItem:hover { 130 | color: #FFFFFF; 131 | background-color: #3D578C; 132 | outline-style: none; 133 | text-decoration: none; 134 | cursor: pointer; 135 | display: block; 136 | } 137 | 138 | /*---------------- Search results window */ 139 | 140 | iframe#MSearchResults { 141 | width: 60ex; 142 | height: 15em; 143 | } 144 | 145 | #MSearchResultsWindow { 146 | display: none; 147 | position: absolute; 148 | left: 0; top: 0; 149 | border: 1px solid #000; 150 | background-color: #EEF1F7; 151 | z-index:10000; 152 | } 153 | 154 | /* ----------------------------------- */ 155 | 156 | 157 | #SRIndex { 158 | clear:both; 159 | padding-bottom: 15px; 160 | } 161 | 162 | .SREntry { 163 | font-size: 10pt; 164 | padding-left: 1ex; 165 | } 166 | 167 | .SRPage .SREntry { 168 | font-size: 8pt; 169 | padding: 1px 5px; 170 | } 171 | 172 | body.SRPage { 173 | margin: 5px 2px; 174 | } 175 | 176 | .SRChildren { 177 | padding-left: 3ex; padding-bottom: .5em 178 | } 179 | 180 | .SRPage .SRChildren { 181 | display: none; 182 | } 183 | 184 | .SRSymbol { 185 | font-weight: bold; 186 | color: #425E97; 187 | font-family: Arial, Verdana, sans-serif; 188 | text-decoration: none; 189 | outline: none; 190 | } 191 | 192 | a.SRScope { 193 | display: block; 194 | color: #425E97; 195 | font-family: Arial, Verdana, sans-serif; 196 | text-decoration: none; 197 | outline: none; 198 | } 199 | 200 | a.SRSymbol:focus, a.SRSymbol:active, 201 | a.SRScope:focus, a.SRScope:active { 202 | text-decoration: underline; 203 | } 204 | 205 | span.SRScope { 206 | padding-left: 4px; 207 | font-family: Arial, Verdana, sans-serif; 208 | } 209 | 210 | .SRPage .SRStatus { 211 | padding: 2px 5px; 212 | font-size: 8pt; 213 | font-style: italic; 214 | font-family: Arial, Verdana, sans-serif; 215 | } 216 | 217 | .SRResult { 218 | display: none; 219 | } 220 | 221 | div.searchresults { 222 | margin-left: 10px; 223 | margin-right: 10px; 224 | } 225 | 226 | /*---------------- External search page results */ 227 | 228 | .searchresult { 229 | background-color: #F0F3F8; 230 | } 231 | 232 | .pages b { 233 | color: white; 234 | padding: 5px 5px 3px 5px; 235 | background-image: url("../tab_a.png"); 236 | background-repeat: repeat-x; 237 | text-shadow: 0 1px 1px #000000; 238 | } 239 | 240 | .pages { 241 | line-height: 17px; 242 | margin-left: 4px; 243 | text-decoration: none; 244 | } 245 | 246 | .hl { 247 | font-weight: bold; 248 | } 249 | 250 | #searchresults { 251 | margin-bottom: 20px; 252 | } 253 | 254 | .searchpages { 255 | margin-top: 10px; 256 | } 257 | 258 | -------------------------------------------------------------------------------- /doc/html/sam__arduino_8h.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: src/sam_arduino.h File Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 | 66 |
    67 |
    68 |
    69 | Classes | 70 | Functions
    71 |
    72 |
    sam_arduino.h File Reference
    73 |
    74 |
    75 | 76 |

    Arduino API for SAM. 77 | More...

    78 | 79 |

    Go to the source code of this file.

    80 | 81 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |

    82 | Classes

    class  SAM
     Arduino API for SAM Text to Speach Engine. More...
     
    struct  PitchedStr
     string and pitch - this can be used to build a song More...
     
    90 | 92 | 94 | 95 |

    91 | Functions

    93 | void printLog (char *msg)
     
    96 |

    Detailed Description

    97 |

    Arduino API for SAM.

    98 |
    Author
    Phil Schatzmann
    99 |
    Version
    0.1
    100 |
    Date
    2021-06-18
    101 | 102 |
    103 | 104 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /doc/html/hierarchy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Class Hierarchy 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    Class Hierarchy
    66 |
    67 |
    68 |
    This inheritance list is sorted roughly, but not completely, alphabetically:
    69 |
    [detail level 123]
    70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
     CPitchedStrString and pitch - this can be used to build a song
     CSAMArduino API for SAM Text to Speach Engine
     CSAMOutputBaseBase Output Class with common functionality
     CSAMOutputCallbackOutput via Callback method
     CSAMOutputI2SOutput to I2S for ESP32: This class is obsolete and has been deactivated in the sam_config.h since the related API is not longer supported by Espressif. Use the I2S functionality provided by your core or the AudioTools library instread
     CSAMOutputStreamOutput to Arduino Stream
     CSAMPrintStreamWrite readable string to Arduino Stream
    78 |
    79 |
    80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/SamTabs.h: -------------------------------------------------------------------------------- 1 | #ifndef SAMTABS_H 2 | #define SAMTABS_H 3 | 4 | #include "sam_debug.h" 5 | #include "sam_pgmspace.h" 6 | 7 | //tab40672 8 | const unsigned char stressInputTable[] PROGMEM = 9 | { 10 | '*', '1', '2', '3', '4', '5', '6', '7', '8' 11 | }; 12 | 13 | //tab40682 14 | const unsigned char signInputTable1[] PROGMEM = 15 | { 16 | ' ', '.', '?', ',', '-', 'I', 'I', 'E', 17 | 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 18 | 'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R', 19 | 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 20 | 'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z', 21 | 'V', 'D', 'C', '*', 'J', '*', '*', '*', 22 | 'E', 'A', 'O', 'A', 'O', 'U', 'B', '*', 23 | '*', 'D', '*', '*', 'G', '*', '*', 'G', 24 | '*', '*', 'P', '*', '*', 'T', '*', '*', 25 | 'K', '*', '*', 'K', '*', '*', 'U', 'U', 26 | 'U' 27 | }; 28 | 29 | //tab40763 30 | const unsigned char signInputTable2[] PROGMEM = 31 | { 32 | '*', '*', '*', '*', '*', 'Y', 'H', 'H', 33 | 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 34 | 'X', 'H', 'X', 'X', 'X', 'X', 'H', '*', 35 | '*', '*', '*', '*', '*', 'X', 'X', '*', 36 | '*', 'H', '*', 'H', 'H', 'X', '*', 'H', 37 | '*', 'H', 'H', '*', '*', '*', '*', '*', 38 | 'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*', 39 | '*', '*', '*', '*', '*', '*', '*', 'X', 40 | '*', '*', '*', '*', '*', '*', '*', '*', 41 | '*', '*', '*', 'X', '*', '*', 'L', 'M', 42 | 'N' 43 | }; 44 | 45 | //loc_9F8C 46 | const unsigned char flags[]={ 47 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xA4 , 0xA4 , 0xA4 , 48 | 0xA4 , 0xA4 , 0xA4 , 0x84 , 0x84 , 0xA4 , 0xA4 , 0x84 , 49 | 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x84 , 0x44 , 0x44 , 50 | 0x44 , 0x44 , 0x44 , 0x4C , 0x4C , 0x4C , 0x48 , 0x4C , 51 | 0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x40 , 0x44 , 0x44 , 52 | 0x44 , 0x44 , 0x48 , 0x40 , 0x4C , 0x44 , 0x00 , 0x00 , 53 | 0xB4 , 0xB4 , 0xB4 , 0x94 , 0x94 , 0x94 , 0x4E , 0x4E , 54 | 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 0x4E , 55 | 0x4E , 0x4E , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 56 | 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x4B , 0x80 , 0xC1 , 57 | 0xC1 58 | 59 | 60 | }; 61 | 62 | //??? flags overlap flags2 63 | //loc_9FDA 64 | const unsigned char flags2[] = 65 | { 66 | 0x80 , 0xC1 , 0xC1 , 0xC1 , 0xC1 , 0x00 , 0x00 , 0x00 , 67 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 68 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 69 | 0x10 , 0x10 , 0x10 , 0x08 , 0x0C , 0x08 , 0x04 , 0x40 , 70 | 0x24 , 0x20 , 0x20 , 0x24 , 0x00 , 0x00 , 0x24 , 0x20 , 71 | 0x20 , 0x24 , 0x20 , 0x20 , 0x00 , 0x20 , 0x00 , 0x00 , 72 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 73 | 0x00 , 0x04 , 0x04 , 0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 74 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x04 , 0x04 , 0x04 , 75 | 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 76 | }; 77 | 78 | 79 | 80 | //tab45616??? 81 | const unsigned char phonemeStressedLengthTable[] PROGMEM = 82 | { 83 | 0x00 , 0x12 , 0x12 , 0x12 , 8 ,0xB , 9 ,0xB , 84 | 0xE ,0xF ,0xB , 0x10 ,0xC , 6 , 6 ,0xE , 85 | 0xC ,0xE ,0xC ,0xB , 8 , 8 ,0xB ,0xA , 86 | 9 , 8 , 8 , 8 , 8 , 8 , 3 , 5 , 87 | 2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 , 88 | 8 , 6 , 6 , 2 , 9 , 4 , 2 , 1 , 89 | 0xE ,0xF ,0xF ,0xF ,0xE ,0xE , 8 , 2 , 90 | 2 , 7 , 2 , 1 , 7 , 2 , 2 , 7 , 91 | 2 , 2 , 8 , 2 , 2 , 6 , 2 , 2 , 92 | 7 , 2 , 4 , 7 , 1 , 4 , 5 , 5 93 | }; 94 | 95 | //tab45536??? 96 | const unsigned char phonemeLengthTable[] PROGMEM = 97 | { 98 | 0 , 0x12 , 0x12 , 0x12 , 8 , 8 , 8 , 8 , 99 | 8 ,0xB , 6 ,0xC ,0xA , 5 , 5 ,0xB , 100 | 0xA ,0xA ,0xA , 9 , 8 , 7 , 9 , 7 , 101 | 6 , 8 , 6 , 7 , 7 , 7 , 2 , 5 , 102 | 2 , 2 , 2 , 2 , 2 , 2 , 6 , 6 , 103 | 7 , 6 , 6 , 2 , 8 , 3 , 1 , 0x1E , 104 | 0xD ,0xC ,0xC ,0xC ,0xE , 9 , 6 , 1 , 105 | 2 , 5 , 1 , 1 , 6 , 1 , 2 , 6 , 106 | 1 , 2 , 8 , 2 , 2 , 4 , 2 , 2 , 107 | 6 , 1 , 4 , 6 , 1 , 4 , 0xC7 , 0xFF 108 | }; 109 | 110 | 111 | 112 | /* 113 | 114 | Ind | phoneme | flags | 115 | -----|---------|----------| 116 | 0 | * | 00000000 | 117 | 1 | .* | 00000000 | 118 | 2 | ?* | 00000000 | 119 | 3 | ,* | 00000000 | 120 | 4 | -* | 00000000 | 121 | 122 | VOWELS 123 | 5 | IY | 10100100 | 124 | 6 | IH | 10100100 | 125 | 7 | EH | 10100100 | 126 | 8 | AE | 10100100 | 127 | 9 | AA | 10100100 | 128 | 10 | AH | 10100100 | 129 | 11 | AO | 10000100 | 130 | 17 | OH | 10000100 | 131 | 12 | UH | 10000100 | 132 | 16 | UX | 10000100 | 133 | 15 | ER | 10000100 | 134 | 13 | AX | 10100100 | 135 | 14 | IX | 10100100 | 136 | 137 | DIPHTONGS 138 | 48 | EY | 10110100 | 139 | 49 | AY | 10110100 | 140 | 50 | OY | 10110100 | 141 | 51 | AW | 10010100 | 142 | 52 | OW | 10010100 | 143 | 53 | UW | 10010100 | 144 | 145 | 146 | 21 | YX | 10000100 | 147 | 20 | WX | 10000100 | 148 | 18 | RX | 10000100 | 149 | 19 | LX | 10000100 | 150 | 37 | /X | 01000000 | 151 | 30 | DX | 01001000 | 152 | 153 | 154 | 22 | WH | 01000100 | 155 | 156 | 157 | VOICED CONSONANTS 158 | 23 | R* | 01000100 | 159 | 24 | L* | 01000100 | 160 | 25 | W* | 01000100 | 161 | 26 | Y* | 01000100 | 162 | 27 | M* | 01001100 | 163 | 28 | N* | 01001100 | 164 | 29 | NX | 01001100 | 165 | 54 | B* | 01001110 | 166 | 57 | D* | 01001110 | 167 | 60 | G* | 01001110 | 168 | 44 | J* | 01001100 | 169 | 38 | Z* | 01000100 | 170 | 39 | ZH | 01000100 | 171 | 40 | V* | 01000100 | 172 | 41 | DH | 01000100 | 173 | 174 | unvoiced CONSONANTS 175 | 32 | S* | 01000000 | 176 | 33 | SH | 01000000 | 177 | 34 | F* | 01000000 | 178 | 35 | TH | 01000000 | 179 | 66 | P* | 01001011 | 180 | 69 | T* | 01001011 | 181 | 72 | K* | 01001011 | 182 | 42 | CH | 01001000 | 183 | 36 | /H | 01000000 | 184 | 185 | 43 | ** | 01000000 | 186 | 45 | ** | 01000100 | 187 | 46 | ** | 00000000 | 188 | 47 | ** | 00000000 | 189 | 190 | 191 | 55 | ** | 01001110 | 192 | 56 | ** | 01001110 | 193 | 58 | ** | 01001110 | 194 | 59 | ** | 01001110 | 195 | 61 | ** | 01001110 | 196 | 62 | ** | 01001110 | 197 | 63 | GX | 01001110 | 198 | 64 | ** | 01001110 | 199 | 65 | ** | 01001110 | 200 | 67 | ** | 01001011 | 201 | 68 | ** | 01001011 | 202 | 70 | ** | 01001011 | 203 | 71 | ** | 01001011 | 204 | 73 | ** | 01001011 | 205 | 74 | ** | 01001011 | 206 | 75 | KX | 01001011 | 207 | 76 | ** | 01001011 | 208 | 77 | ** | 01001011 | 209 | 210 | 211 | SPECIAL 212 | 78 | UL | 10000000 | 213 | 79 | UM | 11000001 | 214 | 80 | UN | 11000001 | 215 | 31 | Q* | 01001100 | 216 | 217 | */ 218 | 219 | #endif 220 | -------------------------------------------------------------------------------- /doc/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: SAM - Software Automatic Mouth - Tiny Speech Synthesizer - Arduino Library 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 |
    49 | 50 |
    54 |
    55 | 56 | 57 |
    58 | 61 |
    62 | 63 |
    64 |
    65 |
    SAM - Software Automatic Mouth - Tiny Speech Synthesizer - Arduino Library
    66 |
    67 |
    68 |

    Sam is a very small Text-To-Speech (TTS) program written in C, that runs on most popular platforms. It is an adaption to C of the speech software SAM (Software Automatic Mouth) for the Commodore C64 published in the year 1982 by Don't Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme converter called reciter and a Phoneme-To-Speech routine for the final output. It is so small that it will work also on embedded computers.
    69 |

    70 |

    I created this project with the intention to provide SAM as Arduino Library which supports different output alternatives:

    71 | 75 |

    76 | Installation

    77 |

    You can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with

    cd ~/Documents/Arduino/libraries
    78 |
    git clone pschatzmann/SAM.git
    79 |

    80 | Documentation

    81 | 87 |

    88 | Voices

    89 |

    Voices can be defined by setting the speed, pitch, throat and moth parameters:

    90 |
    DESCRIPTION SPEED PITCH THROAT MOUTH
    91 |
    Elf 72 64 110 160
    92 |
    Little Robot 92 60 190 190
    93 |
    Stuffy Guy 82 72 110 105
    94 |
    Little Old Lady 82 32 145 145
    95 |
    Extra-Terrestrial 100 64 150 200
    96 |
    SAM 72 64 128 128
    97 |

    You can try out some alternative parameter combinations here.

    98 |

    99 | Output Format

    100 |

    The autput format is as follows:

    101 |
      102 |
    • bits per sample: 16
    • 103 |
    • sample rate: 22050
    • 104 |
    • channels: 1
    • 105 |
    106 |

    You can change the channels to 2 by calling sam.setOutputChannels(2);

    107 |

    108 | Memory Requirements

    109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
    Memory Type Used
    Progmem 225'000
    Dynamic Memory 14'000
    117 |

    The requirements have been determined by compiling the project with an ESP32. The values are rounded up!
    118 |

    119 |

    120 | License

    121 |

    The software is a reverse-engineered version of a commercial software published more than 30 years ago. The current copyright holder is SoftVoice, Inc. (www.text2speech.com)

    122 |

    Any attempt to contact the company failed. The website was last updated in the year 2009. The status of the original software can therefore best described as Abandonware (http://en.wikipedia.org/wiki/Abandonware)

    123 |

    As long this is the case we cannot put the code under any specific open source software license: Use it at your own risk.

    124 |
    125 |
    126 | 127 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /SAM.md: -------------------------------------------------------------------------------- 1 | SAM 2 | === 3 | 4 | Software Automatic Mouth - Tiny Speech Synthesizer 5 | 6 | 7 | What is SAM? 8 | ============ 9 | 10 | Sam is a very small Text-To-Speech (TTS) program written in C, that runs on most popular platforms. 11 | It is an adaption to C of the speech software SAM (Software Automatic Mouth) for the Commodore C64 published 12 | in the year 1982 by Don't Ask Software (now SoftVoice, Inc.). It includes a Text-To-Phoneme converter called reciter and a Phoneme-To-Speech routine for the 13 | final output. It is so small that it will work also on embedded computers. On my computer it takes 14 | less than 39KB (much smaller on embedded devices as the executable-overhead is not necessary) of disk space and is a fully stand alone program. 15 | For immediate output it uses the SDL-library, otherwise it can save .wav files. 16 | 17 | An online version and executables for Windows can be found on the web site: http://simulationcorner.net/index.php?page=sam 18 | 19 | Compile 20 | ======= 21 | 22 | Simply type "make" in your command prompt. 23 | In order to compile without SDL remove the SDL statements from the CFLAGS and LFLAGS variables in the file "Makefile". 24 | 25 | It should compile on every UNIX-like operating system. For Windows you need Cygwin or MinGW( + libsdl). 26 | 27 | 28 | Usage 29 | ===== 30 | 31 | type 32 | 33 | make 34 | for the first output. 35 | 36 | If you have disabled SDL try 37 | 38 | ./sam -wav i_am_sam.wav I am Sam 39 | 40 | to get a wav file. This file can be played by many media players available for the PC. 41 | 42 | you can try other options like 43 | -pitch number 44 | -speed number 45 | -throat number 46 | -mouth number 47 | 48 | Some typical values written in the original manual are: 49 | 50 | DESCRIPTION SPEED PITCH THROAT MOUTH 51 | Elf 72 64 110 160 52 | Little Robot 92 60 190 190 53 | Stuffy Guy 82 72 110 105 54 | Little Old Lady 82 32 145 145 55 | Extra-Terrestrial 100 64 150 200 56 | SAM 72 64 128 128 57 | 58 | 59 | It can even sing 60 | look at the file "sing" 61 | for a small example. 62 | 63 | For the phoneme input table look in the Wiki. 64 | 65 | 66 | A description of additional features can be found in the original manual at 67 | http://www.retrobits.net/atari/sam.shtml 68 | or in the manual of the equivalent Apple II program 69 | http://www.apple-iigs.info/newdoc/sam.pdf 70 | 71 | 72 | Adaption To C 73 | ============= 74 | 75 | This program was converted semi-automatic into C by converting each assembler opcode. 76 | e. g. 77 | 78 | lda 56 => A = mem[56]; 79 | jmp 38018 => goto pos38018; 80 | inc 38 => mem[38]++; 81 | . . 82 | . . 83 | 84 | Then it was manually rewritten to remove most of the 85 | jumps and register variables in the code and rename the variables to proper names. 86 | Most of the description below is a result of this rewriting process. 87 | 88 | Unfortunately its still a not very good readable. But you should see where I started :) 89 | 90 | 91 | 92 | Short description 93 | ================= 94 | 95 | First of all I will limit myself here to a very coarse description. 96 | There are very many exceptions defined in the source code that I will not explain. 97 | Also a lot of code is unknown for me e. g. Code47503. 98 | For a complete understanding of the code I need more time and especially more eyes have a look on the code. 99 | 100 | Reciter 101 | ------- 102 | 103 | It changes the english text to phonemes by a ruleset shown in the wiki. 104 | 105 | The rule 106 | " ANT(I)", "AY", 107 | means that if he find an "I" with previous letters " ANT", exchange the I by the phoneme "AY". 108 | 109 | There are some special signs in this rules like 110 | # 111 | & 112 | @ 113 | ^ 114 | + 115 | : 116 | % 117 | which can mean e. g. that there must be a vocal or a consonant or something else. 118 | 119 | With the -debug option you will get the corresponding rules and the resulting phonemes. 120 | 121 | 122 | Output 123 | ------ 124 | 125 | Here is the full tree of subroutine calls: 126 | 127 | SAMMain() 128 | Parser1() 129 | Parser2() 130 | Insert() 131 | CopyStress() 132 | SetPhonemeLength() 133 | Code48619() 134 | Code41240() 135 | Insert() 136 | Code48431() 137 | Insert() 138 | 139 | Code48547 140 | Code47574 141 | Special1 142 | Code47503 143 | Code48227 144 | 145 | 146 | SAMMain() is the entry routine and calls all further routines. 147 | Parser1 transforms the phoneme input and transforms it to three tables 148 | phonemeindex[] 149 | stress[] 150 | phonemelength[] (zero at this moment) 151 | 152 | This tables are now changed: 153 | 154 | Parser2 exchanges some phonemes by others and inserts new. 155 | CopyStress adds 1 to the stress under some circumstances 156 | SetPhonemeLength sets phoneme lengths. 157 | Code48619 changes the phoneme lengths 158 | Code41240 adds some additional phonemes 159 | Code48431 has some extra rules 160 | 161 | 162 | The wiki shows all possible phonemes and some flag fields. 163 | The final content of these tables can be seen with the -debug command. 164 | 165 | 166 | In the function PrepareOutput() these tables are partly copied into the small tables: 167 | phonemeindexOutput[] 168 | stressOutput[] 169 | phonemelengthOutput[] 170 | for output. 171 | 172 | Final Output 173 | ------------ 174 | 175 | Except of some special phonemes the output is build by a linear combination: 176 | 177 | A = A1 * sin ( f1 * t ) + 178 | A2 * sin ( f2 * t ) + 179 | A3 * rect( f3 * t ) 180 | 181 | where rect is a rectangular function with the same periodicity like sin. 182 | It seems really strange, but this is really enough for most types of phonemes. 183 | 184 | Therefore the above phonemes are converted with some tables to 185 | pitches[] 186 | frequency1[] = f1 187 | frequency2[] = f2 188 | frequency3[] = f3 189 | amplitude1[] = A1 190 | amplitude2[] = A2 191 | amplitude3[] = A3 192 | 193 | Above formula is calculated in one very good omptimized routine. 194 | It only consist of 26 commands: 195 | 196 | 48087: LDX 43 ; get phase 197 | CLC 198 | LDA 42240,x ; load sine value (high 4 bits) 199 | ORA TabAmpl1,y ; get amplitude (in low 4 bits) 200 | TAX 201 | LDA 42752,x ; multiplication table 202 | STA 56 ; store 203 | 204 | LDX 42 ; get phase 205 | LDA 42240,x ; load sine value (high 4 bits) 206 | ORA TabAmpl2,y ; get amplitude (in low 4 bits) 207 | TAX 208 | LDA 42752,x ; multiplication table 209 | ADC Var56 ; add with previous values 210 | STA 56 ; and store 211 | 212 | LDX 41 ; get phase 213 | LDA 42496,x ; load rect value (high 4 bits) 214 | ORA TabAmpl3,y ; get amplitude (in low 4 bits) 215 | TAX 216 | LDA 42752,x ; multiplication table 217 | ADC 56 ; add with previous values 218 | 219 | ADC #136 220 | LSR A ; get highest 4 bits 221 | LSR A 222 | LSR A 223 | LSR A 224 | STA 54296 ;SID main output command 225 | 226 | 227 | The rest is handled in a special way. At the moment I cannot figure out in which way. 228 | But it seems that it uses some noise (e. g. for "s") using a table with random values. 229 | 230 | License 231 | ======= 232 | 233 | The software is a reverse-engineered version of a commercial software published more than 30 years ago. 234 | The current copyright holder is SoftVoice, Inc. (www.text2speech.com) 235 | 236 | Any attempt to contact the company failed. The website was last updated in the year 2009. 237 | The status of the original software can therefore best described as Abandonware 238 | (http://en.wikipedia.org/wiki/Abandonware) 239 | 240 | As long this is the case I cannot put my code under any specific open source software license 241 | Use it at your own risk. 242 | 243 | 244 | 245 | Contact 246 | ======= 247 | 248 | If you have questions don' t hesitate to ask me. 249 | If you discovered some new knowledge about the code please mail me. 250 | 251 | Sebastian Macke 252 | Email: sebastian@macke.de 253 | -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_base-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Member List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 |
    63 |
    64 |
    65 |
    SAMOutputBase Member List
    66 |
    67 |
    68 | 69 |

    This is the complete list of members for SAMOutputBase, including all inherited members.

    70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
    bits_per_sample (defined in SAMOutputBase)SAMOutputBaseprotected
    bitsPerSample() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    channel_count (defined in SAMOutputBase)SAMOutputBaseprotected
    channels() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    close() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    drain() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    is_open (defined in SAMOutputBase)SAMOutputBaseprotected
    isOpen() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    name()=0 (defined in SAMOutputBase)SAMOutputBasepure virtual
    open() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    sampleRate() (defined in SAMOutputBase)SAMOutputBaseinlinestatic
    setChannels(int channels) (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    setSampleRate(uint32_t rate) (defined in SAMOutputBase)SAMOutputBaseinlinestatic
    write(byte *buff, int bytes_count)=0 (defined in SAMOutputBase)SAMOutputBasepure virtual
    ~SAMOutputBase() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /doc/html/tabs.css: -------------------------------------------------------------------------------- 1 | .sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0px/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0px 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255,255,255,0.9);color:#283A5D;outline:none}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a.current{color:#D23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media (min-width: 768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0px 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a:hover span.sub-arrow{border-color:#fff transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;border-radius:5px !important;box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #fff}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #D23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#D23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}} 2 | -------------------------------------------------------------------------------- /src/sam_arduino_out.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sam_out_arduino.h 3 | * @author Phil Schatzmann 4 | * @brief Arduino C++ Output Alternatives. 5 | * @version 0.1 6 | * @date 2021-06-18 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | #include "Arduino.h" 13 | #include "reciter.h" 14 | #include "sam.h" 15 | #include "sam_config.h" 16 | 17 | #if defined(ESP32) && LEGACY_ESP_I2S 18 | #include "driver/i2s.h" 19 | #include "freertos/queue.h" 20 | #endif 21 | 22 | // User Callback 23 | typedef void (*sam_callback)(size_t size, int16_t *values); 24 | 25 | // Application Callback 26 | static void OutputByteCallback(void *cbdata, unsigned char b); 27 | static uint32_t SAM_sample_rate = 22050; 28 | /** 29 | * @brief Base Output Class with common functionality 30 | * 31 | */ 32 | class SAMOutputBase { 33 | public: 34 | virtual ~SAMOutputBase() {} 35 | 36 | virtual void open() { 37 | SAM_LOG("SAMOutputBase::open"); 38 | is_open = true; 39 | }; 40 | 41 | virtual int close() { 42 | is_open = false; 43 | return 0; 44 | } 45 | 46 | virtual int drain() { return 0; } 47 | 48 | virtual int channels() { return channel_count; } 49 | 50 | virtual void setChannels(int channels) { channel_count = channels; } 51 | 52 | virtual int bitsPerSample() { return 16; } 53 | 54 | virtual bool isOpen() { return is_open; } 55 | 56 | static uint32_t sampleRate() { 57 | return SAM_sample_rate; // 44100; 58 | } 59 | 60 | static void setSampleRate(uint32_t rate) { 61 | SAM_sample_rate = rate; // 44100; 62 | } 63 | 64 | virtual const char *name() = 0; 65 | 66 | virtual bool write(byte *buff, int bytes_count) = 0; 67 | 68 | protected: 69 | bool is_open = false; 70 | int channel_count = -1; 71 | int bits_per_sample = -1; 72 | }; 73 | 74 | /** 75 | * @brief Output via Callback method 76 | * 77 | */ 78 | class SAMOutputCallback : public SAMOutputBase { 79 | public: 80 | SAMOutputCallback(sam_callback cb) { callback = cb; } 81 | 82 | virtual bool write(byte *buffer, int bytes_count) { 83 | SAM_LOG("SAMOutputCallback::write: %d", bytes_count); 84 | int samples = bytes_count / sizeof(int16_t); 85 | callback(samples, (int16_t *)buffer); 86 | return true; 87 | } 88 | 89 | const char *name() { return "SAMOutputCallback"; } 90 | 91 | protected: 92 | sam_callback callback; 93 | }; 94 | 95 | #if defined(ESP32) && LEGACY_ESP_I2S 96 | #if __has_include("esp_arduino_version.h") 97 | #include "esp_arduino_version.h" 98 | #endif 99 | 100 | #if !defined(ESP_IDF_VERSION_MAJOR) 101 | #define ESP_IDF_VERSION_MAJOR 2 102 | #endif 103 | 104 | #if ESP_IDF_VERSION_MAJOR < 4 105 | #define I2S_COMM_FORMAT_STAND_I2S \ 106 | (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB) 107 | #endif 108 | 109 | /** 110 | * @brief Output to I2S for ESP32: This class is obsolete and has been 111 | * deactivated in the sam_config.h since the related API is not longer supported 112 | * by Espressif. Use the I2S functionality provided by your core or the 113 | * AudioTools library instread. 114 | * 115 | */ 116 | class SAMOutputI2S : public SAMOutputBase { 117 | public: 118 | SAMOutputI2S(i2s_port_t i2s_num = I2S_NUM_0) { 119 | this->i2s_num = i2s_num; 120 | setupDefaultConfig(); 121 | setupDefaultPins(); 122 | } 123 | 124 | SAMOutputI2S(i2s_port_t i2s_num, i2s_config_t cfg) { 125 | this->i2s_num = i2s_num; 126 | this->i2s_config = cfg; 127 | setupDefaultPins(); 128 | } 129 | 130 | SAMOutputI2S(i2s_port_t i2s_num, i2s_config_t cfg, i2s_pin_config_t pins) { 131 | this->i2s_num = i2s_num; 132 | this->i2s_config = cfg; 133 | this->pin_config = pins; 134 | } 135 | 136 | ~SAMOutputI2S() { 137 | if (isOpen()) { 138 | close(); 139 | } 140 | } 141 | 142 | const char *name() { return "SAMOutputI2S"; } 143 | 144 | int channels() { return 2; } 145 | 146 | virtual void open() { 147 | // update sample sample_rate 148 | i2s_config.sample_rate = SAMOutputBase::sampleRate(); 149 | SAM_LOG("setting sample rate for I2S: %d", i2s_config.sample_rate); 150 | // install driver 151 | if (i2s_driver_install(i2s_num, &i2s_config, 0, NULL) != ESP_OK) { 152 | ESP_LOGE(TAG, "Failed to install i2s"); 153 | } 154 | if (i2s_config.mode & I2S_MODE_DAC_BUILT_IN) { 155 | // for internal DAC, this will enable both of the internal channels 156 | SAM_LOG("i2s_set_pin: %s", "internal DAC"); 157 | if (i2s_set_pin(i2s_num, NULL) != ESP_OK) { 158 | ESP_LOGE(TAG, "Failed to set i2s pins"); 159 | } 160 | } else { 161 | // define pins for external DAC 162 | SAM_LOG("i2s_set_pin: %s", "external DAC"); 163 | if (i2s_set_pin(i2s_num, &pin_config) != ESP_OK) { 164 | ESP_LOGE(TAG, "Failed to set i2s pins"); 165 | } 166 | } 167 | SAMOutputBase::open(); 168 | }; 169 | 170 | virtual int close() { 171 | if (i2s_driver_uninstall(i2s_num) != ESP_OK) { 172 | ESP_LOGE(TAG, "Failed to uninstall i2s"); 173 | } 174 | 175 | return SAMOutputBase::close(); 176 | } 177 | 178 | virtual int drain() { 179 | i2s_zero_dma_buffer(i2s_num); 180 | return 0; 181 | } 182 | 183 | virtual bool write(byte *buffer, int bytes_count) { 184 | SAM_LOG("SAMOutputI2S::write: %d", bytes_count); 185 | size_t i2s_bytes_write; 186 | 187 | if (this->i2s_config.mode & I2S_MODE_DAC_BUILT_IN) { 188 | for (int i = 0; i < bytes_count; i++) { 189 | buffer[i] = buffer[i] + 0x8000; 190 | } 191 | } 192 | 193 | if (i2s_write(i2s_num, buffer, bytes_count, 194 | &i2s_bytes_write, portMAX_DELAY) != ESP_OK) { 195 | ESP_LOGE(TAG, "i2s_write failed!"); 196 | return false; 197 | } 198 | return true; 199 | ; 200 | } 201 | 202 | void setChannels(int ch) { 203 | if (ch != 2) SAM_LOG("Channels is not supported for this output type"); 204 | } 205 | 206 | void setBitsPerSample(int bps) { 207 | if (bps != 16) SAM_LOG("Channels is not supported for this output type"); 208 | } 209 | 210 | protected: 211 | i2s_port_t i2s_num; 212 | i2s_config_t i2s_config; 213 | i2s_pin_config_t pin_config; 214 | const char *TAG = "SAMOutputI2S"; 215 | 216 | void setupDefaultConfig() { 217 | const i2s_config_t i2s_config_default = { 218 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), 219 | .sample_rate = this->sampleRate(), 220 | .bits_per_sample = (i2s_bits_per_sample_t)16, 221 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 222 | .communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_STAND_I2S, 223 | .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority 224 | .dma_buf_count = 10, 225 | .dma_buf_len = 64, 226 | .use_apll = false, 227 | .tx_desc_auto_clear = 228 | true // avoiding noise in case of data unavailability 229 | }; 230 | this->i2s_config = i2s_config_default; 231 | } 232 | 233 | void setupDefaultPins() { 234 | static const i2s_pin_config_t pin_config_default = { 235 | .bck_io_num = 26, 236 | .ws_io_num = 25, 237 | .data_out_num = 22, 238 | .data_in_num = I2S_PIN_NO_CHANGE}; 239 | this->pin_config = pin_config_default; 240 | } 241 | }; 242 | #endif 243 | 244 | /** 245 | * @brief Output to Arduino Stream 246 | * 247 | */ 248 | class SAMOutputStream : public SAMOutputBase { 249 | public: 250 | SAMOutputStream(Print &out) { this->out_ptr = &out; } 251 | const char *name() { return "SAMOutputStream"; } 252 | 253 | virtual int drain() { return 0; } 254 | 255 | virtual bool write(byte *buffer, int bytes_count) { 256 | SAM_LOG("SAMOutputStream::write: %d", bytes_count); 257 | size_t len = bytes_count; 258 | 259 | size_t len_written = out_ptr->write((const uint8_t *)buffer, len); 260 | if (len != len_written) { 261 | SAM_LOG("Error - Could not write all data: %d of %d", len_written, len); 262 | return false; 263 | } 264 | return true; 265 | } 266 | 267 | protected: 268 | Print *out_ptr; 269 | int output_channels; 270 | }; 271 | 272 | /** 273 | * @brief Write readable string to Arduino Stream 274 | * 275 | */ 276 | class SAMPrintStream : public SAMOutputStream { 277 | public: 278 | SAMPrintStream(Print &out) : SAMOutputStream(out) {} 279 | 280 | const char *name() { return "SAMPrintStream"; } 281 | 282 | virtual bool write(byte *buffer, int bytes_count) { 283 | // copy from 1 to 2 channels 284 | int16_t *buffer16 = (int16_t *)buffer; 285 | for (int j = 0; j < bytes_count / 2; j++) { 286 | out_ptr->print(buffer16[j]); 287 | if (j < channels() - 1) { 288 | out_ptr->print(","); 289 | } 290 | if (j == channels() - 1) { 291 | out_ptr->println(); 292 | } 293 | } 294 | 295 | return true; 296 | } 297 | }; 298 | -------------------------------------------------------------------------------- /doc/html/class_s_a_m_output_callback-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Arduino SAM: Member List 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 27 | 28 | 29 |
    24 |
    Arduino SAM 25 |
    26 |
    30 |
    31 | 32 | 33 | 38 | 39 | 40 | 47 | 48 | 49 |
    53 |
    54 | 55 | 56 |
    57 | 60 |
    61 | 62 |
    63 |
    64 |
    65 |
    SAMOutputCallback Member List
    66 |
    67 |
    68 | 69 |

    This is the complete list of members for SAMOutputCallback, including all inherited members.

    70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
    bits_per_sample (defined in SAMOutputBase)SAMOutputBaseprotected
    bitsPerSample() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    callback (defined in SAMOutputCallback)SAMOutputCallbackprotected
    channel_count (defined in SAMOutputBase)SAMOutputBaseprotected
    channels() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    close() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    drain() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    is_open (defined in SAMOutputBase)SAMOutputBaseprotected
    isOpen() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    name() (defined in SAMOutputCallback)SAMOutputCallbackinlinevirtual
    open() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    SAMOutputCallback(sam_callback cb) (defined in SAMOutputCallback)SAMOutputCallbackinline
    sampleRate() (defined in SAMOutputBase)SAMOutputBaseinlinestatic
    setChannels(int channels) (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    setSampleRate(uint32_t rate) (defined in SAMOutputBase)SAMOutputBaseinlinestatic
    write(byte *buffer, int bytes_count) (defined in SAMOutputCallback)SAMOutputCallbackinlinevirtual
    ~SAMOutputBase() (defined in SAMOutputBase)SAMOutputBaseinlinevirtual
    89 | 90 | 93 | 94 | 95 | --------------------------------------------------------------------------------