qambi
Version:
MIDI sequencer, loads MIDI files, can record and playback MIDI, uses WebMIDI and WebAudio
99 lines (84 loc) • 2.67 kB
JavaScript
import {context} from './init_audio.js'
import {getEqualPowerCurve} from './util.js'
export class Sample{
constructor(sampleData, event){
this.event = event
this.sampleData = sampleData
}
start(time){
let {sustainStart, sustainEnd} = this.sampleData
//console.log(sustainStart, sustainEnd)
if(sustainStart && sustainEnd){
this.source.loop = true
this.source.loopStart = sustainStart
this.source.loopEnd = sustainEnd
}
this.source.start(time);
}
stop(time, cb){
let {releaseDuration, releaseEnvelope, releaseEnvelopeArray} = this.sampleData
//console.log(releaseDuration, releaseEnvelope)
this.source.onended = cb
if(releaseDuration && releaseEnvelope){
this.startReleasePhase = time
this.releaseFunction = () => {
fadeOut(this.output, {
releaseDuration,
releaseEnvelope,
releaseEnvelopeArray,
})
}
try{
this.source.stop(time + releaseDuration)
}catch(e){
// in Firefox and Safari you can not call stop more than once
}
this.checkPhase()
}else{
try{
this.source.stop(time)
}catch(e){
// in Firefox and Safari you can not call stop more than once
}
}
}
checkPhase(){
//console.log(context.currentTime, this.startReleasePhase)
if(context.currentTime >= this.startReleasePhase){
this.releaseFunction()
return
}
requestAnimationFrame(this.checkPhase.bind(this))
}
}
export function fadeOut(gainNode, settings){
let now = context.currentTime
let values, i, maxi
//console.log(settings)
try{
switch(settings.releaseEnvelope){
case 'linear':
gainNode.gain.linearRampToValueAtTime(gainNode.gain.value, now)
gainNode.gain.linearRampToValueAtTime(0.0, now + settings.releaseDuration)
break
case 'equal power':
case 'equal_power':
values = getEqualPowerCurve(100, 'fadeOut', gainNode.gain.value)
gainNode.gain.setValueCurveAtTime(values, now, settings.releaseDuration)
break
case 'array':
maxi = settings.releaseEnvelopeArray.length
values = new Float32Array(maxi)
for(i = 0; i < maxi; i++){
values[i] = settings.releaseEnvelopeArray[i] * gainNode.gain.value
}
gainNode.gain.setValueCurveAtTime(values, now, settings.releaseDuration)
break
default:
}
}catch(e){
// in Firefox and Safari you can not call setValueCurveAtTime and linearRampToValueAtTime more than once
//console.log(values, now, settings.releaseDuration)
//console.log(e, gainNode)
}
}