首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建一个无声的音频CMSampleBufferRef

创建一个无声的音频CMSampleBufferRef
EN

Stack Overflow用户
提问于 2015-12-23 18:28:30
回答 3查看 4.3K关注 0票数 8

如何在Swift中创建无声音频CMSampleBufferRef?我希望将无声的CMSampleBufferRefs附加到AVAssetWriterInput的实例中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-25 12:52:34

你不会说你想要什么格式的零(整数/浮点数,单/立体声,采样率),但也许这并不重要。无论如何,这里有一种方法来创建一个无声的CD音频风格的CMSampleBuffer在迅速。

代码语言:javascript
运行
复制
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
}

你不觉得很抱歉你问了吗?你真的需要安静的CMSampleBuffer吗?您不能通过向前移动演示文稿时间戳将静默插入到AVAssetWriterInput中吗?

票数 15
EN

Stack Overflow用户

发布于 2019-08-07 08:48:44

更新为XCode 10.3。迅速5.0.1。别忘了import CoreMedia

代码语言:javascript
运行
复制
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
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-12-23 21:34:18

您需要使用CMBlockBufferCreateWithMemoryBlock()创建块缓冲区。用一堆零填充块缓冲区,然后将其传递到CMAudioSampleBufferCreateWithPacketDescriptions()

免责声明:我还没有在Swift中真正做到这一点,我尝试过了,但是我发现自己每次都在与编译器斗争,所以我转而使用obj-c。是一个低级别的C框架,使用起来非常容易,而不需要使用Swifts类型的系统。我知道这不是你想买的答案,希望它能给你指明正确的方向。

示例

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34441648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档