0

I am making an 8-bit music generator for some 8-bit stuff thing that I am making. Below is the whole code of the page:

var sys = {
    el: function(id){
        return(document.getElementById(id));
    },
    audio: function(vol,type){
        audio.volume = vol;
        type = type;
    }
};
var audio = {
    volume: 100,
    type: "square",
    active: false
};
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();
function beep(frequency,duration,volume = audio.volume) {
        var oscillator = audioCtx.createOscillator();
        var gainNode = audioCtx.createGain();

        oscillator.connect(gainNode);
        gainNode.connect(audioCtx.destination);

        gainNode.gain.value = volume;
        oscillator.frequency.value = frequency;
        oscillator.type = audio.type;

        oscillator.start();

        setTimeout(
            function() {
                oscillator.stop();
            },
            duration
        );
};
var tracks = {
    "untitled-1": {
        frequency: [140,20,40,140,20,40],
        volume: [1,1,1,1,1,1],
        duration: [100,100,200,100,100,200],
        type: ["square",null,null,null,null,null],
        length: 6
    }
};
function play(trackname){
    var track = tracks[trackname];
    var totalDur = 0;
    for(var i = 0; i < track.length; i++){
        setTimeout(() => {
            var track = tracks[trackname];
            try{
                totalDur += track.duration[i];
                if(track.type[i] != null && track.type[i] != "same"){
                    audio.type = track.type[i];
                }
                beep(track.frequency[i],track.duration[i],track.volume[i]);
            }catch(err){
                alert(err);
                try{
                    alert("Frequency: " + track.frequency[i] + "Hz\nVolume: " + track.volume[i] + "\nDuration: " + track.duration[i] + "ms\nType: " + track.type[i] + "\nTrack name: " + trackname + "\nLoop number: " + i);
                }catch(err2){
                    alert(err2);
                }
            }
        },totalDur + track.duration[i]);
    }
}
/*None yet, still working on the other stuff first*/
<!DOCTYPE html>
<html>
    <head>
        <title>8-bit stuff, idk</title>
    </head>
    <body>
        <button onclick="audio.active = false;">Stop all sounds</button>
        <table border="1" cellSpacing="0px"><caption>Sounds</caption>
            <tr>
                <th>Name</th>
                <th>Actions</th>
            </tr>
            <tr>
                <td>untitled-1</td>
                <td><button onclick="play('untitled-1');">Play</button></td>
            </tr>
        </table>
    </body>
</html>

My problem is the for loop with setTimeouts in it. The error handling thing I set up keeps showing me that i is always 6, and that is what is keeping the program from making sounds. untitled-1 is a place holder name for the test track. Please help me with this. I know why this is happening but I do not know how to get around it.

  • See the [linked question's answers](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example). But TL;DR: Use `let` in your `for` loop, not `var`. (There's really no place for `var` in modern JavaScript programming.) – T.J. Crowder Sep 22 '21 at 18:01

0 Answers0