user1861582
user1861582

Reputation: 119

Web Audio API - Ramping Gain to Avoid Clicks

I'm trying to get rid of the clicks in my application by fading the gain. With the code below, I can hear the sound shifting but it doesn't fade out.

var oscillator = audioContext.createOscillator();
oscillator.connect(gainNode);
oscillator.type = 'sine'; // sine, triangle, sawtooth
console.log(self.currentPitch);
if(isFinite(self.currentPitch)==true){
    oscillator.frequency.value = self.currentPitch;
    // connect it to the output
    oscillator.connect(audioContext.destination);
    // start the note
    oscillator.start(0);

setTimeout(function(){
    var now = audioContext.currentTime;
    //gainNode.gain.value=0;
    gainNode.gain.linearRampToValueAtTime(0,now+.05);
    oscillator.stop(now+.05);
}, self.duration*1000);

Here is the complete code:

var Musical = function(){

    var self=this;

    self.basePitch= 420;
    self.currentPitch=420;
    self.baseLineLength=$("#guidecircles circle").first().attr("r");
    self.currentLineLength=100;
    self.duration=.2; //time in seconds
    self.playPosition=0;
    self.playTimer=false;    

     try {
            if (! window.AudioContext) {
                if (! window.webkitAudioContext) {
                    self.bad_browser();
                    return;
                }
                window.AudioContext = window.webkitAudioContext;
            }

            var audioContext = new AudioContext();
        }
        catch(e) {
            console.log('Web Audio API is not supported in this browser');
    }

    var gainNode = audioContext.createGain();
    gainNode.connect(audioContext.destination);


    /* Playing a tone */
    self.playTone=function(){

        self.setCurrentPitch();

         // create the oscillator
        var oscillator = audioContext.createOscillator();
        oscillator.connect(gainNode);
        oscillator.type = 'sine'; // sine, triangle, sawtooth
        console.log(self.currentPitch);
        if(isFinite(self.currentPitch)==true){
            oscillator.frequency.value = self.currentPitch;
            // connect it to the output
            oscillator.connect(audioContext.destination);
            // start the note
            oscillator.start(0);

            setTimeout(function(){
                var now = audioContext.currentTime;
                //gainNode.gain.value=0;
                gainNode.gain.linearRampToValueAtTime(0,now+.05);
                oscillator.stop(now+.05);
            }, self.duration*1000);
        }

       /* if(typeof oscillator !="undefined"){

        }*/

        return self;

    }    

    /* Get current pitch */
    self.setCurrentPitch=function(){
        /* find ratio of current line length to base line length */
        var ratio=parseFloat(self.baseLineLength/self.currentLineLength);
        /* apply ratio to base pitch and set the current pitch */
        self.currentPitch=self.basePitch*ratio;
        console.log(self.baseLineLength,self.currentLineLength,"ratio:"+ratio);
    }

    /* play music */
    self.play=function(){

        self.playTimer=setInterval(function(){ playNext() }, self.duration*1000);

        return self;
    }  

    var playNext=function(){

        var toneLine=$("#musicallines line").eq(self.playPosition);
        $("#musicallines line").removeClass('playing');
        toneLine.addClass('playing');
        if(self.playPosition>($("#musicallines line").length-1)){
            clearInterval(self.playTimer);
            self.playPosition=0;
        }   else { 

        self.playPosition++;
        self.currentLineLength=toneLine.LineEquation().getMagnitude();
        self.playTone();

        }
    }    


    self.bad_browser=function(){
        alert("Your browser does not support web audio");   
    }    

   return self;
}

To see a running version of it go to this site:

RulerandCompass.net

The musical.js file on the live site doesn't have the update with the gain adjustment. The site is a drawing tool for creating ruler and compass patterns.

Ruler and compass drawing

To draw, using the circle tools click on one point then another. Intersection points have a geometric relationship to each other. To make music draw with the musical line tool shown selected below. The pitch is determined by dividing the base pitch (220hz) by the ratio of the first radius to the new line.

Type "p" on the keyboard to play the composition.

enter image description here

Upvotes: 1

Views: 684

Answers (1)

padenot
padenot

Reputation: 1555

You need to setValueAtTime before using other automation functions.

To fade out, you want gainNode.gain.setTargetAtTime(0, audioContext.currentTime, 0.1), where 0.1 is the time constant of a first-order filter, see https://en.wikipedia.org/wiki/Time_constant#Exponential_decay.

Upvotes: 1

Related Questions