{"id":591,"date":"2011-04-14T12:06:55","date_gmt":"2011-04-14T11:06:55","guid":{"rendered":"http:\/\/pkmital.com\/home\/?p=591"},"modified":"2011-04-14T12:06:55","modified_gmt":"2011-04-14T11:06:55","slug":"short-time-fourier-transform-using-the-accelerate-framework","status":"publish","type":"post","link":"https:\/\/pkmital.com\/home\/short-time-fourier-transform-using-the-accelerate-framework\/","title":{"rendered":"Short Time Fourier Transform using the Accelerate framework"},"content":{"rendered":"<p>Using the libraries pkmFFT and pkm::Mat, you can very easily perform a highly optimized short time fourier transform (STFT) with direct access to a floating-point based object.  <\/p>\n<p>Get the code on my github:<br \/>\n<a href=\"http:\/\/github.com\/pkmital\/pkmFFT\">http:\/\/github.com\/pkmital\/pkmFFT<\/a><br \/>\nDepends also on: <a href=\"http:\/\/github.com\/pkmital\/pkmMatrix\">http:\/\/github.com\/pkmital\/pkmMatrix<\/a><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n\/*\n *  pkmSTFT.h\n *\n *  STFT implementation making use of Apple's Accelerate Framework (pkmFFT)\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 *\n *  Usage:\n *\n *  \/\/ be sure to either use malloc or __attribute__ ((aligned (16))\n *  size_t buffer_size = 4096;\n *  float *sample_data = (float *) malloc (sizeof(float) * buffer_size);\n *  pkm::Mat magnitude_matrix, phase_matrix;\n *\n *  pkmSTFT *stft;\n *  stft = new pkmSTFT(512);\n *  stft.STFT(sample_data, buffer_size, magnitude_matrix, phase_matrix);\n *  fft.ISTFT(sample_data, buffer_size, magnitude_matrix, phase_matrix);\n *  delete stft;\n *\n *\/\n\n\n#include &quot;pkmFFT.h&quot;\n#include &quot;pkmMatrix.h&quot;\n\nclass pkmSTFT\n{\npublic:\n\n\tpkmSTFT(size_t size)\n\t{\n\t\tfftSize = size;\n\t\tnumFFTs = 0;\n\t\tfftBins = fftSize\/2;\n\t\thopSize = fftSize\/4;\n\t\twindowSize = fftSize;\n\t\tbufferSize = 0;\n\t\t\n\t\tinitializeFFTParameters(fftSize, windowSize, hopSize);\n\t}\n\t\n\tvoid initializeFFTParameters(size_t _fftSize, size_t _windowSize, size_t _hopSize)\n\t{\n\t\tfftSize = _fftSize;\n\t\thopSize = _hopSize;\n\t\twindowSize = _windowSize;\n\t\t\n\t\t\/\/ fft constructor\n\t\tFFT = new pkmFFT(fftSize);\n\t}\n\t\n\tvoid STFT(float *buf, size_t bufSize, pkm::Mat &amp;M_magnitudes, pkm::Mat &amp;M_phases)\n\t{\t\n\t\t\/\/ pad input buffer\n\t\tint padding = ceilf((float)bufSize\/(float)fftSize) * fftSize - bufSize;\n\t\tfloat *padBuf;\n\t\tif (padding) {\n\t\t\tprintf(&quot;Padding %d sample buffer with %d samples\\n&quot;, bufSize, padding);\n\t\t\tpadBufferSize = bufSize + padding;\n\t\t\tpadBuf = (float *)malloc(sizeof(float)*padBufferSize);\n\t\t\t\/\/ set padding to 0\n\t\t\tmemset(&amp;(padBuf&#x5B;bufSize]), 0, sizeof(float)*padding);\n\t\t\t\/\/ copy original buffer into padded one\n\t\t\tmemcpy(padBuf, buf, sizeof(float)*bufSize);\t}\n\t\telse {\n\t\t\tpadBuf = buf;\n\t\t\tpadBufferSize = bufSize;\n\t\t}\n\t\t\n\t\t\/\/ create output fft matrix\n\t\tnumWindows = (padBufferSize - fftSize)\/hopSize + 1;\n\t\t\n\t\tif (M_magnitudes.rows != numWindows &amp;&amp; M_magnitudes.cols != fftBins) {\n\t\t\tprintf(&quot;Allocating %d bins x %d windows matrix for STFT\\n&quot;, fftBins, numWindows);\n\t\t\tM_magnitudes.reset(numWindows, fftBins, true);\n\t\t\tM_phases.reset(numWindows, fftBins, true);\n\t\t}\n\t\t\n\t\t\/\/ stft\n\t\tfor (size_t i = 0; i &lt; numWindows; i++) {\n\t\t\t\n\t\t\t\/\/ get current col of freq mat\n\t\t\tfloat *magnitudes = M_magnitudes.row(i);\n\t\t\tfloat *phases = M_phases.row(i);\n\t\t\tfloat *buffer = padBuf + i*hopSize;\n\t\t\t\n\t\t\tFFT-&gt;forward(0, buffer, magnitudes, phases);\t\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\/\/ release padded buffer\n\t\tif (padding) {\n\t\t\tfree(padBuf);\n\t\t}\n\t}\n\t\n\t\n\tvoid ISTFT(float *buf, size_t bufSize, pkm::Mat &amp;M_magnitudes, pkm::Mat &amp;M_phases)\n\t{\n\t\tint padding = ceilf((float)bufSize\/(float)fftSize) * fftSize - bufSize;\n\t\tfloat *padBuf;\n\t\tif (padding) \n\t\t{\n\t\t\tprintf(&quot;Padding %d sample buffer with %d samples\\n&quot;, bufSize, padding);\n\t\t\tpadBufferSize = bufSize + padding;\n\t\t\tpadBuf = (float *)calloc(padBufferSize, sizeof(float));\n\t\t}\n\t\telse {\n\t\t\tpadBuf = buf;\n\t\t\tpadBufferSize = bufSize;\n\t\t}\n\t\t\n\t\tpkm::Mat M_istft(padBufferSize, 1, padBuf, false);\n\t\t\n\t\tfor(size_t i = 0; i &lt; numWindows; i++)\n\t\t{\n\t\t\tfloat *buffer = padBuf + i*hopSize;\n\t\t\tfloat *magnitudes = M_magnitudes.row(i);\n\t\t\tfloat *phases = M_phases.row(i);\n\t\t\t\n\t\t\tFFT-&gt;inverse(0, buffer, magnitudes, phases);\n\t\t}\n\n\t\tmemcpy(buf, padBuf, sizeof(float)*bufSize);\n\t\t\/\/ release padded buffer\n\t\tif (padding) {\n\t\t\tfree(padBuf);\n\t\t}\n\t}\n\t\nprivate:\n\t\n\tpkmFFT\t\t\t\t*FFT;\n\t\n\tsize_t\t\t\t\tsampleRate,\n\t\t\t\t\t\tnumFFTs,\n\t\t\t\t\t\tfftSize,\n\t\t\t\t\t\tfftBins,\n\t\t\t\t\t\thopSize,\n\t\t\t\t\t\tbufferSize,\n\t\t\t\t\t\tpadBufferSize,\n\t\t\t\t\t\twindowSize,\n\t\t\t\t\t\tnumWindows;\n};\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Using the libraries pkmFFT and pkm::Mat, you can very easily perform a highly optimized short time fourier transform (STFT) with direct access to a floating-point based object. Get the code&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,196,272,329],"class_list":["post-591","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-iphone","tag-osx","tag-source-code"],"acf":[],"_links":{"self":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts\/591","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=591"}],"version-history":[{"count":0,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/posts\/591\/revisions"}],"wp:attachment":[{"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/media?parent=591"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/categories?post=591"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pkmital.com\/home\/wp-json\/wp\/v2\/tags?post=591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}