gpt4 book ai didi

iOS FFT 绘制频谱

转载 作者:技术小花猫 更新时间:2023-10-29 10:51:11 35 4
gpt4 key购买 nike

我读过这些问题:

Using the Apple FFT and Accelerate Framework

How do I set up a buffer when doing an FFT using the Accelerate framework?

iOS FFT Accerelate.framework draw spectrum during playback

它们都描述了如何使用加速框架设置 fft。在他们的帮助下,我能够设置 fft 并获得基本的频谱分析仪。现在,我正在显示我从 fft 获得的所有值。但是,我只想显示 10-15 个或可变数量的条形图来表示某些频率。就像 iTunes 或 WinAmp 电平表一样。1. 我是否需要对一系列频率的幅度值进行平均?或者他们只是向您显示特定频率条的幅度?2. 另外,我需要将震级值转换为分贝吗?3. 如何将我的数据映射到某个范围。我是否针对我的声音位深度的最大分贝范围进行映射?获取 bin 的最大值将导致跳跃最大映射值。

我的渲染回调:

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, 0, nOver2 * sizeof(float));

obtainedReal = (float *) malloc(n * sizeof(float));
originalReal = (float *) malloc(n * sizeof(float));
frequencyArray = (float *) malloc(n * sizeof(float));

//-- window

UInt32 windowSize = maxSamples;
window = (float *) malloc(windowSize * sizeof(float));

memset(window, 0, windowSize * sizeof(float));
// vDSP_hann_window(window, windowSize, vDSP_HANN_DENORM);

vDSP_blkman_window(window, windowSize, 0);

vDSP_vmul(ioBuffer, 1, window, 1, in_real, 1, maxSamples);

//-- window

vDSP_ctoz((COMPLEX*)in_real, 2, &A, 1, maxSamples/2);

vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);

float 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);
vDSP_zvmags(&A, 1, obtainedReal, 1, nOver2);

Float32 one = 1;
vDSP_vdbcon(obtainedReal, 1, &one, obtainedReal, 1, nOver2, 0);

for (int i = 0; i < nOver2; i++) {
frequencyArray[i] = obtainedReal[i];
}


// Extract the maximum value
double fftMax = 0.0;
vDSP_maxmgvD((double *)obtainedReal, 1, &fftMax, nOver2);

float max = sqrt(fftMax);
}

播放一些音乐,我得到从 -96db 到 0db 的值。绘制一个点:

CGPointMake(i, kMaxSpectrumHeight * (1 - frequencyArray[i]/-96.));

给我一​​个相当圆润的曲线:

plot1

如果我不转换为 db,我可以通过将我的数组值乘以 10000 来绘图并获得漂亮的峰值。

plot2

我做错了什么吗?我如何才能显示可变数量的条形图?

最佳答案

  1. Do I need to average magnitude values from a range of frequencies? Or do they just show you a magnitude for the specific frequency bar?

是的,您肯定需要在您定义的范围内计算平均值。只显示一个 FFT bin 是疯狂的。

  1. Also, do I need to convert my magnitude values to db?

是的:dB 是对数刻度。并非巧合的是,人类的听觉也(大致)以对数尺度起作用。因此,如果您在绘制值之前采用值的 log2(),这些值对于人类来说看起来会更自然。

  1. How do I map my data to a certain range. Do I map against the max db range for my sounds bitdepth? Getting the max Value for a bin will lead to jumping max mapping values.

我发现最简单的事情(至少在概念上)是将您的值从任何格式转换为 0..1,即“标准化和缩放”浮点值。然后从那里你可以根据需要转换成你需要绘制的东西。例如

SInt16 rawValue = fft[0]; // let's say this comes back as 12990

float scaledValue = rawValue/32767.; // This is MAX_INT for 16-bit;
// dividing we get .396435438 which is much easier for most people
// to see conceptually as 39% of our max possible value

float displayValue = log2(scaledValue);

my_fft[0] = displayValue;

关于iOS FFT 绘制频谱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15568607/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com