use tunes::prelude::*;
use tunes::synthesis::effects::convolution;
use std::time::Instant;
fn main() -> anyhow::Result<()> {
println!("🚀 GPU-Accelerated Convolution Reverb Demo\n");
println!("Creating test composition (arpeggios with convolution reverb)...");
println!("Composition: ~4 seconds, 64 notes\n");
let cpu_time;
println!("=== Test 1: CPU Convolution (Cathedral) ===");
println!("Note: Using cathedral preset (long IR ~500k samples)");
println!(" GPU uses partitioned convolution to handle any IR size\n");
{
let mut comp_cpu = Composition::new(Tempo::new(120.0));
let pattern = [C4, E4, G4, B4, C5, B4, G4, E4];
for i in 0..8 {
let start_time = i as f32 * 0.5;
for (j, ¬e) in pattern.iter().enumerate() {
comp_cpu.instrument("piano", &Instrument::acoustic_piano())
.at(start_time + j as f32 * 0.125)
.note(&[note], 0.2);
}
}
let reverb = convolution::presets::cathedral(0.7)?;
comp_cpu.track("piano").convolution_reverb(reverb);
let mut mixer = comp_cpu.into_mixer();
println!("⏱️ Rendering with CPU convolution...");
let start = Instant::now();
mixer.export_wav("gpu_convolution_cpu.wav", 44100)?;
cpu_time = start.elapsed();
println!(" CPU render time: {:.3}s", cpu_time.as_secs_f32());
println!(" Output: gpu_convolution_cpu.wav");
}
#[cfg(feature = "gpu")]
{
println!("\n=== Test 2: GPU Convolution (Cathedral) ===");
let mut comp_gpu = Composition::new(Tempo::new(120.0));
let pattern = [C4, E4, G4, B4, C5, B4, G4, E4];
for i in 0..8 {
let start_time = i as f32 * 0.5;
for (j, ¬e) in pattern.iter().enumerate() {
comp_gpu.instrument("piano", &Instrument::acoustic_piano())
.at(start_time + j as f32 * 0.125)
.note(&[note], 0.2);
}
}
let mut reverb = convolution::presets::cathedral(0.7)?;
print!("🎮 Initializing GPU...");
match reverb.enable_gpu() {
Ok(_) => println!(" ✅ GPU enabled!"),
Err(e) => {
println!(" ❌ GPU initialization failed: {}", e);
println!(" Falling back to CPU");
}
}
comp_gpu.track("piano").convolution_reverb(reverb);
let mut mixer = comp_gpu.into_mixer();
println!("⏱️ Rendering with GPU convolution...");
let start = Instant::now();
mixer.export_wav("gpu_convolution_gpu.wav", 44100)?;
let gpu_time = start.elapsed();
println!(" GPU render time: {:.3}s", gpu_time.as_secs_f32());
println!(" Output: gpu_convolution_gpu.wav");
let speedup = cpu_time.as_secs_f32() / gpu_time.as_secs_f32();
println!("\n📊 Performance Comparison:");
println!(" CPU: {:.3}s", cpu_time.as_secs_f32());
println!(" GPU: {:.3}s", gpu_time.as_secs_f32());
println!(" Speedup: {:.2}x faster", speedup);
if speedup > 1.0 {
println!("\n🎯 GPU acceleration successful! {:.1}% faster", (speedup - 1.0) * 100.0);
} else {
println!("\n⚠️ Note: On integrated GPUs, speedup may be minimal.");
println!(" Discrete GPUs typically show 5-50x speedups.");
}
println!("\n📝 GPU Features:");
println!(" • Partitioned convolution: Handles any IR size (no limits!)");
println!(" • Parallel processing: All partitions processed simultaneously");
println!(" • Long reverbs (cathedral, concert hall) fully supported");
}
#[cfg(not(feature = "gpu"))]
{
println!("\n=== Test 2: GPU Convolution - SKIPPED ===");
println!(" GPU feature not enabled");
println!(" Run with: cargo run --example gpu_convolution_demo --features gpu --release");
}
println!("\n✅ Demo complete!");
Ok(())
}