1 /**
  2  * Parse channel informations
  3  * @param {AP_Instrument} instrument
  4  * @param {String} notes
  5  * @param {Number} tempo
  6  * @constructor
  7  */
  8 function AP_Channel(instrument, notes, tempo) {
  9 	this.instrument = instrument;
 10 	this.notes = notes.split(',');
 11 	this.tempo = tempo || 1;
 12 	this.freq = [];
 13 	this.time = 0;
 14 	this.index = 0;
 15 	if (AP_Channel.freqs.length == 0) {
 16 		var a = Math.pow(2, 1/12);
 17 		for (var n=-57; n<50; n++) {
 18 			AP_Channel.freqs.push(440 * Math.pow(a, n));
 19 		}
 20 	}
 21 };
 22 
 23 /**
 24  * Music note index
 25  */
 26 AP_Channel.keys = {c:0,db:1,d:2,eb:3,e:4,f:5,gb:6,g:7,ab:8,a:9,bb:10,b:11};
 27 
 28 /**
 29  * Frequency buffer
 30  */
 31 AP_Channel.freqs = [];
 32 
 33 /**
 34  * Parse one note
 35  * @param {String} note
 36  */
 37 AP_Channel.prototype.parse = function(note) {
 38 	var match = note.match(/([a-z]+)(\d+)([a-z]*)(\d*)([a-z]*)(\d*)([a-z]*)(\d*)([a-z]*)(\d*)([a-z]*)(\d*)/);
 39 	if (match) {
 40 		match.shift();
 41 		while(match.length) {
 42 			var c = match.shift(),
 43 				n = match.shift();
 44 			if (n) {
 45 				this.freq.push(AP_Channel.freqs[parseInt(n) * 12 + AP_Channel.keys[c]]);
 46 			}
 47 		}
 48 	}
 49 };
 50 
 51 /**
 52  * Generate the next value of the chabbel
 53  * @returns {Number}
 54  */
 55 AP_Channel.prototype.get = function() {
 56 	if (++this.index > this.time) {
 57 		var next = this.notes.shift(),
 58 			match = next ? next.match(/^(\d+)(.*)$/) : false;
 59 		if (!match) return false;
 60 		this.freq = [];
 61 		this.time =  this.instrument.sample / parseInt(match[1]) * this.tempo;
 62 		this.index = 0;
 63 		this.parse(match[2]);
 64 	}
 65 	var value = 0;
 66 	for (var i=0; i<this.freq.length; i++) {
 67 		value += this.instrument.get(this.freq[i], this.index);
 68 	}
 69 	return this.freq.length > 0 ? value / this.freq.length : 0;
 70 };