将音频流转换为频率

Ada*_*ort 6 c# audio naudio

我成功地使用NAudio将音频数据流传输到输出设备(扬声器):

private void OnDataAvailable(object sender, WaveInEventArgs e)
        {
            var buffer = e.Buffer;
            var bytesRecorded = e.BytesRecorded;
            Debug.WriteLine($"Bytes {bytesRecorded}");
Run Code Online (Sandbox Code Playgroud)

并且示例输出:

Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 23040
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Bytes 19200
Run Code Online (Sandbox Code Playgroud)

然后我使用/sf/answers/1429003201/将其转换(FFT)为x和y值:

var buffer = e.Buffer;
            var bytesRecorded = e.BytesRecorded;
            //Debug.WriteLine($"Bytes {bytesRecorded}");
            var bufferIncrement = _waveIn.WaveFormat.BlockAlign;

            for (var index = 0; index < bytesRecorded; index += bufferIncrement)
            {
                var sample32 = BitConverter.ToSingle(buffer, index);
                _sampleAggregator.Add(sample32);
            }
Run Code Online (Sandbox Code Playgroud)

样本输出为:

x: -9.79634E-05, y: -9.212703E-05
x: 6.897306E-05, y: 2.489315E-05
x: 0.0002080683, y: 0.0004317867
x: -0.0001720883, y: -6.681971E-05
x: -0.0001245111, y: 0.0002880402
x: -0.0005751926, y: -0.0002682915
x: -5.280507E-06, y: 7.297558E-05
x: -0.0001143928, y: -0.0001156801
x: 0.0005231025, y: -0.000153206
x: 0.0001011164, y: 7.681748E-05
x: 0.000330695, y: 0.0002293986
Run Code Online (Sandbox Code Playgroud)

不确定这是否可能,或者我只是误解了流返回的内容,但我想获得音频流的频率以便用飞利浦Hue做一些事情.上面的x,y值是在CIE颜色空间中使用的小的方法.我做错了什么,或者我完全误解了OnDataAvailable中缓冲区中的数据是什么?

谢谢!

编辑:

我根据注释和Autotune程序的教程修改了我的OnDataAvailable代码,如下所示:

private void OnDataAvailable(object sender, WaveInEventArgs e)
        {
            var buffer = e.Buffer;
            float sample32 = 0;

            for (var index = buffer.Length > 1024 ? buffer.Length - 1024 : buffer.Length; index < e.BytesRecorded; index += 2)
            {
                var sample = (short) ((buffer[index + 1] << 8) | buffer[index + 0]);
                sample32 = sample / 32768f;
                Debug.WriteLine(sample32);
                LightsController.SetLights(Convert.ToByte(Math.Abs(sample32) * 255));
                _sampleAggregator.Add(sample32);
            }
            var floats = BytesToFloats(buffer);

            if (sample32 != 0.0f)
            {
                var pitchDetect = new FftPitchDetector(sample32);
                var pitch = pitchDetect.DetectPitch(floats, floats.Length);
                Debug.WriteLine($"Pitch {pitch}");
            }
        }
Run Code Online (Sandbox Code Playgroud)

希望我只使用缓冲区中的最后一组元素,因为它似乎并不清楚,我只对最新的可用数据集感兴趣,以获得当前音频的频率.但是,当调用DetectPitch方法时,我仍会偶尔获得索引异常.我哪里错了?我希望用频率来改变色调灯泡的颜色和亮度.

SAC*_*ACn 1

使用

fPeak = SamplingRate * BinNumberOfPeak / FFTLength ;