IT++ Logo
audiofile.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Wed Jul 27 2011 16:27:05 for IT++ by Doxygen 1.7.4