Every Teensy Audio object from oscillator to SGTL5000, with mixer input numbers and the gains the firmware actually writes. Source: audioinit.h, toern.ino, toern_filter.ino, toern_synths.ino.
| Name | Value | Where |
|---|---|---|
| AUDIO_SAMPLE_RATE_EXACT | 44 117 Hz (Teensy default) | All streams |
| TOERN_AUDIO_MEMORY_BLOCKS | 96 (~24 KB RAM2) | AudioMemory() |
| MIX_BUS_HEADROOM | 1/3 ≈ 0.333 × GAIN 1–4 or 5–8 × ALL | mixer1 / mixer2 every input |
| MIX_END_SAMPLES_GAIN | 0.50 | mixer_end in 0 and 1 |
| MIX_END_SYNTH_GAIN | 0.60 × GAIN SYN × ALL | mixer_end in 2 |
| GAIN_4 | 0.80 | mixersynth_end in 0, 2, 3 |
| GAIN_1 / GAIN_2 / GAIN_3 | 0.4 / 0.8 / 0.4 | Defined, unused |
| Default channel volume | 16 / 16 → amp gain 1.0 | amp1–8, 11, 13, 14 |
AudioMixer4 defaults every unwritten input to 1.0. The firmware only lists gains it actually sets.
One lane per channel. Bitcrush is before the state-variable filter. Voices 3 and 4 have no reverb object — they jump from the filter mixer into mixer1.
| Stage | Object | Gain / range |
|---|---|---|
| Player | sound1–8 (AudioPlayArrayResmp) | setAmplitude(vel/127 × neo-slider) 0–1. Velocity is also sent into the sampler note event. |
| Envelope | envelope1–8 | ADSR from PARAM sliders (0–32). Mute / note-off calls noteOff(). |
| Bitcrush | bitcrusher1–8 | Slider 0 = bypass (16-bit @ sample rate). Slider 32 = 80% of old max ≈ 4-bit / ~9.6 kHz (not 1-bit / 1 kHz). |
| Channel amp | amp1–8 | map(channelVol, 0..16, 0..1). At BITC > 0 the amp is ducked toward 0.6 as crush rises (crushCompGain). |
| Filter | filter1–8 SVF | HCUT: LP path, freq 281 Hz–10 kHz. LCUT > 0: switch mixer to HP, freq 40 Hz–2.5 kHz. RES 0.7–5.0. |
| Filter mixer | filtermixerN | Default in0=1, in1=0, in2=0 (LP). Smooth 32-step crossfade. LCUT uses in2=1. |
| Reverb send | freeverb1,2,5–8 | Room 0–1 from RVRB; damping 0.01–0.42. RVRB 0 bypasses and clears delay tanks. No freeverb on 3 or 4. |
| Wet / dry | freeverbmixerN | in0 wet 0 → 0.54; in3 dry 1.0 → 0.88 (send, not a hard crossfade). Off: wet 0, dry 1. |
| Bank mix | mixer1 (ch1–4), mixer2 (ch5–8) | Every input MIX_BUS_HEADROOM = 1/3 × VOL → GAIN (1–4 or 5–8) × ALL. Sized for ~3 full-level hits per bank at 10/10. |
mixer1 inputs: 0 = ch1 verb mix, 1 = ch2 verb mix, 2 = ch3 dry filter, 3 = ch4 dry filter. mixer2: 0–3 = ch5–8 verb mixes.
Three oscillators × three voices, pan-split into L/R mixers, then collapsed to mono for the shared bitcrush / filter / reverb chain. Leftover waveform11_1/2 objects still exist but are muted (gain 0) so they cannot leak into reverb while stopped.
| Stage | Gain notes |
|---|---|
| Oscillators | Always amplitude 1.0. Mix loudness is the 0.33 pan/volume law, not the leftover waveform11_* objects. |
| Preset osc volumes | Per-instrument volume[osc] 10–100 (BASS 100/65/35, etc.). |
| Amp | amp11 = channelVol 0–16 → 0–1, same crush-comp as samples. |
| Reverb | No freeverbmixer. Wet is stacked on dry at synthmixer11. RVRB 0 zeros in0 and bypasses tanks. |
No reverb (filter page 0 uses CENT in that slot). Two oscillators into a mixer, then a single envelope as VCA.
| Mixer | In | Source | Gain |
|---|---|---|---|
| mixer1 | 0 | ch1 verb mix | 1/3 × GAIN 1–4 × ALL |
| 1 | ch2 verb mix | 1/3 × GAIN 1–4 × ALL | |
| 2 | ch3 filter (no verb) | 1/3 × GAIN 1–4 × ALL | |
| 3 | ch4 filter (no verb) | 1/3 × GAIN 1–4 × ALL | |
| mixer2 | 0 | ch5 verb mix | 1/3 × GAIN 5–8 × ALL |
| 1 | ch6 verb mix | 1/3 × GAIN 5–8 × ALL | |
| 2 | ch7 verb mix | 1/3 × GAIN 5–8 × ALL | |
| 3 | ch8 verb mix | 1/3 × GAIN 5–8 × ALL | |
| mixersynth_end | 0 | ch11 | 0.80 |
| 1 | — | unset (default 1.0, nothing patched) | |
| 2 | ch13 | 0.80 | |
| 3 | ch14 | 0.80 | |
| mixer_end | 0 | mixer1 | 0.50 |
| 1 | mixer2 | 0.50 | |
| 2 | mixersynth_end | 0.60 × GAIN SYN × ALL | |
| 3 | audioInputAmp (monitor / pass-through) | 0 by default; see Input |
Worst-case samples: 3 hot hits on a bank → mixer bus ≈ 1.0 at GAIN 1.0x/1.0x; both banks into mixer_end at 0.50 + 0.50 = 1.0 before synth (0.60) and monitor. VOL → GAIN 0.0x–2.0x scales 1–4, 5–8, SYN, and ALL (1.0x = this table). Four simultaneous full-level hits on one bank can clip — drop a GAIN knob or MIX_BUS_HEADROOM to 0.25 if that is a real pattern.
peakOutput listens to mixer_end for the LED-strip meter. It does not change the mix.
VOL → PREV is 0–50 → mixer gain 0–0.5 (RAM path 25% hotter so it matches SD). Independent of MAIN / LOUT / channelVol.
| Mode | mixer_end in3 | Notes |
|---|---|---|
| Idle play | 0 | Input not in the mix. |
| REC monitor | 0 … (1/3 × 0.50) = 0 … 0.167 | Mic: map MIC 0–63. Line: map L-IN 0–15. Mic + SPKR on → 0 (no feedback). |
| Preview cursor on row 1 | 1.0 | Direct pass-through; codec mic/line gain still applies. |
Codec: inputSelect MIC or LINEIN. micGain 0–63 (0 on line). lineInLevel 0–15.
VOL → 2-CH writes mixer_stereoL/R. Hardware: R is I2S DAC 0, L is DAC 1.
| 2-CH | L in0 main | L in1 prev | L in2 mixer1 | R in0 main | R in1 prev | R in2 mixer2 |
|---|---|---|---|---|---|---|
| OFF (0) | 1 | 1 | 0 | 1 | 1 | 0 |
| M+P (1) | 1 | 0 | 0 | 0 | 1 | 0 |
| L+R (2) | 0 | 0 | 1 | 0 | 0 | 1 |
L+R taps mixer1 (voices 1–4) to left and mixer2 (5–8) to right, and mutes mixer_end on both sides — synths 11/13/14 and input monitor drop out of that mode. Stereo in 3 is always 0. VOL → GAIN 1–4 / 5–8 / ALL still apply because they live on mixer1/2; SYN does not in L+R.
| Codec | Control | Range |
|---|---|---|
| Headphone | sgtl5000.volume(GLOB.vol / 10) | VOL MAIN 1–10 → 0.1–1.0 |
| Line out | lineOutLevel | 13–31 (SGTL: higher = quieter). Default 30. |
| HFC | Graphic EQ treble only | 0 = DAP off. 10–250 step 10, then 256 → treble gain 0 … −1.0. Auto-volume / surround / bass enhance off. |