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

📄 rtaudio.cpp

📁 Mobile STK for Symbian OS V0.1
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{  return stream_.state;}RtAudioDeviceInfo RtApi :: getDeviceInfo( int device ){  if (device > (int) devices_.size() || device < 1) {    sprintf(message_, "RtApi: invalid device specifier (%d)!", device);    error(RtError::INVALID_DEVICE);  }  RtAudioDeviceInfo info;  int deviceIndex = device - 1;  // If the device wasn't successfully probed before, try it now (or again).  if (devices_[deviceIndex].probed == false) {    clearDeviceInfo(&devices_[deviceIndex]);    probeDeviceInfo(&devices_[deviceIndex]);  }  info.name.append( devices_[deviceIndex].name );  info.probed = devices_[deviceIndex].probed;  if ( info.probed == true ) {    info.outputChannels = devices_[deviceIndex].maxOutputChannels;    info.inputChannels = devices_[deviceIndex].maxInputChannels;    info.duplexChannels = devices_[deviceIndex].maxDuplexChannels;    for (unsigned int i=0; i<devices_[deviceIndex].sampleRates.size(); i++)      info.sampleRates.push_back( devices_[deviceIndex].sampleRates[i] );    info.nativeFormats = devices_[deviceIndex].nativeFormats;    if ( (deviceIndex == getDefaultOutputDevice()) ||         (deviceIndex == getDefaultInputDevice()) )      info.isDefault = true;  }  return info;}char * const RtApi :: getStreamBuffer(void){  verifyStream();  return stream_.userBuffer;}int RtApi :: getDefaultInputDevice(void){  // Should be implemented in subclasses if appropriate.  return 0;}int RtApi :: getDefaultOutputDevice(void){  // Should be implemented in subclasses if appropriate.  return 0;}void RtApi :: closeStream(void){  // MUST be implemented in subclasses!}void RtApi :: probeDeviceInfo( RtApiDevice *info ){  // MUST be implemented in subclasses!}bool RtApi :: probeDeviceOpen( int device, StreamMode mode, int channels,                                int sampleRate, RtAudioFormat format,                               int *bufferSize, int numberOfBuffers ){  // MUST be implemented in subclasses!  return FAILURE;}// *************************************************** ////// OS/API-specific methods.//// *************************************************** //#if defined(__LINUX_OSS__)#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#include <sys/soundcard.h>#include <errno.h>#include <math.h>#define DAC_NAME "/dev/dsp"#define MAX_DEVICES 16#define MAX_CHANNELS 16extern "C" void *ossCallbackHandler(void * ptr);RtApiOss :: RtApiOss(){  this->initialize();  if (nDevices_ <= 0) {    sprintf(message_, "RtApiOss: no Linux OSS audio devices found!");    error(RtError::NO_DEVICES_FOUND); }}RtApiOss :: ~RtApiOss(){  if ( stream_.mode != UNINITIALIZED )    closeStream();}void RtApiOss :: initialize(void){  // Count cards and devices  nDevices_ = 0;  // We check /dev/dsp before probing devices.  /dev/dsp is supposed to  // be a link to the "default" audio device, of the form /dev/dsp0,  // /dev/dsp1, etc...  However, I've seen many cases where /dev/dsp was a  // real device, so we need to check for that.  Also, sometimes the  // link is to /dev/dspx and other times just dspx.  I'm not sure how  // the latter works, but it does.  char device_name[16];  struct stat dspstat;  int dsplink = -1;  int i = 0;  if (lstat(DAC_NAME, &dspstat) == 0) {    if (S_ISLNK(dspstat.st_mode)) {      i = readlink(DAC_NAME, device_name, sizeof(device_name));      if (i > 0) {        device_name[i] = '\0';        if (i > 8) { // check for "/dev/dspx"          if (!strncmp(DAC_NAME, device_name, 8))            dsplink = atoi(&device_name[8]);        }        else if (i > 3) { // check for "dspx"          if (!strncmp("dsp", device_name, 3))            dsplink = atoi(&device_name[3]);        }      }      else {        sprintf(message_, "RtApiOss: cannot read value of symbolic link %s.", DAC_NAME);        error(RtError::SYSTEM_ERROR);      }    }  }  else {    sprintf(message_, "RtApiOss: cannot stat %s.", DAC_NAME);    error(RtError::SYSTEM_ERROR);  }  // The OSS API doesn't provide a routine for determining the number  // of devices.  Thus, we'll just pursue a brute force method.  The  // idea is to start with /dev/dsp(0) and continue with higher device  // numbers until we reach MAX_DSP_DEVICES.  This should tell us how  // many devices we have ... it is not a fullproof scheme, but hopefully  // it will work most of the time.  int fd = 0;  RtApiDevice device;  for (i=-1; i<MAX_DEVICES; i++) {    // Probe /dev/dsp first, since it is supposed to be the default device.    if (i == -1)      sprintf(device_name, "%s", DAC_NAME);    else if (i == dsplink)      continue; // We've aready probed this device via /dev/dsp link ... try next device.    else      sprintf(device_name, "%s%d", DAC_NAME, i);    // First try to open the device for playback, then record mode.    fd = open(device_name, O_WRONLY | O_NONBLOCK);    if (fd == -1) {      // Open device for playback failed ... either busy or doesn't exist.      if (errno != EBUSY && errno != EAGAIN) {        // Try to open for capture        fd = open(device_name, O_RDONLY | O_NONBLOCK);        if (fd == -1) {          // Open device for record failed.          if (errno != EBUSY && errno != EAGAIN)            continue;          else {            sprintf(message_, "RtApiOss: OSS record device (%s) is busy.", device_name);            error(RtError::WARNING);            // still count it for now          }        }      }      else {        sprintf(message_, "RtApiOss: OSS playback device (%s) is busy.", device_name);        error(RtError::WARNING);        // still count it for now      }    }    if (fd >= 0) close(fd);    device.name.erase();    device.name.append( (const char *)device_name, strlen(device_name)+1);    devices_.push_back(device);    nDevices_++;  }}void RtApiOss :: probeDeviceInfo(RtApiDevice *info){  int i, fd, channels, mask;  // The OSS API doesn't provide a means for probing the capabilities  // of devices.  Thus, we'll just pursue a brute force method.  // First try for playback  fd = open(info->name.c_str(), O_WRONLY | O_NONBLOCK);  if (fd == -1) {    // Open device failed ... either busy or doesn't exist    if (errno == EBUSY || errno == EAGAIN)      sprintf(message_, "RtApiOss: OSS playback device (%s) is busy and cannot be probed.",              info->name.c_str());    else      sprintf(message_, "RtApiOss: OSS playback device (%s) open error.", info->name.c_str());    error(RtError::DEBUG_WARNING);    goto capture_probe;  }  // We have an open device ... see how many channels it can handle  for (i=MAX_CHANNELS; i>0; i--) {    channels = i;    if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) {      // This would normally indicate some sort of hardware error, but under ALSA's      // OSS emulation, it sometimes indicates an invalid channel value.  Further,      // the returned channel value is not changed. So, we'll ignore the possible      // hardware error.      continue; // try next channel number    }    // Check to see whether the device supports the requested number of channels    if (channels != i ) continue; // try next channel number    // If here, we found the largest working channel value    break;  }  info->maxOutputChannels = i;  // Now find the minimum number of channels it can handle  for (i=1; i<=info->maxOutputChannels; i++) {    channels = i;    if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)      continue; // try next channel number    // If here, we found the smallest working channel value    break;  }  info->minOutputChannels = i;  close(fd); capture_probe:  // Now try for capture  fd = open(info->name.c_str(), O_RDONLY | O_NONBLOCK);  if (fd == -1) {    // Open device for capture failed ... either busy or doesn't exist    if (errno == EBUSY || errno == EAGAIN)      sprintf(message_, "RtApiOss: OSS capture device (%s) is busy and cannot be probed.",              info->name.c_str());    else      sprintf(message_, "RtApiOss: OSS capture device (%s) open error.", info->name.c_str());    error(RtError::DEBUG_WARNING);    if (info->maxOutputChannels == 0)      // didn't open for playback either ... device invalid      return;    goto probe_parameters;  }  // We have the device open for capture ... see how many channels it can handle  for (i=MAX_CHANNELS; i>0; i--) {    channels = i;    if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {      continue; // as above    }    // If here, we found a working channel value    break;  }  info->maxInputChannels = i;  // Now find the minimum number of channels it can handle  for (i=1; i<=info->maxInputChannels; i++) {    channels = i;    if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)      continue; // try next channel number    // If here, we found the smallest working channel value    break;  }  info->minInputChannels = i;  close(fd);  if (info->maxOutputChannels == 0 && info->maxInputChannels == 0) {    sprintf(message_, "RtApiOss: device (%s) reports zero channels for input and output.",            info->name.c_str());    error(RtError::DEBUG_WARNING);    return;  }  // If device opens for both playback and capture, we determine the channels.  if (info->maxOutputChannels == 0 || info->maxInputChannels == 0)    goto probe_parameters;  fd = open(info->name.c_str(), O_RDWR | O_NONBLOCK);  if (fd == -1)    goto probe_parameters;  ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);  ioctl(fd, SNDCTL_DSP_GETCAPS, &mask);  if (mask & DSP_CAP_DUPLEX) {    info->hasDuplexSupport = true;    // We have the device open for duplex ... see how many channels it can handle    for (i=MAX_CHANNELS; i>0; i--) {      channels = i;      if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)        continue; // as above      // If here, we found a working channel value      break;    }    info->maxDuplexChannels = i;    // Now find the minimum number of channels it can handle    for (i=1; i<=info->maxDuplexChannels; i++) {      channels = i;      if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i)        continue; // try next channel number      // If here, we found the smallest working channel value      break;    }    info->minDuplexChannels = i;  }  close(fd); probe_parameters:  // At this point, we need to figure out the supported data formats  // and sample rates.  We'll proceed by openning the device in the  // direction with the maximum number of channels, or playback if  // they are equal.  This might limit our sample rate options, but so  // be it.  if (info->maxOutputChannels >= info->maxInputChannels) {    fd = open(info->name.c_str(), O_WRONLY | O_NONBLOCK);    channels = info->maxOutputChannels;  }  else {    fd = open(info->name.c_str(), O_RDONLY | O_NONBLOCK);    channels = info->maxInputChannels;  }  if (fd == -1) {    // We've got some sort of conflict ... abort    sprintf(message_, "RtApiOss: device (%s) won't reopen during probe.",            info->name.c_str());    error(RtError::DEBUG_WARNING);    return;  }  // We have an open device ... set to maximum channels.  i = channels;  if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) {    // We've got some sort of conflict ... abort    close(fd);    sprintf(message_, "RtApiOss: device (%s) won't revert to previous channel setting.",            info->name.c_str());    error(RtError::DEBUG_WARNING);    return;  }  if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) {    close(fd);    sprintf(message_, "RtApiOss: device (%s) can't get supported audio formats.",            info->name.c_str());    error(RtError::DEBUG_WARNING);    return;  }  // Probe the supported data formats ... we don't care about endian-ness just yet.  int format;  info->nativeFormats = 0;#if defined (AFMT_S32_BE)  // This format does not seem to be in the 2.4 kernel version of OSS soundcard.h  if (mask & AFMT_S32_BE) {    format = AFMT_S32_BE;    info->nativeFormats |= RTAUDIO_SINT32;  }#endif#if defined (AFMT_S32_LE)  /* This format is not in the 2.4.4 kernel version of OSS soundcard.h */  if (mask & AFMT_S32_LE) {    format = AFMT_S32_LE;    info->nativeFormats |= RTAUDIO_SINT32;  }#endif  if (mask & AFMT_S8) {    format = AFMT_S8;    info->nativeFormats |= RTAUDIO_SINT8;  }  if (mask & AFMT_S16_BE) {    format = AFMT_S16_BE;    info->nativeFormats |= RTAUDIO_SINT16;  }  if (mask & AFMT_S16_LE) {    format = AFMT_S16_LE;    info->nativeFormats |= RTAUDIO_SINT16;  }  // Check that we have at least one supported format  if (info->nativeFormats == 0) {    close(fd);    sprintf(message_, "RtApiOss: device (%s) data format not supported by RtAudio.",            info->name.c_str());

⌨️ 快捷键说明

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