0

I'm trying to tap the microphone and also get SRC.

@main
struct TapSilenceApp: App {

    let engine = AVAudioEngine()
    let mixer = AVAudioMixerNode()
    let mixer2 = AVAudioMixerNode()

    init() {

        let format = AVAudioFormat(standardFormatWithSampleRate: 16000, channels: 2)!

        let inputNode = engine.inputNode

        // Try using two mixers:
        engine.attach(mixer)
        engine.attach(mixer2)

        engine.connect(inputNode, to: mixer, format: nil)
        engine.connect(mixer, to: mixer2, format: format)

        mixer2.installTap(onBus: 0, bufferSize: 256, format: format) { buffer, _ in
            assert(!buffer.isSilent)
        }

        print("engine: \(engine)")

        engine.prepare()
        try! engine.start()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

That throws an exception with AUGraphParser::InitializeActiveNodesInInputChain(ThisGraph, *GetInputNode()). (AVAudioEngine wins the award for lousiest error messages of any Apple API)

Interestingly, when I remove the call to installTap, it runs.

I still need the tap of course. So trying to connect mixer2 to the output, I do get the tap to run, but the buffers are silent.

Here's the version that's silent:

        let session = AVAudioSession.sharedInstance()

        do {
            try session.setCategory(.playAndRecord, options: .defaultToSpeaker)
        } catch {
            print("Could not set audio category: \(error.localizedDescription)")
        }

        let format = AVAudioFormat(standardFormatWithSampleRate: 16000, channels: 2)!

        let inputNode = engine.inputNode

        // Try using two mixers:
        engine.attach(mixer)
        engine.attach(mixer2)

        engine.connect(inputNode, to: mixer, format: nil)
        engine.connect(mixer, to: mixer2, format: format)
        engine.connect(mixer2, to: engine.mainMixerNode, format: nil)

        mixer2.installTap(onBus: 0, bufferSize: 256, format: mixer2.outputFormat(forBus: 0)) { buffer, _ in
            // assert(!buffer.isSilent)
            print("max value: \(buffer.maxValue)")
        }

        print("engine: \(engine)")

        engine.prepare()
        try! engine.start()

If I just put a tap on the inputNode and remove the mixers, I do get audio input, but of course no SRC.

Taylor
  • 5,871
  • 2
  • 30
  • 64
  • IIRC using connection formats and/or mixers for sample rate conversion doesn't work with `AVAudioEngine`. I think the solution is to let it do its thing with formats and do your own explicity SRC: https://stackoverflow.com/a/40823574/22147 https://stackoverflow.com/a/40823574/22147 – Rhythmic Fistman Nov 11 '22 at 12:33

0 Answers0