Вопрос

I can't seem to create two oscillators with independent gain envelopes.

The code below creates two buttons which each play a sine tone at a different pitch. When I click on the first button, I hear the tone grow in volume as it should. But, when I click the second button, the tone reacts as if it is connected to the gain of the first tone. For example, if I click the second button (turning on the second tone) while the first tone is at volume 1, the second tone will enter at volume 1, even though it is supposed to envelope from 0 to 1 to 0 over the course of 10 seconds.

Can I only have one gain node per audio context? Or is there some other reason that the gains of these oscillators are being connected? In addition, after I play the tones once, I cannot play them again, which makes me especially think that I am doing something wrong. : )

Thanks. A link is below and the code is below that. This is my first post here so let me know if you need anything else. This code must be run in versions of Chrome or Safari that support the web audio api.

http://whitechord.org/just_mod/poly_test.html

WAAPI tests

    <button onclick="play()">play one</button>
    <button onclick="play2()">play two</button>


    <script>

        var context;

        window.addEventListener('load', initAudio, false);

        function initAudio() {
            try {
                context = new webkitAudioContext();
            } catch(e) {
                onError(e);
            }
        }

        function play() {

            var oscillator = context.createOscillator(); 
            var gainNode = context.createGainNode();
            gainNode.gain.value = 0.0;
            oscillator.connect(gainNode);
            gainNode.connect(context.destination);
            oscillator.frequency.value = 700;

            gainNode.gain.linearRampToValueAtTime(0.0, 0); // envelope  
            gainNode.gain.linearRampToValueAtTime(0.1, 5); // envelope  
            gainNode.gain.linearRampToValueAtTime(0.0, 10); // envelope 

            oscillator.noteOn(0);
        }


        function play2() {

            var oscillator2 = context.createOscillator(); 
            var gainNode2 = context.createGainNode();
            gainNode2.gain.value = 0.0;
            oscillator2.connect(gainNode2);
            gainNode2.connect(context.destination);
            oscillator2.frequency.value = 400;

            gainNode2.gain.linearRampToValueAtTime(0.0, 0); // envelope 
            gainNode2.gain.linearRampToValueAtTime(0.1, 5); // envelope 
            gainNode2.gain.linearRampToValueAtTime(0.0, 10); // envelope    

            oscillator2.noteOn(0);
        }


        /* error */

        function onError(e) {
            alert(e);   
        }



    </script>

</body>
</html>
Это было полезно?

Решение

Can I only have one gain node per audio context? Or is there some other reason that the gains of these oscillators are being connected? In addition, after I play the tones once, I cannot play them again, which makes me especially think that I am doing something wrong. : )

You can have as many gain nodes as you want (this is how you could achieve mixing bus-like setups, for example), so that's not the problem. Your problem is the following:

Remember that the second parameter to linearRampToValueAtTime() is time in the same time coordinate system as your context.currentTime.

And your context.currentTime is always moving forward in real time, so all your ramps, curves, etc. should be calculated relative to it.

If you want something to happen 4 seconds from now, you'd pass context.currentTime + 4 to the Web Audio API function.

So, change all your calls linearRampToValueAtTime() in your code, so that they look like:

gainNode2.gain.linearRampToValueAtTime(0.0, context.currentTime); // envelope     
gainNode2.gain.linearRampToValueAtTime(0.1, context.currentTime + 5); // envelope     
gainNode2.gain.linearRampToValueAtTime(0.0, context.currentTime + 10); // envelope 

And that should take care of your issues.

BTW you have a stray double quote in your BODY opening markup tag.

Другие советы

Ask Will Conklin

gainNode2.gain.linearRampToValueAtTime(0.1, context.currentTime + 5); // envelope
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top