├── LICENSE ├── README.md ├── sample.cpp ├── README_JAPANESE.md └── wav_file_reader.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KanijiroSakado 4 | https://twitter.com/kanijiro_sakado 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WavFileReader 2 | A simple and easy C++ single-header library for loading WAV files. 3 | 4 | ## What You Can Do with This 5 | * Loading PCM data as single channel or multi channels 6 | * Loading data from a random point in file 7 | * Getting WAV format information of file 8 | 9 | ## How To Use 10 | 1. Include `wav_file_reader.h`. 11 | 1. Create `sakado::WavFileReader` object and use `Read()` function to read data from WAV files. 12 | 13 | The way of using it is very similar to `fread()` function in C language. 14 | ``` 15 | #include"wav_file_reader.h" 16 | 17 | void example() { 18 | unsigned char buf[44100]; 19 | sakado::WavFileReader wfr("test.wav"); 20 | 21 | wfr.Read(buf, 44100); 22 | 23 | return; 24 | } 25 | ``` 26 | Contained class member public functions are as follows. 27 | 28 | * `Read()` 29 | * `ReadLR()` 30 | * `Seek()` 31 | * `Tell()` 32 | 33 | See `sample.cpp` for more details. 34 | 35 | ## Note 36 | * Supported WAV format are 8bit and 16bit. 37 | * `Read()` function accepts several different data types. Convenient. 38 | * Second arg of `Read()` function is not a size of the data but a count of elements of the data. 39 | * The loaded data will be automatically converted and rescaled from signed 16bit to unsigned 8bit by `Read()` function ONLY WHEN the WAV format is 16bit and the prepared buffer is 8bit. 40 | * `Read()` function automatically averages left and right channels if the format is Stereo. You can use `ReadLR()` function if you want to load channels separately. 41 | * `Read()` function returns (the total number of samples successfully read)/(NumChannels). Use it to check EOF. 42 | * `WavFileReader()` constructor throws WFRException object defined in `wav_file_reader.h` when some exception occured. 43 | * `Seek()` function returns the same value as `fseek()` function in `stdio.h` or `cstdio`. 44 | -------------------------------------------------------------------------------- /sample.cpp: -------------------------------------------------------------------------------- 1 | #include"wav_file_reader.h" 2 | #include 3 | 4 | 5 | void example() { 6 | 7 | unsigned char buf[44100]; 8 | 9 | sakado::WavFileReader wfr("test.wav"); 10 | 11 | //Load first 44100 samples to buf 12 | //Be aware that second arg is not a size but a count of elements 13 | //Loaded values will be (L+R)/2 if the WAV format is Stereo Channels 14 | wfr.Read(buf, 44100); 15 | 16 | //Load next 44100 samples to buf 17 | wfr.Read(buf, 44100); 18 | 19 | return; 20 | } 21 | 22 | 23 | void advanced_example() { 24 | 25 | //The performance will be the best if the second arg of the constructor is set to the same value as which is used when loading 26 | //The arg is related to the size of the internal buffer 27 | sakado::WavFileReader wfr("test.wav",1000); 28 | 29 | //You can also load left and right data separately 30 | //If the format is Mono, same values will be loaded to bufL and bufR 31 | unsigned char bufL[1000]; 32 | unsigned char bufR[1000]; 33 | 34 | wfr.ReadLR(bufL, bufR, 1000); 35 | 36 | //You can use WavFileReader.Seek() function like fseek() function in stdio.h or cstdio 37 | //The first arg is not a bytes-based size but a samples-based size 38 | //If the format is Stereo, the file pointer will jump to (first arg)*2 samples ahead 39 | wfr.Seek(5000, SEEK_CUR); 40 | 41 | //Tell() function is almost same as ftell() function in C language. 42 | //Return value is sample-based as Seek() function. 43 | int v0 = wfr.Tell(); 44 | 45 | //Read() function and ReadLR() function has several overloads 46 | //unsigned char, signed short, int, double, float are available 47 | int bufInt[1000]; 48 | double bufDouble[1000]; 49 | 50 | wfr.Read(bufInt, 1000); 51 | wfr.Read(bufDouble, 1000); 52 | 53 | //You can access to some format information 54 | int v1 = wfr.NumChannels; 55 | int v2 = wfr.SampleRate; 56 | int v3 = wfr.BitsPerSample; 57 | int v4 = wfr.DataSize;//Total size of data 58 | int v5 = wfr.NumData;//Total number of samples(if Stereo, L and R samples are counted as 1) 59 | 60 | return; 61 | } 62 | 63 | 64 | int main(void) { 65 | 66 | //This prgram only do loading data from file 67 | //So nothing exciting will happen 68 | example(); 69 | advanced_example(); 70 | 71 | return 0; 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /README_JAPANESE.md: -------------------------------------------------------------------------------- 1 | みなさんWAVファイルを読み込みたくなる時、ありますよね。
2 | そんな時にわざわざ自分でファイルを解析するプログラムを書くのは面倒だと思いませんか?単に基本的なフォーマット情報や波形を読み込みたいだけなら、C++から使えるこの`WavFileReader`がお手軽です!シングルヘッダライブラリとなっていますのでヘッダファイルをインクルードするだけで使うことができます。えっ?用意するバッファのデータ型やチャンネル数を元ファイルのWAVフォーマットに合わせるのが面倒くさい?大丈夫。適当にメモリを用意しておけば、読み込まれるデータはとりあえず音声データとしての形が破綻しないよう自動的に変換してくれます。**そう、この`WavFileReader`ならね**(詳細は後述太字部)。本ReadMeではこれの使い方をざっくりと説明いたします。ただし対応している形式は非圧縮リニアPCMの8bitと16bitのみであり、24bitには対応していないことにご注意ください。~~また、可読性はユーザビリティとかパフォーマンスとかの犠牲になったのでヘッダファイルの中身は覗かないでください。~~ 3 | 4 | 5 | # 1. ヘッダをインクルードする 6 | https://github.com/KanijiroSakado/WavFileReader 7 | githubからWavFileReaderのリポジトリをcloneもしくはダウンロードし、その中にある`wav_file_reader.h`をこのライブラリを使用したいファイルの先頭でインクルードしてください。 8 | 9 | ```C++ 10 | #include"wav_file_reader.h" 11 | ``` 12 |    13 | # 2. `WavFileReader`のインスタンスを作る 14 | 15 | ```C++ 16 | sakado::WavFileReader wfr("test.wav"); 17 | ``` 18 | 作ってください。名前空間`sakado`をお忘れなく。読み込むファイルもここで指定してください。 19 |    20 | # 3. `Read()`関数でPCMデータを読み込む 21 | `template unsigned int Read(Type *buf, unsigned int count);` 22 | 23 | 読み込むPCMデータを格納する配列を用意してください。その配列の先頭ポインタを第一引数に渡し、第二引数には読み込みたいサンプルの個数を渡します。 24 | 25 | これで第一引数の配列には第二引数で指定された個数ぶんのサンプルが格納されます。C言語の`fread()`関数のような感じです。次のサンプルが読み込みたければ`fread()`と同様にもう一度`Read()`関数を呼べば次のデータが格納されます。 26 | 27 | ```C++ 28 | unsigned char buf[44100]; 29 | wfr.Read(buf, 44100);//最初の44100サンプルを読み込み 30 | wfr.Read(buf, 44100);//次の44100サンプルを読み込み 31 | ``` 32 | 33 | ここで注意して頂きたいのは**WAVファイルのフォーマットがステレオの場合は、左右のデータが自動的に平均された値が配列に格納される**ということです。左右のデータを別々に取得したい場合は[後述](#readlr関数)する`ReadLR()`関数を使用してください。 34 | 35 | `Read()`関数はテンプレート関数になっているため、第一引数には配列ポインタとして`unsigned char*`型以外にも`int*`型、`short*`型、`long*`型、`double*`型、`float*`型が受け取れます。それ以外の型を渡すとエラーになります。 36 | 37 | 基本的に読み込んだデータは数値としては加工されずにそのまま配列に格納されます。しかし**読み込み先が`16bit`で受け取り先が`8bit`の場合のみ例外で、そのままでは溢れてしまうので値は自動的に`8bit`に変換されて格納されます**。上記の例の場合でも`unsigned char*`型で受け取っているので、読み込みファイルのフォーマットが`16bit`の場合にはこれが発動します。 38 |    39 | # 4. コード全体 40 | 以上が最も基本的な使い方です。コードの全体図を以下に示します。 41 | 42 | ```C++ 43 | #include"wav_file_reader.h" 44 | 45 | int main(void) { 46 | 47 | sakado::WavFileReader wfr("test.wav"); 48 | unsigned char buf[44100]; 49 | 50 | wfr.Read(buf, 44100);//最初の44100サンプルを読み込み 51 | wfr.Read(buf, 44100);//次の44100サンプルを読み込み 52 | 53 | return 0; 54 | } 55 | ``` 56 | 簡単ですね。 57 |    58 | # 5. おまけ 59 | 細かい機能の説明をします。 60 |
61 | 62 | ### __WAVフォーマット情報__ 63 | 64 | インスタンス変数により取得可能です。 65 | 66 | ```C++ 67 | int v1 = wfr.NumChannels; 68 | int v2 = wfr.SampleRate; 69 | int v3 = wfr.BitsPerSample; 70 | int v4 = wfr.DataSize;//データの総サイズ 71 | int v5 = wfr.NumData;//データの総サンプル数(ステレオの場合は左右のセットで1つと数えます) 72 | ``` 73 |
74 | 75 | ### __`WavFileReader()`コンストラクタ__ 76 | 77 | `WavFileReader(const char* filename);` 78 | `WavFileReader(const char* filename, unsigned int numPrimaryBuf);` 79 | 80 | 速度面のパフォーマンスを最大限に発揮したいという方は、以下のように第二引数に自分が後にRead()関数の第二引数として使用する値と同じ値またはそれより大きな値を指定してください。これはインスタンス内部で確保されるメモリの大きさに関係します。なので無駄に大きすぎるのも良くないでしょう。 81 | 82 | ```C++ 83 | sakado::WavFileReader wfr("test.wav",44100); 84 | ``` 85 | また、このコンストラクタはファイルが存在しないなどの例外の場合に`wav_file_reader.h`内で定義されている`WFRException`オブジェクトをスローします。 86 |
87 | 88 | ### __`Read()`関数__ 89 | `template unsigned int Read(Type *buf, unsigned int count);` 90 | 91 | [上](#3-read関数でpcmデータを読み込む)でだいたい説明しました。戻り値は`fread()`関数と同じく読み込みに成功したサンプル数です。通常は第二引数と同じ値が返ります。 92 |
93 | 94 | ### __`ReadLR()`関数__ 95 | `template unsigned int ReadLR(Type *bufL, Type *bufR, unsigned int count);` 96 | 97 | `Read()`関数とだいたい同じですが、違う点は配列のポインタを2つ受け取るところです。`bufL`に左のPCMデータ、`bufR`に右のPCMデータがそれぞれ`count`個ずつ格納されます。**読み込み先がモノラルデータの場合は2つの配列には同じ値が格納されます**。この関数も`Read()`関数と同様に第一引数に`unsigned char*`以外の型を受け取れます。扱える型の種類も先程[上](#3-read関数でpcmデータを読み込む)で挙げた`Read()`関数と同様です。 98 | 99 | 戻り値は読み込みに成功したサンプル数です。左右のセットで1つのサンプル数とカウントします。通常は第三引数と同じ値です。 100 | 101 | ```C++ 102 | unsigned char bufL[1000]; 103 | unsigned char bufR[1000]; 104 | 105 | wfr.ReadLR(bufL, bufR, 1000); 106 | ``` 107 |
108 | 109 | ### __`Seek()`関数__ 110 | `int Seek(long offset, int origin);` 111 | 112 | C言語の`fseek()`関数とだいたい同じですが、`offset`に指定する値は移動するデータサイズではなくサンプル数です。読み込み先がステレオの場合は`offset`*2サンプル先に進むことになります。 113 | 114 | `wav_file_reader`ヘッダ内で`cstdio`をインクルードしているので`origin`には`SEEK_CUR`、`SEEK_SET`、`SEEK_END`が使えます。 115 | 116 | 戻り値は成功で0、失敗で0以外です。 117 | 118 | ```C++ 119 | wfr.Seek(5000, SEEK_CUR); 120 | ``` 121 |
122 | 123 | ### __`Tell()`関数__ 124 | `unsigned long Tell(void);` 125 | 126 | C言語の`ftell()`関数のようなものです。戻り値は読み込んでいるファイルの現在の読み込み位置です。戻り値の単位は例によってデータサイズではなくサンプル数であることに注意してください。読み込み先がステレオの場合は左右のセットで1サンプルと数えます。 127 | 128 | ```C++ 129 | unsigned int v0 = wfr.Tell(); 130 | ``` 131 | -------------------------------------------------------------------------------- /wav_file_reader.h: -------------------------------------------------------------------------------- 1 | #ifdef SAKADO_WAV_FILE_READER_H 2 | #else 3 | #define SAKADO_WAV_FILE_READER_H 4 | 5 | #ifdef _MSC_VER 6 | #pragma warning(disable:4996)//Without this, Visual Studio throws warnings that suggests to use fopen_s() instead of fopen() 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | namespace sakado { 18 | 19 | class WFRException :public std::exception {}; 20 | 21 | class WFRFileOpenException :public WFRException { 22 | const char* what(void) const noexcept { 23 | return "File Open Failed"; 24 | } 25 | }; 26 | 27 | class WFRFileValidityException :public WFRException { 28 | const char* what(void) const noexcept { 29 | return "Invalid File"; 30 | } 31 | }; 32 | 33 | class WFRSupportedFormatException :public WFRException { 34 | const char* what(void) const noexcept { 35 | return "Unsupported format"; 36 | } 37 | }; 38 | 39 | 40 | template struct ReadFunctionArgumentTypeValidation; 41 | template<> struct ReadFunctionArgumentTypeValidation {}; 42 | template<> struct ReadFunctionArgumentTypeValidation {}; 43 | template<> struct ReadFunctionArgumentTypeValidation {}; 44 | template<> struct ReadFunctionArgumentTypeValidation {}; 45 | template<> struct ReadFunctionArgumentTypeValidation {}; 46 | template<> struct ReadFunctionArgumentTypeValidation {}; 47 | 48 | 49 | class WavFileReader { 50 | 51 | public: 52 | unsigned long FmtSize; 53 | unsigned short FmtID; 54 | unsigned short NumChannels; 55 | unsigned long SampleRate; 56 | unsigned long BytesPerSec; 57 | unsigned short BlockAlign;//(bytes per sample)*(channels) 58 | unsigned short BitsPerSample; 59 | unsigned long DataSize; 60 | unsigned short BytesPerSample; 61 | unsigned long NumData; 62 | 63 | 64 | WavFileReader(string filename) { 65 | numPrimaryBuf = 65536;//default 66 | WavFileReaderPrivate(filename.c_str()); 67 | } 68 | 69 | 70 | WavFileReader(string filename, unsigned int numPrimaryBuf) { 71 | this->numPrimaryBuf = numPrimaryBuf; 72 | WavFileReaderPrivate(filename.c_str()); 73 | } 74 | 75 | 76 | WavFileReader(const WavFileReader&obj) { 77 | 78 | *this = obj; 79 | 80 | fp = fopen(obj.filename, "rb"); 81 | if (fp == NULL) { 82 | throw WFRFileOpenException(); 83 | } 84 | fseek(fp, ftell(obj.fp), SEEK_SET); 85 | 86 | primaryBuf = (unsigned char*)malloc(obj.BytesPerSample * obj.numPrimaryBuf * obj.NumChannels); 87 | ucharp = (unsigned char*)primaryBuf; 88 | shortp = (signed short*)primaryBuf; 89 | } 90 | 91 | 92 | ~WavFileReader() { 93 | fclose(fp); 94 | free(primaryBuf); 95 | } 96 | 97 | 98 | void PrintHeader() { 99 | 100 | printf("format size= %d\nformat ID = %d\nchannels = %d\nsampling rate = %d\nbytes per sec = %d\nblock align = %d\nbits per sample = %d\ndata size = %d\n" 101 | , FmtSize, FmtID, NumChannels, SampleRate, BytesPerSec, BlockAlign, BitsPerSample, DataSize); 102 | 103 | return; 104 | } 105 | 106 | 107 | template unsigned int Read(Type *buf, unsigned int count) { 108 | 109 | unsigned int readCnt, numSuccess, numDone = 0,leftToRead; 110 | 111 | sizeof(ReadFunctionArgumentTypeValidation); 112 | //If you have a compiler error here, then the type of the first argument of Read function is illegal 113 | //Available types are [unsigned char*, int*, short*, long*, double*, float*] 114 | 115 | leftToRead = count; 116 | 117 | if ((NumChannels == 1 && BitsPerSample == 16 && sizeof(Type) == sizeof(short)) || 118 | (NumChannels == 1 && BitsPerSample == 8 && sizeof(Type) == sizeof(unsigned char))) 119 | { 120 | numSuccess = fread(buf, BytesPerSample, leftToRead, fp); 121 | wavFilePointer += numSuccess; 122 | return numSuccess; 123 | } 124 | 125 | 126 | if (wavFilePointer + leftToRead > NumData)leftToRead = NumData - wavFilePointer; 127 | readCnt = numPrimaryBuf * NumChannels; 128 | 129 | while (leftToRead > 0) { 130 | 131 | if (leftToRead < numPrimaryBuf) { 132 | readCnt = leftToRead * NumChannels; 133 | leftToRead = 0; 134 | } 135 | else { 136 | leftToRead -= numPrimaryBuf; 137 | } 138 | 139 | numSuccess = fread(primaryBuf, BytesPerSample, readCnt, fp) / NumChannels; 140 | if (numSuccess < readCnt) leftToRead = 0; 141 | 142 | ArrangeReadData(buf, numSuccess); 143 | numDone += numSuccess; 144 | 145 | } 146 | wavFilePointer += numDone; 147 | return numDone; 148 | } 149 | 150 | 151 | template unsigned int ReadLR(Type *bufL, Type *bufR, unsigned int count) { 152 | 153 | unsigned int readCnt, numSuccess, numDone = 0,leftToRead; 154 | 155 | sizeof(ReadFunctionArgumentTypeValidation); 156 | //If you have a compiler error here, then the type of the first argument of ReadLR function is illegal 157 | //Available types are [unsigned char*, int*, short*, long*, double*, float*] 158 | 159 | leftToRead = count; 160 | 161 | if ((NumChannels == 1 && BitsPerSample == 16 && sizeof(Type) == sizeof(short)) || 162 | (NumChannels == 1 && BitsPerSample == 8 && sizeof(Type) == sizeof(unsigned char))) 163 | { 164 | numSuccess = fread(bufL, BytesPerSample, leftToRead, fp); 165 | memcpy(bufR, bufL, numSuccess * BytesPerSample); 166 | wavFilePointer += numSuccess; 167 | return numSuccess; 168 | } 169 | 170 | if (wavFilePointer + leftToRead > NumData)leftToRead = NumData - wavFilePointer; 171 | readCnt = numPrimaryBuf * NumChannels; 172 | 173 | while (leftToRead > 0) { 174 | 175 | if (leftToRead < numPrimaryBuf) { 176 | readCnt = leftToRead * NumChannels; 177 | leftToRead = 0; 178 | } 179 | else { 180 | leftToRead -= numPrimaryBuf; 181 | } 182 | 183 | numSuccess = fread(primaryBuf, BytesPerSample, readCnt, fp) / NumChannels; 184 | if (numSuccess < readCnt) leftToRead = 0; 185 | 186 | ArrangeReadLRData(bufL, bufR, numSuccess); 187 | numDone += numSuccess; 188 | 189 | } 190 | wavFilePointer += numDone; 191 | return numDone; 192 | } 193 | 194 | 195 | int Seek(long offset, int origin) { 196 | if (origin == SEEK_SET)wavFilePointer = 0; 197 | if (origin == SEEK_END)wavFilePointer = NumData - 1; 198 | if ((long)wavFilePointer < (-1) * offset) { 199 | fseek(fp, (-1) * wavFilePointer * BlockAlign, origin); 200 | wavFilePointer = 0; 201 | return 1; 202 | } 203 | if ((unsigned long)(wavFilePointer + offset) > NumData) { 204 | fseek(fp, (NumData - wavFilePointer)*BlockAlign, origin); 205 | wavFilePointer = NumData; 206 | return 1; 207 | } 208 | wavFilePointer += offset; 209 | return fseek(fp, BlockAlign*offset, origin); 210 | } 211 | 212 | 213 | unsigned long Tell() { 214 | return wavFilePointer; 215 | } 216 | 217 | 218 | private: 219 | FILE* fp; 220 | unsigned int numPrimaryBuf;//count of general purpose buf = total buf size / BlockAlign 221 | void *primaryBuf; 222 | unsigned long wavFilePointer; 223 | unsigned char *ucharp; 224 | signed short *shortp; 225 | char filename[256]; 226 | 227 | void WavFileReaderPrivate(const char*filename) { 228 | 229 | char ch[5]; 230 | unsigned int size,i;//chunk size 231 | 232 | i = 0; 233 | while (filename[i] != '\0'&&i < 255) { 234 | this->filename[i] = filename[i]; 235 | i++; 236 | } 237 | this->filename[i] = '\0'; 238 | 239 | fp = fopen(filename, "rb"); 240 | if (fp == NULL) { 241 | throw WFRFileOpenException(); 242 | } 243 | 244 | fread(ch, 1, 4, fp); 245 | ch[4] = '\0'; 246 | if (strcmp(ch, "RIFF")) { 247 | fclose(fp); 248 | throw WFRFileValidityException(); 249 | } 250 | 251 | fseek(fp, 4, SEEK_CUR); 252 | fread(ch, 1, 4, fp); 253 | ch[4] = '\0'; 254 | if (strcmp(ch, "WAVE")) { 255 | fclose(fp); 256 | throw WFRFileValidityException(); 257 | } 258 | 259 | fseek(fp, 4, SEEK_CUR); 260 | fread(&FmtSize, 4, 1, fp); 261 | fread(&FmtID, 2, 1, fp); 262 | fread(&NumChannels, 2, 1, fp); 263 | fread(&SampleRate, 4, 1, fp); 264 | fread(&BytesPerSec, 4, 1, fp); 265 | fread(&BlockAlign, 2, 1, fp); 266 | fread(&BitsPerSample, 2, 1, fp); 267 | fseek(fp, FmtSize - 16, SEEK_CUR); 268 | fread(ch, 1, 4, fp); 269 | while (strcmp(ch, "data")) { 270 | if (fread(&size, 4, 1, fp) != 1) { 271 | fclose(fp); 272 | throw WFRFileValidityException(); 273 | } 274 | fseek(fp, size, SEEK_CUR); 275 | fread(ch, 1, 4, fp); 276 | } 277 | fread(&DataSize, 4, 1, fp); 278 | BytesPerSample = BitsPerSample / 8; 279 | NumData = DataSize / BlockAlign; 280 | 281 | if (BitsPerSample != 8 && BitsPerSample != 16) { 282 | fclose(fp); 283 | throw WFRSupportedFormatException(); 284 | } 285 | 286 | if (NumChannels != 1 && NumChannels != 2) { 287 | fclose(fp); 288 | throw WFRFileValidityException(); 289 | } 290 | 291 | wavFilePointer = 0; 292 | 293 | primaryBuf = (unsigned char*)malloc(BytesPerSample * numPrimaryBuf * NumChannels); 294 | ucharp = (unsigned char*)primaryBuf; 295 | shortp = (signed short*)primaryBuf; 296 | 297 | return; 298 | } 299 | 300 | 301 | template void ArrangeReadData(Type *&buf, unsigned int numSuccess) { 302 | 303 | unsigned int i; 304 | 305 | if (NumChannels == 1 && BitsPerSample == 8) { 306 | for (i = 0; i < numSuccess; i++) { 307 | *(buf++) = ucharp[i]; 308 | } 309 | } 310 | else if (NumChannels == 1 && BitsPerSample == 16) { 311 | 312 | switch (sizeof(Type)) { 313 | case sizeof(unsigned char) : 314 | for (i = 0; i < numSuccess; i++) 315 | *(buf++) = (unsigned long)((long)shortp[i] + 0x8000) >> 9; 316 | break; 317 | default: 318 | for (i = 0; i < numSuccess; i++) 319 | *(buf++) = shortp[i]; 320 | } 321 | } 322 | else if (NumChannels == 2 && BitsPerSample == 8) { 323 | 324 | switch (sizeof(Type)) { 325 | case sizeof(unsigned char) : 326 | for (i = 0; i < numSuccess; i += 2) 327 | *(buf++) = ((unsigned long)ucharp[i] + (unsigned long)ucharp[i + 1]) >> 1; 328 | break; 329 | default: 330 | for (i = 0; i < numSuccess; i += 2) 331 | *(buf++) = ((long)ucharp[i] + (long)ucharp[i + 1]) / 2; 332 | } 333 | } 334 | else if (NumChannels == 2 && BitsPerSample == 16) { 335 | 336 | switch (sizeof(Type)) { 337 | case sizeof(unsigned char) : 338 | for (i = 0; i < numSuccess; i += 2) 339 | *(buf++) = (unsigned long)((long)shortp[i] + (long)shortp[i + 1] + 0x10000) >> 9; 340 | break; 341 | default: 342 | for (i = 0; i < numSuccess; i += 2) 343 | *(buf++) = ((long)shortp[i] + (long)shortp[i + 1]) / 2; 344 | } 345 | } 346 | } 347 | 348 | 349 | template void ArrangeReadLRData(Type *&bufL, Type *&bufR, unsigned int numSuccess) { 350 | 351 | unsigned int i; 352 | 353 | if (NumChannels == 1 && BitsPerSample == 8) { 354 | 355 | for (i = 0; i < numSuccess; i++) { 356 | *(bufL++) = ucharp[i]; 357 | *(bufR++) = ucharp[i]; 358 | } 359 | } 360 | else if (NumChannels == 1 && BitsPerSample == 16) { 361 | 362 | switch (sizeof(Type)) { 363 | case sizeof(unsigned char) : 364 | for (i = 0; i < numSuccess; i++) { 365 | *(bufL++) = (unsigned long)((long)shortp[i] + 0x8000) >> 8; 366 | *(bufR++) = (unsigned long)((long)shortp[i] + 0x8000) >> 8; 367 | } 368 | break; 369 | default: 370 | for (i = 0; i < numSuccess; i++) { 371 | *(bufL++) = shortp[i]; 372 | *(bufR++) = shortp[i]; 373 | } 374 | } 375 | } 376 | else if (NumChannels == 2 && BitsPerSample == 8) { 377 | 378 | for (i = 0; i < numSuccess; i += 2) { 379 | *(bufL++) = ucharp[i]; 380 | *(bufR++) = ucharp[i + 1]; 381 | } 382 | } 383 | else if (NumChannels == 2 && BitsPerSample == 16) { 384 | 385 | switch (sizeof(Type)) { 386 | case sizeof(unsigned char) : 387 | for (i = 0; i < numSuccess; i += 2) { 388 | *(bufL++) = ((long)shortp[i] + 0x8000) >> 8; 389 | *(bufR++) = ((long)shortp[i + 1] + 0x8000) >> 8; 390 | } 391 | break; 392 | default: 393 | for (i = 0; i < numSuccess; i += 2) { 394 | *(bufL++) = shortp[i]; 395 | *(bufR++) = shortp[i + 1]; 396 | } 397 | } 398 | } 399 | } 400 | 401 | }; 402 | 403 | 404 | } 405 | 406 | 407 | #endif 408 | --------------------------------------------------------------------------------