IT++ Logo

audiofile.cpp

Go to the documentation of this file.
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 
SourceForge Logo

Generated on Thu Apr 23 20:04:05 2009 for IT++ by Doxygen 1.5.8