Last active
January 12, 2021 12:25
-
-
Save petersalomonsen/5b795090ead4f192e7f5ee5dcdd17392 to your computer and use it in GitHub Desktop.
Intro song for the music talk at WebAssembly summit 2020. Also available on spotify / soundcloud, song name is "Hondarribia" ( by Peter Salomonsen ) Go to: https://petersalomonsen.com/webassemblymusic/livecodev2/?gist=5b795090ead4f192e7f5ee5dcdd17392
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* "Hondarribia" - Intro song for the music talk at WebAssembly summit 2020 | |
* | |
* Also available at spotify / soundcloud | |
* https://open.spotify.com/track/72SIjtJwJWggfl2nvHPptE?si=xUh-n4h7QCuR2McQCYie3Q | |
* https://soundcloud.com/psalomo/hondarribia | |
* | |
* Copyright (c) 2019-2020 - Peter Johan Salomonsen - All rights reserved | |
* | |
*/ | |
global.bpm = 120; | |
global.pattern_size_shift = 4; | |
//global.latencyHint="playback"; | |
global.latencyHint=0.03; | |
// global.looptimes = 100; | |
//soloInstrument('bass'); | |
//soloInstrument('kick'); | |
/*soloInstrument('pad1'); | |
soloInstrument('pad2'); | |
soloInstrument('pad3'); | |
soloInstrument('padsvolume');*/ | |
// global.WASM_SYNTH_LOCATION = 'https://gist.githubusercontent.com/petersalomonsen/ea73551e352440d5f470c6af89d7fe7c/raw/b23b32ba55c1c15e972f39724ae164025f569c76/webchipmusic.wasm'; | |
addInstrument('bass', {type: 'note'}); | |
addInstrument('lead', {type: 'note'}); | |
addInstrument('sinelead', {type: 'note'}); | |
addInstrument('kick', {type: 'number'}); | |
addInstrument('snare', {type: 'number'}); | |
addInstrument('hihat', {type: 'number'}); | |
const padVoices = []; | |
for(let n=1;n<11;n++) { | |
padVoices.push('pad'+n); | |
addInstrument('pad'+n, {type: 'note'}); | |
} | |
addInstrumentGroup('pads', padVoices); | |
addInstrument('padsvolume', {type: 'number'}); | |
addInstrument('drivelead', {type: 'note'}); | |
addInstrument('driveleadpitchbend', {type: 'number'}); | |
addInstrument('deepbass', {type: 'note'}); | |
addInstrument('maserlopassfilter', {type: 'number'}); | |
const pianoVoices = []; | |
for(let n=1;n<6;n++) { | |
pianoVoices.push('piano'+n); | |
addInstrument('piano'+n, {type: 'note'}); | |
} | |
addInstrumentGroup('pianos', pianoVoices); | |
const hihatmainpattern = pp(4, [ | |
,30,80,20, | |
,30,80,20, | |
,30,80,20, | |
,30,80,20, | |
].repeat(1)); | |
const kickmainpattern = pp(1, [100,100,100,100].repeat(1)) | |
const padsmainpattern = pp(4, [[as5(2),g3(2),d5(2),g5(2),],,,, | |
,,,, | |
[d5(2),f5(2),,,a5(2)],,,, | |
,,,, | |
[,ds5(2),as5(2),ds3(2),g5(2)],,,, | |
,,,, | |
[g5(2),c6(2),ds5(2),,],,,, | |
,,,], 10); | |
const sineleadmainpattern = pattern(4, [g6(3/4),,,, | |
,,,as6, | |
a6(3/4),,,, | |
f6(1/2),,f6,g6(1/2), | |
,,,, | |
,,d6,, | |
d7(1/2),,f6,c7(1/2), | |
,,as6(1/2),]); | |
const driveleadmainpattern = pp(4, [,,,, | |
g5(1/2),,d5(1/2),, | |
as5(1/2),,a5(3/4),, | |
,,f5(1/2),, | |
,,f5,g5(3/4), | |
,,c5(1),, | |
,,d5(1),, | |
,,,d5, | |
]); | |
const bassmainpattern = pp(4, [g2(2),,,, | |
,,,, | |
d2(2),,,, | |
,,,, | |
ds2(2),,,, | |
,,,, | |
c2(2),, | |
]); | |
const filterfadeinarr = new Array(128).fill(0).map((v, ndx) => ndx > 125 ? 127: ndx + 2); | |
for(var n=0;n<4;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
//hihat: hihatmainpattern, | |
//kick: kickmainpattern, | |
bass: bassmainpattern, | |
"drivelead": driveleadmainpattern, | |
"maserlopassfilter": pp(2, filterfadeinarr.slice(n*16, (n + 1 ) * 16)) | |
},2); | |
} | |
for(var n=0;n<4;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
hihat: hihatmainpattern, | |
kick: kickmainpattern, | |
bass: bassmainpattern, | |
sinelead: pp(4, sineleadmainpattern), | |
"drivelead": driveleadmainpattern, | |
},2); | |
} | |
// playFromHere(); | |
const deepbasspattern = pattern(4, [ | |
g4,g4,g5,g4, | |
,,,d4, | |
,d4,d5,, | |
d4,,,, | |
ds4,ds4,ds5,ds4, | |
,,,c4, | |
,c4,c5,, | |
c4,,c5,, | |
]); | |
const deepbasspatterns = { | |
"snare": pp(4, [ | |
,,,, | |
85,,,30, | |
,30,,, | |
85,,,, | |
,,,, | |
85,,,20, | |
,20,,30, | |
85,,,30, | |
]), | |
"deepbass": pp(4, deepbasspattern), | |
"pads": pp(4, [,,,, | |
[as5(1/4),g5(1/4),d6(1/4),g4(1/4)],,[as5(1/4),g5(1/4),d6(1/4),g4(1/4)],, | |
[a5(1/2),f5(1/2),c6(1/2),d4(1/2)],,,[a5(1/2),c6(1/2),f5(1/2),d4(1/2)], | |
,,[g5(1/2),ds5(1/2),as5(1/2),ds4(1/2)],, | |
,,,, | |
[g5,ds5,ds4,as5],,[g5(1/2),ds4(1/2),ds5(1/2),as5(1/2)],, | |
[g5(1/2),c4(1/2),ds5(1/2),c6(1/2)],,,[g5(1/2),ds5(1/2),c6(1/2),c4(1/2)], | |
,,[f4,f5,a5,c6],], 10), | |
// pads: padsmainpattern, | |
padsvolume: pp(4, [120]), | |
hihat: hihatmainpattern, | |
kick: kickmainpattern | |
}; | |
for(var n=0;n<2;n++) { | |
playPatterns(deepbasspatterns, 2); | |
} | |
for(var n=0;n<2;n++) { | |
playPatterns(Object.assign({},deepbasspatterns, { | |
"sinelead": pp(4, [,,d6,, | |
g6,,as6,, | |
a6(1/2),,,f6, | |
,f6,g6,, | |
,d6(1/2),,, | |
f6(1/2),,,, | |
c6(1/2),,,d6(1/2), | |
,,,]), | |
}), 2); | |
} | |
for(var n=0;n<2;n++) { | |
playPatterns(Object.assign({},deepbasspatterns, { | |
"bass": pp(4, deepbasspattern), | |
"drivelead": pp(4, [,,d5,, | |
g5(1/2),,as5,, | |
a5(1/2),,,f5, | |
,f5,g5,, | |
,d5(3/4),,, | |
f5(3/4),,,, | |
c5(3/4),,,d5(1), | |
,,,]), | |
"sinelead": pp(4, [,,d6,, | |
g6,,as6,, | |
a6(1/2),,,f6, | |
,f6,g6,, | |
,d6(1/2),,, | |
f6(1/2),,,, | |
c6(1/2),,,d6(1/2), | |
,,,]), | |
}), 2); | |
} | |
// playFromHere(); | |
for(var n=0;n<2;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
hihat: hihatmainpattern, | |
kick: kickmainpattern, | |
"bass": pp(4, deepbasspattern), | |
"deepbass": pp(4, deepbasspattern), | |
sinelead: pp(4, sineleadmainpattern), | |
"drivelead": driveleadmainpattern, | |
"snare": pp(4, [ | |
,,,, | |
70,,,, | |
,,,, | |
70,,,, | |
,,,, | |
70,,,, | |
,,,20, | |
70,,,10, | |
]), | |
},2); | |
} | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
hihat: hihatmainpattern, | |
kick: kickmainpattern, | |
"bass": pp(4, deepbasspattern), | |
"deepbass": pp(4, deepbasspattern), | |
sinelead: pp(4, sineleadmainpattern), | |
lead: pp(4, sineleadmainpattern), | |
"drivelead": driveleadmainpattern, | |
"snare": pp(4, [ | |
,,,, | |
70,,,, | |
,,,, | |
70,,,, | |
,,,, | |
70,,,, | |
,,,20, | |
70,,,, | |
]), | |
},2); | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
hihat: hihatmainpattern, | |
kick: kickmainpattern, | |
"bass": pp(4, deepbasspattern), | |
"deepbass": pp(4, deepbasspattern), | |
sinelead: pp(4, sineleadmainpattern), | |
lead: pp(4, sineleadmainpattern), | |
"drivelead": pp(4, [,,,, | |
g5(1/2),,d5(1/2),, | |
as5(1/2),,a5(3/4),, | |
,,f5(1/2),, | |
,,f5,g5(3/4), | |
,,c5,d5,f5 | |
,a5,c5,d6, | |
,f6,g6,a6, | |
]), | |
"snare": pp(4, [ | |
,,,, | |
70,,,, | |
,,,, | |
70,10,20,5, | |
,20,10,30, | |
70,10,30,20, | |
,20,40,20, | |
70,10,20,50, | |
]), | |
},2); | |
// ------------------ filters are coming | |
// playFromHere(); | |
for(var n=0;n<2;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
kick: kickmainpattern, | |
"bass": bassmainpattern, | |
"maserlopassfilter": pp(4, [ | |
127,10,10,127,10, | |
50,127,0,25, | |
5,10,25,35, | |
5,0,120,10, | |
,120,10,0, | |
120,10,,120, | |
,20,127,20, | |
127,20 | |
]), | |
"drivelead": pp(4, [d5(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),, | |
g6(1/2),,g5(1/2),, | |
f6(1/2),,g5,, | |
d6(1/2),,g5(1/2),, | |
ds6(1/2),,g5(1/2),, | |
c6(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),]), | |
},2); | |
} | |
// --------------- filters applied and added snares | |
for(var n=0;n<2;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
kick: kickmainpattern, | |
snare: pp(4, [ | |
,,,, | |
75,,,10, | |
,,,20, | |
65,,,10, | |
,,,, | |
70,,,100, | |
,20,,, | |
70,,,20, | |
]), | |
"bass": bassmainpattern, | |
"maserlopassfilter": pp(4, [ | |
127,10,10,127,10, | |
50,127,0,25, | |
5,10,25,35, | |
5,0,120,10, | |
,120,10,0, | |
120,10,,120, | |
,20,127,20, | |
127,20 | |
]), | |
"sinelead": pp(4, [,,d6,, | |
g6,,d6,, | |
d7,,,, | |
c7,,,, | |
a6,,as6,, | |
,,g6,, | |
f6,,,g6(1/2), | |
,,d6,]), | |
"drivelead": pp(4, [d5(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),, | |
g6(1/2),,g5(1/2),, | |
f6(1/2),,g5,, | |
d6(1/2),,g5(1/2),, | |
ds6(1/2),,g5(1/2),, | |
c6(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),]), | |
},2); | |
} | |
// ------------- now adding the e-pianos | |
for(var n=0;n<3;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
kick: kickmainpattern, | |
snare: pp(4, [ | |
,,,, | |
75,,,10, | |
,,,20, | |
65,,,10, | |
,,,, | |
70,,,100, | |
,20,,, | |
70,,,20, | |
]), | |
"maserlopassfilter": pp(4, [ | |
127,10,10,127,10, | |
50,127,0,25, | |
5,10,25,35, | |
5,0,120,10, | |
,120,10,0, | |
120,10,20,120, | |
,30,127,40, | |
127,40 | |
]), | |
"sinelead": pp(4, [,,d6,, | |
g6,,d6,, | |
d7,,,, | |
c7,,,, | |
a6,,as6,, | |
,,g6,, | |
f6,,,g6(1/2), | |
,,d6,]), | |
"deepbass": pp(4, [,,,, | |
g3(1/2),,,, | |
d3(1/2),,,d3(1/2), | |
,,ds3(1/2),, | |
,,,, | |
ds3(1/2),,,, | |
c3(1/2),,,c3(1/2), | |
,,d3,]), | |
"pianos": pp(4, [,,,, | |
[as5(1/2),g5(1/2),g4(1/2),d5(1/2)],,,, | |
[f5(1/2),a5(1/2),d5(1/2),d4(1/2)],,,[a5(1/2),d5(1/2),f5,d4], | |
,,[g5,ds4,as5,ds5],, | |
,,,, | |
[g5(1/2),as5(1/2),ds5(1/2),ds4(1/2)],,,, | |
[c4(1/2),g5(1/2),c6(1/2),ds5(1/2)],,,[c6(3/4),g5(1/2),ds5(1/2),c4(1/2)], | |
,,,], 5), | |
"drivelead": pp(4, [d5(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),, | |
g6(1/2),,g5(1/2),, | |
f6(1/2),,g5,, | |
d6(1/2),,g5(1/2),, | |
ds6(1/2),,g5(1/2),, | |
c6(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),]), | |
},2); | |
} | |
// --------- loosening the filters | |
const newhihats = pp(4, [ | |
30,15,110,15, | |
].repeat(7)); | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
kick: kickmainpattern, | |
hihat:newhihats, | |
snare: pp(4, [ | |
,,,, | |
75,,,10, | |
,,,20, | |
65,,,10, | |
,,,, | |
70,,,30, | |
,20,,, | |
70,,,20, | |
]), | |
"maserlopassfilter": pp(4, [ | |
127,20,30,127,30, | |
50,127,0,50, | |
60,10,40,70, | |
100,0,120,80, | |
,120,90,0, | |
120,90,100,127, | |
,100,127,90, | |
127 | |
]), | |
"sinelead": pp(4, [,,d6,, | |
g6,,d6,, | |
d7,,,, | |
c7,,,, | |
a6,,as6,, | |
,,g6,, | |
f6,,,g6(1/2), | |
,,d6,]), | |
"deepbass": pp(4, [,,,, | |
g3(1/2),,,, | |
d3(1/2),,,d3(1/2), | |
,,ds3(1/2),, | |
,,,, | |
ds3(1/2),,,, | |
c3(1/2),,,c3(1/2), | |
,,d3,]), | |
"pianos": pp(4, [,,,, | |
[as5(1/2),g5(1/2),g4(1/2),d5(1/2)],,,, | |
[f5(1/2),a5(1/2),d5(1/2),d4(1/2)],,,[a5(1/2),d5(1/2),f5,d4], | |
,,[g5,ds4,as5,ds5],, | |
,,,, | |
[g5(1/2),as5(1/2),ds5(1/2),ds4(1/2)],,,, | |
[c4(1/2),g5(1/2),c6(1/2),ds5(1/2)],,,[c6(3/4),g5(1/2),ds5(1/2),c4(1/2)], | |
,,,], 5), | |
"drivelead": pp(4, [d5(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),, | |
g6(1/2),,g5(1/2),, | |
f6(1/2),,g5,, | |
d6(1/2),,g5(1/2),, | |
ds6(1/2),,g5(1/2),, | |
c6(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),]), | |
},2); | |
// --- no filters | |
for(var n=0; n<4;n++) { | |
playPatterns({ | |
pads: padsmainpattern, | |
padsvolume: pp(4, [100]), | |
kick: kickmainpattern, | |
hihat: newhihats, | |
snare: pp(4, [ | |
,,,, | |
75,,,10, | |
,,,20, | |
65,,,10, | |
,,,, | |
70,,,30, | |
,20,,, | |
70,,,20, | |
]), | |
"maserlopassfilter": pp(4, [ | |
127 | |
]), | |
"sinelead": pp(4, [,,d6,, | |
g6,,d6,, | |
d7,,,, | |
c7,,,, | |
a6,,as6,, | |
,,g6,, | |
f6,,,g6(1/2), | |
,,d6,]), | |
"deepbass": pp(4, [,,,, | |
g3(1/2),,,, | |
d3(1/2),,,d3(1/2), | |
,,ds3(1/2),, | |
,,,, | |
ds3(1/2),,,, | |
c3(1/2),,,c3(1/2), | |
,,d3,]), | |
"pianos": pp(4, [,,,, | |
[as5(1/2),g5(1/2),g4(1/2),d5(1/2)],,,, | |
[f5(1/2),a5(1/2),d5(1/2),d4(1/2)],,,[a5(1/2),d5(1/2),f5,d4], | |
,,[g5,ds4,as5,ds5],, | |
,,,, | |
[g5(1/2),as5(1/2),ds5(1/2),ds4(1/2)],,,, | |
[c4(1/2),g5(1/2),c6(1/2),ds5(1/2)],,,[c6(3/4),g5(1/2),ds5(1/2),c4(1/2)], | |
,,,], 5), | |
"lead": pp(4, [,,,, | |
as5(1/2),,a5(5/4),, | |
,,,, | |
f5(1/2),,g5(1/2),, | |
,,,, | |
d5(1/2),,f5(3/4),, | |
,,g5(1),, | |
,,d5,]), | |
"drivelead": pp(4, [d5(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),, | |
g6(1/2),,g5(1/2),, | |
f6(1/2),,g5,, | |
d6(1/2),,g5(1/2),, | |
ds6(1/2),,g5(1/2),, | |
c6(1/2),,g5(1/2),, | |
d6(1/2),,g5(1/2),]), | |
},2); | |
} | |
// reduce other stuff | |
const withoutpads = { | |
kick: kickmainpattern, | |
hihat: newhihats, | |
snare: pp(4, [ | |
,,,, | |
75,,,10, | |
,,,20, | |
65,,,10, | |
,,,, | |
70,,,30, | |
,20,,, | |
70,,,20, | |
]), | |
"maserlopassfilter": pp(4, [ | |
127 | |
]), | |
"deepbass": pp(4, [,,,, | |
g3(1/2),,,, | |
d3(1/2),,,d3(1/2), | |
,,ds3(1/2),, | |
,,,, | |
ds3(1/2),,,, | |
c3(1/2),,,c3(1/2), | |
,,d3,]), | |
"pianos": pp(4, [,,,, | |
[as5(1/2),g5(1/2),g4(1/2),d5(1/2)],,,, | |
[f5(1/2),a5(1/2),d5(1/2),d4(1/2)],,,[a5(1/2),d5(1/2),f5,d4], | |
,,[g5,ds4,as5,ds5],, | |
,,,, | |
[g5(1/2),as5(1/2),ds5(1/2),ds4(1/2)],,,, | |
[c4(1/2),g5(1/2),c6(1/2),ds5(1/2)],,,[c6(3/4),g5(1/2),ds5(1/2),c4(1/2)], | |
,,,], 5), | |
}; | |
for(var n=0; n<2;n++) { | |
playPatterns(withoutpads,2 ); | |
} | |
playPatterns(Object.assign({}, withoutpads, { | |
"drivelead": pp(4, [,,,, | |
g6(2),,,, | |
,,f6(3/4),, | |
,,f6,g6, | |
,,f6,d6(1/2), | |
,c6(1/2),,as5, | |
,c6,as5,g5(3/4), | |
,,f5,, | |
]), | |
"driveleadpitchbend": pp(4, [ | |
,,,, | |
2,32,64,0 | |
]) | |
}),2 ); | |
playPatterns(Object.assign({}, withoutpads, { | |
"drivelead": pp(4, [g5(2) | |
]), | |
"driveleadpitchbend": pp(4, [ | |
2,32,64,0 | |
]), | |
"sinelead": pp(4, [,,,, | |
,,,, | |
,,f5,, | |
f5(1/2),,f5(1/2),, | |
f5,g5,d6,, | |
g5,,,d5, | |
as5,,g5(1/2),, | |
f5,g5,,]), | |
}),2 ); | |
for(var n=0;n<2;n++) { | |
playPatterns(Object.assign({}, withoutpads, { | |
"sinelead": pp(4, [,,,, | |
,,,, | |
,,f5,, | |
f5(1/2),,f5(1/2),, | |
f5,g5,d6,, | |
g5,,,d5, | |
as5,,g5(1/2),, | |
f5,g5,,]), | |
}),2 ); | |
} | |
playPatterns({ | |
kick: pp(4, [100]), | |
hihat: pp(4, [100]), | |
"maserlopassfilter": pp(4, [ | |
127 | |
]), | |
"sinelead": pp(4, [,,,, | |
,,,, | |
,,f5,, | |
f5(1/2),,f5(1/2),, | |
f5,g5,d6,, | |
g5,,,d5, | |
as5,,g5(1/2),, | |
f5,g5,g6,]), | |
"deepbass": pp(4, [,,,, | |
g3(1/2),,,, | |
d3(1/2),,,d3(1/2), | |
,,ds3(1/2),, | |
,,,, | |
ds3(1/2),,,, | |
c3(1/2),,,c3(2), | |
,,,]), | |
"pianos": pp(4, [,,,, | |
[as5(1/2),g5(1/2),g4(1/2),d5(1/2)],,,, | |
[f5(1/2),a5(1/2),d5(1/2),d4(1/2)],,,[a5(1/2),d5(1/2),f5,d4], | |
,,[g5,ds4,as5,ds5],, | |
,,,, | |
[g5(1/2),as5(1/2),ds5(1/2),ds4(1/2)],,,, | |
[c4(1/2),g5(1/2),c6(1/2),ds5(1/2)],,,[c6(2),g5(2),ds5(2),c4(2)], | |
,,,], 5), | |
},5 ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { EQBand } from "../fx/eqband"; | |
import { Envelope } from '../synth/envelope.class'; | |
import { Snare } from "../instruments/snare.class"; | |
import { SawBass3 } from "../instruments/bass/sawbass3"; | |
import { Eftang } from "../instruments/lead/eftang"; | |
import { StereoSignal } from "../synth/stereosignal.class"; | |
import { Kick } from "../instruments/kick.class"; | |
import { BrassyLead } from "../instruments/lead/brassy"; | |
import { Hihat } from "../instruments/hihat.class"; | |
import { WaveShaper } from '../synth/shaper'; | |
import { createInstrumentArray } from '../common/mixcommon'; | |
import { BandPass } from '../fx/bandpass'; | |
import { Freeverb } from "../fx/freeverb"; | |
import { DelayLine } from "../fx/delayline"; | |
import { SAMPLERATE } from "../environment"; | |
import { BiQuadFilter, FilterType, Q_BUTTERWORTH } from '../synth/biquad'; | |
import { notefreq } from '../synth/note'; | |
import { Noise } from '../synth/noise.class'; | |
import { SineOscillator } from '../synth/sineoscillator.class'; | |
import { SawOscillator } from '../synth/sawoscillator.class'; | |
import { SquareOscillator } from '../synth/squareoscillator.class'; | |
import { TriBandEQ } from "../fx/tribandeq"; | |
import { SubPiano } from "../instruments/piano/subpiano"; | |
import { softclip } from "./globalimports"; | |
export const PATTERN_SIZE_SHIFT: usize = 4; | |
export const BEATS_PER_PATTERN_SHIFT: usize = 2; | |
const tribandeqleft = new TriBandEQ(20,400,6500,19500); | |
const tribandeqright = new TriBandEQ(20,400,6500,19500); | |
const gain: f32 = 0.30; | |
const bass = new SawBass3(); | |
const lead = new Eftang(); | |
const kick = new Kick(); | |
const snare = new Snare(); | |
const hihat = new Hihat(); | |
const masterlopassfilterleft = new BiQuadFilter(); | |
const masterlopassfilterright = new BiQuadFilter(); | |
masterlopassfilterleft.update_coeffecients( | |
FilterType.LowPass, SAMPLERATE, 20000.0, Q_BUTTERWORTH); | |
masterlopassfilterright.update_coeffecients( | |
FilterType.LowPass, SAMPLERATE, 20000.0, Q_BUTTERWORTH); | |
export class DeepBass { | |
private _note: f32; | |
readonly envelope: Envelope = new Envelope(0.01, 0.2, 0.70, 0.2); | |
readonly filterenv: Envelope = new Envelope(0.01, 0.4, 0.0, 0.2); | |
readonly sawoscillator: SawOscillator = new SawOscillator(); | |
readonly sawoscillator2: SawOscillator = new SawOscillator(); | |
readonly squareoscillator: SquareOscillator = new SquareOscillator(); | |
readonly filter: BiQuadFilter = new BiQuadFilter(); | |
readonly hpfilterl: BiQuadFilter = new BiQuadFilter(); | |
readonly hpfilterr: BiQuadFilter = new BiQuadFilter(); | |
readonly lpfilterl: BiQuadFilter = new BiQuadFilter(); | |
readonly lpfilterr: BiQuadFilter = new BiQuadFilter(); | |
readonly shaperl: WaveShaper = new WaveShaper(); | |
readonly shaperr: WaveShaper = new WaveShaper(); | |
readonly signal: StereoSignal = new StereoSignal(); | |
constructor() { | |
this.hpfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH); | |
this.hpfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, 35, Q_BUTTERWORTH); | |
this.shaperl.drive = 0.3; | |
this.shaperr.drive = 0.3; | |
} | |
set note(note: f32) { | |
if(note > 1) { | |
this.sawoscillator.frequency = notefreq(note + 0.1) / 2; | |
this.sawoscillator2.frequency = notefreq(note - 0.1) / 2; | |
this.squareoscillator.frequency = notefreq(note); | |
this.envelope.attack(); | |
this.filterenv.attack(); | |
} else { | |
this.envelope.release(); | |
this.filterenv.release(); | |
} | |
this._note = note; | |
} | |
get note(): f32 { | |
return this._note; | |
} | |
next(): void { | |
let env: f32 = this.envelope.next(); | |
if(env === 0) { | |
this.signal.clear(); | |
return; | |
} | |
// this.signal.clear(); | |
let filterenv = this.filterenv.next(); | |
this.signal.left *= 0.9 * env; // feedback | |
this.signal.right *= 0.9 * env; // feedback | |
this.lpfilterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (150 * filterenv), Q_BUTTERWORTH); | |
this.lpfilterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, 300 + (150 * filterenv), Q_BUTTERWORTH); | |
const squaresignal = this.squareoscillator.next() * 0.5; | |
this.signal.addMonoSignal( | |
this.lpfilterl.process(squaresignal + this.hpfilterl.process(this.sawoscillator.next() * env)), 0.3, 0.3 | |
); | |
this.signal.addMonoSignal( | |
this.lpfilterr.process(squaresignal + this.hpfilterr.process(this.sawoscillator2.next() * env)), 0.3, 0.7 | |
); | |
this.signal.left = this.shaperl.process(this.signal.left); | |
this.signal.right = this.shaperr.process(this.signal.right); | |
} | |
} | |
export class FlatPad { | |
private _note: f32; | |
readonly envelope: Envelope = new Envelope(0.01, 0.1, 1.0, 0.1); | |
readonly filterenvelope: Envelope = new Envelope(0.001, 1.0, 1.0, 0.1); | |
readonly hipassfilterenvelope: Envelope = new Envelope(0.02, 3, 0.2, 2.0); | |
readonly sawoscillator: SawOscillator = new SawOscillator(); | |
readonly sawoscillator2: SawOscillator = new SawOscillator(); | |
readonly sawoscillator3: SawOscillator = new SawOscillator(); | |
readonly sawoscillator4: SawOscillator = new SawOscillator(); | |
readonly sawoscillator5: SawOscillator = new SawOscillator(); | |
readonly lfo: SineOscillator = new SineOscillator(); | |
readonly filterl: BiQuadFilter = new BiQuadFilter(); | |
readonly filterr: BiQuadFilter = new BiQuadFilter(); | |
readonly signal: StereoSignal = new StereoSignal(); | |
set note(note: f32) { | |
if(note > 1) { | |
this.lfo.frequency = 1; | |
this.lfo.position = 0; | |
this.sawoscillator.frequency = notefreq(note); | |
this.sawoscillator2.frequency = notefreq(note + 0.03); | |
this.sawoscillator3.frequency = notefreq(note - 0.03); | |
this.sawoscillator4.frequency = notefreq(note + 0.06); | |
this.sawoscillator5.frequency = notefreq(note - 0.06); | |
this.envelope.attack(); | |
this.filterenvelope.attack(); | |
this.hipassfilterenvelope.attack(); | |
this._note = note; | |
} else { | |
this.envelope.release(); | |
this.filterenvelope.release(); | |
this.hipassfilterenvelope.release(); | |
} | |
} | |
get note(): f32 { | |
return this._note; | |
} | |
next(): void { | |
let env: f32 = this.envelope.next(); | |
if(env === 0) { | |
this.signal.clear(); | |
return; | |
} | |
const lfo: f32 = this.lfo.next(); | |
const note = this.note; | |
if(note<2) { | |
return; | |
} | |
this.sawoscillator2.frequency = notefreq(note + 0.05 + (0.02 * lfo)); | |
this.sawoscillator3.frequency = notefreq(note - 0.05 - (0.02 * lfo)); | |
this.sawoscillator4.frequency = notefreq(note + 0.1 + (0.03 * lfo)); | |
this.sawoscillator5.frequency = notefreq(note - 0.1 - (0.03 * lfo)); | |
let osc: f32 = this.sawoscillator.next(); | |
let osc2: f32 = this.sawoscillator2.next(); | |
let osc3: f32 = this.sawoscillator3.next(); | |
let osc4: f32 = this.sawoscillator4.next(); | |
let osc5: f32 = this.sawoscillator5.next(); | |
let left = env * (osc + osc2 + osc5); | |
let right = env * (osc + osc3 + osc4 ); | |
const filterlfo: f32 = (lfo * 0.9) + 1; | |
this.filterl.update_coeffecients(FilterType.LowPass, SAMPLERATE, | |
200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (127 - this.note), Q_BUTTERWORTH); | |
this.filterr.update_coeffecients(FilterType.LowPass, SAMPLERATE, | |
200 + this.filterenvelope.next() * filterlfo * 10000 + 20 * (this.note), Q_BUTTERWORTH); | |
this.signal.left = this.filterl.process(left ); | |
this.signal.right = this.filterr.process(right ); | |
} | |
} | |
const pads: FlatPad[] = createInstrumentArray<FlatPad>(10, () => new FlatPad()); | |
let padsVolume: f32 = 1.0; | |
class SineLead { | |
private _note: f32; | |
readonly osc: SineOscillator = new SineOscillator(); | |
readonly lfo: SineOscillator = new SineOscillator(); | |
readonly env1: Envelope = new Envelope(0.02, 0.10, 0.2, 0.3); | |
readonly noiseenv: Envelope = new Envelope(0.01, 0.02, 0.1, 0.3); | |
readonly signal: StereoSignal = new StereoSignal(); | |
private noise: Noise = new Noise(); | |
hpfilterl: BiQuadFilter = new BiQuadFilter(); | |
hpfilterr: BiQuadFilter = new BiQuadFilter(); | |
private bandpass: BandPass = new BandPass(400,2000); | |
private shaper: WaveShaper = new WaveShaper(); | |
constructor() { | |
this.hpfilterl.update_coeffecients(FilterType.HighPass, SAMPLERATE, 7000, 0.5); | |
this.hpfilterr.update_coeffecients(FilterType.HighPass, SAMPLERATE, 7000, 0.5); | |
} | |
set note(note: f32) { | |
if(note > 1) { | |
this.osc.frequency = notefreq(note); | |
this.lfo.frequency = 8; | |
this._note = note; | |
this.env1.attack(); | |
this.noiseenv.attack(); | |
} else { | |
this.env1.release(); | |
this.noiseenv.release(); | |
} | |
} | |
get note(): f32 { | |
return this._note; | |
} | |
next(): void { | |
if(this.env1.state === 4) { | |
this.signal.clear(); | |
return; | |
} | |
const env1: f32 = this.env1.next(); | |
const noiseenv: f32 = this.noiseenv.next(); | |
let lfo: f32 = this.lfo.next(); | |
let osc: f32 = this.osc.next(); | |
osc *= env1; | |
let noiseleft: f32 = this.noise.next() * noiseenv; | |
let noiseright: f32 = this.noise.next() * noiseenv; | |
noiseleft = this.hpfilterl.process(noiseleft); | |
noiseright = this.hpfilterr.process(noiseright); | |
const pan = this._note / 127; | |
this.bandpass.update_frequencies(300,2000 + 1300 * lfo); | |
osc = this.bandpass.process(osc); | |
osc = this.shaper.process(osc); | |
let left = osc * pan; | |
let right = osc * (1 - pan); | |
this.signal.left = left + noiseleft; | |
this.signal.right = right + noiseright; | |
} | |
} | |
export class DriveLead { | |
private _note: f32; | |
readonly envelope: Envelope = new Envelope(0.03, 1.0, 0.6, 0.2); | |
readonly sawoscillatorl: SawOscillator = new SawOscillator(); | |
readonly sawoscillatorr: SawOscillator = new SawOscillator(); | |
readonly shaper: WaveShaper = new WaveShaper(); | |
readonly signal: StereoSignal = new StereoSignal(); | |
readonly lfoenvelope: Envelope = new Envelope(1.0, 0, 1.0, 0.1); | |
readonly lfo: SineOscillator = new SineOscillator(); | |
private baseFrequency : f32; | |
private pitchbend: f32 = 0; | |
set note(note: f32) { | |
if(note > 1) { | |
this.shaper.drive = 0.5; | |
this.baseFrequency = notefreq(note + this.pitchbend); | |
this.lfo.frequency = 8; | |
this.envelope.attack(); | |
this.lfoenvelope.attack(); | |
this._note = note; | |
} else { | |
this.envelope.release(); | |
this.lfoenvelope.release(); | |
} | |
} | |
get note(): f32 { | |
return this._note; | |
} | |
setPitchbend(bend: f32): void { | |
this.pitchbend = bend; | |
this.baseFrequency = notefreq(this._note + bend); | |
} | |
next(): void { | |
let env: f32 = this.envelope.next(); | |
if(env===0) { | |
this.signal.clear(); | |
return; | |
} | |
let lfo: f32 = this.lfo.next() * 3 * this.lfoenvelope.next(); | |
this.sawoscillatorl.frequency = this.baseFrequency + lfo + 0.5; | |
this.sawoscillatorr.frequency = this.baseFrequency + lfo - 0.5; | |
let left = env* this.sawoscillatorl.next() + this.signal.right * 0.5; | |
left = this.shaper.process(left); | |
let right = env* this.sawoscillatorr.next() + this.signal.left * 0.5; | |
right = this.shaper.process(right); | |
this.signal.left = left * 0.5 + right; | |
this.signal.right = right * 0.5 + left; | |
} | |
} | |
const sinelead = new SineLead(); | |
const drivelead = new DriveLead(); | |
const deepbass = new DeepBass(); | |
const pianos: SubPiano[] = createInstrumentArray<SubPiano>(5, () => new SubPiano()); | |
export function setChannelValue(channel: usize, value: f32): void { | |
const setChannelValueFunctions: usize[] = [ | |
changetype<usize>((value:f32): void => {bass.note = value;}), | |
changetype<usize>((value:f32): void => {lead.note = value;}), | |
changetype<usize>((value:f32): void => {sinelead.note = value;}), | |
changetype<usize>((value:f32): void => {kick.note = value;}), | |
changetype<usize>((value:f32): void => {snare.note = value;}), | |
changetype<usize>((value:f32): void => {hihat.note = value;}), | |
changetype<usize>((value:f32): void => {pads[0].note = value;}), | |
changetype<usize>((value:f32): void => {pads[1].note = value;}), | |
changetype<usize>((value:f32): void => {pads[2].note = value;}), | |
changetype<usize>((value:f32): void => {pads[3].note = value;}), | |
changetype<usize>((value:f32): void => {pads[4].note = value;}), | |
changetype<usize>((value:f32): void => {pads[5].note = value;}), | |
changetype<usize>((value:f32): void => {pads[6].note = value;}), | |
changetype<usize>((value:f32): void => {pads[7].note = value;}), | |
changetype<usize>((value:f32): void => {pads[8].note = value;}), | |
changetype<usize>((value:f32): void => {pads[9].note = value;}), | |
changetype<usize>((value:f32): void => { | |
if(value > 0) { | |
padsVolume = value / 100.0; | |
} | |
}), | |
changetype<usize>((value:f32): void => {drivelead.note = value;}), | |
changetype<usize>((value:f32): void => { | |
if(value > 0) { | |
drivelead.setPitchbend((value - 64) / 32); | |
} | |
}), | |
changetype<usize>((value:f32): void => {deepbass.note = value;}), | |
changetype<usize>((value:f32): void => { | |
if(value > 0) { | |
masterlopassfilterleft.update_coeffecients( | |
FilterType.LowPass, SAMPLERATE, ((value - 1)/ 127.0) * 20000.0, Q_BUTTERWORTH); | |
masterlopassfilterright.update_coeffecients( | |
FilterType.LowPass, SAMPLERATE, ((value - 1 )/ 127.0) * 20000.0, Q_BUTTERWORTH); | |
} | |
}), | |
changetype<usize>((value:f32): void => {pianos[0].note = value;}), | |
changetype<usize>((value:f32): void => {pianos[1].note = value;}), | |
changetype<usize>((value:f32): void => {pianos[2].note = value;}), | |
changetype<usize>((value:f32): void => {pianos[3].note = value;}), | |
changetype<usize>((value:f32): void => {pianos[4].note = value;}), | |
]; | |
changetype<(val: f32) => void>(setChannelValueFunctions[channel])(value); | |
} | |
const mainline = new StereoSignal(); | |
const reverbline = new StereoSignal(); | |
const freeverb = new Freeverb(); | |
const delayframes = (SAMPLERATE * (6/8) * 60 / 120) as usize; | |
let delayLeft: DelayLine = new DelayLine(delayframes); | |
let delayRight: DelayLine = new DelayLine(delayframes); | |
let echoline = new StereoSignal(); | |
export function mixernext(leftSampleBufferPtr: usize, rightSampleBufferPtr: usize): void { | |
let left: f32 = 0; | |
let right: f32 = 0; | |
mainline.clear(); | |
reverbline.clear(); | |
echoline.clear(); | |
bass.next(); | |
mainline.addStereoSignal(bass.signal, 1.3, 0.5); | |
reverbline.addStereoSignal(bass.signal, 0.3, 0.5); | |
deepbass.next(); | |
mainline.addStereoSignal(deepbass.signal, 1.2, 0.5); | |
echoline.addStereoSignal(deepbass.signal, 0.3, 0.5); | |
lead.next(); | |
mainline.addStereoSignal(lead.signal, 1.4, 0.5); | |
echoline.addStereoSignal(lead.signal, 1.0, 0.5); | |
drivelead.next(); | |
mainline.addStereoSignal(drivelead.signal, 0.1, 0.3); | |
echoline.addStereoSignal(drivelead.signal, 0.4, 0.7); | |
sinelead.next(); | |
mainline.addStereoSignal(sinelead.signal, 1.4, 0.6); | |
echoline.addStereoSignal(sinelead.signal, 1.3, 0.7); | |
kick.next(); | |
mainline.addStereoSignal(kick.signal, 1.0, 0.5); | |
snare.next(); | |
mainline.addStereoSignal(snare.signal, 0.8, 0.5); | |
reverbline.addStereoSignal(snare.signal, 0.05, 0.5); | |
hihat.next(); | |
mainline.addStereoSignal(hihat.signal, 0.8, 0.5); | |
pads.forEach(pad => { | |
pad.next(); | |
mainline.addStereoSignal(pad.signal, 0.45 * padsVolume, 0.5); | |
}); | |
pianos.forEach(piano => { | |
piano.next(); | |
mainline.addStereoSignal(piano.signal, 0.3, 0.5); | |
echoline.addStereoSignal(piano.signal, 0.1, 0.5); | |
}); | |
echoline.left += delayRight.read() * 0.7; | |
echoline.right += delayLeft.read() * 0.7; | |
delayLeft.write_and_advance(echoline.left); | |
delayRight.write_and_advance(echoline.right); | |
freeverb.tick(reverbline); | |
left = gain * (mainline.left + reverbline.left + echoline.left); | |
right = gain * (mainline.right + reverbline.right + echoline.right); | |
left = masterlopassfilterleft.process(left); | |
right = masterlopassfilterright.process(right); | |
left = tribandeqleft.process(left,1.0, 0.7, 1.0); | |
right = tribandeqright.process(right,1.0, 0.7, 1.0); | |
left = softclip(left); | |
right = softclip(right); | |
store<f32>(leftSampleBufferPtr, left); | |
store<f32>(rightSampleBufferPtr, right); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment