Examples
record_take
examples/flows/record_take.rs, the whole program
Run it with cargo run --example record_take (see the examples for the features some need).
//! `record` records onto armed tracks. `stop` places a clip on each.
//!
//! ```text
//! record::start / stop / collect
//! track::arm / input / monitor
//! ```
//!
//! ```text
//! track::arm(&mut session, vox, true)?;
//! track::input(&mut session, vox, Some(Input::Mono(0)))?;
//! record::start(&mut session, record::Source::Queue { blocks, channels: 1 })?;
//! let clips = record::stop(&mut session)?;
//! ```
//!
//! ```text
//! cargo run --example record_take
//! ```
use superb::primitives::buffers::PlanarBuffer;
use superb::primitives::io::capture::capture_queue;
use superb::primitives::io::{EngineCommand, LiveInput};
use superb::primitives::session::{Input, TrackKind};
use superb::primitives::{Result, SampleRate, TimePosition};
use superb::{record, session, track, transport};
fn main() -> Result<()> {
let rate = SampleRate::HZ_48K;
let block = 256;
let folder = std::env::temp_dir().join("record_take.superb");
let mut session = session::create(&folder, rate, block)?;
let vox = track::add(&mut session, "vox", TrackKind::Audio)?;
let _bed = track::add(&mut session, "bed", TrackKind::Audio)?;
// vox armed, input channel 0, mono. bed unarmed.
track::arm(&mut session, vox, true)?;
track::input(&mut session, vox, Some(Input::Mono(0)))?;
println!("vox armed: {}", session.memory.track(vox)?.state.arm);
// Monitor the live input on vox.
track::monitor(&mut session, vox, true)?;
let (mut ear, live) = capture_queue(1, block, 8)?;
session
.engine
.send(EngineCommand::LiveInput(Some(LiveInput::new(
live, 1, block,
)?)))?;
transport::start(&mut session)?;
session::steps::render_blocks(&mut session, rate.hz() as usize / block)?;
println!(
"punching in at {:.3} s",
transport::playhead(&session).to_seconds(rate)
);
// Record from the playhead into audio/vox <n>.wav.
let (mut mic, blocks) = capture_queue(1, block, 64)?;
record::start(
&mut session,
record::Source::Queue {
blocks,
channels: 1,
},
)?;
println!(
"recording into {:?}",
session.recording.as_ref().map(|r| r.files().to_vec())
);
// Half a second of 440 Hz at 0.4, pushed to the mic and the monitor.
let mut phase = 0.0f32;
let mut monitored = 0.0f32;
let mut sung = PlanarBuffer::new(1, block);
let blocks = rate.hz() as usize / 2 / block;
for n in 0..blocks {
for s in sung.channel_mut(0) {
*s = 0.4 * phase.sin();
phase += 440.0 * core::f32::consts::TAU / rate.hz() as f32;
}
let timestamp_us = (n * block) as u64 * 1_000_000 / rate.hz() as u64;
mic.push(&sung, timestamp_us);
ear.push(&sung, timestamp_us);
let heard = session::steps::render_blocks(&mut session, 1)?;
monitored = monitored.max(heard.peak());
if n == blocks / 2 {
let frames = record::collect(&mut session);
let r = session.recording.as_ref().expect("recording");
println!(
"half way ({:?}): {frames} frames, {} sealed on disk, {} dropped, {} disk errors, peak {:.2}",
transport::state(&session),
r.sealed_frames(),
r.dropped(),
r.disk_errors(),
r.peaks()[0]
);
}
}
println!("heard while recording: peak {monitored:.3} on the vox strip");
let clips = record::stop(&mut session)?;
if let Ok(entries) = std::fs::read_dir(folder.join("audio")) {
for entry in entries.flatten() {
let bytes = entry.metadata().map(|m| m.len()).unwrap_or(0);
println!("written {} ({bytes} bytes)", entry.path().display());
}
}
for id in &clips {
let clip = session.memory.clip(*id)?;
println!(
"clip {:?} on {}: {:.3} s .. {:.3} s (source {:?})",
clip.name,
session.memory.track(session.memory.clip_track(*id)?)?.name,
clip.start().to_seconds(rate),
(clip.start() + clip.length()).to_seconds(rate),
clip.source
);
}
println!("undo label: {:?}", session.history.undo_label());
transport::seek(&mut session, TimePosition::from_seconds(1.0, rate))?;
transport::start(&mut session)?;
let heard = session::steps::render_blocks(&mut session, 8)?;
println!("playback of the clip, peak {:.3}", heard.peak());
// Undo removes the clip and the file. Buffer stays in session.audio.
session::undo(&mut session)?;
println!(
"after undo: {} clips, {} recording(s) in memory, {} unfinished on disk",
session.memory.clip_count(),
session.audio.len(),
record::unfinished(&session).len()
);
// Record 0.5 s from the default input.
#[cfg(feature = "devices")]
{
use superb::devices;
if devices::inputs()?.is_empty() {
println!("no input device to record from");
} else {
track::arm(&mut session, vox, true)?;
record::start(&mut session, record::Source::Device(None))?;
std::thread::sleep(std::time::Duration::from_millis(500));
let clips = record::stop(&mut session)?;
println!("recorded {} clip(s) from the default input", clips.len());
}
}
Ok(())
}