-
Notifications
You must be signed in to change notification settings - Fork 2
Strudel
Excerpt from Strudel website Getting Started With Strudel, you can expressively write dynamic music pieces. It is an official port of the Tidal Cycles pattern language to JavaScript. You don’t need to know JavaScript or Tidal Cycles to make music with Strudel. This interactive tutorial will guide you through the basics of Strudel. The best place to actually make music with Strudel is the Strudel REPL
With it's WebMidi support you can use USBSID-Pico directly from your browser with Strudel.cc
Strudel's WebMidi implementation isn't complete and still under development, see this issue for more information.
To overcome progNum
not being available yet there is a workaround in the examples below.
Strudel has a drawback when it comes to ccv
values. The 0127 midi range is compressed/remapped to 01.
Below are my personal notes and scribbles, if they don't work then they don't work.
Missing progNum
workaround
let progNum = register('progNum',
(prog, chan, pattern) => pattern.onTrigger(
() => WebMidi
.getOutputByName('USBSID-Pico')
.sendProgramChange(prog, chan)
)
)
This function .init()
wil make the bank 0 select only run once
let init = register('init', (pat) => pat.filterWhen((begin) => begin<1))
$: ccn(0x20).ccv(0.0).midi('USBSID-Pico').init() // bank 0
If you want to use the SID voices directly you can use bank 0 and bank 1 for this.
To configure them use the examples below.
// SID1 ~ Voice 1
$: stack(
ccn(0x20).ccv(0.01), // bank 1
ccn(0x1).ccv(0.5), // pwm start
ccn(0x7).ccv(1), // volume
ccn(0x6E).ccv(6), // set frequency cutoff @ 0xB0 (176) = 6 ~ 5,5 (0xFFF max mapped to 127 in steps of 0,03125)
ccn(0x71).ccv(0), // enable filter on voice 1 < bugged
ccn(0x6F).ccv(0.9), // set resonance on filter to 0xB (11) = (0xF max mapped to 127 in steps of 8)
ccn(0x77).ccv(0), // enable lowpas filter
ccn(0x78).ccv(0), // enable bandpass filter
ccn(0x79).ccv(0), // enable highpass filter
ccn(0x49).ccv(0), // attack
ccn(0x4b).ccv(0), // decay
ccn(0x40).ccv(1), // sustain
ccn(0x48).ccv(0.65), // release
ccn(0x15).ccv(0), // noise
ccn(0x16).ccv(0), // pulse
ccn(0x17).ccv(1), // sawtooth
ccn(0x18).ccv(0) // triangle
// progNum(1) // not working yet
).midi('USBSID-Pico').midichan(1).init()
// SID1 ~ Voice 2
$: stack(
ccn(0x20).ccv(0.01), // bank 1
ccn(0x1).ccv(0), // pwm start
ccn(0x7).ccv(1), // volume
ccn(0x6E).ccv(6), // set frequency cutoff @ 0xB0 (176) = 6 ~ 5,5 (0xFFF max mapped to 127 in steps of 0,03125)
ccn(0x71).ccv(0), // enable filter on voice 1 < bugged
ccn(0x6F).ccv(0.9), // set resonance on filter to 0xB (11) = (0xF max mapped to 127 in steps of 8)
ccn(0x77).ccv(0), // enable lowpas filter
ccn(0x78).ccv(0), // enable bandpass filter
ccn(0x79).ccv(1), // enable highpass filter
ccn(0x49).ccv(0), // attack
ccn(0x4b).ccv(0), // decay
ccn(0x40).ccv(0.3), // sustain
ccn(0x48).ccv(0.4), // release
ccn(0x15).ccv(1), // noise
ccn(0x16).ccv(0), // pulse
ccn(0x17).ccv(0), // sawtooth
ccn(0x18).ccv(0) // triangle
// progNum(1) // not working yet
).midi('USBSID-Pico').midichan(2).init()
// SID1 ~ Voice 3
$: stack(
ccn(0x20).ccv(0.01), // bank 1
ccn(0x1).ccv(0.5), // pwm start
ccn(0x7).ccv(1), // volume
ccn(0x6E).ccv(6), // set frequency cutoff @ 0xB0 (176) = 6 ~ 5,5 (0xFFF max mapped to 127 in steps of 0,03125)
ccn(0x71).ccv(127), // enable filter on voice 3 < bugged
ccn(0x6F).ccv(0.9), // set resonance on filter to 0xB (11) = (0xF max mapped to 127 in steps of 8)
ccn(0x77).ccv(0), // enable lowpas filter
ccn(0x78).ccv(0), // enable bandpass filter
ccn(0x79).ccv(0), // enable highpass filter
ccn(0x49).ccv(0), // attack
ccn(0x4b).ccv(0), // decay
ccn(0x40).ccv(1), // sustain
ccn(0x48).ccv(0.65), // release
ccn(0x15).ccv(0), // noise
ccn(0x16).ccv(0), // pulse
ccn(0x17).ccv(1), // sawtooth
ccn(0x18).ccv(0) // triangle
// progNum(1) // not working yet
).midi('USBSID-Pico').midichan(3).init()
// SID2 ~ Voice 1
$: stack(
ccn(0x20).ccv(0.01), // bank 1
ccn(0x1).ccv(0), // pwm start
ccn(0x7).ccv(1), // volume
ccn(0x6E).ccv(6), // set frequency cutoff @ 0xB0 (176) = 6 ~ 5,5 (0xFFF max mapped to 127 in steps of 0,03125)
ccn(0x71).ccv(0), // enable filter on voice 1 < bugged
ccn(0x6F).ccv(0.9), // set resonance on filter to 0xB (11) = (0xF max mapped to 127 in steps of 8)
ccn(0x77).ccv(1), // enable lowpas filter
ccn(0x49).ccv(0), // attack
ccn(0x4b).ccv(0), // decay
ccn(0x40).ccv(0.3), // sustain
ccn(0x48).ccv(0.4), // release
ccn(0x15).ccv(1), // noise
ccn(0x16).ccv(0), // pulse
ccn(0x17).ccv(0), // sawtooth
ccn(0x18).ccv(0) // triangle
// progNum(1) // not working yet
).midi('USBSID-Pico').midichan(4).init()
// SID2 ~ Voice 2
$: stack(
ccn(0x20).ccv(0.01), // bank 1
ccn(0x1).ccv(0.5), // pwm start
ccn(0x7).ccv(1), // volume
ccn(0x6E).ccv(6), // set frequency cutoff @ 0xB0 (176) = 6 ~ 5,5 (0xFFF max mapped to 127 in steps of 0,03125)
ccn(0x71).ccv(0), // enable filter on voice 1 < bugged
ccn(0x6F).ccv(0.9), // set resonance on filter to 0xB (11) = (0xF max mapped to 127 in steps of 8)
ccn(0x77).ccv(0), // enable lowpas filter
ccn(0x78).ccv(0), // enable bandpass filter
ccn(0x79).ccv(0), // enable highpass filter
ccn(0x49).ccv(0), // attack
ccn(0x4b).ccv(0), // decay
ccn(0x40).ccv(1), // sustain
ccn(0x48).ccv(0.65), // release
ccn(0x15).ccv(0), // noise
ccn(0x16).ccv(0), // pulse
ccn(0x17).ccv(1), // sawtooth
ccn(0x18).ccv(0) // triangle
// progNum(1) // not working yet
).midi('USBSID-Pico').midichan(5).init()
These lines should be tested individually and ofcourse set to your personal settings
$: note("c1(1,1) c1(1,1) G(1,1) Eb(1,3) Bb(1,6) G(1,3) Eb(1,3) Bb(1,3)").fast(1).midi('USBSID-Pico').midichan(1) // Imperial march?
$: note("c1(1,6) c1(1,6) c1(1,6) c1(2,6)").fast(1.2).midi('USBSID-Pico').midichan(1) // Bass like rythem
$: note("g5(1,6) g5(1,6) g5(1,6) g5(2,6)").fast(1.2).press().midi('USBSID-Pico').midichan(2) // Hihat like supporting
$: note("g4(1,6) g1(1,6) g(1,6) f1(3,6)").fast(1.2).midi('USBSID-Pico').midichan(1) // note on
$: note("g1(1,4) c1(1,2) c(1,6) e3(2,6)").fast(1.2).midi('USBSID-Pico').midichan(1) // note on
$: note("g1(1,4) c1(1,2) c(1,6) e3(2,6)").fast(1.2).midi('USBSID-Pico').midichan(3) // note on
$: note("e1(2,4) c1(1,6) c3(1,3) e1(3,6)").fast(1.5).midi('USBSID-Pico').midichan(5) // note on
$: note("g5(1,6) g5(1,6) g5(1,6) g5(2,6)").fast(1.5).press().midi('USBSID-Pico').midichan(2) // note on
$: note("g5(1,6) g5(1,6) g5(1,6) g5(2,6)").fast(1.5).press().midi('USBSID-Pico').midichan(4) // note on
// Tune
$: n("[0,7] 4 [2,7] 4")
.scale("C:<major minor>/2")
.fast(1,2)
.midi('USBSID-Pico').midichan(3)
// Weird ass tune
$: chord("<C^7 A7b13 Dm7 G7>*2")
.dict('ireal').layer(
x=>x.struct("[~ x]*2").voicing()
.midi('USBSID-Pico').midichan(1)
,
x=>n("0*4").set(x).mode("root:g2").voicing()
.midi('USBSID-Pico').midichan(5)
)