Author:
- Name: Yusuke Endoh
Location: JP - Japan
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:
- How does it convert ABC notes into the frequency?
- What is
89/84.
? I found it by using the Stern-Brocot tree. - How does it generate a wave? Hint: it generates a saw wave.
Limitation
The following features are supported:
- Notes:
C
D
E
F
G
A
B
(in low octave)c
d
e
f
g
a
b
(in high octave)
- Rests:
z
- Note lengths:
A
(an eighth note)A2
(a quarter note)A3
(a dotted quarter note)A4
(a half note)
The following features are NOT supported:
- Sharp and flat:
^C
_C
- But it is possible to emit the half tones. Do you see how?
- Shorter note lengths than 1:
C1/2
- But you can use
C0.5
instead.
- But you can use
- Higher and lower notes:
c'
C,
- Any meta fields:
T:title
L:1/4
- Bar line, repeat, ties and slurs, and everything else.
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:
- Ubuntu 13.10 with gcc 4.7.3, clang 3.2, and tcc 0.9.25.
- Mac OS X 10.6 with gcc 4.2.1 and clang 1.7.
Legal
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
- endoh3.c - entry source code
- Makefile - entry Makefile
- endoh3.orig.c - original source code
- flea-waltz.abc - sample input
- menuet.abc - sample input
- test.abc - sample input
- try.sh - script to try entry
- twinkle.abc - sample input
- wavify.rb - post process output to form a WAV sound file
- yankee.abc - sample input
Secondary files
- 2013_endoh3.tar.bz2 - download entry tarball
- README.md - markdown source for this web page
- .entry.json - entry summary and manifest in JSON
- .gitignore - list of files that should not be committed under git
- .path - directory path from top level directory
- index.html - this web page