如何实时获取特定频率音频信号的幅度android

Posted

技术标签:

【中文标题】如何实时获取特定频率音频信号的幅度android【英文标题】:How to get an amplitude of certain frequency audio signal realtime android 【发布时间】:2017-02-11 23:03:36 【问题描述】:

我正在开发 lumiere 应用程序。我有一个特定频率的载波信号(更准确地说是 19.2 kHz),我需要在播放音频时获取它的幅度。 我在 Google 上搜索了一些有关音频处理的信息,发现为了获得频谱,您必须使用 FFT 算法。

我已经尝试过 TarsosDSP 库及其 FFT 类。

TarsosDSPAudioFormat format = new TarsosDSPAudioFormat((float) SAMPLE_RATE, 16, 1, true, false);
TarsosDSPAudioFloatConverter converter = TarsosDSPAudioFloatConverter.getConverter(format);

float[] buff = new float[bufferFloatSize];
final float[] amps = new float[fftSize];

converter.toFloatArray(tmpBuffer, buff);

FFT fft = new FFT(bufferFloatSize, new HannWindow());
fft.forwardTransform(buff);
fft.modulus(buff, amps);

然后我得到频带索引并计算它的幅度

int amp = (int) (10 * Math.log10(amps[index]);

但是我得到错误的幅度。 我有一个 19.2kHz 信号的音频文件,其振幅恒定为 0 dB,但 19207 Hz 振幅的结果值在 -39 dB 到 -46 dB 之间变化。我检查了相邻的频率,可能其中一些有 0 dB,但没有。 我还检查了 -36 dB 和 -60 dB 的文件,但结果分别为 -39 到 -48 dB 和 -44 到 - 61 dB。

我们可以看到最后一个文件很接近,但它不是恒定的,我无法预测它什么时候是对的,什么时候是错的。

如果有人遇到这个问题,请帮助我。 如果您知道任何其他确定可行的好的 FFT 库 - 请告诉我

更新: 好的,我已经添加了 TSG 的函数并在我的 fft.forwardTransform() 之前和之后调用它来比较结果; 结果是: 对于 0 dB 19.2kHz 音频文件: 之前:-39 分贝 之后 - 10 分贝

对于 -36 dB 19.2kHz 音频文件: 之前:-75 分贝 之后:-46 分贝

对于 -60 dB 19.2kHz 音频文件: 之前:-97.7 分贝 之后:-69 分贝

现在结果是恒定的,不会随着时间或尝试而改变。 我们还可以看到结果中存在一定的模式。在 fft 之前,结果与正确的结果不同,为 -39 dBs,之后为 -10dBs。 所以问题是:为什么我们会犯这些错误?

【问题讨论】:

【参考方案1】:
    In the TarsosDSP manual , the following example was given sound pressure level in db  where  ,

 db=audioEvent.getdBSPL(); or Amplitude=audioEvent.getRMS() //root mean square of the signal.



    float[] buffer = audioEvent.getFloatBuffer();



    private double soundPressureLevel(final float[] buffer) 
    double power = 0.0D;
    for (float element : buffer) 
    power += element*element;
    

    double value = Math.pow(power, 0.5)/ buffer.length;;
    return 20.0*Math.log10(value);
    
    );

【讨论】:

请您解释一下,为什么要在 20.0*Math.log10(value); 中乘以 20;因为我见过同样的表达式乘以十:10 * Math.log10(value); 函数在 0 dB 19.2kHz 音频文件上的结果在调用 FFT 之前为 -39 dB,在调用 FFT 之后为 -10 dB。 Log.d("test", "在功率电平之前:" + soundPressureLevel(buff) + " dB"); fft.forwardTransform(buff); fft.modulus(buff,amps); Log.d("test", "经过功率电平:" + soundPressureLevel(buff) + " dB"); 我还检查了所有三个文件始终具有相同的结果,更好的是,因为我们有恒定的值(没有像以前那样的变化)并且正确结果和错误之间的差异大约是39 dBs(fft 之前的结果)。就像它应该是 0 dB 并且是 -39 dB,应该是 -36 dB 并且是 -75 dB,应该是 -60 dB 并且是 -98 dB。 据我所知 TarsosDSp 使用的 FFT 是 JTransforms。 TarsosDSP 手册中的公式,audioEvent.getdBSPL() 调用完全匹配通常称为声压级的声压函数表现。 SPL=20Log10(P(rms) /P0) 其中 P0 是一个常数 = 2e-5。 ,P 是您的公式应用的声压波动 rms,称为 PWL 或声功率级,单位也是 dB。两者其实是一样的,都是以一个共同的基准为基准的相对测量,在功率的情况下,基准是强度等级10E-12 W/M2,强度=P sq (rms)除以pc(密度x声速)大气条件下空气的 pc 常数=4e2 kg/m2s

以上是关于如何实时获取特定频率音频信号的幅度android的主要内容,如果未能解决你的问题,请参考以下文章

Android音频FFT使用audiorecord检索特定频率幅度

DSP - 获取所有频率的幅度

如何实时查看输入信号频率?

信号的持续时间会影响其频率分量的幅度吗?另外,采样频率会影响信号的功率吗?

在matlab中提取具有多个频率分量的信号

J2ME/Blackberry - 获取音频信号幅度级别?