<html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>KORG Kaoscillator - Digital Hardcore (Low-Latency) <style>  :root {  --bg-color: #0d0d0d;  --panel-bg: #18181f;  --accent-yellow: #ffcc00;  --accent-red: #ff3333;  }   body {  background-color: var(--bg-color);  color: #fff;  font-family: 'Courier New', Courier, monospace;  display: flex;  justify-content: center;  align-items: center;  min-height: 100vh;  margin: 0;  user-select: none;  }   .kaoss-container {  background: var(--panel-bg);  border: 4px solid #333;  border-radius: 16px;  padding: 20px;  box-shadow: 0 10px 30px rgba(0,0,0,0.9), inset 0 0 15px rgba(255,255,255,0.05);  width: 380px;  display: flex;  flex-direction: column;  gap: 12px;  }   .header {  display: flex;  justify-content: space-between;  align-items: center;  border-bottom: 2px solid #333;  padding-bottom: 6px;  }   .title {  font-weight: bold;  font-size: 1.1rem;  color: var(--accent-yellow);  letter-spacing: 2px;  }   .subtitle {  font-size: 0.65rem;  color: var(--accent-red);  font-weight: bold;  }   .display {  background: #000;  border: 2px solid #444;  border-radius: 6px;  padding: 8px 12px;  display: flex;  flex-direction: column;  gap: 4px;  font-family: monospace;  color: var(--accent-yellow);  text-shadow: 0 0 5px var(--accent-yellow);  font-size: 0.85rem;  }   .display-row {  display: flex;  justify-content: space-between;  }   .pad-container {  position: relative;  width: 100%;  height: 260px;  background: #050505;  border: 3px solid #444;  border-radius: 12px;  overflow: hidden;  cursor: crosshair;  touch-action: none;  }   canvas {  width: 100%;  height: 100%;  }   .controls {  display: grid;  grid-template-columns: 1fr 1fr;  gap: 8px;  }   .control-group {  display: flex;  flex-direction: column;  gap: 3px;  }   label {  font-size: 0.65rem;  color: #aaa;  text-transform: uppercase;  font-weight: bold;  }   select, button, input {  background: #252530;  color: #fff;  border: 1px solid #444;  padding: 6px;  border-radius: 4px;  font-family: inherit;  font-size: 0.78rem;  font-weight: bold;  cursor: pointer;  }   select:focus, button:focus, input:focus {  outline: none;  border-color: var(--accent-yellow);  }   button.active {  background: var(--accent-red);  color: #fff;  box-shadow: 0 0 10px var(--accent-red);  }   <body> <div class="kaoss-container"> <div class="header"> <div class="title">KAOSS-DHC <div class="subtitle">ZERO-LATENCY EDITION <div class="display"> <div class="display-row"> <span id="disp-preset">SYNTH: DHC SAW <span id="disp-bpm">180 BPM <div class="display-row"> <span id="disp-scale">SKALA: PHRYGIAN DOM <span id="disp-pattern">BEAT: DHC BREAK <div class="pad-container" id="pad"> <canvas id="visualizer"> <div class="controls"> <div class="control-group"> <label for="preset">Preset <select id="preset"> <option value="saw">Aggro Saw Lead <option value="acid">Screaming 303 <option value="sub">Distorted Sub <option value="noise">Cyber Chaos <div class="control-group"> <label for="scale">Skala (Exotisch) <select id="scale"> <option value="phrygianDom">Phrygisch-Dominant <option value="hirajoshi">Hirajoshi (Japan) <option value="hungarianMin">Ungarisch Moll <option value="arabic">Arabisch (Bayati) <option value="pelog">Pelog (Bali) <option value="minor">Min-Pentatonisch <option value="blues">Blues <option value="chromatic">Chromatisch <option value="raw">Unquantisiert <div class="control-group"> <label for="beat-pattern">Drum Pattern <select id="beat-pattern"> <option value="dhc">DHC Breakbeat <option value="amen">Amen Cyber Cut <option value="gabber">Gabber 4-to-Floor <option value="industrial">Industrial Sync <option value="speedcore">Speedcore Terror <div class="control-group"> <label for="bpm">Tempo / Beat <div style="display: flex; gap: 4px;"> <input type="number" id="bpm" value="180" min="120" max="240" style="width: 45%;"> <button id="beat-btn" style="width: 55%;">BEAT RUN <script>  let audioCtx = null;  let masterGain, driveNode, filterNode, mainOsc, subOsc;  let noiseBuffer = null;  let isTouching = false;  let beatPlaying = false;   // Scheduler Variables (Low Latency Web Audio Clock)  let lookahead = 25.0; // ms  let scheduleAheadTime = 0.1; // seconds  let nextNoteTime = 0.0;  let current16thNote = 0;  let timerID = null;   const baseFreq = 110; // A2   // Exotic & Standard Scales  const scales = {  phrygianDom: [0, 1, 4, 5, 7, 8, 10, 12, 13, 16, 17, 19, 20, 22, 24],  hirajoshi: [0, 2, 3, 7, 8, 12, 14, 15, 19, 20, 24],  hungarianMin: [0, 2, 3, 6, 7, 8, 11, 12, 14, 15, 18, 19, 20, 23, 24],  arabic: [0, 1, 4, 5, 7, 8, 11, 12, 13, 16, 17, 19, 20, 23, 24],  pelog: [0, 1, 3, 7, 8, 12, 13, 15, 19, 20, 24],  minor: [0, 3, 5, 7, 10, 12, 15, 17, 19, 22, 24],  blues: [0, 3, 5, 6, 7, 10, 12, 15, 17, 18, 19, 22, 24],  chromatic: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]  };   // 16-step Drum Patterns  const drumPatterns = {  dhc: {  kick: [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0],  snare: [0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0],  hat: [1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0]  },  amen: {  kick: [1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0],  snare: [0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1],  hat: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]  },  gabber: {  kick: [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],  snare: [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],  hat: [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]  },  industrial: {  kick: [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0],  snare: [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0],  hat: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  },  speedcore: {  kick: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],  snare: [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],  hat: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]  }  };   function initAudio() {  if (audioCtx) return;  audioCtx = new (window.AudioContext || window.webkitAudioContext)({ latencyHint: 'interactive' });   masterGain = audioCtx.createGain();  masterGain.gain.value = 0.3;   // Hardcore Overdrive Distortion Node  driveNode = audioCtx.createWaveShaper();  driveNode.curve = makeDistortionCurve(95);  driveNode.oversample = '4x';   // Filter Node  filterNode = audioCtx.createBiquadFilter();  filterNode.type = 'lowpass';  filterNode.frequency.value = 2000;  filterNode.Q.value = 6;   filterNode.connect(driveNode);  driveNode.connect(masterGain);  masterGain.connect(audioCtx.destination);   // Pre-generate noise buffer to avoid audio thread stalls  createNoiseBuffer();  }   function createNoiseBuffer() {  const bufferSize = audioCtx.sampleRate * 1.0;  noiseBuffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);  const output = noiseBuffer.getChannelData(0);  for (let i = 0; i < bufferSize; i++) {  output[i] = Math.random() * 2 - 1;  }  }   function makeDistortionCurve(amount) {  let k = amount, n = 44100, curve = new Float32Array(n), deg = Math.PI / 180;  for (let i = 0; i < n; ++i) {  let x = i * 2 / n - 1;  curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));  }  return curve;  }   function mtof(note) {  return baseFreq * Math.pow(2, note / 12);  }   function startSynth() {  initAudio();  if (audioCtx.state === 'suspended') audioCtx.resume();  if (mainOsc) return;   const preset = document.getElementById('preset').value;   mainOsc = audioCtx.createOscillator();  subOsc = audioCtx.createOscillator();   if (preset === 'saw') {  mainOsc.type = 'sawtooth'; subOsc.type = 'square';  } else if (preset === 'acid') {  mainOsc.type = 'sawtooth'; subOsc.type = 'sawtooth';  } else if (preset === 'sub') {  mainOsc.type = 'triangle'; subOsc.type = 'sine';  } else if (preset === 'noise') {  mainOsc.type = 'square'; subOsc.type = 'sawtooth';  }   mainOsc.connect(filterNode);  subOsc.connect(filterNode);   mainOsc.start();  subOsc.start();  }   function stopSynth() {  if (mainOsc) { mainOsc.stop(); mainOsc.disconnect(); mainOsc = null; }  if (subOsc) { subOsc.stop(); subOsc.disconnect(); subOsc = null; }  }   function updateSynth(x, y) {  if (!mainOsc) return;   const scaleType = document.getElementById('scale').value;  let freq;   if (scaleType === 'raw') {  freq = 80 * Math.pow(2, x * 4);  } else {  const currentScale = scales[scaleType];  const noteIndex = Math.floor(x * currentScale.length);  const note = currentScale[Math.min(noteIndex, currentScale.length - 1)];  freq = mtof(note);  }   const minVal = 100, maxVal = 10000;  const cutoff = minVal * Math.pow(maxVal / minVal, y);   // Immediate value scheduling for zero latency  const now = audioCtx.currentTime;  mainOsc.frequency.setValueAtTime(freq, now);  subOsc.frequency.setValueAtTime(freq / 2, now);  filterNode.frequency.setValueAtTime(cutoff, now);   if (document.getElementById('preset').value === 'acid') {  filterNode.Q.setValueAtTime(4 + (y * 18), now);  } else {  filterNode.Q.setValueAtTime(4, now);  }  }   // High-Precision Drum Synthesizer  function triggerDrum(type, time) {  if (type === 'kick') {  let osc = audioCtx.createOscillator();  let gain = audioCtx.createGain();  osc.frequency.setValueAtTime(180, time);  osc.frequency.exponentialRampToValueAtTime(30, time + 0.1);  gain.gain.setValueAtTime(1.4, time);  gain.gain.exponentialRampToValueAtTime(0.001, time + 0.14);  osc.connect(driveNode);  osc.start(time); osc.stop(time + 0.14);  } else if (type === 'snare') {  let noiseSrc = audioCtx.createBufferSource();  noiseSrc.buffer = noiseBuffer;  let filter = audioCtx.createBiquadFilter();  filter.type = 'highpass';  filter.frequency.value = 800;  let gain = audioCtx.createGain();  gain.gain.setValueAtTime(0.9, time);  gain.gain.exponentialRampToValueAtTime(0.01, time + 0.09);  noiseSrc.connect(filter);  filter.connect(driveNode);  noiseSrc.start(time); noiseSrc.stop(time + 0.09);  } else if (type === 'hat') {  let noiseSrc = audioCtx.createBufferSource();  noiseSrc.buffer = noiseBuffer;  let filter = audioCtx.createBiquadFilter();  filter.type = 'highpass';  filter.frequency.value = 6000;  let gain = audioCtx.createGain();  gain.gain.setValueAtTime(0.4, time);  gain.gain.exponentialRampToValueAtTime(0.001, time + 0.04);  noiseSrc.connect(filter);  filter.connect(driveNode);  noiseSrc.start(time); noiseSrc.stop(time + 0.04);  }  }   // Web Audio Lookahead Scheduler  function nextNote() {  const bpm = parseInt(document.getElementById('bpm').value);  const secondsPerBeat = 60.0 / bpm;  nextNoteTime += 0.25 * secondsPerBeat; // 16th note step  current16thNote = (current16thNote + 1) % 16;  }   function scheduleNote(step, time) {  const patKey = document.getElementById('beat-pattern').value;  const pat = drumPatterns[patKey];   if (pat.kick[step]) triggerDrum('kick', time);  if (pat.snare[step]) triggerDrum('snare', time);  if (pat.hat[step]) triggerDrum('hat', time);  }   function scheduler() {  while (nextNoteTime < audioCtx.currentTime + scheduleAheadTime) {  scheduleNote(current16thNote, nextNoteTime);  nextNote();  }  if (beatPlaying) {  timerID = window.setTimeout(scheduler, lookahead);  }  }   document.getElementById('beat-btn').addEventListener('click', (e) => {  initAudio();  if (audioCtx.state === 'suspended') audioCtx.resume();   beatPlaying = !beatPlaying;  e.target.classList.toggle('active', beatPlaying);   if (beatPlaying) {  current16thNote = 0;  nextNoteTime = audioCtx.currentTime;  scheduler();  } else {  clearTimeout(timerID);  }  });   // Touch / Mouse Interaction with RAF Decoupling for smooth performance  const pad = document.getElementById('pad');  const canvas = document.getElementById('visualizer');  const ctx = canvas.getContext('2d');  let touchX = 0, touchY = 0;   function resizeCanvas() {  canvas.width = pad.clientWidth; canvas.height = pad.clientHeight;  }  window.addEventListener('resize', resizeCanvas);  resizeCanvas();   function handleInputStart(e) {  isTouching = true;  startSynth();  handleInputMove(e);  }   function handleInputEnd() {  isTouching = false;  stopSynth();  }   function handleInputMove(e) {  if (!isTouching) return;  const rect = pad.getBoundingClientRect();  const clientX = e.touches ? e.touches[0].clientX : e.clientX;  const clientY = e.touches ? e.touches[0].clientY : e.clientY;   touchX = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));  touchY = Math.max(0, Math.min(1, 1 - (clientY - rect.top) / rect.height));   updateSynth(touchX, touchY);  }   pad.addEventListener('mousedown', handleInputStart);  window.addEventListener('mouseup', handleInputEnd);  pad.addEventListener('mousemove', handleInputMove);   pad.addEventListener('touchstart', handleInputStart, { passive: true });  window.addEventListener('touchend', handleInputEnd);  pad.addEventListener('touchmove', handleInputMove, { passive: true });   // Canvas Visualization Loop  function renderVisualizer() {  requestAnimationFrame(renderVisualizer);   ctx.fillStyle = 'rgba(5, 5, 5, 0.25)';  ctx.fillRect(0, 0, canvas.width, canvas.height);   // Grid  ctx.strokeStyle = '#1a1a1a';  ctx.lineWidth = 1;  for (let i = 0; i < canvas.width; i += 30) {  ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, canvas.height); ctx.stroke();  }  for (let j = 0; j < canvas.height; j += 30) {  ctx.beginPath(); ctx.moveTo(0, j); ctx.lineTo(canvas.width, j); ctx.stroke();  }   // Touch Cursor  if (isTouching) {  const cx = touchX * canvas.width;  const cy = (1 - touchY) * canvas.height;   ctx.strokeStyle = 'rgba(255, 204, 0, 0.6)';  ctx.beginPath(); ctx.moveTo(cx, 0); ctx.lineTo(cx, canvas.height); ctx.stroke();  ctx.beginPath(); ctx.moveTo(0, cy); ctx.lineTo(canvas.width, cy); ctx.stroke();   ctx.fillStyle = '#ff3333';  ctx.shadowColor = '#ff3333';  ctx.shadowBlur = 15;  ctx.beginPath();  ctx.arc(cx, cy, 10, 0, Math.PI * 2);  ctx.fill();  ctx.shadowBlur = 0;  }  }  renderVisualizer();   // UI Display Listeners  document.getElementById('scale').addEventListener('change', (e) => {  document.getElementById('disp-scale').innerText = `SKALA: ${e.target.options[e.target.selectedIndex].text.toUpperCase()}`;  });   document.getElementById('preset').addEventListener('change', (e) => {  document.getElementById('disp-preset').innerText = `SYNTH: ${e.target.options[e.target.selectedIndex].text.toUpperCase()}`;  if (mainOsc) { stopSynth(); startSynth(); }  });   document.getElementById('beat-pattern').addEventListener('change', (e) => {  document.getElementById('disp-pattern').innerText = `BEAT: ${e.target.options[e.target.selectedIndex].text.toUpperCase()}`;  });   document.getElementById('bpm').addEventListener('change', (e) => {  document.getElementById('disp-bpm').innerText = `${e.target.value} BPM`;  });