use audio_automation::prelude::*;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
enum Param {
Volume,
Cutoff,
}
fn main() {
println!("DAW Workflow\n");
arrange_clips();
automation_states();
render_to_audio();
}
fn arrange_clips() {
println!("1. Arranging Clips\n");
let intro = AutomationClip::new("Intro", 4.0)
.with_envelope(
"volume",
AutomationEnvelope::fade_in(Param::Volume, 4.0, CurveType::Linear),
)
.with_envelope(
"cutoff",
AutomationEnvelope::new(Param::Cutoff)
.with_point(AutomationPoint::new(0.0, 0.2))
.with_point(AutomationPoint::new(4.0, 0.2)),
);
let mut verse = AutomationClip::new("Verse", 8.0)
.with_envelope(
"volume",
AutomationEnvelope::new(Param::Volume)
.with_point(AutomationPoint::new(0.0, 1.0))
.with_point(AutomationPoint::new(8.0, 1.0)),
)
.with_envelope(
"cutoff",
AutomationEnvelope::new(Param::Cutoff)
.with_point(AutomationPoint::new(0.0, 0.2))
.with_point(AutomationPoint::with_curve(
8.0,
1.0,
CurveType::Exponential,
)),
);
verse.merge_clip(&intro, 0.0);
println!(" Timeline duration: {:.1} beats", verse.duration);
println!(
" volume at t=0 (fade start): {:.2}",
verse["volume"].get_value_at(0.0).unwrap()
);
println!(
" volume at t=2 (mid fade-in): {:.2}",
verse["volume"].get_value_at(2.0).unwrap()
);
println!(
" volume at t=4 (verse body): {:.2}",
verse["volume"].get_value_at(4.0).unwrap()
);
println!(
" cutoff at t=8 (end of sweep): {:.2}\n",
verse["cutoff"].get_value_at(8.0).unwrap()
);
}
fn automation_states() {
println!("2. Automation States\n");
let env = AutomationEnvelope::new(Param::Volume)
.with_point(AutomationPoint::new(0.0, 0.0))
.with_point(AutomationPoint::new(4.0, 1.0));
let states = AutomationState::all();
for &state in states {
let reads = state.reads_automation();
let records = state.can_record();
let effective_value = if reads {
env.get_value_at(2.0).unwrap() } else {
0.75 };
println!(
" [{:3}] reads={:5} records={:5} → value at t=2: {:.2}",
state.abbreviation(),
reads,
records,
effective_value
);
}
println!();
}
fn render_to_audio() {
println!("3. Rendering to Audio\n");
let sample_rate = 48_000.0;
let duration = 1.0;
let env = AutomationEnvelope::new(Param::Volume)
.with_point(AutomationPoint::new(0.0, 0.0))
.with_point(AutomationPoint::with_curve(
duration,
1.0,
CurveType::SCurve,
));
let buffer = env.to_buffer(sample_rate, duration);
println!(" Buffer length: {} samples", buffer.len());
println!(" buffer[0]: {:.4}", buffer[0]);
println!(" buffer[24000]: {:.4}", buffer[24_000]);
println!(" buffer[47999]: {:.4}", buffer[47_999]);
let rms = {
let sum_sq: f32 = env.iter_samples(sample_rate, duration).map(|v| v * v).sum();
(sum_sq / buffer.len() as f32).sqrt()
};
println!(" RMS over 1 s: {:.4}\n", rms);
}