ThreeSixNine's picture
Create a site like this one https://mynoise.net/NoiseMachines/binauralBrainwaveGenerator.php
ec4b239 verified
<!DOCTYPE html>
<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>