Created
July 17, 2021 19:15
-
-
Save aibo-cora/c57d1a4125e145e586ecb61ebecff47c to your computer and use it in GitHub Desktop.
Class to convert AVAudioPCMBuffer to CMSampleBuffer.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import AVFoundation | |
import CoreMedia | |
class Converter { | |
static func configureSampleBuffer(pcmBuffer: AVAudioPCMBuffer) -> CMSampleBuffer? { | |
let audioBufferList = pcmBuffer.mutableAudioBufferList | |
let asbd = pcmBuffer.format.streamDescription | |
var sampleBuffer: CMSampleBuffer? = nil | |
var format: CMFormatDescription? = nil | |
var status = CMAudioFormatDescriptionCreate(allocator: kCFAllocatorDefault, | |
asbd: asbd, | |
layoutSize: 0, | |
layout: nil, | |
magicCookieSize: 0, | |
magicCookie: nil, | |
extensions: nil, | |
formatDescriptionOut: &format); | |
if (status != noErr) { return nil; } | |
var timing: CMSampleTimingInfo = CMSampleTimingInfo(duration: CMTime(value: 1, timescale: Int32(asbd.pointee.mSampleRate)), | |
presentationTimeStamp: CMClockGetTime(CMClockGetHostTimeClock()), | |
decodeTimeStamp: CMTime.invalid) | |
status = CMSampleBufferCreate(allocator: kCFAllocatorDefault, | |
dataBuffer: nil, | |
dataReady: false, | |
makeDataReadyCallback: nil, | |
refcon: nil, | |
formatDescription: format, | |
sampleCount: CMItemCount(pcmBuffer.frameLength), | |
sampleTimingEntryCount: 1, | |
sampleTimingArray: &timing, | |
sampleSizeEntryCount: 0, | |
sampleSizeArray: nil, | |
sampleBufferOut: &sampleBuffer); | |
if (status != noErr) { NSLog("CMSampleBufferCreate returned error: \(status)"); return nil } | |
status = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer!, | |
blockBufferAllocator: kCFAllocatorDefault, | |
blockBufferMemoryAllocator: kCFAllocatorDefault, | |
flags: 0, | |
bufferList: audioBufferList); | |
if (status != noErr) { NSLog("CMSampleBufferSetDataBufferFromAudioBufferList returned error: \(status)"); return nil; } | |
return sampleBuffer | |
} | |
} |
Apple docs for
CMSampleBufferCreate
state:Example of usage for uncompressed (non-)interleaved audio:
...
sampleTimingArray: one entry = {duration = 1/48000, presentationTimeStamp = 0/48000, decodeTimeStamp = invalid }
...So I think the definition of the
timing
parameter should be:var timing: CMSampleTimingInfo = CMSampleTimingInfo( duration: CMTime(value: 1, timescale: Int32(asbd.pointee.mSampleRate)), - presentationTimeStamp: CMClockGetTime(CMClockGetHostTimeClock()), + presentationTimeStamp: CMTime(value: 0, timescale: Int32(asbd.pointee.mSampleRate)), decodeTimeStamp: CMTime.invalid )
That doesn't seem correct as each buffer will then have 0 as their timestamp causing issues when writing to disk.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@rlaguilar Feel free to adapt this to your needs. This implementation is used in a live app as is.