import os
from pydub import AudioSegment
import numpy as np
import glob

def mp3_to_pcm_c_array(mp3_file_path, output_c_file_path, normalize=True, target_volume=-6.0):
    """
    将MP3文件转换为8kHz, 16bit, 单声道的PCM数据，并生成C语言数组文件
    """
    
    if not os.path.exists(mp3_file_path):
        print(f"错误：文件 '{mp3_file_path}' 不存在！")
        return

    try:
        print(f"正在读取: {mp3_file_path}")
        audio = AudioSegment.from_mp3(mp3_file_path)
        audio = audio.set_channels(1)
        audio = audio.set_frame_rate(8000)
        audio = audio.set_sample_width(2)
        
        if normalize:
            print("正在归一化音量...")
            try:
                current_dbfs = audio.max_dBFS
                gain = target_volume - current_dbfs
                audio = audio.apply_gain(gain)
            except Exception as e:
                samples = np.array(audio.get_array_of_samples())
                max_val = np.max(np.abs(samples))
                if max_val > 0:
                    target_max = 32767 * 10**(target_volume/20)
                    gain = target_max / max_val
                    audio = audio.apply_gain(20*np.log10(gain))
        
        pcm_data = audio.raw_data
        samples = np.frombuffer(pcm_data, dtype=np.int16)
        
        print(f"样本数: {len(samples)}, 数据大小: {len(pcm_data)} 字节")
        
        # 生成数组名（去除扩展名和特殊字符）
        array_name = os.path.splitext(os.path.basename(mp3_file_path))[0]
        for char in ['-', '.', ' ', '(', ')', '[', ']', '#', '，', '。']:
            array_name = array_name.replace(char, '_')
        # 如果数组名以数字开头，加下划线前缀
        if array_name[0].isdigit():
            array_name = '_' + array_name
        
        # ===== 生成 .c 文件 =====
        with open(output_c_file_path, 'w', encoding='utf-8') as f:
            f.write("// ============================================================\n")
            f.write("// 自动生成的音频数据\n")
            f.write("// 采样率: 8000 Hz, 位深: 16bit, 声道: 单声道\n")
            f.write(f"// 来源文件: {os.path.basename(mp3_file_path)}\n")
            f.write(f"// 样本数量: {len(samples)}\n")
            f.write(f"// 数据大小: {len(pcm_data)} 字节\n")
            f.write("// ============================================================\n\n")
            
            f.write(f"int code {array_name}_pcm[{len(samples)}] = {{\n    ")
            
            for i, sample in enumerate(samples):
                if i % 16 == 0 and i > 0:
                    f.write("\n    ")
                f.write(f"{sample:6d}, ")
            
            f.write("\n};\n\n")
            f.write(f"unsigned int code {array_name}_pcm_len = sizeof({array_name}_pcm) / sizeof({array_name}_pcm[0]);\n")
        
        print(f"✅ 生成: {output_c_file_path}")
        
        # ===== 生成 .h 文件 =====
        h_file_path = output_c_file_path.replace('.c', '.h')
        # 从原MP3文件名生成数组名（用于extern声明）
        base_name = os.path.splitext(os.path.basename(mp3_file_path))[0]
        for char in ['-', '.', ' ', '(', ')', '[', ']', '#', '，', '。']:
            base_name = base_name.replace(char, '_')
        if base_name[0].isdigit():
            base_name = '_' + base_name
            
        with open(h_file_path, 'w', encoding='utf-8') as f:
            guard_name = f"_{base_name.upper()}_PCM_H_"
            f.write(f"#ifndef {guard_name}\n")
            f.write(f"#define {guard_name}\n\n")
            
            f.write(f"extern int code {base_name}_pcm[];\n")
            f.write(f"extern unsigned int code {base_name}_pcm_len;\n\n")
            
            f.write(f"#endif /* {guard_name} */\n")
        
        print(f"✅ 生成: {h_file_path}")
        
        # 生成WAV验证文件
        wav_output = os.path.splitext(output_c_file_path)[0] + ".wav"
        audio.export(wav_output, format="wav")
        print(f"✅ 生成验证WAV: {wav_output}\n")
            
    except Exception as e:
        print(f"❌ 转换失败: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    # 批量转换当前目录下所有MP3文件
    mp3_files = glob.glob("*.mp3")
    
    if not mp3_files:
        print("当前目录没有找到MP3文件！")
    else:
        print(f"找到 {len(mp3_files)} 个MP3文件，开始转换...\n")
        for item in mp3_files:
            mp3_to_pcm_c_array(item, f"{item}.c")
        print("🎉 全部转换完成！")