00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.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 #ifdef MARSYAS_VORBIS
00032 #include <vorbis/vorbisfile.h>
00033 #endif
00034
00035
00036 using std::ostringstream;
00037 using namespace Marsyas;
00038
00039 OggFileSource::OggFileSource(mrs_string name):AbsSoundFileSource("OggFileSource", name)
00040 {
00041
00042
00043 hasData_ = false;
00044 addControls();
00045 }
00046
00047 OggFileSource::~OggFileSource()
00048 {
00049 closeFile();
00050 }
00051
00052 OggFileSource::OggFileSource(const OggFileSource& a):AbsSoundFileSource(a)
00053 {
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 ctrl_currentlyPlaying_ = getctrl("mrs_string/currentlyPlaying");
00065 ctrl_regression_ = getctrl("mrs_bool/regression");
00066 ctrl_currentLabel_ = getctrl("mrs_real/currentLabel");
00067 ctrl_previousLabel_ = getctrl("mrs_real/previousLabel");
00068 ctrl_labelNames_ = getctrl("mrs_string/labelNames");
00069 ctrl_nLabels_ = getctrl("mrs_natural/nLabels");
00070 }
00071
00072 MarSystem*
00073 OggFileSource::clone() const
00074 {
00075 return new OggFileSource(*this);
00076 }
00077
00078 void
00079 OggFileSource::addControls()
00080 {
00081
00082 addctrl("mrs_natural/nChannels",1);
00083 addctrl("mrs_natural/bitRate", 160000);
00084 setctrlState("mrs_natural/nChannels", true);
00085 addctrl("mrs_bool/init", false);
00086 setctrlState("mrs_bool/init", true);
00087 addctrl("mrs_bool/hasData", true);
00088 addctrl("mrs_natural/loopPos", (mrs_natural)0);
00089 setctrlState("mrs_natural/loopPos", true);
00090 addctrl("mrs_natural/pos", (mrs_natural)0);
00091 setctrlState("mrs_natural/pos", true);
00092 addctrl("mrs_string/filename", "daufile");
00093 setctrlState("mrs_string/filename", true);
00094 addctrl("mrs_natural/size", (mrs_natural)0);
00095 addctrl("mrs_string/filetype", "ogg");
00096 addctrl("mrs_real/repetitions", 1.0);
00097 setctrlState("mrs_real/repetitions", true);
00098 addctrl("mrs_real/duration", -1.0);
00099 setctrlState("mrs_real/duration", true);
00100
00101 addctrl("mrs_natural/advance", 0);
00102 setctrlState("mrs_natural/advance", true);
00103
00104 addctrl("mrs_bool/shuffle", false);
00105 setctrlState("mrs_bool/shuffle", true);
00106
00107 addctrl("mrs_natural/cindex", 0);
00108 setctrlState("mrs_natural/cindex", true);
00109
00110 addctrl("mrs_string/allfilenames", ",");
00111 addctrl("mrs_natural/numFiles", 1);
00112
00113
00114
00115 addctrl("mrs_string/currentlyPlaying", "doggfile", ctrl_currentlyPlaying_);
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
00123
00129 void
00130 OggFileSource::getHeader(mrs_string filename)
00131 {
00132
00133 closeFile();
00134 mrs_real duration = 0;
00135 mrs_real israte = 22050.0;
00136 mrs_natural nChannels = 1;
00137 mrs_natural size = 0;
00138 hasData_ = false;
00139 mrs_natural bitRate = 128*1024;
00140
00141 #ifdef MARSYAS_VORBIS
00142 FILE* fp = fopen(filename.c_str(), "rb");
00143 vf = new OggVorbis_File;
00144
00145
00146 if(fp && ov_open_callbacks(fp, vf, NULL, 0, OV_CALLBACKS_DEFAULT) == 0)
00147 {
00148 vi=ov_info(vf,-1);
00149 size = ov_pcm_total(vf,-1);
00150 duration = ov_time_total(vf,-1);
00151 nChannels = vi->channels;
00152 israte = vi->rate;
00153 hasData_ = true;
00154 bitRate = ov_bitrate(vf, -1);
00155 }
00156 else
00157 #endif
00158 {
00159 MRSWARN(filename + " does not appear to be an Ogg bitstream.");
00160 }
00161 setctrl("mrs_natural/nChannels", nChannels);
00162 setctrl("mrs_real/israte", israte);
00163 setctrl("mrs_natural/size", size);
00164 setctrl("mrs_bool/hasData", hasData_);
00165 setctrl("mrs_natural/bitRate", bitRate);
00166 updControl("mrs_real/duration", duration);
00167 }
00168
00179 void
00180 OggFileSource::myUpdate(MarControlPtr sender)
00181 {
00182 (void) sender;
00183 MRSDIAG("OggFileSource::myUpdate");
00184
00185 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00186 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations"));
00187 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00188
00189 #ifdef MARSYAS_VORBIS
00190 mrs_natural pos = getctrl("mrs_natural/pos")->to<mrs_natural>();
00191 mrs_natural size = getctrl("mrs_natural/size")->to<mrs_natural>();
00192
00193
00194 if ( pos < size && pos != ov_pcm_tell(vf))
00195 {
00196 ov_pcm_seek(vf, pos_);
00197 }
00198 #endif
00199
00200 }
00201
00207 void OggFileSource::myProcess(realvec& in, realvec& out)
00208 {
00209 (void) in;
00210
00211
00212 if (hasData_)
00213 {
00214 #ifdef MARSYAS_VORBIS
00215
00216
00217
00218 mrs_natural observations = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00219 mrs_natural samples = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00220 mrs_natural israte = (mrs_natural)getctrl("mrs_real/israte")->to<mrs_real>();
00221
00222
00223 mrs_natural size = vi->channels*sizeof(short int)*((mrs_natural)(observations * samples));
00224 char* buf = new char[size];
00225 int bitstream=0;
00226 mrs_natural read = 0;
00227 long r = 0;
00228 bool eof = false;
00229 do
00230 {
00231 r = ov_read(vf, buf+read, size-read, 0, 2, 1, &bitstream);
00232 if(r <= 0)
00233 {
00234 eof = true;
00235 break;
00236 }
00237 read += (mrs_natural) r;
00238 }
00239 while(read < size);
00240
00241
00242 const double peak = 1.0/32768;
00243 short int* src = (short int*)buf;
00244 for (o=0; o < observations; o++)
00245 {
00246 for (t=0; t < samples; t++)
00247 {
00248 const unsigned int i=vi->channels*t;
00249 switch(vi->channels)
00250 {
00251 case 2:
00252 out(0,t) = (src[i] + src[i+1])*peak/2;
00253 break;
00254 default:
00255 out(0,t) = src[i]*peak;
00256 }
00257 }
00258 }
00259 delete [] buf;
00260 if(eof)
00261 closeFile();
00262
00263 #endif
00264 }
00265 else
00266 out.setval(0.0);
00267 if (hasData_)
00268 {
00269
00270 }
00271 else
00272 {
00273
00274 MRSWARN("OggFileSource: track ended.");
00275 }
00276 }
00277
00285 void OggFileSource::closeFile()
00286 {
00287 #ifdef MARSYAS_VORBIS
00288
00289 if(hasData_)
00290 {
00291 ov_clear(vf);
00292 delete vf;
00293 }
00294 #endif
00295
00296 hasData_ = false;
00297 }