Robert Elder Software Inc.
  • Home
  • Store
  • Blog
  • Contact
  • Home
  • Store
  • Blog
  • Contact
  • #linux
  • |
  • #commandline
  • |
  • #softwareengineering
  • |
  • #embeddedsystems
  • |
  • #compilers
  • ...
  • View All >>

Bash One Liner - Compose Music From Entropy in /dev/urandom

2016-03-04 - By Robert Elder

Last Updated Dec 12, 2019:  Fixed an off by one error (awk uses 1-based arrays!).

The Command

cat /dev/urandom | hexdump -v -e '/1 "%u\n"' | awk '{ split("0,2,4,5,7,9,11,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i)) }' | xxd -r -p | aplay -c 2 -f S32_LE -r 16000

The above command was tested on Ubuntu 14.04.  You should hear music play through your speakers.

Updated March 6:  I only expected this to work on Ubuntu, but you can read the comments to find audio clips and versions of the command that people have created for Mac:

/r/programming

/r/coding

/r/linux

Explanation

The first part of the pipe

cat /dev/urandom

prints the contents of /dev/urandom to stdout.  If you're a level 500 elite hacker like I am, you will note that the cryptographic quality of numbers from /dev/urandom is not the same as numbers from /dev/random.  In our case, we don't want this operation to block, so we use /dev/urandom.  See 'man 4 random'. (Updated March 6: In addition to the man page, see 1, 2)

Since the output of /dev/urandom is random binary bytes, we can use hexdump to format it into nice integers from 0-255:

hexdump -v -e '/1 "%u\n"'

Here is a sample of the output from hexdump:

cat /dev/urandom  | hexdump -v -e '/1 "%u\n"' | head
135
16
156
54
115
156
116
20
59
191

The -v flag gets rid of the hexdump's default behaviour of replacing repeated lines with a '*' character.  The -e flag uses '/1 "%u\n"' to print out the binary byte as an a formatted decimal number.

These integers in the range of 0-255 are then passed into awk, one line at a time:

awk '...'

The ... part is the following small program:

split("0,2,4,5,7,9,11,12",a,",");
for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i))

The line

split("0,2,4,5,7,9,11,12",a,",");

creates an array 'a' which encodes the relative number of semitones from the base note in a major musical scale.  This array is useful in the print statement because the frequency in Hertz of a musical note with equal temperament can be calculated using the following formula: 440 * 2^(semitone distance / 12).  440Hz has arbitrarily been chosen as the reference note, and it represents the frequency of A4.

The for loop then prints formatted 4 byte hexadecimal numbers that represent the amplitude of the sound wave at a given point in time:

printf("%08X\n", 100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i))

The formula

100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i)

Can be broken down as follows:

100 #  A scalar multiple used to control the volume.
*
sin(
        1382 #  =~ 440 * 3.14159
        *
        exp(  #  Awk doesn't seem to support arbitrary powers, so we use 2^x = e^(x*ln(2))
                (
                        #  NOTE: awk uses 1-based indexing...
                        a[$1%8+1]  #  Pick a semitone at random on the major scale
                        /
                        12  #  Divide by 12 per the formula
                )
                *
                log(2)
        )
        *
        i  # The counter in the for loop that counts from 0 to 1
)

The amount of time that each note is played for can be controlled by changing how fast the for loop counts up to 1.  This number will also affect the perceived frequency.

The above formula makes a bit more sense if you think about it in the following way.  If you did

for (i = 0; i < 1; i+= 0.0001) sin(i * 3.14159);

This will just calculate values on one cycle of a sine curve.  If you then multiply 'i' by a frequency X of a musical note, each iteration of the for loop will calculate points on the X cycles of notes of the given frequency so the amplitude will change faster than the original 1 cycle per completion of the for loop.

The next part of the pipe uses xxd to convert the 8 byte hexadecimal values back into binary:

xxd -r -p

Which is then fed into aplay and turned into audible sound:

aplay -c 2 -f S32_LE -r 16000

Sad Music

If you want to make the music sound sad, you can change from the major scale to a minor scale:

cat /dev/urandom | hexdump -v -e '/1 "%u\n"' | awk '{ split("0,2,3,5,7,8,10,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i)) }' | xxd -r -p | aplay -c 2 -f S32_LE -r 16000
The Fast Meme Transform: Convert Audio Into Linux Commands
The Fast Meme Transform: Convert Audio Into Linux Commands
Published 2018-02-10
Terminal Block Mining Simulation Game
$1.00 CAD
Terminal Block Mining Simulation Game
A Surprisingly Common Mistake Involving Wildcards & The Find Command
A Surprisingly Common Mistake Involving Wildcards & The Find Command
Published 2020-01-21
A Guide to Recording 660FPS Video On A $6 Raspberry Pi Camera
A Guide to Recording 660FPS Video On A $6 Raspberry Pi Camera
Published 2019-08-01
The Most Confusing Grep Mistakes I've Ever Made
The Most Confusing Grep Mistakes I've Ever Made
Published 2020-11-02
Use The 'tail' Command To Monitor Everything
Use The 'tail' Command To Monitor Everything
Published 2021-04-08
An Overview of How to Do Everything with Raspberry Pi Cameras
An Overview of How to Do Everything with Raspberry Pi Cameras
Published 2019-05-28
An Introduction To Data Science On The Linux Command Line
An Introduction To Data Science On The Linux Command Line
Published 2019-10-16
Join My Mailing List
Privacy Policy
Why Bother Subscribing?
  • Free Software/Engineering Content. I publish all of my educational content publicly for free so everybody can make use of it.  Why bother signing up for a paid 'course', when you can just sign up for this email list?
  • Read about cool new products that I'm building. How do I make money? Glad you asked!  You'll get some emails with examples of things that I sell.  You might even get some business ideas of your own :)
  • People actually like this email list. I know that sounds crazy, because who actually subscribes to email lists these days, right?  Well, some do, and if you end up not liking it, I give you permission to unsubscribe and mark it as spam.
© 2025 Robert Elder Software Inc.
SocialSocialSocialSocialSocialSocialSocial
Privacy Policy      Store Policies      Terms of Use