I have tried to get audio input (and output at the same time) using the AVAudioSourceNode
and AVAudioSinkNode
. The problem is, I haven't been able to find a proper sample on how to set it up, even on Apple's website. I do basically this:
AVAudioEngine* m_engine = [AVAudioEngine new];
AVAudioSession* m_avSession = AVAudioSession.sharedInstance;
if (![m_avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error] ||
![m_avSession setActive:true withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error])
{
m_logger.Error("Could not activate Audio Session: ", error.description);
}
AVAudioSinkNode* CreateInputNode(AVAudioFormat* format)
{
AVAudioSinkNodeReceiverBlock block = [checker, format] (const AudioTimeStamp* timestamp, AVAudioFrameCount frameCount, const AudioBufferList* inputData) {
ProcessAudioForInput(format, inputData, frameCount);
return OSStatus(noErr);
};
return [[AVAudioSinkNode alloc] initWithReceiverBlock:block];
}
AVAudioSessionRouteDescription* route = m_avSession.currentRoute;
AVAudioFormat* inputFormat = [m_engine.inputNode inputFormatForBus:FIRST_AUDIO_BUS];
auto sinkNode = CreateInputNode(inputFormat);
if (sinkNode) {
[m_engine attachNode:sinkNode];
[m_engine connect:sinkNode to:m_engine.inputNode format:inputFormat];
channelCount = inputFormat.channelCount;
}
else {
m_logger.Error("Could not create input node");
}
The [m_engine connect:sinkNode
line generates an exception, which I have strictly no idea how to debug:
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: inSrcImpl->NumberOutputs() > 0'
Could anyone help or point me to proper resources explaining how to set this up, instead of going blind. Note that I have watched some videos from the WWC, like https://developer.apple.com/videos/play/wwdc2019/510/ but the source code and explanations are not helping me solve this problem.
I think you've got your arrows reversed, it should be
inputNode -> sinkNode
not
sinkNode -> inputNode
,
so try this instead
[m_engine connect: m_engine.inputNode to:sinkNode format:inputFormat];