To kick off my time at the Recurse Center I decided to build a modular softsynth in Rust to expand my knowledge of Rust and DSP, as well as build something I and others could use to make music. I’m inspired by an old modular softsynth I used to use called SpiralSynthModular. Unfortunately, this software is dated and no longer updated, and doesn’t compile easily in a modern environment. SpiralSynthModular, an old modular softsynth that left an impression on me The Synth Engine To begin implementing a modular synthesizer, I started by implementing the concept of modules. In the physical world, a module is an electronic circuit with voltage inputs and outputs. Each module does one thing and one thing well. For example, one module could generate a tone whose pitch is determined by an input voltage. Another module could play a sequence of voltages into this “oscillator” to create different tones over time. Yet another module could take the output of the oscillator and filter it to produce sound of different timbre. And another module could prepare the signal for connection with the correct voltage levels to an amplifier and speaker. A real, physical, Doepfer A-100 modular synthesizer. (Image credit) In software, I decided to make each type of synth module its own struct, but with a SynthModule trait common across all kinds of modules, providing a common interface for connecting modules together, executing the signal processing defined inside them, and fetching output buffers from them. pub trait SynthModule { // Required methods fn get_name(&self) -> String; fn get_id(&self) -> String; fn calc(&mut self); fn get_num_inputs(&self) -> u8; fn get_num_outputs(&self) -> u8; fn get_input( &self, input_idx: u8 ) -> Result<Option<(Arc<RwLock<dyn SynthModule + Send + Sync>>, u8)>, ()>; fn get_inputs( &self ) -> Vec<Option<(Arc<RwLock<dyn SynthModule + Send + Sync>>, u8)>>; fn get_output(&self, output_idx: u8) -> Result<&[f32], ()>; fn set_input( &mut self, input_idx: u8, src_modu