🔍

8-bit worlds made from 8-bit audio

STABLE FAST 3D – https://huggingface.co/spaces/stabilityai/stable-fast-3d

THE SYNTH

ONLINE EDITOR : https://editor.p5js.org/brucexxxbanner/sketches/NrfXBIXQe


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Sound Wave Visualizer</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
  <script src="https://sfxr.me/riffwave.js"></script>
  <script src="https://sfxr.me/sfxr.js"></script>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <div id="controls">
    <label for="attack">Attack:</label>
    <input type="range" id="attack" min="0" max="1" step="0.01" value="0.03">
    <br>
    <label for="sustain">Sustain:</label>
    <input type="range" id="sustain" min="0" max="1" step="0.01" value="0.317">
    <br>
    <label for="decay">Decay:</label>
    <input type="range" id="decay" min="0" max="1" step="0.01" value="0.272">
    <br>
    <label for="freq_ramp">Frequency Ramp:</label>
    <input type="range" id="freq_ramp" min="0" max="1" step="0.01" value="0.438">
    <br>
    <label for="vib_strength">Vibration Strength:</label>
    <input type="range" id="vib_strength" min="0" max="1" step="0.01" value="0">
    <br>
    <label for="vib_speed">Vibration Speed:</label>
    <input type="range" id="vib_speed" min="0" max="1" step="0.01" value="0">
    <br>
    <label for="repeat_speed">Repeat Speed:</label>
    <input type="range" id="repeat_speed" min="0" max="1" step="0.01" value="0.756">
    <br>
    <label for="env_punch">Env Punch:</label>
    <input type="range" id="env_punch" min="0" max="1" step="0.01" value="0">
    <br>
    <label for="arp_speed">Arpeggio Speed:</label>
    <input type="range" id="arp_speed" min="0" max="1" step="0.01" value="0">
    <br>
    <label for="arp_mod">Arpeggio Mod:</label>
    <input type="range" id="arp_mod" min="0" max="1" step="0.01" value="0">
    <br>
    <button id="randomize">~ RANDOM ~</button>
    <button id="saveAudio">Save AUDIO</button>
    
    <button id="saveCanvas">Save CURVE</button>


  </div>
  <script src="sketch.js"></script>
</body>
</html>


let alive = 0;
let xoff = 0;
let yoff = 0;
let wave = [];
let waveGraphics;
let waveWidth = 800 - 2 * 40;
let playbackPosition = 0;
let soundDuration = 0;
let soundStartTime = 0;

let pad = 80;

let sound = {
  "oldParams": true,
  "wave_type": 1,
  "p_env_attack": 0.03,
  "p_env_sustain": 0.317,
  "p_env_punch": 0,
  "p_env_decay": 0.272,
  "p_base_freq": 0.261,
  "p_freq_limit": 0,
  "p_freq_ramp": 0.438,
  "p_freq_dramp": 0,
  "p_vib_strength": 0,
  "p_vib_speed": 0,
  "p_arp_mod": 0,
  "p_arp_speed": 0,
  "p_duty": 1,
  "p_duty_ramp": 0,
  "p_repeat_speed": 0.756,
  "p_pha_offset": 0,
  "p_pha_ramp": 0,
  "p_lpf_freq": 1,
  "p_lpf_ramp": 0,
  "p_lpf_resonance": 0,
  "p_hpf_freq": 0,
  "p_hpf_ramp": 0,
  "sound_vol": 0.25,
  "sample_rate": 44100,
  "sample_size": 8
};

function setup() {
  createCanvas(800,500);
  waveGraphics = createGraphics(width, height);

  // Set up slider controls
  select('#attack').input(() => sound.p_env_attack = float(select('#attack').value()));
  select('#sustain').input(() => sound.p_env_sustain = float(select('#sustain').value()));
  select('#decay').input(() => sound.p_env_decay = float(select('#decay').value()));
  select('#freq_ramp').input(() => sound.p_freq_ramp = float(select('#freq_ramp').value()));
  select('#vib_strength').input(() => sound.p_vib_strength = float(select('#vib_strength').value()));
  select('#vib_speed').input(() => sound.p_vib_speed = float(select('#vib_speed').value()));
  select('#repeat_speed').input(() => sound.p_repeat_speed = float(select('#repeat_speed').value()));
  select('#env_punch').input(() => sound.p_env_punch = float(select('#env_punch').value()));
  select('#arp_speed').input(() => sound.p_arp_speed = float(select('#arp_speed').value()));
  select('#arp_mod').input(() => sound.p_arp_mod = float(select('#arp_mod').value()));

  select('#randomize').mousePressed(randomizeParams);
  
  // Setup Save Canvas button
select('#saveCanvas').mousePressed(saveCanvasAsJPG);
  
    // Setup Save button
  select('#saveAudio').mousePressed(saveAudio);
}

function draw() {
  background(255);

  if (alive > 0.1) {
    alive *= 0.96;
    xoff = sin(millis() * 0.1) * alive * 30;
    yoff = sin(millis() * 0.3) * alive * 30;
  }

  let px = width / 2 + xoff;
  let py = height / 2 + yoff;

  fill(0);
  noStroke();

  // Draw the pre-rendered waveform
  image(waveGraphics, 0, 0);
}

function mouseReleased() {
  generateAndPlaySound();
}

function generateAndPlaySound() {
  let s = new SoundEffect(sound).generate();
  wave = s.data;  // Get waveform data
  soundDuration = s.getAudio().duration * 1000;
  soundStartTime = millis();
  s.getAudio().play();

  // Render the waveform to the PGraphics object
  waveGraphics.background(255);
  waveGraphics.fill(0);
  waveGraphics.beginShape();
  
  for (let i = 0; i < wave.length; i++) {
    let x = map(i, 0, wave.length, pad, width - pad * 2);
    waveGraphics.point(x, wave[i]*1.25 + pad, 4);
  }
  
  waveGraphics.endShape();

  // Encode the sound data as a WAV file using riffwave.js
  riffwave = new RIFFWAVE();
  riffwave.header.sampleRate = sound.sample_rate || 44100;
  riffwave.header.numChannels = 1;
  riffwave.Make(wave);  // Pass the audio data
}

// Function to save the audio file when the button is clicked
function saveAudio() {
  if (riffwave) {
    let a = document.createElement("a");
    a.href = riffwave.dataURI;
    a.download = "sound.wav";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  } else {
    console.log("No audio to save. Please generate sound first.");
  }
}
function randomizeParams() {
  sound.p_env_attack = random() * 0.3 + 0.03;
  sound.p_env_sustain = random() * 0.3 + 0.01;
  sound.p_env_decay = random() * 0.1 + 0.3;
  sound.p_freq_ramp = random() * 0.8 + 0.1;
  sound.p_vib_strength = random() * 0.7;
  sound.p_vib_speed = random() * 1.1;
  sound.p_repeat_speed = random() * 0.9 + 0.1;
  sound.p_env_punch = random() * 0.8 + 0.1;
  sound.p_arp_speed = random() * 0.4 + 1.1;
  sound.p_arp_mod = random() * 0.4 + 0.5;

  select('#attack').value(sound.p_env_attack);
  select('#sustain').value(sound.p_env_sustain);
  select('#decay').value(sound.p_env_decay);
  select('#freq_ramp').value(sound.p_freq_ramp);
  select('#vib_strength').value(sound.p_vib_strength);
  select('#vib_speed').value(sound.p_vib_speed);
  select('#repeat_speed').value(sound.p_repeat_speed);
  select('#env_punch').value(sound.p_env_punch);
  select('#arp_speed').value(sound.p_arp_speed);
  select('#arp_mod').value(sound.p_arp_mod);
}


function saveCanvasAsJPG() {
  waveGraphics.save('waveform.jpg');
}