Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tulip/server/refdocs/amy/_VENDORED_FROM.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Auto-generated by tulip/server/sync_amy_docs.py — do not edit by hand.
Source: amy@009d0b494af2d13f7c49b868b78b96e1cef80753
Source: amy@3c868d5a5bb93db3f7c2bb73b4906dd743016b6d
Files: api.md, arduino.md, billie_jean.md, godot.md, juno_patches.md, midi.md, synth.md, upgrading.md
4 changes: 2 additions & 2 deletions tulip/server/refdocs/amy/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ A note on list parameters: When an argument is a list of parameters, you can in
| `i` | `synth` | `synth` | 0-31 | Define a set of voices for voice management. |
| `ic` | **TODO** | `midi_cc` | C,L,N,X,O,CMD | MIDI Control Code command for this synth (1-16). `C`=MIDI CC (0-127), `L`=log mapping (0/1), `N`=min val, `X`=max val, `O`=offset, `CMD`=wire command to execute, where `%i` is replaced by the channel number and `%v` is replaced by the value after min/max/offset/log mapping. Providing `C` with no further args deletes that CC. `C=255` deletes all CC mappings for the specified synth. See [#524](https://github.com/shorepine/amy/issues/524) |
| `id` | `synth_delay_ms` | `synth_delay` | uint | Delay (in ms) applied to synth note-ons. Gives time for decay of 'stolen' notes. |
| `if` | `synth_flags` | `synth_flags` | uint | Flags for synth creation: 1 = Use MIDI drum note->preset translation; 2 = Drop note-off events. |
| `if` | `synth_flags` | `synth_flags` | uint | Flags for synth creation: 1 = Use MIDI drum note->preset translation; 2 = Drop note-off events; 4 = Invert MIDI pedal sense. |
| `ig` | `cv_trigger` | `cv_trigger` | uint,uint | Configure external CV event triggering: Gate CV, trigger threshold, reset threshold, pitch CV, pitch scale, pitch offset, wire command template, %v gets pitch value. |
| `im` | `grab_midi_notes` | `grab_midi_notes` | 0/1 | Use `amy.send(synth=CHANNEL, grab_midi_notes=0)` to prevent the default direct forwarding of MIDI note-on/offs to synth CHANNEL. |
| `iM` | `note_source_channel` | `note_source_channel` | 1-16 | Used internally to mark events that result from MIDI inputs, meaning they won't get forwarded to MIDI out. |
Expand Down Expand Up @@ -364,7 +364,7 @@ These per-oscillator parameters use [CtrlCoefs](synth.md) notation

Devices built with `-DGAMMA9001` (Tulip, AMYboard, AMY on the web, the CPython `amy` module) carry the Gamma9001 drum sample banks: the full TR-808 bank is baked in as PCM presets 0-18, and 136 more samples (TR-909, Linn 9000, Univox MR-12, Tokyo Synthetics, 80s Power Kit, Percussion) live at presets 256-391, served from a platform-provided blob (linked into the binary on web and CPython; an mmapped `drums` flash partition on ESP32-S3). All of them play directly with `wave=PCM, preset=P`.

Patches **384-390** are ready-made General MIDI drum kits over these banks -- load one on a synth with `synth_flags=3` and GM note numbers trigger the mapped samples:
Patches **384-390** are ready-made General MIDI drum kits over these banks -- load one on a synth to make GM note numbers trigger the mapped samples:

| patch | MIDI PC (bank MSB 3) | kit |
|-------|----------------------|-----|
Expand Down
23 changes: 11 additions & 12 deletions tulip/server/refdocs/amy/synth.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,20 @@ amy.send(synth=0, note=70, vel=0)
amy.send(synth=0, vel=0)
# Once a synth has been initialized and associated with a set of voices, you can use it alone with patch
amy.send(synth=0, patch=13) # Load a different Juno patch, it will remain 4-voice.
# You can also use `patch_string` to directly define a patch using a wire-command string.
amy.send(synth=0, num_voices=3, patch_string=amy.message(wave=amy.TRIANGLE, bp0='0,1,1000,0,1000,0'))
# You can release all the voices/oscs being used by a synth by setting its num_voices to zero.
amy.send(synth=0, num_voices=0)
# Each synth has an overall level (`synth_level`, wire code `iV`), default 1.0,
# applied to all of its oscs' audio output at render time. It's a master volume
# for the synth, independent of any osc amp settings (and the natural way to
# scale a drum-kit synth, whose per-drum oscs each carry their own amp):
amy.send(synth=0, synth_level=0.5)
# As a special case, you can use `synth_flags` to set up a MIDI drum synth
# that will translate GM note events into PCM presets. Load one of the drum kit
# patches (384-390, see the Drum kits section). Drum kits are single-voice:
# the one voice holds a dedicated osc per drum sound, so num_voices must be 1:
amy.send(synth=10, num_voices=1, patch=384, synth_flags=3)
# Patches 258 and 384-390 are General MIDI drum synth kits (see the Drum kits section).
# They include special flags that will translate GM note events into PCM presets.
amy.send(synth=10, patch=384)
amy.send(synth=10, note=38, vel=1) # acoustic snare (GM note numbers)
amy.send(synth=10, patch=389) # hot-swap the synth to the 80s Power Kit
# You can also use `patch_string` to directly define a patch using a wire-command string.
amy.send(synth=11, num_voices=3, patch_string='w7f0Z', synth_flags=3)
```

Note 1: Although `note` can take on real values -- e.g. `note=60.5` for 50 cents above C4 -- the voice management tracks voices by integer note numbers (i.e., midi notes) so it rounds note values to the nearest integer when deciding which note-off goes with which note-on. Note also that note-on events that also set the `preset` parameter (e.g. to select PCM samples) will fold the patch number into the note integer used as the key for note-on, note-off matching.
Expand All @@ -94,7 +92,8 @@ Note 2: note-on events to synths (or their component voices) have a specific beh
```
amy.reset()
amy.send(synth=1, num_voices=2, oscs_per_voice=2)
amy.send(synth=1, osc=1, freq=660)
amy.send(synth=1, osc=0, wave=amy.SINE, freq=440) # These are all defaults, so this line is not needed.
amy.send(synth=1, osc=1, wave=amy.SINE, freq=660) # Non-default freq
amy.send(synth=1, note=60, vel=1)
```
.. will sound two sine tones a fifth apart, even though the two oscs are not chained and we only issued a single note-one.
Expand Down Expand Up @@ -171,7 +170,7 @@ You see we first set up the modulation oscillator (a sine wave at 0.5Hz, with am

```python
amy.send(osc=1, wave=amy.TRIANGLE, freq=5, amp=1)
amy.send(osc=0, wave=amy.PULSE, duty={'const': 0.5, 'mod': 0.25}, freq={'mod': 0.5}, mod_source=1)
amy.send(osc=0, wave=amy.PULSE, duty={'const': 0.5, 'mod': 0.25}, freq={'mod': 0.5}, mod_source=1)m
amy.send(osc=0, note=60, vel=0.5)
```

Expand Down Expand Up @@ -221,7 +220,7 @@ Oscillators will not become audible until a `velocity` over 0 is set for the osc

- Pick the table with `preset`: `pcm_wavetable_base` to `pcm_wavetable_base + pcm_wavetable_samples - 1`
- `duty` controls interpolation position across the 64 waveform cycles within one wavetable preset.
- Internally each cycle is 256 samples; full table length is typically 16384 samples.
- Internally each cycle is 256 samples; full table length is typically 16384 samples (64 complete cycles).
- You can load new wavetables using `load_sample` and use your new preset number. Ensure they are 16,384 samples long. Find more on [waveeditonline.com](http://waveeditonline.com).


Expand Down Expand Up @@ -328,7 +327,7 @@ AMY comes with a bank of drum-like PCM samples baked in, as they are normally ha

### Drum kits

On Gamma9001 devices, patches 384-390 are ready-made General MIDI drum kits: load one on a synth with `synth_flags=3` and GM note numbers (35/36 kick, 38 snare, 42 closed hat, 46 open hat, 49 crash, ...) play the right sound.
On Gamma9001 devices, patches 384-390 are ready-made General MIDI drum kits: load one on a synth and GM note numbers (35/36 kick, 38 snare, 42 closed hat, 46 open hat, 49 crash, ...) play the right sound.

| patch | MIDI PC (bank MSB 3) | kit |
|-------|----------------------|-----|
Expand All @@ -340,7 +339,7 @@ On Gamma9001 devices, patches 384-390 are ready-made General MIDI drum kits: loa
| 389 | 5 | 80s Power Kit (gated reverb) |
| 390 | 6 | Percussion (hand drums / latin) |

Switch kits from code with `amy.send(synth=10, patch=38x)`, or over MIDI with a bank select MSB of 3 (CC0=3) followed by a program change 0-6 on the drum channel. A synth already sitting on a kit patch stays in the kit bank, so a bare program change also switches kits. Channel 10 boots as the TR-808 kit when default synths are on; you can run a second kit polytimbrally on another channel, e.g. `amy.send(synth=11, num_voices=4, patch=390, synth_flags=3)`. Set a kit channel's overall level with a constant amp on the synth, e.g. `amy.send(synth=10, amp=0.5)` — the kits keep their per-drum gains in each note mapping's velocity scale, so the level persists across hits, just like on the melodic patches.
Switch kits from code with `amy.send(synth=10, patch=38x)`, or over MIDI with a bank select MSB of 3 (CC0=3) followed by a program change 0-6 on the drum channel. A synth already sitting on a kit patch stays in the kit bank, so a bare program change also switches kits. Channel 10 boots as the TR-808 kit when default synths are on; you can run a second kit polytimbrally on another channel, e.g. `amy.send(synth=11, patch=390)`. Set a kit channel's overall level with a constant amp on the synth, e.g. `amy.send(synth=10, amp=0.5)` — the kits keep their per-drum gains in each note mapping's velocity scale, so the level persists across hits, just like on the melodic patches.


```python
Expand Down
Loading