19#include "../os/macosx/macos.h"
26#define Point OTTDPoint
27#include <AudioUnit/AudioUnit.h>
31#include "../safeguards.h"
35static AudioUnit _outputAudioUnit;
38static OSStatus audioCallback(
void *, AudioUnitRenderActionFlags *,
const AudioTimeStamp *, UInt32, UInt32, AudioBufferList *ioData)
40 MxMixSamples(ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize / 4);
48 struct AURenderCallbackStruct callback;
49 AudioStreamBasicDescription requestedDesc;
52 requestedDesc.mFormatID = kAudioFormatLinearPCM;
53 requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
54 requestedDesc.mChannelsPerFrame = 2;
57 requestedDesc.mBitsPerChannel = 16;
58 requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
60 if constexpr (std::endian::native == std::endian::big) {
61 requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
64 requestedDesc.mFramesPerPacket = 1;
65 requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8;
66 requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket;
68 MxInitialize((uint)requestedDesc.mSampleRate);
71 AudioComponentDescription desc;
72 desc.componentType = kAudioUnitType_Output;
73 desc.componentSubType = kAudioUnitSubType_HALOutput;
74 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
75 desc.componentFlags = 0;
76 desc.componentFlagsMask = 0;
78 AudioComponent comp = AudioComponentFindNext (
nullptr, &desc);
79 if (comp ==
nullptr) {
80 return "cocoa_s: Failed to start CoreAudio: AudioComponentFindNext returned nullptr";
84 if (AudioComponentInstanceNew(comp, &_outputAudioUnit) != noErr) {
85 return "cocoa_s: Failed to start CoreAudio: AudioComponentInstanceNew";
88 if (AudioUnitInitialize(_outputAudioUnit) != noErr) {
89 return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize";
93 if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc,
sizeof(requestedDesc)) != noErr) {
94 return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)";
98 callback.inputProc = audioCallback;
99 callback.inputProcRefCon =
nullptr;
100 if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback,
sizeof(callback)) != noErr) {
101 return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)";
105 if (AudioOutputUnitStart(_outputAudioUnit) != noErr) {
106 return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart";
116 struct AURenderCallbackStruct callback;
119 if (AudioOutputUnitStop(_outputAudioUnit) != noErr) {
120 Debug(driver, 0,
"cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed");
125 callback.inputProc = 0;
126 callback.inputProcRefCon = 0;
127 if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback,
sizeof(callback)) != noErr) {
128 Debug(driver, 0,
"cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback) failed");
132 if (AudioComponentInstanceDispose(_outputAudioUnit) != noErr) {
133 Debug(driver, 0,
"cocoa_s: Core_CloseAudio: AudioComponentInstanceDispose failed");
void Stop() override
Stop this driver.
std::optional< std::string_view > Start(const StringList ¶m) override
Start this driver.
Base for Cocoa sound handling.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
int GetDriverParamInt(const StringList &parm, const char *name, int def)
Get an integer parameter the list of parameters.
std::vector< std::string > StringList
Type for a list of strings.