名曲です
サンプリングレートなどは動画中にあるので、自分のPCがWindowsであれば、同じDLLがあるのでwavファイルが作れるのでは?
WSLならシェル芸もできる!やったね。
やりかた
シェル芸でゴリッとする。
$ cat shell32.dll | xxd -ps | tr -d \\n | awk '{printf("echo %08x | fold -w2 | tac\n", length/2 + 8 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4); printf("echo %08x | fold -w2 | tac\n", length/2); print "echo "$0}' | sed '2iecho -n data | xxd -ps' | sed '2iprintf %04x 16 | fold -w2 | tac' | sed '2iprintf %04x $((16/8*2)) | fold -w2 | tac' | sed '2iprintf %08x $((8000*16/8*2)) | fold -w2 | tac' | sed '2iprintf %08x 8000 | fold -w2 | tac' | sed '2iprintf %04x 2 | fold -w2 | tac' | sed '2iprintf %04x 1 | fold -w2 | tac' | sed '2iprintf %08x 16 | fold -w2 | tac' | sed '2iecho -n WAVEfmt\\\ | xxd -ps' | sed '1iecho -n RIFF | xxd -ps' | sh | tr -d \\n | xxd -r -p > out.wav
上記のシェル芸が何をしているのかと言うと、バイナリにヘッダを追加しています。
概ねsh
に2回投げているので見通しが非常に悪いですが、sed
でコマンドを作って、sh
に渡しています。
詳細な説明は次のワンライナーのあとに解説します。
最初の sh
に投げる前までの出力の12行目までは以下になっています(13行目はデータ部で非常に長いため削っています)。
$ cat shell32.dll | xxd -ps | tr -d \\n | awk '{printf("echo %08x | fold -w2 | tac\n", length/2 + 8 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4); printf("echo %08x | fold -w2 | tac\n", length/2); print "echo "$0}' | sed '2iecho -n data | xxd -ps' | sed '2iprintf %04x 16 | fold -w2 | tac' | sed '2iprintf %04x $((16/8*2)) | fold -w2 | tac' | sed '2iprintf %08x $((8000*16/8*2)) | fold -w2 | tac' | sed '2iprintf %08x 8000 | fold -w2 | tac' | sed '2iprintf %04x 2 | fold -w2 | tac' | sed '2iprintf %04x 1 | fold -w2 | tac' | sed '2iprintf %08x 16 | fold -w2 | tac' | sed '2iecho -n WAVEfmt\\\ | xxd -ps' | sed '1iecho -n RIFF | xxd -ps' | head -n 12 echo -n RIFF | xxd -ps echo 0145d114 | fold -w2 | tac echo -n WAVEfmt\ | xxd -ps printf %08x 16 | fold -w2 | tac printf %04x 1 | fold -w2 | tac printf %04x 2 | fold -w2 | tac printf %08x 8000 | fold -w2 | tac printf %08x $((8000*16/8*2)) | fold -w2 | tac printf %04x $((16/8*2)) | fold -w2 | tac printf %04x 16 | fold -w2 | tac echo -n data | xxd -ps echo 0145d0f0 | fold -w2 | tac
それぞれのprintf
・echo
をsed
で追加しています。
なお、データ長が必要な部分はawk
を使用しています。
wav ヘッダのフォーマットは、次のページを参考にしました。
wav ファイルフォーマット
ワンライナーでは各フィールドを下から順に追加しているので、sh
に投げる前は 3フィールド目の'W' 'A' 'V' 'E'
部分から順に並んでいます。
fold -w 2 | tac
はエンディアンの変換を行っています。
sed
の i
コマンドで追加すると各フィールドごとにエンディアン変換ができるのが個人的に便利だと思っています。
結果
聞いてみるとバージョンが違うのか結構違う音が聞こえてきます。。。ただし、共通している部分もありbin -> wavの変換は上手くできているようです。
まとめ
これで好きなバイナリを音楽として聞く事ができますね!
整形
最初のワンライナーの整形版です。
はてなブログ上で作ってるので動くかは保証しかねます。雰囲気用です。
RATE=8000 # サンプリングレート CHANNELS=2 # モノラル=1,ステレオ=2 BIT_DEPTH=16 # ビット深度 (リニアPCM16bitの16で、データの単位のこと) cat shell32.dll \ | xxd -ps \ | tr -d \\n \ | awk '{ printf("echo %08x | fold -w2 | tac\n", length/2 + 8 + 4 + 2 + 2 + 4 + 4 + 2 + 2 + 4 + 4); printf("echo %08x | fold -w2 | tac\n", length/2); print "echo "$0 }' \ | sed '2iecho -n data | xxd -ps' \ | sed '2iprintf %04x '$BIT_DEPTH' | fold -w2 | tac' \ | sed '2iprintf %04x $(('$BIT_DEPTH'/8*'$CHANNELS')) | fold -w2 | tac' \ | sed '2iprintf %08x $(('$RATE'*'$BIT_DEPTH'/8*2)) | fold -w2 | tac' \ | sed '2iprintf %08x '$RATE' | fold -w2 | tac' \ | sed '2iprintf %04x '$CHANNELS' | fold -w2 | tac' \ | sed '2iprintf %04x 1 | fold -w2 | tac' \ | sed '2iprintf %08x 16 | fold -w2 | tac' \ | sed '2iecho -n WAVEfmt\\\ | xxd -ps' \ | sed '1iecho -n RIFF | xxd -ps' \ | sh \ | tr -d \\n \ | xxd -r -p > out.wav