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