我正在寻找从声音信号中提取音高.
IRC上的某个人刚刚向我解释了如何采用双FFT实现这一目标.特别:
我正在尝试使用vDSP
我无法理解我之前没有遇到过这种技术.我做了很多狩猎和提问; 几周值得.更重要的是,我无法理解为什么我没有想到它.
我试图用vDSP库实现这一目标.它看起来好像有处理所有这些任务的功能.
但是,我想知道最终结果的准确性.
我之前使用的技术是将单个FFT的频率区域扫描为局部最大值.当它遇到一个时,它使用一种狡猾的技术(自上次FFT以来的相位变化)来更准确地将实际峰值放置在箱内.
我担心这种精确度会因为我在这里介绍的技术而丢失.
我想这种技术可以在第二次FFT之后使用,以准确地得到基波.但有点看起来信息在第2步中丢失了.
由于这是一个潜在的棘手过程,有经验的人可以只看一下我正在做的事情并检查它的理智吗?
此外,我听说有一种替代技术涉及在相邻的箱子上安装二次方.这是否具有可比性?如果是这样,我会赞成它,因为它不涉及记住bin阶段.
所以,问题:
有人能指出我对这种技术的一些研究或文献吗?
主要问题:它足够准确吗?可以提高准确度吗?一位专家刚刚告诉我,准确性是不充分的.这是行的结束吗?
皮
PS当我想创建标签时,我很生气,但不能.:| 我已向维护人员建议SO跟踪尝试的标签,但我确信我被忽略了.我们需要vDSP标签,加速框架,倒谱分析
//编辑...
我正在编辑我的问题,以解决专门处理非二次幂图像的问题.我有一个基本结构,适用于尺寸为256x256或1024x1024的方形灰度图像,但无法看到如何推广到任意大小的图像.fft函数似乎希望你包含宽度和高度的log2,但是它不清楚如何解压缩结果数据,或者数据是否只是被扰乱.我认为显而易见的事情是将npot图像置于较大的全黑图像中,然后在查看数据时忽略这些位置中的任何值.但是想知道是否有一种不太笨拙的方法来处理npot数据.
//...END编辑
我在使用Accelerate Framework文档时遇到了一些麻烦.我通常会使用FFTW3,但是我无法在实际的IOS设备上进行编译(请参阅此问题).任何人都可以指向使用Accelerate的超级简单实现,它执行如下操作:
1)将图像数据转换为适当的数据结构,可以传递给Accelerate的FFT方法.
在FFTW3中,最简单的是,使用灰度图像,这涉及将无符号字节放入"fftw_complex"数组中,该数组只是两个浮点数的结构,一个包含实数值,另一个包含虚数(和虚数在哪里)每个像素初始化为零).
2)采用该数据结构并对其执行FFT.
3)打印出幅度和相位.
4)对其执行IFFT.
5)根据IFFT产生的数据重新创建原始图像.
虽然这是一个非常基本的例子,但我在使用Apple网站上的文档时遇到了麻烦.Pi的SO 答案非常有用,但我仍然对如何使用Accelerate使用灰度(或彩色)2D图像执行此基本功能感到困惑.
无论如何,任何指针或特别是一些处理2D图像的简单工作代码都会非常有用!
编辑\\\
好的,花了一些时间深入研究文档和SO上的一些非常有用的代码以及pkmital的github repo,我有一些工作代码,我以为我会发布自1)我花了一段时间来计算它和2)因为我有几个剩下的问题......
初始化FFT"计划".假设一个方形的二次幂图像:
#include <Accelerate/Accelerate.h>
...
UInt32 N = log2(length*length);
UInt32 log2nr = N / 2;
UInt32 log2nc = N / 2;
UInt32 numElements = 1 << ( log2nr + log2nc );
float SCALE = 1.0/numElements;
SInt32 rowStride = 1;
SInt32 columnStride = 0;
FFTSetup setup = create_fftsetup(MAX(log2nr, log2nc), FFT_RADIX2);
Run Code Online (Sandbox Code Playgroud)
传入一个字节数组,用于方形二次灰度图像并将其转换为COMPLEX_SPLIT:
COMPLEX_SPLIT in_fft;
in_fft.realp = ( float* ) …Run Code Online (Sandbox Code Playgroud) 我读过这些问题:
iOS FFT Accerelate.framework在播放期间绘制频谱
它们都描述了如何使用加速框架设置fft.在他们的帮助下,我能够设置fft并获得一个基本的频谱分析仪.现在,我正在显示我从fft获得的所有值.但是,我只想显示10-15或一个可变数量的条形图来确定某些频率.就像iTunes或WinAmp Level Meter一样.1.我是否需要从一系列频率中平均幅度值?或者他们只是向您展示特定频率条的幅度?2.此外,我是否需要将我的幅度值转换为db?3.如何将数据映射到特定范围.我是否映射了我的声音bitdepth的最大db范围?获取bin的最大值将导致跳转最大映射值.
我的RenderCallback:
static OSStatus PlaybackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
UInt32 maxSamples = kAudioBufferNumFrames;
UInt32 log2n = log2f(maxSamples); //bins
UInt32 n = 1 << log2n;
UInt32 stride = 1;
UInt32 nOver2 = n/2;
COMPLEX_SPLIT A;
float *originalReal, *obtainedReal, *frequencyArray, *window, *in_real;
in_real = (float *) malloc(maxSamples * sizeof(float));
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
memset(A.imagp, …Run Code Online (Sandbox Code Playgroud) 我被 Swift 中的插值卡住了。任何人都可以帮助我吗?
我想将浮点数组(例如[0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0])插入另一个具有给定大小(例如128)的数组中。我找到了一篇文章(Use Linear Interpolation to Construct New Data Points),它展示了如何实现这些东西。
有两种方法(您可以在下面看到结果,它们的表现如何):
vDSP_vgenp和的线性插值vDSP_vlint问题是这两种技术都没有实现我的期望,如截图 3 所示。如何使插值分布更平滑?我想看到一个立方体状的曲线。
初始情节:

线性插值:
import Accelerate
let n = vDSP_Length(128)
let stride = vDSP_Stride(1)
let values: [Float] = [0, 0, 100, 25, 0, 0, 0, 25, 0, 0, 0]
let indices: [Float] = [0, 11, 23, 34, 46, 58, 69, …Run Code Online (Sandbox Code Playgroud) 更新:请参阅下面的其他问题以及更多代码;
我正在尝试编码模糊图像的类别.我的出发点是Jeff LaMarche的样本.虽然这(在其他人提出的修正之后)工作正常,但是对于我的要求来说这是一个数量级太慢 - 在3GS上花费大约3秒来做一个体面的模糊,我想把它降到0.5以下秒为全屏(更快更好).
他提到Accelerate框架作为性能增强,所以我花了最后一天看这个,特别是vDSP_f3x3,根据Apple Documenation
通过使用3x3内核执行二维卷积来过滤图像; 单精度.
完美 - 我有一个合适的滤镜矩阵,我有一个图像...但这是我难倒的地方.
vDSP_f3x3假设图像数据是(float*),但我的图像来自;
srcData = (unsigned char *)CGBitmapContextGetData (context);
Run Code Online (Sandbox Code Playgroud)
并且上下文来自CGBitmapContextCreate和kCGImageAlphaPremultipliedFirst,所以我的srcData实际上是ARGB,每个组件有8位.
我怀疑我真正需要的是带有float组件的上下文,但根据Quartz文档,kCGBitMapFloatComponents仅适用于Mac OS而不是iOS :-(
有没有一种真正快速的方法使用加速框架将我所拥有的整数组件转换为vDSP_f3x3需要的浮点组件?我的意思是我可以自己做,但是当我这样做,然后卷积,然后转换回来,我怀疑我会比现在更慢,因为我可能会像我一样卷入.
也许我的方法不对?
有没有人对我使用vDSP在iPhone上进行一些图像处理有一些提示?我能找到的文档是非常以参考为导向的,并且在涉及到这种事情时并不是非常新手友好.
如果有人有真正快速模糊的参考(和高品质,而不是降低分辨率,然后重新调整我见过的东西,看起来裤子),那将是晶圆厂!
编辑:
谢谢@Jason.我已经完成了它并且它几乎正常工作,但现在我的问题是虽然图像确实模糊,但在每次调用时它都会向左移动1个像素.它似乎也使图像变成黑白,但这可能是另一回事.
这段代码中是否有任何内容显然是错误的?我还没有优化它,它有点粗糙,但希望卷积代码足够清晰.
CGImageRef CreateCGImageByBlurringImage(CGImageRef inImage, NSUInteger pixelRadius, NSUInteger gaussFactor)
{
unsigned char *srcData, *finalData;
CGContextRef context = CreateARGBBitmapContext(inImage);
if (context == NULL)
return NULL;
size_t width = CGBitmapContextGetWidth(context);
size_t height = CGBitmapContextGetHeight(context);
size_t bpr = CGBitmapContextGetBytesPerRow(context);
int componentsPerPixel = 4; // ARGB
CGRect rect = {{0,0},{width,height}};
CGContextDrawImage(context, rect, …Run Code Online (Sandbox Code Playgroud) 我正在为iOS(即iPhone或iPad)实现大量使用快速傅里叶变换(以及一些信号处理操作,如插值和重采样)的计算密集型应用程序.什么是允许在iOS上运行FFT的最佳库和API?
我简要介绍了Apple Metal以及Apple vDSP.我不确定vDSP是否使用GPU,尽管它似乎是高度并行化并使用SIMD.Metal似乎允许访问GPU用于计算密集型应用程序,但我无法找到用于FFT和基本信号处理操作的库(类似于AMD的clFFT).Apple是否提供此类库?
是否有其他适用于iOS的GPU适用于计算密集型应用程序的API和库?
谢谢.
我想弄清楚vDSP功能,我得到的结果很奇怪.
这与这个问题有关:
使用std :: complex和iPhone的vDSP功能
基本上我试图理解vDSP_vdist,因为我开始使用std :: complex <float>的向量.现在AFAIK我应该能够通过以下方式计算幅度:
// std::abs of a complex does sqrtf( r^2 + i^2 ).
pOut[idx] = std::abs( pIn[idx] );
Run Code Online (Sandbox Code Playgroud)
然而,当我这样做时,我看到光谱反射在矢量的中点附近.这很奇怪.
但奇怪的是,如果我使用vDSP_ztoc后跟vDSP_vdist,我会得到我期望的结果.所以我写了一些代码来试着理解什么是错的.
bool VecMagnitude( float* pOut, const std::complex< float >* pIn, unsigned int num )
{
std::vector< float > realTemp( num );
std::vector< float > imagTemp( num );
DSPSplitComplex dspsc;
dspsc.realp = &realTemp.front();
dspsc.imagp = &imagTemp.front();
vDSP_ctoz( (DSPComplex*)pIn, 1, &dspsc, 1, num );
int idx = 0;
while( idx < num )
{
if ( …Run Code Online (Sandbox Code Playgroud) 在Accelerate Framework的vDSP功能中,所有功能都要求您输入结果向量.如果我不再需要原始输入向量中的任何内容,将输入向量(或其中一个输入向量)作为结果向量传递是否正确?
我的意思是:
vDSP_vsadd(input_vector,1,scalar_addition,input_vector,1,length);
Run Code Online (Sandbox Code Playgroud)
这将采用input_vector并向所有元素添加scalar_addition.结果将存储在input_vector中.
为运行 IOS 的设备生成正弦波的最有效方法是什么。出于练习的目的,假设频率为 440Hz,采样率为 44100Hz,采样率为 1024。
一个普通的 C 实现看起来像。
#define SAMPLES 1024
#define TWO_PI (3.14159 * 2)
#define FREQUENCY 440
#define SAMPLING_RATE 44100
int main(int argc, const char * argv[]) {
float samples[SAMPLES];
float phaseIncrement = TWO_PI * FREQUENCY / SAMPLING_RATE;
float currentPhase = 0.0;
for (int i = 0; i < SAMPLES; i ++){
samples[i] = sin(currentPhase);
currentPhase += phaseIncrement;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
要利用 Accelerate Framework 和 vecLib vvsinf 函数,可以将循环更改为仅执行加法操作。
#define SAMPLES 1024
#define TWO_PI (3.14159 * 2) …Run Code Online (Sandbox Code Playgroud) 在2006 年 11 月一篇关于使用vDSP向量化代码的有用但有些过时的文章中,作者做出了这样的声明:
\n\n\n\n\n需要记住的重要一点是,只有步长等于 1 的操作才能提供速度极快的矢量化代码。
\n
今天仍然如此吗?即使是在具有更强大矢量内在函数的较新英特尔处理器上?
\n\n我问这个问题是因为我正在编写一些矩阵数学例程,并且刚刚开始将它们全部切换为使用类似Fortran的列优先顺序,以便更容易地与MATLAB、BLAS和LAPACK兼容。但现在我发现对vDSP的一些调用需要在不再连续的向量上工作\xe2\x80\xa6
\n\n目前,这些vDSP调用是我的代码所执行的瓶颈例程。并不是说情况总是如此,但至少现在我不想放慢它们的速度,只是为了使对其他库的调用更简单。
\n\n我现在最常调用的vDSP例程是vDSP_distancesq例程是以防万一会产生影响。
vdsp ×10
fft ×4
ios ×4
iphone ×2
accelerate ×1
c++ ×1
core-audio ×1
cubic-spline ×1
detection ×1
gpgpu ×1
intrinsics ×1
objective-c ×1
performance ×1
pitch ×1
spectrum ×1
swift ×1
vmat ×1