diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/AapSetting.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/AapSetting.kt index cf7da789..d1c49160 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/AapSetting.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/AapSetting.kt @@ -93,9 +93,8 @@ sealed class AapSetting { val enabled: Boolean, ) : AapSetting() - // Wire format matches librepods spec (tested on AirPods Pro 2). On AirPods Pro 3 the device - // accepts and echoes the value but no audible effect has been observed — may need additional - // enable packet or different handling. Requires more investigation. + // UI-space 0..100 (100 = max noise reduction). Wire value is inverted — conversion lives in + // the device profile. Pro 3 silently accepts writes (no echo) but the value persists. data class AdaptiveAudioNoise( val level: Int, ) : AapSetting() diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/DefaultAapDeviceProfile.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/DefaultAapDeviceProfile.kt index af2a25ce..cbeb325c 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/DefaultAapDeviceProfile.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/aap/protocol/DefaultAapDeviceProfile.kt @@ -86,7 +86,7 @@ class DefaultAapDeviceProfile( override fun encodeInitExt(): ByteArray? { if (!model.features.needsInitExt) return null return byteArrayOf( - 0x04, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x0e, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x4d, 0x00, 0xd7.toByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ) } @@ -101,7 +101,9 @@ class DefaultAapDeviceProfile( is AapCommand.SetVolumeSwipeLength -> buildSettingsMessage(SETTING_VOLUME_SWIPE_LENGTH, command.value.wireValue) is AapCommand.SetVolumeSwipe -> buildSettingsMessage(SETTING_VOLUME_SWIPE, encodeAppleBool(command.enabled)) is AapCommand.SetPersonalizedVolume -> buildSettingsMessage(SETTING_PERSONALIZED_VOLUME, encodeAppleBool(command.enabled)) - is AapCommand.SetAdaptiveAudioNoise -> buildSettingsMessage(SETTING_ADAPTIVE_AUDIO_NOISE, command.level.coerceIn(0, 100)) + // Wire semantics are inverted: wire 0 = max noise reduction, wire 100 = min (transparency-like). + // UI value 0..100 follows user intuition (100 = max NC), so flip on write/read. + is AapCommand.SetAdaptiveAudioNoise -> buildSettingsMessage(SETTING_ADAPTIVE_AUDIO_NOISE, 100 - command.level.coerceIn(0, 100)) is AapCommand.SetEndCallMuteMic -> buildEndCallMuteMicMessage(command.muteMic, command.endCall) is AapCommand.SetMicrophoneMode -> buildSettingsMessage(SETTING_MICROPHONE_MODE, command.mode.wireValue) is AapCommand.SetEarDetectionEnabled -> buildSettingsMessage(SETTING_EAR_DETECTION_ENABLED, encodeAppleBool(command.enabled)) @@ -242,7 +244,7 @@ class DefaultAapDeviceProfile( AapSetting.PersonalizedVolume::class to AapSetting.PersonalizedVolume(enabled) } SETTING_ADAPTIVE_AUDIO_NOISE -> { - AapSetting.AdaptiveAudioNoise::class to AapSetting.AdaptiveAudioNoise(level = value) + AapSetting.AdaptiveAudioNoise::class to AapSetting.AdaptiveAudioNoise(level = 100 - value.coerceIn(0, 100)) } SETTING_MICROPHONE_MODE -> { val mode = AapSetting.MicrophoneMode.Mode.fromWire(value) ?: return null