00001 00030 #include <itpp/srccode/audiofile.h> 00031 #include <itpp/base/converters.h> 00032 #include <iostream> 00033 00035 00036 #define SND_MAGIC 0x2e736e64 00037 00038 using std::istream; 00039 using std::ostream; 00040 using std::ifstream; 00041 using std::ofstream; 00042 using std::ios; 00043 00044 namespace itpp 00045 { 00046 00047 inline static short double_to_short(double x) 00048 { 00049 if (x >= 32767.0) 00050 return 32767; 00051 else if (x <= -32768.0) 00052 return -32768; 00053 else 00054 return static_cast<short>(round_i(x)); 00055 } 00056 00057 inline static signed char double_to_char(double x) 00058 { 00059 if (x >= 127.0) 00060 return 127; 00061 else if (x <= -128.0) 00062 return -128; 00063 else 00064 return static_cast<char>(round_i(x)); 00065 } 00066 00067 bool raw16le_read(const char *fname, vec &v) 00068 { 00069 ifstream file(fname, ios::in | ios::binary); 00070 if (!file) 00071 return false; 00072 00073 // Check size of a file 00074 file.seekg(0, ios::end); 00075 int size = file.tellg(); 00076 file.seekg(0, ios::beg); 00077 00078 bool switch_endian = check_big_endianness(); // if BIG_ENDIAN than switch 00079 int n = size / 2; // short vs. byte 00080 v.set_size(n, false); 00081 for (int i = 0; i < n; i++) 00082 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00083 00084 return true; 00085 } 00086 00087 bool raw16le_read(const char *fname, vec &v, int beg, int len) 00088 { 00089 it_assert_debug(len >= 0, "raw16le_read()"); 00090 ifstream file(fname, ios::in | ios::binary); 00091 if (!file) 00092 return false; 00093 00094 bool switch_endian = check_big_endianness(); // if BIG_ENDIAN than switch 00095 v.set_size(len, false); 00096 file.seekg(2 * beg); 00097 for (int i = 0; i < len; i++) 00098 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00099 00100 return true; 00101 } 00102 00103 bool raw16le_write(const char *fname, const vec &v, bool append) 00104 { 00105 ofstream file(fname, (append ? ios::app | ios::ate : ios::out | ios::trunc) | ios::binary); 00106 if (!file) 00107 return false; 00108 00109 bool switch_endian = check_big_endianness(); // if BIG_ENDIAN than switch 00110 for (int i = 0; i < v.size(); i++) 00111 write_endian<short>(file, double_to_short(v(i) * 32768.0), switch_endian); 00112 00113 return true; 00114 } 00115 00116 bool raw16be_read(const char *fname, vec &v) 00117 { 00118 ifstream file(fname, ios::in | ios::binary); 00119 if (!file) 00120 return false; 00121 00122 // Check size of a file 00123 file.seekg(0, ios::end); 00124 int size = file.tellg(); 00125 file.seekg(0, ios::beg); 00126 00127 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00128 int n = size / 2; // short vs. byte 00129 v.set_size(n, false); 00130 for (int i = 0; i < n; i++) 00131 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00132 00133 return true; 00134 } 00135 00136 bool raw16be_read(const char *fname, vec &v, int beg, int len) 00137 { 00138 it_assert_debug(len >= 0, "raw16le_read()"); 00139 ifstream file(fname, ios::in | ios::binary); 00140 if (!file) 00141 return false; 00142 00143 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00144 v.set_size(len, false); 00145 file.seekg(2 * beg); 00146 for (int i = 0; i < len; i++) 00147 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00148 00149 return true; 00150 } 00151 00152 bool raw16be_write(const char *fname, const vec &v, bool append) 00153 { 00154 ofstream file(fname, (append ? ios::app | ios::ate : ios::out | ios::trunc) | ios::binary); 00155 if (!file) 00156 return false; 00157 00158 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00159 for (int i = 0; i < v.size(); i++) 00160 write_endian<short>(file, double_to_short(v(i) * 32768.0), switch_endian); 00161 00162 return true; 00163 } 00164 00166 // 00167 // Audio_File 00168 // 00170 Audio_File::Audio_File() 00171 { 00172 is_valid = false; 00173 } 00174 00176 // 00177 // SND_Format 00178 // 00180 int SND_Format::sample_size() const 00181 { 00182 switch (header.encoding) { 00183 case enc_mulaw8 : 00184 return 1; 00185 case enc_alaw8 : 00186 return 1; 00187 case enc_linear8 : 00188 return 1; 00189 case enc_linear16 : 00190 return 2; 00191 case enc_linear24 : 00192 return 3; 00193 case enc_linear32 : 00194 return 4; 00195 case enc_float : 00196 return 4; 00197 case enc_double : 00198 return 8; 00199 } 00200 return 0; 00201 } 00202 00203 bool SND_Format::read_header(std::istream &f) 00204 { 00205 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00206 f.seekg(0); 00207 header.magic = read_endian<unsigned int>(f, switch_endian); 00208 header.hdr_size = read_endian<unsigned int>(f, switch_endian); 00209 header.data_size = read_endian<unsigned int>(f, switch_endian); 00210 header.encoding = read_endian<unsigned int>(f, switch_endian); 00211 header.sample_rate = read_endian<unsigned int>(f, switch_endian); 00212 header.channels = read_endian<unsigned int>(f, switch_endian); 00213 f.read(header.info, SND_INFO_LEN); 00214 if (!f || header.magic != SND_MAGIC) { 00215 std::cerr << header.magic << " != " << SND_MAGIC << std::endl; 00216 it_warning("SND_Format::read_header(): This is not a .snd file!"); 00217 return false; 00218 } 00219 f.seekg(header.hdr_size); 00220 00221 return f.good(); 00222 } 00223 00224 bool SND_Format::write_header(std::ostream &f) 00225 { 00226 f.seekp(0); 00227 header.magic = SND_MAGIC; 00228 header.hdr_size = sizeof(header); 00229 memset(header.info, 0, SND_INFO_LEN); 00230 00231 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00232 write_endian<unsigned int>(f, header.magic, switch_endian); 00233 write_endian<unsigned int>(f, header.hdr_size, switch_endian); 00234 write_endian<unsigned int>(f, header.data_size, switch_endian); 00235 write_endian<unsigned int>(f, header.encoding, switch_endian); 00236 write_endian<unsigned int>(f, header.sample_rate, switch_endian); 00237 write_endian<unsigned int>(f, header.channels, switch_endian); 00238 f.write(reinterpret_cast<char *>(&header.info), SND_INFO_LEN); 00239 00240 return f.good(); 00241 } 00242 00244 // 00245 // SND_In_File 00246 // 00248 00249 SND_In_File::SND_In_File() 00250 { 00251 } 00252 00253 SND_In_File::SND_In_File(const char *fname) 00254 { 00255 open(fname); 00256 } 00257 00258 bool SND_In_File::open(const char *fname) 00259 { 00260 if (file.is_open()) 00261 close(); 00262 file.clear(); 00263 is_valid = false; 00264 file.open(fname, ios::in | ios::binary); 00265 if (!file) 00266 return false; 00267 if (!read_header(file)) { 00268 file.close(); 00269 return false; 00270 } 00271 00272 is_valid = true; 00273 return true; 00274 } 00275 00276 void SND_In_File::close() 00277 { 00278 file.close(); 00279 is_valid = false; 00280 } 00281 00282 bool SND_In_File::seek_read(int pos) 00283 { 00284 if (pos < 0) 00285 file.seekg(0, ios::end); 00286 else 00287 file.seekg(header.hdr_size + header.channels * sample_size() * pos); 00288 return true; 00289 } 00290 00291 int SND_In_File::tell_read() 00292 { 00293 if (!good()) 00294 return -1; 00295 00296 return ((static_cast<int>(file.tellg()) - sizeof(header)) 00297 / (header.channels * sample_size())); 00298 } 00299 00300 bool SND_In_File::read(vec &v) 00301 { 00302 if (!good()) 00303 return false; 00304 00305 int i, n; 00306 00307 n = samples(); 00308 v.set_size(n, false); 00309 seek_read(0); 00310 00311 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00312 switch (header.encoding) { 00313 case enc_linear8 : 00314 for (i = 0; i < n; i++) 00315 v(i) = read_endian<char>(file, switch_endian) / 128.0; 00316 break; 00317 case enc_linear16 : 00318 for (i = 0; i < n; i++) 00319 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00320 break; 00321 case enc_float : 00322 for (i = 0; i < n; i++) 00323 v(i) = read_endian<float>(file, switch_endian); 00324 break; 00325 case enc_double : 00326 for (i = 0; i < n; i++) 00327 v(i) = read_endian<double>(file, switch_endian); 00328 break; 00329 default : 00330 it_warning("SND_In_File::read(): Unsupported encoding!"); 00331 return false; 00332 } 00333 return file.good(); 00334 } 00335 00336 bool SND_In_File::read(vec &v, int n) 00337 { 00338 if (!good()) 00339 return false; 00340 00341 int i; 00342 00343 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00344 v.set_size(n, false); 00345 switch (header.encoding) { 00346 case enc_linear8 : 00347 for (i = 0; i < n; i++) 00348 v(i) = read_endian<char>(file, switch_endian) / 128.0; 00349 break; 00350 case enc_linear16 : 00351 for (i = 0; i < n; i++) 00352 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00353 break; 00354 case enc_float : 00355 for (i = 0; i < n; i++) 00356 v(i) = read_endian<float>(file, switch_endian); 00357 break; 00358 case enc_double : 00359 for (i = 0; i < n; i++) 00360 v(i) = read_endian<double>(file, switch_endian); 00361 break; 00362 default : 00363 it_warning("SND_In_File::read(): Unsupported encoding!"); 00364 return false; 00365 } 00366 return file.good(); 00367 } 00368 00370 // 00371 // SND_Out_File 00372 // 00374 SND_Out_File::SND_Out_File() 00375 { 00376 } 00377 00378 SND_Out_File::SND_Out_File(const char *fname, int rate, data_encoding e) 00379 { 00380 open(fname, rate, e); 00381 } 00382 00383 bool SND_Out_File::open(const char *fname, int rate, data_encoding e) 00384 { 00385 if (file.is_open()) 00386 close(); 00387 file.clear(); 00388 is_valid = false; 00389 file.open(fname, ios::out | ios::trunc | ios::binary); 00390 if (!file) 00391 return false; 00392 00393 header.data_size = 0; 00394 header.encoding = static_cast<unsigned int>(e); 00395 header.sample_rate = rate; 00396 header.channels = 1; 00397 00398 if (!write_header(file)) 00399 return false; 00400 00401 is_valid = true; 00402 return true; 00403 } 00404 00405 void SND_Out_File::close() 00406 { 00407 file.seekp(0, ios::end); 00408 header.data_size = static_cast<int>(file.tellp()) - sizeof(header); 00409 write_header(file); 00410 file.close(); 00411 is_valid = false; 00412 } 00413 00414 bool SND_Out_File::seek_write(int pos) 00415 { 00416 if (!good()) 00417 return false; 00418 00419 if (pos < 0) 00420 file.seekp(0, ios::end); 00421 else 00422 file.seekp(sizeof(header) + header.channels * sample_size() * pos); 00423 return true; 00424 } 00425 00426 int SND_Out_File::tell_write() 00427 { 00428 if (!good()) 00429 return -1; 00430 00431 return ((static_cast<int>(file.tellp()) - sizeof(header)) 00432 / (header.channels * sample_size())); 00433 } 00434 00435 bool SND_Out_File::write(const vec &v) 00436 { 00437 if (!good()) 00438 return false; 00439 00440 int i; 00441 00442 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00443 switch (header.encoding) { 00444 case enc_linear8 : 00445 for (i = 0; i < v.size(); i++) 00446 write_endian<char>(file, double_to_char(v(i) * 128.0), switch_endian); 00447 break; 00448 case enc_linear16 : 00449 for (i = 0; i < v.size(); i++) 00450 write_endian<short>(file, double_to_short(v(i) * 32768.0), 00451 switch_endian); 00452 break; 00453 case enc_float : 00454 for (i = 0; i < v.size(); i++) 00455 write_endian<float>(file, static_cast<float>(v(i)), switch_endian); 00456 break; 00457 case enc_double : 00458 for (i = 0; i < v.size(); i++) 00459 write_endian<double>(file, static_cast<double>(v(i)), switch_endian); 00460 break; 00461 default : 00462 it_warning("SND_Out_File::write(): Unsupported encoding!"); 00463 return false; 00464 } 00465 00466 return file.good(); 00467 } 00468 00470 // 00471 // SND_IO_File 00472 // 00474 bool SND_IO_File::open(const char *fname) 00475 { 00476 if (file.is_open()) 00477 close(); 00478 file.clear(); 00479 is_valid = false; 00480 file.open(fname, ios::in | ios::out | ios::binary); 00481 if (!file) 00482 return false; 00483 00484 if (!read_header(file)) { 00485 file.close(); 00486 return false; 00487 } 00488 00489 if (!seek_read(0) || !seek_write(0)) { 00490 file.close(); 00491 return false; 00492 } 00493 00494 is_valid = true; 00495 return true; 00496 } 00497 00498 void SND_IO_File::close() 00499 { 00500 write_header(file); 00501 file.close(); 00502 is_valid = false; 00503 } 00504 00505 bool snd_read(const char *fname, vec &v) 00506 { 00507 SND_In_File file; 00508 00509 if (!file.open(fname)) 00510 return false; 00511 00512 return file.read(v); 00513 } 00514 00515 bool snd_read(const char *fname, vec &v, int beg, int len) 00516 { 00517 SND_In_File file; 00518 00519 if (!file.open(fname)) 00520 return false; 00521 00522 file.seek_read(beg); 00523 return file.read(v, len); 00524 } 00525 00526 bool snd_write(const char *fname, const vec &v, int rate, SND_Format::data_encoding e) 00527 { 00528 SND_Out_File file; 00529 00530 if (!file.open(fname, rate, e)) 00531 return false; 00532 00533 return file.write(v); 00534 } 00535 00536 } // namespace itpp 00537
Generated on Sun Jul 26 08:36:51 2009 for IT++ by Doxygen 1.5.9