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