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 };