AMEN AUDIO
AMEN AUDIO / MANUALDownload Markdown ↓

PT32-V MIDI map (fw v32)

Switching era (CC 105) rewrites bit depth, compand, dither, interpolator, src-rate reference, cutoff, resonance, filter env, filter position, pre cutoff/res, drive, crush rate and the output HP to that era's rig-verified defaults. It does not touch the live loop brackets, START, the ADSR, LEVEL, PERIOD, TUNE or REGRIND. (Before v31 it did clear the brackets, which threw away a loop the web editor was still drawing.)

Parts 1–4 listen on MIDI channels 1–4 — four parts, like Paula's four hardware channels. Boot eras: ch 1 = PAULA, ch 2 = SP, ch 3 = S950, ch 4 = MPC60. Each part defaults to 4 voices, filling the 16-voice pool. All CCs below are per part (send on that part's channel). The CC matrix is 40 assignable slots per part — this is the default template; any CC can be re-pointed at any target over SysEx.

Sound

CC Parameter Range / zones
102 Sample slot value % 8 → slot 0–7
103 START offset 0–100% of sample (live; grains follow too)
105 Era mode 0 PAULA · 1 SP · 2 S950 · 3 MPC60 · 4 CLEAN (val%5)
106 Bit depth 4 → 16 bits
108 Filter cutoff 40 Hz → 20 kHz, log
116 Drive 0 → 1
113 SRC RATE (crush) 4 kHz → 48 kHz log; 127 = OFF (native)
114 LED filter ≥ 64 = on (Sallen-Key 3090 Hz, Q 0.66 — schematic)

Character (era voicing)

CC Parameter Range
22 PERIOD 0 free-pitch → 1 integer Amiga periods (chord magic); quantised in the crush-rate domain, so drift stays inside the authentic ~8-cent grid
23 TUNE ±100 cents fine tune
24 HP FREQ 5.1 Hz (the A500's own output HP) → 2 kHz, log
25 HP RES 0 → 1 resonance on the output high-pass
26 AMIGA PAN ≥ 64 = voices hard-panned L/R by slot [DEV-04]
27 REGRIND 0 → +24 st, snapped to semitones. The tracker resample-up trick, virtual: source reads as if cleanly resampled 2^(st/12)× faster, played back down by the same factor — pitch/tempo unchanged, playback step rate divided. A playback mode: every era and the grain layer carry it (PAULA runs its pulse train at period × k; the rest ZOH-hold k source samples per step). Low-period crunch without the note dropping; also lands 48 kHz tags in the authentic 113–856 period window so STRICT/PERIOD bite

Filter (fw v22)

CC Parameter Range
108 CUTOFF 40 Hz → 20 kHz, log (the post-engine VCF)
85 RESONANCE 0 → 1
86 FILTER ENV −1 → +1 envelope sweep (SP pair 1·2)
87 FILTER POS 0–42 POST · 43–84 PRE · 85–127 DUAL
88 PRE CUTOFF 0 = TRACK CUTOFF (CC 108 drives the pre filter); else 40 Hz → 20 kHz log
89 PRE RESO 0 → 1, Q up to 20

POST is the classic chain and is bit-identical to v21. PRE moves the filter in front of the era colouration; DUAL runs a resonant pre filter and the normal VCF.

The point of PRE is that both rate-reduction effects (SRC RATE crush and REGRIND) decimate at the source read, so a filter after them only ever hears signal that has already aliased. The pre filter runs at 48 kHz on a clean read and the decimation happens after it — so its resonant peak folds:

image = |hold rate − pre cutoff|, where hold rate = SRC RATE at root pitch, or 48 kHz ÷ 2^(REGRIND/12).

Sweep PRE CUTOFF up past half the hold rate and the image sweeps down. With SRC RATE 8 kHz, a 6 kHz peak lands at 2 kHz; at 7 kHz it lands at 1 kHz. Turn PRE RESO up and that image is the loudest thing in the sound. Works on every era (PAULA folds through the pulse train, keeping its BLEP construction) and on the grain layer, where each grain folds on its own.

Voices (fw v22)

CC Parameter Range
90 MAX VOICES 1 → 16 for this part (default 4)
91 STEAL <64 FADE (~1.5 ms ramp) · ≥64 CUT (immediate)

The pool is 16 voices shared by the four parts, so 4 each is the balanced split. Give a part more when the others are idle — the allocator's reservation floor still protects the rest, and above ~70% mean CPU load new voices are refused rather than overrunning the audio callback. Watch the heartbeat's mean-load byte: PAULA+grain is ~25% per voice, so a part set to 16 will hit the CPU ceiling long before the voice ceiling.

Envelope (ADSR)

CC Parameter Range
109 Attack 0 → 2 s (squared taper)
110 Decay 0.01 → 8 s (squared)
111 Sustain 0 → 1
112 Release 0.005 → 6 s (squared)

Sustain 0 + short decay = one-shot drum behaviour.

Loop (all live on held notes)

CC Parameter Range / zones
104 Loop mode <32 sample-default · 32–63 OFF · 64–95 FWD · 96–127 P-P
117 Loop bracket L +0–100% offset from START (Digitakt-style)
3 Loop bracket R +0–100% offset from START
107 Loop crossfade 0 → 60 ms (forward-loop seam)

Brackets are START-relative: sliding START (CC 103) drags the loop window across the sample with its length preserved, and an owned playhead relocates phase-preserved when the window moves. Sample-embedded loop points (SysEx 0x04) stay absolute. Brackets capture the playhead only once it enters them; a START past the loop plays the tail out. Exact points persist to SD via SysEx 0x04 (the webapp auto-saves ~1.5 s after edits settle).

Three edge cases behave properly as of v31, and all three used to land on the same 32-sample window — a 1.5 kHz squeal rather than a loop:

  • START + bracket L past the end of the sample (START 0.5 with bracket L at 0.6 is an ordinary gesture) slides the window back inside the sample with its length preserved, which is what the START-slide gesture promises.
  • Crossed brackets (R dragged below L) are ordered, so sweeping one past the other shrinks the loop and grows it again.
  • CC 107 crossfade with the loop starting at the beginning of the sample. The seam's partner is normally the material just before loop start; with no pre-roll the fade now uses the material just past loop end instead — the same seam read from the other side. Before v31 the knob was silently dead for the commonest bracket position of all.

Bracket resolution over MIDI is 1/127 of the sample length. The web editor snaps its markers to that grid so the screen shows the loop the box has; the absolute points written to SD by SysEx 0x04 are sample-exact.

Grain layer

CC Parameter Range / zones
20 Grain on/off ≥ 64 = on
21 Sync source 0–42 TRIG · 43–84 CLOCK · 85–127 OFF (free)
115 Division 12 zones: 1/4 1/4T 1/4. 1/8 1/8T 1/8. 1/16 1/16T 1/16. 1/32 1/32T 1/64
118 Gate 0.05 → 4.0 (1.0 = seamless repeat, >1 = cloud)
2 Scan −1 → +1 playhead travel per grain — only does anything with POS MODE = SCAN
14 Shape grain window: 0 short declick → 1 full Hann
15 Position 0 → 100% of the remaining material after START (or active loop)
16 POS MODE 0–42 HOLD · 43–84 SCAN · 85–127 JUMP
17 Spray 0 → 250 ms onset jitter
18 Pitch jitter 0 → 12 st per grain
19 HOLD 0 → 400 ms minimum grain length, applied after GATE / GATE RATIO / SIZE
28 SWING straight → hard 3:1 shuffle, applied per grain PAIR
29 GATE RATIO ×0.25 → ×4 on the offbeat grain's length (centre-detented at ×1)
30 OFFSET −50% → +50% of a grain period; 64 = dead centre
31 Grain size 1 → 400 ms (the OFF-mode grain length)

SWING needs a whole even number of grains per bar, so it applies to 1/4 … 1/64 and all four triplets, and is ignored on the three dotted divisions (where a pair would straddle the barline). RATIO is included in that test: 1/16 × 1.5 = 24 per bar swings, 1/4 × 1.75 = 7 does not. Under TRIG and OFF sync the pairs are anchored to the note-on instead of the bar, so swing works on every division there — including dotted. In OFF sync GATE RATIO scales SIZE, since that is what sets grain length in that mode.

HOLD is a floor on grain LENGTH, not a length. With it up, sweeping GATE down (or DIVISION up) stops shrinking the grains toward the window's own 0.5 ms edges — the period keeps falling while the length does not, so the cloud starts overlapping instead of thinning into a click train. The same gesture goes from stutter to drone. It is capped at four grain periods, which is exactly what GATE already reaches (its own clamp is 0.05 → 4.0), so HOLD cannot push the grain pool anywhere GATE could not already: worst-case per-voice load is unchanged. At musical divisions the cap never bites (1/16 at 120 BPM caps at 500 ms, above the knob's range); at 1/64 it caps around 125 ms, which is still 4× overlap.

Note what HOLD is, acoustically: with POS MODE = HOLD the overlapping grains read the same material at fixed one-period offsets, which is a comb filter. On tonal material that colours it and can null partials outright (four grains one period apart on a steady sine is 90° spacing — a perfect null). SPRAY, PITCH JIT or POS = SCAN break the coherence if you want thickness without the comb.

OFFSET is absolute against the clock in CLOCK sync; under TRIG/OFF (where there is no external grid) turning it nudges the running cloud.

With no loop, grain base = START + (1 − START) × POSITION, read live at spawn. With an active loop, POSITION spans its brackets and grains stay inside that region, including held grains when brackets move.

Pod performance controls (v33)

CC 93 is pitch: 0 = −12 semitones, 64 = unity, 127 = +12 semitones. CC 92 is the fine-short-gate curve: 0.05 + 3.95 × (value / 127)^2. CC 118 keeps its existing linear gate mapping for older controllers. All three act on held notes. Pod bank/control assignments are in README.md. The Pod division knob covers all 12 existing CC 115 zones; no timing divisions were added or removed.

Performance sources (mod matrix, re-routable)

Source Default routing
CC 1 (mod wheel) → grain SHAPE, +1.0
Channel aftertouch → RESONANCE, +0.6
Velocity (unrouted; matrix source)
Keytrack (unrouted; matrix source)
Pitch bend ± bend range (default 2 st)

Note that CC 1 also lands on grain SHAPE through that default slot. It is a modulation on top of CC 14, not a replacement for it — re-route slot 1 and the wheel stops touching SHAPE, while CC 14 keeps working.

Matrix: 8 slots per part, sources {LFO1, LFO2, ENV1, ENV2, wheel, aftertouch, velocity, keytrack} → 31 destinations: {pitch, cutoff, resonance, level, pan, bits, crush, drive, gate, shape, grain pos, loop L/R} plus, as of v22, {swing, gate ratio, grain offset, pre cutoff, pre reso, start, grain size, density, spray, pitch jitter, scan, grain ratio, hp freq, hp res, filter env, xfade, regrind} and, as of v32, {grain hold}. Destinations are append-only — the raw index travels over SysEx 0x07 and the web editor mirrors the list by index. Configured over SysEx (0x07 slot / 0x08 LFO / 0x09 env) — the webapp's MOD MATRIX panel drives it.

Transport / system

Message Effect
MIDI clock (0xF8) DPLL tempo + phase (grain sync, synced LFOs)
Start / Continue / Stop Bar phase reset / resume / free
Song Position Ptr Re-anchors bar phase
Program change Sample slot select on the part's channel
CC 119 = 127 DEV: jump to DFU bootloader (reflash)

SysEx (all under F0 7D 50 54 … F7)

Cmd Function Reply
0x01 Begin sample transfer —
0x02 Sample data chunk (7-bit packed) 0x70 ack every 8
0x03 End transfer (checksummed) 0x71
0x04 Set loop + root on a slot (→ SD) —
0x05 Ping heartbeat
0x06 Slot info + waveform preview 0x72 + 0x73×17
0x07 Mod matrix slot —
0x08 LFO config (shape/rate/sync/swing) —
0x09 Mod env config (attack/decay) —
0x0A Debug: dump part state 0x74
0x0B Debug: dump every active voice 0x75

Unsolicited: 0x76 reports ITCM corruption (PT32_ITCM builds only) — the first mismatching address between ITCM and its QSPI load image.

Heartbeat (1 Hz, unsolicited): fw version, uptime, clock lock, BPM, active voices, output peak, audio-callback load (peak %, mean %) and the count of blocks that overran the budget. Mean load is the number to watch: the Seed renders roughly 4 PAULA+grain voices before the callback overruns, and a sustained overrun wedges the audio DMA. The allocator refuses new voices above ~70% mean rather than letting that happen, so heavy patches drop a note instead of freezing the box.