gpt4 book ai didi

java - 频谱图的频率范围

转载 作者:太空宇宙 更新时间:2023-11-04 07:18:51 25 4
gpt4 key购买 nike

我能够使用 https://code.google.com/p/musicg/ 中的音乐库来可视化频谱图。但我发现了一些我不太理解的奇怪的事情。我尝试使用采样率为 22050 的 wav 文件,并使用 Blackmann 窗口使用 1024 个样本(重叠 50%)执行 fft。计算结果是二维数组(频谱图[时间][频率]=强度)。我的问题是,如果第二个维度称为频率,为什么它的大小只有256?与频率宽度bin有关吗?那么我如何确定频率?当我尝试使用 512 个样本时,大小减少到一半(128)。

那么我们应该对频谱图进行归一化吗?

spectrogram result

这是我从 musicg 获得的代码

short[] amplitudes=wave.getSampleAmplitudes();

int numSamples = amplitudes.length;
int pointer=0;
// overlapping
if (overlapFactor>1){

int numOverlappedSamples=numSamples*overlapFactor;
int backSamples=fftSampleSize*(overlapFactor-1)/overlapFactor;
int fftSampleSize_1=fftSampleSize-1;
short[] overlapAmp= new short[numOverlappedSamples];
pointer=0;
for (int i=0; i<amplitudes.length; i++){
overlapAmp[pointer++]=amplitudes[i];
if (pointer%fftSampleSize==fftSampleSize_1){
// overlap
i-=backSamples;
}
}
numSamples=numOverlappedSamples;
amplitudes=overlapAmp;
}
// end overlapping

numFrames=numSamples/fftSampleSize;
framesPerSecond=(int)(numFrames/wave.length());

// set signals for fft (windowing)
WindowFunction window = new WindowFunction();
window.setWindowType("BLACKMAN");
double[] win=window.generate(fftSampleSize);

double[][] signals=new double[numFrames][];
for(int f=0; f<numFrames; f++) {
signals[f]=new double[fftSampleSize];

int startSample=f*fftSampleSize;
for (int n=0; n<fftSampleSize; n++){

signals[f][n]=amplitudes[startSample+n]*win[n];
}
}
// end set signals for fft

absoluteSpectrogram=new double[numFrames][];
// for each frame in signals, do fft on it
FastFourierTransform fft = new FastFourierTransform();
for (int i=0; i<numFrames; i++){
absoluteSpectrogram[i]=fft.getMagnitudes(signals[i]);
}

if (absoluteSpectrogram.length>0){

numFrequencyUnit=absoluteSpectrogram[0].length;
unitFrequency=(double)wave.getWaveHeader().getSampleRate()/2/numFrequencyUnit; // frequency could be caught within the half of nSamples according to Nyquist theory

// normalization of absoluteSpectrogram
spectrogram=new double[numFrames][numFrequencyUnit];

// set max and min amplitudes
double maxAmp=Double.MIN_VALUE;
double minAmp=Double.MAX_VALUE;
for (int i=0; i<numFrames; i++){
for (int j=0; j<numFrequencyUnit; j++){
if (absoluteSpectrogram[i][j]>maxAmp){
maxAmp=absoluteSpectrogram[i][j];
}
else if(absoluteSpectrogram[i][j]<minAmp){
minAmp=absoluteSpectrogram[i][j];
}
}
}

谢谢

最佳答案

每个 FFT 结果箱之间的间距是采样率除以 FFT 长度。对于以 22050 sps 的速率采样并馈送到 1024 FFT 长度的数据,所得频率仓间隔约为 21.5 Hz。如果将 FFT 长度减少到 512,则在达到不超过采样率一半之前,较大的箱间距会导致频谱图垂直轴中的总箱数减少。使用布莱克曼窗口(实际上是任何窗口),每个 bin 的带宽都会有一些重叠。

关于java - 频谱图的频率范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19602980/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com