Browse Source

Adding IPA output to emscripten js library and demo

master
Ben 7 years ago
parent
commit
c98ed977f2

+ 8
- 1
emscripten/demo.html View File

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();">&#x21b6;</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();">&#x21b6;</button>
</div> </div>
<label for="voice">Voice</label><select id="voice"></select><button type="button" aria-label="Reset voice" title="Reset voice" onclick="resetVoice();">&#x21b6;</button> <label for="voice">Voice</label><select id="voice"></select><button type="button" aria-label="Reset voice" title="Reset voice" onclick="resetVoice();">&#x21b6;</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>

+ 29
- 0
emscripten/espeakng_glue.cpp View File

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,

+ 1
- 0
emscripten/espeakng_glue.idl View File

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;

+ 27
- 3
emscripten/js/demo.js View File

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');
} }

+ 2
- 1
emscripten/js/espeakng.js View File

'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);
} }

+ 23
- 0
emscripten/post.js View File

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';
} }

Loading…
Cancel
Save