Modifying an audio stream can be done with an AVAssetReader
and AVAssetWriter
. While reading a CMSampleBuffer
can be used to get CMBlockBuffer
which is a pointer to a buffer within CMSampleBuffer
. Those bytes can be copied
into a mutable buffer with CMBlockBufferCopyDataBytes
to modify the values and then use CMBlockBufferReplaceDataBytes
to put the modified values back into the CMSampleBuffer
which also modifies CMSampleBuffer
before appending it
to the AVAssetWriterInput
instance used by AVAssetWriter
.
Last active
November 2, 2023 09:25
-
-
Save brennanMKE/dfe246bb06a4973ae40380bb915676bb to your computer and use it in GitHub Desktop.
Process a CMSampleBuffer to modify the audio using an AVAssetReader and AVAssetWriter in Swift
This file contains hidden or 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
func processSampleBuffer(scale: Float, sampleBuffer: CMSampleBuffer, writerInput: AVAssetWriterInput) -> Bool { | |
guard let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else { | |
return false | |
} | |
let length = CMBlockBufferGetDataLength(blockBuffer) | |
var sampleBytes = UnsafeMutablePointer<Int16>.allocate(capacity: length) | |
defer { sampleBytes.deallocate(capacity: length) } | |
guard checkStatus(CMBlockBufferCopyDataBytes(blockBuffer, 0, length, sampleBytes), message: "Copying block buffer") else { | |
return false | |
} | |
(0..<length).forEach { index in | |
let ptr = sampleBytes + index | |
let scaledValue = Float(ptr.pointee) * scale | |
let processedValue = Int16(max(min(scaledValue, Float(Int16.max)), Float(Int16.min))) | |
ptr.pointee = processedValue | |
} | |
guard checkStatus(CMBlockBufferReplaceDataBytes(sampleBytes, blockBuffer, 0, length), message: "Replacing data bytes in block buffer") else { return false } | |
assert(CMSampleBufferIsValid(sampleBuffer)) | |
return writerInput.append(sampleBuffer) | |
} | |
func checkStatus(_ status: OSStatus, message: String) -> Bool { | |
// See: https://www.osstatus.com/ | |
assert(kCMBlockBufferNoErr == noErr) | |
if status != noErr { | |
debugPrint("Error: \(message) [\(status)]") | |
} | |
return status == noErr | |
} |
what is the value of 'scale', I can't find it
what is the value of 'scale', I can't find it
@daobao777 scale could be specified by yourself. it could be 0.0-1.0
what is the value of 'scale', I can't find it
@daobao777 scale could be specified by yourself. it could be 0.0-1.0
line 15: let scaledValue = Float(ptr.pointee) * scale
what is the value of 'scale', I can't find it
@daobao777 scale could be specified by yourself. it could be 0.0-1.0
I would get the wrong answer when scale is 1.0
So, how can i get accurate data
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this code helped me, but it spent about 5-7ms