[DEBUG] correct the Mac audio interface
This commit is contained in:
@@ -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) {
|
||||
|
Reference in New Issue
Block a user