リニアPCMのWAVファイルを読み込む
wavファイルを読み込む簡単なC++のクラスを書いた。バイナリファイルを構造体定義とfreadで一気に読み込む方法は始めて知った。なんて楽なんだ。
参考urlのデータ読み出し手順の例を読んでいる限り、タグの現れる順番は予め決まっているわけではないようだ。factとかいうタグ情報もあるみたいだけどもう眠いので明日以降読む。
参考:http://www.kk.iij4u.or.jp/~kondo/wave/
実行結果
winsowsXPのsystem32フォルダにあるLoopyMusic.wavとBuzzingBee.wavを読みこませた。
$ a LoopyMusic.wav | expand --tabs=12 size 940794 rate 44100 bits 16 ch 1 data bytes 940750 duration 10.67sec $ a BuzzingBee.wav | expand --tabs=12 size 146650 rate 22050 bits 16 ch 1 data bytes 146606 duration 3.32sec
ソース
/* * wavファイルの読み込み * 参考:http://www.kk.iij4u.or.jp/~kondo/wave/ */ #include<cstdlib> #include<iostream> #include<string> #include<stdexcept> using namespace std; typedef struct { uint32_t id; // "fmt " uint32_t bytes; // fmtチャンクのバイト数 uint16_t formatID; // フォーマットID uint16_t channels; // チャンネル数 uint32_t rate; // サンプリングレート uint32_t velocity; // データ速度 uint16_t blocksize;// ブロックサイズ uint16_t bits; // 量子化ビット数 //uint16_t extension; // 拡張部分のサイズ (リニアPCMならば存在しない) // 拡張部分 (extension bytes) } fmtChunk; typedef struct { uint32_t id; // "data" uint32_t bytes; // 波形データのバイト数 } dataChunk; typedef struct { uint32_t riffID; // "riff" uint32_t size_8; // ファイルサイズ-8 uint32_t wavID; // "WAVE" fmtChunk fmtchunk; dataChunk datachunk; } wavFileHeader; class WAVReader { wavFileHeader header; string filePath; uint8_t *raw; // 波形データ bool load(){ FILE *fp = fopen(filePath.c_str(), "r"); if (!fp){ perror("WAV::load"); exit(1); } fread((void*)&header, sizeof(header), 1, fp); size_t rawbytes = header.datachunk.bytes; raw = new uint8_t[rawbytes]; // 波形データの読み込み //fread((void*)raw, sizeof(rawbytes), 1, fp); // 修正2009/09/26 fread((void*)raw, rawbytes, 1, fp); fclose(fp); } public: WAVReader(const char* path){ filePath = path; load(); } WAVReader(const string& path){ filePath = path; load(); } ~WAVReader(){ delete[] raw; } size_t size(){ return header.size_8 + 8; }; unsigned int bitrate(){ return header.fmtchunk.rate; }; unsigned int bits(){ return header.fmtchunk.bits; } unsigned int channels(){ return header.fmtchunk.channels; }; unsigned int dataBytes(){ return header.datachunk.bytes; }; }; int main(int argc, char** argv) { if (argc < 2){ fprintf(stderr, "usage: %s wavfilepath\n", argv[0]); return 0; } WAVReader wav(argv[1]); const char* desc[] = {"size", "rate", "bits", "ch", "data bytes", ""}; unsigned int val[] = {wav.size(), wav.bitrate(), wav.bits(), wav.channels(), wav.dataBytes()}; for (int i = 0; desc[i][0] != '\0'; i++) printf("%s\t%u\n", desc[i], val[i]); // 再生時間 float duration = ((float)wav.dataBytes() / (wav.bits() / 8) / wav.channels()) / wav.bitrate(); printf("duration\t%.2fsec\n", duration); return 0; }