FFT 音频输入
Posted
技术标签:
【中文标题】FFT 音频输入【英文标题】:FFT audio input 【发布时间】:2014-06-23 15:09:25 【问题描述】:我想对 AudioRecorder 录制并保存到 wav 文件的信号应用 FFT。我使用的 FFT 有一个 Complex[] 输入参数。我很困惑,从字节转换为复数除以 32768 和只在虚部加 0 并将实部作为字节进行转换有区别吗?
编辑:
public Complex[] convertToComplex(byte[] file)
int size= file.length;
double[]x=new double[size];
Complex[]data= new Complex[size];
for(int i=0;i<size;i++)
x[i]=file[i]/32768.0;
data[i]=new Complex(x[i],0);
// Log.d("tag", "indice"+i+":"+data[i]);
return data;
【问题讨论】:
只是为了确认您的音频是 16 位 PCM 对吗?如果是这样,那么不幸的是你的转换是错误的,看看我是如何在我的代码中进行转换的。 是的,它是 16 位 PCM。我不明白你为什么使用short。 myAudiosamples 的长度是 1/2 myAudioBytes? 是的,myAudioSamples 的长度是 1/2 myAudioBytes。我使用“short”是因为它正好有 16 位,您也可以使用双精度(64 位)或浮点型(32 位),因为您的样本仍然适合在。 【参考方案1】:如果您正在处理位深为 16 位的音频(每个样本有 16 位),那么每个字节将只有一半样本。您需要做的是将字节转换为 16 位样本,然后除以得到的数字乘以 32768(这是 2 的补码 16 位数字可以存储的最小数字的大小,即 2^15)以获得实际的音频样本,它是介于 -1 和 1 之间的数字。然后您将把这个数字转换为通过将其虚部设置为 0 来获得复数。
可以在下面看到一个小的 C# 示例(指示性代码):
byte[] myAudioBytes = readAudio();
int numBytes = myAudioBytes.Length;
var myAudioSamples = new List<short>();
for( int i = 0; i < numBytes; i = i + 2)
//Cast to 16 bit audio and then add sample
short sample = (short) ((myAudioBytes[i] << 8 | myAudioBytes[i + 1]) / 32768 );
myAudioSamples.Add(sample);
//Change real audio to Complex audio
var complexAudio = new Complex[myAudioSamples.Length];
int i = 0;
foreach(short sample in myAudioSamples)
complexAudio[i++] = new Complex() Real = sample, Imaginary = 0 ;
//Now you can proceed to getting the FFT of your Audio here
希望代码能够指导您如何处理音频。
【讨论】:
谢谢你们。我编辑了我的问题以添加我所做的转换。我希望它没有错。【参考方案2】:通用 FFT 函数,例如处理复杂输入和输出的数组。因此,对于输入,您可能需要创建一个复数数组,该数组符合 FFT 库所需的复杂数据结构。这可能由每个的实部和虚部组成。只需将虚部设置为 0。实部可能是一个带符号的浮点数,预计在 -1.0..1.0 之间,因此您在除以整数 PCM 样本的正确轨道上。但是,当您编写“转换 bytes”时,会引发危险信号。这些可能是有符号的、小端序的、16 位整数 PCM 样本,因此请务必在除以 32768 之前相应地转换它们(但这是 Java,因此无论如何都会对类型进行更严格的强制)。
【讨论】:
以上是关于FFT 音频输入的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Tizen 上的实时 FFT 获得最准确的音频数据?