00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "WavFileSource.h"
00021
00022
00023 using namespace std;
00024 using namespace Marsyas;
00025
00026 WavFileSource::WavFileSource(mrs_string name):AbsSoundFileSource("WavFileSource",name)
00027 {
00028 sdata_ = 0;
00029 cdata_ = 0;
00030 sfp_ = 0;
00031 pos_ = 0;
00032
00033 addControls();
00034 }
00035
00036
00037 WavFileSource::WavFileSource(const WavFileSource& a): AbsSoundFileSource(a)
00038 {
00039 ctrl_pos_ = getctrl("mrs_natural/pos");
00040 ctrl_currentlyPlaying_ = getctrl("mrs_string/currentlyPlaying");
00041 ctrl_previouslyPlaying_ = getctrl("mrs_string/previouslyPlaying");
00042 ctrl_regression_ = getctrl("mrs_bool/regression");
00043 ctrl_currentLabel_ = getctrl("mrs_real/currentLabel");
00044 ctrl_previousLabel_ = getctrl("mrs_real/previousLabel");
00045 ctrl_labelNames_ = getctrl("mrs_string/labelNames");
00046 ctrl_nLabels_ = getctrl("mrs_natural/nLabels");
00047 ctrl_currentHasData_ = getctrl("mrs_bool/currentHasData");
00048 ctrl_currentLastTickWithData_ = getctrl("mrs_bool/currentLastTickWithData");
00049 }
00050
00051
00052
00053 WavFileSource::~WavFileSource()
00054 {
00055 delete [] sdata_;
00056 delete [] cdata_;
00057 if (sfp_ != NULL)
00058 fclose(sfp_);
00059 }
00060
00061 MarSystem*
00062 WavFileSource::clone() const
00063 {
00064 return new WavFileSource(*this);
00065 }
00066
00067 void
00068 WavFileSource::addControls()
00069 {
00070 addctrl("mrs_bool/hasData", true);
00071 addctrl("mrs_bool/lastTickWithData", false);
00072
00073 addctrl("mrs_natural/pos", (mrs_natural)0, ctrl_pos_);
00074 setctrlState("mrs_natural/pos", true);
00075
00076 addctrl("mrs_natural/loopPos", (mrs_natural)0);
00077 setctrlState("mrs_natural/pos", true);
00078
00079 addctrl("mrs_natural/size", (mrs_natural)0);
00080
00081 addctrl("mrs_string/filename", "dwavfile");
00082 setctrlState("mrs_string/filename", true);
00083
00084 addctrl("mrs_string/filetype", "wav");
00085
00086 addctrl("mrs_real/repetitions", 1.0);
00087 setctrlState("mrs_real/repetitions", true);
00088
00089 addctrl("mrs_real/duration", -1.0);
00090 setctrlState("mrs_real/duration", true);
00091
00092 addctrl("mrs_natural/advance", 0);
00093 setctrlState("mrs_natural/advance", true);
00094
00095 addctrl("mrs_bool/shuffle", false);
00096 setctrlState("mrs_bool/shuffle", true);
00097
00098 addctrl("mrs_natural/cindex", 0);
00099 setctrlState("mrs_natural/cindex", true);
00100
00101 addctrl("mrs_string/allfilenames", ",");
00102 setctrlState("mrs_string/allfilenames", true);
00103
00104 addctrl("mrs_natural/numFiles", 1);
00105 addctrl("mrs_string/currentlyPlaying", "daufile", ctrl_currentlyPlaying_);
00106 addctrl("mrs_string/previouslyPlaying", "daufile", ctrl_previouslyPlaying_);
00107
00108 addctrl("mrs_bool/regression", false, ctrl_regression_);
00109 addctrl("mrs_real/currentLabel", 0.0, ctrl_currentLabel_);
00110 addctrl("mrs_real/previousLabel", 0.0, ctrl_previousLabel_);
00111 addctrl("mrs_natural/nLabels", 0, ctrl_nLabels_);
00112 addctrl("mrs_string/labelNames", ",", ctrl_labelNames_);
00113
00114 addctrl("mrs_bool/currentHasData", true, ctrl_currentHasData_);
00115
00116 addctrl("mrs_bool/currentLastTickWithData", false, ctrl_currentLastTickWithData_);
00117
00118 }
00119
00120 void
00121 WavFileSource::getHeader(mrs_string filename)
00122 {
00123
00124 if (sfp_ != NULL)
00125 fclose(sfp_);
00126
00127 sfp_ = fopen(filename.c_str(), "rb");
00128 if (sfp_)
00129 {
00130 char magic[5];
00131
00132 fseek(sfp_, 8, SEEK_SET);
00133 if (fread(magic, 4, 1, sfp_) == 0)
00134 {
00135 MRSERR("WavFileSource: File " + filename + " is empty ");
00136 }
00137 magic[4] = '\0';
00138
00139 if (strcmp(magic, "WAVE"))
00140 {
00141 MRSWARN("Filename " + filename + " is not correct .wav file \n or has settings that are not supported in Marsyas");
00142
00143 setctrl("mrs_real/israte", 22050.0);
00144 setctrl("mrs_natural/size", 0);
00145 hasData_ = false;
00146 lastTickWithData_ = true;
00147 setctrl("mrs_bool/hasData", false);
00148 setctrl("mrs_bool/lastTickWithData", true);
00149
00150 }
00151 else
00152 {
00153 char id[5];
00154 int chunkSize;
00155 fread(id, 4, 1, sfp_);
00156 id[4] = '\0';
00157
00158 while (strcmp(id, "fmt "))
00159 {
00160 fread(&chunkSize, 4, 1, sfp_);
00161 #if defined(MARSYAS_BIGENDIAN)
00162 chunkSize = ByteSwapLong(chunkSize);
00163 #else
00164 chunkSize = chunkSize;
00165 #endif
00166 fseek(sfp_, chunkSize, SEEK_CUR);
00167 fread(id, 4, 1, sfp_);
00168 }
00169
00170 fread(&chunkSize, 4, 1, sfp_);
00171 #if defined(MARSYAS_BIGENDIAN)
00172 chunkSize = ByteSwapLong(chunkSize);
00173 #else
00174 chunkSize = chunkSize;
00175 #endif
00176
00177 unsigned short format_tag;
00178 fread(&format_tag, 2, 1, sfp_);
00179
00180 #if defined(MARSYAS_BIGENDIAN)
00181 format_tag = ByteSwapShort(format_tag);
00182 #else
00183 format_tag = format_tag;
00184 #endif
00185
00186 if (format_tag != 1)
00187 {
00188 fclose(sfp_);
00189 MRSWARN("Non pcm(compressed) wave files are not supported");
00190 exit(1);
00191 }
00192
00193
00194 unsigned short channels;
00195 fread(&channels, 2,1, sfp_);
00196
00197 #if defined(MARSYAS_BIGENDIAN)
00198 channels = ByteSwapShort(channels);
00199 #else
00200 channels = channels;
00201 #endif
00202
00203 setctrl("mrs_natural/onObservations", (mrs_natural)channels);
00204
00205 unsigned int srate;
00206 fread(&srate, 4,1,sfp_);
00207
00208 #if defined(MARSYAS_BIGENDIAN)
00209 srate = ByteSwapLong(srate);
00210 #else
00211 srate = srate;
00212 #endif
00213
00214
00215 setctrl("mrs_real/israte", (mrs_real)srate);
00216 setctrl("mrs_real/osrate", (mrs_real)srate);
00217
00218 fseek(sfp_,6,SEEK_CUR);
00219 fread(&bits_, 2, 1, sfp_);
00220
00221 #if defined(MARSYAS_BIGENDIAN)
00222 bits_ = ByteSwapShort(bits_);
00223 #else
00224 bits_ = bits_;
00225 #endif
00226
00227 if ((bits_ != 16)&&(bits_ != 8))
00228 {
00229 MRSWARN("WavFileSource::Only linear 8-bit and 16-bit samples are supported ");
00230 }
00231 fseek(sfp_, chunkSize - 16, SEEK_CUR);
00232
00233 fread(id, 4, 1, sfp_);
00234 id[4] = '\0';
00235 while (strcmp(id, "data"))
00236 {
00237 fread(&chunkSize, 4, 1, sfp_);
00238 #if defined(MARSYAS_BIGENDIAN)
00239 chunkSize = ByteSwapLong(chunkSize);
00240 #else
00241 chunkSize = chunkSize;
00242 #endif
00243
00244 fseek(sfp_,chunkSize,SEEK_CUR);
00245 fread(&id,4,1,sfp_);
00246 }
00247
00248 int bytes;
00249 fread(&bytes, 4, 1, sfp_);
00250
00251 #if defined(MARSYAS_BIGENDIAN)
00252 bytes = ByteSwapLong(bytes);
00253 #else
00254 bytes = bytes;
00255 #endif
00256
00257
00258 size_ = bytes / (bits_ / 8)/ (getctrl("mrs_natural/onObservations")->to<mrs_natural>());
00259 csize_ = size_;
00260
00261 setctrl("mrs_natural/size", size_);
00262 ctrl_currentlyPlaying_->setValue(filename, NOUPDATE);
00263 ctrl_previouslyPlaying_->setValue(filename, NOUPDATE);
00264 ctrl_currentLabel_->setValue(0.0, NOUPDATE);
00265 ctrl_previousLabel_->setValue(0.0, NOUPDATE);
00266
00267 ctrl_labelNames_->setValue(",", NOUPDATE);
00268 ctrl_nLabels_->setValue(0, NOUPDATE);
00269 sfp_begin_ = ftell(sfp_);
00270 hasData_ = true;
00271 lastTickWithData_ = false;
00272 pos_ = 0;
00273 samplesOut_ = 0;
00274 MRSDIAG("WavFileSource: "
00275 << filename
00276 << " has the following properties: ");
00277 mrs_real temprate = getControl("mrs_real/israte")->to<mrs_real>();
00278 mrs_natural numInSamples = getControl("mrs_natural/inSamples")->to<mrs_natural>();
00279 MRSDIAG("israte == " << temprate);
00280 MRSDIAG("inSamples == " << numInSamples);
00281
00282 }
00283 }
00284 else
00285 {
00286 MRSWARN("couldn't open file: " << filename);
00287
00288 setctrl("mrs_real/israte", 22050.0);
00289 setctrl("mrs_natural/onObservations", 1);
00290 setctrl("mrs_natural/size", 0);
00291 hasData_ = false;
00292 lastTickWithData_ = true;
00293 setctrl("mrs_bool/hasData", false);
00294 setctrl("mrs_bool/lastTickWithData", true);
00295 pos_ = 0;
00296 }
00297
00298 nChannels_ = getctrl("mrs_natural/onObservations")->to<mrs_natural>();
00299 }
00300
00301 void
00302 WavFileSource::myUpdate(MarControlPtr sender)
00303 {
00304 (void) sender;
00305 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00306 inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00307 israte_ = getctrl("mrs_real/israte")->to<mrs_real>();
00308 osrate_ = getctrl("mrs_real/osrate")->to<mrs_real>();
00309
00310 nChannels_ = getctrl("mrs_natural/onObservations")->to<mrs_natural>();
00311
00312 setctrl("mrs_natural/onSamples", inSamples_);
00313 setctrl("mrs_natural/onObservations", nChannels_);
00314
00315
00316 pos_ = getctrl("mrs_natural/pos")->to<mrs_natural>();
00317 rewindpos_ = getctrl("mrs_natural/loopPos")->to<mrs_natural>();
00318
00319 delete [] sdata_;
00320 delete [] cdata_;
00321
00322 sdata_ = new short[inSamples_ * nChannels_];
00323 cdata_ = new unsigned char[inSamples_ * nChannels_];
00324
00325 repetitions_ = getctrl("mrs_real/repetitions")->to<mrs_real>();
00326 duration_ = getctrl("mrs_real/duration")->to<mrs_real>();
00327
00328 if (duration_ != -1.0)
00329 {
00330 csize_ = (mrs_natural)(duration_ * israte_);
00331 }
00332
00333 samplesToRead_ = inSamples_ * nChannels_;
00334 MRSDIAG("WavFileSource::myUpdate "
00335 << " has the following properties: ");
00336 mrs_real temprate = getControl("mrs_real/israte")->to<mrs_real>();
00337 mrs_natural numInSamples = getControl("mrs_natural/inSamples")->to<mrs_natural>();
00338 MRSDIAG("israte == " << temprate);
00339 MRSDIAG("inSamples == " << numInSamples);
00340
00341 }
00342
00343 mrs_natural
00344 WavFileSource::getLinear8(realvec& slice)
00345 {
00346 mrs_natural t;
00347 mrs_natural c = 0;
00348 fseek(sfp_, pos_ * nChannels_ + sfp_begin_, SEEK_SET);
00349
00350 samplesToRead_ = inSamples_ * nChannels_;
00351 samplesRead_ = (mrs_natural)fread(cdata_, sizeof(unsigned char), samplesToRead_, sfp_);
00352
00353
00354 if (samplesRead_ != samplesToRead_)
00355 {
00356 for (c=0; c < nChannels_; ++c)
00357 for (t=0; t < inSamples_; t++)
00358 {
00359 slice(c,t) = 0.0;
00360 }
00361 samplesToWrite_ = samplesRead_ / nChannels_;
00362 }
00363 else
00364 samplesToWrite_ = inSamples_;
00365
00366 for (t=0; t < samplesToWrite_; t++)
00367 {
00368 for (c=0; c < nChannels_; ++c)
00369 {
00370 slice(c, t) = (mrs_real)-1.0 + (mrs_real) cdata_[nChannels_ * t + c] / 127;
00371 }
00372 }
00373
00374 pos_ += samplesToWrite_;
00375 return pos_;
00376 }
00377
00378 unsigned long
00379 WavFileSource::ByteSwapLong(unsigned long nLongNumber)
00380 {
00381 return (((nLongNumber&0x000000FF)<<24)+((nLongNumber&0x0000FF00)<<8)+
00382 ((nLongNumber&0x00FF0000)>>8)+((nLongNumber&0xFF000000)>>24));
00383 }
00384
00385 unsigned short
00386 WavFileSource::ByteSwapShort (unsigned short nValue)
00387 {
00388 return (((nValue>> 8)) | (nValue << 8));
00389 }
00390
00391 mrs_natural
00392 WavFileSource::getLinear16(realvec& slice)
00393 {
00394 mrs_natural c,t;
00395
00396 fseek(sfp_, 2 * pos_ * nChannels_ + sfp_begin_, SEEK_SET);
00397 samplesRead_ = (mrs_natural)fread(sdata_, sizeof(short), samplesToRead_, sfp_);
00398
00399
00400 if ((samplesRead_ != samplesToRead_)&&(samplesRead_ != 0))
00401 {
00402 for (c=0; c < nChannels_; ++c)
00403 for (t=0; t < inSamples_; t++)
00404 slice(c, t) = 0.0;
00405 samplesToWrite_ = samplesRead_ / nChannels_;
00406 }
00407 else
00408 {
00409 samplesToWrite_ = inSamples_;
00410
00411
00412 if (samplesRead_ == 0)
00413 for (t=0; t < inSamples_; t++)
00414 {
00415 nt_ = nChannels_ * t;
00416 for (c=0; c < nChannels_; ++c)
00417 {
00418 sdata_[nt_ + c] = 0;
00419 }
00420 }
00421 }
00422
00423
00424 for (t=0; t < samplesToWrite_; t++)
00425 {
00426 sval_ = 0;
00427 nt_ = nChannels_ * t;
00428 #if defined(MARSYAS_BIGENDIAN)
00429 for (c=0; c < nChannels_; ++c)
00430 {
00431 sval_ = ByteSwapShort(sdata_[nt_ + c]);
00432 slice(c, t) = (mrs_real) sval_ / (PCM_FMAXSHRT + 1);
00433 }
00434 #else
00435 for (c=0; c < nChannels_; ++c)
00436 {
00437 sval_ = sdata_[nt_ + c];
00438 slice(c, t) = ((mrs_real) sval_ / (PCM_FMAXSHRT + 1));
00439 }
00440 #endif
00441 }
00442
00443 pos_ += samplesToWrite_;
00444 return pos_;
00445 }
00446
00447 void
00448 WavFileSource::myProcess(realvec& in, realvec& out)
00449 {
00450
00451 switch(bits_)
00452 {
00453 case 16:
00454 {
00455 getLinear16(out);
00456 ctrl_pos_->setValue(pos_, NOUPDATE);
00457
00458 if (pos_ >= rewindpos_ + csize_)
00459 {
00460 if (repetitions_ != 1)
00461 pos_ = rewindpos_;
00462 }
00463 samplesOut_ += onSamples_;
00464
00465 if (repetitions_ != 1)
00466 {
00467 hasData_ = (samplesOut_ < repetitions_ * csize_);
00468
00469 lastTickWithData_ = ((samplesOut_ + onSamples_>= repetitions_ * csize_) && hasData_);
00470 }
00471
00472 else
00473 {
00474 hasData_ = pos_ < rewindpos_ + csize_;
00475 lastTickWithData_ = ((pos_ + onSamples_ >= rewindpos_ + csize_) && hasData_);
00476 }
00477
00478 if (repetitions_ == -1)
00479 {
00480 hasData_ = true;
00481 lastTickWithData_ = false;
00482 }
00483 break;
00484 }
00485 case 8:
00486 {
00487 getLinear8(out);
00488 ctrl_pos_->setValue(pos_, NOUPDATE);
00489
00490 if (pos_ >= rewindpos_ + csize_)
00491 {
00492 if (repetitions_ != 1)
00493 pos_ = rewindpos_;
00494 }
00495 samplesOut_ += onSamples_;
00496
00497 if (repetitions_ != 1)
00498 {
00499 hasData_ = (samplesOut_ < repetitions_ * csize_);
00500 lastTickWithData_ = ((samplesOut_ + onSamples_ >= repetitions_ * csize_) && hasData_);
00501 }
00502 else
00503 {
00504 hasData_ = pos_ < rewindpos_ + csize_;
00505 lastTickWithData_ = ((pos_ + onSamples_ >= rewindpos_ + csize_) && hasData_);
00506 }
00507
00508 if (repetitions_ == -1)
00509 {
00510 hasData_ = true;
00511 lastTickWithData_ = false;
00512 }
00513 break;
00514
00515
00516 }
00517 }
00518 ctrl_currentHasData_->setValue(hasData_);
00519
00520 ctrl_currentLastTickWithData_->setValue(lastTickWithData_);
00521 }