kinaar
kinaar

Reputation: 51

MacOS custom Audio Driver doesn't process our hardware audio stream

We are developing a custom audio driver for a USB microphone in order to do simple processing (EQs) on the input audio stream (comparable to an APO for Windows). Our code is based on the SimpleAudioDriver example from Apple and we finally managed to override the original driver with ours (thanks again). But the I/O buffers are not streamed from/to our hardware device. In the SimpleAudioDevice.cpp file, we tried to debug the "input_buffer" (from the default example) :

auto input_buffer = reinterpret_cast<int16_t*>(ivars->m_input_memory_map->GetAddress() + ivars->m_input_memory_map->GetOffset());

And our guess is that as our device is now assign with our driver, this buffer should be filled with the audio data from our microphone but it's not. And we have the same behaviour with the output_buffer, we filled it with the default sine generator and we don't get any audio outputted on the audio device our driver is assigned to.

The documentation says that the

AudioDriverKit maps the memory of these streams to the Core Audio HAL. In an actual hardware driver, this memory needs to be the same I/O memory the system uses for DMA to hardware.

But then no more details are given. How to access this "I/O memory" and use it to process our hardware input/output stream ?

If you have any hints, please get back to us.

Thanks.

Upvotes: 1

Views: 291

Answers (1)

pmdj
pmdj

Reputation: 23438

I'm wondering if you might have an incorrect mental model for how AudioDriverKit works: it's not 100% clear from your question, but it sounds like you're expecting the framework to already be taking care of the (USB Audio Class compliant?) device I/O for you? If so, you're at the wrong layer. AudioDriverKit is for implementing low-level audio drivers and makes no assumption about what kind of device this is - PCI/Thunderbolt, USB, class-compliant or not, etc. That means you're writing all the device I/O code, issuing individual USB data transfer requests from your code.

If you want to keep using the class compliant driver that ships with the OS but merely want to perform pre-/post-processing on audio samples, there are a bunch of different options, but they're not great:

  1. An AppleUSBAudioPlugin kext. This is theoretically exactly what you're after, but on modern macOS, kexts are not an attractive choice.
  2. An Audio Server Plugin which provides a virtual microphone which gets its samples via a loop back from the real raw microphone. The downside here is that you'd need an app running to record from the real microphone, and both the raw and post-processed mic devices will show up in the system.
  3. Continue down the route you've started on and implement enough of the USB audio class in an AudioDriverKit driver to make your microphone work, then post-processing the samples before handing them over to the sound system. This means doing all the low-level USB stuff that's theoretically already implemented in Apple's own USB audio driver.
  4. Some kind of long shot hail-Mary audio plugin that sits between the USB Audio driver and Core Audio. I'm not sure how possible this is, or if it's any less effort than options 2+3.

Upvotes: 2

Related Questions