⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtduplex.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
字号:
/***************************************************//*! \class RtDuplex    \brief STK realtime audio (blocking) input/output class.    This class provides a simplified interface to    RtAudio for realtime audio input/output.  It    may also be possible to achieve duplex    operation using separate RtWvIn and RtWvOut    classes, but this class ensures better    input/output synchronization.    Because this class makes use of RtAudio's    blocking input/output routines, its    performance is less robust on systems where    the audio API is callback-based (Macintosh    CoreAudio and Windows ASIO).    RtDuplex supports multi-channel data in    interleaved format.  It is important to    distinguish the tick() methods, which output    single samples to all channels in a sample    frame and return samples produced by averaging    across sample frames, from the tickFrame()    methods, which take/return pointers to    multi-channel sample frames.    by Perry R. Cook and Gary P. Scavone, 1995 - 2005.*//***************************************************/#include "RtDuplex.h"#if !defined(SYMBIAN)RtDuplex :: RtDuplex(int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers ){  channels_ = nChannels;  bufferSize_ = bufferFrames;  RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;  audio_ = 0;  try {    audio_ = new RtAudio();  }  catch (RtError &error) {    handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );  }  // Now open a stream and get the buffer pointer.  try {    audio_->openStream(device, channels_, device, channels_, format,                      (int)sampleRate, &bufferSize_, nBuffers);    data_ = (StkFloat *) audio_->getStreamBuffer();  }  catch (RtError &error) {    handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );  }  lastOutput_ = (StkFloat *) new StkFloat[channels_];  for (unsigned int i=0; i<channels_; i++) lastOutput_[i] = 0.0;  counter_ = 0;  stopped_ = true;}RtDuplex :: ~RtDuplex(){  if ( !stopped_ )    audio_->stopStream();  delete audio_;  delete [] lastOutput_;  data_ = 0; // RtAudio deletes the buffer itself.}void RtDuplex :: start(){  if ( stopped_ ) {    audio_->startStream();    stopped_ = false;  }}void RtDuplex :: stop(){  if ( !stopped_ ) {    audio_->stopStream();    stopped_ = true;  }}StkFloat RtDuplex :: lastOut(void) const{  if ( channels_ == 1 )    return *lastOutput_;  StkFloat output = 0.0;  for (unsigned int i=0; i<channels_; i++ ) {    output += lastOutput_[i];  }  return output / channels_;}StkFloat RtDuplex :: tick(const StkFloat sample){  if ( stopped_ )    start();  if (counter_ == 0) {    try {      audio_->tickStream();    }    catch (RtError &error) {      handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );    }  }  unsigned long temp = counter_ * channels_;  for (unsigned int i=0; i<channels_; i++) {    lastOutput_[i] = data_[temp];    data_[temp++] = sample;  }  counter_++;  if (counter_ >= (long) bufferSize_)    counter_ = 0;  return lastOut();}StkFloat *RtDuplex :: tick(StkFloat *vector, unsigned int vectorSize){  for ( unsigned int i=0; i<vectorSize; i++ )    vector[i] = tick(vector[i]);  return vector;}StkFrames& RtDuplex :: tick( StkFrames& frames, unsigned int channel ){  if ( channel == 0 || frames.channels() < channel ) {    errorString_ << "RtDuplex::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";    handleError( StkError::FUNCTION_ARGUMENT );  }  if ( frames.channels() == 1 ) {    for ( unsigned int i=0; i<frames.frames(); i++ )      frames[i] = tick( frames[i] );  }  else if ( frames.interleaved() ) {    unsigned int hop = frames.channels();    unsigned int index = channel - 1;    for ( unsigned int i=0; i<frames.frames(); i++ ) {      frames[index] = tick( frames[index] );      index += hop;    }  }  else {    unsigned int iStart = (channel - 1) * frames.frames();    for ( unsigned int i=0; i<frames.frames(); i++ )      frames[iStart + i] = tick( frames[iStart + i] );  }  return frames;}const StkFloat *RtDuplex :: lastFrame() const{  return lastOutput_;}StkFloat *RtDuplex :: tickFrame(StkFloat *frameVector, unsigned int frames){  if ( stopped_ )    start();  unsigned int i;  unsigned long temp;  for (unsigned int j=0; j<frames; j++ ) {    if (counter_ == 0) {      try {        audio_->tickStream();      }      catch (RtError &error) {        handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );      }    }    temp = counter_ * channels_;    for (i=0; i<channels_; i++) {      lastOutput_[i] = data_[temp];      data_[temp++] = frameVector[j*channels_+i];      frameVector[j*channels_+i] = lastOutput_[i];    }    counter_++;    if (counter_ >= (long) bufferSize_)      counter_ = 0;  }  return frameVector;}StkFrames& RtDuplex :: tickFrame( StkFrames& frames ){  if ( channels_ != frames.channels() ) {    errorString_ << "RtDuplex::tickFrame(): incompatible channel value in StkFrames argument!";    handleError( StkError::FUNCTION_ARGUMENT );  }  if ( stopped_ )    start();  unsigned long j, index = 0;  unsigned long k, hop = frames.frames();  for (unsigned int i=0; i<frames.frames(); i++ ) {    if (counter_ == 0) {      try {        audio_->tickStream();      }      catch (RtError &error) {        handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );      }    }    if ( channels_ > 1 && frames.interleaved() == false ) {      k = i;      for (j=0; j<channels_; j++) {        lastOutput_[j] = data_[index];        data_[index++] = frames[k];        frames[k] = lastOutput_[j];        k += hop;      }    }    else {      for (j=0; j<channels_; j++) {        lastOutput_[j] = data_[index];        data_[index] = frames[index];        frames[index++] = lastOutput_[j];      }    }    counter_++;    if (counter_ >= (long) bufferSize_)      counter_ = 0;  }  return frames;}#endif // SYMBIAN

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -