package com.zksy.audio.utils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.transform.DftNormalization;
import org.apache.commons.math3.transform.FastFourierTransformer;
import org.apache.commons.math3.transform.TransformType;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class DataParser {
    public static short toInt16(byte[] buffer, boolean isBigEndian) {
        ByteBuffer byteBuffer = ByteBuffer.wrap(buffer)
                .order(isBigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        return byteBuffer.getShort(0); // 第一个声道的数据在索引0处

    }

    public static int calculateRMS(String filePath) {
        try {
            File audioFile = new File(filePath);
            AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
            AudioFormat format = audioStream.getFormat();
            if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED && format.getSampleSizeInBits() != 16) {
                throw new UnsupportedAudioFileException("Only 16-bit PCM signed WAV files are supported.");
            }

            int blockAlign = (format.getSampleSizeInBits() / 8) * format.getChannels();

            int sampleCount = 0;
            double sumOfSquares = 0;
            double sum = 0;

            byte[] rawBuffer = new byte[blockAlign];
            int bytesRead;

            while ((bytesRead = audioStream.read(rawBuffer, 0, rawBuffer.length)) > 0) {

                for (int i = 0; i < bytesRead / blockAlign; i++) {

                    int sample = toInt16(rawBuffer, format.isBigEndian());


                    sum += sample;  // 累加样本值
                    sampleCount++;
                }

            }

            int mean = (int) (sum / sampleCount);

            audioStream.close();
            audioStream = AudioSystem.getAudioInputStream(audioFile);

            sampleCount = 0;
            sumOfSquares = 0;

            // 从样本中减去平均值，计算新的平方和
            while ((bytesRead = audioStream.read(rawBuffer, 0, rawBuffer.length)) > 0) {
                for (int i = 0; i < bytesRead / blockAlign; i++) {
                    int sample = toInt16(rawBuffer, format.isBigEndian());

                    sample -= mean;  // 去掉平均值
                    sumOfSquares += sample * sample;  // 累加平方值
                    sampleCount++;
                }
            }

            // 计算去直流后的 RMS
            int rms = (int) Math.sqrt(sumOfSquares / sampleCount);

            audioStream.close();

            return rms;

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return 0;
    }

    public static short toInt16(byte[] array, int index) {
        return ByteBuffer.wrap(array, index, 2)
                .order(ByteOrder.LITTLE_ENDIAN)
                .getShort();
    }
    public static double calcCenterFrequency(String wavFilePath) {
        int fftSize = 1024;
        double sampleRate = 8192; // 固定采样率
        double centerFrequency = 0;
        try (AudioInputStream audioStream = AudioSystem.getAudioInputStream(new File(wavFilePath))) {
            AudioFormat format = audioStream.getFormat();

            // 验证音频格式
            if (format.getSampleRate() != 8192 || format.getSampleSizeInBits() != 16) {
                throw new IllegalArgumentException("不支持的音频格式: 需要16位/8192Hz");
            }

            byte[] buffer = new byte[fftSize * 2];
            float[] floatBuffer = new float[fftSize];
            Complex[] fftBuffer = new Complex[fftSize];
            double maxMagnitude = 0;
            int maxIndex = 0;


            // 初始化FFT变换器
            FastFourierTransformer fft = new FastFourierTransformer(DftNormalization.STANDARD);

            int bytesRead;
            int counter = 0;
            while ((bytesRead = audioStream.read(buffer)) > 0) {
                if (bytesRead == 2048) {
                    // 将字节转换为浮点数
                    for (int i = 0; i < bytesRead / 2; i++) {
                        //short sample = (short) ((buffer[i * 2 + 1] << 8) | (buffer[i * 2] & 0xFF));
                        short sample = toInt16(buffer, i * 2);
                        floatBuffer[i] = sample / 32768f;
                        fftBuffer[i] = new Complex(floatBuffer[i], 0);
                    }

                    // 执行FFT变换
                    Complex[] fftResult = fft.transform(fftBuffer, TransformType.FORWARD);
                    counter++;

                    // 计算幅度并寻找峰值
                    maxMagnitude = 0;
                    maxIndex = 0;
                    for (int i = 0; i < fftSize / 2; i++) {
                        double magnitude = Math.sqrt(fftResult[i].getReal() * fftResult[i].getReal()
                                + fftResult[i].getImaginary() * fftResult[i].getImaginary());

                        if (i > 0 && magnitude > maxMagnitude) {
                            maxMagnitude = magnitude;
                            maxIndex = i;
                        }
                    }

                    // 计算中心频率
                    double frequencyResolution = sampleRate / fftSize;
                    centerFrequency = maxIndex * frequencyResolution;

                }
            }
        } catch (UnsupportedAudioFileException | IOException e) {
            throw new RuntimeException("音频处理错误", e);
        }
        return centerFrequency;
    }
}