热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UsingApple’svDSP/AccelerateFFT

原文地址:https:gerrybeauregard.wordpress.com20130128using-apples-vdspaccelerate-fft

原文地址:  https://gerrybeauregard.wordpress.com/2013/01/28/using-apples-vdspaccelerate-fft/


If you want to write code for signal processing on the Mac or iOS, you really should take advantage of Apple’s Accelerate framework. It provides an extensive library of highly optimized mathematical functions suitable for a wide range of signal processing applications.

While many of the functions are fairly straightforward to use, and well-documented in thevDSP Programming Guide, the FFT functions are a bit maddening, especially when doing FFTs of real signals, which is pretty much always the case when dealing with audio.

The following code example shows how to do a real-to-complex FFT of a real vector; convert from complex representation to magnitude and phase; convert it back to rectangular/complex representation; and do complex-to-real FFT, with the correct scaling to get back to the original signal.

//  main.cpp
//  AccelerateFFT
//
//  Demo of how to use Apple's blazingly fast but maddeningly confusing
//  real->complex and complex->real FFT functions.
//
//  Created by Gerry Beauregard (g.beauregard [at] ieee.org) on 2013-01-28.
//
//  Use this code however you like. No credit required, but if this code
//  saves you some hair-pulling, a hat-tip and kind comment is always
//  appreciated ;-)
 
#include
#include
 
const int LOG_N = 4; // Typically this would be at least 10 (i.e. 1024pt FFTs)
const int N = 1 < const float PI = 4*atan(1);
 
int main(int argc, const char * argv[])
{
    // Set up a data structure with pre-calculated values for
    // doing a very fast FFT. The structure is opaque, but presumably
    // includes sin/cos twiddle factors, and a lookup table for converting
    // to/from bit-reversed ordering. Normally you'd create this once
    // in your application, then use it for many (hundreds! thousands!) of
    // forward and inverse FFTs.
    FFTSetup fftSetup = vDSP_create_fftsetup(LOG_N, kFFTRadix2);
 
    // -------------------------------
    // Set up a bunch of buffers
 
    // Buffers for real (time-domain) input and output signals.
    float *x = new float[N];
    float *y = new float[N];
 
    // Initialize the input buffer with a sinusoid
    int BIN = 3;
    for (int k = 0; k         x[k] = cos(2*PI*BIN*k/N);
 
    // We need complex buffers in two different formats!
    DSPComplex *tempComplex = new DSPComplex[N/2];
 
    DSPSplitComplex tempSplitComplex;
    tempSplitComplex.realp = new float[N/2];
    tempSplitComplex.imagp = new float[N/2];
 
    // For polar coordinates
    float *mag = new float[N/2];
    float *phase = new float[N/2];
 
    // ----------------------------------------------------------------
    // Forward FFT
 
    // Scramble-pack the real data into complex buffer in just the way that's
    // required by the real-to-complex FFT function that follows.
    vDSP_ctoz((DSPComplex*)x, 2, &tempSplitComplex, 1, N/2);
 
    // Do real->complex forward FFT
    vDSP_fft_zrip(fftSetup, &tempSplitComplex, 1, LOG_N, kFFTDirection_Forward);
 
    // Print the complex spectrum. Note that since it's the FFT of a real signal,
    // the spectrum is conjugate symmetric, that is the negative frequency components
    // are complex conjugates of the positive frequencies. The real->complex FFT
    // therefore only gives us the positive half of the spectrum from bin 0 ("DC")
    // to bin N/2 (Nyquist frequency, i.e. half the sample rate). Typically with
    // audio code, you don't need to worry much about the DC and Nyquist values, as
    // they'll be very close to zero if you're doing everything else correctly.
    //
    // Bins 0 and N/2 both necessarily have zero phase, so in the packed format
    // only the real values are output, and these are stuffed into the real/imag components
    // of the first complex value (even though they are both in fact real values). Try
    // replacing BIN above with N/2 to see how sinusoid at Nyquist appears in the spectrum.
    printf("\nSpectrum:\n");
    for (int k = 0; k     {
        printf("%3d\t%6.2f\t%6.2f\n", k, tempSplitComplex.realp[k], tempSplitComplex.imagp[k]);
    }
 
    // ----------------------------------------------------------------
    // Convert from complex/rectangular (real, imaginary) coordinates
    // to polar (magnitude and phase) coordinates.
 
    // Compute magnitude and phase. Can also be done using vDSP_polar.
    // Note that when printing out the values below, we ignore bin zero, as the
    // real/complex values for bin zero in tempSplitComplex actually both correspond
    // to real spectrum values for bins 0 (DC) and N/2 (Nyquist) respectively.
    vDSP_zvabs(&tempSplitComplex, 1, mag, 1, N/2);
    vDSP_zvphas(&tempSplitComplex, 1, phase, 1, N/2);
 
    printf("\nMag / Phase:\n");
    for (int k = 1; k     {
        printf("%3d\t%6.2f\t%6.2f\n", k, mag[k], phase[k]);
    }
 
    // ----------------------------------------------------------------
    // Convert from polar coordinates back to rectangular coordinates.
 
    tempSplitComplex.realp = mag;
    tempSplitComplex.imagp = phase;
 
    vDSP_ztoc(&tempSplitComplex, 1, tempComplex, 2, N/2);
    vDSP_rect((float*)tempComplex, 2, (float*)tempComplex, 2, N/2);
    vDSP_ctoz(tempComplex, 2, &tempSplitComplex, 1, N/2);
 
    // ----------------------------------------------------------------
    // Do Inverse FFT
 
    // Do complex->real inverse FFT.
    vDSP_fft_zrip(fftSetup, &tempSplitComplex, 1, LOG_N, kFFTDirection_Inverse);
 
    // This leaves result in packed format. Here we unpack it into a real vector.
    vDSP_ztoc(&tempSplitComplex, 1, (DSPComplex*)y, 2, N/2);
 
    // Neither the forward nor inverse FFT does any scaling. Here we compensate for that.
    float scale = 0.5/N;
    vDSP_vsmul(y, 1, &scale, y, 1, N);
 
    // Assuming it's all correct, the input x and output y vectors will have identical values
    printf("\nInput & output:\n");
    for (int k = 0; k     {
        printf("%3d\t%6.2f\t%6.2f\n", k, x[k], y[k]);
    }
 
    return 0;
}


Note that in order to do anything really interesting with audio on the Mac or iOS (for example the audio time-stretching in my AudioStretch app), there’s loads of other stuff you need to learn how to do: setting up a real-time audio input and output; how to grab and window (Hanning, Hamming, etc.) frames of audio data; how to manipulate signals in the frequency domain; synthesis using overlap-add methods, etc.  Time-permitting, I might cover some of that in future posts.


推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • IB 物理真题解析:比潜热、理想气体的应用
    本文是对2017年IB物理试卷paper 2中一道涉及比潜热、理想气体和功率的大题进行解析。题目涉及液氧蒸发成氧气的过程,讲解了液氧和氧气分子的结构以及蒸发后分子之间的作用力变化。同时,文章也给出了解题技巧,建议根据得分点的数量来合理分配答题时间。最后,文章提供了答案解析,标注了每个得分点的位置。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
author-avatar
沙胆建筑_829
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有