#![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"
)
)]
use core::f32::consts::TAU;
#[cfg(not(bela_device))]
use std::process::ExitCode;
use bela::{BelaApplication, Context};
const FREQUENCY: f32 = 440.0;
const AMPLITUDE: f32 = 0.3;
const LINE_OUT_LEVEL: f32 = -12.0;
const HEADPHONE_LEVEL: f32 = -20.0;
const INPUT_GAIN: f32 = 30.0;
const MISSING_CHANNEL: usize = 64;
struct Sine {
phase: f32,
phase_increment: f32,
}
impl Sine {
const fn new() -> Self {
Self {
phase: 0.0,
phase_increment: 0.0,
}
}
}
unsafe impl BelaApplication for Sine {
fn setup(&mut self, context: &mut Context) -> bool {
self.phase_increment = TAU * FREQUENCY / context.audio_sample_rate();
true
}
fn render(&mut self, context: &mut Context) {
for frame in 0..context.audio_frames() {
let sample = AMPLITUDE * self.phase.sin();
for channel in 0..context.audio_out_channels() {
context.audio_write(frame, channel, sample);
}
self.phase += self.phase_increment;
if self.phase >= TAU {
self.phase -= TAU;
}
}
}
}
#[cfg(bela_device)]
fn outcome(result: Result<(), bela::Error>) -> String {
match result {
Ok(()) => "ok".to_owned(),
Err(error) => format!("failed({error})"),
}
}
#[cfg(bela_device)]
fn main() -> Result<(), bela::Error> {
use bela::{Bela, Channel, Settings};
let mut bela = Bela::new(Sine::new(), &Settings::new())?;
let line_out = outcome(bela.set_line_out_level(Channel::All, LINE_OUT_LEVEL));
let headphone = outcome(bela.set_headphone_level(Channel::All, HEADPHONE_LEVEL));
let input_gain = outcome(bela.set_audio_input_gain(Channel::All, INPUT_GAIN));
let unmuted = outcome(bela.mute_speakers(false));
let missing = match bela.set_line_out_level(Channel::One(MISSING_CHANNEL), LINE_OUT_LEVEL) {
Err(bela::Error::LineOutLevel(_)) => "refused".to_owned(),
Ok(()) => "accepted".to_owned(),
Err(error) => format!("other-error({error})"),
};
let not_a_number = match bela.set_line_out_level(Channel::All, f32::NAN) {
Err(bela::Error::Decibels) => "refused".to_owned(),
Ok(()) => "accepted".to_owned(),
Err(error) => format!("other-error({error})"),
};
println!(
"levels: line-out={line_out} headphone={headphone} input-gain={input_gain} \
unmute={unmuted} missing-channel={missing} not-a-number={not_a_number}"
);
bela.until_stopped()
}
#[cfg(not(bela_device))]
fn main() -> ExitCode {
eprintln!("This example must be cross-compiled for Bela Gem (aarch64-unknown-linux-gnu).");
ExitCode::FAILURE
}