{"id":576,"date":"2011-04-14T00:05:05","date_gmt":"2011-04-13T23:05:05","guid":{"rendered":"http:\/\/pkmital.com\/home\/?p=576"},"modified":"2011-04-14T00:05:05","modified_gmt":"2011-04-13T23:05:05","slug":"real-fftifft-with-the-accelerate-framework","status":"publish","type":"post","link":"https:\/\/pkmital.com\/home\/real-fftifft-with-the-accelerate-framework\/","title":{"rendered":"Real FFT\/IFFT with the Accelerate Framework"},"content":{"rendered":"<p>Apple&#8217;s Accelerate Framework can really speed up your code without thinking too much.  And it will also run on an iPhone.  Even still, I did bang my head a few times trying to get a straightforward Real FFT and IFFT working, even after consulting the Accelerate documentation (<a href=\"http:\/\/developer.apple.com\/library\/ios\/#documentation\/Accelerate\/Reference\/vDSPRef\/Reference\/reference.html\">reference<\/a> and <a href=\"http:\/\/developer.apple.com\/library\/ios\/#documentation\/Performance\/Conceptual\/vDSP_Programming_Guide\/SampleCode\/SampleCode.html\">source code<\/a>), stackoverflow (<a href=\"http:\/\/stackoverflow.com\/questions\/3398753\/using-the-apple-fft-and-accelerate-framework\">here<\/a> and <a href=\"http:\/\/stackoverflow.com\/questions\/1964955\/audio-file-fft-in-an-os-x-environment\">here<\/a>), and an existing implementation (thanks to Chris Kiefer and Mick Grierson).  Still, the previously mentioned examples weren&#8217;t very clear as they did not handle the case of overlapping FFTs which I was doing in the case of a STFT or they did not recover the power spectrum, or they just didn&#8217;t work for me (lots of blaring noise).  <\/p>\n<p>Get the code on my github:<br \/>\n<a href=\"http:\/\/github.com\/pkmital\/pkmFFT\">http:\/\/github.com\/pkmital\/pkmFFT<\/a><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n\/*\n *  pkmFFT.h\n *\n *  Real FFT wraper for Apple's Accelerate Framework\n *\n *  Created by Parag K. Mital - http:\/\/pkmital.com \n *  Contact: parag@pkmital.com\n *\n *  Copyright 2011 Parag K. Mital. All rights reserved.\n * \n *\tPermission is hereby granted, free of charge, to any person\n *\tobtaining a copy of this software and associated documentation\n *\tfiles (the &quot;Software&quot;), to deal in the Software without\n *\trestriction, including without limitation the rights to use,\n *\tcopy, modify, merge, publish, distribute, sublicense, and\/or sell\n *\tcopies of the Software, and to permit persons to whom the\n *\tSoftware is furnished to do so, subject to the following\n *\tconditions:\n *\t\n *\tThe above copyright notice and this permission notice shall be\n *\tincluded in all copies or substantial portions of the Software.\n *\n *\tTHE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,\t\n *\tEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n *\tOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n *\tNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n *\tHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n *\tWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n *\tFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n *\tOTHER DEALINGS IN THE SOFTWARE.\n *\n *  Additional resources: \n *      http:\/\/developer.apple.com\/library\/ios\/#documentation\/Accelerate\/Reference\/vDSPRef\/Reference\/reference.html\n *      http:\/\/developer.apple.com\/library\/ios\/#documentation\/Performance\/Conceptual\/vDSP_Programming_Guide\/SampleCode\/SampleCode.html\n *      http:\/\/stackoverflow.com\/questions\/3398753\/using-the-apple-fft-and-accelerate-framework\n *      http:\/\/stackoverflow.com\/questions\/1964955\/audio-file-fft-in-an-os-x-environment\n *     \n *\n *  This code is a very simple interface for Accelerate's fft\/ifft code.\n *  It was built out of hacking Maximilian (Mick Grierson and Chris Kiefer) and\n *  the above mentioned resources for performing a windowed FFT which could\n *  be used underneath of an STFT implementation\n *\n *  Usage:\n *\n *  \/\/ be sure to either use malloc or __attribute__ ((aligned (16))\n *  float *sample_data = (float *) malloc (sizeof(float) * 4096);\n *  float *allocated_magnitude_buffer =  (float *) malloc (sizeof(float) * 2048);\n *  float *allocated_phase_buffer =  (float *) malloc (sizeof(float) * 2048);\n *\n *  pkmFFT *fft;\n *  fft = new pkmFFT(4096);\n *  fft.forward(0, sample_data, allocated_magnitude_buffer, allocated_phase_buffer);\n *  fft.inverse(0, sample_data, allocated_magnitude_buffer, allocated_phase_buffer);\n *  delete fft;\n *\n *\/\n\n#include &lt;Accelerate\/Accelerate.h&gt;\n\nclass pkmFFT\n{\npublic:\n\n\tpkmFFT(int size = 4096, int window_size = 4096)\n\t{\n\t\tfftSize = size;\t\t\t\t\t\/\/ sample size\n\t\tfftSizeOver2 = fftSize\/2;\t\t\n\t\tlog2n = log2f(fftSize);\t\t\t\/\/ bins\n\t\tlog2nOver2 = log2n\/2;\n\t\t\n\t\tin_real = (float *) malloc(fftSize * sizeof(float));\n\t\tout_real = (float *) malloc(fftSize * sizeof(float));\t\t\n\t\tsplit_data.realp = (float *) malloc(fftSizeOver2 * sizeof(float));\n\t\tsplit_data.imagp = (float *) malloc(fftSizeOver2 * sizeof(float));\n\t\t\n\t\twindowSize = window_size;\n\t\twindow = (float *) malloc(sizeof(float) * windowSize);\n\t\tmemset(window, 0, sizeof(float) * windowSize);\n\t\tvDSP_hann_window(window, window_size, vDSP_HANN_DENORM);\n\t\t\n\t\tscale = 1.0f\/(float)(4.0f*fftSize);\n\t\t\n\t\t\/\/ allocate the fft object once\n\t\tfftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);\n\t\tif (fftSetup == NULL) {\n\t\t\tprintf(&quot;\\nFFT_Setup failed to allocate enough memory.\\n&quot;);\n\t\t}\n\t}\n\t~pkmFFT()\n\t{\n\t\tfree(in_real);\n\t\tfree(out_real);\n\t\tfree(split_data.realp);\n\t\tfree(split_data.imagp);\n\t\t\n\t\tvDSP_destroy_fftsetup(fftSetup);\n\t}\n\t\n\tvoid forward(int start, \n\t\t\t\t float *buffer, \n\t\t\t\t float *magnitude, \n\t\t\t\t float *phase)\n\t{\t\n\t\t\/\/multiply by window\n\t\tvDSP_vmul(buffer, 1, window, 1, in_real, 1, fftSize);\n\t\t\n\t\t\/\/convert to split complex format with evens in real and odds in imag\n\t\tvDSP_ctoz((COMPLEX *) in_real, 2, &amp;split_data, 1, fftSizeOver2);\n\t\t\n\t\t\/\/calc fft\n\t\tvDSP_fft_zrip(fftSetup, &amp;split_data, 1, log2n, FFT_FORWARD);\n\t\t\n\t\tsplit_data.imagp&#x5B;0] = 0.0;\n\t\t\n\t\tfor (i = 0; i &lt; fftSizeOver2; i++) \n\t\t{\n\t\t\t\/\/compute power \n\t\t\tfloat power = split_data.realp&#x5B;i]*split_data.realp&#x5B;i] + \n\t\t\t\t\t\t\tsplit_data.imagp&#x5B;i]*split_data.imagp&#x5B;i];\n\t\t\t\n\t\t\t\/\/compute magnitude and phase\n\t\t\tmagnitude&#x5B;i] = sqrtf(power);\n\t\t\tphase&#x5B;i] = atan2f(split_data.imagp&#x5B;i], split_data.realp&#x5B;i]);\n\t\t}\n\t}\n\t\n\tvoid inverse(int start, \n\t\t\t\t float *buffer,\n\t\t\t\t float *magnitude,\n\t\t\t\t float *phase, \n\t\t\t\t bool dowindow = true)\n\t{\n\t\tfloat *real_p = split_data.realp, *imag_p = split_data.imagp;\n\t\tfor (i = 0; i &lt; fftSizeOver2; i++) {\n\t\t\t*real_p++ = magnitude&#x5B;i] * cosf(phase&#x5B;i]);\n\t\t\t*imag_p++ = magnitude&#x5B;i] * sinf(phase&#x5B;i]);\n\t\t}\n\t\t\n\t\tvDSP_fft_zrip(fftSetup, &amp;split_data, 1, log2n, FFT_INVERSE);\n\t\tvDSP_ztoc(&amp;split_data, 1, (COMPLEX*) out_real, 2, fftSizeOver2);\n\t\t\n\t\tvDSP_vsmul(out_real, 1, &amp;scale, out_real, 1, fftSize);\n\t\t\n\t\t\/\/ multiply by window w\/ overlap-add\n\t\tif (dowindow) {\n\t\t\tfloat *p = buffer + start;\n\t\t\tfor (i = 0; i &lt; fftSize; i++) {\n\t\t\t\t*p++ += out_real&#x5B;i] * window&#x5B;i];\n\t\t\t}\n\t\t}\n\t}\n\t\nprivate:\n\t\n\tsize_t\t\t\t\tfftSize, \n\t\t\t\t\t\tfftSizeOver2,\n\t\t\t\t\t\tlog2n,\n\t\t\t\t\t\tlog2nOver2,\n\t\t\t\t\t\twindowSize,\n\t\t\t\t\t\ti;\t\t\t\t\t\n\t\n\tfloat\t\t\t\t*in_real, \n\t\t\t\t\t\t*out_real,\n\t\t\t\t\t\t*window;\n\t\n\tfloat\t\t\t\tscale;\n\t\n    FFTSetup\t\t\tfftSetup;\n    COMPLEX_SPLIT\t\tsplit_data;\n\t\n\t\n};\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Apple&#8217;s Accelerate Framework can really speed up your code without thinking too much. And it will also run on an iPhone. Even still, I did bang my head a few&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,14,16],"tags":[19,33,44,46,146,182,196,268,272,329],"class_list":["post-576","post","type-post","status-publish","format-standard","hentry","category-audio-visual","category-source-code","category-technology","tag-accelerate","tag-apple","tag-audio","tag-audio-processing","tag-fft","tag-ifft","tag-iphone","tag-optimization","tag-osx","tag-source-code"],"acf":[],"_links":{"self":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts\/576","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/comments?post=576"}],"version-history":[{"count":1,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts\/576\/revisions"}],"predecessor-version":[{"id":2443,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts\/576\/revisions\/2443"}],"wp:attachment":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/media?parent=576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/categories?post=576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/tags?post=576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}