我知道有人问过这个问题,但没有明确的答案。 因此,我在这里找到了一些示例:FFT spectrum analysis 在哪里可以使用FFT类
转换双精度数组RealDoubleFFT transformer;
int blockSize= */2048;
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
bufferReadResult = audioRecord.read(buffer, 0, blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0; // signed 16 bit
}
transformer.ft(toTransform);
所以现在我不知道如何获得频率
我写了这样的方法:
public static int calculateFFTFrequency(double[] audioData){
float sampleRate = 44100;
int numSamples = audioData.length;
double max = Double.MIN_VALUE;
int index = 0;
for (int i = 0; i< numSamples -1; i++){
if (audioData[i] > max) {
max = audioData[i];
index = i;
}
}
float freq = (sampleRate / (float) numSamples * (float) index) * 2F;
return (int)freq;
}
我尝试实现一个公式,但是它并没有给我带来任何好处-一些通配符
我也尝试过零过关:
public static int calculateFrequency(short [] audioData){
int sampleRate = 44100;
int numSamples = audioData.length;
int numCrossing = 0;
for (int p = 0; p < numSamples-1; p++)
{
if ((audioData[p] > 0 && audioData[p + 1] <= 0) ||
(audioData[p] < 0 && audioData[p + 1] >= 0))
{
numCrossing++;
}
}
float numSecondsRecorded = (float)numSamples/(float)sampleRate;
float numCycles = numCrossing/2;
float frequency = numCycles/numSecondsRecorded;
return (int)frequency;
}
但是在零通过方法中,如果我在钢琴上弹“ A”音符,它会向我显示430一段时间(接近A),然后在声音消失时开始显示一些通配数字-800+,1000+,等
有人可以帮助我如何从麦克风中获得更多或更少的实际频率吗?
答案 0 :(得分:0)
您应该使用生成的流而不是麦克风来测试解决方案,然后测试检测到的频率是否符合您的期望。然后,您可以对麦克风进行真实生活测试,如果有任何问题,您应该自己分析麦克风收集的数据。您的环境中可能会听不到声音,可能会导致某些奇怪的结果。当声音消失时,可能会出现一些和声,并且这些和声会比基本声音更悦耳。处理来自真实环境的声音时,有很多事情要考虑。
答案 1 :(得分:0)
您从钢琴听到的是音高,而不仅仅是频谱频率。它们不是同一件事。音调是一种心理声学现象,更多地取决于周期性,而不仅仅是频谱峰值。裸FFT会报告频谱频率幅度,该频谱频率幅度可能由泛音,谐波和其他伪像组成,并且可能包含也可能不包含基本音调频率。
因此,您可能想使用而不是FFT的是音调检测/估计算法,该算法比仅从FFT中选择峰值幅度要复杂一些。