285 lines
8.1 KiB
Plaintext
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!")
|