Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/SoundFileSource2.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2010 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 "SoundFileSource2.h"
00020 #include "../common_source.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00025 SoundFileSource2::SoundFileSource2(mrs_string name):MarSystem("SoundFileSource2",name)
00026 {
00027   src_ = NULL;
00028 
00029   addControls();
00030 
00031   //create a default file source object
00032   fileReady(false);
00033 }
00034 
00035 SoundFileSource2::~SoundFileSource2()
00036 {
00037   delete src_;
00038 }
00039 
00040 SoundFileSource2::SoundFileSource2(const SoundFileSource2& a):MarSystem(a)//[!]
00041 {
00042   src_ = new AbsSoundFileSource2("AbsSoundFileSource2", name_);
00043   filename_ = "defaultfile";
00044 }
00045 
00046 MarSystem*
00047 SoundFileSource2::clone() const
00048 {
00049   return new SoundFileSource2(*this);
00050 }
00051 
00052 void
00053 SoundFileSource2::fileReady(bool ready)
00054 {
00055   if(ready)
00056   {
00057     //...read and setup audio file at src_ level
00058     src_->updControl("mrs_string/filename", getctrl("mrs_string/filename"));
00059 
00060     //check if audio file header was read  without errors
00061     //(if an error occurred, the filename is set to "defaultfile" by src_ )
00062     mrs_string filename = src_->getctrl("mrs_string/filename")->to<mrs_string>();
00063     if (filename == "defaultfile")
00064     {
00065       fileReady(false);
00066       return;
00067     }
00068     setctrl("mrs_string/filename", filename);
00069     filename_ = filename;
00070 
00071     setctrl("mrs_bool/hasData", src_->getctrl("mrs_bool/hasData"));
00072 
00073     //rewind
00074     setctrl("mrs_natural/pos", 0);
00075   }
00076   else
00077   {
00078     //set audio file object to a dummy audio file reader
00079     delete src_;
00080     src_ = new AbsSoundFileSource2("AbsSoundFileSource2", name_);
00081 
00082     //...set controls to a default state
00083     setctrl("mrs_string/filename", "defaultfile");
00084     filename_ = "defaultfile";
00085 
00086     setctrl("mrs_natural/nChannels", (mrs_natural)1);
00087     setctrl("mrs_real/israte", MRS_DEFAULT_SLICE_SRATE);
00088     setctrl("mrs_bool/hasData", false);
00089 
00090     //rewind
00091     setctrl("mrs_natural/pos", 0);
00092   }
00093 }
00094 
00095 void
00096 SoundFileSource2::addControls()
00097 {
00098   //read/write controls (controls with state)
00099   addctrl("mrs_string/filename", "defaultfile");
00100   setctrlState("mrs_string/filename", true);
00101   addctrl("mrs_natural/pos", (mrs_natural)0);
00102   setctrlState("mrs_natural/pos", true);
00103 
00104   //read-only controls (stateless)
00105   addctrl("mrs_bool/hasData", true);
00106   addctrl("mrs_natural/nChannels",(mrs_natural)1);
00107   addctrl("mrs_natural/size", (mrs_natural)0);
00108 }
00109 
00110 void
00111 SoundFileSource2::myUpdate(MarControlPtr sender)
00112 {
00113   (void) sender;  //suppress warning of unused parameter(s)
00114   MRSDIAG("SoundFileSource2::localUpdate");
00115 
00116   //if file name changed, open new audio file
00117   mrs_string filename = getctrl("mrs_string/filename")->to<mrs_string>();
00118   if (filename_ != filename)
00119   {
00120     //if valid audio file format, create corresponding file object (src_)...
00121     if (checkType() == true)
00122     {
00123       //read audio file header and configure objects accordingly
00124       fileReady(true);
00125     }
00126     else //if empty or invalid filename...
00127     {
00128       //...go to a default (dummy) state
00129       fileReady(false);
00130     }
00131   }
00132 
00133   //pass configuration to file source object (src_) and update it
00134   src_->setctrl("mrs_natural/pos", getctrl("mrs_natural/pos"));
00135   src_->setctrl("mrs_bool/hasData", getctrl("mrs_bool/hasData"));
00136   //avoid calling src_->update unless it's really necessary
00137   if(getctrl("mrs_natural/inSamples") != src_->getctrl("mrs_natural/inSamples") ||
00138       getctrl("mrs_natural/inObservations") != src_->getctrl("mrs_natural/inObservations"))
00139   {
00140     src_->setctrl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples"));
00141     src_->setctrl("mrs_natural/inObservations", getctrl("mrs_natural/inObservations"));
00142     src_->update();
00143   }
00144 
00145   //sync controls with file source object
00146   setctrl("mrs_natural/onSamples", src_->getctrl("mrs_natural/onSamples"));
00147   setctrl("mrs_natural/onObservations", src_->getctrl("mrs_natural/onObservations"));
00148   //setctrl("mrs_real/israte", src_->getctrl("mrs_real/israte"));
00149   setctrl("mrs_real/osrate", src_->getctrl("mrs_real/osrate"));
00150   setctrl("mrs_string/onObsNames", src_->getctrl("mrs_string/onObsNames"));
00151 
00152   setctrl("mrs_natural/nChannels", src_->getctrl("mrs_natural/nChannels"));
00153   setctrl("mrs_bool/hasData", src_->getctrl("mrs_bool/hasData"));
00154   setctrl("mrs_natural/size", src_->getctrl("mrs_natural/size"));
00155   setctrl("mrs_natural/pos", src_->getctrl("mrs_natural/pos"));
00156 }
00157 
00158 bool
00159 SoundFileSource2::checkType()
00160 {
00161   mrs_string filename = getctrl("mrs_string/filename")->to<mrs_string>();
00162 
00163   if (filename == "defaultfile")
00164   {
00165     MRSWARN("SoundFileSource2::checkType: empty filename");
00166     return false;
00167   }
00168 
00169   //check if file exists
00170   FILE * sfp = fopen(filename.c_str(), "r");
00171   if (sfp == NULL)
00172   {
00173     mrs_string wrn = "SoundFileSource2::checkType: Problem opening file ";
00174     wrn += filename;
00175     MRSWARN(wrn);
00176     return false;
00177   }
00178   fclose(sfp);
00179 
00180   // try to open file with appropriate format
00181   mrs_string::size_type pos = filename.rfind(".", filename.length());
00182   mrs_string ext;
00183 
00184   if (pos == mrs_string::npos)
00185     ext = "";
00186   else
00187     ext = filename.substr(pos, filename.length());
00188   /*if (ext == ".au")
00189     {
00190     delete src_;
00191     src_ = new AuFileSource(name_);
00192     }
00193     else
00194   */
00195   if (ext == ".wav")
00196   {
00197     delete src_;
00198     src_ = new WavFileSource2(name_);
00199   }
00200   /*
00201     else if (ext == ".raw")
00202     {
00203     delete src_;
00204     src_ = new RawFileSource(name_);
00205     }
00206     else if (ext == ".mf")
00207     {
00208     delete src_;
00209     src_ = new CollectionFileSource(name_);
00210     }
00211     #ifdef MAD_MP3
00212     else if (ext == ".mp3")
00213     {
00214     delete src_;
00215     src_ = new MP3FileSource(name_);
00216     }
00217     #endif
00218     #ifdef OGG_VORBIS
00219     else if (ext == ".ogg")
00220     {
00221     cout << "OGG" << endl;
00222     delete src_;
00223     src_ = new OggFileSource(name_);
00224     }
00225     #endif
00226   */
00227   else
00228   {
00229     if (filename != "defaultfile")
00230     {
00231       mrs_string wrn = "Unsupported format for file ";
00232       wrn += filename;
00233       MRSWARN(wrn);
00234       return false;
00235     }
00236     else
00237       return false;
00238   }
00239   return true;
00240 }
00241 
00242 
00243 realvec&
00244 SoundFileSource2::getAudioRegion(mrs_natural startSample, mrs_natural endSample)
00245 {
00246   return src_->getAudioRegion(startSample, endSample);
00247 }
00248 
00249 void
00250 SoundFileSource2::myProcess(realvec& in, realvec &out)
00251 {
00252   //read audio data from audio file
00253   src_->process(in,out);
00254 
00255   //sync play controls (no update needed!)
00256   setctrl("mrs_natural/pos", src_->getctrl("mrs_natural/pos"));
00257   setctrl("mrs_bool/hasData", src_->getctrl("mrs_bool/hasData"));
00258 
00259   //if muted, replace output data with silence
00260   if(getctrl("mrs_bool/mute")->to<mrs_bool>())
00261     out.setval(0.0);
00262 }