JSFiddle - React, Tailwind, and code Playground

by Ben Gillbanks

HTML

<script src="https://cdn.jsdelivr.net/gh/KilledByAPixel/ZzFX/ZzFXMicro.js"></script>
<script src="https://cdn.jsdelivr.net/gh/keithclark/ZzFXM/zzfxm.js"></script>
    <h1>zzfxm Music Generator</h1>
    <button id="playButton">Play Music</button>

JavaScript

let keys = ["cb", "c", "c#", "db", "d", "eb", "e", "f", "f#", "gb", "g", "a", "ab", "bb", "b",
            "a#m", "d#m", "g#m", "c#m", "f#m", "bm", "em", "am", "dm", "gm", "cm", "fm", "bbm", "ebm", "abm"];
            
let keys_major = ["cb", "c", "c#", "db", "d", "eb", "e", "f", "f#", "gb", "g", "a", "ab", "bb", "b"];
let keys_minor = ["a#m", "d#m", "g#m", "c#m", "f#m", "bm", "em", "am", "dm", "gm", "cm", "fm", "bbm", "ebm", "abm"];

let numbars = 80;
let progression = [];
let barlength = 1024;
let allowedchords = [1, 4, 5];
let key = "c";
let scale = [];
let keychanges = [];

// Define instruments for zzfxM
const instruments = [
    [.9, 0, 143, , , .35, 3],  // Instrument 0
    [1, 0, 216, , , .45, 1, 4, , , 50],  // Instrument 1
    [.75, 0, 196, , .08, .18, 3]  // Instrument 2
];

// Initialize scales and set up chord mappings
function updateScales() {
    if (key == "c") scale = ["c", "d", "e", "f", "g", "a", "b"];
    // Add more keys as needed...
    console.log("Updated scale for key: ", key);
}

// Generate the song's progression and patterns
function init() {
    // Update the scales
    updateScales();

    // Create random chord progression
    for (let i = 0; i < numbars; i++) {
        let valid = false;
        while (!valid) {
            let chord = allowedchords[Math.floor(Math.random() * allowedchords.length)];
            if (i == 0 || progression[i - 1] !== chord) {
                progression.push(chord);
                valid = true;
            }
        }
    }

    // Set up random key changes
    keychanges = [[key, 0]];
    let nk = 4;
    for (let i = 0; i < nk - 1; i++) {
        let randomKey = keys[Math.floor(Math.random() * keys.length)];
        keychanges.push([randomKey, Math.floor((i + 1) * numbars / nk)]);
    }

    return generateSong();
}

// Map chord number to notes in the scale
function intToChord(chord) {
    if (chord === 1) return [scale[0], scale[2], scale[4]]; // I chord
    if (chord === 4) return [scale[3],...