Experimental music from very short C programs
category: code [glöplog]
Qqwy: That's interesting! Is it possible to apply your low pass filter to one of the bytebeat equations? If so, can you post an example? I'd be very interested in learning about this!
Here's another few equations:
((((t*(t*(((t%[1442,3344,4434,5533,4444,44455,33333,3443][(t>>14)%8])))/((t*[455,4,445,4700,0,0,0,3334][(t>>16)%8])/(t<<2))))%2)<<5 | (((Math.sqrt(t%16384)<<5)&64) *[1,0,0,0,0,1,0,0][(t>>14)%8]>>1) | ((t*[22, -14, 108, 2, -80, -99, 62, -62, -11, -127, -102, -80, -114, -66, -2, 68, -63, -101, 0, -13, 37, 55, 104, 61, 125, 101, -54, 60, -91, -102, -127, 17, 26, -23, -97, 80, 43, -77, 117, -71, 66, -59, 30, -86, 111, 112, 65, -49, 85, -95, 38, 27, -39, 80, 94, 44, 20, 116, 36, -74, -106, -57, 57, 96, -37, 39, -72, 21, -80, 121, -127, 88, -84, 54, 120, -6, -94, 41, -41, -22][t%77])&58)*[0,0,1,0,0,0,1,0][(t>>13)%8] | (t*220/t)*[1,0][(t>>13)%2]))
Here's a minimal one:
(((t>>2)|((t>>7)&(t<<7)/(t*(t>>12)%8))))>>2
And a similar one with a progression:
((t>>6)&(t<<3)/(t*(t>>11)%(3+((t>>16)%22))))
Here's another few equations:
((((t*(t*(((t%[1442,3344,4434,5533,4444,44455,33333,3443][(t>>14)%8])))/((t*[455,4,445,4700,0,0,0,3334][(t>>16)%8])/(t<<2))))%2)<<5 | (((Math.sqrt(t%16384)<<5)&64) *[1,0,0,0,0,1,0,0][(t>>14)%8]>>1) | ((t*[22, -14, 108, 2, -80, -99, 62, -62, -11, -127, -102, -80, -114, -66, -2, 68, -63, -101, 0, -13, 37, 55, 104, 61, 125, 101, -54, 60, -91, -102, -127, 17, 26, -23, -97, 80, 43, -77, 117, -71, 66, -59, 30, -86, 111, 112, 65, -49, 85, -95, 38, 27, -39, 80, 94, 44, 20, 116, 36, -74, -106, -57, 57, 96, -37, 39, -72, 21, -80, 121, -127, 88, -84, 54, 120, -6, -94, 41, -41, -22][t%77])&58)*[0,0,1,0,0,0,1,0][(t>>13)%8] | (t*220/t)*[1,0][(t>>13)%2]))
Here's a minimal one:
(((t>>2)|((t>>7)&(t<<7)/(t*(t>>12)%8))))>>2
And a similar one with a progression:
((t>>6)&(t<<3)/(t*(t>>11)%(3+((t>>16)%22))))
Oops,
Here are links for those last 2:
(((t>>2)|((t>>7)&(t<<7)/(t*(t>>12)%8))))>>2
((t>>6)&(t<<3)/(t*(t>>11)%(3+((t>>16)%22))))
Here are links for those last 2:
(((t>>2)|((t>>7)&(t<<7)/(t*(t>>12)%8))))>>2
((t>>6)&(t<<3)/(t*(t>>11)%(3+((t>>16)%22))))
Great stuff!
Hmm... I'm not sure. The Filter depends on the usage of floating-point values. It might be possible to convert it to interger math by multiplying all values before and dividing them after the equation.
I'm not really sure how floating-point values are handled by Wurstcaptures, native C and other bytebeat implementations.
However, converting a function from Bytebeat(range 0..256) to Floatbeat(range -1..1) is trivial: (bytebeat_expression%256)/127-1
Hmm... I'm not sure. The Filter depends on the usage of floating-point values. It might be possible to convert it to interger math by multiplying all values before and dividing them after the equation.
I'm not really sure how floating-point values are handled by Wurstcaptures, native C and other bytebeat implementations.
However, converting a function from Bytebeat(range 0..256) to Floatbeat(range -1..1) is trivial: (bytebeat_expression%256)/127-1
Bytebeat FTW. I'd like to share some of my explorations in a shape of a formula. The language is not C though, but JS (ES5 FTW!) and my simplified bytebeat engine (available here) is hardcoded to generate 8Khz mono 8-bit PCM (and outputs ready-to-use data: URI, I might add).
So, here is the general view of how to generate discrete notes in a compact JS bytebeat expression:
Don't pay much attention to .35 in t*.35 - this is some fine tuning to get notes sound as they should (I was a pianist so I hate when A is not close to 440 Hz :) ) for this very sawtooth wave case.
[Speed] is... well, the speed, starting from 1.
[notes_pattern] is your notes string (just a moment), and [notes_count] it just the length of this string.
-11 is the real deal. It was selected with trial-and-error in order to fit as many notes into printable (and typable!) low-ASCII characters as possible.
So, what's the note range? It's actually a bit more than 2 octaves of full chromatic scale:
1st octave: #$&()+-/1368
2nd octave: ;=AEGKOSW[ae
3rd octave: kow
As you know, any musical engine should allow to enter the rest character. Unfortunately, it can only be entered as \013 sequence here. That's the price for such an extended note range in such a simple formula, but... not a big deal, really.
This plays all the available notes:
And this plays the interleaved major scale, making a rest after each note:
So, I think you've got the point. Everything else depends on the initial tuning and your imagination. :)
So, here is the general view of how to generate discrete notes in a compact JS bytebeat expression:
Code:
t*.35*("[notes_pattern]".charCodeAt(t*[speed]/8e3%[notes_count])-11)
Don't pay much attention to .35 in t*.35 - this is some fine tuning to get notes sound as they should (I was a pianist so I hate when A is not close to 440 Hz :) ) for this very sawtooth wave case.
[Speed] is... well, the speed, starting from 1.
[notes_pattern] is your notes string (just a moment), and [notes_count] it just the length of this string.
-11 is the real deal. It was selected with trial-and-error in order to fit as many notes into printable (and typable!) low-ASCII characters as possible.
So, what's the note range? It's actually a bit more than 2 octaves of full chromatic scale:
1st octave: #$&()+-/1368
2nd octave: ;=AEGKOSW[ae
3rd octave: kow
As you know, any musical engine should allow to enter the rest character. Unfortunately, it can only be entered as \013 sequence here. That's the price for such an extended note range in such a simple formula, but... not a big deal, really.
This plays all the available notes:
Code:
t*.35*("#$&()+-/1368;=AEGKOSW[aekow".charCodeAt(t/1e3%27)-11)
And this plays the interleaved major scale, making a rest after each note:
Code:
t*.35*("#\013;\013&\013A\013)\013G\013+\013K\013/\013S\0133\013[\0138\013e\013;\013k\013".charCodeAt(t/1e3%32)-11)
So, I think you've got the point. Everything else depends on the initial tuning and your imagination. :)
Oops... plz remove all the whitespace in the last code snippet (I have absolutely no idea how it appeared there).
This all sound Dead Horsey
p01, how much is the fi... I meant, how wide is the range?
Btw,
Maybe wurstcaptures is feature-rich, but from my UX, it's too slow, glitchy and too serverside-dependent.
BeatM-based (8KHz with math) pure-HTML5 bytebeat player is coming soon. As for now, let me announce the StackBeat esoteric language fir this entire purpose. It also has a bookmarklet version.
Maybe wurstcaptures is feature-rich, but from my UX, it's too slow, glitchy and too serverside-dependent.
BeatM-based (8KHz with math) pure-HTML5 bytebeat player is coming soon. As for now, let me announce the StackBeat esoteric language fir this entire purpose. It also has a bookmarklet version.
The Dead Horse approach looks like this:
The frequency range is determined by the const and the initial ASCII range. This means 32 to 127 if you limit yourself to the printable characters, Hence this approach goes from a frequency X to a frequency 127 / 32 * X.
It's up to you to fiddle with the const to position your frequency range.
Code:
oscillator += ASCII_CODE / const
The frequency range is determined by the const and the initial ASCII range. This means 32 to 127 if you limit yourself to the printable characters, Hence this approach goes from a frequency X to a frequency 127 / 32 * X.
It's up to you to fiddle with the const to position your frequency range.
Okay. I'm not talking of frequency range. I'm talking of the semitones range. Not every set of numbers among these 127 can form a consistent chromatic scale of several octaves. That's what I tried to do. 27 semitones is the limit I could pull out of the printable ASCII set. That's why frequency range doesn't really matter here: the notes aren't distributed evenly. The higher they get, the sparser they become.
they are related; a 4x frequency range = 2 octaves. Why did you ask if you knew the answer? :p
I was in doubt.
Anyway, Fort Boyard OST melody:
Could anyone suggest a method for adding drum line to it? How to mix different lines in 8KHz bytebeat at all?
Code:
t*.17*("33AAAAA\013AAKKKGGG;;A\013AK[KSSSSSSSS\013\013[\013[SSSKKGGG;;;GGA\013AK[KAAAAAAAA".charCodeAt(t/1800%64)-11)
Could anyone suggest a method for adding drum line to it? How to mix different lines in 8KHz bytebeat at all?
(and remove all whitespace again in the code, I'm curious what the hell adds them to ready post)
interleaved a "bassline" here.
For now I managed to get only some crazy techno version.
But generally, my question was how to mix 2 independent formulas into one stream.
Shifted drums a little but the question stlll remains.
i guess it's like any other synth mixes waveforms. additive. multiplicative. ored. whatever. you gotta keep track of spectral shit to not loose alotta sound here and there.
Thanx, Cap. o_O
Are there any seamless mixing examples suitable for unsigned 8Khz case?
Are there any seamless mixing examples suitable for unsigned 8Khz case?
Hi Suborg,
That's a great description and formula! Very inspiring! Could you explain the \013? How does that convert into a rest?
I've just started working with these equations myself, and here's how I'm approaching drums. First, I use a pattern generator, like this: ((51871 >> ((t>>14)%16))&1)
To break that down:
51871 is decimal for 1100101010011111, which is my 16 step drum pattern in reverse.
I'm bit shifting that to the right at the speed of (t>>14) over and over again.
I'm ANDing the bit-shifted pattern by 1, is how I determine the step's value.
For a kick drum, I'm taking a sound that repeats every beat...
((Math.sqrt(t%16384)<<5)&64)
..and using my pattern generator to filter out the unwanted beats by multiplying them by the 1 or 0 from the pattern generator:
((Math.sqrt(t%16384)<<5)&64)*((51871 >> ((t>>14)%16))&1)
I also ran into trouble with mixing too. I've had some luck simply using a bitwise OR to join two or more sounds. Sounds like whitenoise tend to drown everything else out.
Awesome stuff.
- Bret
That's a great description and formula! Very inspiring! Could you explain the \013? How does that convert into a rest?
I've just started working with these equations myself, and here's how I'm approaching drums. First, I use a pattern generator, like this: ((51871 >> ((t>>14)%16))&1)
To break that down:
51871 is decimal for 1100101010011111, which is my 16 step drum pattern in reverse.
I'm bit shifting that to the right at the speed of (t>>14) over and over again.
I'm ANDing the bit-shifted pattern by 1, is how I determine the step's value.
For a kick drum, I'm taking a sound that repeats every beat...
((Math.sqrt(t%16384)<<5)&64)
..and using my pattern generator to filter out the unwanted beats by multiplying them by the 1 or 0 from the pattern generator:
((Math.sqrt(t%16384)<<5)&64)*((51871 >> ((t>>14)%16))&1)
I also ran into trouble with mixing too. I've had some luck simply using a bitwise OR to join two or more sounds. Sounds like whitenoise tend to drown everything else out.
Awesome stuff.
- Bret
Hi, thanx for your approach. The \013 converts to zero because its' actually 11 (just in octal notation), so when the formula meets \013 and subtracts 11 from the code 11, it renders no sound.
bartoshe: sounds better with seperation ;)
Telephone: t<<4|t>>6|t>>t