Marsyas
0.6.0-alpha
|
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