【问题标题】:How to create AVAudioPCMBuffer with CMSampleBuffer?如何使用 CMSampleBuffer 创建 AVAudioPCMBuffer?
【发布时间】:2023-03-13 15:53:01
【问题描述】:

我有一个AVAsset,我使用AVAssetReaderAudioMixOutput 得到CMSampleBuffer,我想使用这个CMSampleBuffer 来创建AVAudioPlayerNodescheduleBuffer

怎么做,有大佬帮忙吗?

【问题讨论】:

    标签: ios swift avfoundation audiotoolbox


    【解决方案1】:
    extension AVAudioPCMBuffer {
        static func create(from sampleBuffer: CMSampleBuffer) -> AVAudioPCMBuffer? {
            
            guard let description: CMFormatDescription = CMSampleBufferGetFormatDescription(sampleBuffer),
                  let sampleRate: Float64 = description.audioStreamBasicDescription?.mSampleRate,
                  let channelsPerFrame: UInt32 = description.audioStreamBasicDescription?.mChannelsPerFrame /*,
                                                                                                             let numberOfChannels = description.audioChannelLayout?.numberOfChannels */
            else { return nil }
            
            guard let blockBuffer: CMBlockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else {
                return nil
            }
            
            let samplesCount = CMSampleBufferGetNumSamples(sampleBuffer)
            
            //let length: Int = CMBlockBufferGetDataLength(blockBuffer)
            
            let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: AVAudioChannelCount(1), interleaved: false)
            
            let buffer = AVAudioPCMBuffer(pcmFormat: audioFormat!, frameCapacity: AVAudioFrameCount(samplesCount))!
            buffer.frameLength = buffer.frameCapacity
            
            // GET BYTES
            var dataPointer: UnsafeMutablePointer<Int8>?
            CMBlockBufferGetDataPointer(blockBuffer, atOffset: 0, lengthAtOffsetOut: nil, totalLengthOut: nil, dataPointerOut: &dataPointer)
            
            guard var channel: UnsafeMutablePointer<Float> = buffer.floatChannelData?[0],
                  let data = dataPointer else { return nil }
            
            var data16 = UnsafeRawPointer(data).assumingMemoryBound(to: Int16.self)
            
            for _ in 0...samplesCount - 1 {
                channel.pointee = Float32(data16.pointee) / Float32(Int16.max)
                channel += 1
                for _ in 0...channelsPerFrame - 1 {
                    data16 += 1
                }
                
            }
            
            return buffer
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-08
      • 2019-11-19
      • 1970-01-01
      • 2016-05-29
      • 2012-11-15
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      相关资源
      最近更新 更多