00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "AudioSource.h"
00021
00022 using namespace std;
00023 using namespace Marsyas;
00024
00025 AudioSource::AudioSource(string name):MarSystem("AudioSource", name)
00026 {
00027
00028 #ifdef MARSYAS_AUDIOIO
00029 audio_ = NULL;
00030 #endif
00031
00032
00033 ri_ = 0;
00034 pringBufferSize_ = 0;
00035
00036 isInitialized_ = false;
00037 stopped_ = true;
00038
00039 rtSrate_ = 0;
00040 bufferSize_ = 0;
00041 rtChannels_ = 0;
00042 nChannels_ = 0;
00043 pnChannels_ = 0;
00044
00045 addControls();
00046 }
00047
00048 AudioSource::~AudioSource()
00049 {
00050 #ifdef MARSYAS_AUDIOIO
00051 delete audio_;
00052 #endif
00053
00054 }
00055
00056
00057 MarSystem*
00058 AudioSource::clone() const
00059 {
00060 return new AudioSource(*this);
00061 }
00062
00063 void
00064 AudioSource::addControls()
00065 {
00066 addctrl("mrs_natural/nChannels", 1);
00067
00068
00069 #ifdef MARSYAS_MACOSX
00070 addctrl("mrs_natural/bufferSize", 1024);
00071 #else
00072 addctrl("mrs_natural/bufferSize", 256);
00073 #endif
00074
00075
00076 addctrl("mrs_bool/initAudio", false);
00077 setctrlState("mrs_bool/initAudio", true);
00078
00079 addctrl("mrs_bool/hasData", true);
00080 addctrl("mrs_real/gain", 1.0);
00081 }
00082
00083
00084
00085
00086 int
00087 AudioSource::recordCallback(void *outputBuffer, void *inputBuffer,
00088 unsigned int nBufferFrames,
00089 double streamTime, unsigned int status,
00090 void *userData)
00091 {
00092
00093 unsigned int drain_count = 0;
00094 mrs_real* data = (mrs_real*)inputBuffer;
00095 InputData *iData = (InputData *)userData;
00096 AudioSource* mythis = (AudioSource *)iData->myself;
00097 realvec& ringBuffer = *(iData->ringBuffer);
00098 unsigned int t;
00099 unsigned int spaceAvailable;
00100
00101 for (t=0; t < nBufferFrames; t++)
00102 {
00103 if (iData->samplesInBuffer <= iData->high_watermark)
00104 {
00105 ringBuffer(0,iData->wp) = data[2*t];
00106 ringBuffer(1,iData->wp) = data[2*t+1];
00107
00108 iData->wp = ++ (iData->wp) % iData->ringBufferSize;
00109 if (iData->wp >= iData->rp)
00110 iData->samplesInBuffer = iData->wp - iData->rp;
00111 else
00112 iData->samplesInBuffer = iData->ringBufferSize - (iData->rp - iData->wp);
00113 }
00114 else
00115 {
00116 while (iData->samplesInBuffer > iData->high_watermark)
00117 {
00118 SLEEP(1);
00119 drain_count++;
00120 if (drain_count == 1000)
00121 return 1;
00122 }
00123 }
00124 }
00125 return 0;
00126 }
00127
00128
00129
00130 void
00131 AudioSource::myUpdate(MarControlPtr sender)
00132 {
00133 (void) sender;
00134 MRSDIAG("AudioSource::myUpdate");
00135
00136
00137 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00138 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00139 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/nChannels"));
00140
00141
00142 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00143 inObservations_ = ctrl_inObservations_->to<mrs_natural>();
00144 gain_ = getctrl("mrs_real/gain")->to<mrs_real>();
00145
00146
00147
00148
00149 if (inSamples_ < bufferSize_)
00150 ringBufferSize_ = 8 * bufferSize_;
00151 else
00152 {
00153 ringBufferSize_ = 8 * inSamples_;
00154 }
00155
00156
00157 idata.ringBufferSize = ringBufferSize_;
00158 idata.high_watermark = ringBufferSize_/4;
00159 idata.low_watermark = ringBufferSize_/8;
00160
00161
00162 nChannels_ = getctrl("mrs_natural/nChannels")->to<mrs_natural>();
00163 if ((ringBufferSize_ > pringBufferSize_)||(nChannels_ != pnChannels_))
00164 {
00165 ringBuffer_.stretch(nChannels_, ringBufferSize_);
00166 }
00167 pringBufferSize_ = ringBufferSize_;
00168 pnChannels_ = nChannels_;
00169
00170
00171
00172
00173
00174 if (getctrl("mrs_bool/initAudio")->to<mrs_bool>())
00175 initRtAudio();
00176 }
00177
00178
00179 void
00180 AudioSource::initRtAudio()
00181 {
00182
00183 bufferSize_ = (int)getctrl("mrs_natural/bufferSize")->to<mrs_natural>();
00184 nChannels_ = getctrl("mrs_natural/nChannels")->to<mrs_natural>();
00185 rtSrate_ = (int)getctrl("mrs_real/israte")->to<mrs_real>();
00186 rtChannels_ = (int)getctrl("mrs_natural/nChannels")->to<mrs_natural>();
00187
00188
00189
00190 #ifdef MARSYAS_AUDIOIO
00191 if (audio_ == NULL)
00192 audio_ = new RtAudio();
00193
00194
00195 unsigned int bufferFrames = bufferSize_;
00196
00197
00198 RtAudio::StreamParameters iParams;
00199 iParams.deviceId = audio_->getDefaultInputDevice();
00200 iParams.nChannels = rtChannels_;
00201 iParams.firstChannel = 0;
00202
00203 idata.ringBuffer = &ringBuffer_;
00204 idata.wp = 0;
00205 idata.rp = 0;
00206 idata.ringBufferSize = ringBufferSize_;
00207 idata.myself = this;
00208
00209
00210
00211
00212
00213 RtAudioFormat rtFormat = (sizeof(mrs_real) == 8) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
00214
00215
00216 try
00217 {
00218 audio_->openStream(NULL, &iParams, rtFormat, rtSrate_,
00219 &bufferFrames, &recordCallback, (void *)&idata, NULL);
00220 }
00221 catch (RtError& e)
00222 {
00223 e.printMessage();
00224 exit(0);
00225 }
00226
00227
00228
00229
00230 setctrl("mrs_natural/bufferSize", (mrs_natural)bufferFrames);
00231
00232 #endif
00233
00234 isInitialized_ = true;
00235 setctrl("mrs_bool/initAudio", false);
00236 }
00237
00238 void
00239 AudioSource::start()
00240 {
00241 #ifdef MARSYAS_AUDIOIO
00242 if ( stopped_) {
00243 audio_->startStream();
00244 stopped_ = false;
00245 }
00246 #endif
00247 }
00248
00249 void
00250 AudioSource::stop()
00251 {
00252 #ifdef MARSYAS_AUDIOIO
00253 if ( !stopped_ ) {
00254 audio_->stopStream();
00255 stopped_ = true;
00256 }
00257 #endif
00258 }
00259
00260 void
00261 AudioSource::localActivate(bool state)
00262 {
00263 if(state)
00264 start();
00265 else
00266 stop();
00267 }
00268
00269
00270 unsigned int
00271 AudioSource::getSpaceAvailable()
00272 {
00273 unsigned int free = (idata.rp - idata.wp -1 + idata.ringBufferSize) % idata.ringBufferSize;
00274 unsigned int underMark = idata.high_watermark - getSamplesAvailable();
00275
00276 return(min(underMark, free));
00277 }
00278
00279
00280 unsigned int
00281 AudioSource::getSamplesAvailable()
00282 {
00283 unsigned int samplesAvailable = (idata.wp - idata.rp +idata.ringBufferSize) % idata.ringBufferSize;
00284 return samplesAvailable;
00285 }
00286
00287
00288 void
00289 AudioSource::myProcess(realvec& in, realvec& out)
00290 {
00291
00292
00293 (void) in;
00294
00295
00296 if (!isInitialized_)
00297 return;
00298
00299
00300 if(ctrl_mute_->isTrue()) return;
00301
00302
00303
00304
00305 if ( stopped_ )
00306 start();
00307
00308 for (t=0; t < onSamples_; t++)
00309 {
00310 if (getSamplesAvailable())
00311 {
00312 for (o=0; o < onObservations_; o++)
00313 out(o,t) = ringBuffer_(o,idata.rp);
00314 idata.rp = ++(idata.rp) % idata.ringBufferSize;
00315 if (idata.rp >= idata.rp)
00316 idata.samplesInBuffer = idata.wp - idata.rp;
00317 else
00318 idata.samplesInBuffer = idata.ringBufferSize - (idata.rp - idata.wp);
00319
00320 }
00321 }
00322
00323 while (idata.samplesInBuffer < idata.low_watermark)
00324 {
00325 SLEEP(1);
00326 }
00327
00328
00329
00330
00331 }
00332