我想要开发一款在Android上计算声音频率的应用程序。Android设备将通过麦克风(即外部声音)获取声音,并且我在应用中有一个带有颜色背景屏幕。当声音频率改变时,我必须更改屏幕的背景颜色。
所以我的问题是“如何获取声音频率”?
是否有任何可用的Android API?
请帮我解决这个问题。
我想要开发一款在Android上计算声音频率的应用程序。Android设备将通过麦克风(即外部声音)获取声音,并且我在应用中有一个带有颜色背景屏幕。当声音频率改变时,我必须更改屏幕的背景颜色。
所以我的问题是“如何获取声音频率”?
是否有任何可用的Android API?
请帮我解决这个问题。
// sampleRate = 44100
public static int calculate(int sampleRate, short [] audioData){
int numSamples = audioData.length;
int numCrossing = 0;
for (int p = 0; p < numSamples-1; p++)
{
if ((audioData[p] > 0 && audioData[p + 1] <= 0) ||
(audioData[p] < 0 && audioData[p + 1] >= 0))
{
numCrossing++;
}
}
float numSecondsRecorded = (float)numSamples/(float)sampleRate;
float numCycles = numCrossing/2;
float frequency = numCycles/numSecondsRecorded;
return (int)frequency;
}
http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html
诚然,这段代码是用C语言编写的,但我认为你会发现它很容易移植。
简而言之,你需要:
低通滤波输入信号,以便高频泛音不会被误认为是基频(在你的应用中可能看起来不是问题,因为你只是想寻找音高变化,但出于复杂的原因,我建议你仍然这样做)。
使用适当的窗函数对信号进行窗口处理。为了获得最敏感的输出,你应该重叠窗口,但我在示例代码中没有这样做。
对每个窗口中的数据执行FFT,并使用最大绝对峰值的索引计算频率。
请记住,在你的应用程序中,你可能希望快速准确地检测音高变化,我描述的FFT方法可能不足够。你有两个选择:
有一些技术可以利用相位信息提高音高跟踪的特异性,而不仅仅是绝对峰值。
使用基于自相关的时域方法。Yin是一个很好的选择。(搜索“yin pitch tracking”)
这里是提到的代码链接,还有其他一些有用的代码。
关于ZeroCrossings的问题:
在Android上,它无法准确地根据录制的音频确定频率。尽管如此,它仍然有用,可以让您的应用程序大致了解所听到的声音是一个持续的歌唱音,而不是噪音。
这里的代码似乎非常适合确定频率(如果您可以将其从C#翻译成Java) http://code.google.com/p/yaalp/