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 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 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 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 = file.tellg(); 00075 file.seekg(0, ios::beg); 00076 00077 bool switch_endian = check_big_endianness(); // 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 = check_big_endianness(); // 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 = check_big_endianness(); // 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 = file.tellg(); 00124 file.seekg(0, ios::beg); 00125 00126 bool switch_endian = !check_big_endianness(); // 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 = !check_big_endianness(); // 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 = !check_big_endianness(); // 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 : return 1; 00183 case enc_alaw8 : return 1; 00184 case enc_linear8 : return 1; 00185 case enc_linear16 : return 2; 00186 case enc_linear24 : return 3; 00187 case enc_linear32 : return 4; 00188 case enc_float : return 4; 00189 case enc_double : return 8; 00190 } 00191 return 0; 00192 } 00193 00194 bool SND_Format::read_header(std::istream &f) 00195 { 00196 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00197 f.seekg(0); 00198 header.magic = read_endian<unsigned int>(f, switch_endian); 00199 header.hdr_size = read_endian<unsigned int>(f, switch_endian); 00200 header.data_size = read_endian<unsigned int>(f, switch_endian); 00201 header.encoding = read_endian<unsigned int>(f, switch_endian); 00202 header.sample_rate = read_endian<unsigned int>(f, switch_endian); 00203 header.channels = read_endian<unsigned int>(f, switch_endian); 00204 f.read(header.info, SND_INFO_LEN); 00205 if (!f || header.magic != SND_MAGIC) { 00206 std::cerr << header.magic << " != " << SND_MAGIC << std::endl; 00207 it_warning("SND_Format::read_header(): This is not a .snd file!"); 00208 return false; 00209 } 00210 f.seekg(header.hdr_size); 00211 00212 return f.good(); 00213 } 00214 00215 bool SND_Format::write_header(std::ostream &f) 00216 { 00217 f.seekp(0); 00218 header.magic = SND_MAGIC; 00219 header.hdr_size = sizeof(header); 00220 memset(header.info, 0, SND_INFO_LEN); 00221 00222 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00223 write_endian<unsigned int>(f, header.magic, switch_endian); 00224 write_endian<unsigned int>(f, header.hdr_size, switch_endian); 00225 write_endian<unsigned int>(f, header.data_size, switch_endian); 00226 write_endian<unsigned int>(f, header.encoding, switch_endian); 00227 write_endian<unsigned int>(f, header.sample_rate, switch_endian); 00228 write_endian<unsigned int>(f, header.channels, switch_endian); 00229 f.write(reinterpret_cast<char *>(&header.info), SND_INFO_LEN); 00230 00231 return f.good(); 00232 } 00233 00235 // 00236 // SND_In_File 00237 // 00239 00240 SND_In_File::SND_In_File() 00241 { 00242 } 00243 00244 SND_In_File::SND_In_File(const char *fname) 00245 { 00246 open(fname); 00247 } 00248 00249 bool SND_In_File::open(const char *fname) 00250 { 00251 if (file.is_open()) 00252 close(); 00253 file.clear(); 00254 is_valid = false; 00255 file.open(fname, ios::in | ios::binary); 00256 if (!file) 00257 return false; 00258 if (!read_header(file)) { 00259 file.close(); 00260 return false; 00261 } 00262 00263 is_valid = true; 00264 return true; 00265 } 00266 00267 void SND_In_File::close() 00268 { 00269 file.close(); 00270 is_valid = false; 00271 } 00272 00273 bool SND_In_File::seek_read(int pos) 00274 { 00275 if (pos < 0) 00276 file.seekg(0, ios::end); 00277 else 00278 file.seekg(header.hdr_size + header.channels * sample_size() * pos); 00279 return true; 00280 } 00281 00282 int SND_In_File::tell_read() 00283 { 00284 if (!good()) 00285 return -1; 00286 00287 return ((static_cast<int>(file.tellg()) - sizeof(header)) 00288 / (header.channels * sample_size())); 00289 } 00290 00291 bool SND_In_File::read(vec &v) 00292 { 00293 if (!good()) 00294 return false; 00295 00296 int i, n; 00297 00298 n = samples(); 00299 v.set_size(n, false); 00300 seek_read(0); 00301 00302 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00303 switch (header.encoding) { 00304 case enc_linear8 : 00305 for (i=0; i<n; i++) 00306 v(i) = read_endian<char>(file, switch_endian) / 128.0; 00307 break; 00308 case enc_linear16 : 00309 for (i=0; i<n; i++) 00310 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00311 break; 00312 case enc_float : 00313 for (i=0; i<n; i++) 00314 v(i) = read_endian<float>(file, switch_endian); 00315 break; 00316 case enc_double : 00317 for (i=0; i<n; i++) 00318 v(i) = read_endian<double>(file, switch_endian); 00319 break; 00320 default : 00321 it_warning("SND_In_File::read(): Unsupported encoding!"); 00322 return false; 00323 } 00324 return file.good(); 00325 } 00326 00327 bool SND_In_File::read(vec &v, int n) 00328 { 00329 if (!good()) 00330 return false; 00331 00332 int i; 00333 00334 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00335 v.set_size(n, false); 00336 switch (header.encoding) { 00337 case enc_linear8 : 00338 for (i=0; i<n; i++) 00339 v(i) = read_endian<char>(file, switch_endian) / 128.0; 00340 break; 00341 case enc_linear16 : 00342 for (i=0; i<n; i++) 00343 v(i) = read_endian<short>(file, switch_endian) / 32768.0; 00344 break; 00345 case enc_float : 00346 for (i=0; i<n; i++) 00347 v(i) = read_endian<float>(file, switch_endian); 00348 break; 00349 case enc_double : 00350 for (i=0; i<n; i++) 00351 v(i) = read_endian<double>(file, switch_endian); 00352 break; 00353 default : 00354 it_warning("SND_In_File::read(): Unsupported encoding!"); 00355 return false; 00356 } 00357 return file.good(); 00358 } 00359 00361 // 00362 // SND_Out_File 00363 // 00365 SND_Out_File::SND_Out_File() 00366 { 00367 } 00368 00369 SND_Out_File::SND_Out_File(const char *fname, int rate, data_encoding e) 00370 { 00371 open(fname, rate, e); 00372 } 00373 00374 bool SND_Out_File::open(const char *fname, int rate, data_encoding e) 00375 { 00376 if (file.is_open()) 00377 close(); 00378 file.clear(); 00379 is_valid = false; 00380 file.open(fname, ios::out | ios::trunc | ios::binary); 00381 if (!file) 00382 return false; 00383 00384 header.data_size = 0; 00385 header.encoding = static_cast<unsigned int>(e); 00386 header.sample_rate = rate; 00387 header.channels = 1; 00388 00389 if (!write_header(file)) 00390 return false; 00391 00392 is_valid = true; 00393 return true; 00394 } 00395 00396 void SND_Out_File::close() 00397 { 00398 file.seekp(0, ios::end); 00399 header.data_size = static_cast<int>(file.tellp()) - sizeof(header); 00400 write_header(file); 00401 file.close(); 00402 is_valid = false; 00403 } 00404 00405 bool SND_Out_File::seek_write(int pos) 00406 { 00407 if (!good()) 00408 return false; 00409 00410 if (pos < 0) 00411 file.seekp(0, ios::end); 00412 else 00413 file.seekp(sizeof(header) + header.channels * sample_size() * pos); 00414 return true; 00415 } 00416 00417 int SND_Out_File::tell_write() 00418 { 00419 if (!good()) 00420 return -1; 00421 00422 return ((static_cast<int>(file.tellp()) - sizeof(header)) 00423 / (header.channels * sample_size())); 00424 } 00425 00426 bool SND_Out_File::write(const vec &v) 00427 { 00428 if (!good()) 00429 return false; 00430 00431 int i; 00432 00433 bool switch_endian = !check_big_endianness(); // if LITTLE_ENDIAN than switch 00434 switch (header.encoding) { 00435 case enc_linear8 : 00436 for (i=0; i<v.size(); i++) 00437 write_endian<char>(file, double_to_char(v(i) * 128.0), switch_endian); 00438 break; 00439 case enc_linear16 : 00440 for (i=0; i<v.size(); i++) 00441 write_endian<short>(file, double_to_short(v(i) * 32768.0), 00442 switch_endian); 00443 break; 00444 case enc_float : 00445 for (i=0; i<v.size(); i++) 00446 write_endian<float>(file, static_cast<float>(v(i)), switch_endian); 00447 break; 00448 case enc_double : 00449 for (i=0; i<v.size(); i++) 00450 write_endian<double>(file, static_cast<double>(v(i)), switch_endian); 00451 break; 00452 default : 00453 it_warning("SND_Out_File::write(): Unsupported encoding!"); 00454 return false; 00455 } 00456 00457 return file.good(); 00458 } 00459 00461 // 00462 // SND_IO_File 00463 // 00465 bool SND_IO_File::open(const char *fname) 00466 { 00467 if (file.is_open()) 00468 close(); 00469 file.clear(); 00470 is_valid = false; 00471 file.open(fname, ios::in | ios::out | ios::binary); 00472 if (!file) 00473 return false; 00474 00475 if (!read_header(file)) { 00476 file.close(); 00477 return false; 00478 } 00479 00480 if (!seek_read(0) || !seek_write(0)) { 00481 file.close(); 00482 return false; 00483 } 00484 00485 is_valid = true; 00486 return true; 00487 } 00488 00489 void SND_IO_File::close() 00490 { 00491 write_header(file); 00492 file.close(); 00493 is_valid = false; 00494 } 00495 00496 bool snd_read(const char *fname, vec &v) 00497 { 00498 SND_In_File file; 00499 00500 if (!file.open(fname)) 00501 return false; 00502 00503 return file.read(v); 00504 } 00505 00506 bool snd_read(const char *fname, vec &v, int beg, int len) 00507 { 00508 SND_In_File file; 00509 00510 if (!file.open(fname)) 00511 return false; 00512 00513 file.seek_read(beg); 00514 return file.read(v, len); 00515 } 00516 00517 bool snd_write(const char *fname, const vec &v, int rate, SND_Format::data_encoding e) 00518 { 00519 SND_Out_File file; 00520 00521 if (!file.open(fname, rate, e)) 00522 return false; 00523 00524 return file.write(v); 00525 } 00526 00527 } // namespace itpp 00528
Generated on Sun Dec 9 17:26:19 2007 for IT++ by Doxygen 1.5.4