Haskellの憎き ...
女房が安売りしてたと言う、パセリを山のように買ってきた。一山80円だったとか。 本当に山のようにと言うか、大きな杉玉ぐらいあるやつだ。こんなにあるなら、 パセリが主役な料理って無いものか? 早速、調査を命じられましたよ。
料理するならクックパッドで調べてみたけど、この80円玉 を1回で使い切る事が出来そうなものは見つからなかった。ええ、それで、責任取って 、塩を振りかけながら食べましたとも。余ったものは、家で一番大きいタッパーに ギュウギュウ詰めにして、冷凍庫に保管されました。
どうでもいい事だけど、このサイトRailsで構築されてるとか、サーバーは Mongrel 1.1.5 だそうです。
Haskellの憎き ...
そうなんです。以前からの宿題にしていた、音ファイルの解析なんですが、プログラム を書き始めたのはいいのですが、躓いています。
そう、IO a と言う奴に阻まれて、さっぱり前へ進めません。勉強不足は認めますが すらすらと進まないと、気持ちが萎えます。今回は音ファイルと言う事で、バイナリーを 扱う事になりますんで、資料が乏しいのも一因かも知れません。
このあたりをじっくり見て手を 動かしながらですかね。それともProgramming in Haskell で、やり直しでしょうか?
Gaucheで書いて、元気になろう
柔軟で、いろいろな便利機能が取り込まれている、gaucheなら 自由奔放?に書ける だろう。で、書いてみた。
(use binary.io) (use binary.pack) (use util.match) (define sound-file "/home/sakae/wave/onVMWARE") ;(define sound-file "/home/sakae/wave/fromWin") (define M '()) ; For Mono (define L '()) ; For Stereo Left (define R '()) ; For Stereo Right (define (makeM fp func n) (dotimes (i n) (set! M (cons (func fp) M))) (set! M (reverse M))) (define (makeS fp func n) (dotimes (i n) (set! L (cons (func fp) L)) (set! R (cons (func fp) R))) (set! L (reverse L)) (set! R (reverse R))) (define (getV temp fp pos) (port-seek fp pos SEEK_SET) (car (unpack temp :input fp))) (define (wave-info file) (let* ([fp (open-input-file file)] [ms (if (= 1 (getV "s" fp 22)) 'Mono 'Stereo)] ; Mono or Stereo [hz (getV "i" fp 24)] ; Sampling Freq [bit(getV "s" fp 34)] ; 8 or 16Bit [size (if (string=? "data" (getV "A4" fp 36)) ; Data size in Byte (getV "l" fp 40) (getV "l" fp 54))]) (format #t "~a ~a ~a ~a\n" ms hz bit size) (match (cons ms bit) [('Stereo . 16) (makeS fp read-s16 (/ size 4))] [('Stereo . 8) (makeS fp read-s8 (/ size 2))] [('Mono . 16) (makeM fp read-s16 (/ size 2))] [('Mono . 8) (makeM fp read-s8 size)]) (close-input-port fp)))
ファイルのmagicは面倒なので、見てません。エラーチェックもさぼってます。 Haskellやってて、schemeにもあればいいなあと思っていたパターンマッチ機能、 shiroさんはちゃんと用意してくれてました。infoをあちこち読んでたら、Haskell から輸入しましたって機能が他にも有り、ああ、nobsunの影響かな、と。 rubyにも、こういう面白い事やってる方が おられるのね。メアドからドイツの人っぽいけど。
gosh> (wave-info sound-file) Mono 22050 16 441000 #<undef> gosh> (length M) 220500 gosh> (apply max M) 16422 gosh> (apply min M) -16423 gosh> (use srfi-1) #<undef> gosh> (length (filter (lambda (v) (> v 10000)) M)) 3877 gosh> (length (memv 0 M)) 211175
大体、動いてるっぽい。後は、解析用の関数を書いていくだけだな。
おまけ
上記の例では、サンプリング周波数が、22050Hz(周期にすると45.3マイクロ秒)で 行われている。やけに半端な周波数だなあ。しかも、これが業界の標準規格だそうだ。 音本によると、この規格は、ビデオテープに音データを記録する装置の開発から生まれたとの事。
ビデオテープは、525本の走査線x30フレームの構成になっている。この525本の走査線 から、490本を選び、1走査線内に3回のサンプリングデータを記録する事にしたそうな。 そうすると、
3 x 490 x 30 = 44.1KHz
これが、CDの場合のサンプリング周波数にも流用されたとか。22050Hzは、CDほど 音質が良くなくてもいいべと某連合が寄り集まって決めた。(CD音質の半分です。)
パソコンで、モスキート音は、ちゃんと録音・再生出来るのだろうか? 勿論、音 カードを入れれば大丈夫でしょうが。そういう投資をしない場合??かなあ。
まあ、私の場合、耳のf特が落ちてますから、無理ですが。。。