Why DFT from AForge.Math doesn't work?
Pregunta
I tried to get fft and then get dft of a wave using this code:
string s = textBox1.Text;
double[] source = SourceToDouble(s);
listBox2.DataSource = source;
ToPowerOfTwo(ref source);
List<Complex> Source = DoubleToComplex(source);
Complex[] sou = Source.ToArray();
FourierTransform.FFT(sou, FourierTransform.Direction.Forward);
listBox1.DataSource = sou;
FourierTransform.DFT(sou, FourierTransform.Direction.Forward);
DoPlaySound(sou);
SourceToDouble(s)
:
private double[] SourceToDouble(string s)
{
List<double> Final = new List<double>();
EricOulashin.WAVFile audioFile = new EricOulashin.WAVFile();
String warning = audioFile.Open(s, WAVFile.WAVFileMode.READ);
if (warning == "")
{
short audioSample = 0;
for (int sampleNum = 0; sampleNum < audioFile.NumSamples; ++sampleNum)
{
audioSample = audioFile.GetNextSampleAs16Bit();
Final.Add((double)audioSample);
}
}
else
{
throw new Exception(warning);
}
return Final.ToArray();
}
ToPowerOfTwo(ref source)
:
private void ToPowerOfTwo(ref double[] source)
{
List<long> TwoPowers = GetTwoPowers(100);
long pCount = 0;
for (int i = 0; i <= 100; i++)
{
if (source.Count() <= TwoPowers[i])
{
pCount = TwoPowers[i];
break;
}
}
List<double> f = new List<double>(source);
while (f.Count < pCount)
{
f.Add(0.0);
}
//f.Add(0.0);
source = f.ToArray();
}
DoubleToComplex(source)
:
private static List<Complex> DoubleToComplex(double[] source)
{
List<Complex> Source = new List<Complex>();
foreach (double dob in source)
{
Complex c = new Complex(dob, 0.0);
Source.Add(c);
}
return Source;
}
DoPlaySound(sou)
:
private void DoPlaySound(Complex[] c)
{
FourierTransform.DFT(c, FourierTransform.Direction.Forward);
double wav = c[0].Re;
List<double> Big = ToBigger(100000, new double[] { wav });
MakeWavFile(Big, "tmp.wav");
System.Media.SoundPlayer s = new SoundPlayer("tmp.wav");
s.PlayLooping();
}
the problem is this: when I give a wav file to general code, after a long time the method trying to play the final wav (tmp.wav) but it isn't like the general file.
Update 1:
I also tried FourierTransform.DFT(sou, FourierTransform.Direction.Backward);
but it didn't work too!
Solución
An FFT of an entire audio file is not a good way of analyzing voice or other non-stationary information. It would also be very slow. A more common technique would be to analyse short overlapping frames of a few to few dozen milliseconds in length using shorter FFTs, or to process successive frames using overlap-add/save FFT fast convolution.
A single IFFT would be the proper inverse function to an FFT. Otherwise you might end up with a mis-scaled backwards result.
Otros consejos
It seems you are running a forward DFT three times on your data between reading it and playing it. So of course it's not going to sound like the original.
I would rewrite the DoubleToComplex function as:
private static Complex[] DoubleToComplex(double[] source)
{
Complex[] complexSource = new Complex[source.Length];
for(int i =0; i< source.Length; i++ )
{
complexSource[i] = new Complex(source[i], 0.0);
}
return complexSource;
}
Why first create a list to create all the Complex object, to bring it later on back to an Array? To use an Array from the beginning is more efficient.