From d19d8f3248481b139cfb2129c6d761913b0e6581 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Fri, 27 Jun 2025 22:04:15 +0545 Subject: [PATCH] Fix mic blinking and reduce recording startup delay --- VoiceInk/Recorder.swift | 11 +--- .../Services/AudioDeviceConfiguration.swift | 61 +++++-------------- VoiceInk/Services/AudioDeviceManager.swift | 2 +- 3 files changed, 18 insertions(+), 56 deletions(-) diff --git a/VoiceInk/Recorder.swift b/VoiceInk/Recorder.swift index ccb4f7e..0a5017f 100644 --- a/VoiceInk/Recorder.swift +++ b/VoiceInk/Recorder.swift @@ -38,7 +38,6 @@ class Recorder: ObservableObject { if recorder != nil { let currentURL = recorder?.url stopRecording() - try? await Task.sleep(nanoseconds: 100_000_000) if let url = currentURL { do { @@ -52,13 +51,7 @@ class Recorder: ObservableObject { } private func configureAudioSession(with deviceID: AudioDeviceID) async throws { - do { - _ = try AudioDeviceConfiguration.configureAudioSession(with: deviceID) - try AudioDeviceConfiguration.setDefaultInputDevice(deviceID) - } catch { - logger.error("❌ Failed to configure audio session: \(error.localizedDescription)") - throw error - } + try AudioDeviceConfiguration.setDefaultInputDevice(deviceID) } func startRecording(toOutputFile url: URL) async throws { @@ -89,10 +82,8 @@ class Recorder: ObservableObject { if deviceID != 0 { do { try await configureAudioSession(with: deviceID) - try? await Task.sleep(nanoseconds: 50_000_000) } catch { logger.warning("⚠️ Failed to configure audio session for device \(deviceID), attempting to continue: \(error.localizedDescription)") - try? await Task.sleep(nanoseconds: 50_000_000) } } diff --git a/VoiceInk/Services/AudioDeviceConfiguration.swift b/VoiceInk/Services/AudioDeviceConfiguration.swift index 2648a98..4bc235e 100644 --- a/VoiceInk/Services/AudioDeviceConfiguration.swift +++ b/VoiceInk/Services/AudioDeviceConfiguration.swift @@ -7,58 +7,35 @@ class AudioDeviceConfiguration { private static let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "AudioDeviceConfiguration") - static func configureAudioSession(with deviceID: AudioDeviceID) throws -> AudioStreamBasicDescription { - var propertySize = UInt32(MemoryLayout.size) - var streamFormat = AudioStreamBasicDescription() - var propertyAddress = AudioObjectPropertyAddress( - mSelector: kAudioDevicePropertyStreamFormat, - mScope: kAudioDevicePropertyScopeInput, - mElement: kAudioObjectPropertyElementMain - ) - - // First, ensure the device is ready - var isAlive: UInt32 = 0 - var aliveSize = UInt32(MemoryLayout.size) - var aliveAddress = AudioObjectPropertyAddress( - mSelector: kAudioDevicePropertyDeviceIsAlive, + + + static func getDefaultInputDevice() -> AudioDeviceID? { + var defaultDeviceID = AudioDeviceID(0) + var propertySize = UInt32(MemoryLayout.size) + var address = AudioObjectPropertyAddress( + mSelector: kAudioHardwarePropertyDefaultInputDevice, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMain ) - - let aliveStatus = AudioObjectGetPropertyData( - deviceID, - &aliveAddress, - 0, - nil, - &aliveSize, - &isAlive - ) - - if aliveStatus != noErr || isAlive == 0 { - logger.error("Device \(deviceID) is not alive or ready") - throw AudioConfigurationError.failedToGetDeviceFormat(status: aliveStatus) - } - - // Get the device format let status = AudioObjectGetPropertyData( - deviceID, - &propertyAddress, + AudioObjectID(kAudioObjectSystemObject), + &address, 0, nil, &propertySize, - &streamFormat + &defaultDeviceID ) - if status != noErr { - logger.error("Failed to get device format: \(status)") - throw AudioConfigurationError.failedToGetDeviceFormat(status: status) + logger.error("Failed to get current default input device: \(status)") + return nil } - - return streamFormat + return defaultDeviceID } - static func setDefaultInputDevice(_ deviceID: AudioDeviceID) throws { + if let currentDefault = getDefaultInputDevice(), currentDefault == deviceID { + return + } var deviceIDCopy = deviceID let propertySize = UInt32(MemoryLayout.size) var address = AudioObjectPropertyAddress( @@ -101,18 +78,12 @@ class AudioDeviceConfiguration { } enum AudioConfigurationError: LocalizedError { - case failedToGetDeviceFormat(status: OSStatus) case failedToSetInputDevice(status: OSStatus) - case failedToGetAudioUnit var errorDescription: String? { switch self { - case .failedToGetDeviceFormat(let status): - return "Failed to get device format: \(status)" case .failedToSetInputDevice(let status): return "Failed to set input device: \(status)" - case .failedToGetAudioUnit: - return "Failed to get audio unit from input node" } } } \ No newline at end of file diff --git a/VoiceInk/Services/AudioDeviceManager.swift b/VoiceInk/Services/AudioDeviceManager.swift index e9715c3..bbae4a3 100644 --- a/VoiceInk/Services/AudioDeviceManager.swift +++ b/VoiceInk/Services/AudioDeviceManager.swift @@ -325,11 +325,11 @@ class AudioDeviceManager: ObservableObject { do { try AudioDeviceConfiguration.setDefaultInputDevice(availableDevice.id) - self.notifyDeviceChange() } catch { logger.error("Failed to set prioritized device: \(error.localizedDescription)") continue } + notifyDeviceChange() return } }