Skip to content

Instantly share code, notes, and snippets.

@timjb
Created January 23, 2011 11:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timjb/791993 to your computer and use it in GitHub Desktop.
Save timjb/791993 to your computer and use it in GitHub Desktop.
var spawn = require('child_process').spawn;
var EventEmitter = require('events').EventEmitter;
///////////
// Sound //
///////////
function Sound(str, lang, amplitude, speed) {
EventEmitter.apply(this);
this.str = str;
this.lang = lang || 'english';
this.amplitude = (amplitude == undefined) ? 0.5 : amplitude;
this.speed = speed || 160;
}
Sound.prototype.__proto__ = EventEmitter.prototype;
Sound.prototype.play = function() {
var amplitude = Math.round(20*this.amplitude);
var process = spawn('espeak', [
'-v', this.lang,
'-a', amplitude,
'-s', this.speed,
'"'+this.str.replace(/\"/, '\\"')+'"'
]);
var self = this;
process.on('exit', function() {
self.emit('said');
});
};
Sound.prototype.startLoop = function(interval) {
this.endLoop(); // Make sure no loop is running
this.interval = setInterval(this.play.bind(this), interval);
};
Sound.prototype.endLoop = function() {
clearInterval(this.interval);
};
Sound.prototype.times = function(times, delay) {
var self = this;
function f() {
self.play();
times--;
if (times) {
setTimeout(f, delay);
} else {
self.emit('times_end');
}
}
f();
};
Sound.prototype.startBackground = function() {
this.backgroundCallback = this.play.bind(this);
this.on('said', this.backgroundCallback);
this.play();
};
Sound.prototype.stopBackground = function() {
this.removeListener('said', this.backgroundCallback);
};
Sound.prototype.clone = function() {
return new Sound(this.str, this.lang, this.amplitude, this.speed);
};
//////////
// Song //
//////////
function Song(tact, speed) {
EventEmitter.apply(this);
this.tact = tact || 16;
this.speed = speed || 1;
this.boundNote = this.note.bind(this);
}
Song.prototype.__proto__ = EventEmitter.prototype;
Song.prototype.note = function() {
var count = this.count;
var note_values = ['sixteenth'];
if (count % 2 == 0) note_values.push('eighth');
if (count % 4 == 0) note_values.push('quarter');
if (count % 8 == 0) note_values.push('half');
if (count == 0) note_values.push('whole');
//console.log(note_values);
for (var i = 0, l = note_values.length; i < l; i++) {
var note_value = note_values[i];
this.emit(note_value);
this.emit('tact_'+this.currTact+'_'+note_value);
}
if (count == 0) {
this.emit('tact');
this.emit('tact_'+this.currTact);
}
this.emit('tact_'+this.currTact+'_'+count);
this.count = (this.count + 1) % this.tact;
if (this.count == 0) {
this.currTact++;
}
};
Song.prototype.play = function() {
this.stop();
this.resume();
};
Song.prototype.stop = function() {
this.pause();
this.currTact = 0;
this.count = 0;
};
Song.prototype.pause = function() {
clearInterval(this.boundNote);
};
Song.prototype.resume = function() {
setInterval(this.boundNote, this.speed*(1e3/this.tact));
};
//////////
// Test //
//////////
// Bg
/*var sound = new Sound('oui', 'english', 0, 250);
sound.on('said', function() {
sound.amplitude += (1-sound.amplitude)/4;
});
sound.startBackground();
setTimeout(function() {
sound.stopBackground();
}, 10000);*/
// Fg
var sound2 = new Sound('je suis un parisien', 'french', .8, 50);
//sound2.startBackground();
//sound2.times(10, 1000);
var aaa = new Sound('aaaaaaaaaaaa');
var song = new Song(16, 1);
function on(evt, sound) {
if (typeof sound == 'string') {
sound = new Sound(sound);
}
song.on(String(evt), sound.play.bind(sound));
};
on('quarter', 'b');
on('half', 'a');
on('tact', new Sound('annanannananna', 'french'));
//on('tact', aaa);
//on('tact_5', sound2);
song.play();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment