How do you come up with your audio formulas
eguneys opened this issue · 2 comments
I love your audio synthesis code. I had an interesting chatGPT conversation about this I would like to share here:
https://chat.openai.com/share/957a3f2c-2d05-4ed2-885c-3c8af7c7caf9
So, can you please share your insights about how your audio formulas work and how can I learn and apply similar techniques, thank you.
I can try 😂
// N is chosen by the duration of the audio snippet (sampleRate * duration).
// The function "fn" is evaluated for each audio sample.
// Audio is always faded from max volume to 0 volume over the duration (1 - i/N).
for (let i = 0; i < N; i++) {
buffer[i] = fn(i * 44100 / sampleRate) * (1 - i/N);
}
There are 4 base sounds that can be composed to make all sorts of content:
sin
is a smoothooooo
saw
is an electriczzzzz
sqr
is a digitalbrbrbr
random
is a noisyshshsh
Tuning the balance, timing, and frequency of these functions lets you make all sort of audio! There's some amount of intuition you can build by experimenting for a while. I highly recommend plotting some of these functions to help build that intuition 🎵
🦴 Collecting a bone in the game should be imagined as a "points gained" sound. It's a short little "zzz".
boneCollectSound = await generate(0.06, (i) => {
return 0.03 * saw(i/4);
});
🚪 Activating a switch has no sounds on its own, but rather the sound of a door opening for 1.5 seconds. That sound in my mind is a mechanical ratcheting system that is roughly "zi zi zi zi". The low frequency square
wave turns the sound on and off to simulate the intermittent sound of mechanical gear teeth making new contact. Multiplying this by fixed frequency saw
wave makes the sound be "zz" when on and nothing when off.
switchSound = await generate(1.5, (i) => {
return 0.1 * (sqr(i/800) * 0.5 + 0.5) * saw(i/(110));
});
🕸️ Hitting the spider webs with basic attacks should effectively make a cute "boing" sound. A boing sound is all about frequency oscillating around a base frequency. Since a web can be viewed like a guitar string, I use a sin
function as the base waveform, then modulate its frequency with another sin
inside!
boingSound = await generate(0.6, (i) => {
return 0.06 * sin(i/(20+sin(i/900)+i/1300));
});
🔥 The fireball attack is a fun composition of flame sound + doppler shift (the sound cars make while whiffing by). A burning flame is a crackling sound simply modeled with the random
function. As for the doppler shift, take any repeating waveform (I chose square
wave here), then make its base frequency decrease over time. Old game audio has convinced us this sound is pronounced pewwwww
.
fireballSound = await generate(0.4, (i) => {
return 0.03 * (sqr(i/(20 + i / 100) + Math.random()));
});
Hopefully that helps get you started!
Interesting stuff, I will experiment for a while, thanks for your detailed explanation.