Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamiPerttu committed Nov 1, 2024
1 parent 3e3b3f4 commit aa469b4
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 370 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ let mut sequencer = Sequencer::new(false, 2);
```

Adding new events, their start and stop times as well as fade-in and fade-out envelopes
can be set. The sequencer returns an `ID` that can be used for later edits to the events.
can be set. The sequencer returns an `EventId` that can be used for later edits to the event.

```rust
// Add a new event with start time 1.0 seconds and end time 2.0 seconds.
Expand Down Expand Up @@ -619,7 +619,7 @@ This means that `noise() | noise()` is a stereo noise source, for example.
Pseudorandom phase is an attempt to decorrelate different channels of audio.
It is also used to pick sample points for envelopes, contributing to a "warmer" sound.

To override pseudorandom phase in a noise component (`brown`, `mls`, `noise`, `pink` and `white` opcodes),
To override pseudorandom phase in a noise component (`brown`, `mls`, `mls_bits`, `noise`, `pink` and `white` opcodes),
use the `seed` builder method. For example, `noise().seed(1)`.

### Oscillators
Expand Down
32 changes: 32 additions & 0 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,36 @@ fn phaser_bench(_dummy: usize) -> Wave {
)
}

fn lowpass_bench(_dummy: usize) -> Wave {
Wave::render(
44100.0,
1.0,
&mut ((noise()
| lfo(|t| {
(
xerp11(1000.0, 10000.0, sin_hz(1.0, t)),
xerp11(1.0, 2.0, sin_hz(2.0, t)),
)
}))
>> lowpass().subsample(1)),
)
}

fn lowpass16_bench(_dummy: usize) -> Wave {
Wave::render(
44100.0,
1.0,
&mut ((noise()
| lfo(|t| {
(
xerp11(1000.0, 10000.0, sin_hz(1.0, t)),
xerp11(1.0, 2.0, sin_hz(2.0, t)),
)
}))
>> lowpass().subsample(16)),
)
}

fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("netpass", |b| b.iter(|| netpass_bench(black_box(0))));
c.bench_function("sine", |b| b.iter(|| sine_bench(black_box(0))));
Expand All @@ -100,6 +130,8 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("reverb", |b| b.iter(|| reverb_bench(black_box(0))));
c.bench_function("limiter", |b| b.iter(|| limiter_bench(black_box(0))));
c.bench_function("phaser", |b| b.iter(|| phaser_bench(black_box(0))));
c.bench_function("lowpass", |b| b.iter(|| lowpass_bench(black_box(0))));
c.bench_function("lowpass16", |b| b.iter(|| lowpass16_bench(black_box(0))));
}

criterion_group!(benches, criterion_benchmark);
Expand Down
55 changes: 34 additions & 21 deletions src/combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,81 +179,81 @@ pub struct An<X: AudioNode>(pub X);

impl<X: AudioNode> core::ops::Deref for An<X> {
type Target = X;
#[inline]
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<X: AudioNode> core::ops::DerefMut for An<X> {
#[inline]
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

// We relay some calls preferentially to the underlying AudioNode
// - otherwise the AudioUnit implementation would be picked.
// We relay some calls preferentially to the underlying `AudioNode`
// - otherwise the `AudioUnit` implementation would be picked.
impl<X: AudioNode> An<X> {
#[inline]
#[inline(always)]
pub fn reset(&mut self) {
self.0.reset();
}
#[inline]
#[inline(always)]
pub fn set_sample_rate(&mut self, sample_rate: f64) {
self.0.set_sample_rate(sample_rate);
}
#[inline]
#[inline(always)]
pub fn tick(&mut self, input: &Frame<f32, X::Inputs>) -> Frame<f32, X::Outputs> {
self.0.tick(input)
}
#[inline]
#[inline(always)]
pub fn process(&mut self, size: usize, input: &BufferRef, output: &mut BufferMut) {
self.0.process(size, input, output);
}
#[inline]
#[inline(always)]
pub fn set(&mut self, setting: Setting) {
self.0.set(setting);
}
#[inline]
#[inline(always)]
pub fn route(&mut self, input: &SignalFrame, frequency: f64) -> SignalFrame {
self.0.route(input, frequency)
}
#[inline]
#[inline(always)]
pub fn inputs(&self) -> usize {
self.0.inputs()
}
#[inline]
#[inline(always)]
pub fn outputs(&self) -> usize {
self.0.outputs()
}
#[inline]
#[inline(always)]
pub fn set_hash(&mut self, hash: u64) {
self.0.set_hash(hash);
}
#[inline]
#[inline(always)]
pub fn ping(&mut self, probe: bool, hash: AttoHash) -> AttoHash {
self.0.ping(probe, hash)
}
#[inline]
#[inline(always)]
pub fn get_mono(&mut self) -> f32 {
self.0.get_mono()
}
#[inline]
#[inline(always)]
pub fn get_stereo(&mut self) -> (f32, f32) {
self.0.get_stereo()
}
#[inline]
#[inline(always)]
pub fn filter_mono(&mut self, x: f32) -> f32 {
self.0.filter_mono(x)
}
#[inline]
#[inline(always)]
pub fn filter_stereo(&mut self, x: f32, y: f32) -> (f32, f32) {
self.0.filter_stereo(x, y)
}

/// This builder method sets oscillator initial phase in 0...1,
/// overriding pseudorandom phase. The setting takes effect immediately.
/// overriding pseudorandom phase. The setting takes effect immediately (the node is reset).
///
/// ### Example (Square Wave At 110 Hz With Initial Phase 0.5)
/// ```
Expand All @@ -267,8 +267,8 @@ impl<X: AudioNode> An<X> {
}

/// This builder method sets noise generator seed,
/// overriding pseudorandom phase. The setting takes effect immediately.
/// Works with opcodes `mls`, `noise`, `white`, `pink` and `brown`.
/// overriding pseudorandom phase. The setting takes effect immediately (the node is reset).
/// Works with opcodes `mls`, `mls_bits`, `noise`, `white`, `pink` and `brown`.
pub fn seed(mut self, seed: u64) -> Self {
self.set(Setting::seed(seed).left());
self.reset();
Expand All @@ -277,12 +277,25 @@ impl<X: AudioNode> An<X> {

/// This builder method sets the average interval (in seconds)
/// between samples in envelopes. The setting takes effect immediately.
/// The default interval is 2 ms.
/// Works with opcodes `envelope`, `envelope2`, `envelope3`, `envelope_in`,
/// `lfo`, `lfo2`, `lfo3` and `lfo_in`.
pub fn interval(mut self, time: f32) -> Self {
self.set(Setting::interval(time));
self
}

/// This builder method sets the subsampling `period`
/// between reads of non-audio inputs (frequency, Q and gain) in filters.
/// The non-audio inputs are read every `period` samples.
/// The setting has no effect on filters that do not have non-audio inputs (for example, `bell_hz`).
/// The default period is 1 (that is, no subsampling).
/// Works with opcodes `lowpass`, `highpass`, `bandpass`, `notch`, `peak`,
/// `allpass`, `bell`, `lowshelf` and `highshelf`.
pub fn subsample(mut self, period: u32) -> Self {
self.set(Setting::subsample(period));
self
}
}

impl<X> Neg for An<X>
Expand Down
Loading

0 comments on commit aa469b4

Please sign in to comment.