Struct Patch defines parameters for a subtractive synth voice used by the MusicGen engine. It stores oscillator type, unison/voices, detune, envelopes, filter settings, drive, panning, vibrato and various expressive pitch-bend/scoop parameters and a phase seed.
using System;
using System.Collections.Generic;
namespace Skafinity;
// Patch — the subtractive voice definition every pitched note is rendered through:
// unison oscillators → optional high-pass → resonant low-pass with a cutoff envelope.
//
// Part of the MusicGen engine — see MusicGen.cs.
// ── Synth core: unison osc → optional high-pass → resonant low-pass (cutoff
// envelope) → soft drive → AD/sustain amp env. ──
struct Patch
{
public int Osc; // 0 sine 1 saw 2 square 3 triangle
public int Voices;
public float Detune; // cents
public float Amp;
public float Attack; // sec
public double Decay; // sec (exp time constant)
public float Sustain; // 0..1 (only if Sustained)
public bool Sustained;
public float Cutoff; // Hz low-pass
public float CutEnv; // Hz added at attack, decays with Decay
public float Reso; // SVF damping (lower = more resonance)
public float Highpass; // Hz one-pole high-pass (0 = off)
public float Drive; // tanh
public float Pan; // -1..1
public float Vibrato; // Hz (rate of the pitch wobble)
public float Breath; // 0..1 noise mix (reeds)
// ── Expression (per-note pitch shaping; see Expression/Voicing) ──
public float VibDepth; // vibrato depth as a pitch fraction (0 → legacy 0.005 when Vibrato>0)
public float BendSemis; // pitch offset in semitones at note START, glides to 0 (bend-in / glide); −ve starts below
public float BendTime; // 0..1 fraction of the note over which BendSemis glides to 0
public float ScoopSemis; // height (semitones) of a mid-note bend-up-and-back hump (0 = none)
// THE BEND — the one a listener would name as one, and the only gesture here that moves the
// note AWAY from its pitch rather than easing onto it. Everything above is an approach: it
// starts off-pitch and resolves. This starts ON pitch, pushes up by BendUpSemis, and stays
// there — or comes back, if BendUpHold says how long to sit at the top first. All three times
// are SECONDS, never a fraction of the note, so a bend is the same physical gesture whatever
// the tempo and whatever the note length.
public float BendUpSemis; // semitones bent UP part way through the note (0 = none)
public float BendUpStart; // seconds into the note where the bend begins
public float BendUpTime; // seconds the bend takes to reach pitch (and to come back down)
public float BendUpHold; // seconds held at pitch before releasing; 0 = held to the end
public float PhaseSeed; // oscillator start phase (0..1); 0 = legacy in-phase start. Used to
// decorrelate the two double-tracking takes (see RenderPatch).
}
public sealed partial class MusicGen
{
}