Capturing volume levels with AVCaptureAudioDataOutputSampleBufferDelegate in swift

Use AVCaptureAudioDataOutputSampleBufferDelegate's method

captureOutput(captureOutput: AVCaptureOutput!, let didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!)

to get AVCaptureConnection from last parameter.

Then get AVCaptureAudioChannel from connection.audioChannels

Then you can get volume levels from it:

audioChannel.averagePowerLevel
audioChannel.peakHoldLevel

Hey I don't understand much of it but here is a working Swift 5 version:

func captureOutput(_            output      : AVCaptureOutput,
                   didOutput    sampleBuffer: CMSampleBuffer,
                   from         connection  : AVCaptureConnection) {

    var buffer: CMBlockBuffer? = nil

    // Needs to be initialized somehow, even if we take only the address
    let convenianceBuffer = AudioBuffer(mNumberChannels: 1, mDataByteSize: 0, mData: nil)
    var audioBufferList = AudioBufferList(mNumberBuffers: 1,
                                          mBuffers: convenianceBuffer)

    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
        sampleBuffer,
        bufferListSizeNeededOut: nil,
        bufferListOut: &audioBufferList,
        bufferListSize: MemoryLayout<AudioBufferList>.size(ofValue: audioBufferList),
        blockBufferAllocator: nil,
        blockBufferMemoryAllocator: nil,
        flags: UInt32(kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment),
        blockBufferOut: &buffer
    )

    let abl = UnsafeMutableAudioBufferListPointer(&audioBufferList)

    for buffer in abl {
        let originRawPtr = buffer.mData
        let ptrDataSize = Int(buffer.mDataByteSize)

        // From raw pointer to typed Int16 pointer
        let buffPtrInt16 = originRawPtr?.bindMemory(to: Int16.self, capacity: ptrDataSize)

        // From pointer typed Int16 to pointer of [Int16]
        // So we can iterate on it simply
        let unsafePtrByteSize = ptrDataSize/Int16.bitWidth
        let samples = UnsafeMutableBufferPointer<Int16>(start: buffPtrInt16,
                                                        count: unsafePtrByteSize)

        // Average of each sample squared, then root squared
        let sumOfSquaredSamples = samples.map(Float.init).reduce(0) { $0 + $1*$1 }
        let averageOfSomething = sqrt(sumOfSquaredSamples / Float(samples.count))

        DispatchQueue.main.async {
            print("Calulcus of something: \(String(averageOfSomething))" )
        }
    }
}

It appears I have it working. I casted sample to an Int64 before doing any manipulations.

        for buffer in abl{
        let samples = UnsafeMutableBufferPointer<Int16>(start: UnsafeMutablePointer(buffer.mData),
            count: Int(buffer.mDataByteSize)/sizeof(Int16))

        var sum:Int64 = 0

        for sample in samples {
         let s = Int64(sample)
         sum +=s*s
        }


        dispatch_async(dispatch_get_main_queue()) {

            self.volLevel.text = String(sqrt(Float(sum/Int64(samples.count))))
        }