Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/SoundFileSink.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2005 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 "SoundFileSink.h"
00021 
00022 #ifdef MARSYAS_LAME
00023 #include "MP3FileSink.h"
00024 #endif
00025 
00026 using namespace std;
00027 using namespace Marsyas;
00028 
00029 #define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
00030 #define FloatToUnsigned(f)      ((unsigned long)(((long)(f - 2147483648.0)) + 2147483647L) + 1)
00031 
00032 
00033 
00034 SoundFileSink::SoundFileSink(mrs_string name):
00035   MarSystem("SoundFileSink",name),
00036   backend_(0)
00037 {
00038   addControls();
00039 }
00040 
00041 
00042 SoundFileSink::SoundFileSink(const SoundFileSink& a):
00043   MarSystem(a),
00044   backend_(0)
00045 {
00046 }
00047 
00048 
00049 MarSystem*
00050 SoundFileSink::clone() const
00051 {
00052   return new SoundFileSink(*this);
00053 }
00054 
00055 SoundFileSink::~SoundFileSink()
00056 {
00057   delete backend_;
00058 }
00059 
00060 void
00061 SoundFileSink::addControls()
00062 {
00063   addctrl("mrs_string/filename", string());
00064   setctrlState("mrs_string/filename", true);
00065   // lossy encoding specific controls
00066   addctrl("mrs_natural/bitrate", 128);
00067   setctrlState("mrs_natural/bitrate", true);
00068   addctrl("mrs_natural/encodingQuality", 2);
00069   setctrlState("mrs_natural/encodingQuality", true);
00070   addctrl("mrs_string/id3tags", "noTitle|noArtist|noAlbum|1978|noComment|1|0");  // 1: track one O Blues genreopen
00071   setctrlState("mrs_string/id3tags", true);
00072 
00073   // pauses the output.
00074   addctrl("mrs_bool/pause", false);
00075 }
00076 void
00077 SoundFileSink::putHeader()
00078 {
00079   assert(!filename_.empty());
00080   assert(backend_ != 0);
00081 
00082   backend_->putHeader(filename_);
00083 }
00084 
00085 
00086 
00087 bool
00088 SoundFileSink::updateBackend()
00089 {
00090   delete backend_;
00091   backend_ = 0;
00092 
00093   if (filename_.empty())
00094     return false;
00095 
00096   // check if file exists
00097   bool file_exists;
00098   {
00099     FILE *file = fopen(filename_.c_str(), "wb");
00100     file_exists = file != 0;
00101     if (file)
00102       fclose(file);
00103   }
00104   if (!file_exists)
00105   {
00106     MRSWARN("SoundFileSink: Failed to open file for writing: " << filename_);
00107     return false;
00108   }
00109 
00110   // try to open file with appropriate format
00111   mrs_string::size_type pos = filename_.rfind(".", filename_.length());
00112   mrs_string ext;
00113   if (pos != mrs_string::npos)
00114     ext = filename_.substr(pos);
00115 
00116   if (ext == ".au")
00117   {
00118     backend_ = new AuFileSink(getName());
00119   }
00120   else if (ext == ".wav")
00121   {
00122     backend_ = new WavFileSink(getName());
00123   }
00124 #ifdef MARSYAS_LAME
00125   else if (ext == ".mp3")
00126   {
00127     backend_ = new MP3FileSink(getName());
00128   }
00129 #endif
00130   else
00131   {
00132     MRSWARN("Unknown file extension: " << filename_);
00133     return false;
00134   }
00135 
00136   return true;
00137 }
00138 
00139 void
00140 SoundFileSink::myUpdate(MarControlPtr sender)
00141 {
00142   (void) sender;  //suppress warning of unused parameter(s)
00143 
00144   const string &new_filename = getctrl("mrs_string/filename")->to<mrs_string>();
00145 
00146   if (new_filename != filename_)
00147   {
00148     filename_ = new_filename;
00149 
00150     if (updateBackend())
00151     {
00152       backend_->setctrl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples"));
00153       backend_->setctrl("mrs_natural/inObservations", getctrl("mrs_natural/inObservations"));
00154       backend_->setctrl("mrs_real/israte", getctrl("mrs_real/israte"));
00155       backend_->update();
00156 
00157       putHeader();
00158       filename_ = getctrl("mrs_string/filename")->to<mrs_string>();
00159 
00160       setctrl("mrs_real/israte", backend_->getctrl("mrs_real/israte"));
00161     }
00162   }
00163 
00164   if (backend_)
00165   {
00166     backend_->setctrl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples"));
00167     backend_->setctrl("mrs_natural/inObservations", getctrl("mrs_natural/inObservations"));
00168     backend_->setctrl("mrs_real/israte", getctrl("mrs_real/israte"));
00169     // [ML] the filename is now propagated to the child
00170     backend_->setctrl("mrs_string/filename", getctrl("mrs_string/filename"));
00171     backend_->setctrl("mrs_natural/bitrate", getctrl("mrs_natural/bitrate"));
00172     backend_->setctrl("mrs_natural/encodingQuality", getctrl("mrs_natural/encodingQuality"));
00173     backend_->setctrl("mrs_string/id3tags", getctrl("mrs_string/id3tags"));
00174     backend_->update();
00175 
00176     setctrl("mrs_natural/onSamples", backend_->getctrl("mrs_natural/onSamples"));
00177     setctrl("mrs_natural/onObservations", backend_->getctrl("mrs_natural/onObservations"));
00178     setctrl("mrs_real/osrate", backend_->getctrl("mrs_real/israte"));
00179   }
00180 }
00181 
00182 
00183 void
00184 SoundFileSink::myProcess(realvec& in, realvec& out)
00185 {
00186 
00187   mrs_bool paused = getctrl("mrs_bool/pause")->to<mrs_bool>();
00188 
00189   if ((backend_ != NULL) &&  (paused==false))
00190   {
00191     backend_->process(in,out);
00192   }
00193 
00194 
00195 }
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 void
00206 SoundFileSink::putFloat(mrs_natural c, realvec& win)
00207 {
00208   (void) c;
00209   (void) win;
00210   MRSWARN("SoundFileSink::putFloat not implemented");
00211 }
00212 
00213 
00214 
00215 
00216