| display: block; | display: block; | ||||
| margin-bottom: 1rem; | margin-bottom: 1rem; | ||||
| } | } | ||||
| #ipaarea { | |||||
| width: 100%; | |||||
| height: 8rem; | |||||
| display: block; | |||||
| margin-bottom: 1rem; | |||||
| } | |||||
| p.gh { | p.gh { | ||||
| color: #333; | color: #333; | ||||
| text-align: right; | text-align: right; | ||||
| <h1>espeakng.js 1.49.1 Demo</h1> | <h1>espeakng.js 1.49.1 Demo</h1> | ||||
| <form> | <form> | ||||
| <textarea id="texttospeak">Call me Ishmael. Some years ago --- never mind how long precisely --- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation.</textarea> | <textarea id="texttospeak">Call me Ishmael. Some years ago --- never mind how long precisely --- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation.</textarea> | ||||
| <textarea readonly="true" placeholder="IPA" id="ipaarea"></textarea> | |||||
| <div class="speecharg"> | <div class="speecharg"> | ||||
| <label for="pitch">Pitch</label><input id="pitch" type="range" value="50" min="0" max="100" /><button type="button" aria-label="Reset pitch" title="Reset pitch" onclick="resetPitch();">↶</button> | <label for="pitch">Pitch</label><input id="pitch" type="range" value="50" min="0" max="100" /><button type="button" aria-label="Reset pitch" title="Reset pitch" onclick="resetPitch();">↶</button> | ||||
| </div> | </div> | ||||
| <label for="voice">Voice</label><select id="voice"></select><button type="button" aria-label="Reset voice" title="Reset voice" onclick="resetVoice();">↶</button> | <label for="voice">Voice</label><select id="voice"></select><button type="button" aria-label="Reset voice" title="Reset voice" onclick="resetVoice();">↶</button> | ||||
| </div> | </div> | ||||
| <div class="bottom"> | <div class="bottom"> | ||||
| <button type="button" onmousedown="speak();">Speak</button> | |||||
| <button type="button" onmousedown="speakAndIpa();">Speak</button> | |||||
| <button type="button" onmousedown="stop();">Stop</button> | <button type="button" onmousedown="stop();">Stop</button> | ||||
| </div> | </div> | ||||
| <p class="gh"><a href="https://github.com/eeejay/espeak/tree/emscripten">Original Code for eSpeak: Eitan Isaacson</a></p> | <p class="gh"><a href="https://github.com/eeejay/espeak/tree/emscripten">Original Code for eSpeak: Eitan Isaacson</a></p> |
| espeak_SetSynthCallback(NULL); | espeak_SetSynthCallback(NULL); | ||||
| } | } | ||||
| int synth_ipa_(const char* aText, const char* virtualFileName) { | |||||
| /* phoneme_mode | |||||
| bit 1: 0=eSpeak's ascii phoneme names, 1= International Phonetic Alphabet (as UTF-8 characters). | |||||
| bit 7: use (bits 8-23) as a tie within multi-letter phonemes names | |||||
| bits 8-23: separator character, between phoneme names | |||||
| */ | |||||
| espeak_SetSynthCallback(NULL); | |||||
| int phoneme_options = (1 << 1); // Use IPA | |||||
| int use_custom_phoneme_separator = (0 << 7); | |||||
| int phonemes_separator = ' '; // Use a default value | |||||
| int phoneme_conf = phoneme_options | (phonemes_separator << 8); | |||||
| FILE* f_phonemes_out = fopen(virtualFileName,"wb"); | |||||
| if(!f_phonemes_out) | |||||
| return -1; | |||||
| //espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, NULL); | |||||
| espeak_SetPhonemeTrace(phoneme_conf, f_phonemes_out); | |||||
| espeak_Synth(aText, 0, 0, POS_CHARACTER, 0, 0, NULL, NULL); | |||||
| espeak_SetPhonemeTrace(0, NULL); | |||||
| fclose(f_phonemes_out); | |||||
| return 0; | |||||
| } | |||||
| long set_voice( | long set_voice( | ||||
| const char* aName, | const char* aName, | ||||
| const char* aLang=NULL, | const char* aLang=NULL, |
| interface eSpeakNGWorker { | interface eSpeakNGWorker { | ||||
| void eSpeakNGWorker(); | void eSpeakNGWorker(); | ||||
| void synth_(DOMString aText, VoidPtr aCallback); | void synth_(DOMString aText, VoidPtr aCallback); | ||||
| long synth_ipa_(DOMString aText, DOMString virtualFileName); | |||||
| long getSizeOfEventStruct_(); | long getSizeOfEventStruct_(); | ||||
| long set_voice(DOMString aName, DOMString aLang, optional octet gender=0, optional octet age=0, optional octet aVariant=0); | long set_voice(DOMString aName, DOMString aLang, optional octet gender=0, optional octet age=0, optional octet aVariant=0); | ||||
| [Const] attribute espeak_VOICE[] voices; | [Const] attribute espeak_VOICE[] voices; |
| pusher.connect(ctx.destination); | pusher.connect(ctx.destination); | ||||
| console.log(' Creating pusher... done'); | console.log(' Creating pusher... done'); | ||||
| var user_text = document.getElementById('texttospeak').value; | |||||
| // actual synthesis | // actual synthesis | ||||
| console.log(' Calling synthesize...'); | console.log(' Calling synthesize...'); | ||||
| tts.synthesize( | tts.synthesize( | ||||
| document.getElementById('texttospeak').value, | |||||
| user_text, | |||||
| function cb(samples, events) { | function cb(samples, events) { | ||||
| //console.log(' Inside synt cb'); | //console.log(' Inside synt cb'); | ||||
| if (!samples) { | if (!samples) { | ||||
| //console.log(' Leaving synt cb'); | //console.log(' Leaving synt cb'); | ||||
| } // end of function cb | } // end of function cb | ||||
| ); // end of tts.synthesize() | ); // end of tts.synthesize() | ||||
| console.log(' Calling synthesize... done'); | |||||
| console.log(' Calling synthesize... done'); | |||||
| console.log('Leaving speak()'); | console.log('Leaving speak()'); | ||||
| } // end of speak() | } // end of speak() | ||||
| function ipa() { | |||||
| console.log("Synthesizing ipa ... "); | |||||
| var ts = new Date(); | |||||
| var user_text = document.getElementById('texttospeak').value; | |||||
| //user_text = user_text.repeat(50); | |||||
| tts.set_voice(document.getElementById('voice').value); | |||||
| tts.synthesize_ipa(user_text, function(result) { | |||||
| var te = new Date(); | |||||
| document.getElementById('ipaarea').value = result.ipa; | |||||
| console.log("Ipa synthesis done in " + (te-ts) + " ms.") | |||||
| }); | |||||
| } | |||||
| function speakAndIpa() { | |||||
| speak(); | |||||
| ipa(); | |||||
| } | |||||
| function resetPitch() { | function resetPitch() { | ||||
| document.getElementById('pitch').value = 50; | document.getElementById('pitch').value = 50; | ||||
| } | } | ||||
| console.log('Leaving cb1'); | console.log('Leaving cb1'); | ||||
| } // end of function cb1 | } // end of function cb1 | ||||
| ); | ); | ||||
| console.log('Creating eSpeakNG instance... done'); | console.log('Creating eSpeakNG instance... done'); | ||||
| } | } |
| 'set_rate', | 'set_rate', | ||||
| 'set_pitch', | 'set_pitch', | ||||
| 'set_voice', | 'set_voice', | ||||
| 'synthesize' | |||||
| 'synthesize', | |||||
| 'synthesize_ipa' | |||||
| ]) { | ]) { | ||||
| eSpeakNG.prototype[method] = _createAsyncMethod(method); | eSpeakNG.prototype[method] = _createAsyncMethod(method); | ||||
| } | } |
| Runtime.removeFunction(fp); | Runtime.removeFunction(fp); | ||||
| }; | }; | ||||
| eSpeakNGWorker.prototype.synthesize_ipa = function (aText, aCallback) { | |||||
| // Use a unique temp file for the worker. Avoid collisions, just in case. | |||||
| var ipaVirtualFileName = "espeak-ng-ipa-tmp-" + Math.random().toString().substring(2); | |||||
| var res = ""; | |||||
| var code = this.synth_ipa_(aText, ipaVirtualFileName); | |||||
| if(code == 0) | |||||
| res = FS.readFile(ipaVirtualFileName, { encoding: 'utf8' }) | |||||
| // Clean up the tmp file | |||||
| FS.unlink(ipaVirtualFileName); | |||||
| var ret = { | |||||
| code: code, | |||||
| ipa: res | |||||
| } | |||||
| return ret; | |||||
| }; | |||||
| // Make this a worker | // Make this a worker | ||||
| if (typeof WorkerGlobalScope !== 'undefined') { | if (typeof WorkerGlobalScope !== 'undefined') { | ||||
| }); | }); | ||||
| onmessage = function(e) { | onmessage = function(e) { | ||||
| if (!worker) { | if (!worker) { | ||||
| throw 'eSpeakNGWorker worker not initialized'; | throw 'eSpeakNGWorker worker not initialized'; | ||||
| } | } |