Skip to content

Commit

Permalink
Merge pull request #1385 from stream-labs/bugfix/audioapp-timestamp
Browse files Browse the repository at this point in the history
Implement timestamp recalculation for audio buffers
  • Loading branch information
shogo4405 authored Mar 11, 2024
2 parents 9b96908 + e840bdb commit 17d67f5
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 7 deletions.
15 changes: 10 additions & 5 deletions Sources/IO/IOAudioResampler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ struct IOAudioResamplerSettings {
final class IOAudioResampler<T: IOAudioResamplerDelegate> {
private static func makeAudioFormat(_ inSourceFormat: inout AudioStreamBasicDescription) -> AVAudioFormat? {
if inSourceFormat.mFormatID == kAudioFormatLinearPCM && kLinearPCMFormatFlagIsBigEndian == (inSourceFormat.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
// ReplayKit audioApp.
guard inSourceFormat.mBitsPerChannel == 16 else {
return nil
}
let interleaved = !((inSourceFormat.mFormatFlags & kLinearPCMFormatFlagIsNonInterleaved) == kLinearPCMFormatFlagIsNonInterleaved)
if let channelLayout = Self.makeChannelLayout(inSourceFormat.mChannelsPerFrame) {
return .init(
Expand Down Expand Up @@ -168,8 +164,17 @@ final class IOAudioResampler<T: IOAudioResamplerDelegate> {

func append(_ sampleBuffer: CMSampleBuffer) {
inSourceFormat = sampleBuffer.formatDescription?.audioStreamBasicDescription
guard let inSourceFormat else {
return
}
if sampleTime == kIOAudioResampler_sampleTime {
sampleTime = sampleBuffer.presentationTimeStamp.value
let targetSampleTime: CMTimeValue
if sampleBuffer.presentationTimeStamp.timescale == Int32(inSourceFormat.mSampleRate) {
targetSampleTime = sampleBuffer.presentationTimeStamp.value
} else {
targetSampleTime = Int64(Double(sampleBuffer.presentationTimeStamp.value) * inSourceFormat.mSampleRate / Double(sampleBuffer.presentationTimeStamp.timescale))
}
sampleTime = AVAudioFramePosition(targetSampleTime)
if let outputFormat {
anchor = .init(hostTime: AVAudioTime.hostTime(forSeconds: sampleBuffer.presentationTimeStamp.seconds), sampleTime: sampleTime, atRate: outputFormat.sampleRate)
}
Expand Down
10 changes: 8 additions & 2 deletions Sources/IO/IOAudioRingBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ final class IOAudioRingBuffer {
guard CMSampleBufferDataIsReady(sampleBuffer) else {
return
}
let targetSampleTime: CMTimeValue
if sampleBuffer.presentationTimeStamp.timescale == Int32(inputBuffer.format.sampleRate) {
targetSampleTime = sampleBuffer.presentationTimeStamp.value
} else {
targetSampleTime = Int64(Double(sampleBuffer.presentationTimeStamp.value) * inputBuffer.format.sampleRate / Double(sampleBuffer.presentationTimeStamp.timescale))
}
if sampleTime == 0 {
sampleTime = sampleBuffer.presentationTimeStamp.value
sampleTime = targetSampleTime
}
if inputBuffer.frameLength < sampleBuffer.numSamples {
if let buffer = AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: AVAudioFrameCount(sampleBuffer.numSamples)) {
Expand All @@ -67,7 +73,7 @@ final class IOAudioRingBuffer {
}
}
}
skip = max(Int(sampleBuffer.presentationTimeStamp.value - sampleTime), 0)
skip = max(Int(targetSampleTime - sampleTime), 0)
sampleTime += Int64(skip)
append(inputBuffer)
}
Expand Down

0 comments on commit 17d67f5

Please sign in to comment.