Skip to content

Instantly share code, notes, and snippets.

@petersalomonsen
Last active January 12, 2021 12:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petersalomonsen/5b795090ead4f192e7f5ee5dcdd17392 to your computer and use it in GitHub Desktop.
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
/**
*
* "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 );
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