""" Android media.audiofx 组件 — AudioEffect, Equalizer, BassBoost, Virtualizer 等 方法签名完全对齐 Android SDK """ import math from typing import Any, Callable, Dict, List, Optional, Tuple from .._core import Stub, AndroidOnlyError # ═══════════════════════════════════════════════════════════════ # AudioEffect # ═══════════════════════════════════════════════════════════════ class AudioEffect(Stub): """AudioEffect — 音频效果基类""" EFFECT_SUCCESS = 0 EFFECT_ERROR = -1 EFFECT_ALREADY_EXISTS = -2 EFFECT_NO_MORE_SESSION = -3 EFFECT_REQUEST_INIT = -4 EFFECT_INIT_FAILED = -5 EFFECT_INSERT = 1 EFFECT_AUXILIARY = 2 EFFECT_PRE_PROCESSING = 4 EFFECT_POST_PROCESSING = 8 CONTENT_TYPE_MUSIC = 2 CONTENT_TYPE_MOVIE = 3 CONTENT_TYPE_GAME = 4 CONTENT_TYPE_VOICE = 1 # ═══════════════════════════════════════════════════════════ # Descriptor # ═══════════════════════════════════════════════════════════ class Descriptor(Stub): """AudioEffect.Descriptor — 效果描述符""" def __init__(self, type: str = "", uuid: str = "", connectMode: str = "", name: str = "", implementor: str = ""): super().__init__() self.type = type self.uuid = uuid self.connectMode = connectMode self.name = name self.implementor = implementor def toString(self) -> str: return f"Descriptor(type={self.type}, uuid={self.uuid}, name={self.name})" def __init__(self, effectType: str = "", priority: int = 0, audioSession: int = 0): super().__init__() self._enabled = False self._effect_type = effectType self._priority = priority self._audio_session = audioSession self._id = hash(self) & 0x7FFFFFFF self._control_status_listener: Optional[Callable] = None self._enable_status_listener: Optional[Callable] = None def getEnabled(self) -> bool: return self._enabled def setEnabled(self, enabled: bool) -> int: self._enabled = enabled return AudioEffect.EFFECT_SUCCESS def getId(self) -> int: return self._id def getDescriptor(self) -> Descriptor: return AudioEffect.Descriptor( type=self._effect_type, uuid="", connectMode="", name=self.__class__.__name__, implementor="Android-pyApi" ) def release(self): self._enabled = False def setControlStatusListener(self, listener: Callable): self._control_status_listener = listener def setEnableStatusListener(self, listener: Callable): self._enable_status_listener = listener # ═══════════════════════════════════════════════════════════════ # Equalizer # ═══════════════════════════════════════════════════════════════ class Equalizer(AudioEffect): """Equalizer — 均衡器""" PARAM_CURRENT_PRESET = 0 PARAM_GET_BAND = 1 PARAM_STRING_SIZE_MAX = 2 PARAM_BAND_LEVEL = 3 PARAM_LEVEL_RANGE = 4 PARAM_NUM_BANDS = 5 PARAM_BAND_FREQ_RANGE = 6 PARAM_CENTER_FREQ = 7 PARAM_GET_PRESET_NAME = 8 PARAM_NUM_PRESETS = 9 PARAM_PROPERTIES = 10 def __init__(self, priority: int = 0, audioSession: int = 0): super().__init__("Equalizer", priority, audioSession) self._num_bands = 5 self._band_levels: Dict[int, int] = {} self._presets = [ "Normal", "Classical", "Dance", "Flat", "Folk", "Heavy Metal", "Hip Hop", "Jazz", "Pop", "Rock" ] self._current_preset = 0 self._band_freq_ranges: Dict[int, Tuple[int, int]] = { 0: (60, 200), 1: (200, 600), 2: (600, 2400), 3: (2400, 8000), 4: (8000, 16000) } def getNumberOfBands(self) -> int: return self._num_bands def getBand(self, frequency: int) -> int: for band, (low, high) in self._band_freq_ranges.items(): if low <= frequency <= high: return band return 0 def getBandLevel(self, band: int) -> int: return self._band_levels.get(band, 0) def setBandLevel(self, band: int, level: int): self._band_levels[band] = level def getBandLevelRange(self) -> List[int]: return [-1500, 1500] def getCenterFreq(self, band: int) -> int: if band in self._band_freq_ranges: low, high = self._band_freq_ranges[band] return (low + high) // 2 return 0 def getNumberOfPresets(self) -> int: return len(self._presets) def getPresetName(self, preset: int) -> str: if 0 <= preset < len(self._presets): return self._presets[preset] return "Unknown" def usePreset(self, preset: int): if 0 <= preset < len(self._presets): self._current_preset = preset def getCurrentPreset(self) -> int: return self._current_preset def getProperties(self) -> Any: return None def setProperties(self, properties: Any): pass def toString(self) -> str: return f"Equalizer(preset={self._presets[self._current_preset]}," \ f" bands={self._num_bands})" # ═══════════════════════════════════════════════════════════════ # BassBoost # ═══════════════════════════════════════════════════════════════ class BassBoost(AudioEffect): """BassBoost — 低音增强""" PARAM_STRENGTH = 1 PARAM_STRENGTH_SUPPORTED = 2 def __init__(self, priority: int = 0, audioSession: int = 0): super().__init__("BassBoost", priority, audioSession) self._strength: int = 0 def setStrength(self, strength: int): self._strength = max(0, min(1000, strength)) def getRoundedStrength(self) -> int: return self._strength def getStrengthSupported(self) -> bool: return True def toString(self) -> str: return f"BassBoost(strength={self._strength})" # ═══════════════════════════════════════════════════════════════ # Virtualizer # ═══════════════════════════════════════════════════════════════ class Virtualizer(AudioEffect): """Virtualizer — 虚拟器 (空间音频)""" PARAM_STRENGTH = 1 PARAM_STRENGTH_SUPPORTED = 2 PARAM_VIRTUALIZATION_MODE = 3 PARAM_FORCE_VIRTUALIZATION_MODE = 4 VIRTUALIZATION_MODE_AUTO = 0 VIRTUALIZATION_MODE_OFF = 1 VIRTUALIZATION_MODE_TRANSAURAL = 2 VIRTUALIZATION_MODE_BINAURAL = 3 def __init__(self, priority: int = 0, audioSession: int = 0): super().__init__("Virtualizer", priority, audioSession) self._strength: int = 0 self._virtualization_mode = Virtualizer.VIRTUALIZATION_MODE_AUTO def setStrength(self, strength: int): self._strength = max(0, min(1000, strength)) def getRoundedStrength(self) -> int: return self._strength def canVirtualize(self, channelMask: int, virtualizationMode: int) -> bool: return True def getVirtualizationMode(self) -> int: return self._virtualization_mode def toString(self) -> str: return f"Virtualizer(strength={self._strength}, mode={self._virtualization_mode})" # ═══════════════════════════════════════════════════════════════ # PresetReverb # ═══════════════════════════════════════════════════════════════ class PresetReverb(AudioEffect): """PresetReverb — 预设混响""" PRESET_NONE = 0 PRESET_SMALLROOM = 1 PRESET_MEDIUMROOM = 2 PRESET_LARGEROOM = 3 PRESET_MEDIUMHALL = 4 PRESET_LARGEHALL = 5 PRESET_PLATE = 6 PARAM_PRESET = 0 def __init__(self, priority: int = 0, audioSession: int = 0): super().__init__("PresetReverb", priority, audioSession) self._preset = PresetReverb.PRESET_NONE self._preset_names = { PresetReverb.PRESET_NONE: "None", PresetReverb.PRESET_SMALLROOM: "Small Room", PresetReverb.PRESET_MEDIUMROOM: "Medium Room", PresetReverb.PRESET_LARGEROOM: "Large Room", PresetReverb.PRESET_MEDIUMHALL: "Medium Hall", PresetReverb.PRESET_LARGEHALL: "Large Hall", PresetReverb.PRESET_PLATE: "Plate", } def setPreset(self, preset: int): if preset in self._preset_names: self._preset = preset def getPreset(self) -> int: return self._preset def toString(self) -> str: return f"PresetReverb(preset={self._preset_names.get(self._preset, 'Unknown')})" # ═══════════════════════════════════════════════════════════════ # EnvironmentalReverb # ═══════════════════════════════════════════════════════════════ class EnvironmentalReverb(AudioEffect): """EnvironmentalReverb — 环境混响""" def __init__(self, priority: int = 0, audioSession: int = 0): super().__init__("EnvironmentalReverb", priority, audioSession) self._decay_time = 1500 self._decay_hf_ratio = 500 self._density = 500 self._diffusion = 500 self._reverb_level = 0 self._room_level = 0 self._room_hf_level = 0 self._reflections_delay = 20 self._reflections_level = -500 self._reverb_delay = 40 def setDecayTime(self, decayTime: int): self._decay_time = decayTime def getDecayTime(self) -> int: return self._decay_time def setDecayHFRatio(self, decayHFRatio: int): self._decay_hf_ratio = decayHFRatio def getDecayHFRatio(self) -> int: return self._decay_hf_ratio def setDensity(self, density: int): self._density = density def getDensity(self) -> int: return self._density def setDiffusion(self, diffusion: int): self._diffusion = diffusion def getDiffusion(self) -> int: return self._diffusion def setReverbLevel(self, reverbLevel: int): self._reverb_level = reverbLevel def getReverbLevel(self) -> int: return self._reverb_level def setRoomLevel(self, roomLevel: int): self._room_level = roomLevel def getRoomLevel(self) -> int: return self._room_level def setRoomHFLevel(self, roomHFLevel: int): self._room_hf_level = roomHFLevel def getRoomHFLevel(self) -> int: return self._room_hf_level def setReflectionsDelay(self, reflectionsDelay: int): self._reflections_delay = reflectionsDelay def getReflectionsDelay(self) -> int: return self._reflections_delay def setReflectionsLevel(self, reflectionsLevel: int): self._reflections_level = reflectionsLevel def getReflectionsLevel(self) -> int: return self._reflections_level def setReverbDelay(self, reverbDelay: int): self._reverb_delay = reverbDelay def getReverbDelay(self) -> int: return self._reverb_delay def toString(self) -> str: return f"EnvironmentalReverb(decayTime={self._decay_time}," \ f" density={self._density})" # ═══════════════════════════════════════════════════════════════ # LoudnessEnhancer # ═══════════════════════════════════════════════════════════════ class LoudnessEnhancer(AudioEffect): """LoudnessEnhancer — 响度增强器""" PARAM_TARGET_GAIN_MB = 0 def __init__(self, audioSession: int = 0): super().__init__("LoudnessEnhancer", 0, audioSession) self._target_gain = 0 def setTargetGain(self, gainMillibels: int): self._target_gain = gainMillibels def getTargetGain(self) -> int: return self._target_gain def toString(self) -> str: return f"LoudnessEnhancer(targetGain={self._target_gain} mB)" # ═══════════════════════════════════════════════════════════════ # DynamicsProcessing # ═══════════════════════════════════════════════════════════════ class DynamicsProcessing(AudioEffect): """DynamicsProcessing — 动态处理""" class Stage(Stub): """DynamicsProcessing.Stage — 处理阶段""" def __init__(self, enabled: bool = True): super().__init__() self._enabled = enabled self._in_use = True def isEnabled(self) -> bool: return self._enabled def setEnabled(self, enabled: bool): self._enabled = enabled class EQBand(Stage): """DynamicsProcessing.EQBand — EQ 频段""" def __init__(self, enabled: bool = True): super().__init__(enabled) self._gain = 0.0 self._center_freq = 1000.0 def setGain(self, gain: float): self._gain = gain def getGain(self) -> float: return self._gain def setCenterFreq(self, freq: float): self._center_freq = freq def getCenterFreq(self) -> float: return self._center_freq class EQ(Stage): """DynamicsProcessing.EQ — 均衡器""" def __init__(self, enabled: bool = True, bandCount: int = 6): super().__init__(enabled) self._bands = [EQBand() for _ in range(bandCount)] def getBand(self, band: int) -> "DynamicsProcessing.EQBand": if 0 <= band < len(self._bands): return self._bands[band] raise IndexError(f"Band {band} out of range") class MBCBand(Stage): """DynamicsProcessing.MBCBand — 多频段压缩频段""" def __init__(self, enabled: bool = True): super().__init__(enabled) self._gain = 0.0 def setGain(self, gain: float): self._gain = gain def getGain(self) -> float: return self._gain class MBC(Stage): """DynamicsProcessing.MBC — 多频段压缩""" def __init__(self, enabled: bool = True, bandCount: int = 6): super().__init__(enabled) self._bands = [MBCBand() for _ in range(bandCount)] def getBand(self, band: int) -> "DynamicsProcessing.MBCBand": if 0 <= band < len(self._bands): return self._bands[band] raise IndexError(f"Band {band} out of range") class Limiter(Stage): """DynamicsProcessing.Limiter — 限制器""" def __init__(self, enabled: bool = True): super().__init__(enabled) class Channel(Stub): """DynamicsProcessing.Channel — 处理通道""" def __init__(self, stageCount: int = 1): super().__init__() self._stage_count = stageCount class Config(Stub): """DynamicsProcessing.Config — 处理配置""" def __init__(self, channelCount: int = 1, preEqCount: int = 1, mbcCount: int = 1, postEqCount: int = 1, limiterCount: int = 1, prefEqBandCount: int = 6, postEqBandCount: int = 6, mbcBandCount: int = 6): super().__init__() self._channels = [DynamicsProcessing.Channel(0) for _ in range(channelCount)] def __init__(self, audioSession: int = 0): super().__init__("DynamicsProcessing", 0, audioSession) self._channel_count = 1 self._post_constraints: List[Any] = [] self._pre_eqs: List[DynamicsProcessing.EQ] = [DynamicsProcessing.EQ()] self._post_eqs: List[DynamicsProcessing.EQ] = [DynamicsProcessing.EQ()] self._mbcs: List[DynamicsProcessing.MBC] = [DynamicsProcessing.MBC()] self._limiters: List[DynamicsProcessing.Limiter] = [DynamicsProcessing.Limiter()] self._mbands: List[Any] = [] self._channel_stage: List[Any] = [] def getChannelCount(self) -> int: return self._channel_count def getPostConstraints(self) -> List[Any]: return self._post_constraints def getPreEQs(self) -> List[EQ]: return self._pre_eqs def getMbands(self) -> List[Any]: return self._mbands def getPostEQs(self) -> List[EQ]: return self._post_eqs def getLimiters(self) -> List[Limiter]: return self._limiters def getMbc(self) -> List[MBC]: return self._mbcs def getChannelStage(self) -> List[Any]: return self._channel_stage def toString(self) -> str: return f"DynamicsProcessing(channels={self._channel_count})" # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "AudioEffect", "Equalizer", "BassBoost", "Virtualizer", "PresetReverb", "EnvironmentalReverb", "LoudnessEnhancer", "DynamicsProcessing", ]