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

@@ -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
- 0
emscripten/espeakng_glue.cpp 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
- 0
emscripten/espeakng_glue.idl 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
emscripten/js/demo.js 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
emscripten/js/espeakng.js 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
- 0
emscripten/post.js 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';
}

Loading…
Cancel
Save