- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试从 iPhone/iPod 音乐库获取频率以用于 iPod 库上的频谱应用程序,帮助自己 reading-audio-samples-via-avassetreader获取音频样本,然后使用 using-the-apple-fft-and-accelerate-framework和 Apple vDSP Samples ,但不知何故,我在某处错了,无法计算频率。
所以一步一步:
这是从 iPod mp3 库获取频率的正确方法吗?
这是我的代码:
static COMPLEX_SPLIT A;
static FFTSetup setupReal;
static uint32_t log2n, n, nOver2;
static int32_t stride;
static float *obtainedReal;
static float scale;
+ (void)initialize
{
log2n = 10;
n = 1 << log2n;
stride = 1;
nOver2 = n / 2;
A.realp = (float *) malloc(nOver2 * sizeof(float));
A.imagp = (float *) malloc(nOver2 * sizeof(float));
obtainedReal = (float *) malloc(n * sizeof(float));
setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2);
}
- (float) performAcceleratedFastFourierTransForAudioBuffer:(AudioBufferList)ioData
{
NSUInteger * sampleIn = (NSUInteger *)ioData.mBuffers[0].mData;
for (int i = 0; i < nOver2; i++) {
double multiplier = 0.5 * (1 - cos(2*M_PI*i/nOver2-1));
A.realp[i] = multiplier * sampleIn[i];
A.imagp[i] = 0;
}
memset(ioData.mBuffers[0].mData, 0, ioData.mBuffers[0].mDataByteSize);
vDSP_fft_zrip(setupReal, &A, stride, log2n, FFT_FORWARD);
vDSP_zvmags(&A, 1, A.realp, 1, nOver2);
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);
vDSP_ztoc(&A, 1, (COMPLEX *)obtainedReal, 2, nOver2);
int peakIndex = 0;
for (size_t i=1; i < nOver2-1; ++i) {
if ((obtainedReal[i] > obtainedReal[i-1]) && (obtainedReal[i] > obtainedReal[i+1]))
{
peakIndex = i;
break;
}
}
//here I don't know how to calculate frequency with my data
float frequency = obtainedReal[peakIndex-1] / 44100 / n;
vDSP_destroy_fftsetup(setupReal);
free(obtainedReal);
free(A.realp);
free(A.imagp);
return frequency;
}
我得到了 1.485757
和 1.332233
作为我的第一个频率
最佳答案
在我看来,FFT 到复数输入的转换存在问题。 vDSP_ctoz()
将实部和虚部交错的缓冲区拆分为两个缓冲区,一个是实部,一个是虚部。您对该函数的输入似乎只是已转换为 COMPLEX
的真实数据。这意味着您对 vDSP_ctoz()
的输入缓冲区只有所需长度的一半,并且正在转换超出缓冲区大小的一些垃圾数据。
您需要创建 sampleOut
的长度为 2*n
并设置所有其他值(实部),或者更好的是,您可以绕过 >vDSP_ctoz()
并直接将您的输入数据复制到 A.realp
并将 A.imagp
设置为零。 vDSP_ctoz()
仅在连接到生成交错复杂数据的源时才需要。
编辑
好吧,我认为我的第一个建议是错误的,因为 vDSP 文档说实到复就地 fft 的实际输入应该格式化为拆分复数格式,这样 imagp
包含偶数样本,realp
包含奇数样本。我没有实际使用过 vDSP 库,但我熟悉很多其他 FFT 库,但我错过了那个细节。
在调用 vDSP_zvmags(&A, 1, A.realp, 1, nOver2);
之后,您应该能够使用 A.realp
找到峰值点,A.realp
应该包含 FFT 输出的幅度平方,它是标量。如果您要进行缩放,则应在 mag2 操作之前完成,但如果您只是寻找峰值,则可能不需要。
要获得 FFT 输出表示的实际频率,请使用以下公式:
F = (i * Fs) / N, i=0,1,...,N/2
在哪里
i
是FFT输出缓冲区的索引Fs
为音频采样率N
为FFT长度
因此您的计算可能如下所示:
float frequency = (peakIndex * 44100) / n;
请记住,vDSP 仅为实际输入返回输入频谱的前半部分,因为后半部分是冗余的。因此 FFT 输出表示从 0
到 Fs/2
的频率。
另一个注意事项是,我不知道您的寻峰算法是否能很好地工作,因为 FFT 输出不会很平滑并且经常会有很多振荡。您只是在两个相邻样本较低的地方获取第一个样本。如果您只想找到一个峰值,最好只找到整个输出的最大幅度。如果你想找到多个峰值,你将不得不做一些更复杂的事情。
关于ios - 从 AvassetReader 和 vDSP_FFT 获取 iPhone mp3 频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5858494/
我正在使用以下代码播放声音,过一会儿它将停止播放声音,这是因为我相信有太多的Mediaplayer打开实例,所以我添加了一个额外的mp.release();,这只会使我的应用程序崩溃(目前已被注释掉)
我正在查看 XV-6 代码,它通过它识别 MP 结构。它首先在 EBDA 的第一个 kb 中搜索。代码是这样的 static struct mp* mpsearch(void) { uchar *
我在我的应用程序中使用 Mp 饼图。它显示非常小的尺寸,我试图增加它的尺寸但它没有增加它的尺寸。我无法找出问题所在。请告诉我们如何增加尺寸。 这是我的代码: public class MPpiecha
如何使用 MPAndroidChart 实现此目的? 使用版本:com.github.PhilJay:MPAndroidChart:v3.1.0-alpha 添加图例和饼图边距的代码: private
亲爱的社区,我面临以下问题,我正在使用此处提供的 MP android 图表库创建条形图:https://github.com/PhilJay/MPAndroidChart . 我想为我的条设置渐变背
我正在使用 SAS MP Connect 开发我的第一段代码,以运行同一个 sas 作业的并行线程。 我知道 MP CONNECT 仅受可用 CPU 数量的物理限制,但理想情况下我不想在我的工作中使用
我最近购买了在 Linux 服务器上运行的 Stata MP12(8 核)许可证。 有没有人写过 Stata 程序,比如说模拟研究来测试 Stata MP 的性能?我想监视在作业处理过程中实际使用的内
我将不胜感激任何“一步一步”指南,说明如何更改 PHP/HTML 页面上的动态数据库连接/连接字符串/等上的代码,使其“即插即用”工作通过 ftp 将页面和 MySQL 数据库托管在“Azure 网站
试图在我的应用程序中放置一个“暂停”按钮,以播放一些声音片段循环播放。 当我打电话mp.pause();一切都破了,我完全迷路了! 这是我正在使用的方法。 protected void man
我想使用 Mp Chart 创建折线图 我想要实现的是这张图片 但是到目前为止我已经得到了这个。 我使用的代码是这个 private fun setData() { val entries
通常,我可能会编写一个类似simd的循环: float * x = (float *) malloc(10 * sizeof(float)); float * y = (float *) malloc
在与堆栈空间、OpenMP 以及如何处理这些问题相关的其他帖子上,有很多回复。但是,我找不到信息来真正理解 OpenMP 调整编译器选项的原因: 原因是什么-fopenmp在 gfortran 中暗示
我有一段代码,可以根据漂移、波动性和随机数计算任意给定日期的股票价格。但是当我检查输出列表时 - 它们是算术级数,而不是几何级数(幂函数)。我共享的变量有问题吗? 代码如下: #include #i
我正在尝试在 C++11 中并行化动态编程算法使用这种方法: void buildBaseCases() { cout << "Building base cases" << endl
我正在 open MP 中实现并行点积 我有这个代码: #include #include #include #include #include #include #define SIZE
我有一台服务器已经将近 4 年了,直到现在我都没有遇到任何问题(主机端)。我一直在更换主机,因为 ddos 的东西试图找到最适合我的东西。现在我买了一个 VPS(这不是我的第一个)并尝试运行我的服
所以我有两个内部平行区域的外部平行区域。是否可以将 2 个线程放入外部平行线,将 4 个线程放入每个内部平行线?我做了这样的东西,但它似乎无法按照我想要的方式工作。有什么建议吗? start_r =
我希望有人指出我们遇到的问题或解决方法。 使用/MP 编译项目时,似乎只有同一文件夹中的文件会同时编译。我使用 Process Explorer 滑动命令行并确认行为。 项目过滤器似乎对并发编译的内容
本文整理了Java中me.chanjar.weixin.mp.api.WxMpMessageRouter类的一些代码示例,展示了WxMpMessageRouter类的具体用法。这些代码示例主要来源于G
我正在监视 Stata/MP(Stata/SE 的多核版本)的 CPU 和内存使用情况,但我不是 Stata 程序员(更像是 Perl 人)。 任何人都可以发布一些代码,利用公共(public)数据集
我是一名优秀的程序员,十分优秀!