Same issue under iOS.
Older API works (calls the callback):
func startMic1() {
let session = AVAudioSession.sharedInstance()
try! session.setCategory(.playAndRecord, mode: .default)
try! session.setPreferredSampleRate(44100)
try! session.setPreferredInputNumberOfChannels(1)
try! session.setPreferredIOBufferDuration(0.1)
try! session.setActive(true)
var desc = AudioComponentDescription(componentType: kAudioUnitType_Output,
componentSubType: kAudioUnitSubType_RemoteIO,
componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
let comp = AudioComponentFindNext(nil, &desc)
var unit: AudioUnit!
var err = AudioComponentInstanceNew(comp!, &unit)
precondition(err == noErr)
var enable: UInt32 = 1
err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enable, 4)
precondition(err == noErr)
var disable: UInt32 = 0
err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &disable, 4)
precondition(err == noErr)
var cb = AURenderCallbackStruct(inputProc: { _, _, _, _, _, _ in
fatalError("callback")
}, inputProcRefCon: nil)
err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, 16)
precondition(err == noErr)
err = AudioUnitInitialize(unit)
precondition(err == noErr)
err = AudioOutputUnitStart(unit)
precondition(err == noErr)
// from now on the (UI) app continues its normal run loop
}
Newer API doesn't work (callback is not called):
func startMic2() {
let session = AVAudioSession.sharedInstance()
try! session.setCategory(.playAndRecord, mode: .default)
try! session.setPreferredSampleRate(44100)
try! session.setPreferredInputNumberOfChannels(1)
try! session.setPreferredIOBufferDuration(0.1)
try! session.setActive(true)
let compDesc = AudioComponentDescription(componentType: kAudioUnitType_Output,
componentSubType: kAudioUnitSubType_RemoteIO,
componentManufacturer: kAudioUnitManufacturer_Apple,
componentFlags: 0, componentFlagsMask: 0)
let unit = try! AUAudioUnit(componentDescription: compDesc, options: [])
unit.isInputEnabled = true
unit.isOutputEnabled = false
precondition(unit.canPerformInput)
unit.inputHandler = { flags, timeStamp, frameCount, bus in
fatalError("never gets here") // now the weird part - this is never called!
}
try! unit.allocateRenderResources()
try! unit.startHardware() // let's go!
print("mic should be working now... why it doesn't?")
// from now on the (UI) app continues its normal run loop
}
Topic:
App & System Services
SubTopic:
Core OS
Tags: