Skip to main content

proteus_lib/peaks/
mod.rs

1//! Peak extraction and binary peak-file utilities for waveform display.
2
3mod error;
4mod extract;
5mod format;
6
7pub use error::PeaksError;
8
9/// A single peak window with maximum and minimum sample amplitude.
10#[derive(Debug, Clone, Copy)]
11pub struct PeakWindow {
12    pub max: f32,
13    pub min: f32,
14}
15
16/// Peak data for all channels at a fixed window size.
17#[derive(Debug, Clone)]
18pub struct PeaksData {
19    pub sample_rate: u32,
20    pub window_size: u32,
21    pub channels: Vec<Vec<PeakWindow>>,
22}
23
24/// Query options for reading peaks from a binary peaks file.
25#[derive(Debug, Clone, Default)]
26pub struct GetPeaksOptions {
27    /// Start timestamp in seconds (inclusive). If omitted, reads from file start.
28    pub start_seconds: Option<f64>,
29    /// End timestamp in seconds (exclusive). If omitted, reads to file end.
30    pub end_seconds: Option<f64>,
31    /// Maximum number of peak windows to return per channel.
32    ///
33    /// If the range contains fewer peaks than requested, all peaks are returned.
34    pub target_peaks: Option<usize>,
35    /// Maximum number of channels to return.
36    ///
37    /// Channels are selected from index 0 upward.
38    pub channels: Option<usize>,
39}
40
41/// Decode an audio file and write its peaks to a binary file.
42///
43/// # Arguments
44/// * `input_audio_file` - Source audio path.
45/// * `output_peaks_file` - Destination binary peaks file path.
46///
47/// # Errors
48/// Returns an error if audio decode fails or if writing the peaks file fails.
49pub fn write_peaks(input_audio_file: &str, output_peaks_file: &str) -> Result<(), PeaksError> {
50    let peaks = extract::extract_peaks_from_audio(input_audio_file, false)?;
51    format::write_peaks_file(output_peaks_file, &peaks)
52}
53
54/// Read all peaks from a binary peaks file.
55///
56/// # Arguments
57/// * `peaks_file` - Path to a binary peaks file previously written by [`write_peaks`].
58/// * `options` - Query options for range, peak count, and channel count.
59///
60/// # Returns
61/// Per-channel peak data after applying range/channel/downsample options.
62///
63/// # Errors
64/// Returns an error if the file cannot be read or has an invalid peaks format.
65pub fn get_peaks(peaks_file: &str, options: GetPeaksOptions) -> Result<PeaksData, PeaksError> {
66    format::read_peaks_with_options(peaks_file, &options)
67}
68
69/// Read all channels and all peaks from a binary peaks file.
70///
71/// # Arguments
72/// * `peaks_file` - Path to a binary peaks file previously written by [`write_peaks`].
73///
74/// # Returns
75/// Full per-channel peak data.
76///
77/// # Errors
78/// Returns an error if the file cannot be read or has an invalid peaks format.
79pub fn get_all_peaks(peaks_file: &str) -> Result<PeaksData, PeaksError> {
80    get_peaks(peaks_file, GetPeaksOptions::default())
81}
82
83/// Read peaks from a binary peaks file for a specific time range in seconds.
84///
85/// # Arguments
86/// * `peaks_file` - Path to a binary peaks file.
87/// * `start_seconds` - Start timestamp (inclusive).
88/// * `end_seconds` - End timestamp (exclusive).
89///
90/// # Returns
91/// Per-channel peak data for the requested time range.
92///
93/// # Errors
94/// Returns an error if timestamps are invalid, or if file IO/format parsing fails.
95pub fn get_peaks_in_range(
96    peaks_file: &str,
97    start_seconds: f64,
98    end_seconds: f64,
99) -> Result<PeaksData, PeaksError> {
100    get_peaks(
101        peaks_file,
102        GetPeaksOptions {
103            start_seconds: Some(start_seconds),
104            end_seconds: Some(end_seconds),
105            ..Default::default()
106        },
107    )
108}
109
110/// Decode an audio file directly into in-memory peaks.
111///
112/// # Arguments
113/// * `file_path` - Source audio path.
114/// * `limited` - If true, only channel 0 is processed.
115///
116/// # Returns
117/// In-memory per-channel peak data.
118///
119/// # Errors
120/// Returns an error if decoding fails.
121pub fn extract_peaks_from_audio(file_path: &str, limited: bool) -> Result<PeaksData, PeaksError> {
122    extract::extract_peaks_from_audio(file_path, limited)
123}