[英]Audio Processing C++ - FFT
I'm probably going to ask this incorrectly and make myself look very stupid but here goes: 我可能会错误地问这个并让自己看起来非常愚蠢但是这里有:
I'm trying to do some audio manipulate and processing on a .wav file. 我正在尝试对.wav文件进行一些音频操作和处理。 Now, I am able to read all of the data (including the header) but need the data to be in frequency, and, in order to this I need to use an FFT. 现在,我能够读取所有数据(包括标题),但需要数据处于频率,为此,我需要使用FFT。
I searched the internet high and low and found one, and the example was taken out of the "Numerical Recipes in C" book, however, I amended it to use vectors instead of arrays. 我搜索了互联网的高低,找到了一个,这个例子取自“C中的数字食谱”一书,然而,我修改它使用向量而不是数组。 Ok so here's the problem: 好的,这就是问题所在:
I have been given (as an example to use) a series of numbers and a sampling rate: 我被给予(作为一个例子使用)一系列数字和采样率:
X = {50, 206, -100, -65, -50, -6, 100, -135}
Sampling Rate : 8000 Number of Samples: 8 采样率:8000样本数:8
And should therefore answer this: 因此应该回答这个问题:
0Hz A=0 D=1.57079633
1000Hz A=50 D=1.57079633
2000HZ A=100 D=0
3000HZ A=100 D=0
4000HZ A=0 D=3.14159265
The code that I re-wrote compiles, however, when trying to input these numbers into the equation (function) I get a Segmentation fault.. Is there something wrong with my code, or is the sampling rate too high? 我重写的代码编译,然而,当试图将这些数字输入到等式(函数)中时,我得到了一个分段错误。我的代码有问题,或者采样率是否过高? (The algorithm doesn't segment when using a much, much smaller sampling rate). (当使用更小,更小的采样率时,算法不会分段)。 Here is the code: 这是代码:
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr;
#define pi 3.14159
void ComplexFFT(vector<float> &realData, vector<float> &actualData, unsigned long sample_num, unsigned int sample_rate, int sign)
{
unsigned long n, mmax, m, j, istep, i;
double wtemp,wr,wpr,wpi,wi,theta,tempr,tempi;
// CHECK TO SEE IF VECTOR IS EMPTY;
actualData.resize(2*sample_rate, 0);
for(n=0; (n < sample_rate); n++)
{
if(n < sample_num)
{
actualData[2*n] = realData[n];
}else{
actualData[2*n] = 0;
actualData[2*n+1] = 0;
}
}
// Binary Inversion
n = sample_rate << 1;
j = 0;
for(i=0; (i< n /2); i+=2)
{
if(j > i)
{
SWAP(actualData[j], actualData[i]);
SWAP(actualData[j+1], actualData[i+1]);
if((j/2)<(n/4))
{
SWAP(actualData[(n-(i+2))], actualData[(n-(j+2))]);
SWAP(actualData[(n-(i+2))+1], actualData[(n-(j+2))+1]);
}
}
m = n >> 1;
while (m >= 2 && j >= m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax=2;
while(n > mmax) {
istep = mmax << 1;
theta = sign * (2*pi/mmax);
wtemp = sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
for(m=1; (m < mmax); m+=2) {
for(i=m; (i <= n); i += istep)
{
j = i*mmax;
tempr = wr*actualData[j-1]-wi*actualData[j];
tempi = wr*actualData[j]+wi*actualData[j-1];
actualData[j-1] = actualData[i-1] - tempr;
actualData[j] = actualData[i]-tempi;
actualData[i-1] += tempr;
actualData[i] += tempi;
}
wr = (wtemp=wr)*wpr-wi*wpi+wr;
wi = wi*wpr+wtemp*wpi+wi;
}
mmax = istep;
}
// determine if the fundamental frequency
int fundemental_frequency = 0;
for(i=2; (i <= sample_rate); i+=2)
{
if((pow(actualData[i], 2)+pow(actualData[i+1], 2)) > pow(actualData[fundemental_frequency], 2)+pow(actualData[fundemental_frequency+1], 2)) {
fundemental_frequency = i;
}
}
}
int main(int argc, char *argv[]) {
vector<float> numbers;
vector<float> realNumbers;
numbers.push_back(50);
numbers.push_back(206);
numbers.push_back(-100);
numbers.push_back(-65);
numbers.push_back(-50);
numbers.push_back(-6);
numbers.push_back(100);
numbers.push_back(-135);
ComplexFFT(numbers, realNumbers, 8, 8000, 0);
for(int i=0; (i < realNumbers.size()); i++)
{
cout << realNumbers[i] << "\n";
}
}
The other thing, (I know this sounds stupid) but I don't really know what is expected of the "int sign" That is being passed through the ComplexFFT function, this is where I could be going wrong. 另一件事,(我知道这听起来很愚蠢),但我真的不知道对于通过ComplexFFT函数传递的“int符号”的期望是什么,这是我可能出错的地方。
Does anyone have any suggestions or solutions to this problem? 有没有人对这个问题有任何建议或解决方案?
Thank you :) 谢谢 :)
I think the problem lies in errors in how you translated the algorithm. 我认为问题在于你如何翻译算法的错误。
Did you mean to initialize j
to 1
rather than 0
? 你的意思是将j
初始化为1
而不是0
吗?
for(i = 0; (i < n/2); i += 2)
should probably be for (i = 1; i < n; i += 2)
. for(i = 0; (i < n/2); i += 2)
应该是for (i = 1; i < n; i += 2)
。
Your SWAP
s should probably be 您的SWAP
可能应该是
SWAP(actualData[j - 1], actualData[i - 1]); SWAP(actualData[j], actualData[i]);
What are the following SWAP
s for? 以下什么是SWAP
? I don't think they're needed. 我不认为他们是需要的。
if((j/2)<(n/4)) { SWAP(actualData[(n-(i+2))], actualData[(n-(j+2))]); SWAP(actualData[(n-(i+2))+1], actualData[(n-(j+2))+1]); }
The j >= m
in while (m >= 2 && j >= m)
should probably be j > m
if you intended to do bit reversal. 在j >= m
的while (m >= 2 && j >= m)
大概应该是j > m
,如果你打算做位反转。
In the code implementing the Danielson-Lanczos section, are you sure j = i*mmax;
在实现Danielson-Lanczos部分的代码中,你确定j = i*mmax;
was not supposed to be an addition, ie j = i + mmax;
不应该是一个加法,即j = i + mmax;
? ?
Apart from that, there are a lot of things you can do to simplify your code. 除此之外,您可以做很多事情来简化代码。
Using your SWAP
macro should be discouraged when you can just use std::swap
... I was going to suggest std::swap_ranges
, but then I realized you only need to swap the real parts, since your data is all reals (your time-series imaginary parts are all 0
): 当你只能使用std::swap
时,不鼓励使用你的SWAP
宏......我打算建议使用std::swap_ranges
,但后来我意识到你只需交换真实的部分,因为你的数据都是实数(你的数据)时间序列虚部全部为0
):
std::swap(actualData[j - 1], actualData[i - 1]);
You can simplify the entire thing using std::complex
, too. 您也可以使用std::complex
简化整个过程。
I reckon its down to the re-sizing of your vector. 我认为它的重新调整了你的向量。
One possibility: Maybe re-sizing will create temp objects on the stack before moving them back to heap i think. 一种可能性:也许重新调整大小会在堆栈中创建临时对象,然后再将它们移回堆中。
The FFT in Numerical Recipes in C uses the Cooley-Tukey Algorithm , so in answer to your question at the end, the int sign
being passed allows the same routine to be used to compute both the forward ( sign=-1
) and inverse ( sign=1
) FFT. C中的数字配方中的FFT使用Cooley-Tukey算法 ,因此在最后回答您的问题时,传递的int sign
允许使用相同的例程来计算forward( sign=-1
)和inverse( sign=1
)FFT。 This seems to be consistent with the way you are using sign
when you define theta = sign * (2*pi/mmax)
. 这似乎与您在定义theta = sign * (2*pi/mmax)
时使用sign
的方式一致。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.