From 944496841f42f1f1dfd922d5eb4d073595c4c5ce Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Mon, 13 May 2024 10:06:42 +0200 Subject: [PATCH 1/8] cargo: remove dep libm which is now unused --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 28d75a3..18f8695 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,6 @@ required-features = ["recording"] # +++ NOSTD DEPENDENCIES +++ biquad = "0.4" # lowpass filter -libm = "0.2"# floating point operations log = { version = "0.4", default-features = false } ringbuffer = "0.15.0" From 2bc480ad2ac15a6f910c4e4f7426a388b47648f9 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:06:16 +0200 Subject: [PATCH 2/8] misc --- .editorconfig | 2 +- shell.nix | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2537322..a5bf035 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,5 +11,5 @@ indent_size = 4 trim_trailing_whitespace = true max_line_length = 80 -[*.yml] +[{*.nix,*.yml}] indent_size = 2 diff --git a/shell.nix b/shell.nix index c0cc61f..bc778fb 100644 --- a/shell.nix +++ b/shell.nix @@ -1,14 +1,18 @@ { pkgs ? import { } }: -pkgs.mkShell rec { - packages = with pkgs; [ - # Base deps - alsa-lib - pkg-config +let + libDeps = with pkgs; [ # gui examples (minifb) libxkbcommon xorg.libXcursor xorg.libX11 + ]; +in +pkgs.mkShell { + packages = with pkgs; [ + # Base deps + alsa-lib + pkg-config # benchmarks gnuplot @@ -16,5 +20,7 @@ pkgs.mkShell rec { # Development nixpkgs-fmt rustup - ]; + ] ++ libDeps; + + LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath libDeps}"; } From 7b6d083b25a6cdeb644b360d8af6a7a8cb11f04a Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:06:52 +0200 Subject: [PATCH 3/8] misc --- src/stdlib/mod.rs | 2 -- src/stdlib/recording.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/stdlib/mod.rs b/src/stdlib/mod.rs index fd5ecac..87e396e 100644 --- a/src/stdlib/mod.rs +++ b/src/stdlib/mod.rs @@ -23,6 +23,4 @@ SOFTWARE. */ //! All modules that require `std` functionality. -use std::prelude::rust_2021::*; - pub mod recording; diff --git a/src/stdlib/recording.rs b/src/stdlib/recording.rs index 393590e..8e6d880 100644 --- a/src/stdlib/recording.rs +++ b/src/stdlib/recording.rs @@ -24,12 +24,12 @@ SOFTWARE. //! Module for audio recording from an audio input device. -use super::*; use crate::{BeatDetector, BeatInfo}; use core::fmt::{Display, Formatter}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::{BufferSize, StreamConfig}; use std::error::Error; +use std::string::ToString; use std::time::{Duration, Instant}; #[derive(Debug)] From 309e3f56785729b8afa6de06296bf08ca1694675 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:35:56 +0200 Subject: [PATCH 4/8] dependency updates --- Cargo.toml | 11 ++++---- benches/beat_detection_bench.rs | 35 ++++++++++------------- src/audio_history.rs | 2 +- src/beat_detector.rs | 16 +++++------ src/envelope_iterator.rs | 12 ++++---- src/lib.rs | 4 +-- src/max_min_iterator.rs | 2 +- src/root_iterator.rs | 4 +-- src/test_utils.rs | 49 ++++++++++++++------------------- 9 files changed, 61 insertions(+), 74 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18f8695..a210510 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,11 +44,11 @@ name = "general" harness = false [[example]] -name = "minimal-live-input" +name = "live-input-minimal" required-features = ["recording"] [[example]] -name = "minimal-live-input-gui" +name = "live-input-visualize" required-features = ["recording"] [dependencies] @@ -66,12 +66,13 @@ cpal = { version = "0.15", optional = true } assert2 = "0.3.14" ctrlc = { version = "3.4", features = ["termination"] } criterion = { version = "0.5", features = [] } -float-cmp = "0.9.0" +float-cmp = "0.10.0" +hound = "3.5.1" itertools = "0.13.0" simple_logger = "5.0" -minifb = "0.25.0" +minifb = "0.27.0" rand = "0.8.5" -wav = "1.0" + [profile.dev] # otherwise many code is too slow diff --git a/benches/beat_detection_bench.rs b/benches/beat_detection_bench.rs index e5ccba1..a89370e 100644 --- a/benches/beat_detection_bench.rs +++ b/benches/beat_detection_bench.rs @@ -7,7 +7,7 @@ fn criterion_benchmark(c: &mut Criterion) { // to be done. let slice_of_interest = &samples[28000..28000 + 4096]; - let mut detector = BeatDetector::new(header.sampling_rate as f32, true); + let mut detector = BeatDetector::new(header.sample_rate as f32, true); c.bench_function( "simulate beat detection (with lowpass) with 4096 samples per invocation", |b| { @@ -21,7 +21,7 @@ fn criterion_benchmark(c: &mut Criterion) { }, ); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); c.bench_function( "simulate beat detection (no lowpass) with 4096 samples per invocation", |b| { @@ -44,37 +44,30 @@ mod samples { /// Returns the mono samples of the holiday sample (long version) /// together with the sampling rate. - pub fn holiday_long() -> (Vec, wav::Header) { + pub fn holiday_long() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/holiday_lowpassed--long.wav") } } /// Copy and paste from `test_utils.rs`. mod helpers { - use beat_detector::util::{f32_sample_to_i16, stereo_to_mono}; + use beat_detector::util::stereo_to_mono; use itertools::Itertools; - use std::fs::File; use std::path::Path; - use wav::BitDepth; - pub fn read_wav_to_mono>(file: T) -> (Vec, wav::Header) { - let mut file = File::open(file).unwrap(); - let (header, data) = wav::read(&mut file).unwrap(); + pub fn read_wav_to_mono>(file: T) -> (Vec, hound::WavSpec) { + let mut reader = hound::WavReader::open(file).unwrap(); + let header = reader.spec(); - // owning vector with original data in f32 format - let data = match data { - BitDepth::Sixteen(samples) => samples, - BitDepth::ThirtyTwoFloat(samples) => samples - .into_iter() - .map(f32_sample_to_i16) - .map(Result::unwrap) - .collect::>(), - _ => todo!("{data:?} not supported yet"), - }; + // owning vector with original data in i16 format + let data = reader + .samples::() + .map(|s| s.unwrap()) + .collect::>(); - if header.channel_count == 1 { + if header.channels == 1 { (data, header) - } else if header.channel_count == 2 { + } else if header.channels == 2 { let data = data .into_iter() .chunks(2) diff --git a/src/audio_history.rs b/src/audio_history.rs index b16db43..b092aa9 100644 --- a/src/audio_history.rs +++ b/src/audio_history.rs @@ -320,7 +320,7 @@ mod tests { fn audio_history_on_real_data() { let (samples, header) = crate::test_utils::samples::sample1_long(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); assert_eq!( diff --git a/src/beat_detector.rs b/src/beat_detector.rs index 809040e..852655b 100644 --- a/src/beat_detector.rs +++ b/src/beat_detector.rs @@ -193,7 +193,7 @@ mod tests { #[allow(non_snake_case)] fn detect__static__no_lowpass__holiday_single_beat() { let (samples, header) = test_utils::samples::holiday_single_beat(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); assert_eq!( detector.update_and_detect_beat(samples.iter().copied()), Some(EnvelopeInfo { @@ -230,7 +230,7 @@ mod tests { #[allow(non_snake_case)] fn detect__static__lowpass__holiday_single_beat() { let (samples, header) = test_utils::samples::holiday_single_beat(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, true); + let mut detector = BeatDetector::new(header.sample_rate as f32, true); assert_eq!( detector .update_and_detect_beat(samples.iter().copied()) @@ -265,13 +265,13 @@ mod tests { fn detect__dynamic__no_lowpass__holiday_single_beat() { let (samples, header) = test_utils::samples::holiday_single_beat(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); assert_eq!( simulate_dynamic_audio_source(256, &samples, &mut detector), &[829] ); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); assert_eq!( simulate_dynamic_audio_source(2048, &samples, &mut detector), &[829] @@ -283,7 +283,7 @@ mod tests { fn detect__dynamic__no_lowpass__sample1_double_beat() { let (samples, header) = test_utils::samples::sample1_double_beat(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); assert_eq!( simulate_dynamic_audio_source(2048, &samples, &mut detector), &[1309, 8637] @@ -295,7 +295,7 @@ mod tests { fn detect__dynamic__lowpass__sample1_long() { let (samples, header) = test_utils::samples::sample1_long(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, true); + let mut detector = BeatDetector::new(header.sample_rate as f32, true); assert_eq!( simulate_dynamic_audio_source(2048, &samples, &mut detector), &[12939, 93789, 101457, 189595, 270785, 278473] @@ -307,7 +307,7 @@ mod tests { fn detect__dynamic__no_lowpass__holiday_long() { let (samples, header) = test_utils::samples::holiday_long(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, false); + let mut detector = BeatDetector::new(header.sample_rate as f32, false); assert_eq!( simulate_dynamic_audio_source(2048, &samples, &mut detector), &[29077, 31225, 47053, 65811, 83773, 101995, 120137, 138131] @@ -319,7 +319,7 @@ mod tests { fn detect__dynamic__lowpass__holiday_long() { let (samples, header) = test_utils::samples::holiday_long(); - let mut detector = BeatDetector::new(header.sampling_rate as f32, true); + let mut detector = BeatDetector::new(header.sample_rate as f32, true); assert_eq!( simulate_dynamic_audio_source(2048, &samples, &mut detector), &[31335, 47163, 65921, 84223, 102105, 120247, 138559] diff --git a/src/envelope_iterator.rs b/src/envelope_iterator.rs index 1591100..00ed7d2 100644 --- a/src/envelope_iterator.rs +++ b/src/envelope_iterator.rs @@ -336,7 +336,7 @@ mod tests { // sample1: single beat { let (samples, header) = test_utils::samples::sample1_single_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); // Taken from waveform in Audacity. @@ -349,7 +349,7 @@ mod tests { // sample1: double beat { let (samples, header) = test_utils::samples::sample1_double_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); // Taken from waveform in Audacity. @@ -372,7 +372,7 @@ mod tests { // good enough. { let (samples, header) = test_utils::samples::holiday_single_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); // Taken from waveform in Audacity. @@ -387,7 +387,7 @@ mod tests { #[test] fn find_envelopes_sample1_single_beat() { let (samples, header) = test_utils::samples::sample1_single_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let envelopes = EnvelopeIterator::new(&history, None) @@ -400,7 +400,7 @@ mod tests { #[test] fn find_envelopes_sample1_double_beat() { let (samples, header) = test_utils::samples::sample1_double_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let envelopes = EnvelopeIterator::new(&history, None) @@ -419,7 +419,7 @@ mod tests { #[test] fn find_envelopes_holiday_single_beat() { let (samples, header) = test_utils::samples::holiday_single_beat(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let envelopes = EnvelopeIterator::new(&history, None) diff --git a/src/lib.rs b/src/lib.rs index 4d98207..82b1e9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,8 +148,8 @@ mod tests { use crate::test_utils; use std::vec::Vec; - fn _print_sample_stats((samples, header): (Vec, wav::Header)) { - let mut history = AudioHistory::new(header.sampling_rate as f32); + fn _print_sample_stats((samples, header): (Vec, hound::WavSpec)) { + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let all_peaks = MaxMinIterator::new(&history, None).collect::>(); diff --git a/src/max_min_iterator.rs b/src/max_min_iterator.rs index 7b6d97b..c81d2a7 100644 --- a/src/max_min_iterator.rs +++ b/src/max_min_iterator.rs @@ -105,7 +105,7 @@ mod tests { #[test] fn find_maxmin_in_holiday_excerpt() { let (samples, header) = test_utils::samples::holiday_excerpt(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let iter = MaxMinIterator::new(&history, None); diff --git a/src/root_iterator.rs b/src/root_iterator.rs index b506574..75724ca 100644 --- a/src/root_iterator.rs +++ b/src/root_iterator.rs @@ -114,7 +114,7 @@ mod tests { #[test] fn find_roots_in_holiday_excerpt() { let (samples, header) = test_utils::samples::holiday_excerpt(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let iter = RootIterator::new(&history, None); @@ -136,7 +136,7 @@ mod tests { #[test] fn find_roots_in_holiday_excerpt_but_begin_at_specific_index() { let (samples, header) = test_utils::samples::holiday_excerpt(); - let mut history = AudioHistory::new(header.sampling_rate as f32); + let mut history = AudioHistory::new(header.sample_rate as f32); history.update(samples.iter().copied()); let iter = RootIterator::new(&history, Some(929 /* index taken from test above */ + 1)); diff --git a/src/test_utils.rs b/src/test_utils.rs index a90b2bb..5c54f85 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -21,33 +21,26 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -use crate::util::{f32_sample_to_i16, stereo_to_mono}; +use crate::util::stereo_to_mono; use itertools::Itertools; -use std::fs::File; use std::path::Path; use std::vec::Vec; -use wav::BitDepth; /// Reads a WAV file to mono audio. Returns the samples as mono audio. /// Additionally, it returns the sampling rate of the file. -fn read_wav_to_mono>(file: T) -> (Vec, wav::Header) { - let mut file = File::open(file).unwrap(); - let (header, data) = wav::read(&mut file).unwrap(); - - // owning vector with original data in f32 format - let data = match data { - BitDepth::Sixteen(samples) => samples, - BitDepth::ThirtyTwoFloat(samples) => samples - .into_iter() - .map(f32_sample_to_i16) - .map(Result::unwrap) - .collect::>(), - _ => todo!("{data:?} not supported yet"), - }; +fn read_wav_to_mono>(file: T) -> (Vec, hound::WavSpec) { + let mut reader = hound::WavReader::open(file).unwrap(); + let header = reader.spec(); + + // owning vector with original data in i16 format + let data = reader + .samples::() + .map(|s| s.unwrap()) + .collect::>(); - if header.channel_count == 1 { + if header.channels == 1 { (data, header) - } else if header.channel_count == 2 { + } else if header.channels == 2 { let data = data .into_iter() .chunks(2) @@ -75,49 +68,49 @@ pub mod samples { /// Returns the mono samples of the holiday sample (long version) /// together with the sampling rate. - pub fn holiday_long() -> (Vec, wav::Header) { + pub fn holiday_long() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/holiday_lowpassed--long.wav") } /// Returns the mono samples of the holiday sample (excerpt version) /// together with the sampling rate. - pub fn holiday_excerpt() -> (Vec, wav::Header) { + pub fn holiday_excerpt() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/holiday_lowpassed--excerpt.wav") } /// Returns the mono samples of the holiday sample (single-beat version) /// together with the sampling rate. - pub fn holiday_single_beat() -> (Vec, wav::Header) { + pub fn holiday_single_beat() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/holiday_lowpassed--single-beat.wav") } /// Returns the mono samples of the "sample1" sample (long version) /// together with the sampling rate. - pub fn sample1_long() -> (Vec, wav::Header) { + pub fn sample1_long() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/sample1_lowpassed--long.wav") } /// Returns the mono samples of the "sample1" sample (single-beat version) /// together with the sampling rate. - pub fn sample1_single_beat() -> (Vec, wav::Header) { + pub fn sample1_single_beat() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/sample1_lowpassed--single-beat.wav") } /// Returns the mono samples of the "sample1" sample (double-beat version) /// together with the sampling rate. - pub fn sample1_double_beat() -> (Vec, wav::Header) { + pub fn sample1_double_beat() -> (Vec, hound::WavSpec) { read_wav_to_mono("res/sample1_lowpassed--double-beat.wav") } #[test] fn test_samples_are_as_long_as_expected() { - fn to_duration_in_seconds((samples, header): (Vec, wav::Header)) -> f32 { + fn to_duration_in_seconds((samples, header): (Vec, hound::WavSpec)) -> f32 { // Although my code is generic regarding the sampling rate, in my // demo samples, I only use this sampling rate. So let's do a // sanity check. - assert_eq!(header.sampling_rate, 44100); + assert_eq!(header.sample_rate, 44100); - samples.len() as f32 / header.sampling_rate as f32 + samples.len() as f32 / header.sample_rate as f32 } let duration = to_duration_in_seconds(holiday_excerpt()); From 8acb5e5c17675b73cc32c484b00aa58f6a6d2416 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:36:16 +0200 Subject: [PATCH 5/8] clippy --- src/audio_history.rs | 7 ++++--- src/max_min_iterator.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/audio_history.rs b/src/audio_history.rs index b092aa9..d440d8d 100644 --- a/src/audio_history.rs +++ b/src/audio_history.rs @@ -80,9 +80,10 @@ impl Ord for SampleInfo { } /// Accessor over the captured audio history that helps to identify the -/// timestamp of each sample. Users are supposed to add new data in chunks that -/// are less than the buffer size, to slowly fade out old data from the -/// underlying ringbuffer. +/// timestamp of each sample. +/// +/// Users are supposed to add new data in chunks that are less than the buffer +/// size, to slowly fade out old data from the underlying ringbuffer. #[derive(Debug)] pub struct AudioHistory { audio_buffer: ConstGenericRingBuffer, diff --git a/src/max_min_iterator.rs b/src/max_min_iterator.rs index c81d2a7..96f02b1 100644 --- a/src/max_min_iterator.rs +++ b/src/max_min_iterator.rs @@ -50,7 +50,7 @@ impl<'a> MaxMinIterator<'a> { let index = RootIterator::new(buffer, Some(index)) .next() .map(|info| info.index) - .unwrap_or(buffer.data().len() - 1); + .unwrap_or_else(|| buffer.data().len() - 1); Self { buffer, index } } } From b9924669057edd72d102e9d51669f13af31db9b3 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:36:22 +0200 Subject: [PATCH 6/8] examples renamed --- examples/cpal-info.rs | 2 +- examples/cpal-minimal.rs | 57 ------------------- ...al-live-input.rs => live-input-minimal.rs} | 0 ...e-input-gui.rs => live-input-visualize.rs} | 3 +- 4 files changed, 2 insertions(+), 60 deletions(-) delete mode 100644 examples/cpal-minimal.rs rename examples/{minimal-live-input.rs => live-input-minimal.rs} (100%) rename examples/{minimal-live-input-gui.rs => live-input-visualize.rs} (95%) diff --git a/examples/cpal-info.rs b/examples/cpal-info.rs index 1d895eb..eca5a04 100644 --- a/examples/cpal-info.rs +++ b/examples/cpal-info.rs @@ -4,7 +4,7 @@ use cpal::traits::DeviceTrait; mod example_utils; /// Minimal example to explore the structure of the audio input samples we get -/// from cpal. This example does nothing with the beat detection library. +/// from cpal. This binary does nothing with the beat detection library. fn main() { let input_device = example_utils::select_audio_device(); let supported_configs = input_device diff --git a/examples/cpal-minimal.rs b/examples/cpal-minimal.rs deleted file mode 100644 index ee6cce9..0000000 --- a/examples/cpal-minimal.rs +++ /dev/null @@ -1,57 +0,0 @@ -use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use cpal::{BufferSize, StreamConfig}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; - -#[path = "_modules/example_utils.rs"] -mod example_utils; - -/// Minimal example to explore the structure of the audio input samples we get -/// from cpal. This example does nothing with the beat detection library. -fn main() { - let host = cpal::default_host(); - let dev = host.default_input_device().unwrap(); - let x = dev.supported_input_configs().unwrap().collect::>(); - dbg!(x); - let cfg = dev.default_input_config().unwrap(); - let cfg = StreamConfig { - channels: 1, - sample_rate: cfg.sample_rate(), - buffer_size: BufferSize::Default, - }; - - let mut max = i16::MIN; - let mut min = i16::MAX; - - let stream = dev - .build_input_stream( - &cfg, - // cpal is powerful enough to let us specify the type of the - // samples, such as `&[i16]` or `&[f32]`. For i16, the value is - // between `i16::MIN..i16::MAX`, for f32, the value is between - // `-1.0..1.0`. Supported formats are in enum `SampleFormat`. - move |samples: &[i16], _info| { - for &sample in samples { - max = core::cmp::max(max, sample); - min = core::cmp::min(min, sample); - println!("{sample:>6}, max={max:>6}, min={min:>6}"); - } - }, - |e| eprintln!("error: {e:?}"), - None, - ) - .unwrap(); - - let stop_recording = Arc::new(AtomicBool::new(false)); - { - let stop_recording = stop_recording.clone(); - ctrlc::set_handler(move || { - stop_recording.store(true, Ordering::SeqCst); - }) - .unwrap(); - } - - stream.play().unwrap(); - while !stop_recording.load(Ordering::SeqCst) {} - stream.pause().unwrap(); -} diff --git a/examples/minimal-live-input.rs b/examples/live-input-minimal.rs similarity index 100% rename from examples/minimal-live-input.rs rename to examples/live-input-minimal.rs diff --git a/examples/minimal-live-input-gui.rs b/examples/live-input-visualize.rs similarity index 95% rename from examples/minimal-live-input-gui.rs rename to examples/live-input-visualize.rs index b31eab3..5016d11 100644 --- a/examples/minimal-live-input-gui.rs +++ b/examples/live-input-visualize.rs @@ -38,8 +38,7 @@ fn main() { panic!("{}", e); }); - // Limit to max ~60 fps update rate - window.limit_update_rate(Some(std::time::Duration::from_secs_f32(1.0 / 60.0))); + window.set_target_fps(60); let handle = { let rgb_buffer = rgb_buffer.clone(); From 66b6ec703205017b828ee517ef03cf8023b2afb1 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:48:28 +0200 Subject: [PATCH 7/8] fix CI --- Cargo.toml | 8 ++++---- src/util.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a210510..f2cf684 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,13 +53,13 @@ required-features = ["recording"] [dependencies] # +++ NOSTD DEPENDENCIES +++ - -biquad = "0.4" # lowpass filter +biquad = { version = "0.4", default-features = false } # lowpass filter +libm = { version = "0.2.8", default-features = false } log = { version = "0.4", default-features = false } -ringbuffer = "0.15.0" +ringbuffer = { version = "0.15.0", default-features = false } # +++ STD DEPENDENCIES +++ -cpal = { version = "0.15", optional = true } +cpal = { version = "0.15", default-features = false, features = [], optional = true } [dev-dependencies] diff --git a/src/util.rs b/src/util.rs index 6464886..f4b43f4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -19,7 +19,7 @@ pub struct OutOfRangeError(f32); /// range `-i16::MAX..=i16::MAX`. #[inline] pub fn f32_sample_to_i16(val: f32) -> Result { - if val.is_finite() && val.abs() <= 1.0 { + if val.is_finite() && libm::fabsf(val) <= 1.0 { Ok((val * i16::MAX as f32) as i16) } else { Err(OutOfRangeError(val)) From 962a091eb4263c91cae46b670d7060def7183711 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 22 Sep 2024 14:59:29 +0200 Subject: [PATCH 8/8] micro optimization --- src/util.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util.rs b/src/util.rs index f4b43f4..beaf2a4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,11 +4,13 @@ /// Transforms an audio sample in range `i16::MIN..=i16::MAX` to a `f32` in /// range `-1.0..1.0`. #[inline] -pub fn i16_sample_to_f32(mut val: i16) -> f32 { +pub fn i16_sample_to_f32(val: i16) -> f32 { + // If to prevent division result >1.0. if val == i16::MIN { - val += 1; + -1.0 + } else { + val as f32 / i16::MAX as f32 } - val as f32 / i16::MAX as f32 } /// The sample is out of range `-1.0..1.0`.