From 126814911426e610d6db6bae4413ee87338201b7 Mon Sep 17 00:00:00 2001 From: superdooper86 Date: Thu, 23 Jul 2026 14:29:04 +0200 Subject: [PATCH] fix: preserve system audio resampler state --- Meetingnotes.xcodeproj/project.pbxproj | 8 ++++---- meetingnotes/Managers/AudioManager.swift | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Meetingnotes.xcodeproj/project.pbxproj b/Meetingnotes.xcodeproj/project.pbxproj index cdd6a81..352ce38 100644 --- a/Meetingnotes.xcodeproj/project.pbxproj +++ b/Meetingnotes.xcodeproj/project.pbxproj @@ -276,7 +276,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 27; + CURRENT_PROJECT_VERSION = 28; DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\""; DEVELOPMENT_TEAM = G9LVHZAJNX; ENABLE_HARDENED_RUNTIME = YES; @@ -290,7 +290,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.1.15; + MARKETING_VERSION = 1.1.16; ONLY_ACTIVE_ARCH = NO; OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI"; PRODUCT_BUNDLE_IDENTIFIER = net.jamesbone.meetingnotes; @@ -312,7 +312,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 27; + CURRENT_PROJECT_VERSION = 28; DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\""; DEVELOPMENT_TEAM = G9LVHZAJNX; ENABLE_HARDENED_RUNTIME = YES; @@ -326,7 +326,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.1.15; + MARKETING_VERSION = 1.1.16; ONLY_ACTIVE_ARCH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI"; PRODUCT_BUNDLE_IDENTIFIER = net.jamesbone.meetingnotes; diff --git a/meetingnotes/Managers/AudioManager.swift b/meetingnotes/Managers/AudioManager.swift index 0b189c4..1f0412e 100644 --- a/meetingnotes/Managers/AudioManager.swift +++ b/meetingnotes/Managers/AudioManager.swift @@ -344,12 +344,14 @@ final class AudioManager: NSObject, ObservableObject { private func startTapIO(_ tap: ProcessTap) throws { guard var description = tap.tapStreamDescription, let inputFormat = AVAudioFormat(streamDescription: &description), - let targetFormat = systemAudioFile?.processingFormat else { + let targetFormat = systemAudioFile?.processingFormat, + let converter = AVAudioConverter(from: inputFormat, to: targetFormat) else { throw NSError(domain: "AudioManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unsupported system audio format"]) } try tap.run(on: tapQueue) { [weak self] _, inputData, _, _, _ in - guard let self, - let converter = AVAudioConverter(from: inputFormat, to: targetFormat) else { return } + guard let self else { return } + // The tap queue is serial. Reusing the converter preserves its + // resampler state instead of discarding audio at every callback. self.processAudioBuffer( { self.copyAudioBuffer(from: inputData, format: inputFormat) }, converter: converter,