use rivet_app::{AudioEngine, Shared}; use std::{ alloc::{GlobalAlloc, Layout, System}, cell::Cell, }; struct CheckedAllocator; thread_local! { static CHECK:Cell=const {Cell::new(false)}; static OPERATIONS:Cell=const {Cell::new(0)}; } fn record() { if CHECK.try_with(Cell::get).unwrap_or(false) { let _ = OPERATIONS.try_with(|n| n.set(n.get() + 1)); } } unsafe impl GlobalAlloc for CheckedAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { record(); unsafe { System.alloc(layout) } } unsafe fn dealloc(&self, pointer: *mut u8, layout: Layout) { record(); unsafe { System.dealloc(pointer, layout) } } unsafe fn realloc(&self, pointer: *mut u8, layout: Layout, size: usize) -> *mut u8 { record(); unsafe { System.realloc(pointer, layout, size) } } } #[global_allocator] static ALLOCATOR: CheckedAllocator = CheckedAllocator; #[test] fn playback_control_and_rendering_do_not_allocate_or_free() { let shared = Shared::default(); let mut settings = rivet_core::PerformanceSettings { mode: rivet_core::RoleMode::Alternating, ..Default::default() }; for (i, voice) in settings.voices.iter_mut().enumerate() { voice.attack_ms = 100; voice.release_ms = 20; voice.controller.enabled = true; voice.controller.cc = 20 + i as u8; } shared .replace(rivet_core::Session { performance: settings, audition: rivet_core::Audition::Midi, tempo: 300., ..Default::default() }) .unwrap(); let mut audio = AudioEngine::default(); let motif = rivet_core::demo_motif(); audio.player.set_sample_rate(8000.).unwrap(); shared.preview(&motif).unwrap(); CHECK.with(|flag| flag.set(true)); for _ in 0..4 { audio.begin_block(&shared); for _ in 0..10000 { std::hint::black_box(audio.frame(300., true)); } audio.end_block(&shared); } CHECK.with(|flag| flag.set(false)); shared.audition(&motif).unwrap(); CHECK.with(|flag| flag.set(true)); audio.begin_block(&shared); for _ in 0..30000 { std::hint::black_box(audio.frame(300., true)); } audio.end_block(&shared); CHECK.with(|flag| flag.set(false)); shared.stop(); CHECK.with(|flag| flag.set(true)); audio.begin_block(&shared); std::hint::black_box(audio.frame(300., true)); audio.end_block(&shared); CHECK.with(|flag| flag.set(false)); assert_eq!(OPERATIONS.with(Cell::get), 0); assert!(!audio.player.is_playing()); }