コード例 #1
0
bool CAUOutputDevice::GetPreferredChannelLayout(CCoreAudioChannelLayout& layout)
{
  if (!m_DeviceId)
    return false;

  UInt32 propertySize = 0;
  Boolean writable = false;
  OSStatus ret = AudioDeviceGetPropertyInfo(m_DeviceId, 0, false,
    kAudioDevicePropertyPreferredChannelLayout, &propertySize, &writable);
  if (ret)
    return false;

  void* pBuf = malloc(propertySize);
  ret = AudioDeviceGetProperty(m_DeviceId, 0, false,
    kAudioDevicePropertyPreferredChannelLayout, &propertySize, pBuf);
  if (ret)
    CLog::Log(LOGERROR, "CAUOutputDevice::GetPreferredChannelLayout: "
      "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str());
  else
  {
    // Copy the result into the caller's instance
    layout.CopyLayout(*((AudioChannelLayout*)pBuf));
  }
  free(pBuf);
  return (ret == noErr);
}
コード例 #2
0
ファイル: CoreAudioDevice.cpp プロジェクト: 0xheart0/xbmc
bool CCoreAudioDevice::GetPreferredChannelLayout(CCoreAudioChannelLayout& layout) const
{
  if (!m_DeviceId)
    return false;

  AudioObjectPropertyAddress  propertyAddress;
  propertyAddress.mScope    = kAudioDevicePropertyScopeOutput;
  propertyAddress.mElement  = 0;
  propertyAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;

  UInt32 propertySize = 0;
  OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize);
  if (ret)
    return false;

  void* pBuf = malloc(propertySize);
  ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pBuf);
  if (ret != noErr)
    CLog::Log(LOGERROR, "CCoreAudioDevice::GetPreferredChannelLayout: "
      "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str());
  else
  {
    // Copy the result into the caller's instance
    layout.CopyLayout(*((AudioChannelLayout*)pBuf));
  }
  free(pBuf);
  return (ret == noErr);
}
コード例 #3
0
ファイル: CoreAudioDevice.cpp プロジェクト: 0xheart0/xbmc
bool CCoreAudioDevice::GetPreferredChannelLayoutForStereo(CCoreAudioChannelLayout &layout) const
{
  if (!m_DeviceId)
    return false;
  
  AudioObjectPropertyAddress  propertyAddress;
  propertyAddress.mScope    = kAudioDevicePropertyScopeOutput;
  propertyAddress.mElement  = 0;
  propertyAddress.mSelector = kAudioDevicePropertyPreferredChannelsForStereo;

  UInt32 channels[2];// this will receive the channel labels
  UInt32 propertySize = sizeof(channels);

  OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &channels);
  if (ret != noErr)
    CLog::Log(LOGERROR, "CCoreAudioDevice::GetPreferredChannelLayoutForStereo: "
              "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str());
  else
  {
    // Copy/generate a layout into the result into the caller's instance
    layout.CopyLayoutForStereo(channels);
  }
  return (ret == noErr);
}
コード例 #4
0
//Note: in multichannel mode CA will either pull 2 channels of data (stereo) or 6/8 channels of data
//(every speaker setup with more then 2 speakers). The difference between the number of real speakers
//and 6/8 channels needs to be padded with unknown channels so that the sample size fits 6/8 channels
//
//device [in] - the device whose channel layout should be used
//channelMap [in/out] - if filled it will it indicates that we are called from initialize and we log the requested map, out returns the channelMap for device
//channelsPerFrame [in] - the number of channels this device is configured to (e.x. 2 or 6/8)
void AEDeviceEnumerationOSX::GetAEChannelMap(CAEChannelInfo &channelMap, unsigned int channelsPerFrame) const
{
  CCoreAudioChannelLayout calayout;
  bool logMapping = channelMap.Count() > 0; // only log if the engine requests a layout during init
  bool mapAvailable = false;
  unsigned int numberChannelsInDeviceLayout = CA_MAX_CHANNELS; // default number of channels from CAChannelMap
  AudioChannelLayout *layout = NULL;
  
  // try to fetch either the multichannel or the stereo channel layout from the device
  if (channelsPerFrame == 2 || channelMap.Count() == 2)
    mapAvailable = m_caDevice.GetPreferredChannelLayoutForStereo(calayout);
  else
    mapAvailable = m_caDevice.GetPreferredChannelLayout(calayout);
  
  // if a map was fetched - check if it is usable
  if (mapAvailable)
  {
    layout = calayout;
    if (layout == NULL || layout->mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions)
      mapAvailable = false;// wrong map format
    else
      numberChannelsInDeviceLayout = layout->mNumberChannelDescriptions;
  }
  
  // start the mapping action
  // the number of channels to be added to the outgoing channelmap
  // this is CA_MAX_CHANNELS at max and might be lower for some output devices (channelsPerFrame)
  unsigned int numChannelsToMap = std::min((unsigned int)CA_MAX_CHANNELS, (unsigned int)channelsPerFrame);
  
  // if there was a map fetched we force the number of
  // channels to map to channelsPerFrame (this allows mapping
  // of more then CA_MAX_CHANNELS if needed)
  if (mapAvailable)
    numChannelsToMap = channelsPerFrame;
  
  std::string layoutStr;
  
  if (logMapping)
  {
    CLog::Log(LOGDEBUG, "%s Engine requests layout %s", __FUNCTION__, ((std::string)channelMap).c_str());
    
    if (mapAvailable)
      CLog::Log(LOGDEBUG, "%s trying to map to %s layout: %s", __FUNCTION__, channelsPerFrame == 2 ? "stereo" : "multichannel", calayout.ChannelLayoutToString(*layout, layoutStr));
    else
      CLog::Log(LOGDEBUG, "%s no map available - using static multichannel map layout", __FUNCTION__);
  }
  
  channelMap.Reset();// start with an empty map
  
  for (unsigned int channel = 0; channel < numChannelsToMap; channel++)
  {
    // we only try to map channels which are defined in the device layout
    enum AEChannel currentChannel;
    if (channel < numberChannelsInDeviceLayout)
    {
      // get the channel from the fetched map
      if (mapAvailable)
        currentChannel = caChannelToAEChannel(layout->mChannelDescriptions[channel].mChannelLabel);
      else// get the channel from the default map
        currentChannel = CAChannelMap[channel];
      
    }
    else// fill with unknown channels
      currentChannel = caChannelToAEChannel(kAudioChannelLabel_Unknown);
    
    if(!channelMap.HasChannel(currentChannel))// only add if not already added
      channelMap += currentChannel;
  }
  
  if (logMapping)
    CLog::Log(LOGDEBUG, "%s mapped channels to layout %s", __FUNCTION__, ((std::string)channelMap).c_str());
}