从麦克风输入和FFT获取频率-Java

从麦克风输入和FFT获取频率-Java,java,math,audio,fft,microphone,Java,Math,Audio,Fft,Microphone,我的目标是能够处理来自吉他(或其他乐器)的单个音符,并将其转换为频率值 这不必是实时的——我想记录一秒钟的声音并在事后分析数据会容易得多 我知道要做到这一点,我需要使用傅里叶变换(并且有一个类将执行FFT)。然而,我并不真正理解FFT算法的输入/输出-我使用的类似乎使用复数向量输入并给出复数向量输出。这些代表什么 另外,有谁能推荐任何可以检测和记录输入的Java类(如果可能,给出可以插入FFT的频率或值) 提前感谢。FFT的输入将是代表音频的时域信号。如果你从麦克风中录制一些声音一秒钟,这将真正

我的目标是能够处理来自吉他(或其他乐器)的单个音符,并将其转换为频率值

这不必是实时的——我想记录一秒钟的声音并在事后分析数据会容易得多

我知道要做到这一点,我需要使用傅里叶变换(并且有一个类将执行FFT)。然而,我并不真正理解FFT算法的输入/输出-我使用的类似乎使用复数向量输入并给出复数向量输出。这些代表什么

另外,有谁能推荐任何可以检测和记录输入的Java类(如果可能,给出可以插入FFT的频率或值)


提前感谢。

FFT的输入将是代表音频的时域信号。如果你从麦克风中录制一些声音一秒钟,这将真正包含一个由不同数量的不同频率组成的波-希望主要是与你演奏的音符相对应的频率/频率,加上一些外部噪音和麦克风和电子设备引入的噪音。如果在这1秒钟内,您恰好有512个时间点(因此麦克风可以每秒采样512次),那么这些时间点中的每一个都表示麦克风拾取的强度。可以使用FFT将这些声强值从时域表示转换为频域表示

如果您现在将其交给FFT,因为它是实值输入,您将获得对称复数输出(围绕中心值对称),并且可以忽略复数向量输出的后半部分,而只使用前半部分-即,后半部分将与前半部分对称(因此“相同”)。输出表示每个频率对输入波形的贡献-本质上,每个“bin”或数组索引包含有关该频率振幅的信息。要提取要执行的振幅,请执行以下操作:

magnitudeFFTData[i] = Math.sqrt((real * real) + (imaginary * imaginary));
其中,
是复数在该频率区间的实部和虚部。要获得与给定bin对应的频率,您需要以下内容:

frequency = i * Fs / N;
其中,
i
是bin或数组索引号,
Fs
是采样频率,
N
是数据点的数量。来自我最近使用FFT的一个项目:

for (int i = (curPersonFFTData.length / 64); i < (curPersonFFTData.length / 40); i++) {
            double rr = (curPersonFFTData[i].getReal());
            double ri = (curPersonFFTData[i].getImaginary());

            magnitudeCurPersonFFTData[i] = Math.sqrt((rr * rr) + (ri * ri));
            ds.addValue(magnitudeCurPersonFFTData[i]);
        }
for(int i=(curPersonFFTData.length/64);i<(curPersonFFTData.length/40);i++){
double rr=(curPersonFFTData[i].getReal());
double ri=(curPersonFFTData[i].getImaginate());
震级curpersonfftdata[i]=数学sqrt((rr*rr)+(ri*ri));
ds.附加值(震级curpersonfftdata[i]);
}

除以64和40是任意的,只对我的情况有用,只得到某些频率分量,而不是您可能需要的所有频率。您可以轻松地实时完成所有这些操作。

FFT的输入将是表示音频的时域信号。如果你从麦克风中录制一些声音一秒钟,这将真正包含一个由不同数量的不同频率组成的波-希望主要是与你演奏的音符相对应的频率/频率,加上一些外部噪音和麦克风和电子设备引入的噪音。如果在这1秒钟内,您恰好有512个时间点(因此麦克风可以每秒采样512次),那么这些时间点中的每一个都表示麦克风拾取的强度。可以使用FFT将这些声强值从时域表示转换为频域表示

如果您现在将其交给FFT,因为它是实值输入,您将获得对称复数输出(围绕中心值对称),并且可以忽略复数向量输出的后半部分,而只使用前半部分-即,后半部分将与前半部分对称(因此“相同”)。输出表示每个频率对输入波形的贡献-本质上,每个“bin”或数组索引包含有关该频率振幅的信息。要提取要执行的振幅,请执行以下操作:

magnitudeFFTData[i] = Math.sqrt((real * real) + (imaginary * imaginary));
其中,
是复数在该频率区间的实部和虚部。要获得与给定bin对应的频率,您需要以下内容:

frequency = i * Fs / N;
其中,
i
是bin或数组索引号,
Fs
是采样频率,
N
是数据点的数量。来自我最近使用FFT的一个项目:

for (int i = (curPersonFFTData.length / 64); i < (curPersonFFTData.length / 40); i++) {
            double rr = (curPersonFFTData[i].getReal());
            double ri = (curPersonFFTData[i].getImaginary());

            magnitudeCurPersonFFTData[i] = Math.sqrt((rr * rr) + (ri * ri));
            ds.addValue(magnitudeCurPersonFFTData[i]);
        }
for(int i=(curPersonFFTData.length/64);i<(curPersonFFTData.length/40);i++){
double rr=(curPersonFFTData[i].getReal());
double ri=(curPersonFFTData[i].getImaginate());
震级curpersonfftdata[i]=数学sqrt((rr*rr)+(ri*ri));
ds.附加值(震级curpersonfftdata[i]);
}

除以64和40是任意的,只对我的情况有用,只得到某些频率分量,而不是您可能需要的所有频率。您可以轻松地实时完成所有这些操作。

FFT的输入将是表示音频的时域信号。如果你从麦克风中录制一些声音一秒钟,这将真正包含一个由不同数量的不同频率组成的波-希望主要是与你演奏的音符相对应的频率/频率,加上一些外部噪音和麦克风和电子设备引入的噪音。如果在这1秒钟内,您恰好有512个时间点(因此麦克风可以每秒采样512次),那么这些时间点中的每一个都表示麦克风拾取的强度。可以使用FFT将这些声强值从时域表示转换为频域表示