Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.52k stars 983 forks source link

Waveform getValue() never seems to return numbers between -1 and 1 (as the docs suggest it should). #947

Closed cordial closed 3 years ago

cordial commented 3 years ago

Describe the bug

I am using getValue as follows -

    const [playerWave, setPlayerWave] = useState(() => initialiseWave());
    function initialiseWave() {
        return new Waveform();
    }
    player.load(fireBaseUrl).then(() => {
        Transport.scheduleRepeat(function (time) {
            player.start(time);
                }, "4n");
                    startTime = now() + 5.5;
                    // player has previously been set to toDestination...
                    player.connect(playerWave);
                    Transport.start(startTime);
                });
            })
            .catch((err) => {
                                ...
            });
 if (player.state == "started") {
            const waveValues = playerWave.getValue();
            const waveSum = waveValues.reduce((a, b) => a + b, 0);
            const waveAverage = waveSum / waveValues.length || 0;
            console.log(waveValues);
            let waveColour = p5.map(waveAverage, -1, 1, 0, 255);
            p5.lerpColor(p5.color(white), p5.color(black), waveColour);
        }

When I output the values of waveValues, as you can see by the attached image, they barely stray from 0. I haven't modified the gain or the volume, I would expect the values to be bound by the max/min of something? How are the numbers calculated and what would it take to have values that use the whole range from -1 to 1 given different inputs i.e playing different sounds? Or is there some constant or formula I should be multiplying each number by? Seems odd that if you do nothing to volume etc that they barely change from 0.

Screenshot 2021-09-20 at 15 09 58

Note: Browsers' Autoplay Policy leads to a lot of subtle and inconsistent bugs where Tone.js produces no sound. Check out the link for more information and the solution.

To Reproduce

See code samples above

Expected behavior I would except much more of the getValue results returned to be larger and smaller than they are i.e. barely moving from 0. Are the values returned absolute and based on volume levels?

Additional context this is running in next.js/react

cordial commented 3 years ago

The more I think about this, the more i think its related to how the sounds are recorded - do you have levels at which sounds should be recorded such that getValues will return a max of 1 and min of minus 1?

tambien commented 3 years ago

-1 to 1 is the normal range of the audio signal. I believe it's possible for it to be outside of that range (maybe?), but more typically you'll see very small numbers closet o 0 like you're getting.

You can normalize the array by dividing by the max, that'll bring it between -1 to 1, but it won't be consistent between frames unless you smooth that max value across the frames.

What i often do is something like Math.pow(val, 0.1) to boost the values substantially without bringing it outside of the [-1,1] range.