Fork: Testouille 01

Testouillade

Log in to post a comment.

/**
 * Expert Sound Design: Dittytoy Track
 * BPM: 124
 * Scale: Pentatonic
 * Mood: New tracks with presets
 * Complexity: 0.8
 */

ditty.bpm = 124;

// Pentatonic Scale Helper (C Major Pentatonic)
const scale = [0, 2, 4, 7, 9]; // C, D, E, G, A
const getNote = (degree, octave) => 48 + (octave * 12) + scale[degree % 5];

// --- Arrangement Patterns (16 sections, each section = 4 beats / 1 bar) ---
const leadPattern  = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0];
const bassPattern  = [0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0];
const padPattern   = [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0];
const kickPattern  = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1];
const kick2Pattern = [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1];
const hihatPattern = [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0];
const pad2Pattern  = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1];

// --- Synth Definitions ---

// Lead Synth: Sawtooth, Slow Attack, Long Release, Dark Filter
const leadSynth = synth.def((phase, env, tick, options) => {
    const val = Math.sin(phase * 2 * Math.PI) > 0 ? 1 : -1; // Basic Saw/Square hybrid for clarity
    const saw = (phase % 1) * 2 - 1;
    const cutoff = options.filter || 0.08;
    return saw * env.value;
}, { attack: 1.071, release: 3.3 });

// Deep Bass: Square, Plucky, High Filter
const deepBass = synth.def((phase, env, tick, options) => {
    const square = Math.sin(phase * 2 * Math.PI) > 0 ? 1 : -1;
    return square * env.value;
}, { attack: 0.001, release: 0.1 });

// Atmosphere Pad: Sine, Soft
const atmospherePad = synth.def((phase, env, tick, options) => {
    return Math.sin(phase * 2 * Math.PI) * env.value;
}, { attack: 1.141, release: 3 });

// Kick Drum: Sine with pitch envelope
const kickSynth = synth.def((phase, env, tick, options) => {
    const pEnv = Math.exp(-tick * 40);
    return Math.sin(phase * 2 * Math.PI + pEnv * 10) * env.value;
}, { attack: 0.01, release: 0.1 });

// New Kick: Punchier
const kick2Synth = synth.def((phase, env, tick, options) => {
    const pEnv = Math.exp(-tick * 60);
    return Math.sin(phase * 2 * Math.PI + pEnv * 15) * env.value;
}, { attack: 0.001, release: 0.15 });

// New Hihat: White Noise
const hihatSynth = synth.def((phase, env, tick, options) => {
    return (Math.random() * 2 - 1) * env.value;
}, { attack: 0.001, release: 0.05 });

// New Pad: Square, Dark
const pad2Synth = synth.def((phase, env, tick, options) => {
    const square = Math.sin(phase * 2 * Math.PI) > 0 ? 0.5 : -0.5;
    return square * env.value;
}, { attack: 1, release: 3.2 });

// --- Loops ---

loop((loopCount) => {
    if (leadPattern[loopCount % 16]) {
        for (let i = 0; i < 4; i++) {
            leadSynth.play(getNote(i, 2), { amp: 0.4, filter: 0.08 });
            sleep(1);
        }
    } else {
        sleep(4);
    }
}, { name: 'lead' });

loop((loopCount) => {
    if (bassPattern[loopCount % 16]) {
        for (let i = 0; i < 8; i++) {
            deepBass.play(getNote(0, -1), { amp: 0.6, filter: 0.87 });
            sleep(0.5);
        }
    } else {
        sleep(4);
    }
}, { name: 'bass' });

loop((loopCount) => {
    if (padPattern[loopCount % 16]) {
        atmospherePad.play(getNote(0, 1), { amp: 0.5 });
        atmospherePad.play(getNote(2, 1), { amp: 0.5 });
        sleep(4);
    } else {
        sleep(4);
    }
}, { name: 'pad' });

loop((loopCount) => {
    if (kickPattern[loopCount % 16]) {
        for (let i = 0; i < 4; i++) {
            kickSynth.play(35, { amp: 0.8 });
            sleep(1);
        }
    } else {
        sleep(4);
    }
}, { name: 'kick' });

loop((loopCount) => {
    if (kick2Pattern[loopCount % 16]) {
        for (let i = 0; i < 4; i++) {
            kick2Synth.play(40, { amp: 0.7 });
            sleep(0.5);
            if (i % 2 === 0) {
                kick2Synth.play(40, { amp: 0.4 });
            }
            sleep(0.5);
        }
    } else {
        sleep(4);
    }
}, { name: 'kick2' });

loop((loopCount) => {
    if (hihatPattern[loopCount % 16]) {
        for (let i = 0; i < 16; i++) {
            hihatSynth.play(0, { amp: 0.2 + Math.random() * 0.1 });
            sleep(0.25);
        }
    } else {
        sleep(4);
    }
}, { name: 'hihat' });

loop((loopCount) => {
    if (pad2Pattern[loopCount % 16]) {
        pad2Synth.play(getNote(4, 0), { amp: 0.3 });
        pad2Synth.play(getNote(1, 0), { amp: 0.3 });
        sleep(4);
    } else {
        sleep(4);
    }
}, { name: 'pad2' });