#![cfg_attr(
not(bela_device),
allow(
dead_code,
reason = "only the fallback main is reachable off-device; the application code should still compile and lint"
)
)]
#[cfg(not(bela_device))]
use std::process::ExitCode;
use bela::{
BelaApplication, BlockContext, CleanupContext, RenderContext, SetupContext, ThreadInfo,
rt_println,
};
struct Heartbeat {
blocks: u64,
blocks_per_report: u64,
}
impl Heartbeat {
const fn new() -> Self {
Self {
blocks: 0,
blocks_per_report: 1,
}
}
}
impl BelaApplication for Heartbeat {
type RenderState = ();
fn setup(&mut self, context: &SetupContext) -> bool {
let frames = context.audio_frames();
let sample_rate = context.audio_sample_rate();
#[allow(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
reason = "the sample rate is a small positive number"
)]
let sample_rate_hz = sample_rate as u64;
self.blocks_per_report = (sample_rate_hz / frames.max(1) as u64).max(1);
rt_println!(
"setup: {sample_rate} Hz, {frames} frames per block, \
{} in / {} out audio channels, {} render thread(s)",
context.audio_in_channels(),
context.audio_out_channels(),
context.thread_count()
);
true
}
fn create_render_state(&mut self, _thread: ThreadInfo, _context: &SetupContext) {}
fn render(&self, _state: &mut (), _context: &mut RenderContext) {}
fn render_post(&mut self, _states: &mut [()], context: &mut BlockContext) {
self.blocks += 1;
if self.blocks % self.blocks_per_report == 0 {
rt_println!(
"render: {} blocks, {} frames elapsed, {} underruns",
self.blocks,
context.audio_frames_elapsed(),
context.underrun_count()
);
}
}
fn cleanup(&mut self, _states: &mut [()], _context: &CleanupContext) {
rt_println!("cleanup: {} blocks rendered", self.blocks);
}
}
#[cfg(bela_device)]
fn main() -> Result<(), bela::Error> {
bela::Bela::run(Heartbeat::new(), &bela::Settings::new())
}
#[cfg(not(bela_device))]
fn main() -> ExitCode {
eprintln!("This example must be cross-compiled for Bela Gem (aarch64-unknown-linux-gnu).");
ExitCode::FAILURE
}