[DEV] correct IOs and MacOs audio interface (tested on MacOs but not on IOs)
This commit is contained in:
parent
4fc9a3e05f
commit
650f24c288
@ -55,6 +55,7 @@ airtaudio::Api::~Api() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum airtaudio::error airtaudio::Api::startStream() {
|
enum airtaudio::error airtaudio::Api::startStream() {
|
||||||
|
ATA_VERBOSE("Start Stream");
|
||||||
m_startTime = std::chrono::system_clock::now();
|
m_startTime = std::chrono::system_clock::now();
|
||||||
m_duration = std::chrono::duration<int64_t, std::micro>(0);
|
m_duration = std::chrono::duration<int64_t, std::micro>(0);
|
||||||
return airtaudio::error_none;
|
return airtaudio::error_none;
|
||||||
@ -156,6 +157,7 @@ uint32_t airtaudio::Api::getDefaultOutputDevice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum airtaudio::error airtaudio::Api::closeStream() {
|
enum airtaudio::error airtaudio::Api::closeStream() {
|
||||||
|
ATA_VERBOSE("Close Stream");
|
||||||
// MUST be implemented in subclasses!
|
// MUST be implemented in subclasses!
|
||||||
return airtaudio::error_none;
|
return airtaudio::error_none;
|
||||||
}
|
}
|
||||||
|
@ -346,9 +346,10 @@ airtaudio::DeviceInfo airtaudio::api::Core::getDeviceInfo(uint32_t _device) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.sampleRates.clear();
|
info.sampleRates.clear();
|
||||||
for (uint32_t k=0; k<MAX_SAMPLE_RATES; k++) {
|
for (auto &it : airtaudio::genericSampleRate()) {
|
||||||
if (SAMPLE_RATES[k] >= (uint32_t) minimumRate && SAMPLE_RATES[k] <= (uint32_t) maximumRate) {
|
if ( it >= minimumRate
|
||||||
info.sampleRates.push_back(SAMPLE_RATES[k]);
|
&& it <= maximumRate) {
|
||||||
|
info.sampleRates.push_back(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.sampleRates.size() == 0) {
|
if (info.sampleRates.size() == 0) {
|
||||||
@ -388,7 +389,7 @@ OSStatus airtaudio::api::Core::callbackEvent(AudioDeviceID _inDevice,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static OSStatus xrunListener(AudioObjectID _inDevice,
|
OSStatus airtaudio::api::Core::xrunListener(AudioObjectID _inDevice,
|
||||||
uint32_t _nAddresses,
|
uint32_t _nAddresses,
|
||||||
const AudioObjectPropertyAddress _properties[],
|
const AudioObjectPropertyAddress _properties[],
|
||||||
void* _userData) {
|
void* _userData) {
|
||||||
@ -406,7 +407,7 @@ static OSStatus xrunListener(AudioObjectID _inDevice,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static OSStatus rateListener(AudioObjectID _inDevice,
|
static OSStatus rateListener(AudioObjectID _inDevice,
|
||||||
uint32_t _nAddresses,
|
UInt32 _nAddresses,
|
||||||
const AudioObjectPropertyAddress _properties[],
|
const AudioObjectPropertyAddress _properties[],
|
||||||
void* _ratePointer) {
|
void* _ratePointer) {
|
||||||
double *rate = (double*)_ratePointer;
|
double *rate = (double*)_ratePointer;
|
||||||
@ -593,26 +594,6 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
}
|
}
|
||||||
m_bufferSize = *_bufferSize;
|
m_bufferSize = *_bufferSize;
|
||||||
m_nBuffers = 1;
|
m_nBuffers = 1;
|
||||||
// Try to set "hog" mode ... it's not clear to me this is working.
|
|
||||||
if ( _options != nullptr
|
|
||||||
&& _options->flags & HOG_DEVICE) {
|
|
||||||
pid_t hog_pid;
|
|
||||||
dataSize = sizeof(hog_pid);
|
|
||||||
property.mSelector = kAudioDevicePropertyHogMode;
|
|
||||||
result = AudioObjectGetPropertyData(id, &property, 0, nullptr, &dataSize, &hog_pid);
|
|
||||||
if (result != noErr) {
|
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") getting 'hog' state!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hog_pid != getpid()) {
|
|
||||||
hog_pid = getpid();
|
|
||||||
result = AudioObjectSetPropertyData(id, &property, 0, nullptr, dataSize, &hog_pid);
|
|
||||||
if (result != noErr) {
|
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") setting 'hog' state!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check and if necessary, change the sample rate for the device.
|
// Check and if necessary, change the sample rate for the device.
|
||||||
double nominalRate;
|
double nominalRate;
|
||||||
dataSize = sizeof(double);
|
dataSize = sizeof(double);
|
||||||
@ -627,7 +608,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
// Set a property listener for the sample rate change
|
// Set a property listener for the sample rate change
|
||||||
double reportedRate = 0.0;
|
double reportedRate = 0.0;
|
||||||
AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
|
AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
|
||||||
result = AudioObjectAddPropertyListener(id, &tmp, rateListener, (void *) &reportedRate);
|
result = AudioObjectAddPropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate property listener for device (" << _device << ").");
|
ATA_ERROR("system error (" << getErrorCode(result) << ") setting sample rate property listener for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@ -648,7 +629,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
usleep(5000);
|
usleep(5000);
|
||||||
}
|
}
|
||||||
// Remove the property listener.
|
// Remove the property listener.
|
||||||
AudioObjectRemovePropertyListener(id, &tmp, rateListener, (void *) &reportedRate);
|
AudioObjectRemovePropertyListener(id, &tmp, &rateListener, (void *) &reportedRate);
|
||||||
if (microCounter > 5000000) {
|
if (microCounter > 5000000) {
|
||||||
ATA_ERROR("timeout waiting for sample rate update for device (" << _device << ").");
|
ATA_ERROR("timeout waiting for sample rate update for device (" << _device << ").");
|
||||||
return false;
|
return false;
|
||||||
@ -763,7 +744,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
// From the CoreAudio documentation, PCM data must be supplied as
|
// From the CoreAudio documentation, PCM data must be supplied as
|
||||||
// 32-bit floats.
|
// 32-bit floats.
|
||||||
m_userFormat = _format;
|
m_userFormat = _format;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = FLOAT32;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_float;
|
||||||
if (streamCount == 1) {
|
if (streamCount == 1) {
|
||||||
m_nDeviceChannels[modeToIdTable(_mode)] = description.mChannelsPerFrame;
|
m_nDeviceChannels[modeToIdTable(_mode)] = description.mChannelsPerFrame;
|
||||||
} else {
|
} else {
|
||||||
@ -799,9 +780,8 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
uint64_t bufferBytes;
|
uint64_t bufferBytes;
|
||||||
bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
||||||
// m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
// m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
||||||
m_userBuffer[modeToIdTable(_mode)] = (char *) malloc(bufferBytes * sizeof(char));
|
m_userBuffer[modeToIdTable(_mode)].resize(bufferBytes, 0);
|
||||||
memset(m_userBuffer[modeToIdTable(_mode)], 0, bufferBytes * sizeof(char));
|
if (m_userBuffer[modeToIdTable(_mode)].size() == 0) {
|
||||||
if (m_userBuffer[modeToIdTable(_mode)] == nullptr) {
|
|
||||||
ATA_ERROR("error allocating user buffer memory.");
|
ATA_ERROR("error allocating user buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -837,7 +817,7 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
m_sampleRate = _sampleRate;
|
m_sampleRate = _sampleRate;
|
||||||
m_device[modeToIdTable(_mode)] = _device;
|
m_device[modeToIdTable(_mode)] = _device;
|
||||||
m_state = airtaudio::state_stopped;
|
m_state = airtaudio::state_stopped;
|
||||||
m_callbackInfo.object = (void *) this;
|
ATA_VERBOSE("Set state as stopped");
|
||||||
// Setup the buffer conversion information structure.
|
// Setup the buffer conversion information structure.
|
||||||
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
if (m_doConvertBuffer[modeToIdTable(_mode)]) {
|
||||||
if (streamCount > 1) {
|
if (streamCount > 1) {
|
||||||
@ -853,10 +833,10 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
m_mode = airtaudio::mode_duplex;
|
m_mode = airtaudio::mode_duplex;
|
||||||
} else {
|
} else {
|
||||||
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
#if defined(MAC_OS_X_VERSION_10_5) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
|
||||||
result = AudioDeviceCreateIOProcID(id, &airtaudio::api::Core::callbackEvent, (void *) &m_callbackInfo, &m_private->procId[modeToIdTable(_mode)]);
|
result = AudioDeviceCreateIOProcID(id, &airtaudio::api::Core::callbackEvent, this, &m_private->procId[modeToIdTable(_mode)]);
|
||||||
#else
|
#else
|
||||||
// deprecated in favor of AudioDeviceCreateIOProcID()
|
// deprecated in favor of AudioDeviceCreateIOProcID()
|
||||||
result = AudioDeviceAddIOProc(id, &airtaudio::api::Core::callbackEvent, (void *) &m_callbackInfo);
|
result = AudioDeviceAddIOProc(id, &airtaudio::api::Core::callbackEvent, this);
|
||||||
#endif
|
#endif
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
ATA_ERROR("system error setting callback for device (" << _device << ").");
|
ATA_ERROR("system error setting callback for device (" << _device << ").");
|
||||||
@ -871,20 +851,17 @@ bool airtaudio::api::Core::probeDeviceOpen(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Setup the device property listener for over/underload.
|
// Setup the device property listener for over/underload.
|
||||||
property.mSelector = kAudioDeviceProcessorOverload;
|
property.mSelector = kAudioDeviceProcessorOverload;
|
||||||
result = AudioObjectAddPropertyListener(id, &property, xrunListener, this);
|
result = AudioObjectAddPropertyListener(id, &property, &airtaudio::api::Core::xrunListener, this);
|
||||||
return true;
|
return true;
|
||||||
error:
|
error:
|
||||||
for (int32_t i=0; i<2; i++) {
|
m_userBuffer[0].clear();
|
||||||
if (m_userBuffer[i]) {
|
m_userBuffer[1].clear();
|
||||||
free(m_userBuffer[i]);
|
|
||||||
m_userBuffer[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = 0;
|
m_deviceBuffer = 0;
|
||||||
}
|
}
|
||||||
m_state = airtaudio::state_closed;
|
m_state = airtaudio::state_closed;
|
||||||
|
ATA_VERBOSE("Set state as closed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,18 +895,15 @@ enum airtaudio::error airtaudio::api::Core::closeStream() {
|
|||||||
AudioDeviceRemoveIOProc(m_private->id[1], &airtaudio::api::Core::callbackEvent);
|
AudioDeviceRemoveIOProc(m_private->id[1], &airtaudio::api::Core::callbackEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
for (int32_t i=0; i<2; i++) {
|
m_userBuffer[0].clear();
|
||||||
if (m_userBuffer[i]) {
|
m_userBuffer[1].clear();
|
||||||
free(m_userBuffer[i]);
|
|
||||||
m_userBuffer[i] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
m_deviceBuffer = nullptr;
|
m_deviceBuffer = nullptr;
|
||||||
}
|
}
|
||||||
m_mode = airtaudio::mode_unknow;
|
m_mode = airtaudio::mode_unknow;
|
||||||
m_state = airtaudio::state_closed;
|
m_state = airtaudio::state_closed;
|
||||||
|
ATA_VERBOSE("Set state as closed");
|
||||||
return airtaudio::error_none;
|
return airtaudio::error_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,6 +938,7 @@ enum airtaudio::error airtaudio::api::Core::startStream() {
|
|||||||
m_private->drainCounter = 0;
|
m_private->drainCounter = 0;
|
||||||
m_private->internalDrain = false;
|
m_private->internalDrain = false;
|
||||||
m_state = airtaudio::state_running;
|
m_state = airtaudio::state_running;
|
||||||
|
ATA_VERBOSE("Set state as running");
|
||||||
unlock:
|
unlock:
|
||||||
if (result == noErr) {
|
if (result == noErr) {
|
||||||
return airtaudio::error_none;
|
return airtaudio::error_none;
|
||||||
@ -1003,6 +978,7 @@ enum airtaudio::error airtaudio::api::Core::stopStream() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_state = airtaudio::state_stopped;
|
m_state = airtaudio::state_stopped;
|
||||||
|
ATA_VERBOSE("Set state as stopped");
|
||||||
unlock:
|
unlock:
|
||||||
if (result == noErr) {
|
if (result == noErr) {
|
||||||
return airtaudio::error_none;
|
return airtaudio::error_none;
|
||||||
@ -1047,6 +1023,7 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
// Check if we were draining the stream and signal is finished.
|
// Check if we were draining the stream and signal is finished.
|
||||||
if (m_private->drainCounter > 3) {
|
if (m_private->drainCounter > 3) {
|
||||||
m_state = airtaudio::state_stopping;
|
m_state = airtaudio::state_stopping;
|
||||||
|
ATA_VERBOSE("Set state as stopping");
|
||||||
if (m_private->internalDrain == true) {
|
if (m_private->internalDrain == true) {
|
||||||
new std::thread(&airtaudio::api::Core::coreStopStream, this);
|
new std::thread(&airtaudio::api::Core::coreStopStream, this);
|
||||||
} else {
|
} else {
|
||||||
@ -1064,21 +1041,22 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
enum airtaudio::status status = airtaudio::status_ok;
|
enum airtaudio::status status = airtaudio::status_ok;
|
||||||
if ( m_mode != airtaudio::mode_input
|
if ( m_mode != airtaudio::mode_input
|
||||||
&& m_private->xrun[0] == true) {
|
&& m_private->xrun[0] == true) {
|
||||||
status |= airtaudio::status_underflow;
|
status = airtaudio::status_underflow;
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
if ( m_mode != airtaudio::mode_output
|
if ( m_mode != airtaudio::mode_output
|
||||||
&& m_private->xrun[1] == true) {
|
&& m_private->xrun[1] == true) {
|
||||||
status |= airtaudio::mode_input_OVERFLOW;
|
status = airtaudio::status_overflow;
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = info->callback(m_userBuffer[0],
|
int32_t cbReturnValue = info->callback(&m_userBuffer[0][0],
|
||||||
m_userBuffer[1],
|
&m_userBuffer[1][0],
|
||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
streamTime,
|
streamTime,
|
||||||
status);
|
status);
|
||||||
if (cbReturnValue == 2) {
|
if (cbReturnValue == 2) {
|
||||||
m_state = airtaudio::state_stopping;
|
m_state = airtaudio::state_stopping;
|
||||||
|
ATA_VERBOSE("Set state as stopping");
|
||||||
m_private->drainCounter = 2;
|
m_private->drainCounter = 2;
|
||||||
abortStream();
|
abortStream();
|
||||||
return true;
|
return true;
|
||||||
@ -1108,19 +1086,19 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
if (m_doConvertBuffer[0]) {
|
if (m_doConvertBuffer[0]) {
|
||||||
// convert directly to CoreAudio stream buffer
|
// convert directly to CoreAudio stream buffer
|
||||||
convertBuffer((char*)_outBufferList->mBuffers[m_private->iStream[0]].mData,
|
convertBuffer((char*)_outBufferList->mBuffers[m_private->iStream[0]].mData,
|
||||||
m_userBuffer[0],
|
&m_userBuffer[0][0],
|
||||||
m_convertInfo[0]);
|
m_convertInfo[0]);
|
||||||
} else {
|
} else {
|
||||||
// copy from user buffer
|
// copy from user buffer
|
||||||
memcpy(_outBufferList->mBuffers[m_private->iStream[0]].mData,
|
memcpy(_outBufferList->mBuffers[m_private->iStream[0]].mData,
|
||||||
m_userBuffer[0],
|
&m_userBuffer[0][0],
|
||||||
_outBufferList->mBuffers[m_private->iStream[0]].mDataByteSize);
|
_outBufferList->mBuffers[m_private->iStream[0]].mDataByteSize);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// fill multiple streams
|
// fill multiple streams
|
||||||
float *inBuffer = (float *) m_userBuffer[0];
|
float *inBuffer = (float *) &m_userBuffer[0][0];
|
||||||
if (m_doConvertBuffer[0]) {
|
if (m_doConvertBuffer[0]) {
|
||||||
convertBuffer(m_deviceBuffer, m_userBuffer[0], m_convertInfo[0]);
|
convertBuffer(m_deviceBuffer, &m_userBuffer[0][0], m_convertInfo[0]);
|
||||||
inBuffer = (float *) m_deviceBuffer;
|
inBuffer = (float *) m_deviceBuffer;
|
||||||
}
|
}
|
||||||
if (m_deviceInterleaved[0] == false) { // mono mode
|
if (m_deviceInterleaved[0] == false) { // mono mode
|
||||||
@ -1194,16 +1172,16 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
if (m_private->nStreams[1] == 1) {
|
if (m_private->nStreams[1] == 1) {
|
||||||
if (m_doConvertBuffer[1]) {
|
if (m_doConvertBuffer[1]) {
|
||||||
// convert directly from CoreAudio stream buffer
|
// convert directly from CoreAudio stream buffer
|
||||||
convertBuffer(m_userBuffer[1],
|
convertBuffer(&m_userBuffer[1][0],
|
||||||
(char *) _inBufferList->mBuffers[m_private->iStream[1]].mData,
|
(char *) _inBufferList->mBuffers[m_private->iStream[1]].mData,
|
||||||
m_convertInfo[1]);
|
m_convertInfo[1]);
|
||||||
} else { // copy to user buffer
|
} else { // copy to user buffer
|
||||||
memcpy(m_userBuffer[1],
|
memcpy(&m_userBuffer[1][0],
|
||||||
_inBufferList->mBuffers[m_private->iStream[1]].mData,
|
_inBufferList->mBuffers[m_private->iStream[1]].mData,
|
||||||
_inBufferList->mBuffers[m_private->iStream[1]].mDataByteSize);
|
_inBufferList->mBuffers[m_private->iStream[1]].mDataByteSize);
|
||||||
}
|
}
|
||||||
} else { // read from multiple streams
|
} else { // read from multiple streams
|
||||||
float *outBuffer = (float *) m_userBuffer[1];
|
float *outBuffer = (float *) &m_userBuffer[1][0];
|
||||||
if (m_doConvertBuffer[1]) {
|
if (m_doConvertBuffer[1]) {
|
||||||
outBuffer = (float *) m_deviceBuffer;
|
outBuffer = (float *) m_deviceBuffer;
|
||||||
}
|
}
|
||||||
@ -1266,7 +1244,7 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_doConvertBuffer[1]) { // convert from our internal "device" buffer
|
if (m_doConvertBuffer[1]) { // convert from our internal "device" buffer
|
||||||
convertBuffer(m_userBuffer[1],
|
convertBuffer(&m_userBuffer[1][0],
|
||||||
m_deviceBuffer,
|
m_deviceBuffer,
|
||||||
m_convertInfo[1]);
|
m_convertInfo[1]);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ namespace airtaudio {
|
|||||||
AudioBufferList* _outOutputData,
|
AudioBufferList* _outOutputData,
|
||||||
const AudioTimeStamp* _inOutputTime,
|
const AudioTimeStamp* _inOutputTime,
|
||||||
void* _infoPointer);
|
void* _infoPointer);
|
||||||
void coreStopStream(void *_userData);
|
static void coreStopStream(void *_userData);
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CorePrivate> m_private;
|
std::unique_ptr<CorePrivate> m_private;
|
||||||
bool probeDeviceOpen(uint32_t _device,
|
bool probeDeviceOpen(uint32_t _device,
|
||||||
@ -57,6 +57,11 @@ namespace airtaudio {
|
|||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
airtaudio::StreamOptions *_options);
|
airtaudio::StreamOptions *_options);
|
||||||
static const char* getErrorCode(OSStatus _code);
|
static const char* getErrorCode(OSStatus _code);
|
||||||
|
|
||||||
|
static OSStatus xrunListener(AudioObjectID _inDevice,
|
||||||
|
uint32_t _nAddresses,
|
||||||
|
const AudioObjectPropertyAddress _properties[],
|
||||||
|
void* _userData);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -45,14 +45,8 @@ namespace airtaudio {
|
|||||||
public:
|
public:
|
||||||
void callBackEvent(void* _data,
|
void callBackEvent(void* _data,
|
||||||
int32_t _frameRate);
|
int32_t _frameRate);
|
||||||
private:
|
public:
|
||||||
std::unique_ptr<CoreIosPrivate> m_private;
|
std::unique_ptr<CoreIosPrivate> m_private;
|
||||||
static OSStatus playbackCallback(void *_userData,
|
|
||||||
AudioUnitRenderActionFlags* _ioActionFlags,
|
|
||||||
const AudioTimeStamp* _inTimeStamp,
|
|
||||||
uint32_t _inBusNumber,
|
|
||||||
uint32_t _inNumberFrames,
|
|
||||||
AudioBufferList* _ioData);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -69,8 +69,6 @@ airtaudio::api::CoreIos::CoreIos(void) :
|
|||||||
airtaudio::api::CoreIos::~CoreIos(void) {
|
airtaudio::api::CoreIos::~CoreIos(void) {
|
||||||
ATA_INFO("Destroy CoreIOs interface");
|
ATA_INFO("Destroy CoreIOs interface");
|
||||||
AudioUnitUninitialize(m_private->audioUnit);
|
AudioUnitUninitialize(m_private->audioUnit);
|
||||||
delete m_private;
|
|
||||||
m_private = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t airtaudio::api::CoreIos::getDeviceCount(void) {
|
uint32_t airtaudio::api::CoreIos::getDeviceCount(void) {
|
||||||
@ -131,13 +129,13 @@ void airtaudio::api::CoreIos::callBackEvent(void* _data,
|
|||||||
int32_t doStopStream = 0;
|
int32_t doStopStream = 0;
|
||||||
std::chrono::system_clock::time_point streamTime = getStreamTime();
|
std::chrono::system_clock::time_point streamTime = getStreamTime();
|
||||||
enum airtaudio::status status = airtaudio::status_ok;
|
enum airtaudio::status status = airtaudio::status_ok;
|
||||||
if (m_doConvertBuffer[airtaudio::mode_output] == true) {
|
if (m_doConvertBuffer[modeToIdTable(airtaudio::mode_output)] == true) {
|
||||||
doStopStream = m_callbackInfo.callback(m_userBuffer[airtaudio::mode_output],
|
doStopStream = m_callbackInfo.callback(&m_userBuffer[modeToIdTable(airtaudio::mode_output)][0],
|
||||||
nullptr,
|
nullptr,
|
||||||
_frameRate,
|
_frameRate,
|
||||||
streamTime,
|
streamTime,
|
||||||
status);
|
status);
|
||||||
convertBuffer((char*)_data, (char*)m_userBuffer[airtaudio::mode_output], m_convertInfo[airtaudio::mode_output]);
|
convertBuffer((char*)_data, &m_userBuffer[modeToIdTable(airtaudio::mode_output)][0], m_convertInfo[modeToIdTable(airtaudio::mode_output)]);
|
||||||
} else {
|
} else {
|
||||||
doStopStream = m_callbackInfo.callback(_data,
|
doStopStream = m_callbackInfo.callback(_data,
|
||||||
nullptr,
|
nullptr,
|
||||||
@ -152,7 +150,8 @@ void airtaudio::api::CoreIos::callBackEvent(void* _data,
|
|||||||
airtaudio::Api::tickStreamTime();
|
airtaudio::Api::tickStreamTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
OSStatus airtaudio::api::CoreIos::playbackCallback(void *_userData,
|
|
||||||
|
static OSStatus playbackCallback(void *_userData,
|
||||||
AudioUnitRenderActionFlags* _ioActionFlags,
|
AudioUnitRenderActionFlags* _ioActionFlags,
|
||||||
const AudioTimeStamp* _inTimeStamp,
|
const AudioTimeStamp* _inTimeStamp,
|
||||||
uint32_t _inBusNumber,
|
uint32_t _inBusNumber,
|
||||||
@ -197,7 +196,7 @@ bool airtaudio::api::CoreIos::probeDeviceOpen(uint32_t _device,
|
|||||||
m_doByteSwap[modeToIdTable(_mode)] = false; // for endienness ...
|
m_doByteSwap[modeToIdTable(_mode)] = false; // for endienness ...
|
||||||
|
|
||||||
// TODO : For now, we write it in hard ==> to be update later ...
|
// TODO : For now, we write it in hard ==> to be update later ...
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = SINT16;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
|
||||||
m_nDeviceChannels[modeToIdTable(_mode)] = 2;
|
m_nDeviceChannels[modeToIdTable(_mode)] = 2;
|
||||||
m_deviceInterleaved[modeToIdTable(_mode)] = true;
|
m_deviceInterleaved[modeToIdTable(_mode)] = true;
|
||||||
|
|
||||||
@ -215,8 +214,8 @@ bool airtaudio::api::CoreIos::probeDeviceOpen(uint32_t _device,
|
|||||||
if (m_doConvertBuffer[modeToIdTable(_mode)] == true) {
|
if (m_doConvertBuffer[modeToIdTable(_mode)] == true) {
|
||||||
// Allocate necessary internal buffers.
|
// Allocate necessary internal buffers.
|
||||||
uint64_t bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * m_bufferSize * audio::getFormatBytes(m_userFormat);
|
uint64_t bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * m_bufferSize * audio::getFormatBytes(m_userFormat);
|
||||||
m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
m_userBuffer[modeToIdTable(_mode)].resize(bufferBytes, 0);
|
||||||
if (m_userBuffer[modeToIdTable(_mode)] == nullptr) {
|
if (m_userBuffer[modeToIdTable(_mode)].size() == 0) {
|
||||||
ATA_ERROR("error allocating user buffer memory.");
|
ATA_ERROR("error allocating user buffer memory.");
|
||||||
}
|
}
|
||||||
setConvertInfo(_mode, _firstChannel);
|
setConvertInfo(_mode, _firstChannel);
|
||||||
@ -285,7 +284,7 @@ bool airtaudio::api::CoreIos::probeDeviceOpen(uint32_t _device,
|
|||||||
|
|
||||||
// Set output callback
|
// Set output callback
|
||||||
AURenderCallbackStruct callbackStruct;
|
AURenderCallbackStruct callbackStruct;
|
||||||
callbackStruct.inputProc = &airtaudio::api::CoreIos::playbackCallback;
|
callbackStruct.inputProc = &playbackCallback;
|
||||||
callbackStruct.inputProcRefCon = this;
|
callbackStruct.inputProcRefCon = this;
|
||||||
status = AudioUnitSetProperty(m_private->audioUnit,
|
status = AudioUnitSetProperty(m_private->audioUnit,
|
||||||
kAudioUnitProperty_SetRenderCallback,
|
kAudioUnitProperty_SetRenderCallback,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user