iPhone FFT mit Accelerate-framework vDSP
Ich bin habend Schwierigkeit der Implementierung einer FFT mit vDSP. Ich verstehe die Theorie, aber bin auf der Suche nach einem bestimmten code-Beispiel bitte.
Ich habe Daten aus einer wav-Datei wie folgt:
Frage 1. Wie bekomme ich die audio-Daten in den FFT?
Frage 2. Wie bekomme ich die Ausgabe von Daten aus dem FFT?
Frage 3. Das ultimative Ziel ist zu prüfen, für niederfrequente Töne. Wie kann ich dies tun?
-(OSStatus)open:(CFURLRef)inputURL{
OSStatus result = -1;
result = AudioFileOpenURL (inputURL, kAudioFileReadPermission, 0, &mAudioFile);
if (result == noErr) {
//get format info
UInt32 size = sizeof(mASBD);
result = AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataFormat, &size, &mASBD);
UInt32 dataSize = sizeof packetCount;
result = AudioFileGetProperty(mAudioFile, kAudioFilePropertyAudioDataPacketCount, &dataSize, &packetCount);
NSLog([NSString stringWithFormat:@"File Opened, packet Count: %d", packetCount]);
UInt32 packetsRead = packetCount;
UInt32 numBytesRead = -1;
if (packetCount > 0) {
//allocate buffer
audioData = (SInt16*)malloc( 2 *packetCount);
//read the packets
result = AudioFileReadPackets (mAudioFile, false, &numBytesRead, NULL, 0, &packetsRead, audioData);
NSLog([NSString stringWithFormat:@"Read %d bytes, %d packets", numBytesRead, packetsRead]);
}
}
return result;
}
FFT-code unten:
log2n = N;
n = 1 << log2n;
stride = 1;
nOver2 = n / 2;
printf("1D real FFT of length log2 ( %d ) = %d\n\n", n, log2n);
/* Allocate memory for the input operands and check its availability,
* use the vector version to get 16-byte alignment. */
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
originalReal = (float *) malloc(n * sizeof(float));
obtainedReal = (float *) malloc(n * sizeof(float));
if (originalReal == NULL || A.realp == NULL || A.imagp == NULL) {
printf("\nmalloc failed to allocate memory for the real FFT"
"section of the sample.\n");
exit(0);
}
/* Generate an input signal in the real domain. */
for (i = 0; i < n; i++)
originalReal[i] = (float) (i + 1);
/* Look at the real signal as an interleaved complex vector by
* casting it. Then call the transformation function vDSP_ctoz to
* get a split complex vector, which for a real signal, divides into
* an even-odd configuration. */
vDSP_ctoz((COMPLEX *) originalReal, 2, &A, 1, nOver2);
/* Set up the required memory for the FFT routines and check its
* availability. */
setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);
if (setupReal == NULL) {
printf("\nFFT_Setup failed to allocate enough memory for"
"the real FFT.\n");
exit(0);
}
/* Carry out a Forward and Inverse FFT transform. */
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_INVERSE);
/* Verify correctness of the results, but first scale it by 2n. */
scale = (float) 1.0 / (2 * n);
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);
/* The output signal is now in a split real form. Use the function
* vDSP_ztoc to get a split real vector. */
vDSP_ztoc(&A, 1, (COMPLEX *) obtainedReal, 2, nOver2);
/* Check for accuracy by looking at the inverse transform results. */
Compare(originalReal, obtainedReal, n);
Dank
- Wenn alles, was Sie tun möchten, ist zu erkennen niederfrequenten Töne dann per FFT kann overkill. Welche Frequenz/Frequenzen sind Sie auf der Suche nach, und mit wie viel Auflösung ?
- Ich bin auf der Suche nach allen Frequenzen, die enthalten drum-oder bass-sounds, so dass ich reagieren kann, um die beats. Dank
- in diesem Fall könnte man sich besser aus mit einem low-pass-filter + Hüllkurven-Detektor - einfacher zu implementieren und sollte es einfacher sein, sich auf die Akkulaufzeit, da es viel weniger rechenintensiv.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Stellen Sie Ihre audio-sample-Daten in die Reale Teil der Eingabe, und keine imaginären Teil.
Wenn Sie interessiert sind, in der Größenordnung von jeder bin-in die Frequenz-Domäne, dann berechnen Sie
sqrt(re*re + im*im)
für jeden Ausgang bin. Wenn Sie nur daran interessiert sind, in relative Größenordnung, dann können Sie drop die sqrt-und nur die Berechnung der magnitude squared,(re*re + im*im)
.Würden Sie Blick auf die Größen der Behälter oder Behälter (siehe (2)), die entsprechend Ihrer Frequenz oder Frequenzen von Interesse. Wenn die Abtastrate ist Fs, und Ihre FFT-Größe N ist, dann die entsprechende Frequenz für die Ausgabe bin
i
ist gegeben durchf = i * Fs /N
. Umgekehrt, wenn Sie daran interessiert sind, in einer bestimmten Frequenz f, dann den Papierkorb von Interesse,i
, ist gegeben durchi = N * f /Fs
.Zusätzlicher Hinweis: Sie benötigen, um eine geeignete Fenster-Funktion (z.B. Hann aka Hanning) auf Ihrer FFT-Eingangsdaten vor der Berechnung der FFT selbst.
Können Sie überprüfen, äpfel Dokumentation darüber und nehmen gute Pflege von Daten Verpackung.
Hier ist mein Beispiel
Eine Sache, die Sie müssen vorsichtig sein, um die DC-Komponente des FFT berechnet. Verglich ich meine Ergebnisse mit der fftw-Bibliothek FFT-und den Imaginärteil der Transformation, berechnet mit der vDSP Bibliothek hatte immer einen anderen Wert an index 0 (die 0 bedeutet die Frequenz, also DC).
Eine weitere Maßnahme habe ich mich beworben, wurde zu teilen sowohl die realen und imaginären Teile, die durch einen Faktor von 2. Ich denke, dies ist aufgrund des verwendeten Algorithmus in der Funktion. Auch diese beiden Probleme traten in den FFT-Prozess, aber nicht in der IFFT-Prozess.
Ich verwendet vDSP_fft_zrip. Ich hoffe, dass dies helfen kann.
Paolo