[DEBUG] correct the Mac audio interface
This commit is contained in:
parent
09e32a815a
commit
22dd01978a
@ -36,6 +36,7 @@ const std::vector<uint32_t>& audio::orchestra::genericSampleRate() {
|
||||
list.push_back(128000);
|
||||
list.push_back(176400);
|
||||
list.push_back(192000);
|
||||
list.push_back(256000);
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
@ -19,24 +19,46 @@ void audio::orchestra::DeviceInfo::display(int32_t _tabNumber) const {
|
||||
for (int32_t iii=0; iii<_tabNumber; ++iii) {
|
||||
space += " ";
|
||||
}
|
||||
if (isCorrect == false) {
|
||||
ATA_PRINT(space + "NOT CORRECT INFORAMATIONS");
|
||||
return;
|
||||
}
|
||||
ATA_PRINT(space + "mode=" << (input==true?"input":"output"));
|
||||
ATA_PRINT(space + "name=" << name);
|
||||
ATA_PRINT(space + "desc=" << desc);
|
||||
if (desc.size() != 0) {
|
||||
ATA_PRINT(space + "desc=" << desc);
|
||||
}
|
||||
ATA_PRINT(space + "channel" << (channels.size()>1?"s":"") << "=" << channels.size() << " : " << channels);
|
||||
ATA_PRINT(space + "rate" << (sampleRates.size()>1?"s":"") << "=" << sampleRates);
|
||||
ATA_PRINT(space + "native Format" << (nativeFormats.size()>1?"s":"") << ": " << nativeFormats);
|
||||
ATA_PRINT(space + "default=" << (isDefault==true?"true":"false"));
|
||||
}
|
||||
|
||||
void audio::orchestra::DeviceInfo::clear() {
|
||||
isCorrect = false;
|
||||
input = false;
|
||||
name = "";
|
||||
desc = "";
|
||||
channels.clear();
|
||||
sampleRates.clear();
|
||||
nativeFormats.clear();
|
||||
isDefault = false;
|
||||
}
|
||||
|
||||
std::ostream& audio::orchestra::operator <<(std::ostream& _os, const audio::orchestra::DeviceInfo& _obj) {
|
||||
_os << "{";
|
||||
_os << "name=" << _obj.name << ", ";
|
||||
_os << "description=" << _obj.desc << ", ";
|
||||
_os << "channels=" << _obj.channels << ", ";
|
||||
_os << "default=" << _obj.isDefault << ", ";
|
||||
_os << "rates=" << _obj.sampleRates << ", ";
|
||||
_os << "native Format: " << _obj.nativeFormats;
|
||||
if (_obj.isCorrect == false) {
|
||||
_os << "NOT CORRECT INFORAMATIONS";
|
||||
} else {
|
||||
_os << "name=" << _obj.name << ", ";
|
||||
if (_obj.desc.size() != 0) {
|
||||
_os << "description=" << _obj.desc << ", ";
|
||||
}
|
||||
_os << "channels=" << _obj.channels << ", ";
|
||||
_os << "default=" << _obj.isDefault << ", ";
|
||||
_os << "rates=" << _obj.sampleRates << ", ";
|
||||
_os << "native Format: " << _obj.nativeFormats;
|
||||
}
|
||||
_os << "}";
|
||||
return _os;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ namespace audio {
|
||||
*/
|
||||
class DeviceInfo {
|
||||
public:
|
||||
bool isCorrect; //!< the information is correct (the system can return information incorect).
|
||||
bool input; //!< true if the device in an input; false: output.
|
||||
std::string name; //!< Character string device identifier.
|
||||
std::string desc; //!< description of the device
|
||||
@ -28,6 +29,7 @@ namespace audio {
|
||||
bool isDefault; //! is default input/output
|
||||
// Default constructor.
|
||||
DeviceInfo() :
|
||||
isCorrect(false),
|
||||
input(false),
|
||||
name(),
|
||||
desc(),
|
||||
@ -35,7 +37,14 @@ namespace audio {
|
||||
sampleRates(),
|
||||
nativeFormats(),
|
||||
isDefault(false) {}
|
||||
/**
|
||||
* @brief Display the current information of the device (on console)
|
||||
*/
|
||||
void display(int32_t _tabNumber = 1) const;
|
||||
/**
|
||||
* @brief Clear all internal data
|
||||
*/
|
||||
void clear();
|
||||
};
|
||||
std::ostream& operator <<(std::ostream& _os, const audio::orchestra::DeviceInfo& _obj);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ uint32_t audio::orchestra::api::Core::getDeviceCount() {
|
||||
ATA_ERROR("OS-X error getting device info!");
|
||||
return 0;
|
||||
}
|
||||
return dataSize / sizeof(AudioDeviceID);
|
||||
return (dataSize / sizeof(AudioDeviceID)) * 2;
|
||||
}
|
||||
|
||||
uint32_t audio::orchestra::api::Core::getDefaultInputDevice() {
|
||||
@ -145,7 +145,7 @@ uint32_t audio::orchestra::api::Core::getDefaultInputDevice() {
|
||||
}
|
||||
for (uint32_t iii=0; iii<nDevices; iii++) {
|
||||
if (id == deviceList[iii]) {
|
||||
return iii;
|
||||
return iii*2+1;
|
||||
}
|
||||
}
|
||||
ATA_ERROR("No default device found!");
|
||||
@ -189,7 +189,7 @@ uint32_t audio::orchestra::api::Core::getDefaultOutputDevice() {
|
||||
}
|
||||
for (uint32_t iii=0; iii<nDevices; iii++) {
|
||||
if (id == deviceList[iii]) {
|
||||
return iii;
|
||||
return iii*2;
|
||||
}
|
||||
}
|
||||
ATA_ERROR("No default device found!");
|
||||
@ -198,19 +198,25 @@ uint32_t audio::orchestra::api::Core::getDefaultOutputDevice() {
|
||||
|
||||
audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t _device) {
|
||||
audio::orchestra::DeviceInfo info;
|
||||
info.probed = false;
|
||||
// Get device ID
|
||||
uint32_t nDevices = getDeviceCount();
|
||||
if (nDevices == 0) {
|
||||
ATA_ERROR("no devices found!");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
if (_device >= nDevices) {
|
||||
ATA_ERROR("device ID is invalid!");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
AudioDeviceID deviceList[ nDevices ];
|
||||
uint32_t dataSize = sizeof(AudioDeviceID) * nDevices;
|
||||
info.input = false;
|
||||
if (_device%2 == 1) {
|
||||
info.input = true;
|
||||
}
|
||||
// The /2 corespond of not mixing input and output ... ==< then the user number of devide is twice the number of real device ...
|
||||
AudioDeviceID deviceList[nDevices/2];
|
||||
uint32_t dataSize = sizeof(AudioDeviceID) * nDevices/2;
|
||||
AudioObjectPropertyAddress property = {
|
||||
kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
@ -224,10 +230,13 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
||||
(void*)&deviceList);
|
||||
if (result != noErr) {
|
||||
ATA_ERROR("OS-X system error getting device IDs.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
AudioDeviceID id = deviceList[ _device ];
|
||||
AudioDeviceID id = deviceList[ _device/2 ];
|
||||
// ------------------------------------------------
|
||||
// Get the device name.
|
||||
// ------------------------------------------------
|
||||
info.name.erase();
|
||||
CFStringRef cfname;
|
||||
dataSize = sizeof(CFStringRef);
|
||||
@ -235,102 +244,85 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &cfname);
|
||||
if (result != noErr) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device manufacturer.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
//const char *mname = CFStringGetCStringPtr(cfname, CFStringGetSystemEncoding());
|
||||
int32_t length = CFStringGetLength(cfname);
|
||||
char *mname = (char *)malloc(length * 3 + 1);
|
||||
CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding());
|
||||
info.name.append((const char *)mname, strlen(mname));
|
||||
std::vector<char> name;
|
||||
name.resize(length * 3 + 1, '\0');
|
||||
CFStringGetCString(cfname, &name[0], length * 3 + 1, CFStringGetSystemEncoding());
|
||||
info.name.append(&name[0], strlen(&name[0]));
|
||||
info.name.append(": ");
|
||||
CFRelease(cfname);
|
||||
free(mname);
|
||||
property.mSelector = kAudioObjectPropertyName;
|
||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &cfname);
|
||||
if (result != noErr) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting device name.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
//const char *name = CFStringGetCStringPtr(cfname, CFStringGetSystemEncoding());
|
||||
length = CFStringGetLength(cfname);
|
||||
char *name = (char *)malloc(length * 3 + 1);
|
||||
CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding());
|
||||
info.name.append((const char *)name, strlen(name));
|
||||
name.resize(length * 3 + 1, '\0');
|
||||
CFStringGetCString(cfname, &name[0], length * 3 + 1, CFStringGetSystemEncoding());
|
||||
info.name.append(&name[0], strlen(&name[0]));
|
||||
CFRelease(cfname);
|
||||
free(name);
|
||||
// ------------------------------------------------
|
||||
// Get the output stream "configuration".
|
||||
AudioBufferList *bufferList = nil;
|
||||
// ------------------------------------------------
|
||||
property.mSelector = kAudioDevicePropertyStreamConfiguration;
|
||||
property.mScope = kAudioDevicePropertyScopeOutput;
|
||||
// property.mElement = kAudioObjectPropertyElementWildcard;
|
||||
|
||||
if (info.input == false) {
|
||||
property.mScope = kAudioDevicePropertyScopeOutput;
|
||||
} else {
|
||||
property.mScope = kAudioDevicePropertyScopeInput;
|
||||
}
|
||||
AudioBufferList *bufferList = nullptr;
|
||||
dataSize = 0;
|
||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
||||
if (result != noErr || dataSize == 0) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting output stream configuration info for device (" << _device << ").");
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration info for device (" << _device << ").");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
// Allocate the AudioBufferList.
|
||||
bufferList = (AudioBufferList *) malloc(dataSize);
|
||||
if (bufferList == nullptr) {
|
||||
ATA_ERROR("memory error allocating output AudioBufferList.");
|
||||
ATA_ERROR("memory error allocating AudioBufferList.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, bufferList);
|
||||
if ( result != noErr
|
||||
|| dataSize == 0) {
|
||||
free(bufferList);
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting output stream configuration for device (" << _device << ").");
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting stream configuration for device (" << _device << ").");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
// Get output channel information.
|
||||
uint32_t i, nStreams = bufferList->mNumberBuffers;
|
||||
for (i=0; i<nStreams; i++) {
|
||||
info.outputChannels += bufferList->mBuffers[i].mNumberChannels;
|
||||
// Get channel information.
|
||||
for (size_t iii=0; iii<bufferList->mNumberBuffers; ++iii) {
|
||||
for (size_t jjj=0; jjj<bufferList->mBuffers[iii].mNumberChannels; ++jjj) {
|
||||
info.channels.push_back(audio::channel_unknow);
|
||||
}
|
||||
}
|
||||
free(bufferList);
|
||||
// Get the input stream "configuration".
|
||||
property.mScope = kAudioDevicePropertyScopeInput;
|
||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
||||
if ( result != noErr
|
||||
|| dataSize == 0) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting input stream configuration info for device (" << _device << ").");
|
||||
if (info.channels.size() == 0) {
|
||||
ATA_DEBUG("system error (" << getErrorCode(result) << ") getting stream configuration for device (" << _device << ") ==> no channels.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
// Allocate the AudioBufferList.
|
||||
bufferList = (AudioBufferList *) malloc(dataSize);
|
||||
if (bufferList == nullptr) {
|
||||
ATA_ERROR("memory error allocating input AudioBufferList.");
|
||||
return info;
|
||||
}
|
||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, bufferList);
|
||||
if (result != noErr || dataSize == 0) {
|
||||
free(bufferList);
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting input stream configuration for device (" << _device << ").");
|
||||
return info;
|
||||
}
|
||||
// Get input channel information.
|
||||
nStreams = bufferList->mNumberBuffers;
|
||||
for (i=0; i<nStreams; i++) {
|
||||
info.inputChannels += bufferList->mBuffers[i].mNumberChannels;
|
||||
}
|
||||
free(bufferList);
|
||||
// If device opens for both playback and capture, we determine the channels.
|
||||
if ( info.outputChannels > 0
|
||||
&& info.inputChannels > 0) {
|
||||
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
|
||||
}
|
||||
// Probe the device sample rates.
|
||||
bool isInput = false;
|
||||
if (info.outputChannels == 0) {
|
||||
isInput = true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Determine the supported sample rates.
|
||||
// ------------------------------------------------
|
||||
property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
|
||||
if (isInput == false) property.mScope = kAudioDevicePropertyScopeOutput;
|
||||
result = AudioObjectGetPropertyDataSize(id, &property, 0, nullptr, &dataSize);
|
||||
if ( result != kAudioHardwareNoError
|
||||
|| dataSize == 0) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rate info.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
uint32_t nRanges = dataSize / sizeof(AudioValueRange);
|
||||
@ -338,6 +330,7 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &rangeList);
|
||||
if (result != kAudioHardwareNoError) {
|
||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting sample rates.");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
double minimumRate = 100000000.0, maximumRate = 0.0;
|
||||
@ -358,33 +351,40 @@ audio::orchestra::DeviceInfo audio::orchestra::api::Core::getDeviceInfo(uint32_t
|
||||
}
|
||||
if (info.sampleRates.size() == 0) {
|
||||
ATA_ERROR("No supported sample rates found for device (" << _device << ").");
|
||||
info.clear();
|
||||
return info;
|
||||
}
|
||||
// ------------------------------------------------
|
||||
// Determine the format.
|
||||
// ------------------------------------------------
|
||||
// CoreAudio always uses 32-bit floating point data for PCM streams.
|
||||
// Thus, any other "physical" formats supported by the device are of
|
||||
// no interest to the client.
|
||||
info.nativeFormats.push_back(audio::format_float);
|
||||
if (info.outputChannels > 0) {
|
||||
// ------------------------------------------------
|
||||
// Determine the default channel.
|
||||
// ------------------------------------------------
|
||||
|
||||
if (info.input == false) {
|
||||
if (getDefaultOutputDevice() == _device) {
|
||||
info.isDefaultOutput = true;
|
||||
info.isDefault = true;
|
||||
}
|
||||
}
|
||||
if (info.inputChannels > 0) {
|
||||
} else {
|
||||
if (getDefaultInputDevice() == _device) {
|
||||
info.isDefaultInput = true;
|
||||
info.isDefault = true;
|
||||
}
|
||||
}
|
||||
info.probed = true;
|
||||
info.isCorrect = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
OSStatus audio::orchestra::api::Core::callbackEvent(AudioDeviceID _inDevice,
|
||||
const AudioTimeStamp* _inNow,
|
||||
const AudioBufferList* _inInputData,
|
||||
const AudioTimeStamp* _inInputTime,
|
||||
AudioBufferList* _outOutputData,
|
||||
const AudioTimeStamp* _inOutputTime,
|
||||
void* _userData) {
|
||||
const AudioTimeStamp* _inNow,
|
||||
const AudioBufferList* _inInputData,
|
||||
const AudioTimeStamp* _inInputTime,
|
||||
AudioBufferList* _outOutputData,
|
||||
const AudioTimeStamp* _inOutputTime,
|
||||
void* _userData) {
|
||||
audio::orchestra::api::Core* myClass = reinterpret_cast<audio::orchestra::api::Core*>(_userData);
|
||||
audio::Time inputTime;
|
||||
audio::Time outputTime;
|
||||
@ -453,8 +453,8 @@ bool audio::orchestra::api::Core::probeDeviceOpen(uint32_t _device,
|
||||
ATA_ERROR("device ID is invalid!");
|
||||
return false;
|
||||
}
|
||||
AudioDeviceID deviceList[ nDevices ];
|
||||
uint32_t dataSize = sizeof(AudioDeviceID) * nDevices;
|
||||
AudioDeviceID deviceList[ nDevices/2 ];
|
||||
uint32_t dataSize = sizeof(AudioDeviceID) * nDevices/2;
|
||||
AudioObjectPropertyAddress property = {
|
||||
kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
@ -470,7 +470,7 @@ bool audio::orchestra::api::Core::probeDeviceOpen(uint32_t _device,
|
||||
ATA_ERROR("OS-X system error getting device IDs.");
|
||||
return false;
|
||||
}
|
||||
AudioDeviceID id = deviceList[ _device ];
|
||||
AudioDeviceID id = deviceList[ _device/2 ];
|
||||
// Setup for stream mode.
|
||||
bool isInput = false;
|
||||
if (_mode == audio::orchestra::mode_input) {
|
||||
@ -505,7 +505,7 @@ bool audio::orchestra::api::Core::probeDeviceOpen(uint32_t _device,
|
||||
// channels. CoreAudio devices can have an arbitrary number of
|
||||
// streams and each stream can have an arbitrary number of channels.
|
||||
// For each stream, a single buffer of interleaved samples is
|
||||
// provided. RtAudio prefers the use of one stream of interleaved
|
||||
// provided. orchestra prefers the use of one stream of interleaved
|
||||
// data or multiple consecutive single-channel streams. However, we
|
||||
// now support multiple consecutive multi-channel streams of
|
||||
// interleaved data as well.
|
||||
|
@ -46,23 +46,19 @@ audio::orchestra::api::CoreIos::CoreIos(void) :
|
||||
ATA_ERROR("Get count devices : " << 2);
|
||||
audio::orchestra::DeviceInfo tmp;
|
||||
// Add default output format :
|
||||
tmp.name = "out";
|
||||
tmp.name = "speaker";
|
||||
tmp.sampleRates.push_back(48000);
|
||||
tmp.outputChannels = 2;
|
||||
tmp.inputChannels = 0;
|
||||
tmp.duplexChannels = 0;
|
||||
tmp.isDefaultOutput = true;
|
||||
tmp.isDefaultInput = false;
|
||||
tmp.channels.push_back(audio::channel_frontRight);
|
||||
tmp.channels.push_back(audio::channel_frontLeft);
|
||||
tmp.isDefault = true;
|
||||
tmp.nativeFormats.push_back(audio::format_int16);
|
||||
m_devices.push_back(tmp);
|
||||
// add default input format:
|
||||
tmp.name = "in";
|
||||
tmp.name = "microphone";
|
||||
tmp.sampleRates.push_back(48000);
|
||||
tmp.outputChannels = 0;
|
||||
tmp.inputChannels = 2;
|
||||
tmp.duplexChannels = 0;
|
||||
tmp.isDefaultOutput = false;
|
||||
tmp.isDefaultInput = true;
|
||||
tmp.channels.push_back(audio::channel_frontRight);
|
||||
tmp.channels.push_back(audio::channel_frontLeft);
|
||||
tmp.isDefault = true;
|
||||
tmp.nativeFormats.push_back(audio::format_int16);
|
||||
m_devices.push_back(tmp);
|
||||
ATA_INFO("Create CoreIOs interface (end)");
|
||||
@ -114,7 +110,7 @@ enum audio::orchestra::error audio::orchestra::api::CoreIos::abortStream(void) {
|
||||
|
||||
void audio::orchestra::api::CoreIos::callBackEvent(void* _data,
|
||||
int32_t _nbChunk,
|
||||
const audio::Time& _time) {
|
||||
const audio::Time& _time) {
|
||||
int32_t doStopStream = 0;
|
||||
std::vector<enum audio::orchestra::status> status;
|
||||
if (m_doConvertBuffer[modeToIdTable(audio::orchestra::mode_output)] == true) {
|
||||
|
Loading…
Reference in New Issue
Block a user