mirror of https://github.com/AxioDL/boo.git
Add iOS/tvOS support to audiodev
This commit is contained in:
parent
33cfcd8b63
commit
49364a152f
|
@ -184,6 +184,8 @@ elseif(WIN32)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
target_sources(boo PRIVATE
|
target_sources(boo PRIVATE
|
||||||
lib/audiodev/AQS.cpp
|
lib/audiodev/AQS.cpp
|
||||||
|
lib/audiodev/CADebugPrintf.cpp
|
||||||
|
lib/audiodev/CAHostTimeBase.cpp
|
||||||
${AudioMatrix_SRC}
|
${AudioMatrix_SRC}
|
||||||
lib/CFPointer.hpp
|
lib/CFPointer.hpp
|
||||||
)
|
)
|
||||||
|
@ -192,7 +194,11 @@ elseif(APPLE)
|
||||||
PROPERTIES COMPILE_FLAGS -fobjc-arc
|
PROPERTIES COMPILE_FLAGS -fobjc-arc
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(APPKIT_LIBRARY AppKit)
|
if (IOS OR TVOS)
|
||||||
|
set(APPKIT_LIBRARY "")
|
||||||
|
else()
|
||||||
|
find_library(APPKIT_LIBRARY AppKit)
|
||||||
|
endif()
|
||||||
unset(BOO_HAS_METAL CACHE)
|
unset(BOO_HAS_METAL CACHE)
|
||||||
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.11)
|
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.11)
|
||||||
set(BOO_HAS_METAL ON CACHE BOOL "Metal is available in this OS X version" FORCE)
|
set(BOO_HAS_METAL ON CACHE BOOL "Metal is available in this OS X version" FORCE)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "lib/audiodev/AudioVoiceEngine.hpp"
|
#include "lib/audiodev/AudioVoiceEngine.hpp"
|
||||||
|
|
||||||
#include "lib/CFPointer.hpp"
|
#include "lib/CFPointer.hpp"
|
||||||
|
#include "CAHostTimeBase.h"
|
||||||
|
|
||||||
#include <AudioToolbox/AudioToolbox.h>
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
#include <CoreMIDI/CoreMIDI.h>
|
#include <CoreMIDI/CoreMIDI.h>
|
||||||
#include <CoreAudio/HostTime.h>
|
|
||||||
|
|
||||||
#include <logvisor/logvisor.hpp>
|
#include <logvisor/logvisor.hpp>
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
static void DummyCallback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {}
|
static void DummyCallback(AQSAudioVoiceEngine* engine, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {}
|
||||||
|
|
||||||
std::pair<AudioChannelSet, Float64> _getAvailableSetAndRate() {
|
std::pair<AudioChannelSet, Float64> _getAvailableSetAndRate() {
|
||||||
|
#if !TARGET_OS_IOS && !TARGET_OS_TV
|
||||||
AudioObjectPropertyAddress propertyAddress;
|
AudioObjectPropertyAddress propertyAddress;
|
||||||
UInt32 argSize;
|
UInt32 argSize;
|
||||||
int numStreams;
|
int numStreams;
|
||||||
|
@ -78,7 +79,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
CFStringGetCStringPtr(devName, kCFStringEncodingUTF8));
|
CFStringGetCStringPtr(devName, kCFStringEncodingUTF8));
|
||||||
argSize = sizeof(devId);
|
argSize = sizeof(devId);
|
||||||
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize, &devId) == noErr) {
|
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize, &devId) ==
|
||||||
|
noErr) {
|
||||||
argSize = sizeof(CFStringRef);
|
argSize = sizeof(CFStringRef);
|
||||||
AudioObjectPropertyAddress deviceAddress;
|
AudioObjectPropertyAddress deviceAddress;
|
||||||
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
|
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
|
||||||
|
@ -126,11 +128,13 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return {AudioChannelSet::Unknown, 48000.0};
|
return {AudioChannelSet::Stereo, 48000.0};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getCurrentAudioOutput() const override { return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8); }
|
std::string getCurrentAudioOutput() const override {
|
||||||
|
return CFStringGetCStringPtr(m_devName.get(), kCFStringEncodingUTF8);
|
||||||
|
}
|
||||||
|
|
||||||
bool setCurrentAudioOutput(const char* name) override {
|
bool setCurrentAudioOutput(const char* name) override {
|
||||||
m_devName = CFPointer<CFStringRef>::adopt(CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8));
|
m_devName = CFPointer<CFStringRef>::adopt(CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8));
|
||||||
|
@ -143,7 +147,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const override {
|
std::vector<std::pair<std::string, std::string>> enumerateAudioOutputs() const override {
|
||||||
std::vector<std::pair<std::string, std::string>> ret;
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
#if !TARGET_OS_IOS && !TARGET_OS_TV
|
||||||
AudioObjectPropertyAddress propertyAddress;
|
AudioObjectPropertyAddress propertyAddress;
|
||||||
std::vector<AudioObjectID> deviceIDs;
|
std::vector<AudioObjectID> deviceIDs;
|
||||||
UInt32 propertySize;
|
UInt32 propertySize;
|
||||||
|
@ -155,7 +159,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
propertyAddress.mSelector = kAudioHardwarePropertyDevices;
|
propertyAddress.mSelector = kAudioHardwarePropertyDevices;
|
||||||
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
|
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||||
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &propertySize) == noErr) {
|
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &propertySize) ==
|
||||||
|
noErr) {
|
||||||
numDevices = propertySize / sizeof(AudioDeviceID);
|
numDevices = propertySize / sizeof(AudioDeviceID);
|
||||||
ret.reserve(numDevices);
|
ret.reserve(numDevices);
|
||||||
deviceIDs.resize(numDevices);
|
deviceIDs.resize(numDevices);
|
||||||
|
@ -170,15 +175,15 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
numStreams = propertySize / sizeof(AudioStreamID);
|
numStreams = propertySize / sizeof(AudioStreamID);
|
||||||
streamIDs.resize(numStreams);
|
streamIDs.resize(numStreams);
|
||||||
|
|
||||||
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize, &streamIDs[0]) ==
|
if (AudioObjectGetPropertyData(deviceIDs[idx], &propertyAddress, 0, nullptr, &propertySize,
|
||||||
noErr) {
|
&streamIDs[0]) == noErr) {
|
||||||
propertyAddress.mSelector = kAudioStreamPropertyDirection;
|
propertyAddress.mSelector = kAudioStreamPropertyDirection;
|
||||||
bool foundOutput = false;
|
bool foundOutput = false;
|
||||||
for (int stm = 0; stm < numStreams; stm++) {
|
for (int stm = 0; stm < numStreams; stm++) {
|
||||||
UInt32 streamDir;
|
UInt32 streamDir;
|
||||||
propertySize = sizeof(streamDir);
|
propertySize = sizeof(streamDir);
|
||||||
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, nullptr, &propertySize, &streamDir) ==
|
if (AudioObjectGetPropertyData(streamIDs[stm], &propertyAddress, 0, nullptr, &propertySize,
|
||||||
noErr) {
|
&streamDir) == noErr) {
|
||||||
if (streamDir == 0) {
|
if (streamDir == 0) {
|
||||||
foundOutput = true;
|
foundOutput = true;
|
||||||
break;
|
break;
|
||||||
|
@ -206,7 +211,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +220,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> ret;
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
#if !TARGET_OS_TV
|
||||||
ItemCount numDevices = MIDIGetNumberOfDevices();
|
ItemCount numDevices = MIDIGetNumberOfDevices();
|
||||||
ret.reserve(numDevices);
|
ret.reserve(numDevices);
|
||||||
for (int i = int(numDevices) - 1; i >= 0; --i) {
|
for (int i = int(numDevices) - 1; i >= 0; --i) {
|
||||||
|
@ -252,13 +257,14 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
|
|
||||||
ret.push_back(std::make_pair(fmt::format(FMT_STRING("{:08X}"), idNum), std::string(nameCstr)));
|
ret.push_back(std::make_pair(fmt::format(FMT_STRING("{:08X}"), idNum), std::string(nameCstr)));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsVirtualMIDIIn() const override { return true; }
|
bool supportsVirtualMIDIIn() const override { return true; }
|
||||||
|
|
||||||
static MIDIDeviceRef LookupMIDIDevice(const char* name) {
|
static MIDIDeviceRef LookupMIDIDevice(const char* name) {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
ItemCount numDevices = MIDIGetNumberOfDevices();
|
ItemCount numDevices = MIDIGetNumberOfDevices();
|
||||||
for (ItemCount i = 0; i < numDevices; ++i) {
|
for (ItemCount i = 0; i < numDevices; ++i) {
|
||||||
MIDIDeviceRef dev = MIDIGetDevice(i);
|
MIDIDeviceRef dev = MIDIGetDevice(i);
|
||||||
|
@ -274,7 +280,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +288,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIDeviceRef dev = LookupMIDIDevice(name);
|
MIDIDeviceRef dev = LookupMIDIDevice(name);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return {};
|
return {};
|
||||||
|
#if !TARGET_OS_TV
|
||||||
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
|
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
|
||||||
for (ItemCount i = 0; i < numEnt; ++i) {
|
for (ItemCount i = 0; i < numEnt; ++i) {
|
||||||
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
|
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
|
||||||
|
@ -295,7 +301,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +309,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIDeviceRef dev = LookupMIDIDevice(name);
|
MIDIDeviceRef dev = LookupMIDIDevice(name);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return {};
|
return {};
|
||||||
|
#if !TARGET_OS_TV
|
||||||
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
|
ItemCount numEnt = MIDIDeviceGetNumberOfEntities(dev);
|
||||||
for (ItemCount i = 0; i < numEnt; ++i) {
|
for (ItemCount i = 0; i < numEnt; ++i) {
|
||||||
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
|
MIDIEntityRef ent = MIDIDeviceGetEntity(dev, i);
|
||||||
|
@ -316,7 +322,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +330,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
const MIDIPacket* packet = &pktlist->packet[0];
|
const MIDIPacket* packet = &pktlist->packet[0];
|
||||||
for (int i = 0; i < pktlist->numPackets; ++i) {
|
for (int i = 0; i < pktlist->numPackets; ++i) {
|
||||||
std::vector<uint8_t> bytes(std::cbegin(packet->data), std::cbegin(packet->data) + packet->length);
|
std::vector<uint8_t> bytes(std::cbegin(packet->data), std::cbegin(packet->data) + packet->length);
|
||||||
readProcRefCon->m_receiver(std::move(bytes), AudioConvertHostTimeToNanos(packet->timeStamp) / 1.0e9);
|
readProcRefCon->m_receiver(std::move(bytes), CAHostTimeBase::ConvertToNanos(packet->timeStamp) / 1.0e9);
|
||||||
packet = MIDIPacketNext(packet);
|
packet = MIDIPacketNext(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,22 +343,27 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
: IMIDIIn(parent, virt, std::move(receiver)) {}
|
: IMIDIIn(parent, virt, std::move(receiver)) {}
|
||||||
|
|
||||||
~MIDIIn() override {
|
~MIDIIn() override {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (m_midi)
|
if (m_midi)
|
||||||
MIDIEndpointDispose(m_midi);
|
MIDIEndpointDispose(m_midi);
|
||||||
if (m_midiPort)
|
if (m_midiPort)
|
||||||
MIDIPortDispose(m_midiPort);
|
MIDIPortDispose(m_midiPort);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() const override {
|
std::string description() const override {
|
||||||
CFPointer<CFStringRef> namestr;
|
CFPointer<CFStringRef> namestr;
|
||||||
|
#if !TARGET_OS_TV
|
||||||
const char* nameCstr;
|
const char* nameCstr;
|
||||||
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
|
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return nameCstr;
|
return nameCstr;
|
||||||
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -363,31 +374,37 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIOut(AQSAudioVoiceEngine* parent, bool virt) : IMIDIOut(parent, virt) {}
|
MIDIOut(AQSAudioVoiceEngine* parent, bool virt) : IMIDIOut(parent, virt) {}
|
||||||
|
|
||||||
~MIDIOut() override {
|
~MIDIOut() override {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (m_midi)
|
if (m_midi)
|
||||||
MIDIEndpointDispose(m_midi);
|
MIDIEndpointDispose(m_midi);
|
||||||
if (m_midiPort)
|
if (m_midiPort)
|
||||||
MIDIPortDispose(m_midiPort);
|
MIDIPortDispose(m_midiPort);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() const override {
|
std::string description() const override {
|
||||||
CFPointer<CFStringRef> namestr;
|
CFPointer<CFStringRef> namestr;
|
||||||
|
#if !TARGET_OS_TV
|
||||||
const char* nameCstr;
|
const char* nameCstr;
|
||||||
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
|
if (MIDIObjectGetStringProperty(m_midi, kMIDIPropertyName, &namestr))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return nameCstr;
|
return nameCstr;
|
||||||
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t send(const void* buf, size_t len) const override {
|
size_t send(const void* buf, size_t len) const override {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
union {
|
union {
|
||||||
MIDIPacketList head;
|
MIDIPacketList head;
|
||||||
Byte storage[512];
|
Byte storage[512];
|
||||||
} list;
|
} list;
|
||||||
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
|
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
|
||||||
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(), len,
|
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, CAHostTimeBase::GetTheCurrentTime(), len,
|
||||||
reinterpret_cast<const Byte*>(buf))) {
|
reinterpret_cast<const Byte*>(buf))) {
|
||||||
if (m_midiPort)
|
if (m_midiPort)
|
||||||
MIDISend(m_midiPort, m_midi, &list.head);
|
MIDISend(m_midiPort, m_midi, &list.head);
|
||||||
|
@ -395,6 +412,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIReceived(m_midi, &list.head);
|
MIDIReceived(m_midi, &list.head);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -409,6 +427,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
: IMIDIInOut(parent, virt, std::move(receiver)) {}
|
: IMIDIInOut(parent, virt, std::move(receiver)) {}
|
||||||
|
|
||||||
~MIDIInOut() override {
|
~MIDIInOut() override {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (m_midiIn)
|
if (m_midiIn)
|
||||||
MIDIEndpointDispose(m_midiIn);
|
MIDIEndpointDispose(m_midiIn);
|
||||||
if (m_midiPortIn)
|
if (m_midiPortIn)
|
||||||
|
@ -417,27 +436,32 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIEndpointDispose(m_midiOut);
|
MIDIEndpointDispose(m_midiOut);
|
||||||
if (m_midiPortOut)
|
if (m_midiPortOut)
|
||||||
MIDIPortDispose(m_midiPortOut);
|
MIDIPortDispose(m_midiPortOut);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() const override {
|
std::string description() const override {
|
||||||
CFPointer<CFStringRef> namestr;
|
CFPointer<CFStringRef> namestr;
|
||||||
|
#if !TARGET_OS_TV
|
||||||
const char* nameCstr;
|
const char* nameCstr;
|
||||||
if (MIDIObjectGetStringProperty(m_midiIn, kMIDIPropertyName, &namestr))
|
if (MIDIObjectGetStringProperty(m_midiIn, kMIDIPropertyName, &namestr))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
if (!(nameCstr = CFStringGetCStringPtr(namestr.get(), kCFStringEncodingUTF8)))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return nameCstr;
|
return nameCstr;
|
||||||
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t send(const void* buf, size_t len) const override {
|
size_t send(const void* buf, size_t len) const override {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
union {
|
union {
|
||||||
MIDIPacketList head;
|
MIDIPacketList head;
|
||||||
Byte storage[512];
|
Byte storage[512];
|
||||||
} list;
|
} list;
|
||||||
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
|
MIDIPacket* curPacket = MIDIPacketListInit(&list.head);
|
||||||
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, AudioGetCurrentHostTime(), len,
|
if (MIDIPacketListAdd(&list.head, sizeof(list), curPacket, CAHostTimeBase::GetTheCurrentTime(), len,
|
||||||
reinterpret_cast<const Byte*>(buf))) {
|
reinterpret_cast<const Byte*>(buf))) {
|
||||||
if (m_midiPortOut)
|
if (m_midiPortOut)
|
||||||
MIDISend(m_midiPortOut, m_midiOut, &list.head);
|
MIDISend(m_midiPortOut, m_midiOut, &list.head);
|
||||||
|
@ -445,6 +469,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIReceived(m_midiOut, &list.head);
|
MIDIReceived(m_midiOut, &list.head);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -468,11 +493,12 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
m_midiInCounter++;
|
m_midiInCounter++;
|
||||||
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
||||||
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
||||||
|
#if !TARGET_OS_TV
|
||||||
OSStatus stat;
|
OSStatus stat;
|
||||||
if ((stat = MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
|
if ((stat = MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
|
||||||
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIIn&>(*ret).m_midi)))
|
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIIn&>(*ret).m_midi)))
|
||||||
ret.reset();
|
ret.reset();
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,9 +518,10 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
m_midiOutCounter++;
|
m_midiOutCounter++;
|
||||||
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
||||||
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (MIDISourceCreate(m_midiClient, midiName.get(), &static_cast<MIDIOut&>(*ret).m_midi))
|
if (MIDISourceCreate(m_midiClient, midiName.get(), &static_cast<MIDIOut&>(*ret).m_midi))
|
||||||
ret.reset();
|
ret.reset();
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,10 +541,11 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
m_midiInCounter++;
|
m_midiInCounter++;
|
||||||
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
CFPointer<CFStringRef> midiName = CFPointer<CFStringRef>::adopt(
|
||||||
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
|
if (MIDIDestinationCreate(m_midiClient, midiName.get(), MIDIReadProc(MIDIReceiveProc),
|
||||||
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIInOut&>(*ret).m_midiIn))
|
static_cast<IMIDIReceiver*>(ret.get()), &static_cast<MIDIInOut&>(*ret).m_midiIn))
|
||||||
ret.reset();
|
ret.reset();
|
||||||
|
#endif
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -528,9 +556,10 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
m_midiOutCounter++;
|
m_midiOutCounter++;
|
||||||
midiName = CFPointer<CFStringRef>::adopt(
|
midiName = CFPointer<CFStringRef>::adopt(
|
||||||
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
CFStringCreateWithCStringNoCopy(nullptr, name.c_str(), kCFStringEncodingUTF8, kCFAllocatorNull));
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (MIDISourceCreate(m_midiClient, midiName.get(), &static_cast<MIDIInOut&>(*ret).m_midiOut))
|
if (MIDISourceCreate(m_midiClient, midiName.get(), &static_cast<MIDIInOut&>(*ret).m_midiOut))
|
||||||
ret.reset();
|
ret.reset();
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +567,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
if (!m_midiClient)
|
if (!m_midiClient)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
MIDIEndpointRef src = LookupMIDISource(name);
|
MIDIEndpointRef src = LookupMIDISource(name);
|
||||||
if (!src)
|
if (!src)
|
||||||
return {};
|
return {};
|
||||||
|
@ -556,12 +586,16 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
MIDIPortConnectSource(static_cast<MIDIIn&>(*ret).m_midiPort, src, nullptr);
|
MIDIPortConnectSource(static_cast<MIDIIn&>(*ret).m_midiPort, src, nullptr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override {
|
std::unique_ptr<IMIDIOut> newRealMIDIOut(const char* name) override {
|
||||||
if (!m_midiClient)
|
if (!m_midiClient)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
MIDIEndpointRef dst = LookupMIDIDest(name);
|
MIDIEndpointRef dst = LookupMIDIDest(name);
|
||||||
if (!dst)
|
if (!dst)
|
||||||
return {};
|
return {};
|
||||||
|
@ -579,12 +613,16 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
static_cast<MIDIOut&>(*ret).m_midi = dst;
|
static_cast<MIDIOut&>(*ret).m_midi = dst;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override {
|
std::unique_ptr<IMIDIInOut> newRealMIDIInOut(const char* name, ReceiveFunctor&& receiver) override {
|
||||||
if (!m_midiClient)
|
if (!m_midiClient)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
MIDIEndpointRef src = LookupMIDISource(name);
|
MIDIEndpointRef src = LookupMIDISource(name);
|
||||||
if (!src)
|
if (!src)
|
||||||
return {};
|
return {};
|
||||||
|
@ -618,7 +656,10 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
static_cast<MIDIInOut&>(*ret).m_midiOut = dst;
|
static_cast<MIDIInOut&>(*ret).m_midiOut = dst;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
#else
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
bool useMIDILock() const override { return true; }
|
bool useMIDILock() const override { return true; }
|
||||||
|
|
||||||
|
@ -651,15 +692,17 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
if ((err = AudioQueueNewOutput(&desc, AudioQueueOutputCallback(Callback), this, CFRunLoopGetCurrent(),
|
if ((err = AudioQueueNewOutput(&desc, AudioQueueOutputCallback(Callback), this, CFRunLoopGetCurrent(),
|
||||||
m_runLoopMode.get(), 0, &m_queue))) {
|
m_runLoopMode.get(), 0, &m_queue))) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("unable to create output audio queue"));
|
Log.report(logvisor::Fatal, FMT_STRING("unable to create output audio queue: {}"), err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !TARGET_OS_IOS && !TARGET_OS_TV
|
||||||
CFStringRef devName = m_devName.get();
|
CFStringRef devName = m_devName.get();
|
||||||
if ((err = AudioQueueSetProperty(m_queue, kAudioQueueProperty_CurrentDevice, &devName, sizeof(devName)))) {
|
if ((err = AudioQueueSetProperty(m_queue, kAudioQueueProperty_CurrentDevice, &devName, sizeof(devName)))) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("unable to set current device into audio queue"));
|
Log.report(logvisor::Fatal, FMT_STRING("unable to set current device into audio queue"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
AudioQueueAddPropertyListener(m_queue, kAudioQueueDeviceProperty_SampleRate,
|
AudioQueueAddPropertyListener(m_queue, kAudioQueueDeviceProperty_SampleRate,
|
||||||
AudioQueuePropertyListenerProc(SampleRateChanged), this);
|
AudioQueuePropertyListenerProc(SampleRateChanged), this);
|
||||||
|
@ -675,7 +718,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
AudioChannelLayout layout;
|
AudioChannelLayout layout;
|
||||||
UInt32 layoutSz = sizeof(layout);
|
UInt32 layoutSz = sizeof(layout);
|
||||||
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz)) {
|
if (AudioQueueGetProperty(m_queue, kAudioQueueProperty_ChannelLayout, &layout, &layoutSz)) {
|
||||||
Log.report(logvisor::Warning, FMT_STRING("unable to get channel layout from audio queue; using count's default"));
|
Log.report(logvisor::Warning,
|
||||||
|
FMT_STRING("unable to get channel layout from audio queue; using count's default"));
|
||||||
switch (m_mixInfo.m_channels) {
|
switch (m_mixInfo.m_channels) {
|
||||||
case AudioChannelSet::Stereo:
|
case AudioChannelSet::Stereo:
|
||||||
default:
|
default:
|
||||||
|
@ -756,7 +800,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
chMapOut.m_channels[4] = AudioChannel::FrontCenter;
|
chMapOut.m_channels[4] = AudioChannel::FrontCenter;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.report(logvisor::Warning, FMT_STRING("unknown channel layout {}; using stereo"), layout.mChannelLayoutTag);
|
Log.report(logvisor::Warning, FMT_STRING("unknown channel layout {}; using stereo"),
|
||||||
|
layout.mChannelLayoutTag);
|
||||||
chMapOut.m_channelCount = 2;
|
chMapOut.m_channelCount = 2;
|
||||||
chMapOut.m_channels[0] = AudioChannel::FrontLeft;
|
chMapOut.m_channels[0] = AudioChannel::FrontLeft;
|
||||||
chMapOut.m_channels[1] = AudioChannel::FrontRight;
|
chMapOut.m_channels[1] = AudioChannel::FrontRight;
|
||||||
|
@ -793,6 +838,7 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
AudioQueueStart(m_queue, nullptr);
|
AudioQueueStart(m_queue, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !TARGET_OS_IOS && !TARGET_OS_TV
|
||||||
static OSStatus AudioDeviceChanged(AudioObjectID inObjectID, UInt32 inNumberAddresses,
|
static OSStatus AudioDeviceChanged(AudioObjectID inObjectID, UInt32 inNumberAddresses,
|
||||||
const AudioObjectPropertyAddress* inAddresses, AQSAudioVoiceEngine* engine) {
|
const AudioObjectPropertyAddress* inAddresses, AQSAudioVoiceEngine* engine) {
|
||||||
AudioObjectID defaultDeviceId;
|
AudioObjectID defaultDeviceId;
|
||||||
|
@ -806,11 +852,13 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
engine->m_needsRebuild = true;
|
engine->m_needsRebuild = true;
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
AQSAudioVoiceEngine(const char* friendlyName)
|
AQSAudioVoiceEngine(const char* friendlyName)
|
||||||
: m_runLoopMode(CFPointer<CFStringRef>::adopt(
|
: m_runLoopMode(CFPointer<CFStringRef>::adopt(
|
||||||
CFStringCreateWithCStringNoCopy(nullptr, "BooAQSMode", kCFStringEncodingUTF8, kCFAllocatorNull)))
|
CFStringCreateWithCStringNoCopy(nullptr, "BooAQSMode", kCFStringEncodingUTF8, kCFAllocatorNull)))
|
||||||
, m_friendlyName(friendlyName) {
|
, m_friendlyName(friendlyName) {
|
||||||
|
#if !TARGET_OS_IOS && !TARGET_OS_TV && false
|
||||||
AudioObjectPropertyAddress propertyAddress;
|
AudioObjectPropertyAddress propertyAddress;
|
||||||
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
|
||||||
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
|
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
|
||||||
|
@ -818,8 +866,8 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
AudioObjectID defaultDeviceId;
|
AudioObjectID defaultDeviceId;
|
||||||
UInt32 argSize = sizeof(defaultDeviceId);
|
UInt32 argSize = sizeof(defaultDeviceId);
|
||||||
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize, &defaultDeviceId) ==
|
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &argSize,
|
||||||
noErr) {
|
&defaultDeviceId) == noErr) {
|
||||||
argSize = sizeof(CFStringRef);
|
argSize = sizeof(CFStringRef);
|
||||||
AudioObjectPropertyAddress deviceAddress;
|
AudioObjectPropertyAddress deviceAddress;
|
||||||
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
|
deviceAddress.mSelector = kAudioDevicePropertyDeviceUID;
|
||||||
|
@ -832,18 +880,22 @@ struct AQSAudioVoiceEngine : BaseAudioVoiceEngine {
|
||||||
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
|
||||||
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propertyAddress,
|
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propertyAddress,
|
||||||
AudioObjectPropertyListenerProc(AudioDeviceChanged), this);
|
AudioObjectPropertyListenerProc(AudioDeviceChanged), this);
|
||||||
|
#endif
|
||||||
_rebuildAudioQueue();
|
_rebuildAudioQueue();
|
||||||
|
|
||||||
|
#if !TARGET_OS_TV
|
||||||
/* Also create shared MIDI client */
|
/* Also create shared MIDI client */
|
||||||
MIDIClientCreate(CFSTR("Boo MIDI"), nullptr, nullptr, &m_midiClient);
|
MIDIClientCreate(CFSTR("Boo MIDI"), nullptr, nullptr, &m_midiClient);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~AQSAudioVoiceEngine() override {
|
~AQSAudioVoiceEngine() override {
|
||||||
m_cbRunning = false;
|
m_cbRunning = false;
|
||||||
AudioQueueDispose(m_queue, true);
|
AudioQueueDispose(m_queue, true);
|
||||||
|
#if !TARGET_OS_TV
|
||||||
if (m_midiClient)
|
if (m_midiClient)
|
||||||
MIDIClientDispose(m_midiClient);
|
MIDIClientDispose(m_midiClient);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void pumpAndMixVoices() override {
|
void pumpAndMixVoices() override {
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
File: CADebugPrintf.cpp
|
||||||
|
Abstract: CADebugPrintf.h
|
||||||
|
Version: 1.1
|
||||||
|
|
||||||
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||||
|
Inc. ("Apple") in consideration of your agreement to the following
|
||||||
|
terms, and your use, installation, modification or redistribution of
|
||||||
|
this Apple software constitutes acceptance of these terms. If you do
|
||||||
|
not agree with these terms, please do not use, install, modify or
|
||||||
|
redistribute this Apple software.
|
||||||
|
|
||||||
|
In consideration of your agreement to abide by the following terms, and
|
||||||
|
subject to these terms, Apple grants you a personal, non-exclusive
|
||||||
|
license, under Apple's copyrights in this original Apple software (the
|
||||||
|
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||||
|
Software, with or without modifications, in source and/or binary forms;
|
||||||
|
provided that if you redistribute the Apple Software in its entirety and
|
||||||
|
without modifications, you must retain this notice and the following
|
||||||
|
text and disclaimers in all such redistributions of the Apple Software.
|
||||||
|
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||||
|
be used to endorse or promote products derived from the Apple Software
|
||||||
|
without specific prior written permission from Apple. Except as
|
||||||
|
expressly stated in this notice, no other rights or licenses, express or
|
||||||
|
implied, are granted by Apple herein, including but not limited to any
|
||||||
|
patent rights that may be infringed by your derivative works or by other
|
||||||
|
works in which the Apple Software may be incorporated.
|
||||||
|
|
||||||
|
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||||
|
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||||
|
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||||
|
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||||
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||||
|
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||||
|
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||||
|
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
*/
|
||||||
|
//==================================================================================================
|
||||||
|
// Includes
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
// Self Include
|
||||||
|
#include "CADebugPrintf.h"
|
||||||
|
|
||||||
|
#if DEBUG || CoreAudio_Debug
|
||||||
|
|
||||||
|
#if TARGET_OS_WIN32
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
extern "C"
|
||||||
|
int CAWin32DebugPrintf(char* inFormat, ...)
|
||||||
|
{
|
||||||
|
char theMessage[1024];
|
||||||
|
va_list theArguments;
|
||||||
|
va_start(theArguments, inFormat);
|
||||||
|
_vsnprintf(theMessage, 1024, inFormat, theArguments);
|
||||||
|
va_end(theArguments);
|
||||||
|
OutputDebugString(theMessage);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CoreAudio_UseSideFile)
|
||||||
|
#include <unistd.h>
|
||||||
|
FILE* sDebugPrintfSideFile = NULL;
|
||||||
|
extern "C"
|
||||||
|
void OpenDebugPrintfSideFile()
|
||||||
|
{
|
||||||
|
if(sDebugPrintfSideFile == NULL)
|
||||||
|
{
|
||||||
|
char theFileName[1024];
|
||||||
|
snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid());
|
||||||
|
sDebugPrintfSideFile = fopen(theFileName, "a+");
|
||||||
|
DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
File: CADebugPrintf.h
|
||||||
|
Abstract: Part of CoreAudio Utility Classes
|
||||||
|
Version: 1.1
|
||||||
|
|
||||||
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||||
|
Inc. ("Apple") in consideration of your agreement to the following
|
||||||
|
terms, and your use, installation, modification or redistribution of
|
||||||
|
this Apple software constitutes acceptance of these terms. If you do
|
||||||
|
not agree with these terms, please do not use, install, modify or
|
||||||
|
redistribute this Apple software.
|
||||||
|
|
||||||
|
In consideration of your agreement to abide by the following terms, and
|
||||||
|
subject to these terms, Apple grants you a personal, non-exclusive
|
||||||
|
license, under Apple's copyrights in this original Apple software (the
|
||||||
|
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||||
|
Software, with or without modifications, in source and/or binary forms;
|
||||||
|
provided that if you redistribute the Apple Software in its entirety and
|
||||||
|
without modifications, you must retain this notice and the following
|
||||||
|
text and disclaimers in all such redistributions of the Apple Software.
|
||||||
|
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||||
|
be used to endorse or promote products derived from the Apple Software
|
||||||
|
without specific prior written permission from Apple. Except as
|
||||||
|
expressly stated in this notice, no other rights or licenses, express or
|
||||||
|
implied, are granted by Apple herein, including but not limited to any
|
||||||
|
patent rights that may be infringed by your derivative works or by other
|
||||||
|
works in which the Apple Software may be incorporated.
|
||||||
|
|
||||||
|
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||||
|
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||||
|
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||||
|
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||||
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||||
|
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||||
|
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||||
|
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#if !defined(__CADebugPrintf_h__)
|
||||||
|
#define __CADebugPrintf_h__
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Includes
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||||
|
#include <CoreAudio/CoreAudioTypes.h>
|
||||||
|
#else
|
||||||
|
#include "CoreAudioTypes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Macros to redirect debugging output to various logging services
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
//#define CoreAudio_UseSysLog 1
|
||||||
|
//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
|
||||||
|
|
||||||
|
#if DEBUG || CoreAudio_Debug
|
||||||
|
|
||||||
|
#if TARGET_OS_WIN32
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
extern int CAWin32DebugPrintf(char* inFormat, ...);
|
||||||
|
#define DebugPrintfRtn CAWin32DebugPrintf
|
||||||
|
#define DebugPrintfFile
|
||||||
|
#define DebugPrintfLineEnding "\n"
|
||||||
|
#define DebugPrintfFileComma
|
||||||
|
#else
|
||||||
|
#if CoreAudio_UseSysLog
|
||||||
|
#include <sys/syslog.h>
|
||||||
|
#define DebugPrintfRtn syslog
|
||||||
|
#define DebugPrintfFile LOG_NOTICE
|
||||||
|
#define DebugPrintfLineEnding ""
|
||||||
|
#define DebugPrintfFileComma DebugPrintfFile,
|
||||||
|
#elif defined(CoreAudio_UseSideFile)
|
||||||
|
#include <stdio.h>
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
void OpenDebugPrintfSideFile();
|
||||||
|
extern FILE* sDebugPrintfSideFile;
|
||||||
|
#define DebugPrintfRtn fprintf
|
||||||
|
#define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
|
||||||
|
#define DebugPrintfLineEnding "\n"
|
||||||
|
#define DebugPrintfFileComma DebugPrintfFile,
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#define DebugPrintfRtn fprintf
|
||||||
|
#define DebugPrintfFile stderr
|
||||||
|
#define DebugPrintfLineEnding "\n"
|
||||||
|
#define DebugPrintfFileComma DebugPrintfFile,
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DebugPrintfRtn
|
||||||
|
#define DebugPrintfFile
|
||||||
|
#define DebugPrintfLineEnding
|
||||||
|
#define DebugPrintfFileComma
|
||||||
|
#define DebugPrintf(inFormat, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
File: CAHostTimeBase.cpp
|
||||||
|
Abstract: CAHostTimeBase.h
|
||||||
|
Version: 1.1
|
||||||
|
|
||||||
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||||
|
Inc. ("Apple") in consideration of your agreement to the following
|
||||||
|
terms, and your use, installation, modification or redistribution of
|
||||||
|
this Apple software constitutes acceptance of these terms. If you do
|
||||||
|
not agree with these terms, please do not use, install, modify or
|
||||||
|
redistribute this Apple software.
|
||||||
|
|
||||||
|
In consideration of your agreement to abide by the following terms, and
|
||||||
|
subject to these terms, Apple grants you a personal, non-exclusive
|
||||||
|
license, under Apple's copyrights in this original Apple software (the
|
||||||
|
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||||
|
Software, with or without modifications, in source and/or binary forms;
|
||||||
|
provided that if you redistribute the Apple Software in its entirety and
|
||||||
|
without modifications, you must retain this notice and the following
|
||||||
|
text and disclaimers in all such redistributions of the Apple Software.
|
||||||
|
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||||
|
be used to endorse or promote products derived from the Apple Software
|
||||||
|
without specific prior written permission from Apple. Except as
|
||||||
|
expressly stated in this notice, no other rights or licenses, express or
|
||||||
|
implied, are granted by Apple herein, including but not limited to any
|
||||||
|
patent rights that may be infringed by your derivative works or by other
|
||||||
|
works in which the Apple Software may be incorporated.
|
||||||
|
|
||||||
|
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||||
|
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||||
|
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||||
|
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||||
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||||
|
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||||
|
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||||
|
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
*/
|
||||||
|
//=============================================================================
|
||||||
|
// Includes
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#include "CAHostTimeBase.h"
|
||||||
|
|
||||||
|
Float64 CAHostTimeBase::sFrequency = 0;
|
||||||
|
Float64 CAHostTimeBase::sInverseFrequency = 0;
|
||||||
|
UInt32 CAHostTimeBase::sMinDelta = 0;
|
||||||
|
UInt32 CAHostTimeBase::sToNanosNumerator = 0;
|
||||||
|
UInt32 CAHostTimeBase::sToNanosDenominator = 0;
|
||||||
|
pthread_once_t CAHostTimeBase::sIsInited = PTHREAD_ONCE_INIT;
|
||||||
|
#if Track_Host_TimeBase
|
||||||
|
UInt64 CAHostTimeBase::sLastTime = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// CAHostTimeBase
|
||||||
|
//
|
||||||
|
// This class provides platform independent access to the host's time base.
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void CAHostTimeBase::Initialize()
|
||||||
|
{
|
||||||
|
// get the info about Absolute time
|
||||||
|
#if TARGET_OS_MAC
|
||||||
|
struct mach_timebase_info theTimeBaseInfo;
|
||||||
|
mach_timebase_info(&theTimeBaseInfo);
|
||||||
|
sMinDelta = 1;
|
||||||
|
sToNanosNumerator = theTimeBaseInfo.numer;
|
||||||
|
sToNanosDenominator = theTimeBaseInfo.denom;
|
||||||
|
|
||||||
|
// the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
|
||||||
|
sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator);
|
||||||
|
sFrequency *= 1000000000.0;
|
||||||
|
#elif TARGET_OS_WIN32
|
||||||
|
LARGE_INTEGER theFrequency;
|
||||||
|
QueryPerformanceFrequency(&theFrequency);
|
||||||
|
sMinDelta = 1;
|
||||||
|
sToNanosNumerator = 1000000000ULL;
|
||||||
|
sToNanosDenominator = *((UInt64*)&theFrequency);
|
||||||
|
sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency));
|
||||||
|
#endif
|
||||||
|
sInverseFrequency = 1.0 / sFrequency;
|
||||||
|
|
||||||
|
#if Log_Host_Time_Base_Parameters
|
||||||
|
DebugPrintf("Host Time Base Parameters");
|
||||||
|
DebugPrintf(" Minimum Delta: %lu", (unsigned long)sMinDelta);
|
||||||
|
DebugPrintf(" Frequency: %f", sFrequency);
|
||||||
|
DebugPrintf(" To Nanos Numerator: %lu", (unsigned long)sToNanosNumerator);
|
||||||
|
DebugPrintf(" To Nanos Denominator: %lu", (unsigned long)sToNanosDenominator);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
File: CAHostTimeBase.h
|
||||||
|
Abstract: Part of CoreAudio Utility Classes
|
||||||
|
Version: 1.1
|
||||||
|
|
||||||
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||||
|
Inc. ("Apple") in consideration of your agreement to the following
|
||||||
|
terms, and your use, installation, modification or redistribution of
|
||||||
|
this Apple software constitutes acceptance of these terms. If you do
|
||||||
|
not agree with these terms, please do not use, install, modify or
|
||||||
|
redistribute this Apple software.
|
||||||
|
|
||||||
|
In consideration of your agreement to abide by the following terms, and
|
||||||
|
subject to these terms, Apple grants you a personal, non-exclusive
|
||||||
|
license, under Apple's copyrights in this original Apple software (the
|
||||||
|
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||||
|
Software, with or without modifications, in source and/or binary forms;
|
||||||
|
provided that if you redistribute the Apple Software in its entirety and
|
||||||
|
without modifications, you must retain this notice and the following
|
||||||
|
text and disclaimers in all such redistributions of the Apple Software.
|
||||||
|
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||||
|
be used to endorse or promote products derived from the Apple Software
|
||||||
|
without specific prior written permission from Apple. Except as
|
||||||
|
expressly stated in this notice, no other rights or licenses, express or
|
||||||
|
implied, are granted by Apple herein, including but not limited to any
|
||||||
|
patent rights that may be infringed by your derivative works or by other
|
||||||
|
works in which the Apple Software may be incorporated.
|
||||||
|
|
||||||
|
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||||
|
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||||
|
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||||
|
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||||
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||||
|
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||||
|
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||||
|
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#if !defined(__CAHostTimeBase_h__)
|
||||||
|
#define __CAHostTimeBase_h__
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Includes
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||||
|
#include <CoreAudio/CoreAudioTypes.h>
|
||||||
|
#else
|
||||||
|
#include <CoreAudioTypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARGET_OS_MAC
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#elif TARGET_OS_WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include "WinPThreadDefs.h"
|
||||||
|
#else
|
||||||
|
#error Unsupported operating system
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "CADebugPrintf.h"
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// CAHostTimeBase
|
||||||
|
//
|
||||||
|
// This class provides platform independent access to the host's time base.
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#if CoreAudio_Debug
|
||||||
|
// #define Log_Host_Time_Base_Parameters 1
|
||||||
|
// #define Track_Host_TimeBase 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CAHostTimeBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
static UInt64 ConvertToNanos(UInt64 inHostTime);
|
||||||
|
static UInt64 ConvertFromNanos(UInt64 inNanos);
|
||||||
|
|
||||||
|
static UInt64 GetTheCurrentTime();
|
||||||
|
#if TARGET_OS_MAC
|
||||||
|
static UInt64 GetCurrentTime() { return GetTheCurrentTime(); }
|
||||||
|
#endif
|
||||||
|
static UInt64 GetCurrentTimeInNanos();
|
||||||
|
|
||||||
|
static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
|
||||||
|
static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
|
||||||
|
static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
|
||||||
|
|
||||||
|
static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
|
||||||
|
static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
|
||||||
|
|
||||||
|
static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void Initialize();
|
||||||
|
|
||||||
|
static pthread_once_t sIsInited;
|
||||||
|
|
||||||
|
static Float64 sFrequency;
|
||||||
|
static Float64 sInverseFrequency;
|
||||||
|
static UInt32 sMinDelta;
|
||||||
|
static UInt32 sToNanosNumerator;
|
||||||
|
static UInt32 sToNanosDenominator;
|
||||||
|
#if Track_Host_TimeBase
|
||||||
|
static UInt64 sLastTime;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::GetTheCurrentTime()
|
||||||
|
{
|
||||||
|
UInt64 theTime = 0;
|
||||||
|
|
||||||
|
#if TARGET_OS_MAC
|
||||||
|
theTime = mach_absolute_time();
|
||||||
|
#elif TARGET_OS_WIN32
|
||||||
|
LARGE_INTEGER theValue;
|
||||||
|
QueryPerformanceCounter(&theValue);
|
||||||
|
theTime = *((UInt64*)&theValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if Track_Host_TimeBase
|
||||||
|
if(sLastTime != 0)
|
||||||
|
{
|
||||||
|
if(theTime <= sLastTime)
|
||||||
|
{
|
||||||
|
DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
|
||||||
|
}
|
||||||
|
sLastTime = theTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sLastTime = theTime;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return theTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
|
||||||
|
{
|
||||||
|
pthread_once(&sIsInited, Initialize);
|
||||||
|
|
||||||
|
UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
|
||||||
|
#if CoreAudio_Debug
|
||||||
|
if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
|
||||||
|
{
|
||||||
|
DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return theAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
|
||||||
|
{
|
||||||
|
pthread_once(&sIsInited, Initialize);
|
||||||
|
|
||||||
|
UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
|
||||||
|
#if CoreAudio_Debug
|
||||||
|
if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
|
||||||
|
{
|
||||||
|
DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return theAnswer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos()
|
||||||
|
{
|
||||||
|
return ConvertToNanos(GetTheCurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
|
||||||
|
{
|
||||||
|
UInt64 theAnswer;
|
||||||
|
|
||||||
|
if(inStartTime <= inEndTime)
|
||||||
|
{
|
||||||
|
theAnswer = inEndTime - inStartTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theAnswer = inStartTime - inEndTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConvertToNanos(theAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
|
||||||
|
{
|
||||||
|
SInt64 theAnswer;
|
||||||
|
SInt64 theSign = 1;
|
||||||
|
|
||||||
|
if(inStartTime <= inEndTime)
|
||||||
|
{
|
||||||
|
theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
|
||||||
|
theSign = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
|
||||||
|
{
|
||||||
|
#if TARGET_OS_MAC && TARGET_RT_64_BIT
|
||||||
|
__uint128_t theAnswer = inMuliplicand;
|
||||||
|
#else
|
||||||
|
long double theAnswer = inMuliplicand;
|
||||||
|
#endif
|
||||||
|
if(inNumerator != inDenominator)
|
||||||
|
{
|
||||||
|
theAnswer *= inNumerator;
|
||||||
|
theAnswer /= inDenominator;
|
||||||
|
}
|
||||||
|
return static_cast<UInt64>(theAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue