IT++ Logo Newcom Logo

audiofile.cpp

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

Generated on Fri Jun 8 00:27:17 2007 for IT++ by Doxygen 1.5.2