Skip to content

Instantly share code, notes, and snippets.

@jarmitage
Created April 8, 2026 12:10
Show Gist options
  • Select an option

  • Save jarmitage/a58eb1aaa709f8e91061d6e073536363 to your computer and use it in GitHub Desktop.

Select an option

Save jarmitage/a58eb1aaa709f8e91061d6e073536363 to your computer and use it in GitHub Desktop.
Strudel.cc MIDI CC input mappings to PAM (http://map.audio)
[
{
"channel": 1,
"enabled": true,
"id": "macro_volume_default",
"invert": false,
"mode": "absolute",
"number": 1,
"paramId": "macro_volume",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_pan_default",
"invert": false,
"mode": "absolute",
"number": 2,
"paramId": "macro_pan",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_startPos_default",
"invert": false,
"mode": "absolute",
"number": 3,
"paramId": "macro_startPos",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_endPos_default",
"invert": false,
"mode": "absolute",
"number": 4,
"paramId": "macro_endPos",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_pitchShift_default",
"invert": false,
"mode": "absolute",
"number": 5,
"paramId": "macro_pitchShift",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_filterCutoff_default",
"invert": false,
"mode": "absolute",
"number": 6,
"paramId": "macro_filterCutoff",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_filterQ_default",
"invert": false,
"mode": "absolute",
"number": 7,
"paramId": "macro_filterQ",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
},
{
"channel": 1,
"enabled": true,
"id": "macro_stretch_default",
"invert": false,
"mode": "absolute",
"number": 8,
"paramId": "macro_stretch",
"range": {
"min": 0,
"max": 127
},
"source": "cc"
}
]
// PAM factory default macro CCs:
// ch 1, cc 1..8 =>
// volume, pan, start, end, pitch, cutoff, q, stretch
//
// In PAM, restore the default MIDI mappings first if you have custom mappings saved.
// Clock is separate from the macro map. Enable external MIDI clock sync in PAM.
setcpm(120 / 4)
const PAM_PORT = 'IAC Driver Bus 1' // change to the MIDI output that reaches PAM
const PAM_CHANNEL = 1
midimaps({
pam: {
macro_volume: { ccn: 1, min: -60, max: 12, exp: 3.8 },
macro_pan: { ccn: 2, min: -1, max: 1 },
macro_startPos: { ccn: 3, min: 0, max: 100 },
macro_endPos: { ccn: 4, min: 0, max: 100 },
macro_pitchShift: { ccn: 5, min: -24, max: 24 },
macro_filterCutoff: { ccn: 6, min: 20, max: 20000, exp: 0.25 },
macro_filterQ: { ccn: 7, min: 0.1, max: 14, exp: 0.3 },
// This is the macro knob itself; PAM then routes it to sync/factor internally.
macro_stretch: { ccn: 8, min: 0, max: 1 },
},
})
const pam = (pat) => pat.midichan(PAM_CHANNEL).midimap('pam').midi(PAM_PORT, { isController: true })
const pamClock = (pat) => pat.midi(PAM_PORT, { isController: true })
const pamVar = (pat) => pat.ccn(16).midichan(1).midi(PAM_PORT, { isController: true })
const pamLoop = (pat) => pat.ccn(17).midichan(1).midi(PAM_PORT, { isController: true })
const pamLoopVar = (pat) => pat.ccn(18).midichan(1).midi(PAM_PORT, { isController: true })
const pamPreset = (pat) => pat.midichan(1).midi(PAM_PORT, { isController: true })
p0: pamClock(midicmd('clock*48'))
p1: stack(
pam(sine.segment(16).slow(8).range(-18, 3).as('macro_volume')),
pam(sine.segment(16).slow(6).range(-0.75, 0.75).as('macro_pan')),
pam(saw.segment(16).slow(12).range(0, 35).as('macro_startPos')),
pam(saw.segment(16).slow(12).range(55, 100).as('macro_endPos')),
pam(tri.segment(16).slow(10).range(-7, 7).as('macro_pitchShift')),
pam(sine.segment(16).slow(5).range(200, 12000).as('macro_filterCutoff')),
pam(sine.segment(16).slow(7).range(0.3, 8).as('macro_filterQ')),
pam(slow(8, '<0.25 0.5 0.75 1>').as('macro_stretch'))
)
p2: pamVar(slow(8, '<0 0.25 0.5 0.75 1>'))
p3: pamLoop(slow(8, '<0 1 0 1>'))
p4: pamLoopVar(slow(16, '<0 0.33 0.66 1>'))
p5: pamPreset(progNum('<0 1 2 3>').slow(16))
// Raw CC version for quick debugging:
// $: ccn(1).ccv(sine.segment(16).slow(8)).midichan(1).midi(PAM_PORT, { isController: true })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment