234817
feel free to ask questions or share tips about bytebeat! (preferably but not necessarily floatbeat-tailored, as the math for most stuff is usually simpler for that)
this post will also be edited to add useful info so people coming to the thread don't need to look for whether the question they have has already been asked/answered! i may also sometimes sprinkle in some of my own discoveries/techniques as well :3
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
tips for starting out:
•i highly recommend using floatbeat as that will simplify a whole bunch of things later on (no need to center waveforms, avoid wraparound, etc.)
•the dollchan editor is currently the most widely-used and feature-packed editor for bytebeat, so unless you're more comfortable working using the greggman editor for whatever reason i suggest you stick to the former!
•try to approach making music the way you would if you had to build your own music making program! so making an oscillator/sound generator, then a sequencer, mixer - it can be as simple as playing a sine wave at different pitches and having multiple simultaneous instances of that added together to play melodies and chords!
code snippets:
run certain code only at t=0 (useful for initializing persistent variables aka state):
basic setup for audio effects that require state:
a basic low-pass filter (first order):
a better low-pass filter (2nd order, steeper cutoff):
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
note: this thread was mainly made for the bytebeat round(s) in smackdown of the signals but you can look for info or ask around in this thread during other battles as well! i'll also check what sort of things i should explain/demonstrate in the bytebeat guide i'm writing based on what people ask or are confused about
also this is technically a dupe thread since bytebeat general exists but that one is ancient and filled with a bunch of old discussion about stuff that doesn't really matter anymore (concerns about using functions and whatnot) so here we are
this post will also be edited to add useful info so people coming to the thread don't need to look for whether the question they have has already been asked/answered! i may also sometimes sprinkle in some of my own discoveries/techniques as well :3
tips for starting out:
•i highly recommend using floatbeat as that will simplify a whole bunch of things later on (no need to center waveforms, avoid wraparound, etc.)
•the dollchan editor is currently the most widely-used and feature-packed editor for bytebeat, so unless you're more comfortable working using the greggman editor for whatever reason i suggest you stick to the former!
•try to approach making music the way you would if you had to build your own music making program! so making an oscillator/sound generator, then a sequencer, mixer - it can be as simple as playing a sine wave at different pitches and having multiple simultaneous instances of that added together to play melodies and chords!
code snippets:
run certain code only at t=0 (useful for initializing persistent variables aka state):
t || (
// init code here
),
// regular code here
basic setup for audio effects that require state:
t || (
fx = [], // fx memory array
filter = (inp, cut) => (
mem = fx[fxi++], // grabs current effect's memory from the array and increments the memory pointer
// important: if the value at the slot is not an object/array, modifying mem will not modify the value in fx memory! in that case you would need to save the current effect pointer value (pre-increment) and write to fx[fxi] directly, like in the commented lines below:
// cfxi = fxi++,
// fx[cfxi] += 1,
// ...
)
),
d = t, // copy of t for use in effect code since actual t automatically evaluates to 0 for whatever reason
fxi = 0, // fx memory pointer, incremented after each effect use (function call)
// ...
a basic low-pass filter (first order):
t || (
SR = 48000, // sample rate (48000hz)
fx = [],
clamp = (x, a, b) => min(max(x, a), b), // "clamps" a value to fit between 2 numbers (lower bound - a, upper bound - b)
// the fx code for the filter! you don't need to understand how it works, but if you're curious - it initializes its "position" to 0 and exponentially decays towards the input
filter = (inp, cut) => (
cut = clamp(cut/SR*2, 0, 1),
cfxi = fxi++,
fx[cfxi] ??= 0,
out = fx[cfxi],
fx[cfxi] += (inp - out)*cut,
out
)
),
fxi = 0,
src = 1 - t/512%2, // saw wave with a period of 1024 samples (46.875hz)
filter(src, 2000) // filtered (2000hz cutoff) output!
// also, taking the original signal and subtracting a low-pass filtered version of it gives you a high-pass filtered version:
// src - filter(src, 2000)
a better low-pass filter (2nd order, steeper cutoff):
t || (
SR = 48000, // sample rate (48000hz)
fx = [],
clamp = (x, a, b) => min(max(x, a), b), // "clamps" a value to fit between 2 numbers (lower bound - a, upper bound - b)
// fx code for 2nd order filter, based on the impulse tracker filter implementation:
// https://wiki.multimedia.cx/index.php/Impulse_Tracker#Resonant_filters
filter2 = (inp, cut, res) => (
cut = clamp(cut, 0.001, SR/2),
buf = fx[fxi++] ??= [0, 0],
p = 10**(-res*3/320),
r = SR/(2*PI*cut),
e = r*r,
d = e + 2*p*r + 2*p,
out = (inp + (d + e - 1)*buf[0] - e*buf[1])/d,
buf[1] = buf[0],
buf[0] = out,
out
)
),
fxi = 0,
src = 1 - t/512%2, // saw wave with a period of 1024 samples (46.875hz)
src /= 1.5, // reducing saw wave volume by 1.5x
filter2(src, 500, 0) // filtered (500hz cutoff) output!
note: this thread was mainly made for the bytebeat round(s) in smackdown of the signals but you can look for info or ask around in this thread during other battles as well! i'll also check what sort of things i should explain/demonstrate in the bytebeat guide i'm writing based on what people ask or are confused about
also this is technically a dupe thread since bytebeat general exists but that one is ancient and filled with a bunch of old discussion about stuff that doesn't really matter anymore (concerns about using functions and whatnot) so here we are



