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

📄 rtaudio.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        stream_.convertInfo[mode].inOffset.push_back( k );        stream_.convertInfo[mode].outOffset.push_back( k );      }    }  }  return SUCCESS; error:  if (handle) {    if (handle[0])      close(handle[0]);    free(handle);    stream_.apiHandle = 0;  }  if (stream_.userBuffer) {    free(stream_.userBuffer);    stream_.userBuffer = 0;  }  error(RtError::DEBUG_WARNING);  return FAILURE;}void RtApiOss :: closeStream(){  // We don't want an exception to be thrown here because this  // function is called by our class destructor.  So, do our own  // stream check.  if ( stream_.mode == UNINITIALIZED ) {    sprintf(message_, "RtApiOss::closeStream(): no open stream to close!");    error(RtError::WARNING);    return;  }  int *handle = (int *) stream_.apiHandle;  if (stream_.state == STREAM_RUNNING) {    if (stream_.mode == OUTPUT || stream_.mode == DUPLEX)      ioctl(handle[0], SNDCTL_DSP_RESET, 0);    else      ioctl(handle[1], SNDCTL_DSP_RESET, 0);    stream_.state = STREAM_STOPPED;  }  if (stream_.callbackInfo.usingCallback) {    stream_.callbackInfo.usingCallback = false;    pthread_join(stream_.callbackInfo.thread, NULL);  }  if (handle) {    if (handle[0]) close(handle[0]);    if (handle[1]) close(handle[1]);    free(handle);    stream_.apiHandle = 0;  }  if (stream_.userBuffer) {    free(stream_.userBuffer);    stream_.userBuffer = 0;  }  if (stream_.deviceBuffer) {    free(stream_.deviceBuffer);    stream_.deviceBuffer = 0;  }  stream_.mode = UNINITIALIZED;}void RtApiOss :: startStream(){  verifyStream();  if (stream_.state == STREAM_RUNNING) return;  MUTEX_LOCK(&stream_.mutex);  stream_.state = STREAM_RUNNING;  // No need to do anything else here ... OSS automatically starts  // when fed samples.  MUTEX_UNLOCK(&stream_.mutex);}void RtApiOss :: stopStream(){  verifyStream();  if (stream_.state == STREAM_STOPPED) return;  // Change the state before the lock to improve shutdown response  // when using a callback.  stream_.state = STREAM_STOPPED;  MUTEX_LOCK(&stream_.mutex);  int err;  int *handle = (int *) stream_.apiHandle;  if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {    err = ioctl(handle[0], SNDCTL_DSP_POST, 0);    //err = ioctl(handle[0], SNDCTL_DSP_SYNC, 0);    if (err < -1) {      sprintf(message_, "RtApiOss: error stopping device (%s).",              devices_[stream_.device[0]].name.c_str());      error(RtError::DRIVER_ERROR);    }  }  else {    err = ioctl(handle[1], SNDCTL_DSP_POST, 0);    //err = ioctl(handle[1], SNDCTL_DSP_SYNC, 0);    if (err < -1) {      sprintf(message_, "RtApiOss: error stopping device (%s).",              devices_[stream_.device[1]].name.c_str());      error(RtError::DRIVER_ERROR);    }  }  MUTEX_UNLOCK(&stream_.mutex);}void RtApiOss :: abortStream(){  stopStream();}int RtApiOss :: streamWillBlock(){  verifyStream();  if (stream_.state == STREAM_STOPPED) return 0;  MUTEX_LOCK(&stream_.mutex);  int bytes = 0, channels = 0, frames = 0;  audio_buf_info info;  int *handle = (int *) stream_.apiHandle;  if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {    ioctl(handle[0], SNDCTL_DSP_GETOSPACE, &info);    bytes = info.bytes;    channels = stream_.nDeviceChannels[0];  }  if (stream_.mode == INPUT || stream_.mode == DUPLEX) {    ioctl(handle[1], SNDCTL_DSP_GETISPACE, &info);    if (stream_.mode == DUPLEX ) {      bytes = (bytes < info.bytes) ? bytes : info.bytes;      channels = stream_.nDeviceChannels[0];    }    else {      bytes = info.bytes;      channels = stream_.nDeviceChannels[1];    }  }  frames = (int) (bytes / (channels * formatBytes(stream_.deviceFormat[0])));  frames -= stream_.bufferSize;  if (frames < 0) frames = 0;  MUTEX_UNLOCK(&stream_.mutex);  return frames;}void RtApiOss :: tickStream(){  verifyStream();  int stopStream = 0;  if (stream_.state == STREAM_STOPPED) {    if (stream_.callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds    return;  }  else if (stream_.callbackInfo.usingCallback) {    RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;    stopStream = callback(stream_.userBuffer, stream_.bufferSize, stream_.callbackInfo.userData);  }  MUTEX_LOCK(&stream_.mutex);  // The state might change while waiting on a mutex.  if (stream_.state == STREAM_STOPPED)    goto unlock;  int result, *handle;  char *buffer;  int samples;  RtAudioFormat format;  handle = (int *) stream_.apiHandle;  if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {    // Setup parameters and do buffer conversion if necessary.    if (stream_.doConvertBuffer[0]) {      buffer = stream_.deviceBuffer;      convertBuffer( buffer, stream_.userBuffer, stream_.convertInfo[0] );      samples = stream_.bufferSize * stream_.nDeviceChannels[0];      format = stream_.deviceFormat[0];    }    else {      buffer = stream_.userBuffer;      samples = stream_.bufferSize * stream_.nUserChannels[0];      format = stream_.userFormat;    }    // Do byte swapping if necessary.    if (stream_.doByteSwap[0])      byteSwapBuffer(buffer, samples, format);    // Write samples to device.    result = write(handle[0], buffer, samples * formatBytes(format));    if (result == -1) {      // This could be an underrun, but the basic OSS API doesn't provide a means for determining that.      sprintf(message_, "RtApiOss: audio write error for device (%s).",              devices_[stream_.device[0]].name.c_str());      error(RtError::DRIVER_ERROR);    }  }  if (stream_.mode == INPUT || stream_.mode == DUPLEX) {    // Setup parameters.    if (stream_.doConvertBuffer[1]) {      buffer = stream_.deviceBuffer;      samples = stream_.bufferSize * stream_.nDeviceChannels[1];      format = stream_.deviceFormat[1];    }    else {      buffer = stream_.userBuffer;      samples = stream_.bufferSize * stream_.nUserChannels[1];      format = stream_.userFormat;    }    // Read samples from device.    result = read(handle[1], buffer, samples * formatBytes(format));    if (result == -1) {      // This could be an overrun, but the basic OSS API doesn't provide a means for determining that.      sprintf(message_, "RtApiOss: audio read error for device (%s).",              devices_[stream_.device[1]].name.c_str());      error(RtError::DRIVER_ERROR);    }    // Do byte swapping if necessary.    if (stream_.doByteSwap[1])      byteSwapBuffer(buffer, samples, format);    // Do buffer conversion if necessary.    if (stream_.doConvertBuffer[1])      convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] );  } unlock:  MUTEX_UNLOCK(&stream_.mutex);  if (stream_.callbackInfo.usingCallback && stopStream)    this->stopStream();}void RtApiOss :: setStreamCallback(RtAudioCallback callback, void *userData){  verifyStream();  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;  if ( info->usingCallback ) {    sprintf(message_, "RtApiOss: A callback is already set for this stream!");    error(RtError::WARNING);    return;  }  info->callback = (void *) callback;  info->userData = userData;  info->usingCallback = true;  info->object = (void *) this;  // Set the thread attributes for joinable and realtime scheduling  // priority.  The higher priority will only take affect if the  // program is run as root or suid.  pthread_attr_t attr;  pthread_attr_init(&attr);  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);  pthread_attr_setschedpolicy(&attr, SCHED_RR);  int err = pthread_create(&(info->thread), &attr, ossCallbackHandler, &stream_.callbackInfo);  pthread_attr_destroy(&attr);  if (err) {    info->usingCallback = false;    sprintf(message_, "RtApiOss: error starting callback thread!");    error(RtError::THREAD_ERROR);  }}void RtApiOss :: cancelStreamCallback(){  verifyStream();  if (stream_.callbackInfo.usingCallback) {    if (stream_.state == STREAM_RUNNING)      stopStream();    MUTEX_LOCK(&stream_.mutex);    stream_.callbackInfo.usingCallback = false;    pthread_join(stream_.callbackInfo.thread, NULL);    stream_.callbackInfo.thread = 0;    stream_.callbackInfo.callback = NULL;    stream_.callbackInfo.userData = NULL;    MUTEX_UNLOCK(&stream_.mutex);  }}extern "C" void *ossCallbackHandler(void *ptr){  CallbackInfo *info = (CallbackInfo *) ptr;  RtApiOss *object = (RtApiOss *) info->object;  bool *usingCallback = &info->usingCallback;  while ( *usingCallback ) {    pthread_testcancel();    try {      object->tickStream();    }    catch (RtError &exception) {      fprintf(stderr, "\nRtApiOss: callback thread error (%s) ... closing thread.\n\n",              exception.getMessageString());      break;    }  }  return 0;}//******************** End of __LINUX_OSS__ *********************//#endif#if defined(__MACOSX_CORE__)// The OS X CoreAudio API is designed to use a separate callback// procedure for each of its audio devices.  A single RtAudio duplex// stream using two different devices is supported here, though it// cannot be guaranteed to always behave correctly because we cannot// synchronize these two callbacks.  This same functionality can be// achieved with better synchrony by opening two separate streams for// the devices and using RtAudio blocking calls (i.e. tickStream()).//// A property listener is installed for over/underrun information.// However, no functionality is currently provided to allow property// listeners to trigger user handlers because it is unclear what could// be done if a critical stream parameter (buffer size, sample rate,// device disconnect) notification arrived.  The listeners entail// quite a bit of extra code and most likely, a user program wouldn't// be prepared for the result anyway.// A structure to hold various information related to the CoreAudio API// implementation.struct CoreHandle {  UInt32 index[2];  bool stopStream;  bool xrun;  char *deviceBuffer;  pthread_cond_t condition;  CoreHandle()    :stopStream(false), xrun(false), deviceBuffer(0) {}};RtApiCore :: RtApiCore(){  this->initialize();  if (nDevices_ <= 0) {    sprintf(message_, "RtApiCore: no Macintosh OS-X Core Audio devices found!");    error(RtError::NO_DEVICES_FOUND); }}RtApiCore :: ~RtApiCore(){  // The subclass destructor gets called before the base class  // destructor, so close an existing stream before deallocating  // apiDeviceId memory.  if ( stream_.mode != UNINITIALIZED ) closeStream();  // Free our allocated apiDeviceId memory.  AudioDeviceID *id;  for ( unsigned int i=0; i<devices_.size(); i++ ) {    id = (AudioDeviceID *) devices_[i].apiDeviceId;    if (id) free(id);  }}void RtApiCore :: initialize(void){  OSStatus err = noErr;  UInt32 dataSize;  AudioDeviceID	*deviceList = NULL;  nDevices_ = 0;  // Find out how many audio devices there are, if any.  err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &dataSize, NULL);  if (err != noErr) {    sprintf(message_, "RtApiCore: OS-X error getting device info!");    error(RtError::SYSTEM_ERROR);  }  nDevices_ = dataSize / sizeof(AudioDeviceID);  if (nDevices_ == 0) return;  // Make space for the devices we are about to get.  deviceList = (AudioDeviceID	*) malloc( dataSize );  if (deviceList == NULL) {    sprintf(message_, "RtApiCore: memory allocation error during initialization!");

⌨️ 快捷键说明

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