【发布时间】:2017-07-04 13:52:53
【问题描述】:
我已经成功地使用 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://stackoverflow.com/a/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
不确定这是否可能,或者我只是误解了流返回的内容,但我想获取音频流的频率,以便使用 Philips Hue 做一些事情。上面的 x、y 值在 CIE 颜色空间中使用起来太小了。我做错了什么还是我完全误解了 OnDataAvailable 缓冲区中的数据是什么?
谢谢!
编辑:
我已经根据 cmets 和 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 方法时,我仍然偶尔会遇到索引异常。我哪里错了?我希望使用频率来改变色调灯泡的颜色和亮度。
【问题讨论】:
-
你看过这个帖子吗:stackoverflow.com/questions/15009084/… ?
-
@DavidTansey 我没有。将对其进行调查并报告。
-
@DavidTansey 我修改了我的 OnDataAvailable 代码以匹配并将“floats”和“floats.Length”传递给 pitchDetect.DetectPitch 但我在
SmbPitchShift.smbFft(fftBuffer, frames, -1);得到一个索引超出范围异常,如果被注释掉,float real = fftBuffer[bin * 2];。有什么想法吗? -
已修改以匹配什么 - 您是指 OP 在该帖子中显示的代码还是在 Mark Heath 的答案中显示的代码(通过文章链接)?此外,如果您查看 Mark 答案下方的 cmets,您会发现有人遇到了
index out of range问题,Mark 在附加评论中建议了如何解决它。 -
@DavidTansey 两者,它们是相同的代码。从 Mark 的回答来看,SampleAggregator 的目的不是让事情成为 2 的幂,所以我不应该改变我通过音高检测器传递的内容吗?