Check and Windows preview / check (anvil) (push) Successful in 2m15s
Check and Windows preview / check (braze) (push) Successful in 2m26s
Check and Windows preview / check (crucible) (push) Successful in 1m52s
Check and Windows preview / check (knurl) (push) Successful in 1m42s
Check and Windows preview / check (lathe) (push) Successful in 1m44s
Check and Windows preview / check (patina) (push) Successful in 2m38s
Check and Windows preview / check (planish) (push) Successful in 1m29s
Check and Windows preview / check (rivet) (push) Successful in 1m39s
Check and Windows preview / check (temper) (push) Successful in 1m37s
Check and Windows preview / check (weld) (push) Canceled after 2s
Check and Windows preview / previews (push) Canceled after 0s
Check and Windows preview / windows (push) Canceled after 0s
Adds a detuned copy of the bass whose beating stays on the tempo grid on every note. The chosen harmonic k beats once per Rate note value, and harmonic n beats n/k times as fast, so every harmonic is on the grid. - The copy is read from a delay line whose delay falls one period of the tracked note per beat cycle (r = 1 + B/(k f0)) and jumps back exactly one period, crossfaded over 6 ms. On a periodic note the jump has no seam: the output matches the ideal sum within 0.003 on harmonics 1-4. - The delay follows the host's beat position, shifted by the lookahead, so beat peaks land on the grid; free-running when stopped. - Low cut: LR4 high-pass on the copy, the bass split by the same crossover, so the sub does not beat and keeps its level. - Depth, Width, Phase, Gate, Output, Snap, Bypass. Pitch from audio (about 67 ms lookahead) or MIDI. - Editor: one bar of the beat per harmonic with the grid and a playhead. - Catalog, workflows, editor-check, docs, signal chain and site copy.
80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use braze_core::{Engine, Rate, Settings, Source};
|
|
use std::{
|
|
alloc::{GlobalAlloc, Layout, System},
|
|
cell::Cell,
|
|
};
|
|
|
|
struct CheckedAllocator;
|
|
thread_local! {
|
|
static CHECK:Cell<bool>=const {Cell::new(false)};
|
|
static OPERATIONS:Cell<usize>=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 processing_notes_settings_transport_and_analysis_do_not_allocate_or_free() {
|
|
let mut engine = Engine::new(48000., 2).unwrap();
|
|
let mut settings = Settings {
|
|
width: 50.,
|
|
..Settings::default()
|
|
};
|
|
engine.set_settings(settings).unwrap();
|
|
CHECK.with(|v| v.set(true));
|
|
for i in 0..96000 {
|
|
if i % 512 == 0 {
|
|
let playing = (i / 24000) % 2 == 0;
|
|
engine.set_transport(
|
|
Some(140.),
|
|
playing.then_some(i as f64 / 48000. * 140. / 60.),
|
|
);
|
|
}
|
|
if i % 4800 == 0 {
|
|
settings.rate = Rate::ALL[(i / 4800) % Rate::ALL.len()];
|
|
settings.harmonic = 1 + (i / 4800 % 4) as u32;
|
|
settings.source = if i > 48000 {
|
|
Source::Midi
|
|
} else {
|
|
Source::Audio
|
|
};
|
|
engine.set_settings(settings).unwrap();
|
|
engine.note_on(30 + (i / 4800 % 12) as u8);
|
|
}
|
|
if i % 4800 == 2400 {
|
|
engine.note_off(30 + (i / 4800 % 12) as u8);
|
|
}
|
|
let t = i as f32 / 48000.;
|
|
let x = if (i / 2400) % 2 == 0 {
|
|
(std::f32::consts::TAU * 55. * t).sin() * 0.5
|
|
} else {
|
|
0.
|
|
};
|
|
std::hint::black_box(engine.process_sample([x, x]));
|
|
if i % 1600 == 0 {
|
|
std::hint::black_box(engine.take_analyzer());
|
|
}
|
|
}
|
|
engine.reset();
|
|
CHECK.with(|v| v.set(false));
|
|
assert_eq!(OPERATIONS.with(Cell::get), 0);
|
|
}
|