我已经成功地使用NAudio将音频数据流传输到输出设备(扬声器):
private void OnDataAvailable(object sender, WaveInEventArgs e)
{
var buffer = e.Buffer;
var bytesRecorded = e.BytesRecorded;
Debug.WriteLine($"Bytes {bytesRecorded}");
并且样例输出为:
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
我随后使用https://dev59.com/g3bZa4cB1Zd3GeqPKtzX#20414331将其转换(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);
}
使用样例输出:
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
不确定这是否可能,或者我是否误解了流返回的内容,但我想获取音频流的频率,以便对飞利浦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}");
}
}
希望我只使用缓冲区中的最后一组元素,因为它似乎不会自动清除,并且我只对最新可用的数据集感兴趣,以获取当前音频的频率。但是,当调用DetectPitch方法时,有时仍会出现索引异常。我做错了什么?我希望使用频率来更改色调灯泡的颜色和亮度。
SmbPitchShift.smbFft(fftBuffer,frames,-1);
处得到了一个索引超出范围的异常;如果注释掉,会在float real = fftBuffer [bin * 2];
处得到相同的异常。有什么想法吗? - Adam Short