Progress on CoreAudio.framework

This commit is contained in:
Lubos Dolezel 2020-03-05 16:28:43 +01:00
parent 31d468bd53
commit 40ebd8d6e1
10 changed files with 490 additions and 39 deletions

97
cmake/FindFFmpeg.cmake Normal file
View File

@ -0,0 +1,97 @@
# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil)
# Once done this will define
#
# FFMPEG_FOUND - system has ffmpeg or libav
# FFMPEG_INCLUDE_DIR - the ffmpeg include directory
# FFMPEG_LIBRARIES - Link these to use ffmpeg
# FFMPEG_LIBAVCODEC
# FFMPEG_LIBAVFORMAT
# FFMPEG_LIBAVUTIL
#
# Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>
# Modified for other libraries by Lasse Kärkkäinen <tronic>
# Modified for Hedgewars by Stepik777
# Modified for FFmpeg-example Tuukka Pasanen 2018
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
#
include(FindPackageHandleStandardArgs)
if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)
# in cache already
set(FFMPEG_FOUND TRUE)
else()
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(_FFMPEG_AVCODEC libavcodec)
pkg_check_modules(_FFMPEG_AVFORMAT libavformat)
pkg_check_modules(_FFMPEG_AVUTIL libavutil)
endif()
find_path(FFMPEG_AVCODEC_INCLUDE_DIR
NAMES libavcodec/avcodec.h
PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS}
/usr/include
/usr/local/include
/opt/local/include
/sw/include
PATH_SUFFIXES ffmpeg libav)
find_library(FFMPEG_LIBAVCODEC
NAMES avcodec
PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib)
find_library(FFMPEG_LIBAVFORMAT
NAMES avformat
PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib)
find_library(FFMPEG_LIBAVUTIL
NAMES avutil
PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib)
if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT)
set(FFMPEG_FOUND TRUE)
endif()
if(FFMPEG_FOUND)
set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR})
set(FFMPEG_LIBRARIES
${FFMPEG_LIBAVCODEC}
${FFMPEG_LIBAVFORMAT}
${FFMPEG_LIBAVUTIL})
endif()
if(FFMPEG_FOUND)
if(NOT FFMPEG_FIND_QUIETLY)
message(STATUS
"Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}")
endif()
else()
message(FATAL_ERROR
"Could not find libavcodec or libavformat or libavutil")
endif()
endif()
find_package_handle_standard_args(FFMPEG
FOUND_VAR FFMPEG_FOUND
REQUIRED_VARS
FFMPEG_LIBRARIES
FFMPEG_INCLUDE_DIR
VERSION_VAR FFMPEG_VERSION
)

View File

@ -0,0 +1,18 @@
include(FindPackageHandleStandardArgs)
find_path(PULSEAUDIO_INCLUDE_DIRS
NAMES pulse/pulseaudio.h
DOC "PulseAudio include directory"
)
find_library(PULSEAUDIO_LIBRARIES
NAMES pulse
DOC "PulseAudio library"
)
find_package_handle_standard_args(PulseAudio
REQUIRED_VARS PULSEAUDIO_LIBRARIES PULSEAUDIO_INCLUDE_DIRS VERSION_VAR PULSEAUDIO_VERSION
FAIL_MESSAGE "Could NOT find PulseAudio!")
mark_as_advanced(PULSEAUDIO_INCLUDE_DIRS PULSEAUDIO_LIBRARIES)

View File

@ -19,7 +19,9 @@ along with Darling. If not, see <http://www.gnu.org/licenses/>.
#include <CoreAudio/AudioHardware.h>
#include "AudioHardwareImpl.h"
#include "AudioHardwareImplPA.h"
#include <CoreServices/MacErrors.h>
#include <dispatch/dispatch.h>
#include <memory>
#include "stub.h"
@ -27,16 +29,11 @@ static std::unique_ptr<AudioHardwareImpl> g_systemObject;
static AudioHardwareImpl* GetSystemObject()
{
if (!g_systemObject)
{
static std::mutex singleLock;
singleLock.lock();
if (!g_systemObject)
g_systemObject.reset(nullptr); // TODO: create ALSA or PA here
singleLock.unlock();
}
static dispatch_once_t once;
dispatch_once(&once, ^{
// TODO: Or ALSA
g_systemObject.reset(new AudioHardwareImplPA);
});
return g_systemObject.get();
}
@ -46,6 +43,8 @@ static AudioHardwareImpl* GetObject(AudioObjectID objID)
if (objID == kAudioObjectSystemObject)
return GetSystemObject();
// TODO: For ALSA, support more objects for every device
return nullptr;
}
@ -136,7 +135,6 @@ OSStatus AudioObjectRemovePropertyListener(AudioObjectID inObjectID,
OSStatus AudioHardwareUnload(void)
{
g_systemObject.reset(nullptr);
return noErr;
}
@ -157,14 +155,61 @@ OSStatus AudioHardwareDestroyAggregateDevice(AudioObjectID inDeviceID)
OSStatus AudioHardwareGetProperty(AudioHardwarePropertyID inPropId, UInt32* ioPropertyDataSize, void* outPropertyData)
{
STUB();
return unimpErr;
if (!ioPropertyDataSize)
return paramErr;
return AudioDeviceGetProperty(kAudioObjectSystemObject, 0, false, inPropId, ioPropertyDataSize, outPropertyData);
}
OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData)
{
AudioObjectPropertyAddress aopa = {
inPropertyID,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
return AudioObjectGetPropertyData(inDevice, &aopa, 0, nullptr, ioPropertyDataSize, outPropertyData);
}
OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable)
{
AudioObjectPropertyAddress aopa = {
inPropertyID,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
OSStatus status;
if (outSize)
{
status = AudioObjectGetPropertyDataSize(inDevice, &aopa, 0, nullptr, outSize);
if (status != noErr)
return status;
}
if (outWritable)
{
status = AudioObjectIsPropertySettable(inDevice, &aopa, outWritable);
}
return status;
}
OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel,
Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData)
{
AudioObjectPropertyAddress aopa = {
inPropertyID,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
return AudioObjectSetPropertyData(inDevice, &aopa, 0, nullptr, inPropertyDataSize, inPropertyData);
}
OSStatus AudioHardwareGetPropertyInfo(AudioHardwarePropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable)
{
STUB();
return unimpErr;
return AudioDeviceGetPropertyInfo(kAudioObjectSystemObject, 0, false, inPropertyID, outSize, outWritable);
}
OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice,
@ -178,6 +223,14 @@ OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice,
return obj->createIOProcID(inProc, inClientData, outIOProcID);
}
OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData)
{
AudioHardwareImpl* obj = GetObject(inDevice);
if (!obj)
return kAudioHardwareBadObjectError;
return obj->createIOProcID(inProc, inClientData, nullptr);
}
OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice,
AudioDeviceIOProcID inIOProcID)
{
@ -188,6 +241,15 @@ OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice,
return obj->destroyIOProcID(inIOProcID);
}
OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc)
{
AudioHardwareImpl* obj = GetObject(inDevice);
if (!obj)
return kAudioHardwareBadObjectError;
return obj->destroyIOProcID(AudioDeviceIOProcID(inProc));
}
OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID)
{
AudioHardwareImpl* obj = GetObject(inDevice);

View File

@ -1,7 +1,7 @@
/*
This file is part of Darling.
Copyright (C) 2015-2016 Lubos Dolezel
Copyright (C) 2015-2020 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@ along with Darling. If not, see <http://www.gnu.org/licenses/>.
#include "AudioHardwareImpl.h"
#include <typeinfo>
#include <iostream>
#include <cstring>
#include <CoreServices/MacErrors.h>
AudioHardwareImpl::AudioHardwareImpl()
@ -41,11 +42,16 @@ OSStatus AudioHardwareImpl::createIOProcID(AudioDeviceIOProc inProc, void* inCli
{
std::lock_guard<std::mutex> guard(m_procMutex);
if (!outIOProcID || !inProc)
if (!inProc)
return paramErr;
*outIOProcID = reinterpret_cast<AudioDeviceIOProcID>(m_nextProcId++);
m_proc[*outIOProcID] = std::make_pair(inProc, inClientData);
AudioDeviceIOProcID procId;
if (outIOProcID)
*outIOProcID = procId = reinterpret_cast<AudioDeviceIOProcID>(m_nextProcId++);
else
procId = inProc;
m_proc[procId] = std::make_pair(inProc, inClientData);
return noErr;
}
@ -71,6 +77,8 @@ OSStatus AudioHardwareImpl::start(AudioDeviceIOProcID inProcID,
return paramErr;
stream = createStream(inProcID);
if (!stream)
return kAudioHardwareBadStreamError;
m_streams.emplace(std::make_pair(inProcID, std::unique_ptr<AudioHardwareStream>(stream)));
// TODO: time
@ -90,13 +98,15 @@ OSStatus AudioHardwareImpl::stop(AudioDeviceIOProcID inProcID)
bool AudioHardwareImpl::hasProperty(const AudioObjectPropertyAddress* address)
{
return false;
UInt32 ds;
OSStatus status = getPropertyDataSize(address, 0, nullptr, &ds);
return status != kAudioHardwareUnknownPropertyError;
}
OSStatus AudioHardwareImpl::getPropertyDataSize(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* outDataSize)
{
return kAudioHardwareUnknownPropertyError;
return getPropertyData(inAddress, inQualifierDataSize, inQualifierData, outDataSize, nullptr);
}
OSStatus AudioHardwareImpl::isPropertySettable(const AudioObjectPropertyAddress* inAddress, Boolean* outIsSettable)
@ -105,15 +115,98 @@ OSStatus AudioHardwareImpl::isPropertySettable(const AudioObjectPropertyAddress*
return kAudioHardwareUnknownPropertyError;
}
// Examples:
// https://gist.github.com/robotconscience/490ee50d8ad75b47ea1f
// https://gist.github.com/hpux735/2913436
OSStatus AudioHardwareImpl::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* ioDataSize, void* outData)
{
switch (inAddress->mSelector)
{
case kAudioDevicePropertyStreamFormat: // returns AudioStreamBasicDescription
{
if (AudioStreamBasicDescription* asbd = static_cast<AudioStreamBasicDescription*>(outData); asbd && *ioDataSize >= sizeof(AudioStreamBasicDescription))
{
// These are standard values macOS applications have learned to expect
asbd->mChannelsPerFrame = 2;
asbd->mSampleRate = 44100;
asbd->mBitsPerChannel = 32;
asbd->mFormatID = kAudioFormatLinearPCM;
asbd->mFormatFlags = kLinearPCMFormatFlagIsFloat;
asbd->mFramesPerPacket = 1;
asbd->mBytesPerFrame = UInt32(asbd->mBytesPerPacket = asbd->mChannelsPerFrame * asbd->mSampleRate * asbd->mBitsPerChannel / 8);
}
*ioDataSize = sizeof(AudioStreamBasicDescription);
return noErr;
}
case kAudioDevicePropertyDeviceManufacturer:
return getPropertyString(m_manufacturer, ioDataSize, outData);
case kAudioDevicePropertyDeviceManufacturerCFString:
return getPropertyCFString(m_manufacturer, ioDataSize, outData);
case kAudioDevicePropertyDeviceUID: // returns CFStringRef
return getPropertyCFString(m_uid, ioDataSize, outData);
case kAudioDevicePropertyDeviceNameCFString:
return getPropertyCFString(m_name, ioDataSize, outData);
case kAudioDevicePropertyDeviceName: // return char[]
return getPropertyString(m_name, ioDataSize, outData);
case kAudioDevicePropertyNominalSampleRate: // Float64
{
if (Float64* flt = static_cast<Float64*>(outData); flt && *ioDataSize >= sizeof(Float64))
*flt = 44100;
*ioDataSize = sizeof(Float64);
return noErr;
}
case kAudioDevicePropertyAvailableNominalSampleRates: // AudioValueRange[]
{
if (AudioValueRange* avr = static_cast<AudioValueRange*>(outData); avr && *ioDataSize >= sizeof(AudioValueRange)*1)
{
avr->mMinimum = 44100;
avr->mMaximum = 44100;
}
*ioDataSize = sizeof(AudioValueRange) * 1;
return noErr;
}
}
return kAudioHardwareUnknownPropertyError;
}
OSStatus AudioHardwareImpl::getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData)
{
if (CFStringRef* ref = static_cast<CFStringRef*>(outData); ref && *ioDataSize >= sizeof(CFStringRef))
{
*ref = str;
}
*ioDataSize = sizeof(CFStringRef);
return noErr;
}
OSStatus AudioHardwareImpl::getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData)
{
const char* cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);
if (char* target = static_cast<char*>(outData))
strlcpy(target, cstr, *ioDataSize);
*ioDataSize = strlen(cstr) + 1;
return noErr;
}
OSStatus AudioHardwareImpl::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32 inDataSize, const void* inData)
{
switch (inAddress->mSelector)
{
case kAudioDevicePropertyBufferSize:
{
return setBufferSize(*static_cast<const uint32_t*>(inData));
}
// These make sense only for ALSA, but I find it ridiculous that these properties can be set...
case kAudioHardwarePropertyDefaultOutputDevice:
return noErr;
case kAudioHardwarePropertyDefaultInputDevice:
return noErr;
}
return kAudioHardwareUnknownPropertyError;
}
@ -128,3 +221,27 @@ OSStatus AudioHardwareImpl::removePropertyListener(const AudioObjectPropertyAddr
{
return kAudioHardwareUnknownPropertyError;
}
OSStatus AudioHardwareImpl::setBufferSize(uint32_t bufferSize)
{
m_bufferSize = bufferSize;
return noErr;
}
OSStatus AudioHardwareImpl::getCurrentTime(AudioTimeStamp* outTime)
{
std::memset(outTime, 0, sizeof(*outTime));
return noErr;
}
OSStatus AudioHardwareImpl::translateTime(const AudioTimeStamp* inTime, AudioTimeStamp* outTime)
{
*outTime = *inTime;
return noErr;
}
OSStatus AudioHardwareImpl::getNearestStartTime(AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags)
{
std::memset(ioRequestedStartTime, 0, sizeof(*ioRequestedStartTime));
return noErr;
}

View File

@ -20,6 +20,7 @@ along with Darling. If not, see <http://www.gnu.org/licenses/>.
#ifndef AUDIOHARDWAREIMPL_H
#define AUDIOHARDWAREIMPL_H
#include <CoreAudio/AudioHardware.h>
#include <CoreFoundation/CFString.h>
#include <map>
#include <mutex>
#include "AudioHardwareStream.h"
@ -57,13 +58,17 @@ public:
AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags);
virtual OSStatus stop(AudioDeviceIOProcID inProcID);
virtual OSStatus getCurrentTime(AudioTimeStamp* outTime) = 0;
virtual OSStatus getCurrentTime(AudioTimeStamp* outTime);
virtual OSStatus translateTime(const AudioTimeStamp* inTime,
AudioTimeStamp* outTime) = 0;
AudioTimeStamp* outTime);
virtual OSStatus getNearestStartTime(AudioTimeStamp* ioRequestedStartTime,
UInt32 inFlags) = 0;
UInt32 inFlags);
virtual OSStatus setBufferSize(uint32_t bufferSize);
private:
static OSStatus getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData);
static OSStatus getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData);
protected:
virtual AudioHardwareStream* createStream(AudioDeviceIOProcID procID) = 0;
protected:
@ -72,6 +77,9 @@ protected:
int m_nextProcId = 1;
std::map<AudioDeviceIOProcID, std::unique_ptr<AudioHardwareStream>> m_streams;
uint32_t m_bufferSize = 8192;
CFStringRef m_name = CFSTR("unknown"), m_uid = CFSTR("unknown"), m_manufacturer = CFSTR("unknown");
};
#endif /* AUDIOHARDWAREIMPL_H */

View File

@ -0,0 +1,98 @@
/*
This file is part of Darling.
Copyright (C) 2020 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Darling is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Darling. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AudioHardwareImplPA.h"
AudioHardwareImplPA::AudioHardwareImplPA()
{
m_name = CFSTR("PulseAudio");
m_manufacturer = CFSTR("PulseAudio");
m_uid = CFSTR("100");
}
OSStatus AudioHardwareImplPA::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* ioDataSize, void* outData)
{
switch (inAddress->mSelector)
{
// BEGIN kAudioObjectSystemObject properties
case kAudioHardwarePropertyDefaultInputDevice: // returns AudioDeviceID
if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID))
{
// We're doing a bit of an abuse here, which works only for PA where we have a single virtual device.
// For ALSA, we could do kAudioObjectSystemObject + INDEX of device.
*devId = kAudioObjectSystemObject;
}
*ioDataSize = sizeof(AudioDeviceID);
break;
case kAudioHardwarePropertyDefaultOutputDevice: // returns AudioDeviceID
if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID))
{
*devId = kAudioObjectSystemObject;
}
*ioDataSize = sizeof(AudioDeviceID);
break;
case kAudioHardwarePropertyDevices:
{
if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID))
{
devId[0] = kAudioObjectSystemObject;
}
*ioDataSize = sizeof(AudioDeviceID) * 1;
break;
}
// END kAudioObjectSystemObject properties
// BEGIN properties of a specific audio device (in case of PA, it is kAudioObjectSystemObject as well)
case kAudioDevicePropertyStreamConfiguration: // returns AudioBufferList
{
const size_t size = sizeof(AudioBufferList) + 1* sizeof(AudioBuffer);
// Number of returned buffers is the number of channels
// check inAddress->mScope. If it equals kAudioDevicePropertyScopeInput, the caller cares about input only.
if (AudioBufferList* abl = static_cast<AudioBufferList*>(outData); abl && *ioDataSize >= size)
{
abl->mNumberBuffers = 1;
abl->mBuffers[0].mNumberChannels = 2;
// TODO: Is the below stuff ever used? How?
abl->mBuffers[0].mData = nullptr;
abl->mBuffers[0].mDataByteSize = 0;
}
*ioDataSize = size;
break;
}
}
return AudioHardwareImpl::getPropertyData(inAddress, inQualifierDataSize, inQualifierData, ioDataSize, outData);
}
OSStatus AudioHardwareImplPA::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32 inDataSize, const void* inData)
{
return AudioHardwareImpl::setPropertyData(inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
}
AudioHardwareStream* AudioHardwareImplPA::createStream(AudioDeviceIOProcID procID)
{
// TODO
return nullptr;
}

View File

@ -0,0 +1,39 @@
/*
This file is part of Darling.
Copyright (C) 2020 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Darling is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Darling. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUDIOHARDWAREIMPLPA_H
#define AUDIOHARDWAREIMPLPA_H
#include "AudioHardwareImpl.h"
class AudioHardwareImplPA : public AudioHardwareImpl
{
public:
AudioHardwareImplPA();
OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* ioDataSize, void* outData) override;
OSStatus setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32 inDataSize, const void* inData) override;
protected:
AudioHardwareStream* createStream(AudioDeviceIOProcID procID) override;
};
#endif

View File

@ -2,9 +2,12 @@ project(CoreAudio)
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(coreaudio_sources
AudioHardware.cpp
AudioHardwareImpl.cpp
AudioHardwareImplPA.cpp
AudioHardwareStream.cpp
)

View File

@ -176,6 +176,7 @@ typedef AudioDeviceIOProc AudioDeviceIOProcID;
OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice,
AudioDeviceIOProc inProc, void* inClientData,
AudioDeviceIOProcID* outIOProcID);
OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData);
#ifdef __BLOCKS__
@ -191,6 +192,7 @@ OSStatus AudioDeviceCreateIOProcIDWithBlock(AudioDeviceIOProcID* outIOProcID,
OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice,
AudioDeviceIOProcID inIOProcID);
OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc);
OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID);
@ -208,6 +210,7 @@ struct AudioHardwareIOProcStreamUsage
OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData);
OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable);
OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData);
OSStatus AudioDeviceGetCurrentTime(AudioObjectID inDevice, AudioTimeStamp* outTime);

View File

@ -7,7 +7,7 @@
typedef Float32 AudioSampleType;
typedef Float32 AudioUnitSampleType;
struct AudioStreamBasicDescription
typedef struct
{
Float64 mSampleRate;
UInt32 mFormatID;
@ -18,43 +18,49 @@ struct AudioStreamBasicDescription
UInt32 mChannelsPerFrame;
UInt32 mBitsPerChannel;
UInt32 mReserved;
};
} AudioStreamBasicDescription;
struct AudioClassDescription
typedef struct
{
OSType mType;
OSType mSubType;
OSType mManufacturer;
};
} AudioClassDescription;
struct AudioBuffer
typedef struct
{
UInt32 mNumberChannels;
UInt32 mDataByteSize;
void* mData;
};
} AudioBuffer;
struct AudioBufferList
typedef struct
{
UInt32 mNumberBuffers;
AudioBuffer mBuffers[1];
};
} AudioBufferList;
struct AudioStreamPacketDescription
typedef struct
{
Float64 mMinimum;
Float64 mMaximum;
} AudioValueRange;
typedef struct
{
SInt64 mStartOffset;
UInt32 mVariableFramesInPacket; // 0 for constant streams
UInt32 mDataByteSize;
};
} AudioStreamPacketDescription;
struct SMPTETime
typedef struct
{
SInt64 mSubframes, mSubframeDivisor;
UInt32 mCounter, mType, mFlags;
SInt16 mHours, mMinutes, mSeconds, mFrames;
};
} SMPTETime;
struct AudioTimeStamp
typedef struct
{
Float64 mSampleTime;
UInt64 mHostTime;
@ -62,7 +68,7 @@ struct AudioTimeStamp
UInt64 mWordClockTime;
SMPTETime mSMPTETime;
UInt32 mFlags, mReserved;
};
} AudioTimeStamp;
enum
{