00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "WavFileSource2.h"
00020
00021 using namespace std;
00022 using namespace Marsyas;
00023
00024 WavFileSource2::WavFileSource2(mrs_string name):AbsSoundFileSource2("WavFileSource2",name)
00025 {
00026 sdata_ = NULL;
00027 cdata_ = NULL;
00028 sfp_ = NULL;
00029
00030 addControls();
00031 }
00032
00033 WavFileSource2::~WavFileSource2()
00034 {
00035 delete [] sdata_;
00036 delete [] cdata_;
00037 if (sfp_ != NULL)
00038 fclose(sfp_);
00039 }
00040
00041 WavFileSource2::WavFileSource2(const WavFileSource2& a):AbsSoundFileSource2(a)
00042 {
00043 sdata_ = NULL;
00044 cdata_ = NULL;
00045 sfp_ = NULL;
00046 }
00047
00048 MarSystem*
00049 WavFileSource2::clone() const
00050 {
00051 return new WavFileSource2(*this);
00052 }
00053
00054 void
00055 WavFileSource2::addControls()
00056 {
00057 setctrl("mrs_string/filetype", "wav");
00058 }
00059
00060 void
00061 WavFileSource2::hdrError()
00062 {
00063 setctrl("mrs_natural/nChannels", (mrs_natural)1);
00064 setctrl("mrs_real/israte", MRS_DEFAULT_SLICE_SRATE);
00065 setctrl("mrs_natural/size", (mrs_natural)0);
00066 setctrl("mrs_bool/hasData", false);
00067 setctrl("mrs_string/filename", "defaultfile");
00068 }
00069
00070 bool
00071 WavFileSource2::getHeader()
00072 {
00073 unsigned short channels, srate;
00074 mrs_natural size;
00075
00076 mrs_string filename = getctrl("mrs_string/filename")->to<mrs_string>();
00077
00078 if(filename == "defaultfile")
00079 {
00080 MRSERR("WavFileSource2::getHeader: empty FileName");
00081 hdrError();
00082 return false;
00083 }
00084
00085 sfp_ = fopen(filename.c_str(), "rb");
00086 if (sfp_)
00087 {
00088 char magic[5];
00089
00090 fseek(sfp_, 8, SEEK_SET);
00091 if (fread(magic, 4, 1, sfp_) == 0)
00092 {
00093 MRSERR("WavFileSource2::getHeader: File " + filename + " is empty ");
00094 hdrError();
00095 return false;
00096 }
00097 magic[4] = '\0';
00098
00099 if (strcmp(magic, "WAVE"))
00100 {
00101 MRSWARN("WavFileSource2::getHeader: Filename " + filename + " is not correct .wav file \n or has settings that are not supported in Marsyas");
00102 hdrError();
00103 return false;
00104 }
00105 else
00106 {
00107 char id[5];
00108 int chunkSize;
00109 fread(id, 4, 1, sfp_);
00110 id[4] = '\0';
00111
00112 while (strcmp(id, "fmt "))
00113 {
00114 fread(&chunkSize, 4, 1, sfp_);
00115 #if defined(MARSYAS_BIGENDIAN)
00116 chunkSize = ByteSwapLong(chunkSize);
00117 #endif
00118 fseek(sfp_, chunkSize, SEEK_CUR);
00119 fread(id, 4, 1, sfp_);
00120 }
00121
00122 fread(&chunkSize, 4, 1, sfp_);
00123 #if defined(MARSYAS_BIGENDIAN)
00124 chunkSize = ByteSwapLong(chunkSize);
00125 #endif
00126
00127 unsigned short format_tag;
00128 fread(&format_tag, 2, 1, sfp_);
00129 #if defined(MARSYAS_BIGENDIAN)
00130 format_tag = ByteSwapShort(format_tag);
00131 #endif
00132 if (format_tag != 1)
00133 {
00134 fclose(sfp_);
00135 MRSWARN("WavFileSource2::getHeader: Non pcm(compressed) wave files are not supported");
00136 hdrError();
00137 return false;
00138 }
00139
00140
00141 fread(&channels, 2,1, sfp_);
00142 #if defined(MARSYAS_BIGENDIAN)
00143 channels = ByteSwapShort(channels);
00144 #endif
00145
00146 setctrl("mrs_natural/nChannels", (mrs_natural)channels);
00147
00148
00149 fread(&srate, 2,1,sfp_);
00150 #if defined(MARSYAS_BIGENDIAN)
00151 srate = ByteSwapShort(srate);
00152 #endif
00153 setctrl("mrs_real/israte", (mrs_real)srate);
00154
00155
00156 fseek(sfp_,8,SEEK_CUR);
00157 fread(&bits_, 2, 1, sfp_);
00158 #if defined(MARSYAS_BIGENDIAN)
00159 bits_ = ByteSwapShort(bits_);
00160 #endif
00161 if ((bits_ != 16))
00162 {
00163 fclose(sfp_);
00164
00165 MRSWARN("WavFileSource2::getHeader: WavFileSource2::Only linear 16-bit samples are supported for now...");
00166 hdrError();
00167 return false;
00168 }
00169
00170 fseek(sfp_, chunkSize - 16, SEEK_CUR);
00171 fread(id, 4, 1, sfp_);
00172 id[4] = '\0';
00173 while (strcmp(id, "data"))
00174 {
00175 fread(&chunkSize, 4, 1, sfp_);
00176 #if defined(MARSYAS_BIGENDIAN)
00177 chunkSize = ByteSwapLong(chunkSize);
00178 #endif
00179 fseek(sfp_,chunkSize,SEEK_CUR);
00180 fread(&id,4,1,sfp_);
00181 }
00182
00183 int bytes;
00184 fread(&bytes, 4, 1, sfp_);
00185 #if defined(MARSYAS_BIGENDIAN)
00186 bytes = ByteSwapLong(bytes);
00187 #endif
00188
00189 size = bytes / (bits_ / 8)/ channels;
00190 setctrl("mrs_natural/size", size);
00191
00192 sfp_begin_ = ftell(sfp_);
00193
00194
00195 if(size > 0)
00196 setctrl("mrs_bool/hasData", true);
00197 else
00198 setctrl("mrs_bool/hasData", false);
00199 }
00200 }
00201 else
00202 {
00203 hdrError();
00204 return false;
00205 }
00206
00207 return true;
00208 }
00209
00210 void
00211 WavFileSource2::myUpdate(MarControlPtr sender)
00212 {
00213 (void) sender;
00214
00215 mrs_string filename = getctrl("mrs_string/filename")->to<mrs_string>();
00216 if(filename_ != filename)
00217 {
00218 getHeader();
00219 filename_ = getctrl("mrs_string/filename")->to<mrs_string>();
00220 nChannels_ = getctrl("mrs_natural/nChannels")->to<mrs_natural>();
00221 israte_ = getctrl("mrs_real/israte")->to<mrs_real>();
00222 size_ = getctrl("mrs_natural/size")->to<mrs_natural>();
00223 }
00224
00225
00226 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00227 osrate_ = israte_;
00228
00229
00230 setctrl("mrs_natural/onSamples", inSamples_);
00231 setctrl("mrs_natural/onObservations", nChannels_);
00232 setctrl("mrs_real/osrate", osrate_);
00233
00234
00235 delete [] sdata_;
00236 delete [] cdata_;
00237 sdata_ = new short[inSamples_ * nChannels_];
00238 cdata_ = new unsigned char[inSamples_ * nChannels_];
00239
00240 samplesToRead_ = inSamples_ * nChannels_;
00241
00242
00243 ostringstream oss;
00244 for (mrs_natural i = 0; i < nChannels_; ++i)
00245 oss << "audio_ch_" << i+1 << ",";
00246 setctrl("mrs_string/onObsNames", oss.str());
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 unsigned long
00279 WavFileSource2::ByteSwapLong(unsigned long nLongNumber)
00280 {
00281 return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+
00282 ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24));
00283 }
00284
00285 unsigned short
00286 WavFileSource2::ByteSwapShort (unsigned short nValue)
00287 {
00288 return (((nValue>> 8)) | (nValue << 8));
00289 }
00290
00291 mrs_natural
00292 WavFileSource2::getLinear16(realvec& slice)
00293 {
00294 mrs_natural c,t;
00295 mrs_natural pos = getctrl("mrs_natural/pos")->to<mrs_natural>();
00296
00297 fseek(sfp_, 2 * pos * nChannels_ + sfp_begin_, SEEK_SET);
00298
00299 samplesToRead_ = inSamples_ * nChannels_;
00300
00301 samplesRead_ = (mrs_natural)fread(sdata_, sizeof(short), samplesToRead_, sfp_);
00302
00303 if (samplesRead_ != samplesToRead_)
00304 {
00305 samplesToWrite_ = samplesRead_ / nChannels_;
00306 for (c=0; c < nChannels_; ++c)
00307
00308 for(t = samplesToWrite_; t < inSamples_; t++)
00309 {
00310 slice(c, t) = 0.0;
00311 }
00312 }
00313 else
00314 samplesToWrite_ = inSamples_;
00315
00316 for (t=0; t < samplesToWrite_; t++)
00317 {
00318 sval_ = 0;
00319 #if defined(MARSYAS_BIGENDIAN)
00320 for (c=0; c < nChannels_; ++c)
00321 {
00322 sval_ = ByteSwapShort(sdata_[nChannels_*t + c]);
00323 slice(c, t) = (mrs_real) sval_ / (PCM_FMAXSHRT);
00324 }
00325 #else
00326 for (c=0; c < nChannels_; ++c)
00327 {
00328 sval_ = sdata_[nChannels_ *t + c];
00329 slice(c, t) = ((mrs_real) sval_ / (PCM_FMAXSHRT));
00330 }
00331 #endif
00332 }
00333
00334
00335 pos += samplesToWrite_;
00336 setctrl("mrs_natural/pos", pos);
00337 return pos;
00338 }
00339
00340 realvec&
00341 WavFileSource2::getAudioRegion(mrs_natural startSample, mrs_natural endSample)
00342 {
00343 (void) startSample;
00344 (void) endSample;
00345
00346
00347
00348
00349
00350 return audioRegion_;
00351 }
00352
00353 void
00354 WavFileSource2::myProcess(realvec& in, realvec& out)
00355 {
00356 (void) in;
00357
00358
00359 if(!getctrl("mrs_bool/hasData")->to<mrs_bool>())
00360 {
00361 out.setval(0.0);
00362 return;
00363 }
00364
00365 switch(bits_)
00366 {
00367 case 16:
00368 {
00369
00370 getLinear16(out);
00371 break;
00372 }
00373 case 8:
00374 {
00375
00376 break;
00377 }
00378 }
00379
00380
00381 if(getctrl("mrs_natural/pos")->to<mrs_natural>() >= size_)
00382 setctrl("mrs_bool/hasData", false);
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400