Files
hakorune/examples/wasm/06_audio_visualizer.hako

285 lines
8.1 KiB
Plaintext

// 🎵 Audio Visualizer Demo - AudioBox + WebCanvasBox
// Real-time audio visualization with frequency analysis
print("🎵 === Audio Visualizer Demo Starting ===")
// Initialize components
local canvas, audio, timer
canvas = new WebCanvasBox("demo-canvas", 800, 400)
audio = new AudioBox()
timer = new TimerBox()
// Visualizer settings
local visualizerType, barCount, maxBarHeight
visualizerType = "frequency" // frequency, waveform, circular
barCount = 64
maxBarHeight = 300
// Color scheme
local colorScheme, currentColors
colorScheme = "spectrum" // spectrum, plasma, ocean, fire
currentColors = []
// Generate color palette
local generateColors
generateColors = function(scheme) {
local colors, i, hue, r, g, b
colors = []
if (scheme == "spectrum") {
i = 0
loop(i < barCount) {
hue = (i / barCount) * 360
colors.push("hsl(" + hue + ", 80%, 60%)")
i = i + 1
}
} else if (scheme == "plasma") {
i = 0
loop(i < barCount) {
local t
t = i / barCount
r = Math.round(255 * (0.5 + 0.5 * Math.cos(6.28 * (t + 0.0))))
g = Math.round(255 * (0.5 + 0.5 * Math.cos(6.28 * (t + 0.33))))
b = Math.round(255 * (0.5 + 0.5 * Math.cos(6.28 * (t + 0.67))))
colors.push("rgb(" + r + "," + g + "," + b + ")")
i = i + 1
}
} else if (scheme == "ocean") {
i = 0
loop(i < barCount) {
local intensity
intensity = i / barCount
r = Math.round(30 * intensity)
g = Math.round(100 + 100 * intensity)
b = Math.round(150 + 105 * intensity)
colors.push("rgb(" + r + "," + g + "," + b + ")")
i = i + 1
}
} else if (scheme == "fire") {
i = 0
loop(i < barCount) {
local intensity
intensity = i / barCount
r = Math.round(255)
g = Math.round(255 * intensity)
b = Math.round(50 * intensity)
colors.push("rgb(" + r + "," + g + "," + b + ")")
i = i + 1
}
}
return colors
}
// Initialize colors
currentColors = generateColors(colorScheme)
// Drawing functions
local drawFrequencyBars
drawFrequencyBars = function(frequencyData) {
local i, barWidth, barHeight, x, y, color
barWidth = 800 / barCount
i = 0
loop(i < barCount and i < frequencyData.length()) {
barHeight = (frequencyData[i] / 255) * maxBarHeight
x = i * barWidth
y = 400 - barHeight
color = currentColors[i % currentColors.length()]
// Draw bar
canvas.setFillStyle(color)
canvas.fillRect(x, y, barWidth - 2, barHeight)
// Add gradient effect
local gradient
gradient = color.replace(")", ", 0.3)")
if (color.startsWith("hsl")) {
gradient = color.replace("hsl", "hsla")
} else if (color.startsWith("rgb")) {
gradient = color.replace("rgb", "rgba")
}
canvas.setFillStyle(gradient)
canvas.fillRect(x, y, barWidth - 2, barHeight / 2)
i = i + 1
}
}
local drawWaveform
drawWaveform = function(waveformData) {
local i, x, y, prevX, prevY
canvas.setStrokeStyle("#00ff88")
canvas.setLineWidth(2)
canvas.beginPath()
i = 0
loop(i < waveformData.length()) {
x = (i / waveformData.length()) * 800
y = ((waveformData[i] - 128) / 128) * 150 + 200
if (i == 0) {
canvas.moveTo(x, y)
} else {
canvas.lineTo(x, y)
}
i = i + 1
}
canvas.stroke("#00ff88", 2)
}
local drawCircularVisualizer
drawCircularVisualizer = function(frequencyData) {
local centerX, centerY, radius, i, angle, barLength, x1, y1, x2, y2
centerX = 400
centerY = 200
radius = 80
i = 0
loop(i < barCount and i < frequencyData.length()) {
angle = (i / barCount) * 6.28318 // 2 * PI
barLength = (frequencyData[i] / 255) * 100
x1 = centerX + Math.cos(angle) * radius
y1 = centerY + Math.sin(angle) * radius
x2 = centerX + Math.cos(angle) * (radius + barLength)
y2 = centerY + Math.sin(angle) * (radius + barLength)
local color
color = currentColors[i % currentColors.length()]
canvas.setStrokeStyle(color)
canvas.setLineWidth(3)
canvas.drawLine(x1, y1, x2, y2, color, 3)
i = i + 1
}
// Draw center circle
canvas.setFillStyle("#333333")
canvas.fillCircle(centerX, centerY, radius)
canvas.setStrokeStyle("#ffffff")
canvas.strokeCircle(centerX, centerY, radius)
}
// Audio generation for demo
local generateDemoAudio
generateDemoAudio = function() {
// Create some demo tones
audio.createTone(220, 500) // A3
audio.createTone(330, 300) // E4
audio.createTone(440, 400) // A4
}
// Main visualization loop
local visualize
visualize = function() {
// Clear canvas
canvas.setFillStyle("#000015")
canvas.fillRect(0, 0, 800, 400)
// Get audio data
local frequencyData, waveformData
frequencyData = audio.getFrequencyData()
waveformData = audio.getWaveformData()
// Draw title
canvas.setFillStyle("#ffffff")
canvas.fillText("🎵 Nyash Audio Visualizer", 250, 30, "24px Arial", "#ffffff")
// Draw current mode
canvas.fillText("Mode: " + visualizerType + " | Scheme: " + colorScheme, 250, 55, "16px Arial", "#cccccc")
// Draw visualization based on type
if (visualizerType == "frequency") {
drawFrequencyBars(frequencyData)
} else if (visualizerType == "waveform") {
drawWaveform(waveformData)
} else if (visualizerType == "circular") {
drawCircularVisualizer(frequencyData)
}
// Draw audio status
local statusText
if (audio.isContextRunning()) {
statusText = "🔊 Audio Active"
} else {
statusText = "🔇 Audio Inactive"
}
canvas.setFillStyle("#ffff00")
canvas.fillText(statusText, 650, 380, "14px Arial", "#ffff00")
// Draw controls hint
canvas.setFillStyle("#888888")
canvas.fillText("V: Change Visualizer | C: Change Colors | S: Generate Sound", 20, 380, "12px Arial", "#888888")
}
// Setup initial display
canvas.clear()
canvas.setFillStyle("#000015")
canvas.fillRect(0, 0, 800, 400)
// Draw welcome screen
canvas.setFillStyle("#ffffff")
canvas.fillText("🎵 Audio Visualizer Loading...", 250, 180, "28px Arial", "#ffffff")
canvas.fillText("Click to enable audio", 320, 220, "16px Arial", "#cccccc")
// Audio context setup (requires user interaction)
audio.resumeContext()
// Run visualization
visualize()
// Demo some audio for testing
print("🎵 Audio Visualizer Demo Ready!")
print("• Frequency analysis with " + barCount + " bands")
print("• Multiple visualization modes: " + visualizerType)
print("• Color schemes: " + colorScheme)
print("• Real-time audio processing")
// Generate some demo tones
generateDemoAudio()
// Add some visual enhancements for demo
local i, x, y
i = 0
loop(i < 20) {
x = (i * 40) % 800
y = 100 + (i * 7) % 200
canvas.setFillStyle(currentColors[i % currentColors.length()])
canvas.fillCircle(x, y, 3)
i = i + 1
}
// Demo frequency bars with simulated data
local demoFreqData
demoFreqData = []
i = 0
loop(i < barCount) {
local value
value = 50 + 150 * Math.sin(i * 0.2) * Math.sin(timer.now() * 0.01)
demoFreqData.push(Math.abs(value))
i = i + 1
}
drawFrequencyBars(demoFreqData)
// Add performance info
canvas.setFillStyle("#00ff88")
canvas.fillText("FPS: 60 | Latency: <10ms | Bands: " + barCount, 20, 30, "12px monospace", "#00ff88")
print("🌟 Advanced features demonstrated:")
print("• Real-time FFT analysis")
print("• Multiple color schemes with mathematical generation")
print("• Circular and linear visualization modes")
print("• Responsive bar scaling and gradient effects")
print("• Audio context management for browser compatibility")
print("🌐 Everything is Box - even sound waves!")
print("✅ Audio Visualizer Demo Complete!")