at a certain point i lost the interest in making music - somewhere in my early 30's.
-
@TomF @nickappleton @aeva @Farbs what @jkaniarz said is part of what i was thinking of.
use 32 bit integers. for n channels being added, keep log2(n) msb free. scaling down is lossy, so pre-aggregate factors in the entire processing pipeline: normalise all volume levels in a partition of unity, so in combination they use maximum range. apply 1 post scale.
but tom and nick are right in that floats are just convenient. the by far nicest option on x64 is to just set the CPU to zero denormals
@lritter @aeva @jkaniarz @TomF @Farbs 32-bits is usually enough for most things. I’m still scarred from working on 24-bit DSPs which are utter pricks for complex (I.e. involve FFTs) signal paths and the quality can noticeably drop. Regarding saturation, many DSPs have saturating ops and ARM NEON has some basic ones for additive operations.
-
@lritter @aeva @jkaniarz @TomF @Farbs 32-bits is usually enough for most things. I’m still scarred from working on 24-bit DSPs which are utter pricks for complex (I.e. involve FFTs) signal paths and the quality can noticeably drop. Regarding saturation, many DSPs have saturating ops and ARM NEON has some basic ones for additive operations.
@nickappleton @aeva @jkaniarz @TomF @Farbs could also escape to 64 bit int ops and saturate there but this limits cpu targets. there's also the tiny teensy matter of emulating transcendentals.
anyway. all this is low level hell. we were talking about high level heaven - the reason why we do all of this: blessed emergence.
-
@TomF @nickappleton @aeva @Farbs what @jkaniarz said is part of what i was thinking of.
use 32 bit integers. for n channels being added, keep log2(n) msb free. scaling down is lossy, so pre-aggregate factors in the entire processing pipeline: normalise all volume levels in a partition of unity, so in combination they use maximum range. apply 1 post scale.
but tom and nick are right in that floats are just convenient. the by far nicest option on x64 is to just set the CPU to zero denormals
@lritter @TomF @nickappleton @Farbs @jkaniarz i just put all the sound numbers in the float32 hole 🤓
-
@lritter @TomF @nickappleton @Farbs @jkaniarz i just put all the sound numbers in the float32 hole 🤓
@lritter @TomF @nickappleton @Farbs @jkaniarz oh wait no I forgot. I put all the sound numbers in the float64 hole, because it gives a richer, warmer sound
-
@nickappleton @aeva @jkaniarz @TomF @Farbs could also escape to 64 bit int ops and saturate there but this limits cpu targets. there's also the tiny teensy matter of emulating transcendentals.
anyway. all this is low level hell. we were talking about high level heaven - the reason why we do all of this: blessed emergence.
@lritter @nickappleton @jkaniarz @TomF @Farbs just toss them into doubles and get fancy later if you actually need it
-
@lritter @TomF @nickappleton @Farbs @jkaniarz oh wait no I forgot. I put all the sound numbers in the float64 hole, because it gives a richer, warmer sound
-
@lritter @TomF @nickappleton @Farbs @jkaniarz oh wait no I forgot. I put all the sound numbers in the float64 hole, because it gives a richer, warmer sound
@aeva @TomF @nickappleton @Farbs @jkaniarz i wonder if there is a way to make float32 degradation audible. maybe this: add very loud signal A to very quiet signal B, then subtract signal A, normalise signal B. it should now have clicks where it quantizes to zero... or rather, the interference pattern should be more complex. it only pops around where A had max amplitude
-
@aeva okay. so https://en.wikipedia.org/wiki/Datalog#Example
read only the example section. this is the entire language. this is not an intro, a sneak peek (sorry for the typo, a sneak peak is something else), *this is it*. when you have understood the example, you have understood datalog.
@lritter I'm not any less tired but I took another stab at trying to see it. As I understand it, datalog patches describe the explicit and implicit connections between things, and high level audio synthesis is often described as a set of connections, between modules, so I could see that angle working since the math is pulled out of focus, but the implicit connections part is still fuzzy to me. Is this more or less along the lines of what you have in mind?
-
@lritter I'm not any less tired but I took another stab at trying to see it. As I understand it, datalog patches describe the explicit and implicit connections between things, and high level audio synthesis is often described as a set of connections, between modules, so I could see that angle working since the math is pulled out of focus, but the implicit connections part is still fuzzy to me. Is this more or less along the lines of what you have in mind?
@lritter the other angle that comes to mind at the moment is to use this as a sequencer, which isn't really obvious how that would work except that datalog feels markovian, and markov chains etc make sense to me as a procedural sequence generator and I've had some good results using them to generate interesting midi streams
-
@lritter I'm not any less tired but I took another stab at trying to see it. As I understand it, datalog patches describe the explicit and implicit connections between things, and high level audio synthesis is often described as a set of connections, between modules, so I could see that angle working since the math is pulled out of focus, but the implicit connections part is still fuzzy to me. Is this more or less along the lines of what you have in mind?
@aeva it's also relational (in the einstein sense), which allows you (and the compiler) to radically shift perspective with few changes. you can invert a function just by reading it from the outside in. it's particularly well suited to graph processing. in soufflé, a datalog dialect, a toposort is 3 lines. a SCC analysis is less than 10 lines. a raytracer should be similarly dense. and you're thinking data oriented rather than functional - good for entity component systems. for audio:
-
@aeva it's also relational (in the einstein sense), which allows you (and the compiler) to radically shift perspective with few changes. you can invert a function just by reading it from the outside in. it's particularly well suited to graph processing. in soufflé, a datalog dialect, a toposort is 3 lines. a SCC analysis is less than 10 lines. a raytracer should be similarly dense. and you're thinking data oriented rather than functional - good for entity component systems. for audio:
@aeva say we generate a sample of a sine with:
samplerate(44100).
duration(0.5).
pitch(440).
sample(i, sin(t * TAU * p)) :- samplerate(hz), duration(s), range(i, 0, hz * s, 1), t = i / hz, pitch(p).sample() then becomes a wavetable.
challenge: also generate wavetables for pitch 220 and 880. how would you do it?
-
@aeva say we generate a sample of a sine with:
samplerate(44100).
duration(0.5).
pitch(440).
sample(i, sin(t * TAU * p)) :- samplerate(hz), duration(s), range(i, 0, hz * s, 1), t = i / hz, pitch(p).sample() then becomes a wavetable.
challenge: also generate wavetables for pitch 220 and 880. how would you do it?
@lritter am i doing it right
-
@aeva now do it for 120 pitches.
-
@aeva now do it for 120 pitches.
@lritter I already did it for 1000 the other month https://github.com/Aeva/mollytime/blob/457a7df7fee8e2e5a6b6cdf8d070fc0228b7c109/mollytime/screens/common.py#L79
-
@lritter I already did it for 1000 the other month https://github.com/Aeva/mollytime/blob/457a7df7fee8e2e5a6b6cdf8d070fc0228b7c109/mollytime/screens/common.py#L79
@aeva want to know how i do it in my little example?
-
@aeva want to know how i do it in my little example?
@lritter yes
-
@aeva
samplerate(44100).
duration(0.5).
pitch(hz) :- range(p, 0, 10, 1/12), hz = pow(2, p).
sample(p, i, sin(t * TAU * p)) :- samplerate(hz), duration(s), range(i, 0, hz * s, 1), t = i / hz, pitch(p). -
@aeva
samplerate(44100).
duration(0.5).
pitch(hz) :- range(p, 0, 10, 1/12), hz = pow(2, p).
sample(p, i, sin(t * TAU * p)) :- samplerate(hz), duration(s), range(i, 0, hz * s, 1), t = i / hz, pitch(p).@lritter :- s
-
@lritter ...... i don't get it ;_;
-
@aeva hehe. now if i wanted to extend dimensions and also have multiple samplerates, i could do the same again, without making any changes to the implementation of sample(). "i need more than 1 of this" is the simplest task here.