Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/AudioSinkBlocking.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2011 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 
00020 #include "../common_source.h"
00021 #include "AudioSinkBlocking.h"
00022 
00023 
00024 
00025 #include "RtAudio3.h"
00026 
00027 
00028 
00029 
00030 using std::ostringstream;
00031 using std::cout;
00032 using std::endl;
00033 
00034 using namespace Marsyas;
00035 
00036 AudioSinkBlocking::AudioSinkBlocking(mrs_string name):MarSystem("AudioSinkBlocking", name)
00037 {
00038   bufferSize_ = 0;
00039 
00040   start_ = 0;
00041   end_ = 0;
00042 
00043   preservoirSize_ = 0;
00044   pnChannels_ = 1;
00045 
00046   data_ = NULL;
00047   audio_ = NULL;
00048 
00049   rtSrate_ = 0;
00050   bufferSize_ = 0;
00051 
00052   isInitialized_ = false;
00053   stopped_ = true;//lmartins
00054 
00055   rtSrate_ = 0;
00056   bufferSize_ = 0;
00057   rtChannels_ = 0;
00058   rtDevice_ = 0;
00059 
00060   addControls();
00061 }
00062 
00063 AudioSinkBlocking::~AudioSinkBlocking()
00064 {
00065   delete audio_;
00066   data_ = NULL; // RtAudio deletes the buffer itself.
00067 }
00068 
00069 MarSystem*
00070 AudioSinkBlocking::clone() const
00071 {
00072   return new AudioSinkBlocking(*this);
00073 }
00074 
00075 void
00076 AudioSinkBlocking::addControls()
00077 {
00078 
00079 #ifdef MARSYAS_MACOSX
00080   addctrl("mrs_natural/bufferSize", 512);
00081 #else
00082   addctrl("mrs_natural/bufferSize", 256);
00083 #endif
00084 
00085   addctrl("mrs_bool/initAudio", false);
00086   setctrlState("mrs_bool/initAudio", true);
00087 
00088   addctrl("mrs_natural/device", 0);
00089 
00090 }
00091 
00092 void
00093 AudioSinkBlocking::myUpdate(MarControlPtr sender)
00094 {
00095   MRSDIAG("AudioSinkBlocking::myUpdate");
00096 
00097   MarSystem::myUpdate(sender);
00098 
00099 
00100   nChannels_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();//does nothing... [?]
00101 
00102   if (getctrl("mrs_bool/initAudio")->to<mrs_bool>())
00103     initRtAudio();
00104 
00105   //Resize reservoir if necessary
00106   inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00107 
00108 
00109 
00110   if (inSamples_ < bufferSize_)
00111     reservoirSize_ = 2 * bufferSize_;
00112   else
00113   {
00114     if (2 * inSamples_ > preservoirSize_)
00115       reservoirSize_ = 2 * inSamples_;
00116   }
00117 
00118 
00119   if ((reservoirSize_ > preservoirSize_)||(nChannels_ != pnChannels_))
00120   {
00121     //cout << "NCHANNELS = " << nChannels_ << endl;
00122     reservoir_.stretch(nChannels_, reservoirSize_);
00123   } else {
00124     reservoirSize_ = preservoirSize_;
00125   }
00126 
00127   preservoirSize_ = reservoirSize_;
00128   pnChannels_ = nChannels_;
00129 
00130 }
00131 
00132 void
00133 AudioSinkBlocking::initRtAudio()
00134 {
00135 
00136   rtSrate_ = (int)getctrl("mrs_real/israte")->to<mrs_real>();
00137   srate_ = rtSrate_;
00138   bufferSize_ = (int)getctrl("mrs_natural/bufferSize")->to<mrs_natural>();
00139   rtDevice_= (int)getctrl("mrs_natural/device")->to<mrs_natural>();
00140 
00141 #ifdef MARSYAS_MACOSX
00142   if (rtSrate_ == 22050)
00143   {
00144     rtSrate_ = 44100;
00145     bufferSize_ = 2 * bufferSize_;
00146   }
00147 #endif
00148 
00149 
00150 
00151 
00152   //marsyas represents audio data as float numbers
00153   RtAudio3Format rtFormat = (sizeof(mrs_real) == 8) ? RTAUDIO3_FLOAT64 : RTAUDIO3_FLOAT32;
00154 
00155   // hardwire channels to stereo playback even for mono
00156   int rtChannels = nChannels_;
00157 
00158 
00159   if (rtChannels == 1)              // make mono playback in stereo
00160     rtChannels = 2;
00161 
00162   //create new RtAudio object (delete any existing one)
00163   if (audio_ != NULL)
00164   {
00165     audio_->stopStream();
00166     delete audio_;
00167   }
00168 
00169   try
00170   {
00171     audio_ = new RtAudio3(rtDevice_, rtChannels, 0, 0, rtFormat,
00172                           rtSrate_, &bufferSize_, 4);
00173 
00174     data_ = (mrs_real *) audio_->getStreamBuffer();
00175   }
00176   catch (RtError3 &error)
00177   {
00178     error.printMessage();
00179   }
00180 
00181   if (audio_ != NULL)
00182   {
00183     audio_->startStream();
00184   }
00185 
00186   if (rtDevice_ !=0) {
00187     RtAudio3DeviceInfo info;
00188     info = audio_->getDeviceInfo(rtDevice_);
00189     cout << "Using output device: " << info.name << endl;
00190   }
00191 
00192 
00193   //update bufferSize control which may have been changed
00194   //by RtAudio (see RtAudio documentation)
00195   setctrl("mrs_natural/bufferSize", (mrs_natural)bufferSize_);
00196 
00197   isInitialized_ = true;
00198   setctrl("mrs_bool/initAudio", false);
00199 
00200 }
00201 
00202 void
00203 AudioSinkBlocking::start()
00204 {
00205   if ( stopped_ && audio_) {
00206     audio_->startStream();
00207     stopped_ = false;
00208   }
00209 }
00210 
00211 void
00212 AudioSinkBlocking::stop()
00213 {
00214   if ( !stopped_ && audio_) {
00215     audio_->abortStream();
00216     stopped_ = true;
00217   }
00218 }
00219 
00220 void
00221 AudioSinkBlocking::localActivate(bool state)
00222 {
00223   if(state)
00224     start();
00225   else
00226     stop();
00227 }
00228 
00229 void
00230 AudioSinkBlocking::myProcess(realvec& in, realvec& out)
00231 {
00232   mrs_natural t,o;
00233   // cout << "AudioSinkBlocking::myProcess start" << endl;
00234   // check MUTE
00235   if(ctrl_mute_->isTrue())
00236   {
00237     for (t=0; t < inSamples_; t++)
00238     {
00239       for (o=0; o < inObservations_; o++)
00240       {
00241         out(o,t) = in(o,t);
00242       }
00243     }
00244 
00245     if (audio_ != NULL)
00246     {
00247 //          for (t=0; t < bufferSize_; t++)
00248 //          {
00249 //              data_[2*t] = 0.0;
00250 //              data_[2*t+1] = 0.0;
00251 //          }
00252 //
00253 //          try
00254 //          {
00255 //              audio_->tickStream();
00256 //          }
00257 
00258       try
00259       {
00260         audio_->stopStream();
00261       }
00262       catch (RtError3 &error)
00263       {
00264         error.printMessage();
00265       }
00266     }
00267 
00268     return;
00269   }
00270 
00271   // copy to output and into reservoir
00272 
00273 
00274 
00275   for (t=0; t < inSamples_; t++)
00276   {
00277     for (o=0; o < inObservations_; o++)
00278     {
00279       reservoir_(o, end_) = in(o,t);
00280       out(o,t) = in(o,t);
00281     }
00282     end_ ++;
00283     if (end_ == reservoirSize_)
00284       end_ = 0;
00285   }
00286 
00287 
00288 
00289   //check if RtAudio is initialized
00290   if (!isInitialized_) {
00291     return;
00292   }
00293 
00294 
00295   //assure that RtAudio thread is running
00296   //(this may be needed by if an explicit call to start()
00297   //is not done before ticking or calling process() )
00298   if ( stopped_ )
00299   {
00300     start();
00301   }
00302 
00303 
00304   //update reservoir pointers
00305   rsize_ = bufferSize_;
00306 #ifdef MARSYAS_MACOSX
00307   if (srate_ == 22050)
00308     rsize_ = bufferSize_/2;     // upsample to 44100
00309   else
00310     rsize_ = bufferSize_;
00311 #endif
00312 
00313   if (end_ >= start_)
00314     diff_ = end_ - start_;
00315   else
00316     diff_ = reservoirSize_ - (start_ - end_);
00317 
00318   //send audio data in reservoir to RtAudio
00319 
00320 //  cout << "diff_=" << diff_ << " rsize_=" << rsize_ << " reservoirSize_=" << reservoirSize_ << " start_=" << start_ << " end_=" << end_ << endl;
00321   while (diff_ >= rsize_)
00322   {
00323 //    cout << "diff_=" << diff_ << endl;
00324     for (t =0; t < rsize_; t++)
00325     {
00326       int rt = (start_ + t);
00327 
00328       while (rt >= reservoirSize_)
00329         rt -= reservoirSize_;
00330       while (rt < 0)
00331         rt += reservoirSize_;
00332 
00333       const int t2 = 2 * t;
00334 
00335       // What does this do? - LG
00336       // Why is this defined?? - <3 lg
00337 //#ifndef MARSYAS_MACOSX
00338 //
00339 //          if (inObservations_ == 1)
00340 //          {
00341 //              for (int j=0; j < nChannels_; j++)
00342 //              {
00343 //                  data_[t2+j] = reservoir_(0, rt);
00344 //              }
00345 //          }
00346 //          else
00347 //          {
00348 //              for (int j=0; j < nChannels_; j++)
00349 //              {
00350 //                  data_[t2+j] = reservoir_(0+j,   rt);
00351 //              }
00352 //
00353 //          }
00354 //
00355 //#else
00356       const int t4 = 4 * t;
00357       if (srate_ == 22050)
00358       {
00359 
00360         if (inObservations_ == 1)
00361         {
00362           data_[t4] = reservoir_(0,rt);
00363           data_[t4+1] = reservoir_(0,rt);
00364           data_[t4+2] = reservoir_(0,rt);
00365           data_[t4+3] = reservoir_(0,rt);
00366         }
00367         else
00368         {
00369           for (int j=0; j < nChannels_; j++)
00370           {
00371             data_[t4] = reservoir_(0+j,rt);
00372             data_[t4+2+j] = reservoir_(0+j,rt);
00373           }
00374         }
00375 
00376       }
00377       else
00378       {
00379         if (inObservations_ == 1)
00380         {
00381 
00382           mrs_real foo = reservoir_(0, rt);
00383           data_[t2] = foo;
00384           data_[t2+1] = foo;
00385         }
00386         else
00387         {
00388 
00389           for (int j=0; j < nChannels_; j++)
00390           {
00391             data_[t2+j] = reservoir_(j,   rt);
00392           }
00393 
00394         }
00395       }
00396 //#endif
00397     }
00398 
00399     //tick RtAudio
00400     try
00401     {
00402       audio_->tickStream();
00403     }
00404     catch (RtError3 &error)
00405     {
00406       error.printMessage();
00407     }
00408 
00409 
00410     //update reservoir pointers
00411     start_ = (start_ + rsize_) % reservoirSize_;
00412     if (end_ >= start_)
00413       diff_ = end_ - start_;
00414     else
00415       diff_ = reservoirSize_ - (start_ - end_);
00416 
00417   }
00418 //   cout << "AudioSinkBlocking::myProcess end" << endl;
00419 
00420 }