问题
This is similar question to the other questions but not a duplicate one. However, I am still not able to get the correct result.
I am basically trying to record two Wav files (1 - Base File 2 -Temp File) and then convert that to byte and pass to Aforge FFT and then the Correlation.
There are few confusion. When I record the file I am ussing 44100 Khz with 16 bit. Therefore I believe it will return 44100 bytes per second. FFT accepts bytes in power of 2, So I am passing 16384 bytes at a time and storing that to the parent array and then I am using the Cross Corelation Alogorithm to view the similarity and it only returns around 0.30 all the time. I am again not too sure whether I have followed the right way.
I am attaching the sample code and relative references.
static void Start()
{
waveSource = new WaveInEvent();
//waveSource.WaveFormat = new WaveFormat(44100, 1);//44khz rate
waveSource.WaveFormat = new WaveFormat(44100, 16, 1);
waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
Random rnd = new Random();
int card = rnd.Next(52);
waveFile = new WaveFileWriter(@Environment.CurrentDirectory.ToString() + @"\Recording" + card.ToString() + "0001.wav", waveSource.WaveFormat);
waveSource.StartRecording();
}
private static void FileCompare(string file1, string file2)
{
double[] r1;
// readWav(file1, out permanent, out r);
//readWav(file2, out temp, out l);
openWav(file1, out permanent, out r1);
openWav(file2, out temp, out r1);
double[] odoubledata = new double[163840];
double[] odoubledata1 = new double[163840];
int n = 0;
int k = 0;
for (int lk = 0; lk <10; lk++)
{
// if (lk != 0 || lk != 9)
{
AForge.Math.Complex[] c = new AForge.Math.Complex[16384];
for (int i = 0; i < 16384; i++)
{
c[i].Re = permanent[i];
c[i].Im = 0;
}
AForge.Math.Complex[] c1 = new AForge.Math.Complex[16384];
for (int i = 0; i < 16384; i++)
{
c1[i].Re = temp[i];
c1[i].Im = 0;
}
FourierTransform.FFT(c, FourierTransform.Direction.Forward);
FourierTransform.FFT(c1, FourierTransform.Direction.Forward);
// FourierTransform.DFT(c1, FourierTransform.Direction.Forward);
double[] doubledata = new double[c.Length];
double[] doubledata1 = new double[c1.Length];
for (int i = 0; i < c.Length; i++)
{
doubledata[i] = c[i].Re;
odoubledata[k] = c[i].Re;
k = k + 1;
}
for (int i = 0; i < c1.Length; i++)
{
doubledata1[i] = c1[i].Re ;
odoubledata1[n] = c1[i].Re;
n = n + 1;
}
}
}
double temq2;
int off;
CalcCrossCorrelation(odoubledata, odoubledata1, out off, out temq2);
Console.WriteLine("Similarity " + temq2);
}
References - Storing Wav File https://stackoverflow.com/a/17983876/4124478
Reading Wav File https://stackoverflow.com/a/11162668/4124478
Cross Correlation https://stackoverflow.com/a/27277120/4124478
FFT Code https://stackoverflow.com/a/170413/4124478
Update
I am storing the sample files with same bytes as it will be easy to compare. The recording will stop itself after 4 seconds.
static void Start()
{
waveSource = new WaveInEvent();
//waveSource.WaveFormat = new WaveFormat(44100, 1);//44khz rate
waveSource.WaveFormat = new WaveFormat(8192, 16, 1);
waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
Random rnd = new Random();
int card = rnd.Next(52);
waveFile = new WaveFileWriter(@Environment.CurrentDirectory.ToString() + @"\Recording" + card.ToString() + "0001.wav", waveSource.WaveFormat);
waveSource.StartRecording();
}
static void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveFile != null)
{
waveFile.Write(e.Buffer, 0, e.BytesRecorded);
int seconds = (int)(waveFile.Length / waveFile.WaveFormat.AverageBytesPerSecond);
if (seconds > 4)
{
waveFile.Flush();
Stop();
}
}
}
Also, I was not able to send all bytes as the total length was not in power of 2. Therefore, I only send 2 bytes at a time and normally I get 0.60 similarity.
private static void FileCompare(string file1, string file2)
{
double[] l;
double[] r;
double[] r1;
// readWav(file1, out permanent, out r);
// readWav(file2, out temp, out l);
openWav(file1, out permanent, out r1);
openWav(file2, out temp, out r1);
double[] odoubledata = new double[41769];
double[] odoubledata1 = new double[41769];
Console.WriteLine("-------cross correlation--------");
int n = 0;
int k = 0;
for (int i = 0; i < permanent.Length; i = i + 2)
{
Complex[] test1 = new Complex[2];
test1[0].Re = permanent[n];
test1[0].Im = 0;
test1[1].Re = permanent[n + 1];
test1[1].Im = 0;
FourierTransform.FFT(test1, FourierTransform.Direction.Forward);
odoubledata[n] = test1[0].Magnitude + test1[0].SquaredMagnitude;
odoubledata[n + 1] = test1[1].Magnitude + test1[1].SquaredMagnitude;
n = n + 1;
}
for (int i = 0; i < temp.Length; i = i + 2)
{
Complex[] test1 = new Complex[2];
test1[0].Re = temp[k];
test1[0].Im = 0;
test1[1].Re = temp[k + 1];
test1[1].Im = 0;
FourierTransform.FFT(test1, FourierTransform.Direction.Forward);
odoubledata1[k] = test1[0].Magnitude + test1[0].SquaredMagnitude;
odoubledata1[k + 1] = test1[1].Magnitude + test1[1].SquaredMagnitude;
k = k + 1;
}
double temwe2;
int offs;
CalcCrossCorrelation(odoubledata, odoubledata1, out offs, out temwe2);
Console.WriteLine("Similarity Total together " + temwe2);
}
I am not sure whether I am storing correct output values by summing Magnitude and Squared Magnitude.
来源:https://stackoverflow.com/questions/40143221/cross-correlation-and-fft-in-c-sharp-for-voice-authentication