From 2944e4ce5c3f1a5677e7d5d27ad0e0382e673179 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Sun, 21 Dec 2025 13:04:35 +0545 Subject: [PATCH] Improve recorder device change handling --- VoiceInk/AudioEngineRecorder.swift | 76 ---------------------- VoiceInk/Recorder.swift | 19 ++---- VoiceInk/Services/AudioDeviceManager.swift | 4 +- 3 files changed, 8 insertions(+), 91 deletions(-) diff --git a/VoiceInk/AudioEngineRecorder.swift b/VoiceInk/AudioEngineRecorder.swift index d3f596b..bdb0d0e 100644 --- a/VoiceInk/AudioEngineRecorder.swift +++ b/VoiceInk/AudioEngineRecorder.swift @@ -29,32 +29,6 @@ class AudioEngineRecorder: ObservableObject { // Callback to notify parent class of runtime recording errors var onRecordingError: ((Error) -> Void)? - init() { - setupNotifications() - } - - private func setupNotifications() { - NotificationCenter.default.addObserver( - self, - selector: #selector(handleConfigurationChange), - name: .AVAudioEngineConfigurationChange, - object: nil - ) - } - - @objc private func handleConfigurationChange(notification: Notification) { - Task { @MainActor in - guard isRecording else { return } - logger.info("⚠️ AVAudioEngine configuration change detected (e.g. sample rate change). Restarting engine...") - do { - try restartRecordingPreservingFile() - } catch { - logger.error("Failed to recover from configuration change: \(error.localizedDescription)") - stopRecording() - } - } - } - func startRecording(toOutputFile url: URL) throws { stopRecording() @@ -131,52 +105,6 @@ class AudioEngineRecorder: ObservableObject { } } - private func restartRecordingPreservingFile() throws { - if let input = inputNode { - input.removeTap(onBus: tapBusNumber) - } - audioEngine?.stop() - - // Drain queue to prevent old-format buffers racing with new converter - audioProcessingQueue.sync { } - - let engine = AVAudioEngine() - audioEngine = engine - - let input = engine.inputNode - inputNode = input - - let inputFormat = input.outputFormat(forBus: tapBusNumber) - logger.info("Restarting with new input format - Sample Rate: \(inputFormat.sampleRate)") - - guard inputFormat.sampleRate > 0 else { - throw AudioEngineRecorderError.invalidInputFormat - } - - guard let format = recordingFormat else { - throw AudioEngineRecorderError.invalidRecordingFormat - } - - guard let newConverter = AVAudioConverter(from: inputFormat, to: format) else { - throw AudioEngineRecorderError.failedToCreateConverter - } - - fileWriteLock.lock() - converter = newConverter - fileWriteLock.unlock() - - input.installTap(onBus: tapBusNumber, bufferSize: tapBufferSize, format: inputFormat) { [weak self] (buffer, time) in - guard let self = self else { return } - self.audioProcessingQueue.async { - self.processAudioBuffer(buffer) - } - } - - engine.prepare() - try engine.start() - logger.info("✅ Audio engine successfully restarted after configuration change") - } - func stopRecording() { guard isRecording else { return @@ -307,10 +235,6 @@ class AudioEngineRecorder: ObservableObject { var currentRecordingURL: URL? { return recordingURL } - - deinit { - NotificationCenter.default.removeObserver(self) - } } // MARK: - Error Types diff --git a/VoiceInk/Recorder.swift b/VoiceInk/Recorder.swift index 15c5dde..6a3cf01 100644 --- a/VoiceInk/Recorder.swift +++ b/VoiceInk/Recorder.swift @@ -36,20 +36,15 @@ class Recorder: NSObject, ObservableObject { private func handleDeviceChange() async { guard !isReconfiguring else { return } + isReconfiguring = true - - if recorder != nil { - let currentURL = recorder?.currentRecordingURL - stopRecording() - - if let url = currentURL { - do { - try await startRecording(toOutputFile: url) - } catch { - logger.error("❌ Failed to restart recording after device change: \(error.localizedDescription)") - } - } + + try? await Task.sleep(nanoseconds: 200_000_000) + + await MainActor.run { + NotificationCenter.default.post(name: .toggleMiniRecorder, object: nil) } + isReconfiguring = false } diff --git a/VoiceInk/Services/AudioDeviceManager.swift b/VoiceInk/Services/AudioDeviceManager.swift index 33ea497..4ca0442 100644 --- a/VoiceInk/Services/AudioDeviceManager.swift +++ b/VoiceInk/Services/AudioDeviceManager.swift @@ -526,8 +526,6 @@ class AudioDeviceManager: ObservableObject { } private func notifyDeviceChange() { - if !isRecordingActive { - NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) - } + NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) } }