Bitwise
Background:
While looking for Arduino projects to build I found the Algorithmic Noise Machine. I was instantly intrigued by the noises it generated using bitwise operations.
Looking further I realized that Supercollider added support for bitwise operators in v3.5. Unfortunately the only documentation was a single example (quoted below).
// 8-bit magic
(
play {
var t = PulseCount.ar(Impulse.ar(8e3));
HPF.ar(
(
((t * 15) & (t >> 5)) |
((t * 5) & (t >> [3, 4])) |
((t * 2) & (t >> 9)) |
((t * 8) & (t >> 11))
- 3 % 256
) / 127-1 * 3
, 20
).tanh
}
)
I decided to explore the concept a to understand how bitwise operations work on an audio signal. My examples are written in Supercollider but much of this could be applied to other audio languages.
Other Concepts:
Before we get into the bitwise operators I figured we should talk about three basic concepts used in the code above.

(
{
i = Impulse.ar(2e3);
t = PulseCount.ar(i);
[i, t, t % 8]
}.plot()
)- Impulse - Sends out single sample pulses at the frequency specified. This is often used to trigger other Ugens.
- PulseCount - Outputs a number that is incremented each time it receives a trigger. In the plot above notice the steady ascent from 0 to 20.
- Modulo % - The remainder from a division operation. Very useful to “wrap” a number into a certain range. Notice in the plot above how the numbers count from 0 to 7 and then repeat.
Bitwise Operations:
Bitwise operators are used to manipulate numbers directly at the bit level. A bit has only 2 possible values, 1 or 0 (True or False). If you need a refresher on binary numbers I recommend this tutorial.
- AND & - Result is true only if both bits are true. ex. 9 & 3 = 1
00001001 = 9
00000011 = 3
00000001 = 1
Notice how the result only contains true bits that both numbers have in common. - OR | - Result is true if either bit is true. ex. 9 | 3 = 11
00001001 = 9
00000011 = 3
00001011 = 11
Notice how the result contains all the true bits from both numbers. - Bitshift Right >> - Move all bits right the number of digits specified on the righthand side of the equation. ex. 100 >> 2 = 25
01100100 = 100
00011001 = 25
Notice that between the two numbers the pattern of digits is the same, they have simply shifted two places to the right. - Bitshift Left << - Move all bits left the number of digits specified on the righthand side of the equation. ex. 31 <<2 = 124
00011111 = 31
01111100= 124
Notice that between the two numbers the pattern of digits is the same, they have simply shifted two places to the left.
Re-examining The Example:
Now that you understand the basic operations you can look at the middle section of the code as a complicated formula to generate values. The results of this formula are run through a 20 Hz highpass filter to remove excessive bass and a tanh to shape the output. I have put this formula into a function and created a loop to output the values produced using the numbers 1 thru 100 as an input:
(
f = {|t|
(
((t * 15) & (t >> 5)) |
((t * 5) & (t >> [3, 4])) |
((t * 2) & (t >> 9)) |
((t * 8) & (t >> 11))
- 3 % 256
) / 127-1 * 3
};
(1..100).do({|i|f.(i).postln});
)A Simpler Example:
The formula is still pretty complicated so I tried to make a simpler example to understand why it sounds the way it does:

(
{
var t = PulseCount.ar(Impulse.ar(8e3));
a = (t * 15);
b = (t >> 3);
c = a & b;
c % 256;
}.play
)
Breaking this down into it’s pieces:
- a = (t * 15); - value that is incrementing by 15. (ex. 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150)
- b = (t >> 3); - incrementing value with a bitshift right 3 places applied. (ex. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)
- c = a & b; - apply a bitwise AND to both previous values. (ex. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)
- c % 256; - this keeps the numbers from incrementing infinity and forms the basis of the repeating pattern.
Why does it form a sawtooth shape?
- The result of an AND operation will never be larger than the smaller of the inputs.
- A bitshift right will always produce a smaller number.
- Based on the previous two points variable b will always be much smaller than a and will control the rate at which the numbers increase.
- The modulo operation will “wrap” the numbers around instead of letting them rise infinitely, thus performing a repeating pattern.
Closing Thoughts:
Bitwise operations are capable of complex and chaotic rhythms, a little bit of knowledge about them will help you to bend these patterns to your will.
Further Reading:
A comment suggested this paper as further reading on the topic.hyenaanna liked this
adamferriss liked this
functime liked this
meghusn liked this ma101jl-blog said: Interesting post. The origins of the ‘Bytebeat’ genre are described in this paper, might be an interesting read if you aren’t already aware of it. arxiv.org/pdf/111…
vividsnow liked this
schemawound posted this