use anyhow::{Result, anyhow};
use lasprs::ps::*;
use lasprs::{FreqWeighting, Overlap, WindowType, daq::*};
use std::{thread, time::Duration};
fn main() -> Result<()> {
println!("Simple LaspRS Recording and Analysis Example");
println!("==========================================");
let mut stream_mgr = StreamMgr::new_with_devices();
#[cfg(feature = "loopback-api")]
{
println!("Using loopback device (no audio hardware required)...");
let devices = stream_mgr.getDeviceInfo();
if let Some(loopback_device) = devices.iter().find(|d| d.device_name == "Loopback") {
let config = DaqConfig::newFromDeviceInfo(loopback_device);
stream_mgr.startStream(StreamType::Input, &config)?;
} else {
println!("Loopback device not found, using default input stream...");
stream_mgr.startDefaultInputStream()?;
}
}
#[cfg(not(feature = "loopback-api"))]
{
println!("Starting default input stream (system default input device)...");
println!("Note: This will use your system microphone. Make some noise to see signal!");
stream_mgr.startDefaultInputStream()?;
}
let name = "simple_recording";
let _ = std::fs::remove_file(name);
let recording_duration = Duration::from_secs(2);
let cps_settings = CPSSettings {
nfft: 1024, overlap: Overlap::NoOverlap {},
window: WindowType::Hann,
istart: None,
istop: None,
};
let record_settings = RecordSettings::new_simple(name, Some(recording_duration))?;
println!(
"Recording for {} seconds to '{}'...",
recording_duration.as_secs(),
name
);
let mut recording = Recording::new(record_settings, &mut stream_mgr)?;
loop {
match recording.status() {
RecordStatus::Recording {
recorded, pct_done, ..
} => {
print!("\rProgress: {:.0}% ({:.1}s)", pct_done * 100.0, recorded);
std::io::Write::flush(&mut std::io::stdout()).unwrap();
}
RecordStatus::Finished { finishedrecording } => {
println!("\nRecording done");
if let Some(error) = &finishedrecording.error {
anyhow::bail!("Recording error: {}", error);
}
break;
}
_ => {}
}
thread::sleep(Duration::from_millis(50));
}
stream_mgr.stopInputStream()?;
println!("Opening measurement file for analysis...");
let measurement = recording
.getMeasurement()
.ok_or_else(|| anyhow!("Failed to get measurement"))?;
let (nchannels, samplerate, duration);
let cps;
{
let mut measurement = measurement.write();
println!("Measurement info:");
nchannels = measurement.nchannels();
samplerate = measurement.samplerate();
duration = measurement.get_duration();
println!(" Channels: {}", nchannels);
println!(" Sample rate: {} Hz", samplerate);
println!(" Duration: {:.2} s", duration);
println!("Calculating auto power spectrum...");
cps = measurement.CPS(
&cps_settings,
FreqWeighting::Z, Some(&[0]), )?;
}
let powers = cps.ap(0);
let total_power: f64 = powers.iter().sum();
let max_power = powers.iter().cloned().fold(0.0f64, f64::max);
println!("Auto power results:");
println!(" Total power: {:.3e}", total_power);
println!(" Peak power: {:.3e}", max_power);
println!(" Frequency bins: {}", powers.len());
let freq_res = *samplerate as f64 / cps_settings.nfft as f64;
println!("First 5 frequency bins:");
for (i, &power) in powers.iter().take(5).enumerate() {
println!(" {:.1} Hz: {:.3e}", i as f64 * freq_res, power);
}
std::fs::remove_file(name)?;
println!("Cleaned up recording file");
Ok(())
}