我使用NAudio捕获声音输入,输入显示为包含IeeeFloat格式声音信息的缓冲区。
现在我在缓冲区中有这些数据,我想以不同的采样率将其转换为PCM。
我已经想出如何从IeeeFloat转换为PCM,还可以在单声道和立体声之间进行转换。转换采样率非常困难。
任何解决方案,最好使用NAudio,可以将IeeeFLoat缓冲区转换为选择PCM格式的缓冲区(包括更改采样率)?
答案 0 :(得分:1)
如果要在接收数据时重新采样,则需要执行输入驱动的重采样。我刚才写了an article on this。
NAudio有一些辅助类可以从单声道到立体声,并浮动到PCM,但它们往往在IWaveProvider
或ISampleProvider
输入上运行。通常情况下,如果我只是将样本作为原始字节块,我将使用自己的简单代码编写,从浮点数转换为PCM并将样本加倍。这并不难,WaveBuffer
类允许您直接从byte[]
读取浮动样本。
答案 1 :(得分:1)
我最近不得不这样做,却找不到内置的方法来做,所以我按照Mark所说的去做,手动转换原始数据。下面是对IeeeFloat(32位浮点采样),48000个采样/秒,2个通道到16位短,16000个采样/秒,1个通道进行降采样的代码。
我对某些事情进行了硬编码,因为我的格式是已知的并且是固定的,但是适用相同的原理。
private DownsampleFile()
{
var file = {your file}
using (var reader = new NAudio.Wave.WaveFileReader(file.FullName))
using (var writer = new NAudio.Wave.WaveFileWriter({your output file}, MyWaveFormat))
{
float[] floats;
//a variable to flag the mod 3-ness of the current sample
//we're mapping 48000 --> 16000, so we need to average 3 source
//samples to make 1 output sample
var arity = -1;
var runningSamples = new short[3];
while ((floats = reader.ReadNextSampleFrame()) != null)
{
//simple average to collapse 2 channels into 1
float mono = (float)((double)floaters[0] + (double)floaters[1]) / 2;
//convert (-1, 1) range int to short
short sixteenbit = (short)(mono * 32767);
//the input is 48000Hz and the output is 16000Hz, so we need 1/3rd of the data points
//so save up 3 running samples and then mix and write to the file
arity = (arity + 1) % 3;
runningSamples[arity] = sixteenbit;
//on the third of 3 running samples
if (arity == 2)
{
//simple average of the 3 and put in the 0th position
runningSamples[0] = (short)(((int)runningSamples[0] + (int)runningSamples[1] + (int)runningSamples[2]) / 3);
//write the one 16 bit short to the output
writer.WriteData(runningSamples, 0, 1);
}
}
}
}