【发布时间】:2015-03-06 16:45:30
【问题描述】:
我知道这个问题已经被问过一百次了……但我对我的结果感到沮丧,所以我想再问一次。在深入研究 fft 之前,我需要弄清楚这个简单的任务。
我需要检测音频文件中的 20 赫兹音调。我自己插入 20hz 音调,就像在图片中一样。 (可以是任何频率,只要听众听不到,所以我想我应该选择20hz到50hz左右的频率)
有关音频文件的信息。
afinfo 1.m4a
File: 1.m4a
File type ID: adts
Num Tracks: 1
----
Data format: 1 ch, 22050 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
Channel layout: Mono
estimated duration: 8.634043 sec
audio bytes: 42416
audio packets: 219
bit rate: 33364 bits per second
packet size upper bound: 768
maximum packet size: 319
audio data file offset: 0
optimized
format list:
[ 0] format: 1 ch, 22050 Hz, 'aac ' (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame
Channel layout: Mono
----
我遵循了这三个教程,并提出了一个可以读取音频缓冲区并为我提供 fft 双打的工作代码。
http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html
https://github.com/alexbw/iPhoneFFT
How do I obtain the frequencies of each value in an FFT?
我读取数据如下
// If there's more packets, read them
inCompleteAQBuffer->mAudioDataByteSize = numBytes;
CheckError(AudioQueueEnqueueBuffer(inAQ,
inCompleteAQBuffer,
(sound->packetDescs?nPackets:0),
sound->packetDescs),
"couldn't enqueue buffer");
sound->packetPosition += nPackets;
int numFrequencies=2048;
int kNumFFTWindows=10;
SInt16 *testBuffer = (SInt16*)inCompleteAQBuffer->mAudioData; //Read data from buffer...!
OouraFFT *myFFT = [[OouraFFT alloc] initForSignalsOfLength:numFrequencies*2 andNumWindows:kNumFFTWindows];
for(long i=0; i<myFFT.dataLength; i++)
{
myFFT.inputData[i] = (double)testBuffer[i];
}
[myFFT calculateWelchPeriodogramWithNewSignalSegment];
for (int i=0;i<myFFT.dataLength/2;i++) {
NSLog(@"the spectrum data %d is %f ",i,myFFT.spectrumData[i]);
}
和我的输出日志类似
Everything checks out for 4096 samples of data
Set up all values, about to init window type 2
the spectrum data 0 is 42449.823771
the spectrum data 1 is 39561.024361
.
.
.
.
the spectrum data 2047 is -42859933071799162597786649755206634193030992632381393031503716729604050285238471034480950745056828418192654328314899253768124076782117157451993697900895932215179138987660717342012863875797337184571512678648234639360.000000
我知道我还没有计算幅度,但我怎样才能检测到声音中有 20 赫兹呢?我需要学习 Goertzel 算法吗?
【问题讨论】:
-
从您的图片中,我不清楚您是在以较低频率突发的 20Hz 正弦波还是以 20Hz 突发的较高频率正弦波。
-
先做一个低通滤波。然后使用自相关,对于噪声信号,它通常比 FFT 中的谐波更好
-
如果底部图中的这些脉冲是 20Hz 单周期,那么您将无法使用 FFT 或 Goertzel 算法轻松可靠地实时获取它们。如果您将它们用作文件中的隐藏标记,那么我将对数据进行低通过滤,然后进行自相关,甚至只是观察高于某个阈值的正确宽度的部分。 (已编辑:自相关不会很好地拾取那些单周期)
-
我还看到您正在使用 AAC - 您可能希望通过在 Audacity 中进行压缩后查看添加的音调来确认最终文件中是否出现了该音调。音频压缩通过丢弃部分听不见的信号来工作,因此它可能会在您有机会处理它之前移除 20Hz 音调。
-
@Katie 是的,我用几个程序检查了音频,并确保没有修剪低频。我最初的想法是在 20z 中插入 5 个幅度很大的周期,所以当我得到 5 次正布尔值时,使用一个简单的计数器继续应用我的逻辑,这是个坏主意吗?
标签: ios c audio signal-processing fft