Adding IPA output to emscripten js library and demo

This commit is contained in:
Ben
2017-07-28 17:06:55 +02:00
parent 22270bd259
commit c98ed977f2
6 changed files with 90 additions and 5 deletions
+8 -1
View File
@@ -52,6 +52,12 @@
display: block;
margin-bottom: 1rem;
}
#ipaarea {
width: 100%;
height: 8rem;
display: block;
margin-bottom: 1rem;
}
p.gh {
color: #333;
text-align: right;
@@ -100,6 +106,7 @@
<h1>espeakng.js 1.49.1 Demo</h1>
<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 readonly="true" placeholder="IPA" id="ipaarea"></textarea>
<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>
</div>
@@ -110,7 +117,7 @@
<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 class="bottom">
<button type="button" onmousedown="speak();">Speak</button>
<button type="button" onmousedown="speakAndIpa();">Speak</button>
<button type="button" onmousedown="stop();">Stop</button>
</div>
<p class="gh"><a href="https://github.com/eeejay/espeak/tree/emscripten">Original Code for eSpeak: Eitan Isaacson</a></p>
+29
View File
@@ -50,6 +50,35 @@ public:
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(
const char* aName,
const char* aLang=NULL,
+1
View File
@@ -52,6 +52,7 @@ interface espeak_EVENT {
interface eSpeakNGWorker {
void eSpeakNGWorker();
void synth_(DOMString aText, VoidPtr aCallback);
long synth_ipa_(DOMString aText, DOMString virtualFileName);
long getSizeOfEventStruct_();
long set_voice(DOMString aName, DOMString aLang, optional octet gender=0, optional octet age=0, optional octet aVariant=0);
[Const] attribute espeak_VOICE[] voices;
+27 -3
View File
@@ -179,10 +179,12 @@ function speak() {
pusher.connect(ctx.destination);
console.log(' Creating pusher... done');
var user_text = document.getElementById('texttospeak').value;
// actual synthesis
console.log(' Calling synthesize...');
tts.synthesize(
document.getElementById('texttospeak').value,
user_text,
function cb(samples, events) {
//console.log(' Inside synt cb');
if (!samples) {
@@ -203,11 +205,32 @@ function speak() {
//console.log(' Leaving synt cb');
} // end of function cb
); // end of tts.synthesize()
console.log(' Calling synthesize... done');
console.log(' Calling synthesize... done');
console.log('Leaving 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() {
document.getElementById('pitch').value = 50;
}
@@ -254,5 +277,6 @@ function initializeDemo() {
console.log('Leaving cb1');
} // end of function cb1
);
console.log('Creating eSpeakNG instance... done');
}
+2 -1
View File
@@ -63,7 +63,8 @@ for (var method of [
'set_rate',
'set_pitch',
'set_voice',
'synthesize'
'synthesize',
'synthesize_ipa'
]) {
eSpeakNG.prototype[method] = _createAsyncMethod(method);
}
+23
View File
@@ -93,6 +93,28 @@ eSpeakNGWorker.prototype.synthesize = function (aText, aCallback) {
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
if (typeof WorkerGlobalScope !== 'undefined') {
@@ -104,6 +126,7 @@ if (typeof WorkerGlobalScope !== 'undefined') {
});
onmessage = function(e) {
if (!worker) {
throw 'eSpeakNGWorker worker not initialized';
}