Last active
November 14, 2021 07:16
-
-
Save petersalomonsen/e9cf4f8b80b35a09435f3e2f39889318 to your computer and use it in GitHub Desktop.
great knot remix https://petersalomonsen.com/webassemblymusic/livecodev2/?gist=e9cf4f8b80b35a09435f3e2f39889318
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
/* | |
* Copyright (c) 2021 - Peter Johan Salomonsen | |
*/ | |
setBPM(100); | |
addInstrument('BoltToysPluck'); | |
addInstrument('SphericalBowl'); | |
addInstrument('KnotPressureModeled'); | |
addInstrument('empty1'); | |
addInstrument('empty2'); | |
addInstrument('empty3'); | |
addInstrument('empty4'); | |
addInstrument('audioplayer1'); | |
addInstrument('audioplayer2'); | |
addInstrument('audioplayer3'); | |
['arm_with_crook_SLIDE_ARP.wav', 'house_BROKEN_CRYSTAL.wav', 'rope_GTR_EFX.wav', | |
'bolt_TOYS_PERCUSSIONS.wav', 'knot_PRESSURE.wav', 'spherical_bowl_ILLNESS.wav', | |
'folded_cloth_SWZ_BASS.wav', 'owl_sound_n5.wav', 'sun_BUILD_UP.wav', | |
'goatskin_SITAR.wav', 'papyrus_roll_VOCODER.wav', 'vertical_beam_sound_n2.wav', | |
'horned_viper_KICK_DRUM.wav', 'quail_chick_FRASCH_BASSLINE.wav', | |
'water_ripple_DARK.wav'].forEach(url => addAudio('https://storage.googleapis.com/wasm-music-audio/'+url)); | |
const metronome = () => createTrack(2).steps(1,[fs5,fs5,fs5,fs5]); | |
const drumbeat = async () => { | |
createTrack(7).steps(4, [ | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
].repeat(3)); | |
return createTrack(7).steps(4, [ | |
[c6],,c6,, | |
ds5,,,ds5, | |
,ds5,c6,, | |
ds5,,,, | |
c6,,c6,, | |
ds5,,,ds5(0.2,40), | |
,ds5,c6,, | |
ds5,,,c6(0.2, 20), | |
c6,,c6,, | |
ds5,,,ds5, | |
,ds5,c6,, | |
ds5,,,, | |
c6,,c6,, | |
ds5,,,ds5(0.2,40), | |
,ds5,c6,ds5(0.2,30), | |
ds5,ds5(0.2,30),ds5(0.2,50),ds5(0.2,30), | |
]); | |
} | |
const drumbeat2 = async () => { | |
createTrack(7).steps(4, [ | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
].repeat(3)); | |
return createTrack(7).steps(4, [ | |
[c6],,,, | |
[c6,ds5],,,[c6(0.25,30),ds5], | |
c6,ds5,,, | |
[c6,ds5],,,, | |
c6,,,, | |
[c6,ds5],,,ds5(0.2,40), | |
c6,ds5,c6(0.2,60),, | |
[c6,ds5],,,c6(0.2, 20), | |
c6,,,, | |
[c6,ds5],,,ds5, | |
c6,ds5,,, | |
[c6,ds5],,,, | |
c6,,,, | |
[c6,ds5],,,ds5(0.2,40), | |
c6,ds5,,ds5(0.2,30), | |
[c6,ds5],ds5(0.2,30),[c6,ds5(0.2,50)],ds5(0.2,30), | |
]); | |
} | |
const intromelody = () => createTrack(0).play([[ 0.05, a3(7.71, 47) ], | |
[ 0, e4(8, 52) ], | |
[ 0, a5(8, 55) ], | |
[ 6, a6(2, 77) ], | |
[ 0, e6(10, 60) ], | |
[ 10, d6(2, 65) ], | |
[ 12, e6(2, 67) ], | |
[ 8, g4(8, 47) ], | |
[ 8, c4(8, 58) ], | |
[ 14, c6(2, 72) ], | |
[ 8, g6(12, 74) ], | |
[ 20, f6(4, 83) ], | |
[ 16, f3(8, 60) ], | |
[ 16, a5(8, 72) ], | |
[ 16, c4(8, 53) ], | |
[ 22, e6(2, 74) ], | |
[ 24, e4(8, 57) ], | |
[ 24, a4(8, 57) ], | |
[ 24, a3(8, 57) ], | |
[ 24, a5(8, 74) ]]); | |
intromelody(); | |
await createTrack(7).steps(1, [ds5(32,93),,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,,]); | |
intromelody(); | |
createTrack(7).steps(4, [[gs5(32,100), ds5(32,93)]]); | |
await drumbeat(); | |
await drumbeat(); | |
createTrack(8).steps(4, [as5(32,50),g5(32,90)]); | |
createTrack(9).steps(4, [[cs6(32,120), controlchange(74, 2)]]); | |
await drumbeat2(); | |
await drumbeat2(); | |
createTrack(7).steps(4, [[d5(16,60),cs6(16,75)]]); | |
await drumbeat(); | |
createTrack(2).steps(1, [[a5(8,25),e6(8,25)] | |
,,,,,,,,[gs5(8,30),ds6(8,30)]]); | |
createTrack(7).steps(4, [[d5(16,60),cs6(16,75)]]); | |
await drumbeat(); | |
createTrack(1).steps(1, [[a5(8,25),e6(8,25),a3(8,25)] | |
,,,,,,,,[gs5(8,25),ds6(8,25),gs3(8,25)]]); | |
createTrack(2).steps(1, [[a5(8,25),e6(8,25)] | |
,,,,,,,,[ds6(8,30),gs6(8,30)]]); | |
createTrack(7).steps(1, [,,,,,,,,,,,cs5(8,30)]); | |
createTrack(9).steps(1, [controlchange(74, 127),,,,,,,,,,,,,cs5(8,20)]); | |
createTrack(8).steps(1, [,,,,,,,,,,,,,,,cs5(16,12)]); | |
createTrack(7).steps(4, [[d5(16,60),cs6(16,75)]]); | |
await drumbeat(); | |
createTrack(7).steps(4, [c5(32,60)]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,10),, | |
c6,,c4(0.2,10),, | |
c6,,c4(0.1,30),, | |
c6,c4(0.05,5),c4(0.05,20),, | |
].repeat(3)); | |
createTrack(7).steps(1, [ | |
,fs5(7.9,90),g5(7.9),, | |
,,,, | |
,fs5(7,90),g5(6),, | |
,,,, | |
]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,10),, | |
c6,,c4(0.2,10),, | |
c6,,c4(0.1,30),, | |
c6,c4(0.05,5),c4(0.05,20),, | |
].repeat(3)); | |
function secondPluck() { | |
createTrack(0).play([[ 1, e5(6.65, 45) ], | |
[ 1, a4(7, 45) ], | |
[ 1, e6(7, 45) ], | |
[ 1, a5(7, 45) ], | |
[ 1, a6(7, 45) ], | |
[ 8, g4(7, 45) ], | |
[ 9, g6(7, 45) ], | |
[ 9, g5(7, 45) ], | |
[ 8, c4(7, 45) ], | |
[ 9, c6(7, 45) ]]); | |
} | |
secondPluck(); | |
createTrack(7).steps(4, [c5(16,60)]); | |
createTrack(7).steps(1, [ | |
,fs5(7.9,90),g5(7.9),, | |
,,,, | |
,fs5(7,90),g5(6),, | |
,,,, | |
]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,10),, | |
c6,,c4(0.2,10),, | |
c6,,c4(0.1,30),, | |
c6,c4(0.05,5),c4(0.05,20),, | |
].repeat(3)); | |
for (var n=0;n<2;n++) { | |
createTrack(1).steps(1, [ | |
[a5(5),a2(8)],,,, | |
e5(4),,,, | |
[g5(8),c3(8)],,,, | |
,,,, | |
]); | |
secondPluck(); | |
createTrack(7).steps(4, [c5(16,60)]); | |
createTrack(7).steps(1, [ | |
,fs5(7.9,90),g5(7.9),, | |
,,,, | |
,fs5(7,90),g5(6),, | |
,,,, | |
]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,10),, | |
c6,,c4(0.2,10),, | |
c6,,c4(0.1,30),, | |
c6,,c4(0.05,10),, | |
].repeat(3)); | |
} | |
// Stranger things | |
for (var n=0;n<2;n++) { | |
createTrack(1).steps(1, [ | |
[a5(5),a2(8)],,,, | |
e5(4),,,, | |
[as5(8),ds3(8)],,,, | |
,,,, | |
]); | |
createTrack(7).steps(4, [[b5(16,100)]]); | |
createTrack(7).steps(1, [ | |
,fs5(7.9,90),g5(7.9),, | |
,,,, | |
,fs5(7,90),g5(6),, | |
,,,, | |
]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,10),, | |
c6,,c4(0.2,10),, | |
c6,,c4(0.1,30),, | |
c6,,c4(0.05,10),, | |
].repeat(3)); | |
} | |
createTrack(7).steps(4, [[d5(32,70),b5(32,100)]]); | |
for (var n=0;n<2;n++) { | |
createTrack(1).steps(1, [ | |
[e6(5),a5(8)],,,, | |
a6(4),,,, | |
[as6(8),ds4(8)],,,, | |
,,,, | |
]); | |
createTrack(7).steps(1, [ | |
,fs5(7.9,90),g5(7.9),, | |
,,,, | |
,fs5(7,90),g5(6),, | |
,,,, | |
]); | |
await createTrack(7).steps(4, [ | |
c6,,c4(0.2,3),, | |
c6,,c4(0.2,3),, | |
c6,,c4(0.1,6),, | |
c6,,c4(0.05,3),, | |
].repeat(3)); | |
} | |
async function waterRipple() { | |
createTrack(7).steps(4, [d6(32,100)]); | |
createTrack(0).steps(4, [ | |
e5(8,60),,b5(32,60),, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
ds5(8,60),,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
e5(8,60),,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
,,,, | |
f5(8,60),,,, | |
]); | |
} | |
async function waterRippleDrum() { | |
await createTrack(7).steps(4, [ | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,c6(0.2,30), | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,,, | |
c6,,c6,, | |
].repeat(1)); | |
} | |
async function waterRippleDrum2() { | |
createTrack(7).steps(4, [ | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
,,c4(0.5,30),, | |
].repeat(7)); | |
await waterRippleDrum(); | |
} | |
waterRipple(); | |
await waterRippleDrum(); | |
function waterRippleMelody() { | |
createTrack(1).play([ | |
[ 0.00, e5(8, 127) ], | |
[ 5.00, e5(0.09, 127) ], | |
[ 5.92, e5(2.03, 127) ], | |
[ 7.84, fs5(8.19, 127) ], | |
[ 3.88, b4(16.20, 127) ], | |
[ 15.95, gs5(5.06, 127) ], | |
[ 20.05, e5(3.76, 127) ], | |
[ 21.84, gs5(2.04, 127) ], | |
[ 23.92, b5(4.08, 127) ], | |
[ 23.92, f5(7.93, 127) ], | |
[ 27.86, a5(4.03, 127) ]]); | |
} | |
waterRippleMelody(); | |
waterRipple(); | |
await waterRippleDrum2(); | |
function waterRippleKnotPressure() { | |
createTrack(2).play([ | |
[0.5,e6(8,55)], | |
[8.5,ds6(8,55)], | |
[16.5,e6(8,55)], | |
[24.5,f6(8,55)], | |
]); | |
} | |
waterRippleMelody(); | |
waterRippleKnotPressure(); | |
waterRipple(); | |
await waterRippleDrum2(); | |
createTrack(0).play([ | |
[0.75, gs6(8,70)], | |
[8.75, fs6(8,70)], | |
[16.75, gs6(8,70)], | |
[24.75, b6(8,70)], | |
]); | |
waterRippleMelody(); | |
waterRippleKnotPressure(); | |
createTrack(7).steps(4,[ | |
,,,, | |
ds5(0.5),,,ds5(0.5,30), | |
,,,, | |
ds5(0.5),,,, | |
].repeat(7)); | |
waterRipple(); | |
await waterRippleDrum2(); | |
createTrack(0).play([ | |
[0.75, gs6(8,70)], | |
[8.75, fs6(8,70)], | |
[16.75, gs6(8,70)], | |
[24.75, b6(8,70)], | |
]); | |
waterRippleKnotPressure(); | |
createTrack(7).steps(4,[ | |
,,,, | |
ds5(0.5),,,ds5(0.5,30), | |
,,,, | |
ds5(0.5),,,, | |
].repeat(7)); | |
waterRipple(); | |
await waterRippleDrum2(); | |
createTrack(0).play([ | |
[0.75, gs6(8,70)], | |
[8.75, fs6(8,70)], | |
[9.5, b6(7,100)], | |
[16.75, gs6(8,70)], | |
[24.75, b6(8,70)], | |
]); | |
createTrack(7).steps(4,[ | |
,,,, | |
ds5(0.5),,,ds5(0.5,30), | |
,,,, | |
ds5(0.5),,,, | |
].repeat(7)); | |
waterRipple(); | |
await waterRippleDrum2(); | |
createTrack(7).steps(4,[ | |
[a5(32,60)],,ds5(30,20) | |
]); | |
createTrack(1).play([ | |
[0,a3(8,100)], | |
[8,g3(8,100)], | |
[16,e3(8,100)], | |
[24,c3(8,100)], | |
]); | |
createTrack(0).play([ | |
[0,a4(16,60)], | |
[0.5,e5(16,60)], | |
[9,g5(15,60)], | |
[16.5,e6(24,60)] | |
]); | |
await createTrack(7).steps(4, ([ | |
c6,,,, | |
[c6],,,, | |
c6,,,, | |
[c6],,,, | |
].repeat(2).concat([ | |
c6,,,, | |
[c6],,,, | |
c6,,,, | |
[c6],,c6,, | |
]).repeat(1))); | |
await createTrack(7).steps(1,[ | |
ds5(8),,,,,,,, | |
]); | |
loopHere(); |
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
/* | |
* (c) Peter Johan Salomonsen 2021 | |
*/ | |
import { AudioPlayerChannel, MonoAudioPlayer, AudioExciterWaveGuide, noise, AuxExciterWaveGuide, WaveGuide, AllPassFloat, beatToFrame, AudioPlayer, cos, outputline, Limiter, TriangleOscillator, PI, sin, cos, FFT, EQBand, TriBandEQ, EnvelopeState, Pan, SineOscillator, IFFTOscillator, BiQuadFilter, FilterType, Q_BUTTERWORTH, DelayLine, BandPass,SawOscillator,softclip, midichannels, MidiChannel, MidiVoice, StereoSignal, Freeverb, SineOscillator, Envelope } from '../mixes/globalimports'; | |
import { SAMPLERATE } from '../environment'; | |
const BPM: f32 = 100; | |
function notefreq(note: f32): f32 { | |
return 440 * Mathf.pow(2, (-69 + note) / 12); | |
} | |
const delayframes = (SAMPLERATE * (6/8) * 60 / BPM) as usize; | |
const echoLeft = new DelayLine(delayframes); | |
const echoRight = new DelayLine(delayframes); | |
const echoline = new StereoSignal(); | |
class BoltToysPluck extends MidiVoice { | |
env: Envelope = new Envelope(0.005, 0.2, 1.0, 0.23); | |
waveguide1: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(6)); | |
waveguide2: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(7)); | |
noteon(note: u8, velocity: u8): void { | |
super.noteon(note, velocity); | |
const freq = notefreq(note); | |
let exciterFeedbackFreq = (2000 + Mathf.pow(freq,0.8) * 2)as f32; | |
if (exciterFeedbackFreq > 12000) { | |
exciterFeedbackFreq = 12000; | |
} | |
this.waveguide1.exciterFilter.update(exciterFeedbackFreq, Q_BUTTERWORTH); | |
this.waveguide2.exciterFilter.update(exciterFeedbackFreq, Q_BUTTERWORTH); | |
let feedbackfreq: f32 = 1000 + Mathf.pow(freq, 0.65) * 15; | |
this.waveguide1.start(freq , feedbackfreq); | |
this.waveguide2.start(freq , feedbackfreq); | |
const filtergain = this.waveguide1.filterFeedback.coeffs.magnitude; | |
let feedbacklevel: f32 = note < 36 ? 0.930 : | |
note < 48 ? 0.946 : | |
note < 60 ? 0.992 : | |
note < 72 ? 0.996 : | |
0.9999; | |
if (feedbacklevel > 0.9999) { | |
feedbacklevel = 0.9999; | |
} else if (feedbacklevel < 0) { | |
feedbacklevel = 0; | |
} | |
this.waveguide1.feedbackLevel = feedbacklevel; | |
this.waveguide2.feedbackLevel = feedbacklevel; | |
this.env.attack(); | |
} | |
noteoff(): void { | |
this.env.release(); | |
} | |
isDone(): boolean { | |
return this.env.isDone(); | |
} | |
nextframe(): void { | |
const env = this.env.next() * this.velocity * (1/127); | |
const wg1: f32 = this.waveguide1.process(); | |
const wg2: f32 = this.waveguide2.process(); | |
this.channel.signal.add( | |
env * (wg1) , | |
env * (wg2) | |
); | |
} | |
} | |
class SphericalBowlModeled extends MidiVoice { | |
env: Envelope = new Envelope(0.001, 1, 0.95, 0.5); | |
waveguide1: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(10)); | |
waveguide2: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(11)); | |
noteon(note: u8, velocity: u8): void { | |
super.noteon(note, velocity); | |
const freq = notefreq(note); | |
this.waveguide1.exciterFilter.update(15000, Q_BUTTERWORTH); | |
this.waveguide2.exciterFilter.update(15000, Q_BUTTERWORTH); | |
const feedbacklevel: f32 = 0.9; | |
this.waveguide1.feedbackLevel = feedbacklevel; | |
this.waveguide2.feedbackLevel = feedbacklevel; | |
this.waveguide1.start(freq, freq * 6000 / Mathf.pow(note, 1.3) ); | |
this.waveguide2.start(freq, freq * 6000 / Mathf.pow(note, 1.3) ); | |
this.env.attack(); | |
} | |
noteoff(): void { | |
this.env.release(); | |
} | |
isDone(): boolean { | |
return this.env.isDone(); | |
} | |
nextframe(): void { | |
const env:f32 = this.env.next() * this.velocity * 0.08; | |
const left = | |
this.waveguide1.process() | |
* env; | |
const right = | |
this.waveguide2.process() | |
* env; | |
this.channel.signal.add( | |
left, right | |
); | |
} | |
} | |
class KnotPressureModeled extends MidiVoice { | |
env: Envelope = new Envelope(0.001, 1, 0.80, 0.5); | |
waveguide1: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(8)); | |
waveguide2: AudioExciterWaveGuide = new AudioExciterWaveGuide(new MonoAudioPlayer(9)); | |
noteon(note: u8, velocity: u8): void { | |
super.noteon(note, velocity); | |
const freq = notefreq(note); | |
this.waveguide1.exciterFilter.update(8000, Q_BUTTERWORTH); | |
this.waveguide2.exciterFilter.update(8000, Q_BUTTERWORTH); | |
const feedbacklevel: f32 = -0.9; | |
this.waveguide1.feedbackLevel = feedbacklevel; | |
this.waveguide2.feedbackLevel = feedbacklevel; | |
this.waveguide1.start(freq, freq * 4000 / Mathf.pow(note, 1.3) ); | |
this.waveguide2.start(freq, freq * 4000 / Mathf.pow(note, 1.3) ); | |
this.env.attack(); | |
} | |
noteoff(): void { | |
this.env.release(); | |
} | |
isDone(): boolean { | |
return this.env.isDone(); | |
} | |
nextframe(): void { | |
const env:f32 = this.env.next() * this.velocity * 0.05; | |
const left = | |
this.waveguide1.process() | |
* env; | |
const right = | |
this.waveguide2.process() | |
* env; | |
this.channel.signal.add( | |
left, right | |
); | |
} | |
} | |
export function initializeMidiSynth(): void { | |
midichannels[0] = new MidiChannel(16, (ch) => new BoltToysPluck(ch)); | |
midichannels[0].controlchange(7, 66); | |
midichannels[0].controlchange(10, 64); | |
midichannels[0].controlchange(91, 20); | |
midichannels[1] = new MidiChannel(15, (ch) => new SphericalBowlModeled(ch)); | |
midichannels[1].controlchange(7,25); | |
midichannels[1].controlchange(10, 64); | |
midichannels[1].controlchange(91, 60); | |
midichannels[2] = new MidiChannel(5, (ch) => new KnotPressureModeled(ch)); | |
midichannels[2].controlchange(7, 70); | |
midichannels[2].controlchange(10, 80); | |
midichannels[2].controlchange(91, 20); | |
const audioPlayerChannel: () => AudioPlayerChannel = () => new AudioPlayerChannel(16, (ch, ndx) => { | |
if (ndx < 15) { | |
return new AudioPlayer(ch, ndx, 0, (ndx + 60) as u8); | |
} else { | |
switch(ndx) { | |
case 15: | |
default: | |
return new AudioPlayer(ch, 4, beatToFrame(7, BPM), 48 as u8, new Envelope(0.001,0.2,0.4,0.1)); | |
} | |
} | |
}); | |
midichannels[7] = audioPlayerChannel(); | |
midichannels[7].controlchange(7, 120); | |
midichannels[7].controlchange(91, 10); | |
midichannels[8] = audioPlayerChannel(); | |
midichannels[8].controlchange(7, 120); | |
midichannels[8].controlchange(10, 35); | |
midichannels[8].controlchange(91, 10); | |
midichannels[9] = audioPlayerChannel(); | |
midichannels[9].controlchange(7, 120); | |
midichannels[9].controlchange(10, 95); | |
midichannels[9].controlchange(91, 10); | |
} | |
class MultiBandEQ { | |
bands: StaticArray<EQBand>; | |
constructor(freqs: f32[]) { | |
this.bands = new StaticArray<EQBand>(freqs.length - 1); | |
for ( let n=1; n<freqs.length; n++) { | |
this.bands[n-1] = new EQBand(freqs[n-1], freqs[n]); | |
} | |
} | |
process(signal: f32, levels: f32[]): f32 { | |
let ret: f32 = 0; | |
for (let n = 0;n<this.bands.length; n++) { | |
ret += this.bands[n].process(signal) * levels[n]; | |
} | |
return ret; | |
} | |
} | |
const eqfreqs: f32[] = [20,60,150,600,12000,19000] | |
const eqlevels: f32[] = [1.0, 1.0, 1.0, 1.0, 1.0]; | |
const eqleft = new MultiBandEQ(eqfreqs); | |
const eqright = new MultiBandEQ(eqfreqs); | |
export function postprocess(): void { | |
const gain: f32 = 2.3; | |
let left = outputline.left; | |
let right = outputline.right; | |
const echol = echoLeft.read() * 0.2; | |
const echor = echoRight.read() * 0.2; | |
echoLeft.write_and_advance(echol + echoline.left); | |
echoRight.write_and_advance(echor + echoline.right); | |
left+=echol; | |
right+=echor; | |
left = eqleft.process(left, eqlevels); | |
right = eqright.process(right, eqlevels); | |
left*=gain; | |
right*=gain; | |
outputline.left = left; | |
outputline.right = right; | |
echoline.clear(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment