| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 | 
function PushAudioNode(context, start_callback, end_callback, buffer_size) {
  this.context = context;
  this.start_callback = start_callback;
  this.end_callback = end_callback;
  this.buffer_size = buffer_size || 4096;
  this.samples_queue = [];
  this.scriptNode = context.createScriptProcessor(this.buffer_size, 1, 1);
  this.connected = false;
  this.sinks = [];
  this.startTime = 0;
  this.closed = false;
  this.track_callbacks = new Map();
}
PushAudioNode.prototype.push = function(chunk) {
  if (this.closed) {
    throw 'Cannot push more chunks after node was closed';
  }
  this.samples_queue.push(chunk);
  if (!this.connected) {
    if (!this.sinks.length) {
      throw 'No destination set for PushAudioNode';
    }
    this._do_connect();
  }
}
PushAudioNode.prototype.close = function() {
  this.closed = true;
}
PushAudioNode.prototype.connect = function(dest) {
  this.sinks.push(dest);
  if (this.samples_queue.length) {
    this._do_connect();
  }
}
PushAudioNode.prototype._do_connect = function() {
  if (this.connected) return;
  this.connected = true;
  for (var dest of this.sinks) {
    this.scriptNode.connect(dest);
  }
  this.scriptNode.onaudioprocess = this.handleEvent.bind(this);
}
PushAudioNode.prototype.disconnect = function() {
  this.scriptNode.onaudioprocess = null;
  this.scriptNode.disconnect();
  this.connected = false;
}
PushAudioNode.prototype.addTrackCallback = function(aTimestamp, aCallback) {
  var callbacks = this.track_callbacks.get(aTimestamp) || [];
  callbacks.push(aCallback);
  this.track_callbacks.set(aTimestamp, callbacks);
}
PushAudioNode.prototype.handleEvent = function(evt) {
  if (!this.startTime) {
    this.startTime = evt.playbackTime;
    if (this.start_callback) {
      this.start_callback();
    }
  }
  var currentTime = evt.playbackTime - this.startTime;
  var playbackDuration = this.scriptNode.bufferSize / this.context.sampleRate;
  for (var entry of this.track_callbacks) {
    var timestamp = entry[0];
    var callbacks = entry[1];
    if (timestamp < currentTime) {
      this.track_callbacks.delete(timestamp);
    } else if (timestamp < currentTime + playbackDuration) {
      for (var cb of callbacks) {
        cb();
      }
      this.track_callbacks.delete(timestamp);
    }
  }
  var offset = 0;
  while (this.samples_queue.length && offset < evt.target.bufferSize) {
    var chunk = this.samples_queue[0];
    var to_copy = chunk.subarray(0, evt.target.bufferSize - offset);
    if (evt.outputBuffer.copyToChannel) {
      evt.outputBuffer.copyToChannel(to_copy, 0, offset);
    } else {
      evt.outputBuffer.getChannelData(0).set(to_copy, offset);
    }
    offset += to_copy.length;
    chunk = chunk.subarray(to_copy.length);
    if (chunk.length)
      this.samples_queue[0] = chunk;
    else
      this.samples_queue.shift();
  }
  if (!this.samples_queue.length && this.closed) {
    if (this.end_callback) {
      this.end_callback(evt.playbackTime - this.startTime);
    }
    this.disconnect();
  }
}
var ctx = new (window.AudioContext || window.webkitAudioContext)();
var tts;
var pusher;
var pusher_buffer_size = 4096;
var chunkID = 0;
function stop() {
  console.log('Inside stop()');
  if (pusher) {
    console.log('  Calling pusher.disconnect...');
    pusher.disconnect();
    console.log('  Calling pusher.disconnect... done');
    pusher = null;
  }
  console.log('Leaving stop()');
} 
function speak() {
  console.log('Inside speak()');
  console.log('  Stopping...');
  stop();
  console.log('  Stopping... done');
  console.log('  Setting rate...');
  tts.set_rate(Number(document.getElementById('rate').value));
  console.log('  Setting rate... done');
  console.log('  Setting pitch...');
  tts.set_pitch(Number(document.getElementById('pitch').value));
  console.log('  Setting pitch... done');
  console.log('  Setting voice...');
  tts.set_voice(document.getElementById('voice').value);
  console.log('  Setting voice... done');
  var now = Date.now();
  chunkID = 0;
  console.log('  Creating pusher...');
  pusher = new PushAudioNode(
    ctx,
    function() {
      
    },
    function() {
      
    },
    pusher_buffer_size
  );
  pusher.connect(ctx.destination);
  console.log('  Creating pusher... done');
  var user_text = document.getElementById('texttospeak').value;
  
  
  console.log('  Calling synthesize...');
  tts.synthesize(
    user_text,
    function cb(samples, events) {
      
      if (!samples) {
        if (pusher) {
          pusher.close();
        }
        return;
      }
      if (pusher) {
        
        pusher.push(new Float32Array(samples));
        ++chunkID;
      }
      if (now) {
        
        now = 0;
      }
      
    } 
  ); 
  console.log('  Calling synthesize... done');  
  console.log('Leaving speak()');
} 
function ipa() {
  
  console.log("Synthesizing ipa ... ");
  var ts = new Date();
  var user_text = document.getElementById('texttospeak').value;
 
  
  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;
}
function resetRate() {
  document.getElementById('rate').value = 175;
}
function resetVoice() {
  document.getElementById('default-voice').selected = true;
}
function initializeDemo() {
  console.log('Creating eSpeakNG instance...');
  tts = new eSpeakNG(
    'js/espeakng.worker.js',
    function cb1() {
      console.log('Inside cb1');
      tts.list_voices(
        function cb2(result) {
          console.log('Inside cb2');
          var sel = document.getElementById('voice');
          var index = 0;
          for (voice of result) {
            var opt = document.createElement('option');
            var languages = voice.languages.map(function(lang) {
              return lang.name;
            }).join(", ");
            opt.text = voice.name + ' (' + languages + ')';
            opt.value = voice.identifier;
            console.log('Adding voice: ' + opt.text);
            sel.add(opt);
            if (voice.name === 'English (Great Britain)') {
              opt.id = 'default-voice';
              opt.selected = true;
            }
          }
          console.log('Leaving cb2');
        } 
      );
      console.log('Removing loading class...');
      document.body.classList.remove('loading');
      console.log('Removing loading class... done');
      console.log('Leaving cb1');
    } 
  );
    
  console.log('Creating eSpeakNG instance... done');
}
 |