Create a silent audio CMSampleBufferRef

后端 未结 3 679
失恋的感觉
失恋的感觉 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:52

    You don't say what format you want your zeros (integer/floating point, mono/stereo, sample rate), but maybe it doesn't matter. Anyway, here's one way to create a silent CD audio style CMSampleBuffer in swift.

    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(
            kCFAllocatorDefault,
            nil,
            blockSize,  // blockLength
            nil,        // blockAllocator
            nil,        // customBlockSource
            0,          // offsetToData
            blockSize,  // dataLength
            0,          // flags
            &block
        )
        assert(status == kCMBlockBufferNoErr)
    
        // we seem to get zeros from the above, but I can't find it documented. so... memset:
        status = CMBlockBufferFillDataBytes(0, block!, 0, 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(kCFAllocatorDefault, &asbd, 0, nil, 0, nil, nil, &formatDesc)
        assert(status == noErr)
    
        var sampleBuffer: CMSampleBuffer?
    
        // born ready
        status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(
            kCFAllocatorDefault,
            block,      // dataBuffer
            formatDesc!,
            nFrames,    // numSamples
            CMTimeMake(startFrm, Int32(sampleRate)),    // sbufPTS
            nil,        // packetDescriptions
            &sampleBuffer
        )
        assert(status == noErr)
    
        return sampleBuffer
    }
    

    Doesn't it make you sorry you asked? Do you really need silent CMSampleBuffers? Can't you insert silence into an AVAssetWriterInput by moving the presentation time stamp forward?

提交回复
热议问题