microwave 0.35.0

Make xenharmonic music and explore musical tunings.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
Make xenharmonic music and explore musical tunings.

# Resources

- [Changelog]https://github.com/Woyten/tune/releases
- [Scale expressions]https://github.com/Woyten/tune/blob/master/tune-cli/README.md

# Overview

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

- [tune]https://github.com/Woyten/tune – a microtonal library
- [magnetron]https://github.com/Woyten/tune/tree/master/magnetron – a modular synthesizer architecture
- [fluid-xenth]https://github.com/Woyten/tune/tree/master/fluid-xenth – a microtonal soundfont renderer
- [Bevy]https://bevyengine.org – a graphics and game engine

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

- [XĂȘnerie (15-EDO)]https://youtu.be/0PczKDrOdUA
- [Don't Take Five (16-EDO)]https://youtu.be/LLgClI8pyNw
- [The Bedoginning (17-EDO)]https://youtu.be/gaYvK9OBHK0

# Download / Installation

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

- [microwave (Browser)]https://woyten.github.io/microwave - Very experimental!

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

- [microwave 0.35.0 (Linux)]https://github.com/Woyten/tune/releases/download/microwave-0.35.0/microwave-0.35.0-x86_64-unknown-linux-gnu.zip
- [microwave 0.35.0 (Windows)]https://github.com/Woyten/tune/releases/download/microwave-0.35.0/microwave-0.35.0-x86_64-pc-windows-msvc.zip
- [microwave 0.35.0 (macOS)]https://github.com/Woyten/tune/releases/download/microwave-0.35.0/microwave-0.35.0-x86_64-apple-darwin.zip

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](https://bevyengine.org/learn/book/getting-started/setup/).

# 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.

![](https://github.com/Woyten/tune/raw/master/microwave/screenshot.png)

## 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:

- `audio-effect.yml`: Demo showing how to configure an effect-only profile.
- `microwave.yml`: The default profile created at first startup.
- `sympathetic.yml`: Demo showing how to use note-input controlled waveguides to achieve a sympathetic resonance effect.

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:

- Numbers, e.g.
  ```yml
  frequency: 440.0
  ```
- Strings referring to a named template, e.g.
  ```yml
  frequency: WaveformPitch
  ```
- Nested LF source expressions, e.g.
  ```yml
  frequency: { Mul: [ 2.0, WaveformPitch ] }
  ```
  or (using indented style)
  ```yml
  frequency:
    Mul:
      - 2.0
      - WaveformPitch
  ```

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:

- While a key is pressed down, `OffVelocitySet` resolves to 0.0. As a result, `Controller`, as well, resolves to 0.0, regardless of the damper pedal state. Therefore, the waveform remains stable.
- As soon as a key is released, `OffVelocitySet` will resolve to 1.0. Now, `Controller` will interpolate between 1.0 (`map0` = damper released released) and 0.0 (`map1` = damper pedal pressed). As a consequence, the waveform will fade out unless the damper pedal is pressed.

**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 &approx; -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:

- **Pan controller:** From 1 to 0 (left channel) or 0 to 1 (right channel) (&approx; -6dB)
- **Velocity controller:** From 0 to 0.25 (&approx; -12dB)
- **Key velocity:** From 0 to 1

**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

- `name`: The name of the envelope.
- `fadeout`: The amount by which the waveform should fade out. **Important:** If this value is set to constant 0.0 the waveform will never fade out and continue to consume CPU resources, eventually leading to an overload of the audio thread.
- `attack_time`: The linear attack time in seconds.
- `decay_rate`: The exponential decay rate in 1/seconds (inverse half-life) after the attack phase is over.
- `release_time`: The linear release time in seconds. The waveform is considered exhausted as soon as the integral over `fadeout / release_time * dt` reaches 1.0.
- `in_buffer`: The waveform buffer containing the signal that is supposed to be enveloped.
- `out_buffers`: The (stereo) buffers of the main audio pipeline that the enveloped signal is supposed to be written to.
- `out_levels`: The amplitude factor to apply when writing to the main audio pipeline. It makes sense to use `EnvelopeL`/`EnvelopeR` as a value but the user can choose whatever LF source expression they find useful.

### `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:

- **Foreground:** Only activate notes when the given output target is currently active.
- **Background:** Always activate notes when a note event is received.

### Magnetron Synthesizer &ndash; 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.
1. 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.
1. Apply a second-order high-pass filter to the samples stored in buffer 1. The high-pass's resonance frequency rises from 2*F* to 4*F* within 0.1 seconds. Write the result to buffer 7.
1. 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 &ndash; 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:

- `buffer_size`: A fixed delay buffer size of 100000 samples.
- `gain`: An input gain ranging from 0.0 to 0.5. The input gain can be controlled via the F9 key or MIDI CCN 78.
- `rotation_radius`: A rotation radius of 20 cm.
- `speed`: A rotation speed ranging from 1 Hz to 7 Hz. The selected speed is determined by the `Fader` component which will gradually fade between the two values. The movement of the fader is controlled by the the F10 key or MIDI CCN 79 and ranges from -2.0/s to 1.0/s in order to simulate the rotary speaker's deceleration and acceleration.
- `in_buffers`: Buffers 4 and 5 are used as effect inputs.
- `out_buffers`: Buffers 14 and 15 are used as effect outputs.

### 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

- Sound features
  - Built-in modular waveform synthesizer with physical modeling synthesis
    ```bash
    microwave run -p <profile-location> [scale-expression]
    ```
  - Soundfont renderer
  - External synthesizer via MIDI-out
  - Microphone / aux input
  - WAV recording
- Control features
  - Sequencer / piano keyboard via MIDI-in
    ```bash
    microwave run --midi-in <midi-source> [scale-expression]
    ```
  - Lumatone / multichannel input
    ```bash
    # 31-EDO Lumatone preset centered around D4 (62, Layout offset -5)
    microwave ref-note 62 --root 57 --luma-offs 31 --lo-key 0 --up-key 155 --midi-in lumatone steps 1:31:2
    ```
  - Computer keyboard (configurable isomorphic layout)
  - Touch Screen
  - Mouse
  - Channel events (pitch-bend, modulation, pedals, aftertouch, etc.)
  - Polyphonic events (key pressure)
  - LF sources (envelopes, time slices, oscillators, etc.)
- Effects
  - Low-pass
  - 2nd order low-pass
  - High-pass
  - 2nd order high-pass
  - Band-pass
  - Notch filter
  - All-pass
  - Reverb
  - Spatial delay
  - Rotary speaker
- Microtuning features
  - Custom scales
  - SCL imports
  - KBM imports
  - Tuning-dependent automatic isomorphic keyboard layouts
  - MIDI-out retuning via different tuning message types
  - Display frequencies and rational number approximations
  - Customizable second visual keyboard (`--kb2` option)

![](https://github.com/Woyten/tune/raw/master/microwave/screenshot2.png)


# Help

For a complete list of command line options run

```bash
microwave help
```

# License

`microwave` statically links against [OxiSynth](https://crates.io/crates/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*.