Synthetic Sorrow

os

Log in to post a comment.

// DARK MELANCHOLIC HARDCORE TECHNO
// Heavy, distorted, introspective with industrial textures and haunting atmospheres

ditty.bpm = 145;

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

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

// Deep, heavy kick with distortion
const kick = synth.def(class {
  constructor(options) {
    this.t = 0;
  }
  process(note, env, tick, options) {
    this.t += ditty.dt;
    // Deep sub kick with harsh overtones
    const freq = 80 * Math.exp(-this.t * 5);
    const raw = Math.sin(this.t * freq * Math.PI * 2);
    // Heavy distortion
    const distorted = Math.tanh(raw * (1 + options.distortion) * 3);
    return distorted * env.value * 0.9;
  }
}, { 
  attack: 0.0005, 
  release: 0.6, 
  duration: 1,
  amp: 0.95,
  distortion: 0.6
});

// Industrial noise hi-hat (harsher)
const hihat = synth.def((phase, env, tick, options) => {
  const noise = (Math.random() - 0.5) * 2;
  // Add metallic overtones
  const metallic = Math.sin(phase * 2 * Math.PI * 200);
  return (noise * 0.7 + metallic * 0.3) * env.value;
}, { 
  attack: 0.0005, 
  release: 0.05, 
  duration: 0.5,
  amp: 0.45
});

// Dark, distorted closed hat
const darkhat = synth.def((phase, env, tick, options) => {
  const noise = (Math.random() - 0.5) * 2;
  // Harsher, more compressed
  const harsh = Math.tanh(noise * 2);
  return harsh * env.value;
}, { 
  attack: 0.001, 
  release: 0.08, 
  duration: 0.5,
  amp: 0.2
});

// Distorted sawtooth bass - angry and heavy
const heavyBass = 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;
    // Hard clipping distortion
    const distorted = Math.tanh(raw * (2 + options.distortion * 2));
    return distorted * env.value * 0.85;
  }
}, { 
  attack: 0.03, 
  release: 0.14,
  amp: 0.75,
  distortion: 0.8
});

// Sad, minor key synth - melancholic
const melancholicSynth = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt;
    // Square wave with pulse width modulation
    const pwm = 0.3 + Math.sin(tick * 0.5) * 0.1;
    const raw = this.phase % 1 < pwm ? 1 : -1;
    return raw * env.value * 0.7;
  }
}, { 
  attack: 0.02, 
  release: 0.25,
  amp: 0.1
});

// Deep pad synth - atmospheric darkness
const darkPad = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt * 0.5; // Slower
    const wave1 = Math.sin(this.phase * 2 * Math.PI);
    const wave2 = Math.sin(this.phase * 2.01 * Math.PI); // Slight detuning
    return (wave1 + wave2) * 0.5 * env.value * 0.6;
  }
}, { 
  attack: 0.1, 
  release: 0.5,
  amp: 0.4
});

// Industrial noise perc
const perc = synth.def((phase, env, tick, options) => {
  const noise = (Math.random() - 0.5) * 2;
  const sine = Math.sin(phase * 2 * Math.PI * 150);
  return (noise * 0.6 + sine * 0.4) * env.value;
}, { 
  attack: 0.001, 
  release: 0.06,
  amp: 0.35
});

// Drone/ambient texture
const drone = synth.def(class {
  constructor(options) {
    this.phase = 0;
  }
  process(note, env, tick, options) {
    this.phase += midi_to_hz(note) * ditty.dt * 0.25; // Very slow
    const base = Math.sin(this.phase * 2 * Math.PI);
    const sub = Math.sin(this.phase * 0.5 * Math.PI);
    return (base + sub) * 0.5 * env.value * 0.5;
  }
}, { 
  attack: 0.3, 
  release: 0.6,
  amp: 0.3
});

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

// LOOP 1: HEAVY DISTORTED KICK - Dark foundation
loop( (loopCount) => {
  for (let i = 0; i < 4; i++) {
    kick.play(c2, { 
      amp: 0.95,
      distortion: 0.6 + input.distortionAmount * 0.3
    });
    sleep(1);
  }
}, { 
  name: 'kick', 
  amp: 1.0,
  sync: 4
});

// LOOP 2: INDUSTRIAL HI-HATS (harsh, compressed rhythm)
loop( (loopCount) => {
  for (let i = 0; i < 16; i++) {
    if (i % 2 === 0) {  // Every other 16th note
      if (Math.random() > 0.3) {  // Random skips for tension
        hihat.play(c5, { amp: 0.35 + Math.random() * 0.1 });
      }
    }
    sleep(0.25);
  }
}, { 
  name: 'hihat_industrial',
  amp: 0.8,
  sync: 4
});

// LOOP 3: DARK CLOSED HATS (syncopated, oppressive)
loop( (loopCount) => {
  sleep(0.75);
  darkhat.play(c4, { amp: 0.38 });
  sleep(0.5);
  
  darkhat.play(c4, { amp: 0.35 });
  sleep(1);
  
  darkhat.play(c4, { amp: 0.4 });
  sleep(1.75);
}, { 
  name: 'darkhat',
  amp: 0.4,
  sync: 4
});

// LOOP 4: HEAVY DISTORTED BASS - Oppressive and angry
loop( (loopCount) => {
  // Minor key pattern - melancholic and dark
  const bassPattern = [g0, d1, g0, bb0, g0, d1, f0, d1];
  
  for (let i = 0; i < bassPattern.length; i++) {
    heavyBass.play(bassPattern[i], { 
      duration: 1,
      release: 0.1,
      attack: 0.02,
      amp: 0.75 + input.darknessFactor * 0.15,
      distortion: 0.7 + input.distortionAmount * 0.2
    });
    sleep(1);
  }
}, { 
  name: 'bass_heavy',
  amp: 0.85,
  sync: 8
});

// LOOP 5: MELANCHOLIC SYNTH MELODY (sad minor key progression)
loop( (loopCount) => {
  // Gm - Bb - Gm - Eb progression (dark and introspective)
  const melodyNotes = [g4, d4, g4, eb5, g4, d4, f4, d4];
  
  for (let i = 0; i < melodyNotes.length; i++) {
    melancholicSynth.play(melodyNotes[i], { 
      duration: 0.9,
      release: 0.2,
      attack: 0.02,
      amp: 0.45 + input.darknessFactor * 0.1
    });
    sleep(1);
  }
}, { 
  name: 'melancholic_synth',
  amp: 0.2,
  sync: 8
});

// LOOP 6: DARK ATMOSPHERIC PAD (underlying melancholy)
loop( (loopCount) => {
  // Long droning pad in minor key
  darkPad.play(g2, { 
    duration: 8,
    release: 0.5,
    attack: 0.2,
    amp: 0.35
  });
  sleep(4);
  
  darkPad.play(eb2, { 
    duration: 8,
    release: 0.5,
    attack: 0.2,
    amp: 0.32
  });
  sleep(4);
}, { 
  name: 'dark_pad',
  amp: 0.65,
  sync: 8
});

// LOOP 7: DRONE/AMBIENT TEXTURE (hypnotic darkness)
loop( (loopCount) => {
  // Very low, slowly evolving drone
  drone.play(g1, { 
    duration: 16,
    release: 0.6,
    attack: 0.3,
    amp: 0.28
  });
  sleep(8);
  
  drone.play(d1, { 
    duration: 16,
    release: 0.6,
    attack: 0.3,
    amp: 0.26
  });
  sleep(8);
}, { 
  name: 'drone',
  amp: 0.55,
  sync: 16
});

// LOOP 8: INDUSTRIAL PERCUSSION HITS (sparse, unsettling)
loop( (loopCount) => {
  sleep(1.25);
  perc.play(g3, { 
    duration: 0.4,
    release: 0.05,
    amp: 0.25
  });
  sleep(1.5);
  
  perc.play(d3, { 
    duration: 0.4,
    release: 0.05,
    amp: 0.22
  });
  sleep(1.25);
}, { 
  name: 'industrial_perc',
  amp: 0.6,
  sync: 4
});

// LOOP 9: BASS COUNTERPOINT (adds depth and sadness)
loop( (loopCount) => {
  if (loopCount > 1) {
    // Plays a different bass pattern for contrast after 8 bars
    const counterBass = [g0, c1, g0, f0, g0, c1, bb0, c1];
    
    for (let i = 0; i < counterBass.length; i++) {
      heavyBass.play(counterBass[i], { 
        duration: 1,
        release: 0.11,
        attack: 0.025,
        amp: 0.65,
        distortion: 0.6
      });
      sleep(1);
    }
  } else {
    sleep(8);
  }
}, { 
  name: 'bass_counter',
  amp: 0.7,
  sync: 8
});

// LOOP 10: HARMONIC DISSONANCE (creates unease)
loop( (loopCount) => {
  if (loopCount % 3 === 2) {  // Every 24 bars
    // Intentional dissonant notes for tension
    for (let i = 0; i < 8; i++) {
      melancholicSynth.play(g4 + (i % 2 === 0 ? 1 : 3), { 
        duration: 0.4,
        release: 0.08,
        amp: 0.25,
        pan: Math.sin(i * Math.PI / 4)
      });
      sleep(0.5);
    }
  } else {
    sleep(4);
  }
}, { 
  name: 'dissonance',
  amp: 0.5,
  sync: 4
});