From 34e4a5130e555138afd5f290670e52be292d8605 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sat, 23 May 2020 10:45:10 +0800 Subject: [PATCH] delete mid.js --- libs/thirdparty/LICENSE.md | 29 -- libs/thirdparty/mid.js | 701 ------------------------------------- libs/thirdparty/mid.min.js | 1 - 3 files changed, 731 deletions(-) delete mode 100644 libs/thirdparty/mid.js delete mode 100644 libs/thirdparty/mid.min.js diff --git a/libs/thirdparty/LICENSE.md b/libs/thirdparty/LICENSE.md index 667f1d31..2d1241cf 100644 --- a/libs/thirdparty/LICENSE.md +++ b/libs/thirdparty/LICENSE.md @@ -228,35 +228,6 @@ localforage WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - -mid -============ - -Copyright (c) 2010, Matt Westcott & Ben Firshman -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The names of its contributors may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zip ============ diff --git a/libs/thirdparty/mid.js b/libs/thirdparty/mid.js deleted file mode 100644 index 45af166d..00000000 --- a/libs/thirdparty/mid.js +++ /dev/null @@ -1,701 +0,0 @@ -var sampleRate = 44100; /* hard-coded in Flash player */ - -function AudioPlayer(context, generator, loop) { - - // Uses Webkit Web Audio API if available - sampleRate = context.sampleRate; - - var channelCount = 2; - var bufferSize = 4096*4; // Higher for less gitches, lower for less latency - - var node = context.createScriptProcessor(bufferSize, 0, channelCount); - - node.onaudioprocess = function(e) { process(e) }; - - function process(e) { - if (generator.finished) { - if (loop) { - generator.reset(); - generator.finished = false; - } - else { - node.disconnect(); - return; - } - } - - var dataLeft = e.outputBuffer.getChannelData(0); - var dataRight = e.outputBuffer.getChannelData(1); - - var generate = generator.generate(bufferSize); - - for (var i = 0; i < bufferSize; ++i) { - dataLeft[i] = generate[i*2]; - dataRight[i] = generate[i*2+1]; - } - } - - // start - // node.connect(context.destination); - - return { - 'play': function () { - node.connect(context.destination); - }, - 'pause': function() { - node.disconnect(); - } - } -} -/* -class to parse the .mid file format -(depends on stream.js) -*/ -function MidiFile(data) { - function readChunk(stream) { - var id = stream.read(4); - var length = stream.readInt32(); - return { - 'id': id, - 'length': length, - 'data': stream.read(length) - }; - } - - var lastEventTypeByte; - - function readEvent(stream) { - var event = {}; - event.deltaTime = stream.readVarInt(); - var eventTypeByte = stream.readInt8(); - if ((eventTypeByte & 0xf0) == 0xf0) { - /* system / meta event */ - if (eventTypeByte == 0xff) { - /* meta event */ - event.type = 'meta'; - var subtypeByte = stream.readInt8(); - var length = stream.readVarInt(); - switch(subtypeByte) { - case 0x00: - event.subtype = 'sequenceNumber'; - if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length; - event.number = stream.readInt16(); - return event; - case 0x01: - event.subtype = 'text'; - event.text = stream.read(length); - return event; - case 0x02: - event.subtype = 'copyrightNotice'; - event.text = stream.read(length); - return event; - case 0x03: - event.subtype = 'trackName'; - event.text = stream.read(length); - return event; - case 0x04: - event.subtype = 'instrumentName'; - event.text = stream.read(length); - return event; - case 0x05: - event.subtype = 'lyrics'; - event.text = stream.read(length); - return event; - case 0x06: - event.subtype = 'marker'; - event.text = stream.read(length); - return event; - case 0x07: - event.subtype = 'cuePoint'; - event.text = stream.read(length); - return event; - case 0x20: - event.subtype = 'midiChannelPrefix'; - if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length; - event.channel = stream.readInt8(); - return event; - case 0x2f: - event.subtype = 'endOfTrack'; - if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length; - return event; - case 0x51: - event.subtype = 'setTempo'; - if (length != 3) throw "Expected length for setTempo event is 3, got " + length; - event.microsecondsPerBeat = ( - (stream.readInt8() << 16) - + (stream.readInt8() << 8) - + stream.readInt8() - ) - return event; - case 0x54: - event.subtype = 'smpteOffset'; - if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length; - var hourByte = stream.readInt8(); - event.frameRate = { - 0x00: 24, 0x20: 25, 0x40: 29, 0x60: 30 - }[hourByte & 0x60]; - event.hour = hourByte & 0x1f; - event.min = stream.readInt8(); - event.sec = stream.readInt8(); - event.frame = stream.readInt8(); - event.subframe = stream.readInt8(); - return event; - case 0x58: - event.subtype = 'timeSignature'; - if (length != 4) throw "Expected length for timeSignature event is 4, got " + length; - event.numerator = stream.readInt8(); - event.denominator = Math.pow(2, stream.readInt8()); - event.metronome = stream.readInt8(); - event.thirtyseconds = stream.readInt8(); - return event; - case 0x59: - event.subtype = 'keySignature'; - if (length != 2) throw "Expected length for keySignature event is 2, got " + length; - event.key = stream.readInt8(true); - event.scale = stream.readInt8(); - return event; - case 0x7f: - event.subtype = 'sequencerSpecific'; - event.data = stream.read(length); - return event; - default: - // console.log("Unrecognised meta event subtype: " + subtypeByte); - event.subtype = 'unknown' - event.data = stream.read(length); - return event; - } - event.data = stream.read(length); - return event; - } else if (eventTypeByte == 0xf0) { - event.type = 'sysEx'; - var length = stream.readVarInt(); - event.data = stream.read(length); - return event; - } else if (eventTypeByte == 0xf7) { - event.type = 'dividedSysEx'; - var length = stream.readVarInt(); - event.data = stream.read(length); - return event; - } else { - throw "Unrecognised MIDI event type byte: " + eventTypeByte; - } - } else { - /* channel event */ - var param1; - if ((eventTypeByte & 0x80) == 0) { - /* running status - reuse lastEventTypeByte as the event type. - eventTypeByte is actually the first parameter - */ - param1 = eventTypeByte; - eventTypeByte = lastEventTypeByte; - } else { - param1 = stream.readInt8(); - lastEventTypeByte = eventTypeByte; - } - var eventType = eventTypeByte >> 4; - event.channel = eventTypeByte & 0x0f; - event.type = 'channel'; - switch (eventType) { - case 0x08: - event.subtype = 'noteOff'; - event.noteNumber = param1; - event.velocity = stream.readInt8(); - return event; - case 0x09: - event.noteNumber = param1; - event.velocity = stream.readInt8(); - if (event.velocity == 0) { - event.subtype = 'noteOff'; - } else { - event.subtype = 'noteOn'; - } - return event; - case 0x0a: - event.subtype = 'noteAftertouch'; - event.noteNumber = param1; - event.amount = stream.readInt8(); - return event; - case 0x0b: - event.subtype = 'controller'; - event.controllerType = param1; - event.value = stream.readInt8(); - return event; - case 0x0c: - event.subtype = 'programChange'; - event.programNumber = param1; - return event; - case 0x0d: - event.subtype = 'channelAftertouch'; - event.amount = param1; - return event; - case 0x0e: - event.subtype = 'pitchBend'; - event.value = param1 + (stream.readInt8() << 7); - return event; - default: - throw "Unrecognised MIDI event type: " + eventType - } - } - } - - stream = Stream(data); - var headerChunk = readChunk(stream); - if (headerChunk.id != 'MThd' || headerChunk.length != 6) { - throw "Bad .mid file - header not found"; - } - var headerStream = Stream(headerChunk.data); - var formatType = headerStream.readInt16(); - var trackCount = headerStream.readInt16(); - var timeDivision = headerStream.readInt16(); - - if (timeDivision & 0x8000) { - throw "Expressing time division in SMTPE frames is not supported yet" - } else { - ticksPerBeat = timeDivision; - } - - var header = { - 'formatType': formatType, - 'trackCount': trackCount, - 'ticksPerBeat': ticksPerBeat - } - var tracks = []; - for (var i = 0; i < header.trackCount; i++) { - tracks[i] = []; - var trackChunk = readChunk(stream); - if (trackChunk.id != 'MTrk') { - throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id; - } - var trackStream = Stream(trackChunk.data); - while (!trackStream.eof()) { - var event = readEvent(trackStream); - tracks[i].push(event); - //console.log(event); - } - } - - return { - 'header': header, - 'tracks': tracks - } -} -function Replayer(midiFile, synth) { - var trackStates = []; - var beatsPerMinute = 120; - var ticksPerBeat = midiFile.header.ticksPerBeat; - var channelCount = 16; - var channels = []; - var nextEventInfo; - var samplesToNextEvent; - - function Channel() { - - var generatorsByNote = {}; - var currentProgram = PianoProgram; - - function noteOn(note, velocity) { - if (generatorsByNote[note] && !generatorsByNote[note].released) { - /* playing same note before releasing the last one. BOO */ - generatorsByNote[note].noteOff(); /* TODO: check whether we ought to be passing a velocity in */ - } - generator = currentProgram.createNote(note, velocity); - synth.addGenerator(generator); - generatorsByNote[note] = generator; - } - function noteOff(note, velocity) { - if (generatorsByNote[note] && !generatorsByNote[note].released) { - generatorsByNote[note].noteOff(velocity); - } - } - function setProgram(programNumber) { - currentProgram = PROGRAMS[programNumber] || PianoProgram; - } - - return { - 'noteOn': noteOn, - 'noteOff': noteOff, - 'setProgram': setProgram - } - } - - function getNextEvent() { - var ticksToNextEvent = null; - var nextEventTrack = null; - var nextEventIndex = null; - - for (var i = 0; i < trackStates.length; i++) { - if ( - trackStates[i].ticksToNextEvent != null - && (ticksToNextEvent == null || trackStates[i].ticksToNextEvent < ticksToNextEvent) - ) { - ticksToNextEvent = trackStates[i].ticksToNextEvent; - nextEventTrack = i; - nextEventIndex = trackStates[i].nextEventIndex; - } - } - if (nextEventTrack != null) { - /* consume event from that track */ - var nextEvent = midiFile.tracks[nextEventTrack][nextEventIndex]; - if (midiFile.tracks[nextEventTrack][nextEventIndex + 1]) { - trackStates[nextEventTrack].ticksToNextEvent += midiFile.tracks[nextEventTrack][nextEventIndex + 1].deltaTime; - } else { - trackStates[nextEventTrack].ticksToNextEvent = null; - } - trackStates[nextEventTrack].nextEventIndex += 1; - /* advance timings on all tracks by ticksToNextEvent */ - for (var i = 0; i < trackStates.length; i++) { - if (trackStates[i].ticksToNextEvent != null) { - trackStates[i].ticksToNextEvent -= ticksToNextEvent - } - } - nextEventInfo = { - 'ticksToEvent': ticksToNextEvent, - 'event': nextEvent, - 'track': nextEventTrack - } - var beatsToNextEvent = ticksToNextEvent / ticksPerBeat; - var secondsToNextEvent = beatsToNextEvent / (beatsPerMinute / 60); - samplesToNextEvent += secondsToNextEvent * synth.sampleRate; - } else { - nextEventInfo = null; - samplesToNextEvent = null; - self.finished = true; - } - } - - function generate(samples) { - var data = new Array(samples*2); - var samplesRemaining = samples; - var dataOffset = 0; - - while (true) { - if (samplesToNextEvent != null && samplesToNextEvent <= samplesRemaining) { - /* generate samplesToNextEvent samples, process event and repeat */ - var samplesToGenerate = Math.ceil(samplesToNextEvent); - if (samplesToGenerate > 0) { - synth.generateIntoBuffer(samplesToGenerate, data, dataOffset); - dataOffset += samplesToGenerate * 2; - samplesRemaining -= samplesToGenerate; - samplesToNextEvent -= samplesToGenerate; - } - - handleEvent(); - getNextEvent(); - } else { - /* generate samples to end of buffer */ - if (samplesRemaining > 0) { - synth.generateIntoBuffer(samplesRemaining, data, dataOffset); - samplesToNextEvent -= samplesRemaining; - } - break; - } - } - return data; - } - - function handleEvent() { - var event = nextEventInfo.event; - switch (event.type) { - case 'meta': - switch (event.subtype) { - case 'setTempo': - beatsPerMinute = 60000000 / event.microsecondsPerBeat - } - break; - case 'channel': - switch (event.subtype) { - case 'noteOn': - channels[event.channel].noteOn(event.noteNumber, event.velocity); - break; - case 'noteOff': - channels[event.channel].noteOff(event.noteNumber, event.velocity); - break; - case 'programChange': - //console.log('program change to ' + event.programNumber); - channels[event.channel].setProgram(event.programNumber); - break; - } - break; - } - } - - function reset() { - for (var i = 0; i < midiFile.tracks.length; i++) { - trackStates[i] = { - 'nextEventIndex': 0, - 'ticksToNextEvent': ( - midiFile.tracks[i].length ? - midiFile.tracks[i][0].deltaTime : - null - ) - }; - } - for (var i = 0; i < channelCount; i++) { - channels[i] = Channel(); - } - samplesToNextEvent = 0; - getNextEvent(); - } - - reset(); - - var self = { - 'reset': reset, - 'generate': generate, - 'finished': false - } - return self; -} -/* Wrapper for accessing strings through sequential reads */ -function Stream(str) { - var position = 0; - - function read(length) { - var result = str.substr(position, length); - position += length; - return result; - } - - /* read a big-endian 32-bit integer */ - function readInt32() { - var result = ( - (str.charCodeAt(position) << 24) - + (str.charCodeAt(position + 1) << 16) - + (str.charCodeAt(position + 2) << 8) - + str.charCodeAt(position + 3)); - position += 4; - return result; - } - - /* read a big-endian 16-bit integer */ - function readInt16() { - var result = ( - (str.charCodeAt(position) << 8) - + str.charCodeAt(position + 1)); - position += 2; - return result; - } - - /* read an 8-bit integer */ - function readInt8(signed) { - var result = str.charCodeAt(position); - if (signed && result > 127) result -= 256; - position += 1; - return result; - } - - function eof() { - return position >= str.length; - } - - /* read a MIDI-style variable-length integer - (big-endian value in groups of 7 bits, - with top bit set to signify that another byte follows) - */ - function readVarInt() { - var result = 0; - while (true) { - var b = readInt8(); - if (b & 0x80) { - result += (b & 0x7f); - result <<= 7; - } else { - /* b is the last byte */ - return result + b; - } - } - } - - return { - 'eof': eof, - 'read': read, - 'readInt32': readInt32, - 'readInt16': readInt16, - 'readInt8': readInt8, - 'readVarInt': readVarInt - } -} -function SineGenerator(freq) { - var self = {'alive': true}; - var period = sampleRate / freq; - var t = 0; - - self.generate = function(buf, offset, count) { - for (; count; count--) { - var phase = t / period; - var result = Math.sin(phase * 2 * Math.PI); - buf[offset++] += result; - buf[offset++] += result; - t++; - } - } - - return self; -} - -function SquareGenerator(freq, phase) { - var self = {'alive': true}; - var period = sampleRate / freq; - var t = 0; - - self.generate = function(buf, offset, count) { - for (; count; count--) { - var result = ( (t / period) % 1 > phase ? 1 : -1); - buf[offset++] += result; - buf[offset++] += result; - t++; - } - } - - return self; -} - -function ADSRGenerator(child, attackAmplitude, sustainAmplitude, attackTimeS, decayTimeS, releaseTimeS) { - var self = {'alive': true} - var attackTime = sampleRate * attackTimeS; - var decayTime = sampleRate * (attackTimeS + decayTimeS); - var decayRate = (attackAmplitude - sustainAmplitude) / (decayTime - attackTime); - var releaseTime = null; /* not known yet */ - var endTime = null; /* not known yet */ - var releaseRate = sustainAmplitude / (sampleRate * releaseTimeS); - var t = 0; - - self.noteOff = function() { - if (self.released) return; - releaseTime = t; - self.released = true; - endTime = releaseTime + sampleRate * releaseTimeS; - } - - self.generate = function(buf, offset, count) { - if (!self.alive) return; - var input = new Array(count * 2); - for (var i = 0; i < count*2; i++) { - input[i] = 0; - } - child.generate(input, 0, count); - - childOffset = 0; - while(count) { - if (releaseTime != null) { - if (t < endTime) { - /* release */ - while(count && t < endTime) { - var ampl = sustainAmplitude - releaseRate * (t - releaseTime); - buf[offset++] += input[childOffset++] * ampl; - buf[offset++] += input[childOffset++] * ampl; - t++; - count--; - } - } else { - /* dead */ - self.alive = false; - return; - } - } else if (t < attackTime) { - /* attack */ - while(count && t < attackTime) { - var ampl = attackAmplitude * t / attackTime; - buf[offset++] += input[childOffset++] * ampl; - buf[offset++] += input[childOffset++] * ampl; - t++; - count--; - } - } else if (t < decayTime) { - /* decay */ - while(count && t < decayTime) { - var ampl = attackAmplitude - decayRate * (t - attackTime); - buf[offset++] += input[childOffset++] * ampl; - buf[offset++] += input[childOffset++] * ampl; - t++; - count--; - } - } else { - /* sustain */ - while(count) { - buf[offset++] += input[childOffset++] * sustainAmplitude; - buf[offset++] += input[childOffset++] * sustainAmplitude; - t++; - count--; - } - } - } - } - - return self; -} - -function midiToFrequency(note) { - return 440 * Math.pow(2, (note-69)/12); -} - -PianoProgram = { - 'attackAmplitude': 0.2, - 'sustainAmplitude': 0.1, - 'attackTime': 0.02, - 'decayTime': 0.3, - 'releaseTime': 0.02, - 'createNote': function(note, velocity) { - var frequency = midiToFrequency(note); - return ADSRGenerator( - SineGenerator(frequency), - this.attackAmplitude * (velocity / 128), this.sustainAmplitude * (velocity / 128), - this.attackTime, this.decayTime, this.releaseTime - ); - } -} - -StringProgram = { - 'createNote': function(note, velocity) { - var frequency = midiToFrequency(note); - return ADSRGenerator( - SineGenerator(frequency), - 0.5 * (velocity / 128), 0.2 * (velocity / 128), - 0.4, 0.8, 0.4 - ); - } -} - -PROGRAMS = { - 41: StringProgram, - 42: StringProgram, - 43: StringProgram, - 44: StringProgram, - 45: StringProgram, - 46: StringProgram, - 47: StringProgram, - 49: StringProgram, - 50: StringProgram -}; - -function Synth(sampleRate) { - - var generators = []; - - function addGenerator(generator) { - generators.push(generator); - } - - function generate(samples) { - var data = new Array(samples*2); - generateIntoBuffer(samples, data, 0); - return data; - } - - function generateIntoBuffer(samplesToGenerate, buffer, offset) { - for (var i = offset; i < offset + samplesToGenerate * 2; i++) { - buffer[i] = 0; - } - for (var i = generators.length - 1; i >= 0; i--) { - generators[i].generate(buffer, offset, samplesToGenerate); - if (!generators[i].alive) generators.splice(i, 1); - } - } - - return { - 'sampleRate': sampleRate, - 'addGenerator': addGenerator, - 'generate': generate, - 'generateIntoBuffer': generateIntoBuffer - } -} diff --git a/libs/thirdparty/mid.min.js b/libs/thirdparty/mid.min.js deleted file mode 100644 index 62466cc1..00000000 --- a/libs/thirdparty/mid.min.js +++ /dev/null @@ -1 +0,0 @@ -var sampleRate=44100;function AudioPlayer(b,f,a){sampleRate=b.sampleRate;var c=2;var g=4096*4;var d=b.createScriptProcessor(g,0,c);d.onaudioprocess=function(h){e(h)};function e(m){if(f.finished){if(a){f.reset();f.finished=false}else{d.disconnect();return}}var l=m.outputBuffer.getChannelData(0);var k=m.outputBuffer.getChannelData(1);var h=f.generate(g);for(var j=0;j>4;u.channel=t&15;u.type="channel";switch(i){case 8:u.subtype="noteOff";u.noteNumber=v;u.velocity=w.readInt8();return u;case 9:u.noteNumber=v;u.velocity=w.readInt8();if(u.velocity==0){u.subtype="noteOff"}else{u.subtype="noteOn"}return u;case 10:u.subtype="noteAftertouch";u.noteNumber=v;u.amount=w.readInt8();return u;case 11:u.subtype="controller";u.controllerType=v;u.value=w.readInt8();return u;case 12:u.subtype="programChange";u.programNumber=v;return u;case 13:u.subtype="channelAftertouch";u.amount=v;return u;case 14:u.subtype="pitchBend";u.value=v+(w.readInt8()<<7);return u;default:throw"Unrecognised MIDI event type: "+i}}}stream=Stream(g);var k=a(stream);if(k.id!="MThd"||k.length!=6){throw"Bad .mid file - header not found"}var f=Stream(k.data);var d=f.readInt16();var h=f.readInt16();var p=f.readInt16();if(p&32768){throw"Expressing time division in SMTPE frames is not supported yet"}else{ticksPerBeat=p}var j={"formatType":d,"trackCount":h,"ticksPerBeat":ticksPerBeat};var m=[];for(var e=0;e0){c.generateIntoBuffer(r,t,p);p+=r*2;s-=r;e-=r}i();g()}else{if(s>0){c.generateIntoBuffer(s,t,p);e-=s}break}}return t}function i(){var p=m.event;switch(p.type){case"meta":switch(p.subtype){case"setTempo":o=60000000/p.microsecondsPerBeat}break;case"channel":switch(p.subtype){case"noteOn":d[p.channel].noteOn(p.noteNumber,p.velocity);break;case"noteOff":d[p.channel].noteOff(p.noteNumber,p.velocity);break;case"programChange":d[p.channel].setProgram(p.programNumber);break}break}}function f(){for(var p=0;p127){i-=256}b+=1;return i}function c(){return b>=g.length}function d(){var j=0;while(true){var i=h();if(i&128){j+=(i&127);j<<=7}else{return j+i}}}return{"eof":c,"read":e,"readInt32":f,"readInt16":a,"readInt8":h,"readVarInt":d}}function SineGenerator(c){var a={"alive":true};var d=sampleRate/c;var b=0;a.generate=function(g,i,h){for(;h;h--){var f=b/d;var e=Math.sin(f*2*Math.PI);g[i++]+=e;g[i++]+=e;b++}};return a}function SquareGenerator(d,a){var b={"alive":true};var e=sampleRate/d;var c=0;b.generate=function(g,i,h){for(;h;h--){var f=((c/e)%1>a?1:-1);g[i++]+=f;g[i++]+=f;c++}};return b}function ADSRGenerator(c,i,k,h,l,j){var n={"alive":true};var f=sampleRate*h;var g=sampleRate*(h+l);var b=(i-k)/(g-f);var a=null;var e=null;var d=k/(sampleRate*j);var m=0;n.noteOff=function(){if(n.released){return}a=m;n.released=true;e=a+sampleRate*j};n.generate=function(p,t,s){if(!n.alive){return}var o=new Array(s*2);for(var r=0;r=0;g--){c[g].generate(f,j,h);if(!c[g].alive){c.splice(g,1)}}}return{"sampleRate":b,"addGenerator":e,"generate":a,"generateIntoBuffer":d}}; \ No newline at end of file