Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/WavFileSink.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2006 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "../common_source.h"
00020 #include "WavFileSink.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00025 WavFileSink::WavFileSink(mrs_string name):AbsSoundFileSink("WavFileSink",name)
00026 {
00027   //type_ = "WavFileSink";
00028   //name_ = name;
00029 
00030   sfp_ = NULL;
00031   sdata_ = NULL;
00032   cdata_ = NULL;
00033 
00034   addControls();
00035 }
00036 
00037 WavFileSink::~WavFileSink()
00038 {
00039   delete [] sdata_;
00040   delete [] cdata_;
00041   if (sfp_) fclose(sfp_);
00042 }
00043 
00044 MarSystem*
00045 WavFileSink::clone() const
00046 {
00047   return new WavFileSink(*this);
00048 }
00049 
00050 void
00051 WavFileSink::addControls()
00052 {
00053   addctrl("mrs_string/filename", "default");
00054   setctrlState("mrs_string/filename", true);
00055 
00056   // lossy encoding specific controls
00057   addctrl("mrs_natural/bitrate", 128);
00058   setctrlState("mrs_natural/bitrate", true);
00059   addctrl("mrs_natural/encodingQuality", 2);
00060   setctrlState("mrs_natural/encodingQuality", true);
00061   addctrl("mrs_string/id3tags", "id3tags");  // 1: track one O Blues genreopen
00062   setctrlState("mrs_string/id3tags", true);
00063 
00064 }
00065 
00066 bool
00067 WavFileSink::checkExtension(mrs_string filename)
00068 {
00069   FileName fn(filename);
00070   mrs_string wavext  = "wav";
00071   mrs_string sndext = "snd";
00072 
00073   if (fn.ext() == wavext)
00074     return true;
00075   else
00076     return false;
00077 }
00078 
00079 void
00080 WavFileSink::myUpdate(MarControlPtr sender)
00081 {
00082   (void) sender;  //suppress warning of unused parameter(s)
00083   MRSDIAG("WavFileSink::myUpdate");
00084 
00085   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00086   setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations"));
00087   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00088 
00089   nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00090 
00091   delete [] sdata_;
00092   delete [] cdata_;
00093 
00094   sdata_ = new short[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_];
00095   cdata_ = new unsigned char[getctrl("mrs_natural/inSamples")->to<mrs_natural>() * nChannels_];
00096 
00097   filename_ = getctrl("mrs_string/filename")->to<mrs_string>();
00098 }
00099 
00100 void
00101 WavFileSink::putHeader(mrs_string filename)
00102 {
00103   mrs_natural nChannels = (mrs_natural)getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00104   sfp_ = fopen(filename.c_str(), "wb");
00105 
00106   written_ = 0;
00107 
00108   /* prepare header */
00109   hdr_.riff[0] = 'R';
00110   hdr_.riff[1] = 'I';
00111   hdr_.riff[2] = 'F';
00112   hdr_.riff[3] = 'F';
00113 
00114   hdr_.file_size = 44;
00115 
00116   hdr_.wave[0] = 'W';
00117   hdr_.wave[1] = 'A';
00118   hdr_.wave[2] = 'V';
00119   hdr_.wave[3] = 'E';
00120 
00121   hdr_.fmt[0] = 'f';
00122   hdr_.fmt[1] = 'm';
00123   hdr_.fmt[2] = 't';
00124   hdr_.fmt[3] = ' ';
00125 
00126 #if defined(MARSYAS_BIGENDIAN)
00127   hdr_.chunk_size = ByteSwapLong(16);
00128   hdr_.format_tag = ByteSwapShort(1);
00129   hdr_.num_chans = ByteSwapShort((signed short)nChannels);
00130   hdr_.sample_rate = ByteSwapLong((mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>());
00131   hdr_.bytes_per_sec = ByteSwapLong(hdr_.sample_rate * 2);
00132   hdr_.bytes_per_samp = ByteSwapShort(2);
00133   hdr_.bits_per_samp = ByteSwapShort(16);
00134   hdr_.data_length = ByteSwapLong(0);
00135 #else
00136   hdr_.chunk_size = 16;
00137   hdr_.format_tag = 1;
00138   hdr_.num_chans = (signed short)nChannels;
00139   hdr_.sample_rate = (mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>();
00140   hdr_.bytes_per_sec = hdr_.sample_rate * 2;
00141   hdr_.bytes_per_samp = 2;
00142   hdr_.bits_per_samp = 16;
00143   hdr_.data_length = 0;
00144 #endif
00145 
00146   hdr_.data[0] = 'd';
00147   hdr_.data[1] = 'a';
00148   hdr_.data[2] = 't';
00149   hdr_.data[3] = 'a';
00150 
00151   fwrite(&hdr_, 4, 11, sfp_);
00152 
00153   sfp_begin_ = ftell(sfp_);
00154 }
00155 
00156 unsigned long
00157 WavFileSink::ByteSwapLong(unsigned long nLongNumber)
00158 {
00159   return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+
00160           ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24));
00161 }
00162 
00163 unsigned short
00164 WavFileSink::ByteSwapShort (unsigned short nValue)
00165 {
00166   return (static_cast<unsigned short>((nValue & 0xff00) >> 8) |
00167           static_cast<unsigned short>((nValue & 0xff) << 8));
00168 }
00169 
00170 void
00171 WavFileSink::putLinear16Swap(realvec& slice)
00172 {
00173   for (mrs_natural c=0; c < nChannels_; ++c)
00174     for (mrs_natural t=0; t < inSamples_; t++)
00175     {
00176 #if defined(MARSYAS_BIGENDIAN)
00177       sdata_[t*nChannels_ + c] = ByteSwapShort((short)(slice(c,t) * PCM_MAXSHRT));
00178 #else
00179       sdata_[t*nChannels_ + c] = (short)(slice(c,t) * PCM_MAXSHRT);
00180 #endif
00181     }
00182 
00183   if ((mrs_natural)fwrite(sdata_, sizeof(short), nChannels_ * inSamples_, sfp_) != nChannels_ * inSamples_)
00184   {
00185     MRSERR("Problem: could not write window to file " + filename_);
00186   }
00187 }
00188 
00189 void
00190 WavFileSink::myProcess(realvec& in, realvec& out)
00191 {
00192   mrs_natural o,t;
00193 
00194   // copy input to output
00195   for (o=0; o < inObservations_; o++)
00196     for (t=0; t < inSamples_; t++)
00197     {
00198       out(o,t) = in(o,t);
00199     }
00200 
00201   long fileSize;
00202   fpos_ = ftell(sfp_);
00203 
00204   // jump to start and write data size
00205   fseek(sfp_, 40, SEEK_SET);
00206   written_ += inSamples_;
00207   fileSize = (written_ * 2 * nChannels_);
00208 #if defined(MARSYAS_BIGENDIAN)
00209   fileSize =    ByteSwapLong(fileSize);
00210 #endif
00211 
00212   fwrite(&fileSize, 4, 1, sfp_);
00213   fseek(sfp_, fpos_, SEEK_SET);
00214 
00215   putLinear16Swap(in);
00216 }
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234