mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-22 02:58:32 +00:00
fix: use custom version of ZZFX
- ZZFX audio context broke tests - only needed buildSamples function
This commit is contained in:
parent
90cdea3656
commit
b991cfc493
@ -161,5 +161,6 @@ Then just make sure your first call of `superdough` happens after a click of som
|
|||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
- [ZZFX](https://github.com/KilledByAPixel/ZzFX) used for synths starting with z
|
||||||
- [SuperDirt](https://github.com/musikinformatik/SuperDirt)
|
- [SuperDirt](https://github.com/musikinformatik/SuperDirt)
|
||||||
- [WebDirt](https://github.com/dktr0/WebDirt)
|
- [WebDirt](https://github.com/dktr0/WebDirt)
|
||||||
|
|||||||
@ -36,7 +36,6 @@
|
|||||||
"vite": "^4.3.3"
|
"vite": "^4.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanostores": "^0.8.1",
|
"nanostores": "^0.8.1"
|
||||||
"zzfx": "^1.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ZZFX } from 'zzfx';
|
//import { ZZFX } from 'zzfx';
|
||||||
import { midiToFreq, noteToMidi } from './util.mjs';
|
import { midiToFreq, noteToMidi } from './util.mjs';
|
||||||
import { registerSound, getAudioContext } from './superdough.mjs';
|
import { registerSound, getAudioContext } from './superdough.mjs';
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ export const getZZFX = (value, t, duration) => {
|
|||||||
const readableParams = Object.fromEntries(paramOrder.map((param, i) => [param, params[i]]));
|
const readableParams = Object.fromEntries(paramOrder.map((param, i) => [param, params[i]]));
|
||||||
console.log(readableParams);
|
console.log(readableParams);
|
||||||
|
|
||||||
const samples = ZZFX.buildSamples(...params);
|
const samples = /* ZZFX. */ buildSamples(...params);
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
const buffer = context.createBuffer(1, samples.length, context.sampleRate);
|
const buffer = context.createBuffer(1, samples.length, context.sampleRate);
|
||||||
buffer.getChannelData(0).set(samples);
|
buffer.getChannelData(0).set(samples);
|
||||||
@ -98,7 +98,7 @@ export function registerZZFXSounds() {
|
|||||||
console.log('registerZZFXSounds');
|
console.log('registerZZFXSounds');
|
||||||
['zsine', 'zsaw', 'ztri', 'ztan', 'znoise'].forEach((wave) => {
|
['zsine', 'zsaw', 'ztri', 'ztan', 'znoise'].forEach((wave) => {
|
||||||
registerSound(wave, (t, value, onended) => {
|
registerSound(wave, (t, value, onended) => {
|
||||||
const duration = 0.2;
|
const duration = 0.3;
|
||||||
const { node: o } = getZZFX({ s: wave, ...value }, t, duration);
|
const { node: o } = getZZFX({ s: wave, ...value }, t, duration);
|
||||||
o.onended = () => {
|
o.onended = () => {
|
||||||
o.disconnect();
|
o.disconnect();
|
||||||
@ -111,3 +111,122 @@ export function registerZZFXSounds() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/KilledByAPixel/ZzFX/blob/master/ZzFX.js#L85C5-L180C6
|
||||||
|
// changes: replaced this.volume with 1 + using sampleRate from getAudioContext()
|
||||||
|
function buildSamples(
|
||||||
|
volume = 1,
|
||||||
|
randomness = 0.05,
|
||||||
|
frequency = 220,
|
||||||
|
attack = 0,
|
||||||
|
sustain = 0,
|
||||||
|
release = 0.1,
|
||||||
|
shape = 0,
|
||||||
|
shapeCurve = 1,
|
||||||
|
slide = 0,
|
||||||
|
deltaSlide = 0,
|
||||||
|
pitchJump = 0,
|
||||||
|
pitchJumpTime = 0,
|
||||||
|
repeatTime = 0,
|
||||||
|
noise = 0,
|
||||||
|
modulation = 0,
|
||||||
|
bitCrush = 0,
|
||||||
|
delay = 0,
|
||||||
|
sustainVolume = 1,
|
||||||
|
decay = 0,
|
||||||
|
tremolo = 0,
|
||||||
|
) {
|
||||||
|
// init parameters
|
||||||
|
let PI2 = Math.PI * 2,
|
||||||
|
sampleRate = getAudioContext().sampleRate,
|
||||||
|
sign = (v) => (v > 0 ? 1 : -1),
|
||||||
|
startSlide = (slide *= (500 * PI2) / sampleRate / sampleRate),
|
||||||
|
startFrequency = (frequency *= ((1 + randomness * 2 * Math.random() - randomness) * PI2) / sampleRate),
|
||||||
|
b = [],
|
||||||
|
t = 0,
|
||||||
|
tm = 0,
|
||||||
|
i = 0,
|
||||||
|
j = 1,
|
||||||
|
r = 0,
|
||||||
|
c = 0,
|
||||||
|
s = 0,
|
||||||
|
f,
|
||||||
|
length;
|
||||||
|
|
||||||
|
// scale by sample rate
|
||||||
|
attack = attack * sampleRate + 9; // minimum attack to prevent pop
|
||||||
|
decay *= sampleRate;
|
||||||
|
sustain *= sampleRate;
|
||||||
|
release *= sampleRate;
|
||||||
|
delay *= sampleRate;
|
||||||
|
deltaSlide *= (500 * PI2) / sampleRate ** 3;
|
||||||
|
modulation *= PI2 / sampleRate;
|
||||||
|
pitchJump *= PI2 / sampleRate;
|
||||||
|
pitchJumpTime *= sampleRate;
|
||||||
|
repeatTime = (repeatTime * sampleRate) | 0;
|
||||||
|
|
||||||
|
// generate waveform
|
||||||
|
for (length = (attack + decay + sustain + release + delay) | 0; i < length; b[i++] = s) {
|
||||||
|
if (!(++c % ((bitCrush * 100) | 0))) {
|
||||||
|
// bit crush
|
||||||
|
s = shape
|
||||||
|
? shape > 1
|
||||||
|
? shape > 2
|
||||||
|
? shape > 3 // wave shape
|
||||||
|
? Math.sin((t % PI2) ** 3) // 4 noise
|
||||||
|
: Math.max(Math.min(Math.tan(t), 1), -1) // 3 tan
|
||||||
|
: 1 - (((((2 * t) / PI2) % 2) + 2) % 2) // 2 saw
|
||||||
|
: 1 - 4 * Math.abs(Math.round(t / PI2) - t / PI2) // 1 triangle
|
||||||
|
: Math.sin(t); // 0 sin
|
||||||
|
|
||||||
|
s =
|
||||||
|
(repeatTime
|
||||||
|
? 1 - tremolo + tremolo * Math.sin((PI2 * i) / repeatTime) // tremolo
|
||||||
|
: 1) *
|
||||||
|
sign(s) *
|
||||||
|
Math.abs(s) ** shapeCurve * // curve 0=square, 2=pointy
|
||||||
|
volume *
|
||||||
|
1 * // envelope
|
||||||
|
(i < attack
|
||||||
|
? i / attack // attack
|
||||||
|
: i < attack + decay // decay
|
||||||
|
? 1 - ((i - attack) / decay) * (1 - sustainVolume) // decay falloff
|
||||||
|
: i < attack + decay + sustain // sustain
|
||||||
|
? sustainVolume // sustain volume
|
||||||
|
: i < length - delay // release
|
||||||
|
? ((length - i - delay) / release) * // release falloff
|
||||||
|
sustainVolume // release volume
|
||||||
|
: 0); // post release
|
||||||
|
|
||||||
|
s = delay
|
||||||
|
? s / 2 +
|
||||||
|
(delay > i
|
||||||
|
? 0 // delay
|
||||||
|
: ((i < length - delay ? 1 : (length - i) / delay) * // release delay
|
||||||
|
b[(i - delay) | 0]) /
|
||||||
|
2)
|
||||||
|
: s; // sample delay
|
||||||
|
}
|
||||||
|
|
||||||
|
f =
|
||||||
|
(frequency += slide += deltaSlide) * // frequency
|
||||||
|
Math.cos(modulation * tm++); // modulation
|
||||||
|
t += f - f * noise * (1 - (((Math.sin(i) + 1) * 1e9) % 2)); // noise
|
||||||
|
|
||||||
|
if (j && ++j > pitchJumpTime) {
|
||||||
|
// pitch jump
|
||||||
|
frequency += pitchJump; // apply pitch jump
|
||||||
|
startFrequency += pitchJump; // also apply to start
|
||||||
|
j = 0; // stop pitch jump time
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repeatTime && !(++r % repeatTime)) {
|
||||||
|
// repeat
|
||||||
|
frequency = startFrequency; // reset frequency
|
||||||
|
slide = startSlide; // reset slide
|
||||||
|
j ||= 1; // reset pitch jump time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|||||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@ -395,9 +391,6 @@ importers:
|
|||||||
nanostores:
|
nanostores:
|
||||||
specifier: ^0.8.1
|
specifier: ^0.8.1
|
||||||
version: 0.8.1
|
version: 0.8.1
|
||||||
zzfx:
|
|
||||||
specifier: ^1.2.0
|
|
||||||
version: 1.2.0
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
vite:
|
vite:
|
||||||
specifier: ^4.3.3
|
specifier: ^4.3.3
|
||||||
@ -14038,6 +14031,6 @@ packages:
|
|||||||
/zwitch@2.0.4:
|
/zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
|
|
||||||
/zzfx@1.2.0:
|
settings:
|
||||||
resolution: {integrity: sha512-RtFz6PTMfCmxTfaCOv6GWAV4YaL/T0hltiMGkd87clybO8WLPlH6kX8sNkZGFKw9YPyu1UNsUYf/5/Vn4dondA==}
|
autoInstallPeers: true
|
||||||
dev: false
|
excludeLinksFromLockfile: false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user