jussi-kalliokoski / audiolib.js

audiolib.js is a powerful audio tools library for javascript.
http://audiolibjs.org/
672 stars 58 forks source link

Envelope problem #56

Closed redned closed 12 years ago

redned commented 12 years ago

Hi. I'm having some problems getting the adsr envelope to work. The attack portion is working but only on the first key press. Any subsequent key press the envelope does not work.

Could you shed any light on where I am going wrong please. Cheers.

var 
    osc1,osc2, 
    lfo1,noise,
    dev1, sampleRate, fx, j, volENV, currentNote,currentNote2, noteOnName, noteOffName;
var pressed = [];
var released = [];
var attack;
var decay;
var sustain;
var release;
var velocity = 127;
var time, feedback, lfospeed;

function fillBuffer(buffer, channelCount)
{
    var l   = buffer.length, env,
        smpl1, smpl2, 
        i, n, 
    for (i=0; i<l; i+=channelCount){
        volENV.generate();

        lfo1.generate();//LFO generated
        lfo1.frequency = lfospeed;
        noise.generate();

        osc1.fm = lfo1.getMix() * 0.2;
        osc1.generate();

        smpl1 = osc1.getMix();  
        smpl1 = smpl1 * volENV.getMix();

        for (n=0; n<channelCount; n++){
            buffer[i + n] = fx.pushSample(smpl1 * 0.5) ;
        }
    }
}

window.addEventListener('load', function() {
    dev1            = audioLib.AudioDevice(fillBuffer, 2);
    sampleRate      = dev1.sampleRate;

    volENV = new audioLib.ADSREnvelope(sampleRate, 200, 50, 1, 500, 250, 0);
    //volENV.triggerGate(true);

    fx          = (new audioLib.LP12Filter(sampleRate, 200, 2), new audioLib.Delay(sampleRate, 75, .1));

    lfo1            = new audioLib.Oscillator(sampleRate);
    lfo1.waveShape = 'triangle';

    osc1            = new audioLib.Oscillator(sampleRate, null);

    midiBridge.init({
        connectAllInputs : true,
        ready : function(msg) {
            content.innerHTML = "<h1>loaded</h1><br/>";
        },
        error : function(msg) {
            console.log(msg);
        },
        data : function(midiEvent) {
            if(midiEvent.status == midiBridge.NOTE_ON) {
                        volENV.triggerGate(true);
                        noteOnName = midiEvent.noteName;
                        pressed.unshift(noteOnName);
                        console.log(noteOnName +" on");
                        console.log(pressed);
                osc1 = new audioLib.generators.Note(sampleRate, noteOnName);
                    osc1.waveShape = document.getElementById("waveform").value;
                        osc1.mix = osc1.mix * midiEvent.data2 / 127;
                        currentNote = noteOnName; 
            }
            if(midiEvent.status == midiBridge.NOTE_OFF){// && currentNote == 0){
                        volENV.triggerGate(false);
                        noteOffName = midiEvent.noteName;                       
                        if(pressed.slice(0,1) == noteOffName){
                            osc1 = new audioLib.Oscillator(sampleRate, null);
                    }
                    else{
                            console.log("do nothing");
                    }
            }
        }
    });    
},false);
}
jussi-kalliokoski commented 12 years ago

Hey there!

A quick look reveals a few problems:

if(pressed.slice(0,1) == noteOffName){ this will never be true, slice creates a new array, which is a unique object. What you want is if(pressed[0] === noteOffName){. Also probably a good idea to use triple equals.

volENV = new audioLib.ADSREnvelope(sampleRate, 200, 50, 1, 500, 250, 0); discard the last two arguments and it should work. If you specify the those two, triggerGate will not react, because the ADSREnvelope assumes that you want a static envelope (i.e. the ADSREnvelope starts to oscillate), since you specified a static time for sustain and release.

volENV.triggerGate(false); if you turn the oscillator immediately after the key is lifted, you never get to the release part. To get that as well, you need some kind of decay management. Otherwise this is ok, just combined with the way you're dealing with the oscillators makes it malfunction a bit.

osc1 = new audioLib.Oscillator(sampleRate, null); and osc1 = new audioLib.generators.Note(sampleRate, noteOnName); it's probably a better idea to keep the same oscillator instance all the time, since you only have one oscillator anyway. Just set the frequency to match the note whenever the key changes, and when the key is lifted, set the frequency to zero. Or even better, if you're making a mono synth, you can make the choice of never setting the frequency to zero, instead just release the gate for the envelope, and the sound will fade out.

Hope this helps!

Cheers, Jussi

redned commented 12 years ago

That sorted it. Thanks a lot!