<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Random Binaural Beat Generator</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(45deg, #1a1a1a, #2d2d2d); color: #fff; min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 2rem; } .container { max-width: 800px; width: 100%; background: rgba(255, 255, 255, 0.1); padding: 2rem; border-radius: 15px; backdrop-filter: blur(10px); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } h1 { text-align: center; margin-bottom: 2rem; color: #00ff88; text-shadow: 0 0 10px rgba(0, 255, 136, 0.5); } .controls { display: grid; gap: 1.5rem; margin-bottom: 2rem; } .control-group { display: flex; flex-direction: column; gap: 0.5rem; } label { font-size: 1.1rem; color: #00ff88; } input[type="range"] { width: 100%; height: 10px; background: rgba(255, 255, 255, 0.1); border-radius: 5px; outline: none; -webkit-appearance: none; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; background: #00ff88; border-radius: 50%; cursor: pointer; transition: background 0.3s; } .value-display { font-size: 1.2rem; color: #fff; text-align: center; } .buttons { display: flex; gap: 1rem; justify-content: center; } button { padding: 1rem 2rem; font-size: 1.1rem; border: none; border-radius: 5px; background: #00ff88; color: #1a1a1a; cursor: pointer; transition: all 0.3s; } button:hover { background: #00cc6a; transform: translateY(-2px); } .display { margin-top: 2rem; padding: 1rem; background: rgba(0, 255, 136, 0.1); border-radius: 10px; text-align: center; } #currentFrequencies { font-size: 1.5rem; color: #00ff88; margin: 1rem 0; line-height: 1.6; } .wave-visualizer { width: 100%; height: 100px; background: rgba(255, 255, 255, 0.05); margin-top: 2rem; border-radius: 5px; overflow: hidden; position: relative; } .wave { position: absolute; width: 100%; height: 100%; background: linear-gradient(180deg, transparent 0%, #00ff88 50%, transparent 100%); opacity: 0.3; animation: wave 2s infinite linear; } @keyframes wave { 0% { transform: translateX(-100%) scaleY(0.5); } 50% { transform: translateX(0%) scaleY(1); } 100% { transform: translateX(100%) scaleY(0.5); } } </style> </head> <body> <div class="container"> <h1>Random Binaural Beat Generator</h1> <div class="controls"> <div class="control-group"> <label for="beatFrequency">Target Beat Frequency (Hz)</label> <input type="range" id="beatFrequency" min="1" max="40" value="7.83"> <div class="value-display" id="beatFrequencyValue">7.83 Hz</div> </div> <div class="control-group"> <label for="interval">Interval Between Changes (ms)</label> <input type="range" id="interval" min="100" max="2000" value="500"> <div class="value-display" id="intervalValue">500 ms</div> </div> <div class="control-group"> <label for="volume">Volume</label> <input type="range" id="volume" min="0" max="1" step="0.1" value="0.5"> <div class="value-display" id="volumeValue">50%</div> </div> </div> <div class="buttons"> <button id="startBtn">Start</button> <button id="stopBtn">Stop</button> </div> <div class="display"> <p>Current Frequencies:</p> <div id="currentFrequencies"> Left: 0 Hz<br> Right: 0 Hz<br> Beat: 0 Hz </div> </div> <div class="wave-visualizer"> <div class="wave"></div> </div> </div> <script> let audioContext; let oscillatorLeft; let oscillatorRight; let gainNode; let isPlaying = false; let intervalId; const startBtn = document.getElementById('startBtn'); const stopBtn = document.getElementById('stopBtn'); const beatFrequencySlider = document.getElementById('beatFrequency'); const intervalSlider = document.getElementById('interval'); const volumeSlider = document.getElementById('volume'); const currentFrequenciesDisplay = document.getElementById('currentFrequencies'); function updateValueDisplays() { document.getElementById('beatFrequencyValue').textContent = `${beatFrequencySlider.value} Hz`; document.getElementById('intervalValue').textContent = `${intervalSlider.value} ms`; document.getElementById('volumeValue').textContent = `${Math.round(volumeSlider.value * 100)}%`; } function getRandomBaseFrequency() { // Random frequency between 100 and 400 Hz return Math.random() * 300 + 100; } function initAudio() { audioContext = new (window.AudioContext || window.webkitAudioContext)(); gainNode = audioContext.createGain(); gainNode.connect(audioContext.destination); oscillatorLeft = audioContext.createOscillator(); oscillatorRight = audioContext.createOscillator(); const merger = audioContext.createChannelMerger(2); oscillatorLeft.connect(merger, 0, 0); oscillatorRight.connect(merger, 0, 1); merger.connect(gainNode); updateFrequencies(); updateVolume(); } function updateFrequencies() { const beatFreq = parseFloat(beatFrequencySlider.value); const baseFreq = getRandomBaseFrequency(); // Ensure both frequencies create the desired beat frequency const leftFreq = baseFreq; const rightFreq = baseFreq + beatFreq; oscillatorLeft.frequency.setValueAtTime(leftFreq, audioContext.currentTime); oscillatorRight.frequency.setValueAtTime(rightFreq, audioContext.currentTime); currentFrequenciesDisplay.innerHTML = ` Left: ${leftFreq.toFixed(2)} Hz<br> Right: ${rightFreq.toFixed(2)} Hz<br> Beat: ${beatFreq.toFixed(2)} Hz `; } function updateVolume() { gainNode.gain.setValueAtTime(volumeSlider.value, audioContext.currentTime); } function startRandomization() { intervalId = setInterval(() => { updateFrequencies(); }, parseFloat(intervalSlider.value)); } startBtn.addEventListener('click', () => { if (!isPlaying) { initAudio(); oscillatorLeft.start(); oscillatorRight.start(); startRandomization(); isPlaying = true; } }); stopBtn.addEventListener('click', () => { if (isPlaying) { clearInterval(intervalId); oscillatorLeft.stop(); oscillatorRight.stop(); audioContext.close(); isPlaying = false; currentFrequenciesDisplay.innerHTML = ` Left: 0 Hz<br> Right: 0 Hz<br> Beat: 0 Hz `; } }); beatFrequencySlider.addEventListener('input', () => { updateValueDisplays(); if (isPlaying) updateFrequencies(); }); intervalSlider.addEventListener('input', () => { updateValueDisplays(); if (isPlaying) { clearInterval(intervalId); startRandomization(); } }); volumeSlider.addEventListener('input', () => { updateValueDisplays(); if (isPlaying) updateVolume(); }); updateValueDisplays(); </script> </body> </html>