Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamiPerttu committed Nov 18, 2024
1 parent 9132588 commit a4f126b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- `BiquadBank` parameters for channel `i` are now set with the syntax `Setting::biquad(...).index(i)`.
- New `Wave` methods `mix` and `mix_channel`.
- New builder notation for setting envelope sampling interval, for example, `lfo(|t| exp(-t)).interval(0.01)`.
- New `Wave` methods `append`, `amplify` and `retain`.

### Version 0.20

Expand Down
4 changes: 2 additions & 2 deletions examples/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,12 @@ impl eframe::App for State {
(pass() | lfo(move |t| (max(800.0, 20000.0 * exp(-t * 6.0)), 3.0)))
>> !dlowpass(Tanh(1.02))
>> mul((1.0, 0.666, 1.0))
>> dlowpass(Tanh(1.0)),
>> dlowpass(Tanh(1.02)),
)),
Filter::FeedbackBiquad => Net::wrap(Box::new(
(mul(2.0)
| lfo(move |t| (xerp11(200.0, 10000.0, sin_hz(0.2, t)), 5.0)))
>> fresonator(Softsign(1.01)),
>> fresonator(Softsign(1.10)),
)),
};
let mut note = Box::new(waveform >> filter >> dcblock());
Expand Down
46 changes: 44 additions & 2 deletions src/wave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ extern crate alloc;
use alloc::sync::Arc;
use alloc::vec::Vec;

/// Multichannel wave in 32-bit float precision. Requires memory allocation via `Vec`.
/// Multichannel wave in 32-bit float precision.
/// Requires memory allocation via `Vec`.
/// Each channel is stored in its own vector of samples.
#[derive(Clone)]
pub struct Wave {
/// Vector of channels. Each channel is stored in its own vector.
/// Vector of channels.
vec: Vec<Vec<f32>>,
/// Sample rate of the wave.
sample_rate: f64,
Expand Down Expand Up @@ -149,6 +151,8 @@ impl Wave {

/// Insert a channel to the wave at channel `channel` from a vector of `samples`.
/// The length of the wave and the number of samples must match.
/// If there are no channels yet, then the length of the wave
/// will become the length of the slice.
pub fn insert_channel(&mut self, channel: usize, samples: &[f32]) {
assert!(self.channels() == 0 || self.len() == samples.len());
assert!(channel <= self.channels());
Expand Down Expand Up @@ -177,6 +181,19 @@ impl Wave {
self.vec.remove(channel)
}

/// Append the contents of the `source` wave to the end of this wave.
/// The number of channels in `source` and this wave must match.
/// Any sample rate differences are ignored.
/// The `source` wave is left unchanged.
pub fn append(&mut self, source: &Wave) {
assert!(self.channels() == source.channels());
let offset = self.length();
self.resize(self.length() + source.length());
for i in 0..self.channels() {
self.mix_channel(i, offset as isize, source.channel(i));
}
}

/// Sample accessor.
#[inline]
pub fn at(&self, channel: usize, index: usize) -> f32 {
Expand Down Expand Up @@ -284,6 +301,22 @@ impl Wave {
self.len = length;
}

/// Retain in this wave only samples in `start .. start + length` and discard the rest.
/// Only the part of the span overlapping the wave is considered.
/// That is, the offset may be negative and the end of the span may lie beyond the end of the wave.
pub fn retain(&mut self, start: isize, length: usize) {
let i0 = max(start, 0) as usize;
let i1 = min(self.length(), max(0, start + length as isize) as usize);
if i0 > 0 {
for channel in 0..self.channels() {
for i in i0..i1 {
self.set(channel, i - i0, self.at(channel, i));
}
}
}
self.resize(i1 - i0);
}

/// Peak amplitude of the wave. An empty wave has zero amplitude.
///
/// ### Example
Expand All @@ -303,6 +336,15 @@ impl Wave {
peak
}

/// Multiply all samples with `amplitude`.
pub fn amplify(&mut self, amplitude: f32) {
for channel in 0..self.channels() {
for i in 0..self.length() {
self.set(channel, i, self.at(channel, i) * amplitude);
}
}
}

/// Scales the wave to the range -1..1. Does nothing if the wave is empty.
///
/// ### Example
Expand Down

0 comments on commit a4f126b

Please sign in to comment.