Why is AVAudioEngine input giving all zero samples?

I am trying to get access to raw audio samples from mic. I've written a simple example application that writes the values to a text file.

Below is my sample application. All the input samples from the buffers connected to the input tap is zero. What am I doing wrong?

I did add the Privacy - Microphone Usage Description key to my application target properties and I am allowing microphone access when the application launches. I do find it strange that I have to provide permission every time even though in Settings > Privacy, my application is listed as one of the applications allowed to access the microphone.

class AudioRecorder {
  private let audioEngine = AVAudioEngine()
  private var fileHandle: FileHandle?
  
  func startRecording() {
    let inputNode = audioEngine.inputNode
    
    let audioFormat: AVAudioFormat
#if os(iOS)
    let hardwareSampleRate = AVAudioSession.sharedInstance().sampleRate
    audioFormat = AVAudioFormat(standardFormatWithSampleRate: hardwareSampleRate, channels: 1)!
#elseif os(macOS)
    audioFormat = inputNode.inputFormat(forBus: 0) // Use input node's current format
#endif
    
    setupTextFile()
    
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: audioFormat) { [weak self] buffer, _ in
      self!.processAudioBuffer(buffer: buffer)
    }
    
    do {
      try audioEngine.start()
      print("Recording started with format: \(audioFormat)")
    } catch {
      print("Failed to start audio engine: \(error.localizedDescription)")
    }
  }
  
  func stopRecording() {
    audioEngine.stop()
    audioEngine.inputNode.removeTap(onBus: 0)
    print("Recording stopped.")
  }
  
  private func setupTextFile() {
    let tempDir = FileManager.default.temporaryDirectory
    let textFileURL = tempDir.appendingPathComponent("audioData.txt")
    
    FileManager.default.createFile(atPath: textFileURL.path, contents: nil, attributes: nil)
    
    fileHandle = try? FileHandle(forWritingTo: textFileURL)
  }
  
  private func processAudioBuffer(buffer: AVAudioPCMBuffer) {
    guard let channelData = buffer.floatChannelData else { return }
    
    let channelSamples = channelData[0]
    let frameLength = Int(buffer.frameLength)
    
    var textData = ""
    var allZero = true
    for i in 0..<frameLength {
      let sample = channelSamples[i]
      if sample != 0 {
        allZero = false
      }
      textData += "\(sample)\n"
    }
    
    if allZero {
      print("Got \(frameLength) worth of audio data on \(buffer.stride) channels. All data is zero.")
    } else {
      print("Got \(frameLength) worth of audio data on \(buffer.stride) channels.")
    }
    
    // Write to file
    if let data = textData.data(using: .utf8) {
      fileHandle!.write(data)
    }
  }
}
Answered by DTS Engineer in 818807022

Hello @oreman,

Your code works for me (the data is non-zero). Maybe this is a project configuration issue? Can you provide a sample project that reproduces?

-- Greg

Accepted Answer

Hello @oreman,

Your code works for me (the data is non-zero). Maybe this is a project configuration issue? Can you provide a sample project that reproduces?

-- Greg

Hi Greg,

Thank you very much. Knowing that the code is not the issue gave me enough to resolve the issue. It is a macOS Sandbox app and Audio Input was not checked.

The app now also stopped asking me for permission every time when it runs.

I still get the following warnings traced when the app runs. It seems to have no effect. Can I safely ignore it?

AddInstanceForFactory: No factory registered for id <CFUUID 0x600002d100e0> F8BB1C28-BAE8-11D6-9C31-00039315CD46
  HALC_ProxyObjectMap.cpp:173    HALC_ProxyObjectMap::_CopyObjectByObjectID: failed to create the local object
     HALC_ShellDevice.cpp:2670   HALC_ShellDevice::RebuildControlList: couldn't find the control object
throwing -10877
throwing -10877
 86275          HALC_ProxyIOContext.cpp:1073  HALC_ProxyIOContext::_StartIO(): Start failed - StartAndWaitForState returned error 35
 86275          HALC_ProxyIOContext.cpp:1073  HALC_ProxyIOContext::_StartIO(): Start failed - StartAndWaitForState returned error 35
 86275          HALC_ProxyIOContext.cpp:1073  HALC_ProxyIOContext::_StartIO(): Start failed - StartAndWaitForState returned error 35
        HALB_IOThread.cpp:326    HALB_IOThread::_Start: there already is a thread
Why is AVAudioEngine input giving all zero samples?
 
 
Q