Herzlich willkommen zum SELF-Treffen 2026
vom 24.04. – 26.04.2026 in Halle (Saale)

Beispiel:Web-Audio-07.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

<!DOCTYPE html> <html lang="de"> <head>

 <meta charset="UTF-8">
 <title>Mini-Mischpult für eine Audiodatei</title>
 <style type="text/css">
   body {
     font-family: monospace;
   }
   
   .controls {
     display: grid;
     grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
     gap: 3em;
     max-width: 70em;
   }
   .control-group {
     display: flex;
     flex-direction: column;
     gap: .5em;
   }
   input[type="range"] {
     width: 100%;
     cursor: pointer;
   }
   .value {
     color: #888;
   }
   .buttons {
     display: flex;
     gap: 1em;
     margin-bottom: 1.5rem;
   }
   button {
     font-family: monospace;
     font-size: 1em;
     padding: 1em;
     cursor: pointer;
   }
   button:disabled {
     opacity: 0.35;
     cursor: default;
   }
   #status {
     color: red;
     margin-bottom: 2em;
   }
 </style>

</head> <body>

Mini-Mischpult für eine Audiodatei

 <button id="startBtn">▶ Start</button>
 <button id="stopBtn" disabled>■ Stop</button>
Status: Bereit.
   <label for="volume">Lautstärke</label>
   <input type="range" id="volume" min="0" max="1" step="0.01" value="0.8">
   0.80
   <label for="pan">Balance links/rechts</label>
   <input type="range" id="pan" min="-1" max="1" step="0.01" value="0">
   Mitte
   <label for="reverbGain">Hall – Stärke</label>
   <input type="range" id="reverbGain" min="0" max="0.9" step="0.01" value="0">
   0.00
   <label for="echoGain">Echo – Stärke</label>
   <input type="range" id="echoGain" min="0" max="0.9" step="0.01" value="0">
   0.00
   <label for="echoDelay">Echo – Tempo (Sekunden)</label>
   <input type="range" id="echoDelay" min="0.1" max="1.0" step="0.01" value="0.3">
   0.30 s

<script> document.addEventListener('DOMContentLoaded', function () {

 const AUDIO_URL = '/images/b/bd/Ouvertuere_trocken.mp3'; // Datei-URL im Wiki
 let audioContext = null;
 let audioBuffer = null;
 let source = null;
 // Nodes – werden beim ersten Start aufgebaut
 let gainNode = null;
 let pannerNode = null;
 let reverbDelay = null;
 let reverbFeedback = null;
 let echoDelay = null;
 let echoFeedback = null;
 const startBtn = document.getElementById('startBtn');
 const stopBtn  = document.getElementById('stopBtn');
 const status   = document.getElementById('status');
 // --- AudioContext ---
 function getAudioContext() {
   if (!audioContext) {
     audioContext = new AudioContext();
   }
   return audioContext;
 }
 // --- Audiodatei laden ---
 async function loadAudio() {
   if (audioBuffer) return audioBuffer;
   status.textContent = 'Status: Lade Audiodatei';
   const audioCtx = getAudioContext();
   const response = await fetch(AUDIO_URL);
   const arrayBuffer = await response.arrayBuffer();
   audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
   status.textContent = 'Status: Bereit';
   return audioBuffer;
 }
 // --- Audiograph aufbauen ---
 // BufferSource → Gain (Lautstärke) → StereoPanner (Balance)
 //                      ↓
 //                 ReverbDelay (Feedback-Loop)
 //                      ↓
 //                 EchoDelay (Feedback-Loop)
 //                      ↓
 //                   Destination
 function buildGraph(audioCtx) {
   gainNode    = audioCtx.createGain();
   pannerNode  = audioCtx.createStereoPanner();
   reverbDelay   = audioCtx.createDelay(5.0);
   reverbFeedback= audioCtx.createGain();
   echoDelay   = audioCtx.createDelay(2.0);
   echoFeedback  = audioCtx.createGain();
   // Lautstärke → Balance → Reverb-Loop → Echo-Loop → Ausgang
   gainNode.connect(pannerNode);
   pannerNode.connect(reverbDelay);
   reverbDelay.connect(reverbFeedback);
   reverbFeedback.connect(reverbDelay);   // Feedback-Schleife Hall
   reverbDelay.connect(echoDelay);
   echoDelay.connect(echoFeedback);
   echoFeedback.connect(echoDelay);     // Feedback-Schleife Echo
   echoDelay.connect(audioCtx.destination);
   // Aktuelle Reglerwerte übernehmen
   applyValues();
 }
 function applyValues() {
   if (!gainNode) return;
   gainNode.gain.value     = parseFloat(document.getElementById('volume').value);
   pannerNode.pan.value    = parseFloat(document.getElementById('pan').value);
   reverbDelay.delayTime.value = 0.03; // kurze Verzögerung für Hallcharakter
   reverbFeedback.gain.value = parseFloat(document.getElementById('reverbGain').value);
   echoDelay.delayTime.value = parseFloat(document.getElementById('echoDelay').value);
   echoFeedback.gain.value   = parseFloat(document.getElementById('echoGain').value);
 }
 // --- Start ---
 async function startAudio() {
   try {
     const audioCtx = getAudioContext();
     if (!audioBuffer) await loadAudio();
     if (audioCtx.state === 'suspended') await audioCtx.resume();
     buildGraph(audioCtx);
     // Für jede Wiedergabe muss eine neue BufferSourceNode erzeugt werden –
     // eine Node kann nur einmal abgespielt werden.
     source = audioCtx.createBufferSource();
     source.buffer = audioBuffer;
     source.loop = true;
     source.connect(gainNode);
     source.start();
     startBtn.disabled = true;
     stopBtn.disabled  = false;
     status.textContent = 'Status: Spielt';
   } catch (err) {
     status.textContent = 'Status: Fehler (' + err.message + ')';
     console.error(err);
   }
 }
 // --- Stop ---
 function stopAudio() {
   if (source) {
     source.stop();
     source = null;
   }
   startBtn.disabled = false;
   stopBtn.disabled  = true;
   status.textContent = 'Status: Gestoppt';
 }
 // --- Regler-Events ---
 function linkSlider(id, valId, format, apply) {
   const slider = document.getElementById(id);
   const display = document.getElementById(valId);
   slider.addEventListener('input', function () {
     display.textContent = format(this.value);
     if (gainNode) apply(parseFloat(this.value));
   });
   display.textContent = format(slider.value);
 }
 linkSlider('volume', 'volumeVal',
   v => parseFloat(v).toFixed(2),
   v => gainNode.gain.value = v
 );
 linkSlider('pan', 'panVal',
   v => v == 0 ? 'Mitte' : (v < 0 ? 'L ' : 'R ') + Math.abs(parseFloat(v)).toFixed(2),
   v => pannerNode.pan.value = v
 );
 linkSlider('reverbGain', 'reverbGainVal',
   v => parseFloat(v).toFixed(2),
   v => reverbFeedback.gain.value = v
 );
 linkSlider('echoGain', 'echoGainVal',
   v => parseFloat(v).toFixed(2),
   v => echoFeedback.gain.value = v
 );
 linkSlider('echoDelay', 'echoDelayVal',
   v => parseFloat(v).toFixed(2) + ' s',
   v => echoDelay.delayTime.value = v
 );
 startBtn.addEventListener('click', startAudio);
 stopBtn.addEventListener('click', stopAudio);

}); </script>

</body> </html>