Rで、Matlab互換のwavreadが欲しかったのだけど、いろいろ探しても3ch以上のファイルに対応したものがなかったので、しょうがなく自分で作ってみた。これで5.1chのファイルもいじれる。
source("wavread.R") x <- wavread("filename.wav")
とするとfilename.wavという名前のWAVファイルが読み込まれる。source()はwavread関数を使えるようにするための文なので、一回だけやっておけばOK。
その後、画面に波形を表示したければ
plot(x$time, x$data[,1], type="l")
参考にしたのは『WAVプログラミング―C言語で学ぶ音響処理』と、以前、本家Microsoftから入手したフォーマット規格書。規格書はWotsitからリンクがあったはず。
コードは以下。バグ等あるかもしれないけど責任持たないのでよろしくー(24bitのWAVが読み込めないかもしれない)。いつかwavwriteも作りますが、writeの方がほんのちょっとだけ面倒くさいんだよね。
wavread <- function(filename) { ## open connection to the file con <- file(filename, open="rb") ## check if the file is canonical WAV file if (readChar(con, nchars=4, useBytes=TRUE) != "RIFF") { close(con) stop(paste(filename, "is not a RIFF file.")) } size.riff <- readBin(con, integer(), 1) if (readChar(con, nchars=4, useBytes=TRUE) != "WAVE") { close(con) stop(paste(filename, "is not a WAVE file.")) } if (readChar(con, nchars=4, useBytes=TRUE) != "fmt ") { close(con) stop(paste(filename, "does not have a 'fmt ' chunk.")) } size.fmt <- readBin(con, integer(), 1, endian="little") ## read fmt chunk format.id <- readBin(con, what="raw", n=2, endian="little") if (prod(format.id != c(1, 0))) { close(con) stop(paste(filename, "has to be in Linear PCM format.")) } num.channels <- readBin(con, what="int", size=2, n=1, endian="little") fs <- readBin(con, integer(), n=1, endian="little") bps <- readBin(con, integer(), n=1, endian="little") block.size <- readBin(con, what="int", size=2, n=1, endian="little") nbits <- readBin(con, what="int", size=2, n=1, endian="little") if (bps != fs * nbits/8 * num.channels) { close(con) stop(paste(filename, "has something wrong in the 'fmt ' chunk.")) } ## skip ext chunk (if exists) chunk.name <- readChar(con, nchars=4, useBytes=TRUE) if (chunk.name == "ext ") { size.ext <- readBin(con, integer(), 1, endian="little") skip.ext <- readBin(con, what="raw", size.ext) } ## read data chunk if (chunk.name != "data") { close(con) stop(paste(filename, "does not have a 'data' chunk.")) } size.data <- readBin(con, integer(), 1, endian="little") data <- readBin(con, what="int", size=nbits/8, size.data) / (2^(nbits-1)) data <- matrix(data, ncol=num.channels, byrow=TRUE) ## close connection to the file close(con) ## time in seconds t <- (seq(max(dim(data)))-1) / fs return(list(data=data, fs=fs, nbit=nbits, nch=num.channels, time=t)) }