Create a site like this one https://mynoise.net/NoiseMachines/binauralBrainwaveGenerator.php
ec4b239
verified
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SonicZen Wave Generator</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script> | |
| <style> | |
| .wave-control { | |
| background: linear-gradient(to right, #4f46e5, #7c3aed); | |
| height: 8px; | |
| border-radius: 4px; | |
| } | |
| .wave-control::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: white; | |
| cursor: pointer; | |
| box-shadow: 0 0 10px rgba(0,0,0,0.2); | |
| } | |
| .preset-btn { | |
| transition: all 0.3s ease; | |
| } | |
| .preset-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); | |
| } | |
| .frequency-display { | |
| font-family: monospace; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="text-center mb-12"> | |
| <h1 class="text-4xl font-bold text-indigo-700 mb-2">SonicZen Wave Generator</h1> | |
| <p class="text-lg text-gray-600">Binaural Beats & Brainwave Entrainment</p> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Left Panel - Controls --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i data-feather="sliders" class="mr-2"></i> Wave Controls | |
| </h2> | |
| <!-- Frequency Control --> | |
| <div class="mb-8"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <label class="text-gray-700 font-medium">Frequency (Hz)</label> | |
| <span class="frequency-display text-indigo-600 font-bold">440</span> | |
| </div> | |
| <input type="range" min="20" max="2000" value="440" class="wave-control w-full" id="frequencyControl"> | |
| </div> | |
| <!-- Wave Type Selector --> | |
| <div class="mb-8"> | |
| <label class="text-gray-700 font-medium block mb-2">Wave Type</label> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <button class="wave-type-btn preset-btn bg-indigo-100 text-indigo-700 py-2 px-4 rounded-lg" data-type="sine"> | |
| <i data-feather="activity" class="mr-2"></i> Sine | |
| </button> | |
| <button class="wave-type-btn preset-btn bg-indigo-100 text-indigo-700 py-2 px-4 rounded-lg" data-type="square"> | |
| <i data-feather="square" class="mr-2"></i> Square | |
| </button> | |
| <button class="wave-type-btn preset-btn bg-indigo-100 text-indigo-700 py-2 px-4 rounded-lg" data-type="sawtooth"> | |
| <i data-feather="triangle" class="mr-2"></i> Sawtooth | |
| </button> | |
| <button class="wave-type-btn preset-btn bg-indigo-100 text-indigo-700 py-2 px-4 rounded-lg" data-type="triangle"> | |
| <i data-feather="zap" class="mr-2"></i> Triangle | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Binaural Beats Control --> | |
| <div class="mb-8"> | |
| <div class="flex items-center mb-4"> | |
| <label class="inline-flex items-center"> | |
| <input type="checkbox" class="form-checkbox h-5 w-5 text-indigo-600" id="binauralToggle"> | |
| <span class="ml-2 text-gray-700 font-medium">Binaural Beats</span> | |
| </label> | |
| </div> | |
| <div class="pl-6" id="binauralControls" style="display: none;"> | |
| <div class="mb-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <label class="text-gray-700">Beat Frequency (Hz)</label> | |
| <span class="frequency-display text-indigo-600 font-bold">10</span> | |
| </div> | |
| <input type="range" min="0.5" max="30" step="0.5" value="10" class="wave-control w-full" id="beatControl"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Volume Control --> | |
| <div class="mb-8"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <label class="text-gray-700 font-medium">Volume</label> | |
| <span id="volumeDisplay" class="text-indigo-600 font-bold">50%</span> | |
| </div> | |
| <input type="range" min="0" max="100" value="50" class="wave-control w-full" id="volumeControl"> | |
| </div> | |
| <!-- Main Play/Pause Button --> | |
| <button id="playBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-lg transition duration-300 flex items-center justify-center"> | |
| <i data-feather="play" class="mr-2"></i> Play Sound | |
| </button> | |
| </div> | |
| <!-- Middle Panel - Presets --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i data-feather="bookmark" class="mr-2"></i> Brainwave Presets | |
| </h2> | |
| <div class="space-y-4"> | |
| <button class="preset-btn w-full bg-indigo-50 hover:bg-indigo-100 text-indigo-700 py-3 px-4 rounded-lg transition duration-300 text-left flex items-center" data-preset="gamma"> | |
| <i data-feather="zap" class="mr-3 text-yellow-500"></i> | |
| <div> | |
| <h3 class="font-semibold">Gamma Waves (30-100 Hz)</h3> | |
| <p class="text-sm text-gray-600">Heightened perception, problem solving</p> | |
| </div> | |
| </button> | |
| <button class="preset-btn w-full bg-indigo-50 hover:bg-indigo-100 text-indigo-700 py-3 px-4 rounded-lg transition duration-300 text-left flex items-center" data-preset="beta"> | |
| <i data-feather="alert-circle" class="mr-3 text-blue-500"></i> | |
| <div> | |
| <h3 class="font-semibold">Beta Waves (12-30 Hz)</h3> | |
| <p class="text-sm text-gray-600">Active thinking, focus, alertness</p> | |
| </div> | |
| </button> | |
| <button class="preset-btn w-full bg-indigo-50 hover:bg-indigo-100 text-indigo-700 py-3 px-4 rounded-lg transition duration-300 text-left flex items-center" data-preset="alpha"> | |
| <i data-feather="eye" class="mr-3 text-green-500"></i> | |
| <div> | |
| <h3 class="font-semibold">Alpha Waves (8-12 Hz)</h3> | |
| <p class="text-sm text-gray-600">Relaxation, creativity, flow states</p> | |
| </div> | |
| </button> | |
| <button class="preset-btn w-full bg-indigo-50 hover:bg-indigo-100 text-indigo-700 py-3 px-4 rounded-lg transition duration-300 text-left flex items-center" data-preset="theta"> | |
| <i data-feather="moon" class="mr-3 text-purple-500"></i> | |
| <div> | |
| <h3 class="font-semibold">Theta Waves (4-8 Hz)</h3> | |
| <p class="text-sm text-gray-600">Meditation, deep relaxation, intuition</p> | |
| </div> | |
| </button> | |
| <button class="preset-btn w-full bg-indigo-50 hover:bg-indigo-100 text-indigo-700 py-3 px-4 rounded-lg transition duration-300 text-left flex items-center" data-preset="delta"> | |
| <i data-feather="cloud" class="mr-3 text-indigo-500"></i> | |
| <div> | |
| <h3 class="font-semibold">Delta Waves (0.5-4 Hz)</h3> | |
| <p class="text-sm text-gray-600">Deep sleep, healing, regeneration</p> | |
| </div> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Right Panel - Visualizer --> | |
| <div class="bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i data-feather="bar-chart-2" class="mr-2"></i> Wave Visualizer | |
| </h2> | |
| <div class="bg-gray-50 rounded-lg h-64 mb-6 flex items-center justify-center"> | |
| <canvas id="waveCanvas" width="100%" height="100%"></canvas> | |
| </div> | |
| <div class="bg-gray-50 rounded-lg p-4"> | |
| <h3 class="font-semibold text-gray-800 mb-2">Current Settings</h3> | |
| <div class="grid grid-cols-2 gap-4 text-sm"> | |
| <div> | |
| <p class="text-gray-600">Wave Type:</p> | |
| <p class="text-indigo-600 font-medium" id="currentWaveType">Sine</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-600">Base Frequency:</p> | |
| <p class="text-indigo-600 font-medium" id="currentFrequency">440 Hz</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-600">Binaural Beats:</p> | |
| <p class="text-indigo-600 font-medium" id="currentBinaural">Off</p> | |
| </div> | |
| <div> | |
| <p class="text-gray-600">Beat Frequency:</p> | |
| <p class="text-indigo-600 font-medium" id="currentBeat">0 Hz</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Footer --> | |
| <footer class="mt-12 text-center text-gray-500 text-sm"> | |
| <p>Use headphones for best binaural beats experience. Not for medical use.</p> | |
| <p class="mt-2">© 2023 SonicZen Wave Generator</p> | |
| </footer> | |
| </div> | |
| <script> | |
| // Initialize Tone.js | |
| document.addEventListener('DOMContentLoaded', function() { | |
| feather.replace(); | |
| // Audio setup | |
| let oscillatorLeft = null; | |
| let oscillatorRight = null; | |
| let gainNode = null; | |
| let isPlaying = false; | |
| // Canvas setup | |
| const canvas = document.getElementById('waveCanvas'); | |
| const ctx = canvas.getContext('2d'); | |
| canvas.width = canvas.offsetWidth; | |
| canvas.height = canvas.offsetHeight; | |
| // UI Elements | |
| const playBtn = document.getElementById('playBtn'); | |
| const frequencyControl = document.getElementById('frequencyControl'); | |
| const volumeControl = document.getElementById('volumeControl'); | |
| const binauralToggle = document.getElementById('binauralToggle'); | |
| const binauralControls = document.getElementById('binauralControls'); | |
| const beatControl = document.getElementById('beatControl'); | |
| const waveTypeBtns = document.querySelectorAll('.wave-type-btn'); | |
| const presetBtns = document.querySelectorAll('.preset-btn[data-preset]'); | |
| // Display elements | |
| const frequencyDisplay = document.querySelector('#frequencyControl + .frequency-display'); | |
| const beatDisplay = document.querySelector('#beatControl + .frequency-display'); | |
| const volumeDisplay = document.getElementById('volumeDisplay'); | |
| const currentWaveType = document.getElementById('currentWaveType'); | |
| const currentFrequency = document.getElementById('currentFrequency'); | |
| const currentBinaural = document.getElementById('currentBinaural'); | |
| const currentBeat = document.getElementById('currentBeat'); | |
| // Current settings | |
| let currentWaveTypeValue = 'sine'; | |
| let currentFrequencyValue = 440; | |
| let currentVolumeValue = 0.5; | |
| let currentBeatValue = 10; | |
| let currentBinauralState = false; | |
| // Update displays | |
| function updateDisplays() { | |
| frequencyDisplay.textContent = currentFrequencyValue; | |
| beatDisplay.textContent = currentBeatValue; | |
| volumeDisplay.textContent = Math.round(currentVolumeValue * 100) + '%'; | |
| currentWaveType.textContent = currentWaveTypeValue.charAt(0).toUpperCase() + currentWaveTypeValue.slice(1); | |
| currentFrequency.textContent = currentFrequencyValue + ' Hz'; | |
| currentBinaural.textContent = currentBinauralState ? 'On' : 'Off'; | |
| currentBeat.textContent = currentBinauralState ? currentBeatValue + ' Hz' : '0 Hz'; | |
| drawWave(); | |
| } | |
| // Draw waveform visualization | |
| function drawWave() { | |
| const width = canvas.width; | |
| const height = canvas.height; | |
| ctx.clearRect(0, 0, width, height); | |
| ctx.beginPath(); | |
| ctx.strokeStyle = '#4f46e5'; | |
| ctx.lineWidth = 2; | |
| const centerY = height / 2; | |
| const amplitude = height / 3; | |
| const frequency = currentFrequencyValue / 50; // Scale for visualization | |
| // If binaural beats are on, create a more complex visualization | |
| if (currentBinauralState) { | |
| ctx.strokeStyle = '#7c3aed'; | |
| for (let x = 0; x < width; x++) { | |
| const progress = x / width * Math.PI * 10; | |
| const leftWave = Math.sin(progress * frequency) * amplitude; | |
| const rightWave = Math.sin(progress * (frequency + currentBeatValue/50)) * amplitude; | |
| const y = centerY + (leftWave + rightWave) / 2; | |
| if (x === 0) { | |
| ctx.moveTo(x, y); | |
| } else { | |
| ctx.lineTo(x, y); | |
| } | |
| } | |
| } else { | |
| for (let x = 0; x < width; x++) { | |
| const progress = x / width * Math.PI * 10; | |
| const y = centerY + Math.sin(progress * frequency) * amplitude; | |
| if (x === 0) { | |
| ctx.moveTo(x, y); | |
| } else { | |
| ctx.lineTo(x, y); | |
| } | |
| } | |
| } | |
| ctx.stroke(); | |
| } | |
| // Handle window resize | |
| window.addEventListener('resize', function() { | |
| canvas.width = canvas.offsetWidth; | |
| canvas.height = canvas.offsetHeight; | |
| drawWave(); | |
| }); | |
| // Initialize Tone.js when user interacts | |
| function initAudio() { | |
| if (Tone.context.state !== 'running') { | |
| Tone.start(); | |
| } | |
| // Create audio nodes | |
| gainNode = new Tone.Gain(currentVolumeValue).toDestination(); | |
| if (currentBinauralState) { | |
| oscillatorLeft = new Tone.Oscillator(currentFrequencyValue, currentWaveTypeValue).connect(gainNode); | |
| oscillatorRight = new Tone.Oscillator(currentFrequencyValue + currentBeatValue, currentWaveTypeValue).connect(gainNode); | |
| } else { | |
| oscillatorLeft = new Tone.Oscillator(currentFrequencyValue, currentWaveTypeValue).connect(gainNode); | |
| } | |
| } | |
| // Play/pause audio | |
| function togglePlayback() { | |
| if (!isPlaying) { | |
| initAudio(); | |
| if (currentBinauralState) { | |
| oscillatorLeft.start(); | |
| oscillatorRight.start(); | |
| } else { | |
| oscillatorLeft.start(); | |
| } | |
| playBtn.innerHTML = '<i data-feather="pause" class="mr-2"></i> Pause Sound'; | |
| playBtn.classList.remove('bg-indigo-600', 'hover:bg-indigo-700'); | |
| playBtn.classList.add('bg-red-500', 'hover:bg-red-600'); | |
| isPlaying = true; | |
| } else { | |
| if (oscillatorLeft) oscillatorLeft.stop(); | |
| if (oscillatorRight) oscillatorRight.stop(); | |
| playBtn.innerHTML = '<i data-feather="play" class="mr-2"></i> Play Sound'; | |
| playBtn.classList.remove('bg-red-500', 'hover:bg-red-600'); | |
| playBtn.classList.add('bg-indigo-600', 'hover:bg-indigo-700'); | |
| isPlaying = false; | |
| } | |
| feather.replace(); | |
| } | |
| // Event listeners | |
| playBtn.addEventListener('click', togglePlayback); | |
| frequencyControl.addEventListener('input', function() { | |
| currentFrequencyValue = parseInt(this.value); | |
| if (oscillatorLeft) oscillatorLeft.frequency.value = currentFrequencyValue; | |
| if (oscillatorRight) oscillatorRight.frequency.value = currentFrequencyValue + currentBeatValue; | |
| updateDisplays(); | |
| }); | |
| volumeControl.addEventListener('input', function() { | |
| currentVolumeValue = parseInt(this.value) / 100; | |
| if (gainNode) gainNode.gain.value = currentVolumeValue; | |
| updateDisplays(); | |
| }); | |
| binauralToggle.addEventListener('change', function() { | |
| currentBinauralState = this.checked; | |
| if (currentBinauralState) { | |
| binauralControls.style.display = 'block'; | |
| } else { | |
| binauralControls.style.display = 'none'; | |
| } | |
| // Restart audio if playing | |
| if (isPlaying) { | |
| togglePlayback(); | |
| setTimeout(togglePlayback, 100); | |
| } | |
| updateDisplays(); | |
| }); | |
| beatControl.addEventListener('input', function() { | |
| currentBeatValue = parseFloat(this.value); | |
| if (oscillatorRight) oscillatorRight.frequency.value = currentFrequencyValue + currentBeatValue; | |
| updateDisplays(); | |
| }); | |
| // Wave type buttons | |
| waveTypeBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| currentWaveTypeValue = this.dataset.type; | |
| // Update active button styling | |
| waveTypeBtns.forEach(b => b.classList.remove('bg-indigo-600', 'text-white')); | |
| this.classList.add('bg-indigo-600', 'text-white'); | |
| if (oscillatorLeft) oscillatorLeft.type = currentWaveTypeValue; | |
| if (oscillatorRight) oscillatorRight.type = currentWaveTypeValue; | |
| // Restart audio if playing | |
| if (isPlaying) { | |
| togglePlayback(); | |
| setTimeout(togglePlayback, 100); | |
| } | |
| updateDisplays(); | |
| }); | |
| }); | |
| // Preset buttons | |
| presetBtns.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const preset = this.dataset.preset; | |
| // Set frequencies based on preset | |
| switch(preset) { | |
| case 'gamma': | |
| currentFrequencyValue = 40; | |
| currentBeatValue = 5; | |
| break; | |
| case 'beta': | |
| currentFrequencyValue = 20; | |
| currentBeatValue = 4; | |
| break; | |
| case 'alpha': | |
| currentFrequencyValue = 10; | |
| currentBeatValue = 3; | |
| break; | |
| case 'theta': | |
| currentFrequencyValue = 6; | |
| currentBeatValue = 2; | |
| break; | |
| case 'delta': | |
| currentFrequencyValue = 2; | |
| currentBeatValue = 1.5; | |
| break; | |
| } | |
| // Enable binaural beats if not already | |
| if (!currentBinauralState) { | |
| binauralToggle.checked = true; | |
| currentBinauralState = true; | |
| binauralControls.style.display = 'block'; | |
| } | |
| // Update UI controls | |
| frequencyControl.value = currentFrequencyValue; | |
| beatControl.value = currentBeatValue; | |
| // Restart audio if playing | |
| if (isPlaying) { | |
| togglePlayback(); | |
| setTimeout(togglePlayback, 100); | |
| } else { | |
| updateDisplays(); | |
| } | |
| }); | |
| }); | |
| // Initial display update | |
| updateDisplays(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |