Make xenharmonic music and explore musical tunings.

Resources

Overview

microwave is a microtonal modular waveform synthesizer and effects processor with soundfont rendering capabilities based on:

It features a virtual piano UI enabling you to play polyphonic microtonal melodies with your touch screen, computer keyboard, MIDI keyboard or mouse. The UI provides information about pitches and just intervals in custom tuning systems.

The built-in modular synthesis engine does not use any fixed architecture and can be customized to react to all sorts of input events.

Demo

Download / Installation

Option A: Try out the web app to get a very first impression:

Option B: Download a precompiled version of microwave for the supported target architectures:

Option C: Use Cargo to build a fresh binary from scratch for your own target architecture:

```bash

If you are using Linux: Make sure all dev dependencies are installed.

On the CI environment (Ubuntu 20.04) we only need to add two dev dependencies:

sudo apt install libasound2-dev libudev-dev

Make sure pkg-config is installed

sudo apt install pkg-config

cargo install -f microwave ```

microwave should run out-of-the box on a recent (Ubuntu) Linux, Windows or macOS installation. If it doesn't, the problem is probably caused by the Bevy framework. In that case, try following these instructions.

Usage

Hint: Run microwave with parameters from a shell environment (Bash, PowerShell). Double-clicking on the executable will not provide access to all features!

bash microwave run # 12-EDO scale (default) microwave run steps 1:22:2 # 22-EDO scale microwave run scl-file my_scale.scl # imported scale microwave run help # Print help about how to set the parameters to start microwave

This should spawn a window displaying a virtual keyboard. Use your touch screen, computer keyboard or mouse to play melodies on the virtual piano.

Profiles

On startup, microwave tries to load a profile specified by the -p / --profile parameter or the MICROWAVE_PROFILE environment variable. If no such file is found microwave will create a default profile for you.

Example Profiles

microwave is shipped with the following example profiles:

To use a profile, run:

bash microwave -p <profile-name>

Profile Structure

The profile has the following structure:

yaml num_buffers: # Number of main audio buffers audio_buffers: # Audio buffers that are played back by the main audio device waveform_templates: # Named templates to be used by the Magnetron synthesizer waveform_envelopes: # Named envelopes to be used by the Magnetron synthesizer effect_templates: # Named templates to be used by the effect processors stages: # Stages that can create or process audio or MIDI data

LF (Low-Frequency) Sources

Almost all numerical profile parameters can update in real-time. To keep the audio engine performant updates are usually evaluated at a much lower rate than the audio sampling rate. LF sources, therefore, add control and expressiveness to your playing but aren't well suited for spectral sound modulation.

To define an LF source the following data types can be used:

Unfortunately, no detailed LF source documentation is available yet. However, the example profile, microwave's error messages and basic YAML knowledge should enable you to find valid LF source expressions.

waveform_templates Section

The purpose of the waveform_templates section of the profile is to define the most important LF sources s.t. they do not have to be redefined over and over again. The default profile contains some templates that will be explained in the following paragraphs.

WaveformPitch and WaveformPeriod Templates

yml waveform_templates: - name: WaveformPitch value: Mul: - Property: WaveformPitch - Semitones: Controller: kind: PitchBend map0: 0.0 map1: 2.0 - name: WaveformPeriod value: Mul: - Property: WaveformPeriod - Semitones: Controller: kind: PitchBend map0: 0.0 map1: -2.0

The given fragment defines a template with name WaveformPitch or WaveformPeriod, respectively. The output values are calculated by reading the waveform's WaveformPitch/WaveformPeriod property and multiplying it with the pitch-bend wheel's value in whole tones.

Note: Reacting to pitch-bend events is not a hardcoded feature of microwave but a behavior that the user can define by themself!

Fadeout Template

yml waveform_templates: - name: Fadeout value: Controller: kind: Damper map0: { Property: OffVelocitySet } map1: 0.0

The Fadeout template provides a value describing to what extent a waveform is supposed to be faded out. It works in the following way:

Note: Like in the examples before, reacting to the damper pedal is not a hardcoded feature built into microwave but customizable behavior.

EnvelopeL and EnvelopeR Templates

yml waveform_templates: - name: EnvelopeL value: Mul: - Controller: kind: Pan map0: { Property: Velocity } map1: 0.0 - Controller: kind: Volume map0: 0.0 map1: 0.25 - name: EnvelopeR value: Mul: - Controller: kind: Pan map0: 0.0 map1: { Property: Velocity } - Controller: kind: Volume map0: 0.0 map1: 0.25

These templates are designed to provide a reasonable envelope amplitude of ≈ -18dB which is sensitive to the pan controller, the volume controller and the pressed key's velocity. The result is obtained by multiplying the following quantities:

Note: You are not forced to couple envelope amplitudes to those quantities. For example, you could replace the pan controller with the balance controller. Use an LF source that matches your use case.

How to Access the Templates

Just provide the name of the template as a single string argument. Examples:

yml frequency: WaveformPitch fadeout: Fadeout out_levels: [EnvelopeL, EnvelopeR]

waveform_envelopes Section

Every waveform needs to refer to an envelope defined in the waveform_envelopes section of the config file. Envelopes transfer the result of the internal waveform buffers to the main audio pipeline and limit the waveform's lifetime.

An envelope definition typically looks like the following:

yml waveform_envelopes: - name: Piano fadeout: Fadeout attack_time: 0.01 decay_rate: 1.0 release_time: 0.25 in_buffer: 7 out_buffers: [0, 1] out_levels: [EnvelopeL, EnvelopeR]

with

effect_templates Section

This section is completely analogous to the waveform_templates section but it is dedicated to work in combination with the Effect stages documented below. One key difference is that it is not able to access waveform-specific properties like Velocity, KeyPressure, etc.

stages Section / Main Audio Pipeline

The stages section defines the sections that are evaluated sequentially while the main audio thread is running. Not all sections (e.g. MidiOut) contribute to the main audio pipeline but it makes sense to declare them here anyway. Some of the stages, the output targets, are sensitive to note inputs. In that case, the note_input property has to be set. It can have the following values:

Magnetron Synthesizer – Create Your Own Waveforms

To enable the modular magnetron synthesizer engine add the following stage:

yaml stages: - Magnetron: note_input: Foreground num_buffers: # Number of waveform audio buffers waveforms: # Waveform definitions

waveforms Section

The waveforms section defines the waveform render stages to be applied sequentially when a waveform is triggered.

You can mix and match as many stages as you want to create the tailored sound you wish for. The following example config defines a clavinettish sounding waveform that I discovered by accident:

yml waveforms: - name: Funky Clavinet envelope: Piano stages: - Oscillator: kind: Sin frequency: WaveformPitch modulation: None out_buffer: 0 out_level: 440.0 - Oscillator: kind: Triangle frequency: WaveformPitch modulation: ByFrequency mod_buffer: 0 out_buffer: 1 out_level: 1.0 - Filter: kind: HighPass2 resonance: Mul: - WaveformPitch - Fader: movement: 10.0 map0: 2.0 map1: 4.0 quality: 5.0 in_buffer: 1 out_buffer: 7 out_level: 1.0

While rendering the sound the following stages are applied:

  1. Generate a sine wave with the waveform's nominal frequency F and an amplitude of 440. Write this waveform to buffer 0.
  2. Generate a triangle wave with frequency F and an amplitude of 1.0. Modulate the waveform's frequency (in Hz) sample-wise by the amount stored in buffer 0. Write the modulated waveform to buffer 1.
  3. Apply a second-order high-pass filter to the samples stored in buffer 1. The high-pass's resonance frequency rises from 2F to 4F within 0.1 seconds. Write the result to buffer 7.
  4. Wrap an envelope around the signal in buffer 7 and transfer the enveloped signal to buffer 0 and 1 of the main audio pipeline. This is the behavior defined for the Piano envelope in the waveform_envelopes section (see above).

To create your own waveforms use the default config file as a starting point and try editing it by trial-and-error. Let microwave's error messages guide you to find valid configurations.

Fluid Synthesizer

For playback of sampled sounds you need to add a Fluid stage to the stages section.

The following example starts up a Fluid stage which renders the contents of a given soundfont file. The rendered audio will be written to the audio buffers 0 and 1 of the main audio pipeline.

yaml stages: - Fluid: note_input: Foreground soundfont_location: <soundfont-location> out_buffers: [0, 1]

If you like to use compressed sf3 files you need to compile microwave with the sf3 feature enabled. Note that the startup will take significantly longer since the soundfont needs to be decompressed first.

Effects – Create Your Own Effects

To add your own customized effects add a Generic stage. The following config will add a rotary-speaker effect stage to the main audio pipeline.

yaml stages: - Generic: Effect: RotarySpeaker: buffer_size: 100000 gain: Controller: kind: Sound9 map0: 0.0 map1: 0.5 rotation_radius: 20.0 speed: Fader: movement: Controller: kind: Sound10 map0: -2.0 map1: 1.0 map0: 1.0 map1: 7.0 in_buffers: [4, 5] out_buffers: [14, 15]

The given config defines the following properties:

MIDI Out

To enable playback through an external MIDI device add the following stage to the audio pipeline:

yaml stages: - MidiOut: note_input: Foreground out_device: <midi-device> out_channel: 0 num_out_channels: 9 device_id: 127 tuning_program: 0 tuning_method: <tuning-method> The available tuning methods are full, full-rt, octave-1, octave-1-rt, octave-2, octave-2-rt, fine-tuning and pitch-bend.

To retrieve a list of available MIDI devices run:

bash microwave devices

Command Line Parameters

The command-line enables you to set set up sample rates, buffer sizes and other startup parameters. To print a full list of available command-line arguments run:

bash microwave run help

MIDI In

To listen for events originating from an external MIDI device you need to specify the name of the input device:

bash microwave devices # List MIDI devices microwave run --midi-in name-of-my-device microwave run --midi-in "name of my device" # If the device name contains spaces

Live Interactions

You can live-control your waveforms and effects with your mouse pointer, touch pad or any MIDI Control Change messages source.

The following example stage defines a resonating low-pass filter whose resonance frequency can be controlled with a MIDI modulation wheel/lever from 2,000 to 10,000 Hz.

yml Filter: kind: LowPass2 resonance: Controller: kind: Modulation map0: 2000.0 map1: 10000.0 quality: 5.0 in_buffer: 0 out_buffer: 7 out_level: 1.0

If you want to use the mouse's vertical axis for sound control use the Breath controller.

yml resonance: Controller: kind: Breath map0: 2000.0 map1: 10000.0

If you want to use the touchpad for polyphonic sound control use the KeyPressure property.

yml resonance: Linear: input: Property: KeyPressure map0: 2000.0 map1: 10000.0

Note: While Controller values are scaled to 0..1 (or -1..1 in the case of pitch-bend events) and require a range mapping (map0/map1 parameters), Property values can be directly digested. If necessary, they can be To rescaled using Mul or Linear.

Feature List

Help

For a complete list of command line options run

bash microwave help

License

microwave statically links against OxiSynth for soundfont rendering capabilities. This makes the binary executable of microwave a derivative work of OxiSynth. OxiSynth is licensed under the GNU Lesser General Public License, version 2.1.