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   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 
SourceForge Logo

Generated on Sun Dec 9 17:38:50 2007 for IT++ by Doxygen 1.5.4