Java 频谱图的频率范围
我能够使用musicg库从中可视化光谱图,但我发现了一些奇怪的事情,我并不真正理解。 我尝试使用采样率为22050的wav文件,并使用blackmann窗口使用1024个采样和50%重叠执行fft。 计算结果为二维阵列(谱图[时间][频率]=强度)。 我的问题是,如果第二维度叫做频率,为什么它的大小只有256?它与频率宽度有关吗?那么我如何确定频率? 当我尝试使用512个样本时,大小减少到一半(128) 那么我们应该使光谱图正常化吗 这是我从musicg得到的代码Java 频谱图的频率范围,java,audio,fft,spectrogram,windowing,Java,Audio,Fft,Spectrogram,Windowing,我能够使用musicg库从中可视化光谱图,但我发现了一些奇怪的事情,我并不真正理解。 我尝试使用采样率为22050的wav文件,并使用blackmann窗口使用1024个采样和50%重叠执行fft。 计算结果为二维阵列(谱图[时间][频率]=强度)。 我的问题是,如果第二维度叫做频率,为什么它的大小只有256?它与频率宽度有关吗?那么我如何确定频率? 当我尝试使用512个样本时,大小减少到一半(128) 那么我们应该使光谱图正常化吗 这是我从musicg得到的代码 short[] amplit
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];
}
}
}
short[]振幅=wave.getSample振幅();
int numSamples=振幅.length;
int指针=0;
//重叠
如果(重叠系数>1){
int numOverlappedSamples=numSamples*重叠因子;
int backSamples=fftSampleSize*(重叠因子-1)/重叠因子;
int-fftSampleSize_1=fftSampleSize-1;
short[]overlappamp=新的short[numOverlappedSamples];
指针=0;
对于(int i=0;i每个FFT结果单元之间的间隔是采样率除以FFT长度。对于以22050 sps的速率采样并馈送到1024 FFT长度的数据,产生的频率单元间隔约为21.5 Hz。如果将FFT长度减少到512,则较大的单元间隔会导致频谱图v中的总单元数减少在达到不超过一半采样率之前的垂直轴。使用Blackman窗口(实际上是任何窗口),每个存储单元的带宽将有一些重叠。每个FFT结果存储单元之间的间隔是采样率除以FFT长度。对于以22050 SP的速率采样并馈送到1024 FFT长度的数据,产生的频率存储单元间隔将约为21.5 Hz。如果将FFT长度减少到512,则会产生更大的存储单元间隔在达到不超过一半的采样率之前,它在频谱图垂直轴上的总存储单元较少。使用Blackman窗口(实际上是任何窗口),每个存储单元的带宽都会有一些重叠。第二维度是频率系数。粗略地说,FFT会告诉某些特定频率的功率,您可以“猜测”它们之间的幂是什么。为了在频率维度上获得更好的分辨率,你应该使用更大的FFT窗口(更多的样本)。然后,我们如何确定频谱图上存在的最低频率和最高频率?第二个维度是频率系数。粗略地说,FFT告诉某些特定频率的幂,你可以“猜猜”它们之间的幂是什么。为了在频率维度上获得更好的分辨率,你应该使用更大的FFT窗口(更多样本)。那么,我们如何确定频谱图上存在的最低频率和最高频率?