从阵列中的音频字节获取音高或幅度等信息

Eld*_*lay -2 c# audio fft

我想得到一个字节数组中音频字节的音高.这是我现在的代码:

        byte[] wav = File.ReadAllBytes("test.wav");
        for (int i = 44; i<wav.Length; i++)
        {
            // wav[i] is an audio byte, channel shifts every 2 bytes (I think)
        }
Run Code Online (Sandbox Code Playgroud)

起初我认为wav文件是用数百或数千个块构建的,每个块都包含一个采样率,所以我试图扫描整个数组中的另一个字节序列,代表单词"WAVE",它是一个部分.块,但采样率仅在数组的开头,并且在44位之后,所有数组都只是音频数据本身.
音频字节只是十六进制值,我无法理解如何从该值获取任何信息.

更新:我已经下载了具有FFT算法的Math.NET库.这是FFT的文档:https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm 我已经阅读了所有的方法,但我不知道什么方法会做我想要的(给它几个字节的wav文件并获得它们的频率).

更新2:现在我使用Accord库进行FFT,我在youtube上找到了一个教程.这是我将音频字节转换为双数组的代码:

            for (int i = 44; i<wav.Length; i+=BufferSize)
        {
            float currentSec = (float) audioLength / wav.Length * i;

            byte[] buffer = new byte[BufferSize];

            for (int j = 0; j < buffer.Length; j++)
            {
                if ((i + j + 1) < wav.Length)
                    buffer[j] = wav[i + j];
            }

            int SAMPLE_RESOLUTION = 16;
            int BYTES_PER_POINT = SAMPLE_RESOLUTION / 8;

            Int32[] vals = new Int32[buffer.Length / BYTES_PER_POINT];
            double[] Ys = new double[buffer.Length / BYTES_PER_POINT];
            double[] Ys2 = new double[buffer.Length / BYTES_PER_POINT];

            for (int k = 0; k < Ys.Length; k++)
            {
                byte hByte = buffer[k * 2 + 1];
                byte lByte = buffer[k * 2 + 0];

                vals[k] = (int)(short)((hByte << 8) | lByte);
                Ys[k] = vals[k];
            }
            Ys2 = FFT(Ys);

            double avgFrq = AverageFromArray(Ys2);

            if(lastSecond < (int) currentSec)
                lastSecond = (int) currentSec;

        }
Run Code Online (Sandbox Code Playgroud)

FFT功能:

       private double[] FFT(double[] data)
   {
        double[] fft = new double[data.Length];
        System.Numerics.Complex[] fftComplex = new System.Numerics.Complex[data.Length];
        for (int i = 0; i < data.Length; i++)
        {
            fftComplex[i] = new System.Numerics.Complex(data[i], 0);
        }

        Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
        for (int i = 0; i < data.Length; i++)
        {
            fft[i] = fftComplex[i].Magnitude;
        }

        return fft;
    }
Run Code Online (Sandbox Code Playgroud)

所以要检查它是否有效我制作的wav文件只是5000Hz频率下的白噪声,但这些是我从FFT得到的结果(2048字节数组的值):https: //pastebin.com/PUq5bQTn 整个音频文件具有相同的5000Hz频率,但我的代码给我的值为605.80502914453746和4401.1090268930584

Joh*_*nne 6

我担心你的代码(和问题)过于幼稚.

  1. Wav文件不仅仅是音频样本的集合.有关文件格式及其结构的描述,请查看(例如)http://soundfile.sapp.org/doc/WaveFormat/.

  2. 如果你想阅读,处理,写入音频文件,那里有不同的库(例如NAudio)可以提供很多帮助.

  3. 从音频流中的1个样本中,您永远无法计算音高.为此,您需要(相对较大的)样本数并使用FFT变换计算频谱.