├── dog_bark.wav ├── README.md ├── .gitattributes ├── .gitignore ├── Program.cs └── WAV_file.cs /dog_bark.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joaocarvalhoopen/WAV_Tools_C_Sharp/HEAD/dog_bark.wav -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WAV Tools C Sharp 2 | Code to read and write WAV files. 3 | 4 | Features supported: 5 | - 8 and 16 bits 6 | - Mono and Stereo 7 | - Examples of usage are given 8 | 9 | BSD Style license. 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Joao Nuno Carvalho 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | */ 14 | 15 | using System; 16 | using System.Collections.Generic; 17 | 18 | namespace WAV_Tools_C_Sharp 19 | { 20 | class Program 21 | { 22 | static void Main(string[] args) 23 | { 24 | Console.WriteLine("&&&&&&&&&&&&&&&&&&"); 25 | Console.WriteLine("&&& Wave Tools &&&"); 26 | Console.WriteLine("&&&&&&&&&&&&&&&&&&"); 27 | 28 | Console.WriteLine(); 29 | Console.WriteLine(">>>> BEGIN test01_ReadWriteWAVFile()"); 30 | test01_ReadWrite8BitsMonoWAVFile(); 31 | Console.WriteLine(">>>> END test01_ReadWriteWAVFile()"); 32 | Console.WriteLine(); 33 | 34 | Console.WriteLine(">>>> BEGIN test02_generate8BitsMono440HzWAVFile()"); 35 | test02_generate8BitsMono440HzWAVFile(); 36 | Console.WriteLine(">>>> END test02_generate8BitsMono440HzWAVFile()"); 37 | Console.WriteLine(); 38 | 39 | Console.WriteLine(">>>> BEGIN test03_generate16BitsMono440HzWAVFile()"); 40 | test03_generate16BitsMono440HzWAVFile(); 41 | Console.WriteLine(">>>> END test03_generate16BitsMono440HzWAVFile()"); 42 | Console.WriteLine(); 43 | 44 | Console.WriteLine(">>>> BEGIN test04_Read8BitsMonoWrite8bitsStereoWAVFile()"); 45 | test04_Read8BitsMonoWrite8bitsStereoWAVFile(); 46 | Console.WriteLine(">>>> END test04_Read8BitsMonoWrite8bitsStereoWAVFile()()"); 47 | Console.WriteLine(); 48 | 49 | Console.WriteLine(">>>> BEGIN test05_Read16BitsMonoWrite16bitsStereoWAVFile()"); 50 | test05_Read16BitsMonoWrite16bitsStereoWAVFile(); 51 | Console.WriteLine(">>>> END test05_Read16BitsMonoWrite16bitsStereoWAVFile()"); 52 | Console.WriteLine(); 53 | 54 | Console.WriteLine(">>>> BEGIN test06_ReadWrite8BitsStereoWAVFile()"); 55 | test06_ReadWrite8BitsStereoWAVFile(); 56 | Console.WriteLine(">>>> END test06_ReadWrite8BitsStereoWAVFile()"); 57 | Console.WriteLine(); 58 | 59 | Console.WriteLine(">>>> BEGIN test07_ReadWrite16BitsStereoWAVFile()"); 60 | test07_ReadWrite16BitsStereoWAVFile(); 61 | Console.WriteLine(">>>> END test07_ReadWrite16BitsStereoWAVFile()"); 62 | Console.WriteLine(); 63 | 64 | // Double Normalized Testes. 65 | Console.WriteLine(">>>> BEGIN test08_ReadWrite8BitsMono__double__WAVFile()"); 66 | test08_ReadWrite8BitsMono__double__WAVFile(); 67 | Console.WriteLine(">>>> END test08_ReadWrite8BitsMono__double__WAVFile()"); 68 | Console.WriteLine(); 69 | 70 | Console.WriteLine(">>>> BEGIN test09_ReadWrite16BitsMono__double__WAVFile()"); 71 | test09_ReadWrite16BitsMono__double__WAVFile(); 72 | Console.WriteLine(">>>> END test09_ReadWrite16BitsMono__double__WAVFile()"); 73 | Console.WriteLine(); 74 | 75 | Console.WriteLine(">>>> BEGIN test10_ReadWrite8BitsStereo__double__WAVFile()"); 76 | test10_ReadWrite8BitsStereo__double__WAVFile(); 77 | Console.WriteLine(">>>> END test10_ReadWrite8BitsStereo__double__WAVFile()"); 78 | Console.WriteLine(); 79 | 80 | Console.WriteLine(">>>> BEGIN test11_ReadWrite16BitsStereo__double__WAVFile()"); 81 | test11_ReadWrite16BitsStereo__double__WAVFile(); 82 | Console.WriteLine(">>>> END test11_ReadWrite16BitsStereo__double__WAVFile()"); 83 | Console.WriteLine(); 84 | } 85 | 86 | private static int test01_ReadWrite8BitsMonoWAVFile() 87 | { 88 | WAV_file my_wav_file = new WAV_file(); 89 | my_wav_file.File_name = "dog_bark.wav"; 90 | Console.WriteLine( "Nome: " + my_wav_file.File_name ); 91 | my_wav_file.Path = ".\\"; 92 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 93 | Console.WriteLine( "Path: " + my_wav_file.Path ); 94 | my_wav_file.loadFile(); 95 | Console.Write(my_wav_file.toWAVHeaderString()); 96 | 97 | System.Byte[] buffer_8_bits_Mono; 98 | uint numberOfSamples = (uint) my_wav_file.getBuffer_8_bits_mono( out buffer_8_bits_Mono); 99 | 100 | // Buffer processing. 101 | Console.WriteLine(); 102 | Console.WriteLine(); 103 | for (uint i = 0; i < numberOfSamples; i++) 104 | { 105 | // Console.Write( buffer_8_bits_Mono[i].toString() + "."); 106 | } 107 | Console.WriteLine(); 108 | Console.WriteLine(); 109 | 110 | // We are going to save the file on the hard drive with another name. 111 | my_wav_file.File_name = "test01_dog_bark_saved.wav"; 112 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 113 | my_wav_file.setBuffer_8_bits_mono(buffer_8_bits_Mono); 114 | my_wav_file.writeFile(); 115 | return 0; 116 | } // END 117 | 118 | private static int test02_generate8BitsMono440HzWAVFile() 119 | { 120 | WAV_file my_wav_file = new WAV_file(); 121 | my_wav_file.File_name = "test02_A440_8_Bits_Mono.wav"; 122 | Console.WriteLine("Nome: " + my_wav_file.File_name); 123 | my_wav_file.Path = ".\\"; 124 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 125 | Console.WriteLine("Path: " + my_wav_file.Path); 126 | 127 | const System.UInt32 C_SAMPLES_PER_SEC = 8000; 128 | const System.UInt32 C_TIME_SEC = 5; 129 | 130 | my_wav_file.BitsPerSample = WAV_file.BITS_PER_SAMPLE.BPS_8_BITS; 131 | my_wav_file.NumOfChannels = WAV_file.NUM_CHANNELS.ONE; 132 | my_wav_file.SampleRate = C_SAMPLES_PER_SEC; 133 | my_wav_file.NumberOfSamples = C_SAMPLES_PER_SEC * C_TIME_SEC; // 5 segundos 134 | 135 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 136 | 137 | System.Byte[] buffer_8_bits_Mono; 138 | // Allocate the memory for the buffer. 139 | my_wav_file.getBuffer_8_bits_mono(out buffer_8_bits_Mono); 140 | 141 | 142 | // Fills the buffer with a sinusoidal. 143 | float alphaAngle = 0; 144 | const System.UInt32 C_SIGNAL_FREQUENCY = 440; // 440 Hz La (A) 145 | for (uint i = 0; i < my_wav_file.NumberOfSamples; i++) 146 | { 147 | buffer_8_bits_Mono[i] = (System.Byte) ( ( (Math.Sin(alphaAngle) * (System.Byte.MaxValue / 2)) + (System.Byte.MaxValue / 2) ) ); 148 | alphaAngle += (2 * (float) (Math.PI) * C_SIGNAL_FREQUENCY) / C_SAMPLES_PER_SEC; 149 | } 150 | 151 | my_wav_file. setBuffer_8_bits_mono(buffer_8_bits_Mono); 152 | my_wav_file.writeFile(); 153 | return 0; 154 | } // END 155 | 156 | private static int test03_generate16BitsMono440HzWAVFile() 157 | { 158 | WAV_file my_wav_file = new WAV_file(); 159 | my_wav_file.File_name = "test03_A440_16_Bits_Mono.wav"; 160 | Console.WriteLine("Nome: " + my_wav_file.File_name); 161 | my_wav_file.Path = ".\\"; 162 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 163 | Console.WriteLine("Path: " + my_wav_file.Path); 164 | 165 | const System.UInt32 C_SAMPLES_PER_SEC = 8000; 166 | const System.UInt32 C_TIME_SEC = 5; 167 | 168 | my_wav_file.BitsPerSample = WAV_file.BITS_PER_SAMPLE.BPS_16_BITS; 169 | my_wav_file.NumOfChannels = WAV_file.NUM_CHANNELS.ONE; 170 | my_wav_file.SampleRate = C_SAMPLES_PER_SEC; 171 | my_wav_file.NumberOfSamples = C_SAMPLES_PER_SEC * C_TIME_SEC; // 5 segundos 172 | 173 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 174 | 175 | System.Int16[] buffer_16_bits_Mono; 176 | // Allocate the memory for the buffer. 177 | my_wav_file.getBuffer_16_bits_mono(out buffer_16_bits_Mono); 178 | 179 | 180 | // Fills the buffer with a sinusoidal. 181 | float alphaAngle = 0; 182 | const System.UInt32 C_SIGNAL_FREQUENCY = 440; // 440 Hz La (A) 183 | for (uint i = 0; i < my_wav_file.NumberOfSamples; i++) 184 | { 185 | buffer_16_bits_Mono[i] = (System.Int16) (Math.Round(Math.Sin(alphaAngle) * System.Int16.MaxValue)); 186 | alphaAngle += (2 * (float)(Math.PI) * C_SIGNAL_FREQUENCY) / C_SAMPLES_PER_SEC; 187 | } 188 | 189 | my_wav_file.setBuffer_16_bits_mono(buffer_16_bits_Mono); 190 | my_wav_file.writeFile(); 191 | return 0; 192 | } // END 193 | 194 | private static int test04_Read8BitsMonoWrite8bitsStereoWAVFile() 195 | { 196 | WAV_file my_wav_file = new WAV_file(); 197 | my_wav_file.File_name = "test02_A440_8_Bits_Mono.wav"; 198 | Console.WriteLine("Nome: " + my_wav_file.File_name); 199 | my_wav_file.Path = ".\\"; 200 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 201 | Console.WriteLine("Path: " + my_wav_file.Path); 202 | my_wav_file.loadFile(); 203 | Console.Write(my_wav_file.toWAVHeaderString()); 204 | 205 | System.Byte[] buffer_8_bits_Mono; 206 | uint numberOfSamples = (uint)my_wav_file.getBuffer_8_bits_mono(out buffer_8_bits_Mono); 207 | 208 | // Buffer processing. 209 | Console.WriteLine(); 210 | Console.WriteLine(); 211 | for (uint i = 0; i < numberOfSamples; i++) 212 | { 213 | // Console.Write( buffer_8_bits_Mono[i].toString() + "."); 214 | } 215 | Console.WriteLine(); 216 | Console.WriteLine(); 217 | 218 | // We are going to save the file on the hard drive with another name. 219 | my_wav_file.File_name = "test04_A440_8_Bits_Stereo.wav"; 220 | my_wav_file.NumOfChannels = WAV_file.NUM_CHANNELS.TWO; 221 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 222 | my_wav_file.setBuffer_8_bits_stereo(buffer_8_bits_Mono, buffer_8_bits_Mono); 223 | my_wav_file.writeFile(); 224 | return 0; 225 | } // END 226 | 227 | private static int test05_Read16BitsMonoWrite16bitsStereoWAVFile() 228 | { 229 | WAV_file my_wav_file = new WAV_file(); 230 | my_wav_file.File_name = "test03_A440_16_Bits_Mono.wav"; 231 | Console.WriteLine("Nome: " + my_wav_file.File_name); 232 | my_wav_file.Path = ".\\"; 233 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 234 | Console.WriteLine("Path: " + my_wav_file.Path); 235 | my_wav_file.loadFile(); 236 | Console.Write(my_wav_file.toWAVHeaderString()); 237 | 238 | System.Int16[] buffer_16_bits_Mono; 239 | uint numberOfSamples = (uint)my_wav_file.getBuffer_16_bits_mono(out buffer_16_bits_Mono); 240 | 241 | // Buffer processing. 242 | Console.WriteLine(); 243 | Console.WriteLine(); 244 | for (uint i = 0; i < numberOfSamples; i++) 245 | { 246 | // Console.Write( buffer_16_bits_Mono[i].toString() + "."); 247 | } 248 | Console.WriteLine(); 249 | Console.WriteLine(); 250 | 251 | // We are going to save the file on the hard drive with another name. 252 | my_wav_file.File_name = "test05_A440_16_Bits_Stereo.wav"; 253 | my_wav_file.NumOfChannels = WAV_file.NUM_CHANNELS.TWO; 254 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 255 | my_wav_file.setBuffer_16_bits_stereo(buffer_16_bits_Mono, buffer_16_bits_Mono); 256 | my_wav_file.writeFile(); 257 | return 0; 258 | } // END 259 | 260 | private static int test06_ReadWrite8BitsStereoWAVFile() 261 | { 262 | WAV_file my_wav_file = new WAV_file(); 263 | my_wav_file.File_name = "test04_A440_8_Bits_Stereo.wav"; 264 | Console.WriteLine("Nome: " + my_wav_file.File_name); 265 | my_wav_file.Path = ".\\"; 266 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 267 | Console.WriteLine("Path: " + my_wav_file.Path); 268 | my_wav_file.loadFile(); 269 | Console.Write(my_wav_file.toWAVHeaderString()); 270 | 271 | System.Byte[] buffer_8_bits_stereo_left; 272 | System.Byte[] buffer_8_bits_stereo_right; 273 | uint numberOfSamples = (uint)my_wav_file.getBuffer_8_bits_stereo(out buffer_8_bits_stereo_left, out buffer_8_bits_stereo_right); 274 | 275 | // Buffer processing. 276 | Console.WriteLine(); 277 | Console.WriteLine(); 278 | for (uint i = 0; i < numberOfSamples; i++) 279 | { 280 | // Console.Write( buffer_8_bits_stereo_left[i].toString() + "."); 281 | // Console.Write( buffer_8_bits_stereo_right[i].toString() + "."); 282 | 283 | } 284 | Console.WriteLine(); 285 | Console.WriteLine(); 286 | 287 | // We are going to save the file on the hard drive with another name. 288 | my_wav_file.File_name = "test06_A440_8_Bits_Stereo_saved.wav"; 289 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 290 | my_wav_file.setBuffer_8_bits_stereo(buffer_8_bits_stereo_left, buffer_8_bits_stereo_right); 291 | my_wav_file.writeFile(); 292 | return 0; 293 | } // END . 294 | 295 | private static int test07_ReadWrite16BitsStereoWAVFile() 296 | { 297 | WAV_file my_wav_file = new WAV_file(); 298 | my_wav_file.File_name = "test05_A440_16_Bits_Stereo.wav"; 299 | Console.WriteLine("Nome: " + my_wav_file.File_name); 300 | my_wav_file.Path = ".\\"; 301 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 302 | Console.WriteLine("Path: " + my_wav_file.Path); 303 | my_wav_file.loadFile(); 304 | Console.Write(my_wav_file.toWAVHeaderString()); 305 | 306 | System.Int16[] buffer_16_bits_stereo_left; 307 | System.Int16[] buffer_16_bits_stereo_right; 308 | uint numberOfSamples = (uint)my_wav_file.getBuffer_16_bits_stereo(out buffer_16_bits_stereo_left, out buffer_16_bits_stereo_right); 309 | 310 | // Buffer processing. 311 | Console.WriteLine(); 312 | Console.WriteLine(); 313 | for (uint i = 0; i < numberOfSamples; i++) 314 | { 315 | // Console.Write( buffer_16_bits_stereo_left[i].toString() + "."); 316 | // Console.Write( buffer_16_bits_stereo_right[i].toString() + "."); 317 | 318 | } 319 | Console.WriteLine(); 320 | Console.WriteLine(); 321 | 322 | // We are going to save the file on the hard drive with another name. 323 | my_wav_file.File_name = "test07_A440_16_Bits_Stereo_saved.wav"; 324 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 325 | my_wav_file.setBuffer_16_bits_stereo(buffer_16_bits_stereo_left, buffer_16_bits_stereo_right); 326 | my_wav_file.writeFile(); 327 | return 0; 328 | } // END 329 | 330 | private static int test08_ReadWrite8BitsMono__double__WAVFile() 331 | { 332 | WAV_file my_wav_file = new WAV_file(); 333 | my_wav_file.File_name = "test02_A440_8_Bits_Mono.wav"; 334 | Console.WriteLine("Nome: " + my_wav_file.File_name); 335 | my_wav_file.Path = ".\\"; 336 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 337 | Console.WriteLine("Path: " + my_wav_file.Path); 338 | my_wav_file.loadFile(); 339 | Console.Write(my_wav_file.toWAVHeaderString()); 340 | 341 | double[] buffer_double_mono; 342 | uint numberOfSamples = (uint)my_wav_file.getBuffer_double_mono_normalized(out buffer_double_mono); 343 | 344 | // Buffer processing. 345 | Console.WriteLine(); 346 | Console.WriteLine(); 347 | for (uint i = 0; i < numberOfSamples; i++) 348 | { 349 | // Console.Write( buffer_double_mono[i].toString() + "."); 350 | } 351 | Console.WriteLine(); 352 | Console.WriteLine(); 353 | 354 | // We are going to save the file on the hard drive with another name. 355 | my_wav_file.File_name = "test08_A440_8_Bits_Mono.wav"; 356 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 357 | my_wav_file.setBuffer_double_mono_normalized(buffer_double_mono); 358 | my_wav_file.writeFile(); 359 | return 0; 360 | } // END 361 | 362 | private static int test09_ReadWrite16BitsMono__double__WAVFile() 363 | { 364 | WAV_file my_wav_file = new WAV_file(); 365 | my_wav_file.File_name = "test03_A440_16_Bits_Mono.wav"; 366 | Console.WriteLine("Nome: " + my_wav_file.File_name); 367 | my_wav_file.Path = ".\\"; 368 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 369 | Console.WriteLine("Path: " + my_wav_file.Path); 370 | my_wav_file.loadFile(); 371 | Console.Write(my_wav_file.toWAVHeaderString()); 372 | 373 | double[] buffer_double_mono; 374 | uint numberOfSamples = (uint)my_wav_file.getBuffer_double_mono_normalized(out buffer_double_mono); 375 | 376 | // Buffer processing. 377 | Console.WriteLine(); 378 | Console.WriteLine(); 379 | for (uint i = 0; i < numberOfSamples; i++) 380 | { 381 | // Console.Write( buffer_double_mono[i].toString() + "."); 382 | } 383 | Console.WriteLine(); 384 | Console.WriteLine(); 385 | 386 | // We are going to save the file on the hard drive with another name. 387 | my_wav_file.File_name = "test09_A440_16_Bits_Mono.wav"; 388 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 389 | my_wav_file.setBuffer_double_mono_normalized(buffer_double_mono); 390 | my_wav_file.writeFile(); 391 | return 0; 392 | } // END 393 | 394 | private static int test10_ReadWrite8BitsStereo__double__WAVFile() 395 | { 396 | WAV_file my_wav_file = new WAV_file(); 397 | my_wav_file.File_name = "test04_A440_8_Bits_Stereo.wav"; 398 | Console.WriteLine("Nome: " + my_wav_file.File_name); 399 | my_wav_file.Path = ".\\"; 400 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 401 | Console.WriteLine("Path: " + my_wav_file.Path); 402 | my_wav_file.loadFile(); 403 | Console.Write(my_wav_file.toWAVHeaderString()); 404 | 405 | double[] buffer_double_left; 406 | double[] buffer_double_right; 407 | uint numberOfSamples = (uint)my_wav_file.getBuffer_double_stereo_normalized(out buffer_double_left, out buffer_double_right); 408 | 409 | // Buffer processing. 410 | Console.WriteLine(); 411 | Console.WriteLine(); 412 | for (uint i = 0; i < numberOfSamples; i++) 413 | { 414 | // Console.Write( buffer_double_left[i].toString() + "."); 415 | // Console.Write( buffer_double_right[i].toString() + "."); 416 | } 417 | Console.WriteLine(); 418 | Console.WriteLine(); 419 | 420 | // We are going to save the file on the hard drive with another name. 421 | my_wav_file.File_name = "test10_A440_8_Bits_Stereo.wav"; 422 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 423 | my_wav_file.setBuffer_double_stereo_normalized(buffer_double_left, buffer_double_right); 424 | my_wav_file.writeFile(); 425 | return 0; 426 | } // END 427 | 428 | private static int test11_ReadWrite16BitsStereo__double__WAVFile() 429 | { 430 | WAV_file my_wav_file = new WAV_file(); 431 | my_wav_file.File_name = "test05_A440_16_Bits_Stereo.wav"; 432 | Console.WriteLine("Nome: " + my_wav_file.File_name); 433 | my_wav_file.Path = ".\\"; 434 | // my_wav_file.Path = ".\\Debug\\wav_files\\"; 435 | Console.WriteLine("Path: " + my_wav_file.Path); 436 | my_wav_file.loadFile(); 437 | Console.Write(my_wav_file.toWAVHeaderString()); 438 | 439 | double[] buffer_double_left; 440 | double[] buffer_double_right; 441 | uint numberOfSamples = (uint)my_wav_file.getBuffer_double_stereo_normalized(out buffer_double_left, out buffer_double_right); 442 | 443 | // Buffer processing. 444 | Console.WriteLine(); 445 | Console.WriteLine(); 446 | for (uint i = 0; i < numberOfSamples; i++) 447 | { 448 | // Console.Write( buffer_double_left[i].toString() + "."); 449 | // Console.Write( buffer_double_right[i].toString() + "."); 450 | } 451 | Console.WriteLine(); 452 | Console.WriteLine(); 453 | 454 | // We are going to save the file on the hard drive with another name. 455 | my_wav_file.File_name = "test11_A440_16_Bits_Stereo.wav"; 456 | my_wav_file.initializeWaveHeaderStructBeforeWriting(); 457 | my_wav_file.setBuffer_double_stereo_normalized(buffer_double_left, buffer_double_right); 458 | my_wav_file.writeFile(); 459 | return 0; 460 | } // END 461 | 462 | } // END Class Program. 463 | } 464 | -------------------------------------------------------------------------------- /WAV_file.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Joao Nuno Carvalho 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | */ 14 | 15 | using System; 16 | using System.IO; 17 | using System.Collections.Generic; 18 | using System.Text; 19 | 20 | namespace WAV_Tools_C_Sharp 21 | { 22 | public class WAV_file 23 | { 24 | public enum NUM_CHANNELS 25 | { 26 | NOT_DEFINED = 0, 27 | ONE = 1, 28 | TWO = 2 29 | }; 30 | 31 | public enum BITS_PER_SAMPLE 32 | { 33 | NOT_DEFINED = 0, 34 | BPS_8_BITS = 8, 35 | BPS_16_BITS = 16 36 | }; 37 | 38 | const int C_HEADER_BYTE_SIZE = 44; 39 | 40 | // WAV file header fields. 41 | private byte[] chunk_id = new Byte[4]; // This are char[] in the C sense, one byte each. 42 | private System.UInt32 chunk_size; 43 | private byte[] format = new Byte[4]; // " 44 | private byte[] fmtchunk_id = new Byte[4]; // " 45 | private System.UInt32 fmtchunk_size; 46 | private System.UInt16 audio_format; 47 | private System.UInt16 num_channels; 48 | private System.UInt32 sample_rate; 49 | private System.UInt32 byte_rate; 50 | private System.UInt16 block_align; 51 | private System.UInt16 bps; //Bits per sample 52 | private byte[] datachunk_id = new Byte[4]; // This are char[] in the C sense, one byte each. 53 | private System.UInt32 datachunk_size; 54 | 55 | 56 | // WAV object fields. 57 | private string _file_name; 58 | public string File_name 59 | { 60 | get { return _file_name; } 61 | set 62 | { 63 | if (!value.ToUpper().EndsWith("WAV")) 64 | throw new ArgumentException("WAV file name must end with 'wav', or 'WAV' extension!"); 65 | _file_name = value; 66 | } 67 | } 68 | 69 | private string _path; 70 | public string Path 71 | { 72 | get { return _path; } 73 | set { _path = value; } 74 | } 75 | 76 | private System.UInt32 _numberOfSamples; 77 | public System.UInt32 NumberOfSamples 78 | { 79 | get { return _numberOfSamples; } 80 | set { _numberOfSamples = value; } 81 | } 82 | 83 | private System.Byte[] bufferInternal_uint8 = null; 84 | private System.Int16[] bufferInternal_int16 = null; 85 | 86 | 87 | // Constructor 88 | public WAV_file() 89 | { 90 | 91 | } 92 | 93 | public WAV_file(string path, string file_name) 94 | { 95 | Path = path; 96 | File_name = file_name; 97 | } 98 | 99 | // Properties. 100 | public NUM_CHANNELS NumOfChannels 101 | { 102 | get { return (NUM_CHANNELS)num_channels; } 103 | set { num_channels = (System.UInt16)value; } 104 | } 105 | 106 | public System.UInt32 SampleRate 107 | { 108 | get { return sample_rate; } 109 | set { sample_rate = value; } 110 | } 111 | 112 | private System.UInt32 ByteRate 113 | { 114 | get { return byte_rate; } 115 | set { byte_rate = value; } 116 | } 117 | 118 | public BITS_PER_SAMPLE BitsPerSample 119 | { 120 | get { return (BITS_PER_SAMPLE)bps; } 121 | set { bps = (System.UInt16)value; } 122 | } 123 | 124 | public bool isStereo() 125 | { 126 | if (num_channels == 2) 127 | return true; 128 | else 129 | return false; 130 | } 131 | 132 | public void initializeWaveHeaderStructBeforeWriting() 133 | { 134 | // Initial fill of waveHeader data structure, byte[]. 135 | chunk_id = System.Text.Encoding.ASCII.GetBytes("RIFF"); 136 | 137 | // waveHeader.chunk_size = ; 138 | format = System.Text.Encoding.ASCII.GetBytes("WAVE"); 139 | 140 | fmtchunk_id = System.Text.Encoding.ASCII.GetBytes("fmt "); 141 | fmtchunk_size = 16; 142 | audio_format = 1; 143 | // num_channels; 144 | if (num_channels != (uint)NUM_CHANNELS.ONE 145 | && num_channels != (uint)NUM_CHANNELS.TWO) 146 | { 147 | throw new ApplicationException("ERROR: The number of channels wasn't set to 1 or 2 "); 148 | } 149 | // sample_rate; 150 | if (sample_rate == 0) 151 | { 152 | throw new ApplicationException("ERROR: The sample rate wasn't set to ex: 8000 S/s or ex:44100"); 153 | } 154 | byte_rate = (System.UInt32)(sample_rate * num_channels * (bps / 8)); 155 | block_align = (System.UInt16)(num_channels * (bps / 8)); 156 | // bps; // BitsPerSample 157 | if (bps != (uint)BITS_PER_SAMPLE.BPS_8_BITS 158 | && bps != (uint)BITS_PER_SAMPLE.BPS_16_BITS) 159 | { 160 | throw new ApplicationException("ERROR: The bits per sample wasn't set to 8 or 16 Bits "); 161 | } 162 | 163 | // Fill the data subchunk. 164 | datachunk_id = System.Text.Encoding.ASCII.GetBytes("data"); 165 | datachunk_size = (System.UInt32)(_numberOfSamples * num_channels * (bps / 8)); 166 | 167 | // Fill of the the first chunck size. It has to be made out of order. 168 | chunk_size = 36 + datachunk_size; 169 | // No error. 170 | } 171 | 172 | public string toWAVHeaderString() 173 | { 174 | StringBuilder strBuf = new StringBuilder(); 175 | 176 | strBuf.AppendLine("################"); 177 | strBuf.AppendLine("WAV Header dump."); 178 | strBuf.AppendLine("################"); 179 | strBuf.AppendLine(">> RIFF header."); 180 | strBuf.Append("chunk_id [char 4]: "); strBuf.AppendLine(System.Text.Encoding.ASCII.GetString(chunk_id)); //Copy the char[]. 181 | strBuf.AppendFormat("chunk_size [uint32]: {0}", chunk_size); strBuf.AppendLine(); // Just for \n. 182 | strBuf.Append("format [char 4]: "); strBuf.AppendLine(System.Text.Encoding.ASCII.GetString(format)); //Copy the char[]. 183 | 184 | strBuf.AppendLine(">> fmt header."); 185 | strBuf.Append("fmtchunk_id [char 4]: "); strBuf.AppendLine(System.Text.Encoding.ASCII.GetString(fmtchunk_id)); //Copy the char[]. 186 | strBuf.AppendFormat("fmtchunk_size [uint32]: {0}", fmtchunk_size); strBuf.AppendLine(); // Just for \n. 187 | strBuf.AppendFormat("audio_format [uint16]: {0}", audio_format); strBuf.AppendLine(); // Just for \n. 188 | strBuf.AppendFormat("num_channels [uint16]: {0}", num_channels); strBuf.AppendLine(); // Just for \n. 189 | strBuf.AppendFormat("sample_rate [uint32]: {0}", sample_rate); strBuf.AppendLine(); // Just for \n. 190 | strBuf.AppendFormat("byte_rate [uint32]: {0}", byte_rate); strBuf.AppendLine(); // Just for \n. 191 | strBuf.AppendFormat("block_align [uint16]: {0}", block_align); strBuf.AppendLine(); // Just for \n. 192 | strBuf.AppendFormat("bps [uint16]: {0}", bps); strBuf.AppendLine(); // Just for \n. 193 | strBuf.AppendLine(">> data header."); 194 | strBuf.Append("datachunk_id [char 4]: "); strBuf.AppendLine(System.Text.Encoding.ASCII.GetString(datachunk_id)); //Copy the char[]. 195 | strBuf.AppendFormat("datachunk_size [uint32]: {0}", datachunk_size); strBuf.AppendLine(); // Just for \n. 196 | 197 | return strBuf.ToString(); 198 | } 199 | 200 | public bool loadFile() 201 | { 202 | string file_path = System.IO.Path.Combine(_path, _file_name); 203 | 204 | if (!File.Exists(file_path)) 205 | { 206 | throw new ApplicationException("ERROR file " + file_path + " doesn't exists. "); 207 | } 208 | if ((new FileInfo(file_path)).Length < C_HEADER_BYTE_SIZE) 209 | { 210 | throw new ApplicationException("ERROR: File " + file_path + " is smalller then the header of a WAV file"); 211 | } 212 | 213 | using (BinaryReader reader = new BinaryReader(File.Open(file_path, FileMode.Open))) 214 | { 215 | // Read WAV file header fields. 216 | chunk_id = reader.ReadBytes(4); // Byte[] 217 | chunk_size = reader.ReadUInt32(); 218 | format = reader.ReadBytes(4); // Byte[] 219 | fmtchunk_id = reader.ReadBytes(4); // Byte[] 220 | fmtchunk_size = reader.ReadUInt32(); 221 | audio_format = reader.ReadUInt16(); 222 | num_channels = reader.ReadUInt16(); 223 | sample_rate = reader.ReadUInt32(); 224 | byte_rate = reader.ReadUInt32(); 225 | block_align = reader.ReadUInt16(); 226 | bps = reader.ReadUInt16(); //Bits per sample 227 | datachunk_id = reader.ReadBytes(4); // Byte[] 228 | datachunk_size = reader.ReadUInt32(); 229 | 230 | // File type validations. 231 | if (System.Text.Encoding.ASCII.GetString(chunk_id) != "RIFF" 232 | || System.Text.Encoding.ASCII.GetString(format) != "WAVE") 233 | { 234 | throw new ApplicationException("ERROR: File " + file_path + " is not a WAV file"); 235 | } 236 | if (audio_format != 1) 237 | { 238 | throw new ApplicationException("ERROR: File " + file_path + " the API only supports PCM format in WAV."); 239 | } 240 | 241 | switch ((BITS_PER_SAMPLE)bps) 242 | { 243 | case BITS_PER_SAMPLE.BPS_8_BITS: 244 | bufferInternal_uint8 = reader.ReadBytes((int)datachunk_size); 245 | _numberOfSamples = datachunk_size / num_channels; 246 | break; 247 | 248 | case BITS_PER_SAMPLE.BPS_16_BITS: 249 | // Note: To make the following convertion from byte[] to int16[] I could make unsafe code 250 | // and a simple cast but i'm trying to not make unsafe code. 251 | int num_int16 = (int)(datachunk_size / sizeof(System.Int16)); 252 | bufferInternal_int16 = new System.Int16[num_int16]; 253 | byte[] two_byte_buf_to_int16; 254 | for (int i = 0; i < num_int16; i++) 255 | { 256 | two_byte_buf_to_int16 = reader.ReadBytes(2); 257 | bufferInternal_int16[i] = BitConverter.ToInt16(two_byte_buf_to_int16, 0); 258 | } 259 | _numberOfSamples = (datachunk_size / 2) / num_channels; 260 | break; 261 | 262 | default: 263 | throw new ApplicationException("ERROR: Incorret bits per sample in file " + file_path); 264 | } 265 | return true; 266 | } 267 | } // END loadFile(). 268 | 269 | public bool writeFile() 270 | { 271 | string file_path = System.IO.Path.Combine(_path, _file_name); 272 | 273 | // TODO: Test if the file could be open for writing. 274 | 275 | using (BinaryWriter writer = new BinaryWriter(File.Open(file_path, FileMode.Create))) 276 | { 277 | // Write all fields of WAV the header. 278 | writer.Write(chunk_id); // Byte[4] 279 | writer.Write(chunk_size); // UInt32 280 | writer.Write(format); // Byte[4] 281 | writer.Write(fmtchunk_id); // Byte[4] 282 | writer.Write(fmtchunk_size); // UInt32 283 | writer.Write(audio_format); // UInt16 284 | writer.Write(num_channels); // UInt16 285 | writer.Write(sample_rate); // UInt32 286 | writer.Write(byte_rate); // UInt32 287 | writer.Write(block_align); // UInt16 288 | writer.Write(bps); // UInt16 289 | writer.Write(datachunk_id); // Byte[4] 290 | writer.Write(datachunk_size); // UInt32 291 | 292 | switch ((BITS_PER_SAMPLE)bps) 293 | { 294 | case BITS_PER_SAMPLE.BPS_8_BITS: 295 | if (bufferInternal_uint8 == null) 296 | { 297 | throw new ApplicationException("ERROR: Data buffer uint8 is NULL!"); 298 | } 299 | // Write WAV data buffer. 300 | writer.Write(bufferInternal_uint8); 301 | break; 302 | 303 | case BITS_PER_SAMPLE.BPS_16_BITS: 304 | if (bufferInternal_int16 == null) 305 | { 306 | throw new ApplicationException("ERROR: Data buffer int16 is NULL!"); 307 | } 308 | // Note: To make the following convertion from byte[] to int16[] I could make unsafe code 309 | // and a simple cast but i'm trying to not make unsafe code. 310 | int num_int16 = (int)(datachunk_size / sizeof(System.Int16)); 311 | byte[] two_bytes_buf_from_int16; 312 | for (int i = 0; i < num_int16; i++) 313 | { 314 | two_bytes_buf_from_int16 = BitConverter.GetBytes(bufferInternal_int16[i]); 315 | writer.Write(two_bytes_buf_from_int16); 316 | } 317 | break; 318 | 319 | default: 320 | throw new ApplicationException("ERROR: Incorret bits per sample to write file " + file_path); 321 | } 322 | } 323 | 324 | return true; 325 | } // END writeFile(). 326 | 327 | ///////////////// 328 | // Get Buffers 329 | //////////////// 330 | 331 | // NOTE: If no file have been readed it return an allocated and inicialized buffer. 332 | public int getBuffer_8_bits_mono(out System.Byte[] p_new_buffer_8_bits_mono) 333 | { 334 | p_new_buffer_8_bits_mono = null; 335 | if (num_channels == (int)NUM_CHANNELS.TWO) 336 | { 337 | throw new ApplicationException("ERROR: getBuffer_8_bits_mono() can't be used for a stereo WAV file!"); 338 | } 339 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_8_BITS) 340 | { 341 | throw new ApplicationException("BitsPerSample for this file isn't 8 bits!"); 342 | } 343 | if (bufferInternal_uint8 == null) 344 | { 345 | // The buffer hasn't been created, we allocate memory and fill it with center value. 346 | bufferInternal_uint8 = new System.Byte[datachunk_size]; 347 | System.Byte medium_value = System.Byte.MaxValue / 2; 348 | for (int i = 0; i < bufferInternal_uint8.Length; i++) 349 | { 350 | bufferInternal_uint8[i] = medium_value; 351 | } 352 | } 353 | p_new_buffer_8_bits_mono = new System.Byte[datachunk_size]; 354 | Array.Copy(bufferInternal_uint8, p_new_buffer_8_bits_mono, datachunk_size); 355 | return (int)datachunk_size; 356 | } // END getBuffer_8_bits_mono() 357 | 358 | public int getBuffer_8_bits_stereo(out System.Byte[] newBuffer_1_8_bits_left, out System.Byte[] newBuffer_2_8_bits_right) 359 | { 360 | newBuffer_1_8_bits_left = null; 361 | newBuffer_2_8_bits_right = null; 362 | if (num_channels == (int)NUM_CHANNELS.ONE) 363 | { 364 | throw new ApplicationException("ERROR: getBuffer_8_bits_stereo() can't be used for a mono WAV file!"); 365 | } 366 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_8_BITS) 367 | { 368 | throw new ApplicationException("BitsPerSample for this file isn't 8 bits!"); 369 | } 370 | if (bufferInternal_uint8 == null) 371 | { 372 | // The buffer hasn't been created, we allocate memory and fill it with center value. 373 | bufferInternal_uint8 = new System.Byte[datachunk_size]; 374 | System.Byte medium_value = System.Byte.MaxValue / 2; 375 | for (int i = 0; i < bufferInternal_uint8.Length; i++) 376 | { 377 | bufferInternal_uint8[i] = medium_value; 378 | } 379 | } 380 | newBuffer_1_8_bits_left = new System.Byte[datachunk_size / 2]; 381 | newBuffer_2_8_bits_right = new System.Byte[datachunk_size / 2]; 382 | for (System.UInt32 i = 0; i < datachunk_size; i += 2) 383 | { 384 | newBuffer_1_8_bits_left[i / 2] = bufferInternal_uint8[i]; 385 | newBuffer_2_8_bits_right[i / 2] = bufferInternal_uint8[i + 1]; 386 | } 387 | return (int)(datachunk_size / 2); 388 | } // END getBuffer_8_bits_stereo(). 389 | 390 | // NOTE: If no file have been readed it return an allocated and inicialized buffer. 391 | public int getBuffer_16_bits_mono(out System.Int16[] p_new_buffer_16_bits_mono) 392 | { 393 | p_new_buffer_16_bits_mono = null; 394 | if (num_channels == (int)NUM_CHANNELS.TWO) 395 | { 396 | throw new ApplicationException("ERROR: getBuffer_16_bits_mono() can't be used for a stereo WAV file!"); 397 | } 398 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_16_BITS) 399 | { 400 | throw new ApplicationException("BitsPerSample for this file isn't 16 bits!"); 401 | } 402 | if (bufferInternal_int16 == null) 403 | { 404 | // The buffer hasn't been created, we allocate memory and fill it with center value. 405 | bufferInternal_int16 = new System.Int16[datachunk_size / 2]; 406 | // Note: The buffer is already initialized to zero. 407 | } 408 | p_new_buffer_16_bits_mono = new System.Int16[datachunk_size / 2]; 409 | Array.Copy(bufferInternal_int16, p_new_buffer_16_bits_mono, datachunk_size / 2); 410 | return (int)(datachunk_size / 2); 411 | } // END getBuffer_16_bits_mono() 412 | 413 | public int getBuffer_16_bits_stereo(out System.Int16[] newBuffer_1_16_bits_left, out System.Int16[] newBuffer_2_16_bits_right) 414 | { 415 | newBuffer_1_16_bits_left = null; 416 | newBuffer_2_16_bits_right = null; 417 | if (num_channels == (int)NUM_CHANNELS.ONE) 418 | { 419 | throw new ApplicationException("ERROR: getBuffer_8_bits_stereo() can't be used for a mono WAV file!"); 420 | } 421 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_16_BITS) 422 | { 423 | throw new ApplicationException("BitsPerSample for this file isn't 16 bits!"); 424 | } 425 | if (bufferInternal_int16 == null) 426 | { 427 | // The buffer hasn't been created, we allocate memory and fill it with center value (zero). 428 | bufferInternal_int16 = new System.Int16[datachunk_size / sizeof(System.UInt16)]; 429 | } 430 | newBuffer_1_16_bits_left = new System.Int16[(datachunk_size / 2) / sizeof(System.UInt16)]; 431 | newBuffer_2_16_bits_right = new System.Int16[(datachunk_size / 2) / sizeof(System.UInt16)]; 432 | for (System.UInt32 i = 0; i < datachunk_size / 2; i += 2) 433 | { 434 | newBuffer_1_16_bits_left[i / 2] = bufferInternal_int16[i]; 435 | newBuffer_2_16_bits_right[i / 2] = bufferInternal_int16[i + 1]; 436 | } 437 | return (int)(datachunk_size / 4); 438 | } // END getBuffer_16_bits_stereo(). 439 | 440 | // NOTE: If no file have been readed it return an allocated and inicialized buffer. 441 | public int getBuffer_double_mono_normalized(out double[] p_new_buffer_double_mono) 442 | { 443 | p_new_buffer_double_mono = null; 444 | if (num_channels == (int)NUM_CHANNELS.TWO) 445 | { 446 | throw new ApplicationException("ERROR: getBuffer_double_mono_normalized() can't be used for a stereo WAV file!"); 447 | } 448 | int number_of_samples_tmp = 0; 449 | switch (BitsPerSample) 450 | { 451 | case BITS_PER_SAMPLE.BPS_8_BITS: 452 | if (bufferInternal_uint8 == null) 453 | { 454 | // The buffer hasn't been created, we allocate memory and fill it with center value. 455 | bufferInternal_uint8 = new System.Byte[datachunk_size]; 456 | System.Byte medium_value = System.Byte.MaxValue / 2; 457 | for (int i = 0; i < bufferInternal_uint8.Length; i++) 458 | { 459 | bufferInternal_uint8[i] = medium_value; 460 | } 461 | } 462 | p_new_buffer_double_mono = new double[datachunk_size]; 463 | for (int i = 0; i < bufferInternal_uint8.Length; i++) 464 | { 465 | p_new_buffer_double_mono[i] = (bufferInternal_uint8[i] - (System.Byte.MaxValue / 2)) / (System.Byte.MaxValue / 2.0); 466 | } 467 | number_of_samples_tmp = (int)datachunk_size; 468 | break; 469 | 470 | case BITS_PER_SAMPLE.BPS_16_BITS: 471 | if (bufferInternal_int16 == null) 472 | { 473 | // The buffer hasn't been created, we allocate memory and fill it with center value. 474 | bufferInternal_int16 = new System.Int16[datachunk_size / 2]; 475 | // Note: The buffer is already initialized to zero. 476 | } 477 | p_new_buffer_double_mono = new double[datachunk_size / 2]; 478 | for (int i = 0; i < bufferInternal_int16.Length; i++) 479 | { 480 | p_new_buffer_double_mono[i] = bufferInternal_int16[i] / ((double)System.Int16.MaxValue); 481 | } 482 | number_of_samples_tmp = (int)(datachunk_size / 2); 483 | break; 484 | 485 | default: 486 | throw new ApplicationException("BitsPerSample isn't filled for this file!"); 487 | } 488 | return number_of_samples_tmp; 489 | } // END getBuffer_double_mono_normalized 490 | 491 | // NOTE: If no file have been readed it return an allocated and inicialized buffer. 492 | public int getBuffer_double_stereo_normalized(out double[] p_new_buffer_double_left, out double[] p_new_buffer_double_right) 493 | { 494 | p_new_buffer_double_left = null; 495 | p_new_buffer_double_right = null; 496 | if (num_channels == (int)NUM_CHANNELS.ONE) 497 | { 498 | throw new ApplicationException("ERROR: getBuffer_double_stereo_normalized() can't be used for a mono WAV file!"); 499 | } 500 | int number_of_samples_tmp = 0; 501 | switch (BitsPerSample) 502 | { 503 | case BITS_PER_SAMPLE.BPS_8_BITS: 504 | if (bufferInternal_uint8 == null) 505 | { 506 | // The buffer hasn't been created, we allocate memory and fill it with center value. 507 | bufferInternal_uint8 = new System.Byte[datachunk_size]; 508 | System.Byte medium_value = System.Byte.MaxValue / 2; 509 | for (int i = 0; i < bufferInternal_uint8.Length; i++) 510 | { 511 | bufferInternal_uint8[i] = medium_value; 512 | } 513 | } 514 | p_new_buffer_double_left = new double[datachunk_size / sizeof(System.UInt16)]; 515 | p_new_buffer_double_right = new double[datachunk_size / sizeof(System.UInt16)]; 516 | for (System.UInt32 i = 0; i < datachunk_size; i += 2) 517 | { 518 | p_new_buffer_double_left[i / 2] = (bufferInternal_uint8[i] - (System.Byte.MaxValue / 2)) / (System.Byte.MaxValue / 2.0); 519 | p_new_buffer_double_right[i / 2] = (bufferInternal_uint8[i+1] - (System.Byte.MaxValue / 2)) / (System.Byte.MaxValue / 2.0); 520 | } 521 | number_of_samples_tmp = (int) (datachunk_size / 2); 522 | break; 523 | 524 | case BITS_PER_SAMPLE.BPS_16_BITS: 525 | if (bufferInternal_int16 == null) 526 | { 527 | // The buffer hasn't been created, we allocate memory and fill it with center value. 528 | bufferInternal_int16 = new System.Int16[datachunk_size / sizeof(System.UInt16)]; 529 | // Note: The buffer is already initialized to zero. 530 | } 531 | p_new_buffer_double_left = new double[(datachunk_size / 2) / sizeof(System.UInt16)]; 532 | p_new_buffer_double_right = new double[(datachunk_size / 2) / sizeof(System.UInt16)]; 533 | 534 | 535 | for (System.UInt32 i = 0; i < datachunk_size / 2; i += 2) 536 | { 537 | p_new_buffer_double_left[i / 2] = bufferInternal_int16[i] / ((double)System.Int16.MaxValue); 538 | p_new_buffer_double_right[i / 2] = bufferInternal_int16[i + 1] / ((double)System.Int16.MaxValue); 539 | } 540 | number_of_samples_tmp = (int)(datachunk_size / 4); 541 | break; 542 | 543 | default: 544 | throw new ApplicationException("BitsPerSample isn't filled for this file!"); 545 | } 546 | return number_of_samples_tmp; 547 | } // END getBuffer_double_stereo_normalized() 548 | 549 | ///////////////// 550 | // Set Buffers 551 | //////////////// 552 | 553 | public int setBuffer_8_bits_mono( System.Byte[] p_new_buffer_8_bits_mono) 554 | { 555 | if (p_new_buffer_8_bits_mono == null) 556 | { 557 | throw new ApplicationException("ERROR: setBuffer_8_bits_mono() p_new_buffer_8_bits_mono is NULL!"); 558 | } 559 | if (_numberOfSamples == 0) 560 | { 561 | throw new ApplicationException("WARNING: setBuffer_8_bits_mono() the length of the buffer is zero!"); 562 | } 563 | if (_numberOfSamples != p_new_buffer_8_bits_mono.Length) 564 | { 565 | throw new ApplicationException("WARNING: setBuffer_8_bits_mono() the length of the buffer is different from numberOfSamples!"); 566 | } 567 | if (num_channels == (int)NUM_CHANNELS.TWO) 568 | { 569 | throw new ApplicationException("ERROR: setBuffer_8_bits_mono() can't be used for a stereo WAV file!"); 570 | } 571 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_8_BITS) 572 | { 573 | throw new ApplicationException("BitsPerSample for this file isn't 8 bits!"); 574 | } 575 | if (bufferInternal_uint8 != null) 576 | { 577 | bufferInternal_uint8 = null; 578 | } 579 | bufferInternal_uint8 = new System.Byte[_numberOfSamples]; 580 | Array.Copy(p_new_buffer_8_bits_mono, bufferInternal_uint8, _numberOfSamples); 581 | return (int) _numberOfSamples; 582 | } // END setBuffer_8_bits_mono(). 583 | 584 | public int setBuffer_8_bits_stereo(System.Byte[] p_new_buffer_1_8_bits_left, System.Byte[] p_new_buffer_2_8_bits_right ) 585 | { 586 | if (p_new_buffer_1_8_bits_left == null) 587 | { 588 | throw new ApplicationException("ERROR: setBuffer_8_bits_stereo() p_new_buffer_1_8_bits_left is NULL!"); 589 | } 590 | if (p_new_buffer_2_8_bits_right == null) 591 | { 592 | throw new ApplicationException("ERROR: setBuffer_8_bits_stereo() p_new_buffer_1_8_bits_right is NULL!"); 593 | } 594 | if (_numberOfSamples == 0) 595 | { 596 | throw new ApplicationException("WARNING: setBuffer_8_bits_stereo() the length of the buffer is zero!"); 597 | } 598 | if ( _numberOfSamples != p_new_buffer_1_8_bits_left.Length 599 | || _numberOfSamples != p_new_buffer_2_8_bits_right.Length) 600 | { 601 | throw new ApplicationException("WARNING: setBuffer_8_bits_stereo() the length of the buffers is different from numberOfSamples!"); 602 | } 603 | if (num_channels == (int)NUM_CHANNELS.ONE) 604 | { 605 | throw new ApplicationException("ERROR: setBuffer_8_bits_stereo() can't be used for a mono WAV file!"); 606 | } 607 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_8_BITS) 608 | { 609 | throw new ApplicationException("BitsPerSample for this file isn't 8 bits!"); 610 | } 611 | if (bufferInternal_uint8 != null) 612 | { 613 | bufferInternal_uint8 = null; 614 | } 615 | bufferInternal_uint8 = new System.Byte[_numberOfSamples * 2]; 616 | for (uint i = 0; i < (_numberOfSamples * 2); i += 2) 617 | { 618 | bufferInternal_uint8[i] = p_new_buffer_1_8_bits_left[i / 2]; 619 | bufferInternal_uint8[i + 1] = p_new_buffer_2_8_bits_right[i / 2]; 620 | } 621 | return (int) (_numberOfSamples / 2); 622 | } // END setBuffer_8_bits_stereo(). 623 | 624 | public int setBuffer_16_bits_mono(System.Int16[] p_new_buffer_16_bits_mono) 625 | { 626 | if (p_new_buffer_16_bits_mono == null) 627 | { 628 | throw new ApplicationException("ERROR: setBuffer_16_bits_mono() p_new_buffer_16_bits_mono is NULL!"); 629 | } 630 | if (_numberOfSamples == 0) 631 | { 632 | throw new ApplicationException("WARNING: setBuffer_16_bits_mono() the length of the buffer is zero!"); 633 | } 634 | if (_numberOfSamples != p_new_buffer_16_bits_mono.Length) 635 | { 636 | throw new ApplicationException("WARNING: setBuffer_16_bits_mono() the length of the buffer is different from numberOfSamples!"); 637 | } 638 | if (num_channels == (int)NUM_CHANNELS.TWO) 639 | { 640 | throw new ApplicationException("ERROR: setBuffer_16_bits_mono() can't be used for a stereo WAV file!"); 641 | } 642 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_16_BITS) 643 | { 644 | throw new ApplicationException("BitsPerSample for this file isn't 16 bits!"); 645 | } 646 | if (bufferInternal_int16 != null) 647 | { 648 | bufferInternal_int16 = null; 649 | } 650 | bufferInternal_int16 = new System.Int16[_numberOfSamples]; 651 | Array.Copy(p_new_buffer_16_bits_mono, bufferInternal_int16, _numberOfSamples); 652 | return (int)_numberOfSamples; 653 | } // END setBuffer_16_bits_mono(). 654 | 655 | public int setBuffer_16_bits_stereo(System.Int16[] p_new_buffer_1_16_bits_left, System.Int16[] p_new_buffer_2_16_bits_right) 656 | { 657 | if (p_new_buffer_1_16_bits_left == null) 658 | { 659 | throw new ApplicationException("ERROR: setBuffer_16_bits_stereo() p_new_buffer_1_16_bits_left is NULL!"); 660 | } 661 | if (p_new_buffer_2_16_bits_right == null) 662 | { 663 | throw new ApplicationException("ERROR: setBuffer_16_bits_stereo() p_new_buffer_2_8_bits_right is NULL!"); 664 | } 665 | if (_numberOfSamples == 0) 666 | { 667 | throw new ApplicationException("WARNING: setBuffer_8_bits_stereo() the length of the buffer is zero!"); 668 | } 669 | if ( _numberOfSamples != p_new_buffer_1_16_bits_left.Length 670 | || _numberOfSamples != p_new_buffer_2_16_bits_right.Length) 671 | { 672 | throw new ApplicationException("WARNING: setBuffer_16_bits_stereo() the length of the buffers is different from numberOfSamples!"); 673 | } 674 | if (num_channels == (int)NUM_CHANNELS.ONE) 675 | { 676 | throw new ApplicationException("ERROR: setBuffer_16_bits_stereo() can't be used for a mono WAV file!"); 677 | } 678 | if (BitsPerSample != BITS_PER_SAMPLE.BPS_16_BITS) 679 | { 680 | throw new ApplicationException("BitsPerSample for this file isn't 16 bits!"); 681 | } 682 | if (bufferInternal_int16 != null) 683 | { 684 | bufferInternal_int16 = null; 685 | } 686 | bufferInternal_int16 = new System.Int16[_numberOfSamples * 2]; 687 | 688 | for (uint i = 0; i < (_numberOfSamples * 2); i += 2) 689 | { 690 | bufferInternal_int16[i] = p_new_buffer_1_16_bits_left[i / 2]; 691 | bufferInternal_int16[i + 1] = p_new_buffer_2_16_bits_right[i / 2]; 692 | } 693 | return (int) (_numberOfSamples / 2); 694 | } // END setBuffer_16_bits_stereo(). 695 | 696 | public int setBuffer_double_mono_normalized( double[] p_new_buffer_double_mono) 697 | { 698 | if (p_new_buffer_double_mono == null) 699 | { 700 | throw new ApplicationException("ERROR: setBuffer_double_mono_normalized() p_new_buffer_double_mono is NULL!"); 701 | } 702 | if (_numberOfSamples == 0) 703 | { 704 | throw new ApplicationException("WARNING: setBuffer_double_mono_normalized() the length of the file/buffer is zero!"); 705 | } 706 | if (_numberOfSamples != p_new_buffer_double_mono.Length) 707 | { 708 | throw new ApplicationException("WARNING: setBuffer_double_mono_normalized() the length of the buffer is different from numberOfSamples!"); 709 | } 710 | if (num_channels == (int)NUM_CHANNELS.TWO) 711 | { 712 | throw new ApplicationException("ERROR: setBuffer_double_mono_normalized() can't be used for a stereo WAV file!"); 713 | } 714 | int number_of_samples_tmp = 0; 715 | switch (BitsPerSample) 716 | { 717 | case BITS_PER_SAMPLE.BPS_8_BITS: 718 | // The buffer is created even if it already existed, we allocate memory and fill it with center value. 719 | bufferInternal_uint8 = new System.Byte[_numberOfSamples]; 720 | for (int i = 0; i < _numberOfSamples; i++) 721 | { 722 | bufferInternal_uint8[i] = (System.Byte) ( (p_new_buffer_double_mono[i] * (System.Byte.MaxValue / 2) ) + (System.Byte.MaxValue / 2) ); 723 | } 724 | number_of_samples_tmp = (int)_numberOfSamples; 725 | break; 726 | 727 | case BITS_PER_SAMPLE.BPS_16_BITS: 728 | // The buffer is created even if it already existed, we allocate memory and fill it with center value. 729 | bufferInternal_int16 = new System.Int16[_numberOfSamples]; 730 | for (int i = 0; i < _numberOfSamples; i++) 731 | { 732 | bufferInternal_int16[i] = (System.Int16) ( p_new_buffer_double_mono[i] * ((double)System.Int16.MaxValue) ); 733 | } 734 | number_of_samples_tmp = (int)_numberOfSamples; 735 | break; 736 | 737 | default: 738 | throw new ApplicationException("BitsPerSample isn't filled for this file!"); 739 | } 740 | return number_of_samples_tmp; 741 | } // END setBuffer_double_mono_normalized() 742 | 743 | public int setBuffer_double_stereo_normalized(double[] p_new_buffer_double_left, double[] p_new_buffer_double_right) 744 | { 745 | if (p_new_buffer_double_left == null) 746 | { 747 | throw new ApplicationException("ERROR: setBuffer_double_stereo_normalized() p_new_buffer_double_left is NULL!"); 748 | } 749 | if (p_new_buffer_double_right == null) 750 | { 751 | throw new ApplicationException("ERROR: setBuffer_double_stereo_normalized() p_new_buffer_double_right is NULL!"); 752 | } 753 | if (_numberOfSamples == 0) 754 | { 755 | throw new ApplicationException("WARNING: setBuffer_double_stereo_normalized() the length of the file/buffer is zero!"); 756 | } 757 | 758 | 759 | if ( _numberOfSamples != p_new_buffer_double_left.Length 760 | || _numberOfSamples != p_new_buffer_double_right.Length) 761 | { 762 | throw new ApplicationException("WARNING: setBuffer_double_Stereo_normalized() the length of the buffer is different from numberOfSamples!"); 763 | } 764 | if (num_channels == (int)NUM_CHANNELS.ONE) 765 | { 766 | throw new ApplicationException("ERROR: setBuffer_double_stereo_normalized() can't be used for a mono WAV file!"); 767 | } 768 | int number_of_samples_tmp = 0; 769 | switch (BitsPerSample) 770 | { 771 | case BITS_PER_SAMPLE.BPS_8_BITS: 772 | // The buffer is created even if it already existed, we allocate memory and fill it with center value. 773 | bufferInternal_uint8 = new System.Byte[_numberOfSamples * 2]; 774 | for (int i = 0; i < _numberOfSamples * 2; i += 2) 775 | { 776 | bufferInternal_uint8[i] = (System.Byte)((p_new_buffer_double_left[i / 2] * (System.Byte.MaxValue / 2)) + (System.Byte.MaxValue / 2)); 777 | bufferInternal_uint8[i + 1] = (System.Byte)((p_new_buffer_double_right[i / 2] * (System.Byte.MaxValue / 2)) + (System.Byte.MaxValue / 2)); 778 | } 779 | number_of_samples_tmp = (int) (_numberOfSamples / 2); 780 | break; 781 | 782 | case BITS_PER_SAMPLE.BPS_16_BITS: 783 | // The buffer is created even if it already existed, we allocate memory and fill it with center value. 784 | bufferInternal_int16 = new System.Int16[_numberOfSamples * 2]; 785 | for (int i = 0; i < _numberOfSamples * 2; i += 2) 786 | { 787 | bufferInternal_int16[i] = (System.Int16)(p_new_buffer_double_left[i / 2] * ((double)System.Int16.MaxValue)); 788 | bufferInternal_int16[i + 1] = (System.Int16)(p_new_buffer_double_right[i / 2] * ((double)System.Int16.MaxValue)); 789 | } 790 | number_of_samples_tmp = (int)_numberOfSamples / 2; 791 | break; 792 | 793 | default: 794 | throw new ApplicationException("BitsPerSample isn't filled for this file!"); 795 | } 796 | return number_of_samples_tmp; 797 | } // END setBuffer_double_stereo_normalized() 798 | 799 | 800 | } // End of class WAV_file. 801 | } // End of namespace. 802 | --------------------------------------------------------------------------------