Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a silent audio CMSampleBufferRef

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

like image 202
Ivan Lesko Avatar asked Dec 23 '15 18:12

Ivan Lesko


1 Answers

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?

like image 153
Rhythmic Fistman Avatar answered Oct 14 '22 05:10

Rhythmic Fistman