IOCCC image by Matt Zucker

The International Obfuscated C Code Contest

2013/endoh3 - Most tweetable one liner

play music with ABC notation

Author:

To build:

    make

Bugs and (Mis)features:

The current status of this entry is:

STATUS: INABIAF - please DO NOT fix

For more detailed information see 2013/endoh3 in bugs.html.

To use:

    ./endoh3

This program plays sound. See the FAQ on “compile with sound” if you do not know how to set your system up for this or if you want to verify that everything is oky.

Try:

    ./try.sh

    ./try.sh ABC

    ./try.sh test.abc yankee.abc

    ./try.sh *.abc

The script will check for SoX first and next padsp from PulseAudio and finally if neither are found if you have ruby(1) installed it’ll use the included ruby script to convert it to a WAV file for you to play.

If no args are passed to the script it will play twinkle.abc and the string ABC. Otherwise while there’s a remaining arg if it’s a file it will run the program on the file. If it’s not a file it’ll run it as a string.

The *.abc files are provided as music samples.

Judges’ remarks:

This program can toot out a tune that is small enough to posted to most social media platforms that have small message length limits.

This endoh3ram can toot out a tune that is small enough.

A modern day (2023) note about the award ‘Most tweetable 1-liner’ and twitter:

The IOCCC no longer endorses the use of what was once twitter, or whatever it might be called today. We recommend that you pick a responsible social media platform to post the program’s output on. Nevertheless the award of this entry will remain the same for historical purposes.

Author’s remarks:

Remarks

This is a sound synthesizer for a subset of ABC music notation.

Try:

    cc -o endoh3 endoh3.c
    echo "CDEFGABc" | ./endoh3 > /dev/dsp

If /dev/dsp is not available on your system, use an OSS sound wrapper such as padsp or aoss:

    echo "CDEFGABc" | ./endoh3 | padsp tee /dev/dsp > /dev/null

If you are using Mac OS X, try sox like so:

    echo "CDEFGABc" | ./endoh3 | sox -q -traw -r8000 -b8 -e unsigned-integer - -tcoreaudio

If that does not work, use the attached script to convert the output into a wave file format:

    echo "CDEFGABc" | ./endoh3 | ruby wavify.rb > cde.wav

and play cde.wav.

You can also enjoy some music scores that I attached. With /dev/dsp you can do so like:

    cat twinkle.abc | ./endoh3 > /dev/dsp
    cat menuet.abc | ./endoh3 > /dev/dsp

but you should be able to modify it a way to meet your system requirements as described above.

Obfuscation

The following sequence of questions may be helpful to understand the endoh3ram program:

Limitation

The following features are supported:

The following features are NOT supported:

Known Bugs

You can NOT write a note length immediately followed by a note E, such as C2E2.

Can you figure out why?

A workaround is inserting a whitespace: C2 E2.

Portability

I tested it on:

I believe that all the scores that I attached are out-of-copyright.

I did write a score of the Happy Birthday song too. (It does not matter because the song is out-of-copyright in my country.) But I do not attach it to protect you from W****r.

For the same reason, do not post a score that contains only z1092. You know, it is “the famous song”.

NOTICE to those who wish for a greater challenge:

If you want a greater challenge, don’t read any further: just try to understand the program via the source.

If you get stuck, come back and read below for additional hints and information.

How this entry works:

Here is a magical expression which I found by brute-force:

    (c % 32 + 5) * 9 / 5 % 13 + n / 32 * 12 - 22

Interestingly, it converts an ASCII number of ABC notes to the corresponding tone number.

    'C' (ASCII  67) =>  3
    'D' (ASCII  68) =>  5
    'E' (ASCII  69) =>  7
    'F' (ASCII  70) =>  9
    'G' (ASCII  71) => 10
    'A' (ASCII  65) => 12
    'B' (ASCII  66) => 14
    'c' (ASCII  99) => 15
    'd' (ASCII 100) => 17
    'e' (ASCII 101) => 19
    'f' (ASCII 102) => 20
    'g' (ASCII 103) => 22
    'a' (ASCII  97) => 24
    'b' (ASCII  98) => 26

By the way, you can write a half-tone by the following characters.

    'K' =>  4 (= C#)
    'L' =>  6 (= D#)
    'U' =>  8 (= F#)
    'V' => 11 (= G#)
    'P' => 13 (= A#)

Note that the tone numbers simply enumerate the semi-tone steps. So we can calculate the frequency easily: pow(2, n / 12.0). Then, how can we calculate pow without math.h? pow(2, 1.0 / 12.0) is approximated by 89/84.. (I found this approximation by using the Stern-Brocot tree.) We can gain the frequency by multiplying the value by n times.

Finally, the following code generates a saw wave:

    for(c = 0; c < len; c++) putchar(a = n * D);

where D is a frequency and a is a variable whose type is char. By assigning float to char variable, the implicit type conversion is performed from float to char (modulo 256).

(Strictly speaking, this behavior is undefined according to 6.3.1.4 in C99; you can replace it with (long)(n*D) if you are pedantic.)

All that was left was to combine and condense the components. The key is squashing them into just one for-loop.

Inventory for 2013/endoh3

Primary files

Secondary files


Jump to: top