もっともツイート可能なワンライナー
引用元:https://www.ioccc.org/2013/endoh3/endoh3.c
審査員・作者による説明:https://www.ioccc.org/2013/endoh3/index.html
次のように実行する。
$ gcc -o endoh3 endoh3.c
$ echo 'CDEFGABc' | ./endoh3 | ruby wavify.rb > cde.wav
cde.wavを再生すると、ドレミファソラシドが流れる。 音量に注意。
きらきら星。
$ cat twinkle.abc | ./endoh3 | ruby wavify.rb > twinkle.wav
$ cat menuet.abc | ./endoh3 | ruby wavify.rb > menuet.wav
ABC記譜法のサブセットから音楽データを合成する。
対応している機能は次の通り。
CからB(低いオクターブ)、cからb(高いオクターブ)zAで8分音符、A2で4分音符、A3で付点4分音符、A4で2分音符。楽譜データのパースはscanf(" %c%f")で行う。
音符を音程に変えるのは、ブルートフォースで見つけた次の式。
(a % 32 + 5) * 9 / 5 % 13 + a / 32 * 12 - 22
音符のASCIIコードをaに入れてこの式を計算すると、次のように音程の数字が得られる。
'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シャープやフラットの記法(^Cや_C)には対応していないが、次の文字で音を出すことは可能。
'K' → 4 (= C#)'L' → 6 (= D#)'U' → 8 (= F#)'V' → 11 (= G#)'P' → 13 (= A#)この音程の数字に対してpow(2, n / 12.0)を計算すれば周波数が得られる。
しかしpowは使えないので、pow(2, 1 / 12.0) ≒ 89/84.0をn回掛けることで算出する。
そして、次の計算で出力を行う。
for(c = 0; c < 音符の長さに相当する回数; c++) putchar(a = c * D);
aはchar型の変数、Dが周波数、cはカウンタ。
aに代入することで、D * cを256で割った余りになるので、のこぎり波が出力されることになる。
以上の処理を1つのfor文で行うことで実現されている。
細かいことだが、scanf(" %c%f")でパースする都合上、C2E2とは書けない。
2e2が浮動小数点数リテラルとみなされるため。
C2 E2のようにスペースをあけば回避できる。
賞名の"tweetable"は、「さえずる」という意味と、Twitterにツイート可能という意味を重ねている。 当時のTwitterの文字数制限(140文字)に収まるコードなので。