J使用PCM数据在Android中转换FFT(JTransforms FFT in Android from PCM data)

我一直在玩这个游戏已经有一段时间了,我无法弄清楚我在这里要做的事情。

我正在将PCM音频数据读入一个audioData数组中:

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);

我无法理解如何工作,有人可以给我一些建议吗? 在这之后我需要进行任何计算吗?

我确信我走了,任何事情将不胜感激!

I've been playing with this now for sometime, I cant work out what I am meant to be doing here.

I am reading in PCM audio data into an audioData array:

recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array

I want to use Piotr Wendykier's JTransform library in order to preform an FFT on my PCM data in order to obtain the frequency.

import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;

At the moment I have this:

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);

I cant make sense of how to work this, can somebody give me some pointers? Will i have to perform any calculations after this?

I'm sure I'm way off, anything would be greatly appreciated!

Ben

原文:https://stackoverflow.com/questions/7649003

更新时间:2020-01-09 15:32

最满意答案

如果您只是在输入波形中查找单个正弦波音调的频率,那么您需要找到幅度最大的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)

If you're just looking for the frequency of a single sinusoidal tone in the input waveform then you need to find the FFT peak with the largest magnitude, where:

Magnitude = sqrt(re*re + im*im)

The index i of this largest magnitude peak will tell you the approximate frequency of your sinusoid:

Frequency = Fs * i / N

where:

Fs = sample rate (Hz)

i = index of peak

N = number of points in FFT (1024 in this case)

2011-10-04

相关问答

你的输入都是0。 short s = 32767;

double d = s/32768;

System.out.println("dividing a short yields a truncated result " + d);

d = (double) s / 32768;

System.out.println("casting to a double and then dividing yields " + d);

Your inputs are all 0. short s = 327

...

首先,您需要确保您获得的结果正确转换为float / double。 我不知道短[]版本是如何工作的,但是byte []版本只返回原始字节版本。 然后,该字节数组需要正确转换为浮点数。 转换代码应该如下所示: double[] micBufferData = new double[];

final int bytesPerSample = 2; // As it is 16bit PCM

final double amplificat

...

您可以使用AudioTrack播放PCM数据! 也许是这样的: int bufsize = AudioTrack.getMinBufferSize(44100,

AudioFormat.CHANNEL_OUT_STEREO,

AudioFormat.ENCODING_PCM_16BIT);

AudioTrack audio = new AudioTrack(AudioManager.STREAM_MUSIC,

...

我应该使用NDK来避免这种情况吗? 不,你会得到与NDK相同的结果。 AudioRecord提供对原始PCM数据的访问。 设备之间的差异发生,因为它们使用不同的音频模块。 这些模块具有不同的硬件功能 (低通滤波器/灵敏度),您无法通过软件禁用它们。 其背后的原因是这些功能可以降低噪音。 should i use NDK to avoid that? No, you will get the same results with the NDK. AudioRecord provides alread

...

您需要首先将字节数组转换为适合您样本的数组类型,然后反转该数组。 例如,如果您的样本是16位,那么您将要转换为短数组。 或者,在16位情况下,您可以将数据保存为字节然后反向 - 但是以成对字节为单位。 public void reverse(byte[] array) {

if (array == null) {

return;

}

int i = 0;

int j = array.length - 1;

byte t

...

如果您只是在输入波形中查找单个正弦波音调的频率,那么您需要找到幅度最大的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)

If you're just looking for

...

假设音频是立体声的,一旦你有两个第一个字节的原始PCM对应左声道音频,两个跟随右声道音频,所以你可以将它们视为短路然后第一个短路代表左声道和第二个正确的渠道。 因此,如果您想获得左声道数据,则必须使用输入原始PCM进行循环并保存每一个短路。 喜欢这个: void demux(short in[], short left[], short right[], int len) {

for (int i=0; i

left[i] = in[i];

...

是的,它是原始PCM,您可以使用Android SDK挂接到PCM播放。 Yes it's raw PCM , you can hook into the PCM playback with the Android SDK.

来自android-ndk-r8b / docs / opensles / index.html PCM数据格式 PCM数据格式只能与缓冲区队列一起使用。 所以SLDataFormat_PCM 不能像我假设的那样与SLDataLocator_Address一起使用。 我可以使用缓冲区队列执行我想要的操作,而不是像这样使用一个大队列 bufferqueueitf->Enqueue(bufferqueueitf,dataChunk,dataSize);

from android-ndk-r8b/do

...

你的问题是java中的短路是bigendian,但是如果从WAV文件中获取数据,那么数据就是小端。 Your problem is that shorts in java are bigendian, but if you got your data from a WAV file the data is little endian.

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐