00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "common.h"
00021 #include "AudioSinkBlocking.h"
00022
00023
00024
00025 #ifdef MARSYAS_AUDIOIO
00026 #include "RtAudio3.h"
00027 #endif
00028
00029
00030
00031 using std::ostringstream;
00032 using std::cout;
00033 using std::endl;
00034
00035 using namespace Marsyas;
00036
00037 AudioSinkBlocking::AudioSinkBlocking(mrs_string name):MarSystem("AudioSinkBlocking", name)
00038 {
00039 bufferSize_ = 0;
00040
00041 start_ = 0;
00042 end_ = 0;
00043
00044 preservoirSize_ = 0;
00045 pnChannels_ = 1;
00046
00047 data_ = NULL;
00048 #ifdef MARSYAS_AUDIOIO
00049 audio_ = NULL;
00050 #endif
00051
00052 rtSrate_ = 0;
00053 bufferSize_ = 0;
00054
00055 isInitialized_ = false;
00056 stopped_ = true;
00057
00058 rtSrate_ = 0;
00059 bufferSize_ = 0;
00060 rtChannels_ = 0;
00061 rtDevice_ = 0;
00062
00063 addControls();
00064 }
00065
00066 AudioSinkBlocking::~AudioSinkBlocking()
00067 {
00068 #ifdef MARSYAS_AUDIOIO
00069 delete audio_;
00070 #endif
00071 data_ = NULL;
00072 }
00073
00074 MarSystem*
00075 AudioSinkBlocking::clone() const
00076 {
00077 return new AudioSinkBlocking(*this);
00078 }
00079
00080 void
00081 AudioSinkBlocking::addControls()
00082 {
00083
00084 #ifdef MARSYAS_MACOSX
00085 addctrl("mrs_natural/bufferSize", 512);
00086 #else
00087 addctrl("mrs_natural/bufferSize", 256);
00088 #endif
00089
00090 addctrl("mrs_bool/initAudio", false);
00091 setctrlState("mrs_bool/initAudio", true);
00092
00093 addctrl("mrs_natural/device", 0);
00094
00095 }
00096
00097 void
00098 AudioSinkBlocking::myUpdate(MarControlPtr sender)
00099 {
00100 MRSDIAG("AudioSinkBlocking::myUpdate");
00101
00102 MarSystem::myUpdate(sender);
00103
00104
00105 nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00106
00107 if (getctrl("mrs_bool/initAudio")->to<mrs_bool>())
00108 initRtAudio();
00109
00110
00111 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00112
00113
00114
00115 if (inSamples_ < bufferSize_)
00116 reservoirSize_ = 2 * bufferSize_;
00117 else
00118 {
00119 if (2 * inSamples_ > preservoirSize_)
00120 reservoirSize_ = 2 * inSamples_;
00121 }
00122
00123
00124 if ((reservoirSize_ > preservoirSize_)||(nChannels_ != pnChannels_))
00125 {
00126
00127 reservoir_.stretch(nChannels_, reservoirSize_);
00128 } else {
00129 reservoirSize_ = preservoirSize_;
00130 }
00131
00132 preservoirSize_ = reservoirSize_;
00133 pnChannels_ = nChannels_;
00134
00135 }
00136
00137 void
00138 AudioSinkBlocking::initRtAudio()
00139 {
00140
00141 rtSrate_ = (int)getctrl("mrs_real/israte")->to<mrs_real>();
00142 srate_ = rtSrate_;
00143 bufferSize_ = (int)getctrl("mrs_natural/bufferSize")->to<mrs_natural>();
00144 rtDevice_= (int)getctrl("mrs_natural/device")->to<mrs_natural>();
00145
00146 #ifdef MARSYAS_MACOSX
00147 if (rtSrate_ == 22050)
00148 {
00149 rtSrate_ = 44100;
00150 bufferSize_ = 2 * bufferSize_;
00151 }
00152 #endif
00153
00154
00155
00156
00157 #ifdef MARSYAS_AUDIOIO
00158
00159 RtAudio3Format rtFormat = (sizeof(mrs_real) == 8) ? RTAUDIO3_FLOAT64 : RTAUDIO3_FLOAT32;
00160
00161
00162 int rtChannels = nChannels_;
00163
00164
00165 if (rtChannels == 1)
00166 rtChannels = 2;
00167
00168
00169 if (audio_ != NULL)
00170 {
00171 audio_->stopStream();
00172 delete audio_;
00173 }
00174
00175 try
00176 {
00177 audio_ = new RtAudio3(rtDevice_, rtChannels, 0, 0, rtFormat,
00178 rtSrate_, &bufferSize_, 4);
00179
00180 data_ = (mrs_real *) audio_->getStreamBuffer();
00181 }
00182 catch (RtError3 &error)
00183 {
00184 error.printMessage();
00185 }
00186
00187 if (audio_ != NULL)
00188 {
00189 audio_->startStream();
00190 }
00191
00192 if (rtDevice_ !=0){
00193 RtAudio3DeviceInfo info;
00194 info = audio_->getDeviceInfo(rtDevice_);
00195 cout << "Using output device: " << info.name << endl;
00196 }
00197
00198 #endif
00199
00200
00201
00202 setctrl("mrs_natural/bufferSize", (mrs_natural)bufferSize_);
00203
00204 isInitialized_ = true;
00205 setctrl("mrs_bool/initAudio", false);
00206
00207 }
00208
00209 void
00210 AudioSinkBlocking::start()
00211 {
00212 #ifdef MARSYAS_AUDIOIO
00213
00214 if ( stopped_ && audio_) {
00215 audio_->startStream();
00216 stopped_ = false;
00217 }
00218
00219
00220 #endif
00221 }
00222
00223 void
00224 AudioSinkBlocking::stop()
00225 {
00226 #ifdef MARSYAS_AUDIOIO
00227 if ( !stopped_ && audio_) {
00228
00229 audio_->abortStream();
00230 stopped_ = true;
00231
00232
00233 }
00234 #endif
00235 }
00236
00237 void
00238 AudioSinkBlocking::localActivate(bool state)
00239 {
00240 if(state)
00241 start();
00242 else
00243 stop();
00244 }
00245
00246 void
00247 AudioSinkBlocking::myProcess(realvec& in, realvec& out)
00248 {
00249 mrs_natural t,o;
00250
00251
00252 if(ctrl_mute_->isTrue())
00253 {
00254 for (t=0; t < inSamples_; t++)
00255 {
00256 for (o=0; o < inObservations_; o++)
00257 {
00258 out(o,t) = in(o,t);
00259 }
00260 }
00261 #ifdef MARSYAS_AUDIOIO
00262 if (audio_ != NULL)
00263 {
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 try
00276 {
00277 audio_->stopStream();
00278 }
00279 catch (RtError3 &error)
00280 {
00281 error.printMessage();
00282 }
00283 }
00284 #endif
00285 return;
00286 }
00287
00288
00289
00290
00291
00292 for (t=0; t < inSamples_; t++)
00293 {
00294 for (o=0; o < inObservations_; o++)
00295 {
00296 reservoir_(o, end_) = in(o,t);
00297 out(o,t) = in(o,t);
00298 }
00299 end_ ++;
00300 if (end_ == reservoirSize_)
00301 end_ = 0;
00302 }
00303
00304
00305
00306
00307 if (!isInitialized_) {
00308 return;
00309 }
00310
00311
00312
00313
00314
00315 if ( stopped_ )
00316 {
00317 start();
00318 }
00319
00320
00321
00322 rsize_ = bufferSize_;
00323 #ifdef MARSYAS_MACOSX
00324 if (srate_ == 22050)
00325 rsize_ = bufferSize_/2;
00326 else
00327 rsize_ = bufferSize_;
00328 #endif
00329
00330 if (end_ >= start_)
00331 diff_ = end_ - start_;
00332 else
00333 diff_ = reservoirSize_ - (start_ - end_);
00334
00335
00336
00337
00338 while (diff_ >= rsize_)
00339 {
00340
00341 for (t =0; t < rsize_; t++)
00342 {
00343 int rt = (start_ + t);
00344
00345 while (rt >= reservoirSize_)
00346 rt -= reservoirSize_;
00347 while (rt < 0)
00348 rt += reservoirSize_;
00349
00350 const int t2 = 2 * t;
00351 #ifndef MARSYAS_MACOSX
00352
00353 if (inObservations_ == 1)
00354 {
00355 for (int j=0; j < nChannels_; j++)
00356 {
00357 data_[t2+j] = reservoir_(0, rt);
00358 }
00359 }
00360 else
00361 {
00362 for (int j=0; j < nChannels_; j++)
00363 {
00364 data_[t2+j] = reservoir_(0+j, rt);
00365 }
00366
00367 }
00368
00369 #else
00370 const int t4 = 4 * t;
00371 if (srate_ == 22050)
00372 {
00373
00374 if (inObservations_ == 1)
00375 {
00376 data_[t4] = reservoir_(0,rt);
00377 data_[t4+1] = reservoir_(0,rt);
00378 data_[t4+2] = reservoir_(0,rt);
00379 data_[t4+3] = reservoir_(0,rt);
00380 }
00381 else
00382 {
00383 for (int j=0; j < nChannels_; j++)
00384 {
00385 data_[t4] = reservoir_(0+j,rt);
00386 data_[t4+2+j] = reservoir_(0+j,rt);
00387 }
00388 }
00389
00390 }
00391 else
00392 {
00393 if (inObservations_ == 1)
00394 {
00395
00396 mrs_real foo = reservoir_(0, rt);
00397 data_[t2] = foo;
00398 data_[t2+1] = foo;
00399 }
00400 else
00401 {
00402
00403 for (int j=0; j < nChannels_; j++)
00404 {
00405 data_[t2+j] = reservoir_(j, rt);
00406 }
00407
00408 }
00409 }
00410 #endif
00411 }
00412
00413 #ifdef MARSYAS_AUDIOIO
00414
00415 try
00416 {
00417 audio_->tickStream();
00418 }
00419 catch (RtError3 &error)
00420 {
00421 error.printMessage();
00422 }
00423
00424
00425
00426 start_ = (start_ + rsize_) % reservoirSize_;
00427 if (end_ >= start_)
00428 diff_ = end_ - start_;
00429 else
00430 diff_ = reservoirSize_ - (start_ - end_);
00431
00432 #endif
00433 }
00434
00435
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448