/**
* 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' });