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特が落ちてますから、無理ですが。。。