我有以下方法将IMediaSample中的PCM数据收集到FFT的浮点数中:
public int PCMDataCB(IntPtr Buffer, int Length, ref TDSStream Stream, out float[] singleChannel)
{
int numSamples = Length / (Stream.Bits / 8);
int samplesPerChannel = numSamples / Stream.Channels;
float[] samples = new float[numSamples];
if (Stream.Bits == 32 && Stream.Float) {
// this seems to work for 32 bit floating point
byte[] buffer32f = new byte[numSamples * 4];
Marshal.Copy(Buffer, buffer32f, 0, numSamples);
for (int j = 0; j < buffer32f.Length; j+=4)
{
samples[j / 4] = System.BitConverter.ToSingle(new byte[] { buffer32f[j + 0], buffer32f[j + 1], buffer32f[j + 2], buffer32f[j + 3]}, 0);
}
}
else if (Stream.Bits == 24)
{
// I need this code
}
// compress result into one mono channel
float[] result = new float[samplesPerChannel];
for (int i = 0; i < numSamples; i += Stream.Channels)
{
float tmp = 0;
for (int j = 0; j < Stream.Channels; j++)
tmp += samples[i + j] / Stream.Channels;
result[i / Stream.Channels] = tmp;
}
// mono output to be used for visualizations
singleChannel = result;
return 0;
}
似乎可以用于32b浮点数,因为我在频谱分析仪中得到了合理的数据(尽管它似乎过度(或压缩?)到较低的频率)。
我似乎也设法使其适用于8,16和32非浮点数,但是当位数为24时我只能读取垃圾。
如何使用24位PCM进入缓冲区?
缓冲区来自IMediaSample。
我想知道的另一件事是,我使用的方法是通过求和除以通道数来将所有通道添加到一个...
答案 0 :(得分:1)
我明白了:
byte[] buffer24 = new byte[numSamples * 3];
Marshal.Copy(Buffer, buffer24, 0, numSamples * 3);
var window = (float)(255 << 16 | 255 << 8 | 255);
for (int j = 0; j < buffer24.Length; j+=3)
{
samples[j / 3] = (buffer24[j] << 16 | buffer24[j + 1] << 8 | buffer24[j + 2]) / window;
}
从三个字节创建一个整数,然后通过除以三个字节的最大值将其缩放到1 / -1范围内。
答案 1 :(得分:0)
你试过吗
byte[] buffer24f = new byte[numSamples * 3];
Marshal.Copy(Buffer, buffer24f, 0, numSamples);
for (int j = 0; j < buffer24f.Length; j+=3)
{
samples[j / 3] = System.BitConverter.ToSingle(
new byte[] {
0,
buffer24f[j + 0],
buffer24f[j + 1],
buffer24f[j + 2]
}, 0);
}