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 "RawFileSource.h" 00020 00021 using namespace std; 00022 using namespace Marsyas; 00023 00024 RawFileSource::RawFileSource(mrs_string name):AbsSoundFileSource("RawFileSource", name) 00025 { 00026 sfp_ = NULL; 00027 buffer_ = NULL; 00028 00029 phaseOffset_ = 0.0; 00030 bufferSize_ = 0; 00031 time_ = 0.0; 00032 00033 hasData_ = true; 00034 00035 addControls(); 00036 } 00037 00038 RawFileSource::~RawFileSource() 00039 { 00040 if (sfp_ != NULL) 00041 fclose(sfp_); 00042 00043 delete [] buffer_; 00044 00045 } 00046 00047 MarSystem* RawFileSource::clone() const 00048 { 00049 return new RawFileSource(*this);//[?] copy constructor?!? 00050 } 00051 00052 void 00053 RawFileSource::addControls() 00054 { 00055 addctrl("mrs_natural/nChannels",1); 00056 addctrl("mrs_real/frequency",440.0); 00057 setctrlState("mrs_real/frequency",true); 00058 addctrl("mrs_natural/size", 0); 00059 addctrl("mrs_natural/pos", 0); 00060 setctrlState("mrs_natural/pos", true); 00061 addctrl("mrs_bool/hasData", true); 00062 addctrl("mrs_bool/noteon", false); 00063 setctrlState("mrs_bool/noteon", true); 00064 addctrl("mrs_string/filetype", "raw"); 00065 addctrl("mrs_bool/currentHasData", true, ctrl_currentHasData_); 00066 } 00067 00068 00069 void RawFileSource::openFile(mrs_string filename) 00070 { 00071 getHeader(filename); 00072 rate_ = fileSize_ * getctrl("mrs_real/frequency")->to<mrs_real>() / getctrl("mrs_real/israte")->to<mrs_real>(); 00073 } 00074 00075 00076 // get file data info from the raw file 00077 bool RawFileSource::getRawInfo( const char *fileName ) 00078 { 00079 // Use the system call "stat" to determine the file length. 00080 struct stat filestat; 00081 if ( stat(fileName, &filestat) == -1 ) { 00082 return false; 00083 } 00084 00085 // length in 2-byte samples 00086 fileSize_ = (mrs_natural) filestat.st_size / 2; 00087 bufferSize_ = fileSize_; 00088 00089 // assume little endian for now 00090 byteSwap_ = true; 00091 00092 return true; 00093 } 00094 00095 // 00096 // STK raw files don't have a header, so just open the file and get info 00097 // 00098 void RawFileSource::getHeader(mrs_string fileName) 00099 { 00100 00101 sfp_ = fopen(fileName.c_str(), "raw"); 00102 if (sfp_ == NULL) { 00103 MRSWARN("Could not open file: " + fileName); 00104 return; 00105 } 00106 00107 bool result = getRawInfo( fileName.c_str() ); 00108 if ( ! result ) { 00109 MRSWARN("Could not get raw data information from file: " + fileName); 00110 return; 00111 } 00112 00113 // allocate storage for the buffer 00114 mrs_natural samples = (bufferSize_+1)* getctrl("mrs_natural/nChannels")->to<mrs_natural>(); 00115 data_.create(samples); 00116 00117 if(buffer_) 00118 delete [] buffer_; 00119 buffer_ = new short[bufferSize_]; 00120 00121 // now read the data into our buffer (data_[]). 00122 readData(0); 00123 } 00124 00125 00126 void RawFileSource::swap16(unsigned char *ptr) 00127 { 00128 register unsigned char val; 00129 00130 // Swap 1st and 2nd bytes 00131 val = *(ptr); 00132 *(ptr) = *(ptr+1); 00133 *(ptr+1) = val; 00134 } 00135 00136 00137 // 00138 // read all the raw data into data[] 00139 // 00140 void RawFileSource::readData(unsigned long index)//[!] 00141 { 00142 mrs_natural i; 00143 mrs_natural length = bufferSize_; 00144 00145 // Read samples into data[]. 00146 if (fseek(sfp_, index, SEEK_SET) == -1) { 00147 MRSWARN("ERROR(fseek): could not read raw file data."); 00148 return; 00149 } 00150 00151 if (fread(buffer_, length, 2, sfp_) != 2 ) { 00152 MRSWARN("ERROR(fread): could not read raw file data"); 00153 return; 00154 } 00155 00156 // if we are on a little endian machine. 00157 byteSwap_ = true; 00158 if ( byteSwap_ ) { 00159 short* ptr = buffer_; 00160 for ( i=length; i>=0; i-- ) 00161 swap16((unsigned char *)(ptr++)); 00162 } 00163 00164 for ( i=length-1; i>=0; i-- ) { 00165 data_(i) = buffer_[i]; 00166 } 00167 00168 // repeat last sample frame for interpolation 00169 data_(length) = data_(length-1); 00170 00171 // find the peak 00172 mrs_real max = 0.0; 00173 for (i=0; i < length; ++i) { 00174 if (fabs(data_(i)) > max) 00175 max = (mrs_real) fabs((double) data_(i)); 00176 } 00177 00178 // now normalize according to the peak. 00179 if (max > 0.0) { 00180 max = (mrs_real)(1.0 / max); 00181 max *= 1.0; // constant factor for now. 00182 for ( i=0; i <= length; ++i ) { 00183 data_(i) *= max; 00184 } 00185 } 00186 00187 } 00188 00189 void RawFileSource::myUpdate(MarControlPtr sender) 00190 { 00191 (void) sender; //suppress warning of unused parameter(s) 00192 00193 nChannels_ = getctrl("mrs_natural/nChannels")->to<mrs_natural>(); 00194 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>(); 00195 inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00196 israte_ = getctrl("mrs_real/israte")->to<mrs_real>(); 00197 00198 setctrl("mrs_natural/onSamples", inSamples_); 00199 setctrl("mrs_natural/onObservations", inObservations_); 00200 setctrl("mrs_real/osrate", israte_); 00201 00202 pos_ = getctrl("mrs_natural/pos")->to<mrs_natural>(); 00203 00204 rate_ = fileSize_ * getctrl("mrs_real/frequency")->to<mrs_real>() / israte_; 00205 } 00206 00207 00208 void RawFileSource::myProcess(realvec& in,realvec &out) 00209 { 00210 (void) in; 00211 //checkFlow(in,out); 00212 00213 mrs_real alpha; 00214 mrs_natural i, index; 00215 00216 if (!getctrl("mrs_bool/noteon")->isTrue()) { 00217 return; 00218 } 00219 00220 for (i = 0; i < inSamples_; ++i ) { 00221 00222 // loop back to start of the wavetable 00223 if (time_ >= fileSize_) { 00224 time_ -= fileSize_; 00225 } 00226 00227 // linear interpolation 00228 index = (mrs_natural) time_; 00229 alpha = time_ - (mrs_real) index; // fractional part of time address 00230 out(0,i) = data_(index); 00231 out(0,i) += (alpha * (data_(index+1) - data_(index))); 00232 00233 time_ += rate_; 00234 00235 } 00236 ctrl_currentHasData_->setValue(hasData_); 00237 }