Skip to content

Commit

Permalink
Synthizer: be consistent about SR and BLOCK_SIZE being public and bet…
Browse files Browse the repository at this point in the history
…ter document what they do
  • Loading branch information
ahicks92 committed Mar 8, 2024
1 parent c27d368 commit e8dd632
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 15 deletions.
6 changes: 2 additions & 4 deletions crates/synthizer/examples/write_wave_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ fn main() -> Result<()> {
let sine = syz::nodes::TrigWaveformNode::new_sin(&server, 261f64)?;
server.connect(&sine, 0, &audio_output, 0)?;

// A real app would want to stream data, but we will just use an in-memory buffer since this is only an example.
let sr = server.get_sr() as usize;
// A buffer of stereo data.
let mut buffer = vec![0.0f32; sr * 2];
let mut buffer = vec![0.0f32; syz::SR as usize * 2];

server.synthesize_stereo(&mut buffer[..])?;

Expand All @@ -34,7 +32,7 @@ fn main() -> Result<()> {
// These are the settings for 32-bit float, what we get from Synthizer.
sample_format: hound::SampleFormat::Float,
bits_per_sample: 32,
sample_rate: sr as u32,
sample_rate: syz::SR,
};
let mut writer = hound::WavWriter::create(file_path, spec)?;

Expand Down
20 changes: 18 additions & 2 deletions crates/synthizer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/// at the edges, or upsampling/downsampling as needed. If you need more flexibility, e.g. writing a DAW, then consider
/// other crates; this library is intentionally opinionated and is designed for interactive applications in which
/// circumstance high sample rates offer no gain at the cost of increased CPU load.
pub const SR: u16 = 44100;
pub const SR: u32 = 44100;

/// The maximum channels which the library will ever output.
///
Expand All @@ -19,7 +19,23 @@ pub(crate) const MAX_CHANNELS: usize = 16;
pub(crate) const MAX_OUTPUTS: usize = 16;
pub(crate) const MAX_INPUTS: usize = 16;

pub(crate) const BLOCK_SIZE: usize = 128;
/// The number of samples between server parameter updates
///
/// In order to be efficient, Synthizer only reacts to user-specified changes every `BLOCK_SIZE` frames. We call this a
/// block. Avoiding trying to respond on every sample allows for amortizing things such as graph updates internally.
///
/// When writing code which uses Synthizer to synthesize audio instead of outputting to an audio device, it is useful to
/// know this value. In particular, it is possible to use it to declare arrays (e.g. intermediarte buffers as struct
/// fields) rather than heap allocations and to make simulation updates happen exactly on block boundaries. When
/// synthesizing audio, note that the performance characteristics don't change based on how many samples you ask for.
/// Internally, partial blocks are synthesized as whole blocks and then streamed to the application.
///
/// Changing the value of this constant is *not* considered a breaking change to the public API. It is exposed to allow
/// for things like `[f32; BLOCK_SIZE]`. The guarantee we make here is that it will never be raised such that using
/// such arrays in TLS or statics would cause an issue. Synthizer itself frequently uses TLS to store such arrays. Note
/// that the stack was not mentioned; even today, stereo arrays on the stack are impractically large, especially in
/// debug builds.
pub const BLOCK_SIZE: usize = 128;

/// This convenience alias will always be a `[f64; BLOCK_SIZE]`.
///
Expand Down
2 changes: 1 addition & 1 deletion crates/synthizer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ mod unique_id;
mod worker_pool;

pub use channel_format::*;
pub use config::SR;
pub use config::{BLOCK_SIZE, SR};
pub use db::DbExt;
pub use error::{Error, Result};
pub use loop_spec::*;
Expand Down
10 changes: 2 additions & 8 deletions crates/synthizer/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct ServerInternal {
/// (supercollider, pyo, etc).
///
/// In addition to pushing data to an audio device, it is possible to pull data to your own code as f32 samples at the
/// server's internal sampling rate, [Server::get_sr]. if resampling is required, you must currently handle that
/// server's internal sampling rate, [crate::SR]. if resampling is required, you must currently handle that
/// yourself.
#[derive(Clone)]
pub struct Server {
Expand Down Expand Up @@ -269,15 +269,9 @@ impl Server {
.connect(output_node, output_index, input_node, input_index)
}

/// Get the sampling rate of this server.
///
/// This is the sampling rate which will be used when calling [Server::synthesize_data].
pub fn get_sr(&self) -> u64 {
crate::config::SR as u64
}

/// get Synthizer to synthesize a block of stereo data.
///
///
/// This function will perform synthesis on the current thread, writing to the given output slice in the server's
/// sampling rate. Note that this includes things such as running streaming sources.
///
Expand Down

0 comments on commit e8dd632

Please sign in to comment.