Create a silent audio CMSampleBufferRef

后端 未结 3 683
失恋的感觉
失恋的感觉 2021-01-12 10:20

How do you create a silent audio CMSampleBufferRef in Swift? I am looking to append silent CMSampleBufferRefs to an instance of AVAssetWriter

3条回答
  •  暖寄归人
    2021-01-12 10:47

    Updated for XCode 10.3. Swift 5.0.1. Don't forget the import CoreMedia.

    import Foundation
    import CoreMedia
    
    class CMSampleBufferFactory
    {
        static func createSilentAudio(startFrm: Int64, nFrames: Int, sampleRate: Float64, numChannels: UInt32) -> CMSampleBuffer? {
            let bytesPerFrame = UInt32(2 * numChannels)
            let blockSize = nFrames*Int(bytesPerFrame)
    
            var block: CMBlockBuffer?
            var status = CMBlockBufferCreateWithMemoryBlock(
                allocator: kCFAllocatorDefault,
                memoryBlock: nil,
                blockLength: blockSize,
                blockAllocator: nil,
                customBlockSource: nil,
                offsetToData: 0,
                dataLength: blockSize,
                flags: 0,
                blockBufferOut: &block
            )
            assert(status == kCMBlockBufferNoErr)
    
            guard var eBlock = block else { return nil }
    
            // we seem to get zeros from the above, but I can't find it documented. so... memset:
            status = CMBlockBufferFillDataBytes(with: 0, blockBuffer: eBlock, offsetIntoDestination: 0, dataLength: blockSize)
            assert(status == kCMBlockBufferNoErr)
    
    
            var asbd = AudioStreamBasicDescription(
                mSampleRate: sampleRate,
                mFormatID: kAudioFormatLinearPCM,
                mFormatFlags: kLinearPCMFormatFlagIsSignedInteger,
                mBytesPerPacket: bytesPerFrame,
                mFramesPerPacket: 1,
                mBytesPerFrame: bytesPerFrame,
                mChannelsPerFrame: numChannels,
                mBitsPerChannel: 16,
                mReserved: 0
            )
    
            var formatDesc: CMAudioFormatDescription?
            status = CMAudioFormatDescriptionCreate(allocator: kCFAllocatorDefault, asbd: &asbd, layoutSize: 0, layout: nil, magicCookieSize: 0, magicCookie: nil, extensions: nil, formatDescriptionOut: &formatDesc)
            assert(status == noErr)
    
            var sampleBuffer: CMSampleBuffer?
    
            status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(
                allocator: kCFAllocatorDefault,
                dataBuffer: eBlock,
                formatDescription: formatDesc!,
                sampleCount: nFrames,
                presentationTimeStamp: CMTimeMake(value: startFrm, timescale: Int32(sampleRate)),  
                packetDescriptions: nil,
                sampleBufferOut: &sampleBuffer
            )
            assert(status == noErr)
            return sampleBuffer
        }
    }
    

提交回复
热议问题