Skip to content

Commit

Permalink
Prepare for release
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikNatanael committed Jan 18, 2024
1 parent af50af9 commit b5b1216
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 130 deletions.
7 changes: 5 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

## Current changes

## v0.5.0

Large breaking changes in this version

- New Handle system for ergonomically building and interacting with the graph!
- New Handle API for ergonomically building and interacting with the graph!
- A modal thread local interface to interact with knyst, making the Handle system possible, accessed through `knyst_commands()`.
- NodeAddress was replaced by NodeId which is Copy.
- Enabled routing a graph's inputs to its outputs directly, mostly for completeness of the API.
- Fixed bug where input from graph inputs would overwrite other inputs to a node.
- Updated all dependencies to the latest version.
- New `impl_gen` macro for implementing the Gen trait and adding a Handle with input dependent methods and with much less error prone boilerplate.
- Fixed bug in the `Wavetable` which produced artefacts.
- Fixed bug in `Wavetable` which produced artefacts.
- Refactored the codebase to something more logical. Many paths have changed, but importing the prelude should give you most of what you need.

## v0.4.3
Expand Down
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,87 @@

Knyst is a real time audio synthesis framework focusing on flexibility and performance. It's main target use case is desktop multi-threaded environments, but it can also do single threaded and/or non real time synthesis. Embedded platforms are currently not supported, but on the roadmap.

> [!IMPORTANT]
> Knyst is not stable. Knyst's API is still developing and can vary wildly between releases.
## The name

"Knyst" is a Swedish word meaning _very faint sound_. It is normally almost exclusively used in the negative e.g. "Det hörs inte ett knyst" (eng. "You cannot hear a sound"), but I think it's well worth some affirmative use.

# Examples

## Play a sine wave

```rust
// Set up knyst
let mut backend = CpalBackend::new(CpalBackendOptions::default())?;
let _sphere = KnystSphere::start(
&mut backend,
SphereSettings {
num_inputs: 1,
num_outputs: 2,
..Default::default()
},
print_error_handler,
);
// Add a sine wave to the top level graph
let sine_osc_handle = oscillator(WavetableId::cos()).freq(200.);
// Output it to the graph output, which for the top level graph is the
// application output.
graph_output(0, sine_osc_handle);
```

## Implement your own `Gen`

Using the `impl_gen` macro takes care of most of the boiler plate. However, if you need a variable number of inputs or outputs
you have to implement the `Gen` trait yourself.

```rust
struct DummyGen {
counter: Sample,
}
#[impl_gen]
impl DummyGen {
// Having a `new` method enabled generation of a function `dummy_gen() -> Handle<DummyGenHandle>`
pub fn new() -> Self {
Self {
counter: 0.,
}
}

/// The process method, or any method with the `#[process]` attribute is what will be run every block
/// when processing audio. It must not allocate or wait (unless you are doing non-realtime stuff).
///
/// Inputs are extracted from any argument with the type &[Sample]
/// Outputs are extracted from any argument with the type &mut [Sample]
///
/// Additionally, &[Trig] is an input channel of triggers and enables the `inputname_trig()` method on the handle
/// to conveniently schedule a trigger. `SampleRate` gives you the current sample rate and `BlockSize` gives you
/// the block size.
#[process]
fn process(&mut self, counter: &[Sample], output: &mut [Sample]) -> GenState {
for (count, out) in counter.iter().zip(output.iter_mut()) {
self.counter += 1.;
*out = count + self.counter;
}
GenState::Continue
}
/// The init method will be called before adding the `Gen` to a running graph. Here is where you can
/// allocate buffers and initialise state based on sample rate and block size.
fn init(&mut self, _sample_rate: SampleRate, _block_size: BlockSize, _node_id: NodeId) {
self.counter = 0.;
}
}
```

# Features

- good runtime performance
- real time changes to the audio graph via an async compatible interface
- sample accurate node and parameter change scheduling to the graph
- interopability with static Rust DSP libraries e.g. dasp and fundsp (they can be encapsulated in a node and added to the graph)
- graphs can be nodes and changes can be applied to graphs within graphs at any depth
- feedback connections to get a 1 block delayed output of a node
- feedback connections to get a 1 block delayed output of a node to an earlier node in the chain
- any number of inputs/outputs from a node
- allows inner graphs with different block sizes using automatic buffering where necessary
- choose your level of flexibility and optimisation: create a graph with lots of interconnected nodes or hard code it all into one node when you need more performance
Expand Down
127 changes: 0 additions & 127 deletions knyst/examples/filtered_noise.rs

This file was deleted.

5 changes: 5 additions & 0 deletions knyst_macro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# knyst_macro

Macros to improve ergonomics for [Knyst](https://github.com/ErikNatanael/knyst). See the knyst documentation for more information.

Versions follow the main knyst crate.

0 comments on commit b5b1216

Please sign in to comment.