#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
智能音频处理助手的核心处理模块
包含各种音频处理功能的实现
"""

import os
import time
import traceback
import sys
from typing import Callable, Dict, Any, Optional

# 导入基础模块
try:
    import numpy as np
    NUMPY_AVAILABLE = True
except ImportError:
    NUMPY_AVAILABLE = False
    print("警告: 未能导入numpy模块，部分功能将不可用")
    # 创建一个假的numpy模块，以便在导入失败时仍能继续
    class FakeNumpy:
        def __init__(self):
            pass
        def array(self, *args, **kwargs):
            return []
        def clip(self, *args, **kwargs):
            return []
        def concatenate(self, *args, **kwargs):
            return []
        def zeros(self, *args, **kwargs):
            return []
        def abs(self, *args, **kwargs):
            return []
        def where(self, *args, **kwargs):
            return [], []
    np = FakeNumpy()

# 导入音频处理模块
try:
    import librosa
    import soundfile as sf
    LIBROSA_AVAILABLE = True
except ImportError:
    LIBROSA_AVAILABLE = False
    print("警告: 未能导入librosa或soundfile模块，音频处理功能将不可用")

# 导入深度学习模块
try:
    import torch
    TORCH_AVAILABLE = True
except ImportError:
    TORCH_AVAILABLE = False
    print("警告: 未能导入PyTorch，人声提取功能将使用备用方法")

# 导入语音识别模块
try:
    import whisper
    WHISPER_AVAILABLE = True
except ImportError:
    WHISPER_AVAILABLE = False
    print("警告: 未能导入whisper模块，语音转文字功能将不可用")

# 导入降噪模块
try:
    import noisereduce as nr
    NOISEREDUCE_AVAILABLE = True
except ImportError:
    NOISEREDUCE_AVAILABLE = False
    print("警告: 未能导入noisereduce模块，降噪功能将不可用")

# 基础处理器类
class AudioProcessor:
    """音频处理器基类"""
    
    def __init__(self):
        """初始化处理器"""
        pass
        
    def process(self, 
                input_file: str, 
                output_file: str, 
                params: Dict[str, Any] = None,
                progress_callback: Optional[Callable[[int], None]] = None) -> str:
        """
        处理音频文件
        
        Args:
            input_file: 输入音频文件路径
            output_file: 输出音频文件路径
            params: 处理参数
            progress_callback: 进度回调函数
            
        Returns:
            输出文件路径
        """
        if progress_callback:
            progress_callback(0)
            
        try:
            # 检查librosa是否可用
            if not LIBROSA_AVAILABLE:
                raise ImportError("缺少librosa或soundfile模块，无法处理音频")
                
            # 检查numpy是否可用
            if not NUMPY_AVAILABLE:
                raise ImportError("缺少numpy模块，无法处理音频")
                
            # 加载音频
            self._update_progress(progress_callback, 10)
            y, sr = self._load_audio(input_file)
            
            # 处理音频
            self._update_progress(progress_callback, 30)
            y_processed = self._process_audio(y, sr, params or {})
            
            # 保存音频
            self._update_progress(progress_callback, 80)
            self._save_audio(y_processed, sr, output_file)
            
            self._update_progress(progress_callback, 100)
            return output_file
        except Exception as e:
            print(f"处理音频时出错: {str(e)}")
            traceback.print_exc()
            raise
    
    def _load_audio(self, file_path: str) -> tuple:
        """加载音频文件"""
        if not os.path.exists(file_path):
            raise FileNotFoundError(f"找不到音频文件: {file_path}")
            
        return librosa.load(file_path, sr=None)
    
    def _save_audio(self, y: np.ndarray, sr: int, file_path: str) -> None:
        """保存音频文件"""
        # 确保输出目录存在
        output_dir = os.path.dirname(file_path)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)
            
        sf.write(file_path, y, sr)
    
    def _process_audio(self, y: np.ndarray, sr: int, params: Dict[str, Any]) -> np.ndarray:
        """
        处理音频数据
        
        子类必须重写此方法
        """
        raise NotImplementedError("子类必须实现此方法")
    
    def _update_progress(self, 
                         progress_callback: Optional[Callable[[int], None]], 
                         value: int) -> None:
        """更新进度"""
        if progress_callback:
            progress_callback(value)
            time.sleep(0.01)  # 避免UI卡死

# 音量增强处理器
class VolumeEnhancer(AudioProcessor):
    """音量增强处理器"""
    
    def _process_audio(self, y: np.ndarray, sr: int, params: Dict[str, Any]) -> np.ndarray:
        """增强音频音量"""
        gain = params.get('gain', 1.5)  # 默认增益为1.5
        return np.clip(y * gain, -1.0, 1.0)  # 放大并限制在[-1, 1]范围内

# 语音转文字处理器
class SpeechToText(AudioProcessor):
    """语音转文字处理器"""
    
    def __init__(self):
        super().__init__()
        self.model = None
        
    def _load_model(self):
        """懒加载Whisper模型"""
        if not WHISPER_AVAILABLE:
            raise ImportError("缺少whisper模块，无法执行语音转文字功能。请安装：pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper")
            
        if self.model is None:
            try:
                # 使用小模型以平衡速度和准确性
                self.model = whisper.load_model("base")
            except Exception as e:
                raise ImportError(f"加载Whisper模型失败: {str(e)}. 可能需要安装额外的依赖，请运行: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper")
    
    def process(self, 
                input_file: str, 
                output_file: str, 
                params: Dict[str, Any] = None,
                progress_callback: Optional[Callable[[int], None]] = None) -> str:
        """处理音频文件并生成文本转录"""
        if progress_callback:
            progress_callback(0)
        
        try:
            # 检查输入文件是否存在
            if not os.path.exists(input_file):
                raise FileNotFoundError(f"找不到输入文件: {input_file}")
            
            # 检查是否可以使用whisper或备用方法
            use_backup_method = not WHISPER_AVAILABLE
            
            if not use_backup_method:
                # 尝试使用Whisper进行转录
                try:
                    self._update_progress(progress_callback, 10)
                    self._load_model()
                    
                    # 设置语言
                    self._update_progress(progress_callback, 20)
                    language = params.get('language', '自动检测')
                    language_code = None
                    if language == '中文':
                        language_code = 'zh'
                    elif language == '英语':
                        language_code = 'en'
                    
                    # 识别
                    self._update_progress(progress_callback, 30)
                    options = {}
                    if language_code:
                        options['language'] = language_code
                    
                    # 使用librosa直接加载音频而不依赖ffmpeg
                    print("使用librosa直接加载音频...")
                    # 使用librosa加载音频并重采样到16kHz (whisper期望的速率)
                    audio, sr = librosa.load(input_file, sr=16000, mono=True)
                    
                    # 转换为浮点数数组
                    audio = audio.astype(np.float32)
                    
                    # 确保音频长度适合模型
                    if len(audio) == 0:
                        raise ValueError("音频文件为空或无法读取")
                    
                    print(f"音频加载成功，长度: {len(audio)/16000:.2f}秒，采样率: 16000Hz")
                    self._update_progress(progress_callback, 40)
                    
                    # 运行模型
                    print(f"转录音频 (语言: {language})...")
                    result = self.model.transcribe(audio, **options)
                    print("转录完成!")
                    
                    # 生成文本文件
                    self._update_progress(progress_callback, 80)
                    with open(output_file, 'w', encoding='utf-8') as f:
                        f.write(result["text"])
                    
                    # 生成带时间戳的字幕文件
                    srt_file = output_file.replace('.txt', '.srt')
                    self._generate_srt(result["segments"], srt_file)
                    
                    self._update_progress(progress_callback, 100)
                    return output_file
                
                except Exception as e:
                    print(f"Whisper转录失败: {str(e)}")
                    print("尝试使用备用方法...")
                    use_backup_method = True
            
            # 备用方法：使用simple_audio_info.py分析音频
            if use_backup_method:
                print("使用备用方法分析音频...")
                self._update_progress(progress_callback, 30)
                
                try:
                    # 尝试加载并使用simple_audio_info.py
                    try:
                        # 如果simple_audio_info.py在同一目录下
                        current_dir = os.path.dirname(os.path.abspath(__file__))
                        sys.path.append(current_dir)
                        
                        try:
                            import simple_audio_info
                            print("使用simple_audio_info模块分析音频...")
                            self._update_progress(progress_callback, 40)
                            
                            # 调用simple_audio_info分析音频
                            result = simple_audio_info.analyze_audio(input_file, output_file)
                            if result:
                                self._update_progress(progress_callback, 100)
                                return output_file
                        except ImportError:
                            print("未找到simple_audio_info模块，使用内置方法...")
                    except:
                        print("加载simple_audio_info失败，使用内置方法...")
                    
                    # 内置备用方法：使用wave模块分析
                    self._update_progress(progress_callback, 50)
                    
                    try:
                        # 如果输入文件是WAV格式
                        import wave
                        import codecs
                        
                        with wave.open(input_file, 'rb') as wav_file:
                            # 获取基本信息
                            channels = wav_file.getnchannels()
                            sample_width = wav_file.getsampwidth()
                            frame_rate = wav_file.getframerate()
                            n_frames = wav_file.getnframes()
                            duration = n_frames / frame_rate
                            
                            file_size = os.path.getsize(input_file)
                            
                            # 生成报告文件
                            with codecs.open(output_file, 'w', encoding='utf-8-sig') as f:
                                f.write("音频文件分析报告\n")
                                f.write("==============\n\n")
                                f.write(f"文件名: {os.path.basename(input_file)}\n")
                                f.write(f"文件大小: {file_size / 1024:.2f} KB\n")
                                f.write(f"通道数: {channels}\n")
                                f.write(f"采样宽度: {sample_width * 8} 位\n")
                                f.write(f"采样率: {frame_rate} Hz\n")
                                f.write(f"总帧数: {n_frames}\n")
                                f.write(f"时长: {duration:.2f} 秒\n\n")
                                
                                f.write("音频质量评估：\n")
                                if frame_rate >= 44100 and sample_width >= 2:
                                    f.write("- 音频质量评级: 高质量 (CD级别或更高)\n")
                                elif frame_rate >= 22050 and sample_width >= 2:
                                    f.write("- 音频质量评级: 中等质量 (适合语音)\n")
                                else:
                                    f.write("- 音频质量评级: 低质量\n")
                                    
                                # 添加备注
                                f.write("\n备注: 此分析仅提供音频的基本信息，不含实际的语音转文字功能。\n")
                                f.write("如需使用完整的语音转文字功能，请安装以下依赖:\n")
                                f.write("1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper\n")
                                f.write("2. 安装ffmpeg并设置系统环境变量\n")
                    except:
                        # 如果不是WAV格式或者出现其他错误，则尝试使用基本的文件信息
                        with codecs.open(output_file, 'w', encoding='utf-8-sig') as f:
                            f.write("音频文件基本信息\n")
                            f.write("==============\n\n")
                            f.write(f"文件名: {os.path.basename(input_file)}\n")
                            f.write(f"文件大小: {os.path.getsize(input_file) / 1024:.2f} KB\n")
                            f.write(f"修改时间: {time.ctime(os.path.getmtime(input_file))}\n\n")
                            
                            f.write("\n备注: 无法分析此音频文件的详细信息。\n")
                            f.write("如需使用完整的语音转文字功能，请安装以下依赖:\n")
                            f.write("1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper\n")
                            f.write("2. 安装ffmpeg并设置系统环境变量\n")
                except Exception as e:
                    print(f"备用分析方法失败: {str(e)}")
                    # 确保生成基本报告
                    with open(output_file, 'w', encoding='utf-8') as f:
                        f.write(f"分析失败: {str(e)}\n\n")
                        f.write("语音转文字功能需要安装以下依赖：\n")
                        f.write("1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper\n")
                        f.write("2. 下载并安装ffmpeg: https://ffmpeg.org/download.html\n")
                
                self._update_progress(progress_callback, 100)
                return output_file
        
        except Exception as e:
            print(f"转换语音为文本时出错: {str(e)}")
            traceback.print_exc()
            
            # 确保即使出错也生成一个结果文件
            try:
                with open(output_file, 'w', encoding='utf-8') as f:
                    f.write(f"转录失败: {str(e)}\n")
                    f.write("语音转文字功能需要安装以下依赖：\n")
                    f.write("1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openai-whisper\n")
                    f.write("2. 下载并安装ffmpeg: https://ffmpeg.org/download.html\n")
                    f.write("3. 确保ffmpeg在系统PATH中\n")
            except:
                pass
                
            raise
    
    def _generate_srt(self, segments, output_file):
        """生成SRT字幕文件"""
        try:
            with open(output_file, 'w', encoding='utf-8') as f:
                for i, segment in enumerate(segments):
                    # 将时间戳从秒转换为SRT格式 (HH:MM:SS,mmm)
                    start = self._format_timestamp(segment['start'])
                    end = self._format_timestamp(segment['end'])
                    
                    # 写入字幕条目
                    f.write(f"{i+1}\n")
                    f.write(f"{start} --> {end}\n")
                    f.write(f"{segment['text'].strip()}\n\n")
            print(f"字幕文件已生成: {output_file}")
        except Exception as e:
            print(f"生成字幕文件失败: {str(e)}")
    
    def _format_timestamp(self, seconds):
        """将秒数转换为SRT时间戳格式"""
        hours = int(seconds / 3600)
        minutes = int((seconds % 3600) / 60)
        secs = int(seconds % 60)
        millis = int((seconds - int(seconds)) * 1000)
        return f"{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}"

# 音频降噪处理器
class NoiseReducer(AudioProcessor):
    """音频降噪处理器"""
    
    def _process_audio(self, y: np.ndarray, sr: int, params: Dict[str, Any]) -> np.ndarray:
        """降噪处理"""
        if not NOISEREDUCE_AVAILABLE:
            raise ImportError("缺少noisereduce模块，无法执行音频降噪功能")
            
        strength = params.get('strength', '中')
        
        # 根据强度设置降噪参数
        prop_decrease = 0.5  # 默认值 (中)
        if strength == '低':
            prop_decrease = 0.3
        elif strength == '高':
            prop_decrease = 0.7
        
        # 使用noisereduce库执行降噪处理
        return nr.reduce_noise(
            y=y, 
            sr=sr,
            prop_decrease=prop_decrease,
            stationary=False
        )

# 人声提取处理器
class VoiceExtractor(AudioProcessor):
    """人声提取处理器"""
    
    def __init__(self):
        super().__init__()
        self.model = None
        self.model_type = None
    
    def _load_model(self):
        """加载模型或设置为备用算法"""
        if not TORCH_AVAILABLE:
            self.model = None
            self.model_type = "fallback"
            print("警告: 未能导入PyTorch，将使用备用方法提取人声")
            return
            
        if self.model is None:
            try:
                # 在没有加载模型的情况下设置备用方法
                self.model_type = "fallback"
                
                # 如果PyTorch可用，但没有安装特定依赖，仍使用备用算法
                print("使用基于频谱的人声提取方法")
            except Exception as e:
                print(f"初始化人声提取器时出错: {str(e)}")
                self.model_type = "fallback"
    
    def process(self, 
                input_file: str, 
                output_file: str, 
                params: Dict[str, Any] = None,
                progress_callback: Optional[Callable[[int], None]] = None) -> str:
        """执行人声提取处理，所有情况下使用备用方法"""
        if progress_callback:
            progress_callback(0)
        
        try:
            # 检查基本依赖
            if not LIBROSA_AVAILABLE:
                raise ImportError("缺少librosa模块，无法执行人声提取功能")
                
            # 加载音频
            self._update_progress(progress_callback, 10)
            y, sr = self._load_audio(input_file)
            
            # 提取人声
            self._update_progress(progress_callback, 20)
            
            # 初始化模型（将使用备用算法）
            if self.model_type is None:
                self._load_model()
                
            # 使用备用方法处理
            print("使用备用方法进行人声提取...")
            self._update_progress(progress_callback, 40)
            y_processed = self._fallback_separation(y, sr, params)
            
            # 保存音频
            self._update_progress(progress_callback, 90)
            self._save_audio(y_processed, sr, output_file)
            
            self._update_progress(progress_callback, 100)
            return output_file
        except Exception as e:
            print(f"提取人声时出错: {str(e)}")
            traceback.print_exc()
            raise
    
    def _fallback_separation(self, y: np.ndarray, sr: int, params: Dict[str, Any]) -> np.ndarray:
        """备用的语音分离算法，使用频谱处理方法"""
        try:
            print("正在使用频谱特性分离人声...")
            # 应用谐波-打击乐分离
            print("1. 执行谐波-打击乐分离")
            y_harmonic, y_percussive = librosa.effects.hpss(y)
            
            # 人声通常在中频范围，进行滤波处理
            print("2. 应用人声频率范围滤波")
            
            # 使用带通滤波器突出人声频率范围(80Hz-4000Hz)
            nyquist = sr / 2
            filter_order = 4
            low_cutoff = 80 / nyquist
            high_cutoff = 4000 / nyquist
            
            # 尝试使用SciPy滤波
            try:
                from scipy.signal import butter, sosfilt
                print("3. 使用SciPy带通滤波")
                sos = butter(filter_order, [low_cutoff, high_cutoff], btype='band', output='sos')
                y_vocals = sosfilt(sos, y_harmonic)
            except ImportError:
                # 如果scipy不可用，使用简单的谐波提取
                print("3. SciPy不可用，直接使用谐波分量")
                y_vocals = y_harmonic
            
            # 尝试使用MFCC增强
            try:
                print("4. 增强人声特征")
                # 提取MFCC特征
                mfccs = librosa.feature.mfcc(y=y_vocals, sr=sr, n_mfcc=13)
                
                # 增强低阶MFCC(对应于声音的基频和音色)
                mfccs[:2, :] *= 1.5
                
                # 应用轻微平滑
                y_vocals = librosa.util.normalize(y_vocals)
            except Exception as e:
                print(f"MFCC增强失败: {e}")
            
            # 应用额外的降噪
            if NOISEREDUCE_AVAILABLE:
                print("5. 应用轻度降噪处理")
                level = params.get('level', 3)
                # 根据用户选择的级别调整降噪强度
                decrease = 0.3
                if level > 3:
                    decrease = 0.4
                elif level < 3:
                    decrease = 0.2
                
                y_vocals = nr.reduce_noise(y=y_vocals, sr=sr, prop_decrease=decrease)
            
            # 应用音量增强
            print("6. 调整最终音量")
            level = params.get('level', 3) 
            gain = 1.0 + (level - 1) * 0.2  # 根据level参数(1-5)设置增益
            y_vocals = np.clip(y_vocals * gain, -1.0, 1.0)
            
            print("人声提取完成")
            return y_vocals
        except Exception as e:
            print(f"备用人声提取方法失败: {str(e)}")
            # 如果备用方法失败，返回原始音频
            print("返回原始音频")
            return y

# 音频修复处理器
class AudioRestorer(AudioProcessor):
    """音频修复处理器 - 改进版
    
    提供三个级别的音频修复功能：
    - 轻度：基础降噪和均衡化，适合质量较好但有轻微问题的音频
    - 中度：中等强度的处理，包括动态范围压缩、自适应均衡化和谐波增强
    - 深度：强力处理，结合多种技术，适合严重模糊或损坏的音频
    """
    
    def _process_audio(self, y: np.ndarray, sr: int, params: Dict[str, Any]) -> np.ndarray:
        """根据用户选择的强度级别修复音频质量"""
        intensity = params.get('intensity', '中度')
        
        # 打印处理信息
        print(f"开始音频修复 (强度: {intensity})...")
        
        # 根据强度设置修复参数
        if intensity == '轻度':
            return self._light_restoration(y, sr)
        elif intensity == '深度':
            return self._deep_restoration(y, sr)
        else:  # 中度
            return self._medium_restoration(y, sr)
    
    def _light_restoration(self, y: np.ndarray, sr: int) -> np.ndarray:
        """轻度修复 - 适合质量尚可但需要轻微增强的音频"""
        print("执行轻度音频修复...")
        
        # 步骤1: 轻度降噪
        if NOISEREDUCE_AVAILABLE:
            print("1. 应用轻度降噪")
            y = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.2, stationary=False)
        
        # 步骤2: 轻度谐波增强
        print("2. 增强谐波")
        y = self._enhance_harmonics(y, sr, strength=0.3)
        
        # 步骤3: 轻度均衡化 - 轻微增强中频以提高清晰度
        print("3. 应用轻度均衡化")
        y = self._apply_basic_eq(y, sr, mid_boost=1.2)
        
        # 步骤4: 归一化
        print("4. 归一化音量")
        y = librosa.util.normalize(y)
        
        print("轻度修复完成")
        return y
    
    def _medium_restoration(self, y: np.ndarray, sr: int) -> np.ndarray:
        """中度修复 - 适合有明显问题但细节仍可辨识的音频"""
        print("执行中度音频修复...")
        
        # 步骤1: 中等强度降噪
        if NOISEREDUCE_AVAILABLE:
            print("1. 应用中度降噪")
            y = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.4, stationary=False)
        
        # 步骤2: 波形整形 - 削波剪裁修复
        print("2. 修复波形失真")
        y = np.clip(y, -0.98, 0.98)
        
        # 步骤3: 动态范围压缩 - 使弱声音更加突出
        print("3. 应用动态范围压缩")
        threshold = 0.3
        ratio = 2.0
        y = self._compress_dynamic_range(y, threshold, ratio)
        
        # 步骤4: 谐波增强 - 增加细节
        print("4. 增强谐波")
        y = self._enhance_harmonics(y, sr, strength=0.5)
        
        # 步骤5: 自适应均衡化 - 增强语音区域的频率
        print("5. 应用自适应均衡")
        y = self._adaptive_eq(y, sr)
        
        # 步骤6: 共振峰增强 - 提高清晰度
        print("6. 增强共振峰")
        y = self._enhance_formants(y, sr, strength=0.4)
        
        # 步骤7: 归一化
        print("7. 归一化音量")
        y = librosa.util.normalize(y)
        
        print("中度修复完成")
        return y
    
    def _deep_restoration(self, y: np.ndarray, sr: int) -> np.ndarray:
        """深度修复 - 适合严重模糊或受损的音频"""
        print("执行深度音频修复...")
        
        # 步骤1: 强力降噪
        if NOISEREDUCE_AVAILABLE:
            print("1. 应用强力降噪")
            # 先执行一次标准降噪
            y = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.6, stationary=False)
            # 再执行一次针对残留噪声的降噪
            y = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.3, stationary=True)
        
        # 步骤2: 波形重建和去除削波
        print("2. 修复波形失真")
        y = np.clip(y, -0.95, 0.95)
        
        # 步骤3: 谐波重建 - 恢复谐波结构
        print("3. 增强谐波结构")
        y = self._enhance_harmonics(y, sr, strength=0.7)
        
        # 步骤4: 频谱修复 - 恢复丢失的频率
        print("4. 频谱修复")
        y = self._spectral_restoration(y, sr)
        
        # 步骤5: 强力动态范围处理 - 使弱信号明显
        print("5. 动态范围处理")
        threshold = 0.2
        ratio = 3.0
        y = self._compress_dynamic_range(y, threshold, ratio)
        
        # 步骤6: 频谱掩蔽去噪 - 降低噪声同时保留信号
        print("6. 频谱掩蔽去噪")
        y = self._spectral_masking(y, sr)
        
        # 步骤7: 共振峰增强 - 大幅提高清晰度
        print("7. 强化共振峰")
        y = self._enhance_formants(y, sr, strength=0.8)
        
        # 步骤8: 增强中高频 - 提高清晰度
        print("8. 增强中高频")
        y = self._enhance_mid_high_freq(y, sr, boost_factor=1.8)
        
        # 步骤9: 自适应锐化 - 增强边缘和瞬态
        print("9. 应用自适应锐化")
        y = self._adaptive_sharpening(y, sr)
        
        # 步骤10: 最终归一化和限制
        print("10. 最终处理")
        y = librosa.util.normalize(y)
        y = np.clip(y, -0.99, 0.99)
        
        print("深度修复完成")
        return y
    
    def _compress_dynamic_range(self, y: np.ndarray, threshold: float, ratio: float) -> np.ndarray:
        """动态范围压缩 - 使较弱的声音更加突出"""
        # 简单的动态范围压缩实现
        mask = np.abs(y) > threshold
        y_compressed = y.copy()
        y_compressed[mask] = threshold + (y_compressed[mask] - threshold) / ratio
        
        # 对压缩后的音频进行归一化处理
        return librosa.util.normalize(y_compressed)
    
    def _enhance_harmonics(self, y: np.ndarray, sr: int, strength: float = 0.5) -> np.ndarray:
        """增强谐波结构，提高音频清晰度"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 提取谐波和打击乐部分
            y_harmonic, y_percussive = librosa.effects.hpss(y)
            
            # 增强谐波部分
            y_harmonic_enhanced = y_harmonic * (1.0 + strength)
            
            # 混合回原始信号
            y_enhanced = y_percussive + y_harmonic_enhanced
            
            # 归一化以避免削波
            return librosa.util.normalize(y_enhanced)
        except Exception as e:
            print(f"谐波增强失败: {str(e)}")
            return y
    
    def _apply_basic_eq(self, y: np.ndarray, sr: int, mid_boost: float = 1.2) -> np.ndarray:
        """应用基本均衡，增强语音频率区域"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 转换到频域
            D = librosa.stft(y)
            
            # 获取幅度和相位
            magnitude, phase = librosa.magphase(D)
            
            # 获取频率索引
            freqs = librosa.fft_frequencies(sr=sr)
            
            # 增强语音频率 (中频，通常在300Hz-3kHz范围)
            speech_mask = (freqs > 300) & (freqs < 3000)
            idx_to_boost = np.where(speech_mask)[0]
            magnitude[idx_to_boost, :] *= mid_boost
            
            # 重建信号
            D_enhanced = magnitude * np.exp(1.j * np.angle(D))
            y_enhanced = librosa.istft(D_enhanced, length=len(y))
            
            return y_enhanced
        except Exception as e:
            print(f"均衡化失败: {str(e)}")
            return y
    
    def _adaptive_eq(self, y: np.ndarray, sr: int) -> np.ndarray:
        """自适应均衡，基于音频内容智能调整频率响应"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 计算频谱中心点，了解音频频率分布
            spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=sr)[0]
            avg_centroid = np.mean(spectral_centroid)
            
            # 基于频谱中心调整均衡策略
            D = librosa.stft(y)
            magnitude, phase = librosa.magphase(D)
            freqs = librosa.fft_frequencies(sr=sr)
            
            # 如果频谱中心较低，增强高频
            if avg_centroid < 1000:
                high_mask = freqs > 2000
                idx_high = np.where(high_mask)[0]
                magnitude[idx_high, :] *= 1.4
                print("  - 检测到低频偏重，增强高频")
            
            # 如果频谱中心较高，增强低频
            elif avg_centroid > 3000:
                low_mask = (freqs > 250) & (freqs < 1000)
                idx_low = np.where(low_mask)[0]
                magnitude[idx_low, :] *= 1.3
                print("  - 检测到高频偏重，增强低频")
            
            # 默认情况下，增强语音关键频率
            else:
                mid_mask = (freqs > 500) & (freqs < 2500)
                idx_mid = np.where(mid_mask)[0]
                magnitude[idx_mid, :] *= 1.25
                print("  - 增强语音关键频率")
            
            # 重建信号
            D_enhanced = magnitude * np.exp(1.j * np.angle(D))
            y_enhanced = librosa.istft(D_enhanced, length=len(y))
            
            return y_enhanced
        except Exception as e:
            print(f"自适应均衡失败: {str(e)}")
            return y
    
    def _enhance_formants(self, y: np.ndarray, sr: int, strength: float = 0.5) -> np.ndarray:
        """增强共振峰，提高语音清晰度"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 计算线性预测系数 (LPC) - 用于共振峰分析
            try:
                from scipy.signal import lfilter
                
                # 分帧处理以计算LPC
                frame_length = 2048
                hop_length = 512
                
                # 创建结果数组
                y_enhanced = np.zeros_like(y)
                
                # 分帧处理
                for i in range(0, len(y) - frame_length, hop_length):
                    # 提取帧
                    frame = y[i:i+frame_length]
                    
                    # 应用窗函数
                    frame = frame * np.hamming(len(frame))
                    
                    # 实现简单的共振峰增强 - 使用频域改变共振峰区域
                    frame_fft = np.fft.rfft(frame)
                    frame_mag = np.abs(frame_fft)
                    frame_phase = np.angle(frame_fft)
                    
                    # 查找峰值 (简单的局部最大值检测)
                    peaks = []
                    for j in range(1, len(frame_mag) - 1):
                        if frame_mag[j] > frame_mag[j-1] and frame_mag[j] > frame_mag[j+1]:
                            peaks.append(j)
                    
                    # 增强峰值
                    for peak in peaks:
                        # 只增强至少达到平均幅度的峰值
                        if frame_mag[peak] > np.mean(frame_mag):
                            frame_mag[peak] *= (1.0 + strength)
                    
                    # 重建信号
                    frame_enhanced_fft = frame_mag * np.exp(1.j * frame_phase)
                    frame_enhanced = np.fft.irfft(frame_enhanced_fft)
                    
                    # 重叠相加
                    y_enhanced[i:i+frame_length] += frame_enhanced * np.hamming(len(frame_enhanced))
                
                # 归一化结果
                y_enhanced = librosa.util.normalize(y_enhanced)
                return y_enhanced
                
            except ImportError or Exception as e:
                print(f"  LPC分析不可用, 使用简化方法: {str(e)}")
                
                # 使用简化的频域调整方法
                D = librosa.stft(y)
                magnitude, phase = librosa.magphase(D)
                
                # 对频域进行平滑，保留峰值
                smooth_mag = np.copy(magnitude)
                for i in range(1, magnitude.shape[0]-1):
                    smooth_mag[i] = (magnitude[i-1] + magnitude[i] + magnitude[i+1]) / 3
                
                # 计算原始幅度与平滑版的比值，识别峰值
                ratio = magnitude / (smooth_mag + 1e-10)
                
                # 增强比值大于1的部分(峰值)
                peak_mask = ratio > 1.0
                magnitude[peak_mask] = magnitude[peak_mask] * (1.0 + strength * (ratio[peak_mask] - 1.0))
                
                # 重建信号
                D_enhanced = magnitude * np.exp(1.j * np.angle(D))
                y_enhanced = librosa.istft(D_enhanced, length=len(y))
                
                return y_enhanced
                
        except Exception as e:
            print(f"共振峰增强失败: {str(e)}")
            return y
    
    def _spectral_restoration(self, y: np.ndarray, sr: int) -> np.ndarray:
        """频谱修复，修复或补偿丢失的频率"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 计算频谱
            D = librosa.stft(y)
            magnitude, phase = librosa.magphase(D)
            
            # 计算频率掩码，检测"缺失"的频率区域
            mean_magnitudes = np.mean(magnitude, axis=1)
            
            # 计算移动平均以检测下降的区域
            window_size = 5
            smoothed = np.zeros_like(mean_magnitudes)
            for i in range(len(mean_magnitudes)):
                start = max(0, i - window_size // 2)
                end = min(len(mean_magnitudes), i + window_size // 2 + 1)
                smoothed[i] = np.mean(mean_magnitudes[start:end])
            
            # 找到明显低于周围频率的区域
            ratio = mean_magnitudes / (smoothed + 1e-10)
            holes = ratio < 0.7
            
            # 修复这些区域
            for i in range(len(holes)):
                if holes[i]:
                    # 找到最近的非洞区域作为参考
                    left = i - 1
                    while left >= 0 and holes[left]:
                        left -= 1
                    
                    right = i + 1
                    while right < len(holes) and holes[right]:
                        right += 1
                    
                    # 如果找到了参考，进行修复
                    if left >= 0 and right < len(holes):
                        # 使用线性插值
                        for j in range(magnitude.shape[1]):
                            left_val = magnitude[left, j]
                            right_val = magnitude[right, j]
                            magnitude[i, j] = left_val + (right_val - left_val) * (i - left) / (right - left)
            
            # 重建信号
            D_restored = magnitude * np.exp(1.j * np.angle(D))
            y_restored = librosa.istft(D_restored, length=len(y))
            
            return y_restored
        except Exception as e:
            print(f"频谱修复失败: {str(e)}")
            return y
    
    def _spectral_masking(self, y: np.ndarray, sr: int) -> np.ndarray:
        """频谱掩蔽去噪，保留信号同时去除噪声"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 转换到频域
            D = librosa.stft(y)
            magnitude, phase = librosa.magphase(D)
            
            # 估计噪声水平 (使用静默区域或信号最小值)
            noise_floor = np.percentile(magnitude, 15, axis=1, keepdims=True)
            
            # 计算信噪比
            snr = magnitude / (noise_floor + 1e-10)
            
            # 计算掩蔽因子 (软阈值)
            mask = 1.0 - np.exp(-snr + 2)  # 指数函数用于平滑过渡
            mask = np.clip(mask, 0.1, 1.0)  # 限制最小值，保留部分信号
            
            # 应用掩蔽
            magnitude_clean = magnitude * mask
            
            # 重建信号
            D_clean = magnitude_clean * np.exp(1.j * np.angle(D))
            y_clean = librosa.istft(D_clean, length=len(y))
            
            return y_clean
        except Exception as e:
            print(f"频谱掩蔽去噪失败: {str(e)}")
            return y
    
    def _enhance_mid_high_freq(self, y: np.ndarray, sr: int, boost_factor: float = 1.5) -> np.ndarray:
        """增强中高频范围，提高清晰度"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 使用FFT分解频域
            D = librosa.stft(y)
            
            # 获取频率和幅度
            magnitude, phase = librosa.magphase(D)
            
            # 获取频率索引
            freqs = librosa.fft_frequencies(sr=sr)
            
            # 定义中高频范围，并创建平滑的提升曲线
            # 语音主要清晰度在1kHz-8kHz
            low_mid = 1000
            high_mid = 8000
            
            # 创建平滑的提升曲线，避免突变
            boost_curve = np.ones(len(freqs))
            
            # 低于1kHz的不变
            boost_curve[freqs < low_mid] = 1.0
            
            # 1kHz-8kHz的提升
            mask = (freqs >= low_mid) & (freqs <= high_mid)
            normalized_pos = (freqs[mask] - low_mid) / (high_mid - low_mid)
            # 用正弦曲线创建平滑的钟形提升曲线
            boost_curve[mask] = 1.0 + (boost_factor - 1.0) * np.sin(normalized_pos * np.pi)
            
            # 高于8kHz的逐渐减弱提升
            mask = freqs > high_mid
            normalized_pos = (freqs[mask] - high_mid) / (sr/2 - high_mid)
            boost_curve[mask] = boost_factor * (1.0 - normalized_pos)
            
            # 确保不会低于1.0
            boost_curve = np.maximum(boost_curve, 1.0)
            
            # 对每个频率应用提升
            for i in range(len(freqs)):
                magnitude[i, :] *= boost_curve[i]
            
            # 重建信号
            D_modified = magnitude * np.exp(1.j * np.angle(D))
            y_modified = librosa.istft(D_modified)
            
            # 如果处理改变了长度，则调整为原始长度
            if len(y_modified) > len(y):
                y_modified = y_modified[:len(y)]
            elif len(y_modified) < len(y):
                padding = np.zeros(len(y) - len(y_modified))
                y_modified = np.concatenate((y_modified, padding))
            
            # 规范化以避免爆音
            return librosa.util.normalize(y_modified)
        except Exception as e:
            print(f"中高频增强处理错误: {str(e)}")
            return y
            
    def _adaptive_sharpening(self, y: np.ndarray, sr: int) -> np.ndarray:
        """自适应锐化，增强瞬态和边缘，使声音更清晰"""
        if not LIBROSA_AVAILABLE:
            return y
            
        try:
            # 计算原始信号的导数(差分)来检测瞬态
            diff = np.diff(y, prepend=y[0])
            
            # 标准化差分信号
            diff_norm = np.abs(diff) / (np.max(np.abs(diff)) + 1e-10)
            
            # 创建自适应锐化掩码
            sharpening_mask = diff_norm
            
            # 应用锐化（通过强调导数部分）
            y_sharp = y + 0.3 * diff * sharpening_mask
            
            # 归一化结果
            return librosa.util.normalize(y_sharp)
        except Exception as e:
            print(f"自适应锐化失败: {str(e)}")
            return y 