Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
j在Android中从PCM数据转换FFT_Android_Fft_Pcm - Fatal编程技术网

j在Android中从PCM数据转换FFT

j在Android中从PCM数据转换FFT,android,fft,pcm,Android,Fft,Pcm,我已经玩了一段时间了,我不知道我应该在这里做什么 我正在将PCM音频数据读入音频数据阵列: recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array 我想使用Piotr Wendykier的JTransform库对PCM数据进行FFT,以获得频率 import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; 目前,我

我已经玩了一段时间了,我不知道我应该在这里做什么

我正在将PCM音频数据读入音频数据阵列:

 recorder.read(audioData,0,bufferSize);     //read the PCM audio data into the audioData array
我想使用Piotr Wendykier的JTransform库对PCM数据进行FFT,以获得频率

import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
目前,我有以下几点:

       DoubleFFT_1D fft = new DoubleFFT_1D(1024); // 1024 is size of array

for (int i = 0; i < 1023; i++) {
           a[i]= audioData[i];               
           if (audioData[i] != 0)
           Log.v(TAG, "audiodata=" + audioData[i] + " fft= " + a[i]);
       }
       fft.complexForward(a);
DoubleFFT\u 1D fft=新的DoubleFFT\u 1D(1024);//1024是数组的大小
对于(int i=0;i<1023;i++){
a[i]=音频数据[i];
如果(音频数据[i]!=0)
Log.v(标记“audiodata=“+audiodata[i]”+“fft=“+a[i]);
}
正向(a)的fft.complex;
我搞不懂怎么做,有人能给我一些建议吗?在这之后我需要进行任何计算吗

我相信我已经走远了,任何事情都将不胜感激


Ben

如果您只是在输入波形中查找单一正弦音调的频率,则需要找到最大幅度的FFT峰值,其中:

Magnitude = sqrt(re*re + im*im)
这个最大幅值峰值的索引
i
将告诉您正弦曲线的近似频率:

Frequency = Fs * i / N
其中:

Fs = sample rate (Hz)
i = index of peak
N = number of points in FFT (1024 in this case)

如果您正在查找音频输入(1D,实数据)的FFT,您是否应该使用1D实FFT?

是的,您需要使用realForward函数而不是complexForward函数,因为您传递的是实数组而不是复数组

编辑:

或者,您可以获取实部并执行复到复fft,如下所示:

double[]in=新的双精度[N];
阅读
double[]fft=新的double[N*2];
对于(int i=0;i

我尝试将结果与matlab进行比较,但我没有得到相同的结果。。。(震级)

由于我花了几个小时来实现这一点,这里有一个完整的Java实现:

import org.jtransforms.fft.DoubleFFT_1D;

public class FrequencyScanner {
    private double[] window;

    public FrequencyScanner() {
        window = null;
    }

    /** extract the dominant frequency from 16bit PCM data.
     * @param sampleData an array containing the raw 16bit PCM data.
     * @param sampleRate the sample rate (in HZ) of sampleData
     * @return an approximation of the dominant frequency in sampleData
     */
    public double extractFrequency(short[] sampleData, int sampleRate) {
        /* sampleData + zero padding */
        DoubleFFT_1D fft = new DoubleFFT_1D(sampleData.length + 24 * sampleData.length);
        double[] a = new double[(sampleData.length + 24 * sampleData.length) * 2];

        System.arraycopy(applyWindow(sampleData), 0, a, 0, sampleData.length);
        fft.realForward(a);

        /* find the peak magnitude and it's index */
        double maxMag = Double.NEGATIVE_INFINITY;
        int maxInd = -1;

        for(int i = 0; i < a.length / 2; ++i) {
            double re  = a[2*i];
            double im  = a[2*i+1];
            double mag = Math.sqrt(re * re + im * im);

            if(mag > maxMag) {
                maxMag = mag;
                maxInd = i;
            }
        }

        /* calculate the frequency */
        return (double)sampleRate * maxInd / (a.length / 2);
    }

    /** build a Hamming window filter for samples of a given size
     * See http://www.labbookpages.co.uk/audio/firWindowing.html#windows
     * @param size the sample size for which the filter will be created
     */
    private void buildHammWindow(int size) {
        if(window != null && window.length == size) {
            return;
        }
        window = new double[size];
        for(int i = 0; i < size; ++i) {
            window[i] = .54 - .46 * Math.cos(2 * Math.PI * i / (size - 1.0));
        }
    }

    /** apply a Hamming window filter to raw input data
     * @param input an array containing unfiltered input data
     * @return a double array containing the filtered data
     */
    private double[] applyWindow(short[] input) {
        double[] res = new double[input.length];

        buildHammWindow(input.length);
        for(int i = 0; i < input.length; ++i) {
            res[i] = (double)input[i] * window[i];
        }
        return res;
    }
}
import org.jtransforms.fft.DoubleFFT\u 1D;
公共类频率扫描器{
私人双[]窗口;
公共频率扫描仪(){
窗口=空;
}
/**从16位PCM数据中提取主频。
*@param sampleData包含原始16位PCM数据的数组。
*@param sampleRate采样数据的采样率(以HZ为单位)
*@返回样本数据中主频的近似值
*/
公共双提取频率(短[]采样数据,int-sampleRate){
/*采样数据+零填充*/
DoubleFFT_1D fft=新的DoubleFFT_1D(sampleData.length+24*sampleData.length);
double[]a=新的double[(sampleData.length+24*sampleData.length)*2];
System.arraycopy(applyWindow(sampleData),0,a,0,sampleData.length);
fft.realfroward(a);
/*找到峰值大小及其指数*/
double maxMag=double.NEGATIVE_无穷大;
int maxInd=-1;
对于(int i=0;imaxMag){
maxMag=mag;
maxInd=i;
}
}
/*计算频率*/
返回(双)取样器*maxInd/(a.length/2);
}
/**为给定大小的样本构建汉明窗口过滤器
*看http://www.labbookpages.co.uk/audio/firWindowing.html#windows
*@param size将为其创建筛选器的样本大小
*/
专用窗口(整数大小){
if(window!=null&&window.length==size){
返回;
}
窗口=新的双[尺寸];
对于(int i=0;i
FrequencyScanner
将返回呈现样本数据中主频的近似值。 它对它的输入应用一个函数,以允许从音频流中传入任意样本。 精度是通过在进行FFT变换之前对样本数据进行内部零填充来实现的。 (我知道有更好、更复杂的方法可以做到这一点,但填充方法足以满足我的个人需求)


我根据220hz和440hz的参考声音创建的原始16位PCM样本进行测试,结果匹配。

对不起,我应该说complexForward的功能:计算复杂数据的1D正向DFT,将结果保留在a中。复数按顺序存储为两个双值:实部和虚部,即输入数组的大小必须大于或等于2*n。输入数据的物理布局必须如下所示:a[2*k]=Re[k],a[2*k+1]=Im[k],0给我举个例子……这听起来很像我正在尝试做的。但是,我不确定如何从变换中得到实值和虚值。我也不确定是否应该使用DoubleFFT_1D类?与DoubleFFT_2D类或FloatFFT_1D类等不同,您只需要对音频进行1D FFT(2D FFT通常用于图像等2D数据)。从你在上面的问题中所说的,听起来像是实数和imag分量是交错的,所以bin i在索引2*i处有实数分量,在索引2*i+1处有imag分量。谢谢Paul,太好了,有几件事我不明白。。。我是否像这样向前传递fft.complexForward(audioData);?如果我这样做了,它会操纵数组吗?它没有返回类型。谢谢我不熟悉这个具体的FFT但是