我应该从getFft中看到什么样的输出?

好吧,所以我正在创建一个Android音频可视化应用程序。 问题是,我从getFft()方法得到的东西与google所说的应该产生的东西并不相符。 我一直追溯到C ++的源代码,但我不熟悉C ++或FFT来真正了解正在发生的事情。

我会尽力包含这里所需的一切:

(Java)Visualizer.getFft(byte [] fft)

/** * Returns a frequency capture of currently playing audio content. The capture is a 8-bit * magnitude FFT. Note that the size of the FFT is half of the specified capture size but both * sides of the spectrum are returned yielding in a number of bytes equal to the capture size. * {@see #getCaptureSize()}. * 

This method must be called when the Visualizer is enabled. * @param fft array of bytes where the FFT should be returned * @return {@link #SUCCESS} in case of success, * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT} * in case of failure. * @throws IllegalStateException */ public int getFft(byte[] fft) throws IllegalStateException { synchronized (mStateLock) { if (mState != STATE_ENABLED) { throw(new IllegalStateException("getFft() called in wrong state: "+mState)); } return native_getFft(fft); } }

(C ++)Visualizer.getFft(uint8_t * fft)

 status_t Visualizer::getFft(uint8_t *fft) { if (fft == NULL) { return BAD_VALUE; } if (mCaptureSize == 0) { return NO_INIT; } status_t status = NO_ERROR; if (mEnabled) { uint8_t buf[mCaptureSize]; status = getWaveForm(buf); if (status == NO_ERROR) { status = doFft(fft, buf); } } else { memset(fft, 0, mCaptureSize); } return status; } 

(C ++)Visualizer.doFft(uint8_t * fft,uint8_t *波形)

 status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform) { int32_t workspace[mCaptureSize >> 1]; int32_t nonzero = 0; for (uint32_t i = 0; i > 1] = (waveform[i] ^ 0x80) <> 1] |= (waveform[i + 1] ^ 0x80) <> 1]; } if (nonzero) { fixed_fft_real(mCaptureSize >> 1, workspace); } for (uint32_t i = 0; i > 1] >> 23; fft[i + 1] = workspace[i >> 1] >> 7; } return NO_ERROR; } 

(C ++)fixedfft.fixed_fft_real(int n,int32_t * v)

 void fixed_fft_real(int n, int32_t *v) { int scale = LOG_FFT_SIZE, m = n >> 1, i; fixed_fft(n, v); for (i = 1; i <= n; i <<= 1, --scale); v[0] = mult(~v[0], 0x80008000); v[m] = half(v[m]); for (i = 1; i > 1; ++i) { int32_t x = half(v[i]); int32_t z = half(v[n - i]); int32_t y = z - (x ^ 0xFFFF); x = half(x + (z ^ 0xFFFF)); y = mult(y, twiddle[i << scale]); v[i] = x - y; v[n - i] = (x + y) ^ 0xFFFF; } } 

(C ++)fixedfft.fixed_fft(int n,int32_t * v)

 void fixed_fft(int n, int32_t *v) { int scale = LOG_FFT_SIZE, i, p, r; for (r = 0, i = 1; i >= 1, r ^= p); if (i < r) { int32_t t = v[i]; v[i] = v[r]; v[r] = t; } } for (p = 1; p < n; p <<= 1) { --scale; for (i = 0; i < n; i += p << 1) { int32_t x = half(v[i]); int32_t y = half(v[i + p]); v[i] = x + y; v[i + p] = x - y; } for (r = 1; r < p; ++r) { int32_t w = MAX_FFT_SIZE / 4 - (r <> 31; w = twiddle[(w ^ i) - i] ^ (i << 16); for (i = r; i < n; i += p << 1) { int32_t x = half(v[i]); int32_t y = mult(w, v[i + p]); v[i] = x - y; v[i + p] = x + y; } } } } 

如果你完成了所有这些,你真棒! 所以我的问题是,当我调用java方法getFft()时,我最终得到负值,如果返回的数组用于表示大小,则该值不应该存在。 所以我的问题是,我需要做些什么来使数组代表幅度?

编辑:看来我的数据实际上可能是傅里叶系数。 我在网上偷看并找到了这个 。 小程序“开始函数FFT”显示系数的图形表示,它是我从getFft()绘制数据图形时发生的吐痰图像。 所以新问题: 这是我的数据吗? 如果是这样,我如何从系数到光谱分析呢?

FFT不仅会产生幅度; 它也产生相位(每个样本的输出是一个复数)。 如果你想要幅度,那么你需要为每个输出样本显式计算它,如re*re + im*im ,其中reim分别是每个复数的实部和虚部。

不幸的是,我无法在你的代码中看到任何处理复杂数字的地方,因此可能需要重写一些。

UPDATE

如果我不得不猜测(在看了一下代码之后),我会说实际组件是偶数索引,奇数组件是奇数索引。 所以为了获得数量,你需要做类似的事情:

 uint32_t mag[N/2]; for (int i = 0; i < N/2; i++) { mag[i] = fft[2*i]*fft[2*i] + fft[2*i+1]*fft[2*i+1]; } 

一个可能的解释为什么你看到负值: byte是Java中的签名数据类型。 所有大于或等于1000 0000 2的值都被解释为负整数。

如果我们知道所有值都应该在[0..255]范围内,那么我们将值映射到更大的类型并过滤高位:

 byte signedByte = 0xff; // = -1 short unsignedByte = ((short) signedByte) & 0xff; // = 255 

“捕获是一个8位幅度的FFT”可能意味着返回值具有8位幅度,而不是它们本身就是幅度。

据杰森说

对于实值信号,如音频处理中的信号,负频率输出将是正频率的镜像。

Android 2.3 Visualizer – 理解getFft()的麻烦