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

- 41,701
- 23
- 172
- 300

- 1,274
- 13
- 26
-
also remember that just starting to play a null sound may sort of pop when you start, so you might need to do a few samples of mixing, or muting whatever is playing before that sound... and also middle will only be 0 if you have a float rep, or a signed int rep, an unsigned int rep, should be filled with max/2 (ish) – Grady Player Dec 23 '15 at 21:43
3 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 CMSampleBuffer
s? Can't you insert silence into an AVAssetWriterInput
by moving the presentation time stamp forward?

- 34,352
- 5
- 87
- 159
-
Thanks this is very informative :-) Unfortunately I do need AVAssetWriter to export a silent movie. I'm exporting time-lapses that can't contain audio. If I was just exporting to the camera roll it wouldn't be a problem but I'm inserting the video into an AVMutableCoposition. AVMutableCompositionTrack seems to be bugged in iOS 9, it doesn't like inserting AVAssets without audio tracks. This question touches on the subject: http://stackoverflow.com/a/33277354/2526115 – Ivan Lesko Dec 28 '15 at 17:34
-
Moving the presentation time stamp forward is also not an option because AVAssetWriter will export a video with a duration of the last time stamp. – Ivan Lesko Dec 28 '15 at 19:20
-
-
1I'm definitely not sorry the question was asked. So now we have such great informative example of how its done. Maybe for the purpose of silent sample, and maybe other. Thanks. – user1244109 Sep 16 '16 at 07:05
-
Can't you get the same result by _not_ creating an audio track at all? – Rhythmic Fistman May 16 '17 at 04:15
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
}
}

- 1,149
- 1
- 13
- 26
-
-
I would convert CMSampleBuffer to Swift "Data" -> https://stackoverflow.com/questions/45054779/how-to-convert-cmsamplebuffer-to-data-in-swift – Darkwonder Feb 10 '20 at 09:13
-
And then Swift "Data" to Swift "String" -> https://www.hackingwithswift.com/example-code/language/how-to-convert-data-to-a-string – Darkwonder Feb 10 '20 at 09:13
You need to create a block buffer using CMBlockBufferCreateWithMemoryBlock()
.
Fill the block buffer with a bunch of zeros and then pass it into CMAudioSampleBufferCreateWithPacketDescriptions()
.
Disclaimer: I haven't actually done this in Swift, I attempted it but found myself fighting the compiler at every turn so I switched to obj-c. The Core Media Framework is a low level C framework and was a lot easier to use without screwing around with Swifts type system. I know this isn't the answer you're looking for buy hopefully it will point you in the right direction.

- 922
- 11
- 18
-
-
@IvanLesko I put an example on github. It is a command line utility to create a single second of silence and put it into a file. – Pescolly Dec 29 '15 at 00:47