|
| 1 | +use crate::envelope_iterator::ENVELOPE_MIN_DURATION_MS; |
1 | 2 | use core::cmp::Ordering;
|
2 | 3 | use core::time::Duration;
|
3 | 4 | use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
|
4 | 5 |
|
5 |
| -/// Default buffer size for [`AudioHistory`]. For a typical (and to be expected) |
6 |
| -/// sampling frequency of 44100Hz, this corresponds to 1000ms which is more than |
7 |
| -/// enough to detect beats that are typically at 60Hz, with a period duration |
8 |
| -/// of 20ms (or 20Hz at 50ms). This results in roughly 35kib of stack usage |
9 |
| -/// for the audio buffer. |
10 |
| -/// |
11 |
| -/// TODO I plan to reduce this to 500, 300, or even 200ms to reduce memory usage. |
12 |
| -/// However, during development, a large ubffer size is necessary to tune the |
13 |
| -/// algorithm in a way that it reliably works for data analysis when the full |
14 |
| -/// sample is in memory. If that works reliably, I can test the library in a |
15 |
| -/// "data streaming approach" and discover beats one by one. However, for now, |
16 |
| -/// I keep it very basic and easy. |
17 |
| -pub const DEFAULT_BUFFER_SIZE: usize = 44100; |
| 6 | +const SAFE_MIN_DURATION_MS: usize = (ENVELOPE_MIN_DURATION_MS as f64 * 2.5) as usize; |
| 7 | + |
| 8 | +/// Based on the de-facto default sampling rate of 44100 Hz / 44.1 kHz. |
| 9 | +const DEFAULT_SAMPLES_PER_SECOND: usize = 44100; |
| 10 | +const MS_PER_SECOND: usize = 1000; |
| 11 | + |
| 12 | +/// Default buffer size for [`AudioHistory`]. The size is a trade-off between |
| 13 | +/// memory efficiency and effectiveness in detecting envelops properly. |
| 14 | +pub const DEFAULT_BUFFER_SIZE: usize = |
| 15 | + (SAFE_MIN_DURATION_MS * DEFAULT_SAMPLES_PER_SECOND) / MS_PER_SECOND; |
18 | 16 |
|
19 | 17 | /// Sample info with time context.
|
20 | 18 | #[derive(Copy, Clone, Debug)]
|
@@ -87,6 +85,7 @@ impl AudioHistory {
|
87 | 85 |
|
88 | 86 | /// Update the audio history with fresh samples. The audio samples are
|
89 | 87 | /// expected to be in mono channel, i.e., no stereo interleaving
|
| 88 | + /// TODO: Update consume iterator and consume enum: Interleaved or Mono |
90 | 89 | pub fn update(&mut self, mono_samples: &[f32]) {
|
91 | 90 | if mono_samples.len() >= self.audio_buffer.capacity() {
|
92 | 91 | log::warn!(
|
@@ -183,9 +182,18 @@ impl AudioHistory {
|
183 | 182 | #[cfg(test)]
|
184 | 183 | mod tests {
|
185 | 184 | use super::*;
|
186 |
| - use crate::test_util::{sample_1_test_data, single_beat_test_data}; |
| 185 | + use crate::test_util::{sample_1_test_data}; |
187 | 186 | use std::prelude::v1::Vec;
|
188 | 187 |
|
| 188 | + #[test] |
| 189 | + fn buffer_len_sane() { |
| 190 | + let sampling_rate = 1.0 / DEFAULT_SAMPLES_PER_SECOND as f32; |
| 191 | + let duration = Duration::from_secs_f32(sampling_rate * DEFAULT_BUFFER_SIZE as f32); |
| 192 | + dbg!(duration); |
| 193 | + assert!(duration.as_millis() > 10); |
| 194 | + assert!(duration.as_millis() <= 1000); |
| 195 | + } |
| 196 | + |
189 | 197 | #[test]
|
190 | 198 | fn audio_duration_is_updated_properly() {
|
191 | 199 | let mut hist = AudioHistory::new(2.0);
|
@@ -277,18 +285,37 @@ mod tests {
|
277 | 285 | let mut hist = AudioHistory::new(1.0);
|
278 | 286 |
|
279 | 287 | hist.update(&[0.0]);
|
280 |
| - assert_eq!(hist.index_to_sample_info(0).duration_behind, Duration::from_secs(0)); |
| 288 | + assert_eq!( |
| 289 | + hist.index_to_sample_info(0).duration_behind, |
| 290 | + Duration::from_secs(0) |
| 291 | + ); |
281 | 292 | hist.update(&[0.0]);
|
282 |
| - assert_eq!(hist.index_to_sample_info(0).duration_behind, Duration::from_secs(1)); |
283 |
| - assert_eq!(hist.index_to_sample_info(1).duration_behind, Duration::from_secs(0)); |
284 |
| - |
| 293 | + assert_eq!( |
| 294 | + hist.index_to_sample_info(0).duration_behind, |
| 295 | + Duration::from_secs(1) |
| 296 | + ); |
| 297 | + assert_eq!( |
| 298 | + hist.index_to_sample_info(1).duration_behind, |
| 299 | + Duration::from_secs(0) |
| 300 | + ); |
285 | 301 |
|
286 | 302 | hist.update(&[0.0].repeat(hist.data().capacity() * 2));
|
287 | 303 |
|
288 | 304 | let sample = hist.index_to_sample_info(0);
|
289 |
| - assert_eq!(hist.index_to_sample_info(0).duration_behind, Duration::from_secs_f32((DEFAULT_BUFFER_SIZE - 1) as f32)); |
290 |
| - assert_eq!(hist.index_to_sample_info(DEFAULT_BUFFER_SIZE - 10).duration_behind, Duration::from_secs_f32(9.0)); |
291 |
| - assert_eq!(hist.index_to_sample_info(DEFAULT_BUFFER_SIZE - 1).duration_behind, Duration::from_secs(0)); |
| 305 | + assert_eq!( |
| 306 | + hist.index_to_sample_info(0).duration_behind, |
| 307 | + Duration::from_secs_f32((DEFAULT_BUFFER_SIZE - 1) as f32) |
| 308 | + ); |
| 309 | + assert_eq!( |
| 310 | + hist.index_to_sample_info(DEFAULT_BUFFER_SIZE - 10) |
| 311 | + .duration_behind, |
| 312 | + Duration::from_secs_f32(9.0) |
| 313 | + ); |
| 314 | + assert_eq!( |
| 315 | + hist.index_to_sample_info(DEFAULT_BUFFER_SIZE - 1) |
| 316 | + .duration_behind, |
| 317 | + Duration::from_secs(0) |
| 318 | + ); |
292 | 319 | }
|
293 | 320 |
|
294 | 321 | #[test]
|
|
0 commit comments