/** * 均衡器管理器 * 管理均衡器预设、状态和 FFmpeg 过滤器生成 */ import { PreferencesUtil } from '@pura/harmony-utils'; import { IjkMediaPlayer } from '@ohos/ijkplayer'; import Logger from './Logger'; // 频段定义 export interface EqualizerBand { frequency: number; // 中心频率 (Hz) label: string; // 显示标签 (如 "32Hz", "1kHz") gain: number; // 增益值 (-12 到 +12 dB) } // 预设定义 export interface EqualizerPreset { id: string; // 预设唯一标识 name: string; // 预设名称 gains: number[]; // 10 个频段的增益值 isCustom: boolean; // 是否为自定义预设 } export class EqualizerManager { private static instance: EqualizerManager | null = null; private static readonly TAG: string = 'heanup EqualizerManager'; // 持久化键名 private static readonly PREF_ENABLED: string = 'equalizer_enabled'; private static readonly PREF_PRESET_ID: string = 'equalizer_preset_id'; private static readonly PREF_CUSTOM_GAINS: string = 'equalizer_custom_gains'; private static readonly PREF_CUSTOM_PRESETS: string = 'equalizer_custom_presets'; // 10 频段定义 public static readonly BANDS: EqualizerBand[] = [ { frequency: 32, label: '32Hz', gain: 0 }, { frequency: 64, label: '64Hz', gain: 0 }, { frequency: 125, label: '125Hz', gain: 0 }, { frequency: 250, label: '250Hz', gain: 0 }, { frequency: 500, label: '500Hz', gain: 0 }, { frequency: 1000, label: '1kHz', gain: 0 }, { frequency: 2000, label: '2kHz', gain: 0 }, { frequency: 4000, label: '4kHz', gain: 0 }, { frequency: 8000, label: '8kHz', gain: 0 }, { frequency: 16000, label: '16kHz', gain: 0 } ]; // 内置预设 - 增益值增大以获得更明显的效果 public static readonly BUILT_IN_PRESETS: EqualizerPreset[] = [ { id: 'normal', name: '正常', gains: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], isCustom: false }, { id: 'pop', name: '流行', gains: [-2, 3, 6, 6, 3, 0, -2, -2, -2, -2], isCustom: false }, { id: 'rock', name: '摇滚', gains: [6, 5, 2, 0, -2, 0, 3, 5, 6, 6], isCustom: false }, { id: 'jazz', name: '爵士', gains: [5, 3, 2, 3, -3, -3, 0, 2, 3, 5], isCustom: false }, { id: 'classical', name: '古典', gains: [6, 5, 3, 2, -2, -2, 0, 3, 5, 6], isCustom: false }, { id: 'bass_boost', name: '低音增强', gains: [10, 8, 6, 3, 0, 0, 0, 0, 0, 0], isCustom: false }, { id: 'treble_boost', name: '高音增强', gains: [0, 0, 0, 0, 0, 2, 4, 6, 8, 10], isCustom: false }, { id: 'vocal', name: '人声增强', gains: [-4, -2, 0, 4, 6, 6, 4, 0, -2, -4], isCustom: false }, { id: 'dance', name: '舞曲', gains: [8, 6, 3, 0, 0, -3, -2, 3, 5, 6], isCustom: false }, { id: 'acoustic', name: '原声', gains: [5, 4, 2, 2, 3, 3, 3, 5, 4, 2], isCustom: false } ]; // 当前状态 private _enabled: boolean = false; private _currentPresetId: string = 'normal'; private _customGains: number[] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; private _customPresets: EqualizerPreset[] = []; private constructor() { this.loadState(); } public static getInstance(): EqualizerManager { if (EqualizerManager.instance === null) { EqualizerManager.instance = new EqualizerManager(); } return EqualizerManager.instance; } // 类型守卫:验证是否为有效的增益数组 private isValidGainsArray(value: object): boolean { if (!Array.isArray(value)) { return false; } if (value.length !== 10) { return false; } for (let i = 0; i < value.length; i++) { if (typeof value[i] !== 'number') { return false; } } return true; } // 类型守卫:验证是否为有效的预设数组 private isValidPresetArray(value: object): boolean { if (!Array.isArray(value)) { return false; } for (let i = 0; i < value.length; i++) { const item = value[i] as Record; if (typeof item !== 'object' || item === null) { return false; } if (typeof item['id'] !== 'string' || typeof item['name'] !== 'string' || !Array.isArray(item['gains']) || typeof item['isCustom'] !== 'boolean') { return false; } } return true; } // 加载持久化状态 private loadState(): void { this._enabled = PreferencesUtil.getBooleanSync(EqualizerManager.PREF_ENABLED, false); this._currentPresetId = PreferencesUtil.getStringSync(EqualizerManager.PREF_PRESET_ID, 'normal'); const gainsStr = PreferencesUtil.getStringSync(EqualizerManager.PREF_CUSTOM_GAINS, ''); if (gainsStr.length > 0) { try { const parsed: object = JSON.parse(gainsStr) as object; if (this.isValidGainsArray(parsed)) { this._customGains = parsed as number[]; } } catch (e) { Logger.error(EqualizerManager.TAG, `解析自定义增益失败: ${(e as Error).message}`); } } const presetsStr = PreferencesUtil.getStringSync(EqualizerManager.PREF_CUSTOM_PRESETS, ''); if (presetsStr.length > 0) { try { const parsed: object = JSON.parse(presetsStr) as object; if (this.isValidPresetArray(parsed)) { this._customPresets = parsed as EqualizerPreset[]; } } catch (e) { Logger.error(EqualizerManager.TAG, `解析自定义预设失败: ${(e as Error).message}`); } } Logger.info(EqualizerManager.TAG, `状态已加载: enabled=${this._enabled}, preset=${this._currentPresetId}`); } // 保存状态 private saveState(): void { PreferencesUtil.putSync(EqualizerManager.PREF_ENABLED, this._enabled); PreferencesUtil.putSync(EqualizerManager.PREF_PRESET_ID, this._currentPresetId); PreferencesUtil.putSync(EqualizerManager.PREF_CUSTOM_GAINS, JSON.stringify(this._customGains)); PreferencesUtil.putSync(EqualizerManager.PREF_CUSTOM_PRESETS, JSON.stringify(this._customPresets)); } // Getter/Setter get enabled(): boolean { return this._enabled; } set enabled(value: boolean) { this._enabled = value; this.saveState(); } get currentPresetId(): string { return this._currentPresetId; } get customGains(): number[] { return this._customGains.slice(); } // 获取所有预设(内置 + 自定义) getAllPresets(): EqualizerPreset[] { const result: EqualizerPreset[] = []; for (let i = 0; i < EqualizerManager.BUILT_IN_PRESETS.length; i++) { result.push(EqualizerManager.BUILT_IN_PRESETS[i]); } for (let i = 0; i < this._customPresets.length; i++) { result.push(this._customPresets[i]); } return result; } // 获取当前预设 getCurrentPreset(): EqualizerPreset | null { const allPresets = this.getAllPresets(); for (let i = 0; i < allPresets.length; i++) { if (allPresets[i].id === this._currentPresetId) { return allPresets[i]; } } return null; } // 获取当前增益值 getCurrentGains(): number[] { if (this._currentPresetId === 'custom') { return this._customGains.slice(); } const preset = this.getCurrentPreset(); if (preset !== null) { return preset.gains.slice(); } return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; } // 设置预设 setPreset(presetId: string): void { this._currentPresetId = presetId; this.saveState(); Logger.info(EqualizerManager.TAG, `预设已更改: ${presetId}`); } // 设置自定义增益 setCustomGain(bandIndex: number, gain: number): void { if (bandIndex < 0 || bandIndex >= 10) { return; } // 限制增益范围 -12 到 +12 let clampedGain = gain; if (clampedGain < -12) { clampedGain = -12; } if (clampedGain > 12) { clampedGain = 12; } this._customGains[bandIndex] = clampedGain; this._currentPresetId = 'custom'; this.saveState(); } // 设置所有自定义增益 setAllCustomGains(gains: number[]): void { if (gains.length !== 10) { return; } for (let i = 0; i < 10; i++) { let g = gains[i]; if (g < -12) { g = -12; } if (g > 12) { g = 12; } this._customGains[i] = g; } this._currentPresetId = 'custom'; this.saveState(); } // 重置为平坦 resetToFlat(): void { this._customGains = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; this._currentPresetId = 'normal'; this.saveState(); } // 保存当前设置为新预设 saveAsPreset(name: string): EqualizerPreset { const id = `custom_${Date.now()}`; const currentGains = this.getCurrentGains(); const newPreset: EqualizerPreset = { id: id, name: name, gains: currentGains, isCustom: true }; this._customPresets.push(newPreset); this._currentPresetId = id; this.saveState(); return newPreset; } // 删除自定义预设 deleteCustomPreset(presetId: string): boolean { let index = -1; for (let i = 0; i < this._customPresets.length; i++) { if (this._customPresets[i].id === presetId) { index = i; break; } } if (index >= 0) { this._customPresets.splice(index, 1); if (this._currentPresetId === presetId) { this._currentPresetId = 'normal'; } this.saveState(); return true; } return false; } /** * 应用均衡器到播放器(OHAudioSuite 实时生效) */ applyToPlayer(player: IjkMediaPlayer): void { const gains = this.getCurrentGains(); player.setEqualizerEnabled(this._enabled); player.setEqualizerGains(gains); Logger.info(EqualizerManager.TAG, `均衡器已下发: enabled=${this._enabled}, gains=${JSON.stringify(gains)}`); } /** * 获取预设的显示名称 */ getPresetDisplayName(presetId: string): string { if (presetId === 'custom') { return '自定义'; } const preset = this.getCurrentPreset(); if (preset !== null && preset.id === presetId) { return preset.name; } const allPresets = this.getAllPresets(); for (let i = 0; i < allPresets.length; i++) { if (allPresets[i].id === presetId) { return allPresets[i].name; } } return '自定义'; } }