Saturday, March 2, 2024
HomeiOS Developmentios - AudioUnitRender produces empty audio buffers

ios – AudioUnitRender produces empty audio buffers


I am making an attempt to combine audio from a few audio sources utilizing Audio Models. The construction is kind of easy, I’ve two inputs, a mixer audio unit and a generic output. The issue is that the buffers from the output AudioUnit are solely crammed with zeros.

  • Inputs are offered via AURenderCallbackStruct on to the mixer.
  • Mixer subtype is kAudioUnitSubType_MultiChannelMixer.
  • Output subtype is kAudioUnitSubType_GenericOutput to drag the blended audio manually with out enjoying it. Output is related via AudioUnitConnection to keep away from deprecated AUGraph. AVAudioSession can’t be used both for ReplayKit compatibility.

I eliminated all OSStatus checks to offer shorter model of the code; nevertheless, all Audio Unit strategies return noErr. The setup technique is:

personal func setupAudioUnits() {
    // Organising mixer unit
    var mixerComponentDescription = AudioComponentDescription(
        componentType: kAudioUnitType_Mixer,
        componentSubType: kAudioUnitSubType_MultiChannelMixer,
        componentManufacturer: kAudioUnitManufacturer_Apple,
        componentFlags: 0,
        componentFlagsMask: 0)
    let mixerComponent = AudioComponentFindNext(nil, &mixerComponentDescription)
    AudioComponentInstanceNew(mixerComponent!, &mixerAudioUnit)
    guard let mixerAudioUnit else { fatalError() }

    var streamFormat = outputFormat.streamDescription.pointee
    AudioUnitSetProperty(mixerAudioUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Output,
                         0,
                         &streamFormat,
                         UInt32(MemoryLayout<AudioStreamBasicDescription>.dimension))                                
                            
    AudioUnitInitialize(mixerAudioUnit)

    var busCount = UInt32(inputs)
    AudioUnitSetProperty(mixerAudioUnit,
                         kAudioUnitProperty_ElementCount,
                         kAudioUnitScope_Input,
                         0,
                         &busCount,
                         UInt32(MemoryLayout<UInt32>.dimension))

    // Organising mixer's inputs
    for enter in 0..<inputs {
        var callbackStruct = AURenderCallbackStruct(inputProc: inputRenderCallback, 
                                                    inputProcRefCon: Unmanaged.passUnretained(self).toOpaque())
        AudioUnitSetProperty(mixerAudioUnit,
                             kAudioUnitProperty_SetRenderCallback,
                             kAudioUnitScope_Input,
                             UInt32(enter),
                             &callbackStruct,
                             UInt32(MemoryLayout<AURenderCallbackStruct>.dimension))
    }

    // Organising output unit
    var outputDescription = AudioComponentDescription(
          componentType: kAudioUnitType_Output,
          componentSubType: kAudioUnitSubType_GenericOutput,
          componentManufacturer: kAudioUnitManufacturer_Apple,
          componentFlags: 0,
          componentFlagsMask: 0)
    let outputComponent = AudioComponentFindNext(nil, &outputDescription)
    AudioComponentInstanceNew(outputComponent!, &outputAudioUnit)
    guard let outputAudioUnit else { fatalError() }

    AudioUnitSetProperty(outputAudioUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input,
                         0,
                         &streamFormat,
                         UInt32(MemoryLayout<AudioStreamBasicDescription>.dimension))

    AudioUnitInitialize(outputAudioUnit)

    // Organising a connection between the mixer and output items
    var connection = AudioUnitConnection(sourceAudioUnit: mixerAudioUnit,
                                         sourceOutputNumber: 0,
                                         destInputNumber: 0)

    AudioUnitSetProperty(outputAudioUnit,
                         kAudioUnitProperty_MakeConnection,
                         kAudioUnitScope_Input,
                         0,
                         &connection,
                         UInt32(MemoryLayout<AudioUnitConnection>.dimension))

    AudioOutputUnitStart(outputAudioUnit)
}

Right here is the half that initiates the rendering. I am offering nil for mData to make use of the inner buffer of the audio unit.

personal func render(numberOfFrames: AVAudioFrameCount) {
    timeStamp.mFlags = .sampleTimeValid
    timeStamp.mSampleTime = Float64(sampleTime)

    let channelCount = outputFormat.channelCount
    let audioBufferList = AudioBufferList.allocate(maximumBuffers: Int(channelCount))
    for i in 0..<Int(channelCount) {
        audioBufferList[i] = AudioBuffer(mNumberChannels: 1,
                                          mDataByteSize: outputFormat.streamDescription.pointee.mBytesPerFrame,
                                          mData: nil)
    }

    // at all times returns noErr
    AudioUnitRender(outputAudioUnit,
                    nil,
                    &timeStamp,
                    0,
                    numberOfFrames,
                    audioBufferList.unsafeMutablePointer)

    for channel in 0..<Int(channelCount) {
        let outputBufferData = audioBufferList[channel].mData?.assumingMemoryBound(to: Float.self)
        // Inspecting the info
        // Audio buffer has solely zeros
    }

    sampleTime += Int64(numberOfFrames)
}

AudioUnitRender at all times returns noErr and the buffers have right dimension that’s primarily based on the offered AVAudioFormat. Enter callback is being known as and ioData is crammed with information:

inputRenderCallback

Nevertheless, the output buffer is at all times crammed with zeros:

outputBufferData

Is there one thing improper with my output audio unit setup or with the connection? Or possibly the mixer is just not passing the info ahead? Any assistance is appreciated.



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments