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