Marsyas
0.6.0-alpha
|
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 <marsyas/common_source.h> 00020 #include "OggFileSource.h" 00021 00022 #include <cstdio> 00023 00024 #ifndef WIN32 00025 #include <sys/stat.h> 00026 #include <sys/types.h> 00027 #include <sys/mman.h> 00028 #include <fcntl.h> 00029 #endif 00030 00031 #include <vorbis/vorbisfile.h> 00032 00033 00034 using std::ostringstream; 00035 using namespace Marsyas; 00036 00037 OggFileSource::OggFileSource(mrs_string name):AbsSoundFileSource("OggFileSource", name) 00038 { 00039 //type_ = "OggFileSource"; 00040 //name_ = name; 00041 hasData_ = false; 00042 addControls(); 00043 } 00044 00045 OggFileSource::~OggFileSource() 00046 { 00047 closeFile(); 00048 } 00049 00050 OggFileSource::OggFileSource(const OggFileSource& a):AbsSoundFileSource(a) 00051 { 00052 // type_ = a.type_; 00053 // name_ = a.name_; 00054 // ncontrols_ = a.ncontrols_; 00055 // 00056 // inSamples_ = a.inSamples_; 00057 // inObservations_ = a.inObservations_; 00058 // onSamples_ = a.onSamples_; 00059 // onObservations_ = a.onObservations_; 00060 // dbg_ = a.dbg_; 00061 // mute_ = a.mute_; 00062 ctrl_currentlyPlaying_ = getctrl("mrs_string/currentlyPlaying"); 00063 ctrl_previouslyPlaying_ = getctrl("mrs_string/previouslyPlaying"); 00064 ctrl_regression_ = getctrl("mrs_bool/regression"); 00065 ctrl_currentLabel_ = getctrl("mrs_real/currentLabel"); 00066 ctrl_previousLabel_ = getctrl("mrs_real/previousLabel"); 00067 ctrl_labelNames_ = getctrl("mrs_string/labelNames"); 00068 ctrl_nLabels_ = getctrl("mrs_natural/nLabels"); 00069 } 00070 00071 MarSystem* 00072 OggFileSource::clone() const 00073 { 00074 return new OggFileSource(*this); 00075 } 00076 00077 void 00078 OggFileSource::addControls() 00079 { 00080 // nChannels is one for now 00081 addctrl("mrs_natural/nChannels",1); 00082 addctrl("mrs_natural/bitRate", 160000); 00083 setctrlState("mrs_natural/nChannels", true); 00084 addctrl("mrs_bool/init", false); 00085 setctrlState("mrs_bool/init", true); 00086 addctrl("mrs_bool/hasData", true); 00087 addctrl("mrs_natural/loopPos", (mrs_natural)0); 00088 setctrlState("mrs_natural/loopPos", true); 00089 addctrl("mrs_natural/pos", (mrs_natural)0); 00090 setctrlState("mrs_natural/pos", true); 00091 addctrl("mrs_string/filename", "daufile"); 00092 setctrlState("mrs_string/filename", true); 00093 addctrl("mrs_natural/size", (mrs_natural)0); 00094 addctrl("mrs_string/filetype", "ogg"); 00095 addctrl("mrs_real/repetitions", 1.0); 00096 setctrlState("mrs_real/repetitions", true); 00097 addctrl("mrs_real/duration", -1.0); 00098 setctrlState("mrs_real/duration", true); 00099 00100 addctrl("mrs_natural/advance", 0); 00101 setctrlState("mrs_natural/advance", true); 00102 00103 addctrl("mrs_bool/shuffle", false); 00104 setctrlState("mrs_bool/shuffle", true); 00105 00106 addctrl("mrs_natural/cindex", 0); 00107 setctrlState("mrs_natural/cindex", true); 00108 00109 addctrl("mrs_string/allfilenames", ","); 00110 addctrl("mrs_natural/numFiles", 1); 00111 00112 // addctrl("mrs_string/currentlyPlaying", "daufile"); 00113 00114 addctrl("mrs_string/currentlyPlaying", "doggfile", ctrl_currentlyPlaying_); 00115 addctrl("mrs_string/previouslyPlaying", "doggfile", ctrl_previouslyPlaying_); 00116 addctrl("mrs_bool/regression", false, ctrl_regression_); 00117 addctrl("mrs_real/currentLabel", 0.0, ctrl_currentLabel_); 00118 addctrl("mrs_real/previousLabel", 0.0, ctrl_previousLabel_); 00119 addctrl("mrs_natural/nLabels", 0, ctrl_nLabels_); 00120 addctrl("mrs_string/labelNames", ",", ctrl_labelNames_); 00121 00122 addctrl("mrs_bool/lastTickWithData", false); 00123 addctrl("mrs_bool/currentLastTickWithData", false, ctrl_currentLastTickWithData_); 00124 } 00125 00126 00132 void 00133 OggFileSource::getHeader(mrs_string filename) 00134 { 00135 // if we have a file open already, close it 00136 closeFile(); 00137 mrs_real duration = 0; 00138 mrs_real israte = 22050.0; 00139 mrs_natural nChannels = 1; 00140 mrs_natural size = 0; 00141 hasData_ = false; 00142 mrs_natural bitRate = 128*1024; 00143 00144 FILE* fp = fopen(filename.c_str(), "rb"); 00145 vf = new OggVorbis_File; 00146 00147 /* Using ov_open_callbacks because ov_open fails under windows. */ 00148 if(fp && ov_open_callbacks(fp, vf, NULL, 0, OV_CALLBACKS_DEFAULT) == 0) 00149 { 00150 vi=ov_info(vf,-1); 00151 size = ov_pcm_total(vf,-1); 00152 duration = ov_time_total(vf,-1); 00153 nChannels = vi->channels; 00154 israte = vi->rate; 00155 hasData_ = true; 00156 bitRate = ov_bitrate(vf, -1); 00157 } 00158 else 00159 { 00160 (void) filename; // in case the macro is not expanded 00161 MRSWARN(filename + " does not appear to be an Ogg bitstream."); 00162 } 00163 setctrl("mrs_natural/nChannels", nChannels); 00164 setctrl("mrs_real/israte", israte); 00165 setctrl("mrs_natural/size", size); 00166 setctrl("mrs_bool/hasData", hasData_); 00167 setctrl("mrs_natural/bitRate", bitRate); 00168 updControl("mrs_real/duration", duration); 00169 } 00170 00181 void 00182 OggFileSource::myUpdate(MarControlPtr sender) 00183 { 00184 (void) sender; //suppress warning of unused parameter(s) 00185 MRSDIAG("OggFileSource::myUpdate"); 00186 00187 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples")); 00188 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations")); 00189 setctrl("mrs_real/osrate", getctrl("mrs_real/israte")); 00190 00191 mrs_natural pos = getctrl("mrs_natural/pos")->to<mrs_natural>(); 00192 mrs_natural size = getctrl("mrs_natural/size")->to<mrs_natural>(); 00193 00194 // if the user has seeked somewhere in the file 00195 if ( pos < size && pos != ov_pcm_tell(vf)) 00196 { 00197 ov_pcm_seek(vf, pos_); 00198 } 00199 00200 } 00201 00207 void OggFileSource::myProcess(realvec& in, realvec& out) 00208 { 00209 (void) in; 00210 //checkFlow(in,out); 00211 00212 if (hasData_) 00213 { 00214 /*mrs_real duration = getctrl("mrs_real/duration")->to<mrs_real>(); 00215 mrs_real rate = getctrl("mrs_real/israte")->to<mrs_real>(); 00216 */ 00217 mrs_natural observations = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00218 mrs_natural samples = getctrl("mrs_natural/inSamples")->to<mrs_natural>(); 00219 mrs_natural israte = (mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>(); 00220 00221 //mrs_natural size = (mrs_natural)(duration * rate); 00222 mrs_natural size = vi->channels*sizeof(short int)*((mrs_natural)(observations * samples)); 00223 char* buf = new char[size]; 00224 int bitstream=0; 00225 mrs_natural read = 0; 00226 long r = 0; 00227 bool eof = false; 00228 do 00229 { 00230 r = ov_read(vf, buf+read, size-read, 0, 2/*use 1 for 8bit samples..use 2 for 16*/, 1, &bitstream); 00231 if(r <= 0) 00232 { 00233 eof = true; 00234 break; 00235 } 00236 read += (mrs_natural) r; 00237 } 00238 while(read < size); 00239 00240 // getLinear16(out); for (o=0; o < inObservations_; o++) { 00241 const double peak = 1.0/32768; // normalize 24-bit sample 00242 short int* src = (short int*)buf; 00243 for (mrs_natural o=0; o < observations; o++) 00244 { 00245 for (mrs_natural t=0; t < samples; t++) 00246 { 00247 const unsigned int i=vi->channels*t; 00248 switch(vi->channels) 00249 { 00250 case 2: 00251 out(0,t) = (src[i] + src[i+1])*peak/2; 00252 break; 00253 default: 00254 out(0,t) = src[i]*peak; 00255 } 00256 } 00257 } 00258 delete [] buf; 00259 if(eof) 00260 closeFile(); 00261 00262 } 00263 else 00264 out.setval(0.0); 00265 if (hasData_) 00266 { 00267 // hasData_ = (samplesOut_ < repetitions_ * csize_); 00268 } 00269 else 00270 { 00271 // if hasData_ was false already it got set in fillStream 00272 MRSWARN("OggFileSource: track ended."); 00273 } 00274 } 00275 00283 void OggFileSource::closeFile() 00284 { 00285 00286 if(hasData_) 00287 { 00288 ov_clear(vf); 00289 delete vf; 00290 } 00291 00292 hasData_ = false; 00293 }