16 位音频的 fftw :: 峰值在 2f 处出现错误
fftw of 16bit Audio :: peak appearing wrong at 2f
我正在使用端口音频在我的 PC 上(介于 -1 和 +1 之间)获取 32 位浮点音频 (44.1Khz),并使用 fftw 获取它的 fft。
现在我需要获取 16 位 int 音频并获取其 fft。我已将音频样本转换为在 -1 和 +1 之间浮动。 fft 有效,但峰值出现在其应有频率的 2 倍处,因此最大频率分辨率也降低了。因此,对于 44KHz,我可以看到的最大分量约为 10KHz,而 32 位 int/float.
约为 20KHz
例如,如果我将 10KHz 信号从 Sign 发生器提供给声卡,峰值现在显示为 20KHz。而我唯一改变的是格式从 paInt32 到 paInt16。它适用于 paInt32 格式。
outputStreamParam.channelCount = 1;
outputStreamParam.device = Pa_GetDefaultOutputDevice();
outputStreamParam.sampleFormat = paInt16;
outputStreamParam.suggestedLatency = suggestedLatency;
outputStreamParam.hostApiSpecificStreamInfo = NULL;
inputStreamParam.channelCount = 1;
inputStreamParam.device = Pa_GetDefaultInputDevice();
inputStreamParam.sampleFormat = paInt16;
inputStreamParam.suggestedLatency = suggestedLatency;
inputStreamParam.hostApiSpecificStreamInfo = NULL;
将 int(16 或 32)转换为介于 -1 和 +1 之间的浮点数。
int audioProcessor::processingCallback(const void *inputBuffer,
void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags)
{ unsigned int i;
framesPerBuffer = framesPerBuffer/2;
int *inint = (int*) inputBuffer;
float *out = (float*) outputBuffer;
float *in = (float*) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
in[i] = inint[i]/2147483647.0f;
}
FFTW 处理器代码。
this->fftSize = fftSize;
cout << "Plan start " << endl;
outArraySize = fftSize/2+1;
cout << "fft Processor start \n";
fftIn = (double*) fftw_malloc(sizeof(double) * fftSize);
fftOut = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * outArraySize );
fftOutAbs = (double*) fftw_malloc(sizeof(double) * outArraySize );
// fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_ESTIMATE);
cout << "Plan succeed " << endl;
fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_MEASURE);
}
您需要实现两种不同的转换方法。一个用于 int32 浮动,另一个用于 int16 浮动。目前实现的是在 int16 情况下使用 int32 转换。一个问题是转换为浮点数的比例因子是错误的。另一个问题是它通过输入信号的速度是预期速度的两倍,这导致频率全部偏离 2 倍。
对于从 int16 的转换,您需要执行如下操作:
{
unsigned int i;
framesPerBuffer = framesPerBuffer/2;
short *in = (short*) inputBuffer;
float *out = (float*) outputBuffer;
for (i=0; i<framesPerBuffer; i++)
{
out[i] = in[i]/32767.0f;
}
发布的代码的另一个问题是它将浮点样本写回错误的缓冲区。自 sizeof(int)==sizeof(float)
.
以来,您可能没有注意到它与 int32 的关系
此外,framesPerFrameBuffer = framesPerFrameBuffer/2
也很可疑。我不明白你为什么需要它。
我正在使用端口音频在我的 PC 上(介于 -1 和 +1 之间)获取 32 位浮点音频 (44.1Khz),并使用 fftw 获取它的 fft。
现在我需要获取 16 位 int 音频并获取其 fft。我已将音频样本转换为在 -1 和 +1 之间浮动。 fft 有效,但峰值出现在其应有频率的 2 倍处,因此最大频率分辨率也降低了。因此,对于 44KHz,我可以看到的最大分量约为 10KHz,而 32 位 int/float.
约为 20KHz例如,如果我将 10KHz 信号从 Sign 发生器提供给声卡,峰值现在显示为 20KHz。而我唯一改变的是格式从 paInt32 到 paInt16。它适用于 paInt32 格式。
outputStreamParam.channelCount = 1;
outputStreamParam.device = Pa_GetDefaultOutputDevice();
outputStreamParam.sampleFormat = paInt16;
outputStreamParam.suggestedLatency = suggestedLatency;
outputStreamParam.hostApiSpecificStreamInfo = NULL;
inputStreamParam.channelCount = 1;
inputStreamParam.device = Pa_GetDefaultInputDevice();
inputStreamParam.sampleFormat = paInt16;
inputStreamParam.suggestedLatency = suggestedLatency;
inputStreamParam.hostApiSpecificStreamInfo = NULL;
将 int(16 或 32)转换为介于 -1 和 +1 之间的浮点数。
int audioProcessor::processingCallback(const void *inputBuffer,
void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags)
{ unsigned int i;
framesPerBuffer = framesPerBuffer/2;
int *inint = (int*) inputBuffer;
float *out = (float*) outputBuffer;
float *in = (float*) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
in[i] = inint[i]/2147483647.0f;
}
FFTW 处理器代码。
this->fftSize = fftSize;
cout << "Plan start " << endl;
outArraySize = fftSize/2+1;
cout << "fft Processor start \n";
fftIn = (double*) fftw_malloc(sizeof(double) * fftSize);
fftOut = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * outArraySize );
fftOutAbs = (double*) fftw_malloc(sizeof(double) * outArraySize );
// fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_ESTIMATE);
cout << "Plan succeed " << endl;
fftwPlan = fftw_plan_dft_r2c_1d(fftSize, fftIn, fftOut, FFTW_MEASURE);
}
您需要实现两种不同的转换方法。一个用于 int32 浮动,另一个用于 int16 浮动。目前实现的是在 int16 情况下使用 int32 转换。一个问题是转换为浮点数的比例因子是错误的。另一个问题是它通过输入信号的速度是预期速度的两倍,这导致频率全部偏离 2 倍。
对于从 int16 的转换,您需要执行如下操作:
{
unsigned int i;
framesPerBuffer = framesPerBuffer/2;
short *in = (short*) inputBuffer;
float *out = (float*) outputBuffer;
for (i=0; i<framesPerBuffer; i++)
{
out[i] = in[i]/32767.0f;
}
发布的代码的另一个问题是它将浮点样本写回错误的缓冲区。自 sizeof(int)==sizeof(float)
.
此外,framesPerFrameBuffer = framesPerFrameBuffer/2
也很可疑。我不明白你为什么需要它。