Neon Euphoria

Yes it is

Log in to post a comment.

// ELECTRO EDM FESTIVE
// High-energy dancefloor with bright synths, dirty bass, and energetic percussion

ditty.bpm = 132;

// ===== INPUT SLIDERS =====
input.bassEnergy = 0.8; // min=0, max=1, step=0.1
input.synthBrightness = 0.7; // min=0, max=1, step=0.1

// ===== SYNTH DEFINITIONS =====

// Punchy kick drum with frequency sweep
const kick = synth.def(class {
  constructor(options) {
    this.t = 0;
  }
  process(note, env, tick, options) {
    this.t += ditty.dt;
    // Pitch drop from 150Hz to 60Hz
    const freq = 150 * Math.exp(-this.t * 6);
    return Math.sin(this.t * freq * Math.PI * 2) * env.value;
  }
}, { 
  attack: 0.001, 
  release: 0.5, 
  duration: 1,
  amp: 1.0
});

// Bright closed hi-hats for energy
const hihat = synth.def((phase, env, tick, options) => 
  (Math.random() - 0.5) * env.value
, { 
  attack: 0.0005, 
  release: 0.06, 
  duration: 0.5,
  amp: 0.5
});

// Crashy open hi-hat for transitions
const crashhat = synth.def((phase, env, tick, options) => 
  (Math.random() - 0.5) * env.value
, { 
  attack: 0.001, 
  release: 0.25, 
  duration: 0.5,
  amp: 0.6
});

// Dirty sawtooth bass
const bass = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt;
    // Sawtooth wave
    const raw = (this.phase % 1) * 2 - 1;
    // Soft clipping for aggression
    const clipped = raw > 0.8 ? 1 : raw < -0.8 ? -1 : raw;
    return clipped * env.value * 0.85;
  }
}, { 
  attack: 0.02, 
  release: 0.12,
  amp: 0.8
});

// Bright square wave synth for leads
const brightSynth = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt;
    // Square wave
    const raw = this.phase % 1 < 0.5 ? 1 : -1;
    return raw * env.value * 0.7;
  }
}, { 
  attack: 0.01, 
  release: 0.15,
  amp: 0.6
});

// Arpeggiated synth for festive energy
const arpSynth = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt;
    // Triangle wave
    const saw = this.phase % 1;
    const tri = saw < 0.5 ? saw * 4 - 1 : 3 - saw * 4;
    return tri * env.value * 0.6;
  }
}, { 
  attack: 0.005, 
  release: 0.1,
  amp: 0.5
});

// Snare crack
const snare = synth.def((phase, env, tick, options) => 
  ((Math.random() - 0.5) * 2) * Math.sin(phase * 2 * Math.PI * 200) * env.value
, { 
  attack: 0.0005, 
  release: 0.15,
  amp: 0.7
});

// Perc for fills
const perc = synth.def((phase, env, tick, options) => 
  Math.sin(phase * 2 * Math.PI) * env.value
, { 
  attack: 0.001, 
  release: 0.05,
  amp: 0.4
});

// ===== MAIN LOOPS =====

// LOOP 1: KICK - 4-on-the-floor base (essential for EDM)
loop( (loopCount) => {
  for (let i = 0; i < 4; i++) {
    kick.play(c2, { amp: 1.0 });
    sleep(1);
  }
}, { 
  name: 'kick', 
  amp: 1.0,
  sync: 4
});

// LOOP 2: CLOSED HI-HATS on 16th notes (high energy)
loop( (loopCount) => {
  for (let i = 0; i < 16; i++) {
    if (i % 4 !== 0) {  // Skip some to create pocket
      hihat.play(c5, { amp: 0.4 + Math.random() * 0.1 });
    }
    sleep(0.25);
  }
}, { 
  name: 'hihat_closed',
  amp: 0.9,
  sync: 4
});

// LOOP 3: SNARE on 2 and 4 (classic EDM pattern)
loop( (loopCount) => {
  sleep(1);        // Beat 2
  snare.play(c4, { amp: 0.8 });
  sleep(1);
  
  sleep(1);        // Beat 4
  snare.play(c4, { amp: 0.75 });
  sleep(1);
}, { 
  name: 'snare',
  amp: 0.85,
  sync: 4
});

// LOOP 4: CRASH HATS for variation and transitions
loop( (loopCount) => {
  if (loopCount % 2 === 1) {  // Every other loop (every 4 bars)
    sleep(3.5);
    crashhat.play(c5, { amp: 0.6 });
    sleep(0.5);
  } else {
    sleep(4);
  }
}, { 
  name: 'crash',
  amp: 0.7,
  sync: 4
});

// LOOP 5: MAIN BASS - Dirty and energetic
loop( (loopCount) => {
  // Festive bass pattern with more movement
  const bassPattern = [c1, g0, c1, eb1, c1, g0, c1, b0];
  
  for (let i = 0; i < bassPattern.length; i++) {
    bass.play(bassPattern[i], { 
      duration: 1,
      release: 0.08,
      attack: 0.015,
      amp: 0.7 + input.bassEnergy * 0.2
    });
    sleep(1);
  }
}, { 
  name: 'bass',
  amp: 0.9,
  sync: 8
});

// LOOP 6: BRIGHT SYNTH MELODY - Festival vibe
loop( (loopCount) => {
  const melodyNotes = [c5, g4, c5, eb5, c5, g4, a4, g4];
  
  for (let i = 0; i < melodyNotes.length; i++) {
    brightSynth.play(melodyNotes[i], { 
      duration: 0.8,
      release: 0.1,
      attack: 0.01,
      amp: 0.5 + input.synthBrightness * 0.15
    });
    sleep(1);
  }
}, { 
  name: 'bright_synth',
  amp: 0.75,
  sync: 8
});

// LOOP 7: ARPEGGIATED FESTIVE SYNTH (adds high-energy texture)
loop( (loopCount) => {
  const arpNotes = scale(c5, scales['major'], 1);
  
  for (let i = 0; i < 16; i++) {
    arpSynth.play(arpNotes[i % arpNotes.length], { 
      duration: 0.4,
      release: 0.08,
      amp: 0.3 + Math.random() * 0.1
    });
    sleep(0.25);
  }
}, { 
  name: 'arp_synth',
  amp: 0.65,
  sync: 4
});

// LOOP 8: PERCUSSION FILLS (breaks up monotony with energy bursts)
loop( (loopCount) => {
  if (loopCount % 4 === 3) {  // Every 16 bars
    // Drum fill
    for (let i = 0; i < 8; i++) {
      perc.play(f4 + i * 2, { 
        duration: 0.25,
        release: 0.04,
        amp: 0.3 + Math.random() * 0.15
      });
      sleep(0.25);
    }
  } else {
    sleep(4);
  }
}, { 
  name: 'fills',
  amp: 0.6,
  sync: 4
});

// LOOP 9: SECONDARY BRIGHT SYNTH - Counter-melody (festive interaction)
loop( (loopCount) => {
  if (loopCount > 0 && loopCount % 2 === 0) {
    // Play counter-melody on even loops
    const counterNotes = [a5, b5, c6, b5, a5];
    
    for (let i = 0; i < counterNotes.length; i++) {
      brightSynth.play(counterNotes[i], { 
        duration: 1,
        release: 0.12,
        attack: 0.01,
        amp: 0.4
      });
      sleep(1);
    }
  } else {
    sleep(5);
  }
}, { 
  name: 'counter_synth',
  amp: 0.6,
  sync: 8
});