Skip to content

Commit

Permalink
Fix crash in envelope processor (#168)
Browse files Browse the repository at this point in the history
* Fix crash in envelope processor

* Improve display in meter example
  • Loading branch information
joe-noel-dev authored Dec 21, 2024
1 parent b25e22d commit a17f6f3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 9 deletions.
15 changes: 12 additions & 3 deletions examples/src/bin/meter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cell::RefCell, rc::Rc, thread, time::Duration};
use std::{cell::RefCell, io::Write, rc::Rc, thread, time::Duration};

use examples::{read_file_into_buffer, AudioCallback};
use rawdio::{prelude::*, Envelope, Gain, Sampler};
Expand Down Expand Up @@ -41,7 +41,16 @@ fn play_file(file_to_play: &str) {
context.process_notifications();

for event in envelope.borrow_mut().take_notifications() {
println!("{}: {}", event.channel_index(), event.peak_level());
if event.channel_index() != 0 {
continue;
}

let peak_level = event.peak_level();
let max_blocks = 50;
let blocks = (peak_level.abs() * max_blocks as f32).round() as usize;
print!("\r{}", "█".repeat(blocks));
print!("{}|", "_".repeat(max_blocks - blocks));
std::io::stdout().flush().unwrap();
}
}

Expand Down Expand Up @@ -72,7 +81,7 @@ fn create_gain(context: &mut dyn Context, channel_count: usize, sample_duration:
fn create_envelope(context: &mut dyn Context, channel_count: usize) -> Rc<RefCell<Envelope>> {
let attack_time = Duration::ZERO;
let release_time = Duration::from_millis(300);
let notification_frequency = 2.0;
let notification_frequency = 20.0;

Envelope::new(
context,
Expand Down
59 changes: 53 additions & 6 deletions src/effects/envelope/envelope_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ impl DspProcessor for EnvelopeProcessor {
let mut position = 0;
let channel_count = context.input_buffer.channel_count();

while position < channel_count {
while position < context.input_buffer.frame_count() {
let frame_count = std::cmp::min(
context.input_buffer.frame_count(),
context.input_buffer.frame_count() - position,
self.notification.samples_until_next_notification(),
);

Expand All @@ -71,14 +71,61 @@ impl DspProcessor for EnvelopeProcessor {
}
}

if self
.notification
.advance(context.input_buffer.frame_count())
{
if self.notification.advance(frame_count) {
self.send_notifications(channel_count);
}

position += frame_count;
}
}
}

#[cfg(test)]
mod tests {
use crossbeam::channel;

use super::*;
use crate::{graph::DspParameters, ProcessContext};

#[test]
fn test_envelope_processor() {
let sample_rate = 48_000;
let channel_count = 1;
let attack_time = Duration::from_millis(0);
let release_time = Duration::from_millis(100);
let notification_frequency = 2.0;
let (tx, rx) = channel::unbounded();

let mut processor = EnvelopeProcessor::new(
sample_rate,
channel_count,
attack_time,
release_time,
notification_frequency,
tx,
);

let frame_count = 45;
let input = OwnedAudioBuffer::new(frame_count, channel_count, sample_rate);
let mut output = OwnedAudioBuffer::new(frame_count, channel_count, sample_rate);

let mut total_frames = 48_000;
let mut offset = 0;
while total_frames > 0 {
let frames = std::cmp::min(frame_count, total_frames);

processor.process_audio(&mut ProcessContext {
input_buffer: &input,
output_buffer: &mut output,
start_time: &Timestamp::from_samples(offset as f64, sample_rate),
parameters: &DspParameters::empty(),
});

total_frames -= frames;
offset += frames;
}

let event_count = rx.len();
assert_eq!(event_count, 2);
}
}

0 comments on commit a17f6f3

Please sign in to comment.