Rust Sound Synthesis Library

Overview

Oscen crates.io

logo

Oscen [“oh-sin”] is a library for building modular synthesizers in Rust.

It contains a collection of components frequently used in sound synthesis such as oscillators, filters, and envelope generators. It lets you connect (or patch) the output of one module into the input of another.

Example

use crossbeam::crossbeam_channel::{unbounded, Receiver, Sender};
use nannou::prelude::*;
use nannou_audio as audio;
use nannou_audio::Buffer;
use oscen::filters::Lpf;
use oscen::operators::Modulator;
use oscen::oscillators::{SineOsc, SquareOsc};
use oscen::signal::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    pub stream: audio::Stream<Synth>,
    receiver: Receiver<f32>,
    samples: Vec<f32>,
}

struct Synth {
    sender: Sender<f32>,
    rack: Rack,
}

fn model(app: &App) -> Model {
    let (sender, receiver) = unbounded();
    app.new_window().size(700, 360).view(view).build().unwrap();
    let audio_host = audio::Host::new();

    // Build the Synth.
    // A Rack is a collection of synth modules.
    let mut rack = Rack::new(vec![]);

    // Use a low frequencey sine wave to modulate the frequency of a square wave.
    let sine = SineOsc::new().hz(1).rack(&mut rack);
    let modulator = Modulator::new(sine.tag())
        .base_hz(440)
        .mod_hz(220)
        .mod_idx(1)
        .rack(&mut rack);

    // Create a square wave oscillator and add it the the rack.
    let square = SquareOsc::new().hz(modulator.tag()).rack(&mut rack);

    // Create a low pass filter whose input is the square wave.
    Lpf::new(square.tag()).cutoff_freq(880).rack(&mut rack);

    let synth = Synth { sender, rack };
    let stream = audio_host
        .new_output_stream(synth)
        .render(audio)
        .build()
        .unwrap();

    Model {
        stream,
        receiver,
        samples: vec![],
    }
}

fn audio(synth: &mut Synth, buffer: &mut Buffer) {
    let sample_rate = buffer.sample_rate() as Real;
    for frame in buffer.frames_mut() {
        // The signal method returns the sample of the last synth module in
        // the rack.
        let amp = synth.rack.signal(sample_rate) as f32;

        for channel in frame {
            *channel = amp;
        }
        synth.sender.send(amp).unwrap();
    }
}

fn update(_app: &App, model: &mut Model, _update: Update) {
    let samples: Vec<f32> = model.receiver.try_iter().collect();
    model.samples = samples;
}

fn view(app: &App, model: &Model, frame: Frame) {
    use nannou_apps::scope;
    scope(app, &model.samples, frame);
}
Comments
  • Architecture Idea #1

    Architecture Idea #1

    The biggest problem with our existing architecture is that when we nest waves in structures like PolyWave and VCO we loose access to the specific features of the "inner" waves. For example, if we put a SinWave in a VCO we can't access the hz field in the sine wave. The idea in this PR is twofold:

    • Change the base type of compound waves from Box<dyn Wave + Send> to Arc<Mutex<dyn Wave + Send>>, the Arc allows us to have multiple owners of the inner wave, e.g.
    let wave = SineWave::boxed(440.);
    let polywave = Polywave::boxed(wave);
    

    we can access the inner SineWave from either wave or polywave. The mutex is so we can mutate the inner wave in a thread safe way.

    • Create compound wave types that are parameterized by the types of the underlying waves. For example: SumWave<V, W>. This allows us to "talk" to the inner waves because the compiler knows their type.

    The main benefits of this approach are that:

    1. It allows us to retain most of our existing architecture
    2. It allows users of the library to create new types of waves and controls without changing the library code
    3. It works

    The main negative is that the syntax becomes quite cumbersome. Which hopefully can be alleviated with smart constructors and macros.

    Another idea which I haven't fully explored yet is to use a DAG instead of our nested waves, a la dsp-chain. As far as I can tell the problem here is that our node type has to be an enum containing all of the different types of synth component. Therefore a library user can't extend the code to include new synths, controllers, filters, etc. I could be wrong about this but that is my impression from a cursory glance at dsp-chain.

    Let's all try to think of other potential architechtures!

    opened by jeffreyrosenbluth 1
  • Time

    Time

    Don't merge yet, I want to do a few more things on this branch. But I do think we should use this branch soon. The architecture is better, more rust like and we can define new Oscillators without breaking any code, even in separate modules as opposed to having to update the enum

    opened by jeffreyrosenbluth 1
  • Std osc

    Std osc

    • Create a StdOsc struct instead of various standard oscillators: sine, saw, square, triangle, etc.
    • Redo Modulator so that both timbre remains constant at different frequencies
    opened by jeffreyrosenbluth 0
  • Cannot compile to WASM

    Cannot compile to WASM

       Compiling rustc-serialize v0.3.24
       Compiling libc v0.2.73
       Compiling midir v0.5.0
       Compiling num-iter v0.1.41
    error[E0432]: unresolved imports `backend::MidiInput`, `backend::MidiInputConnection`, `backend::MidiOutput`, `backend::MidiOutputConnection`
     --> /Users/chaosprint/.cargo/registry/src/github.com-1ecc6299db9ec823/midir-0.5.0/src/common.rs:3:5
      |
    3 |     MidiInput as MidiInputImpl,
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `MidiInput` in `backend`
    4 |     MidiInputConnection as MidiInputConnectionImpl,
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `MidiInputConnection` in `backend`
    5 |     MidiOutput as MidiOutputImpl,
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `MidiOutput` in `backend`
    6 |     MidiOutputConnection as MidiOutputConnectionImpl
      |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `MidiOutputConnection` in `backend`
    
       Compiling memoffset v0.5.5
       Compiling num-bigint v0.2.6
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0432`.
    error: could not compile `midir`.
    warning: build failed, waiting for other jobs to finish...
    error[E0046]: not all trait items implemented, missing: `encode`
        --> /Users/chaosprint/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-serialize-0.3.24/src/serialize.rs:1358:1
         |
    853  |     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>;
         |     ---------------------------------------------------------------- `encode` from trait
    ...
    1358 | impl Encodable for path::Path {
         | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `encode` in implementation
    
    error[E0046]: not all trait items implemented, missing: `decode`
        --> /Users/chaosprint/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-serialize-0.3.24/src/serialize.rs:1382:1
         |
    904  |     fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
         |     ----------------------------------------------------------- `decode` from trait
    ...
    1382 | impl Decodable for path::PathBuf {
         | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `decode` in implementation
    
    error: aborting due to 2 previous errors
    
    For more information about this error, try `rustc --explain E0046`.
    error: could not compile `rustc-serialize`.
    
    To learn more, run the command again with --verbose.
    

    Seems that some dependencies do not support WASM. Is it possible to replace it?

    opened by chaosprint 0
  • Fail to build

    Fail to build

    When building the top-level workspace (with a simple cargo build), on Linux, I get the following error:

    error: multiple packages link to native library `alsa`, but a native library can be linked only once
    
    package `alsa-sys v0.1.2`
        ... which is depended on by `alsa v0.2.2`
        ... which is depended on by `midir v0.5.0`
        ... which is depended on by `nannou_apps v0.1.0 (/home/hub/source/oscen/nannou-apps)`
    links to native library `alsa`
    
    package `alsa-sys v0.3.0`
        ... which is depended on by `alsa v0.4.2`
        ... which is depended on by `cpal v0.12.1`
        ... which is depended on by `cpal-apps v0.1.0 (/home/hub/source/oscen/cpal-apps)`
    

    cpal-apps shall downgrade cpal to 0.11. Otherwise midir 0.7.0 should work, but nannou-audio still pull cpal 0.11.

    opened by hfiguiere 0
  • Perfomance

    Perfomance

    • Get rid of ArcMutex
    • Check cpu usage when idle
    • Allocations (pushing onto a vector in graph)
    • most efficient way to share common state and resources such as buffers/wavetables, but could be other large structures as well, without any locks so that's one thing.
    • support control rate signals for things like LFOs that are only calculated once per block instead of every sample
    enhancement 
    opened by jeffreyrosenbluth 1
Releases(clock)
Owner
Reed Rosenbluth
Reed Rosenbluth
DSP real time audio synthesis, effect algorithms and utilities for Rust

synfx-dsp synfx-dsp DSP real time audio synthesis, effect algorithms and utilities for Rust Most of the algorithms and implementations in this library

Weird Constructor 8 Nov 23, 2022
A CLI and library to convert data to sound, and vice versa (dependency-free)

Data to sound A simple crate to convert data to sound, and sound to data. The sound file format is wave (.wav). You can use it as a library or as a co

Awiteb 8 Feb 28, 2023
Procedural engine sound generator controlled via GUI or CLI

enginesound GUI Application used to generate purely synthetic engine sounds with advanced options written in Rust loosely based on this paper Reading

null 198 Dec 30, 2022
A rust binding for the FMOD library

rust-fmod This is a rust binding for FMOD, the library developped by FIRELIGHT TECHNOLOGIES. FMOD website : www.fmod.org You can also find it on crate

Guillaume Gomez 55 Nov 2, 2022
Cross-platform audio I/O library in pure Rust

CPAL - Cross-Platform Audio Library Low-level library for audio input and output in pure Rust. This library currently supports the following: Enumerat

null 1.8k Jan 8, 2023
Rust audio playback library

Audio playback library Rust playback library. Playback is handled by cpal. MP3 decoding is handled by minimp3. WAV decoding is handled by hound. Vorbi

null 1.2k Jan 1, 2023
Rust bindings for the soloud audio engine library

soloud-rs A crossplatform Rust bindings for the soloud audio engine library. Supported formats: wav, mp3, ogg, flac. The library also comes with a spe

Mohammed Alyousef 38 Dec 8, 2022
Symphonia is a pure Rust audio decoding and media demuxing library supporting AAC, FLAC, MP3, MP4, OGG, Vorbis, and WAV.

Pure Rust multimedia format demuxing, tag reading, and audio decoding library

Philip Deljanov 1k Jan 2, 2023
A wav encoding and decoding library in Rust

Hound A wav encoding and decoding library in Rust. Hound can read and write the WAVE audio format, an ubiquitous format for raw, uncompressed audio. T

Ruud van Asseldonk 345 Dec 27, 2022
Small music theory library with MIDI capabilities written in Rust

mumuse Small music theory library with MIDI capabilities written in Rust (wip). Examples Creating notes and transpositions // Declare Note from &str l

Alexis LOUIS 4 Jul 27, 2022
ears is a simple library to play Sounds and Musics in Rust

ears ears is a simple library to play Sounds and Musics in Rust. ears is build on the top of OpenAL and libsndfile. Provides an access to the OpenAL s

Jeremy Letang 56 Dec 1, 2022
A low-overhead and adaptable audio playback library for Rust

Awedio   A low-overhead and adaptable audio playback library for Rust. Examples Play a single sound file: let (mut manager, backend) = awedio::start()

10 Buttons 20 May 25, 2023
A song analysis library for making playlists

bliss-rs is the Rust improvement of bliss, a library used to make playlists by analyzing songs, and computing distance between them.

null 49 Dec 25, 2022
A library for constructing Groth-Sahai proofs using pre-built wrappers

Groth-Sahai Wrappers A Rust library containing wrappers that facilitate the construction of non-interactive witness-indistinguishable and zero-knowled

Jacob White 1 Mar 7, 2022
Flutter crossplatform audio playback library powered by golang beep & oto

Rowdy Pure Rust based Dart/Flutter audio playback library Installation $ flutter pub add rowdy Configuration You'll need the Rust toolchain installed

Kingkor Roy Tirtho 3 Aug 31, 2022
A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without altering any audio information.

OptiVorbis A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without alter

OptiVorbis 27 Jan 3, 2023
TinyAudio is a cross-platform audio output library

TinyAudio TinyAudio is a cross-platform audio output library. Its main goal to provide unified access to a default sound output device of your operati

Dmitry Stepanov 39 Apr 4, 2023
Spotify for the terminal written in Rust 🚀

Spotify TUI A Spotify client for the terminal written in Rust. The terminal in the demo above is using the Rigel theme. Spotify TUI Installation Homeb

Alexander Keliris 14.1k Jan 1, 2023
Easy Api in Rust to play Sounds

ears ears is a simple library to play sounds and music in Rust. Provides an access to the OpenAL spatialization functionality in a simple way. Accepts

Jan Niklas Hasse 82 Jan 1, 2023