Amy*_*y B 34 java audio fft frequency pitch
我想将声音的音高绘制成图形.
目前我可以绘制幅度.下图是由返回的数据创建的getUnscaledAmplitude():

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(file)));
byte[] bytes = new byte[(int) (audioInputStream.getFrameLength()) * (audioInputStream.getFormat().getFrameSize())];
audioInputStream.read(bytes);
// Get amplitude values for each audio channel in an array.
graphData = type.getUnscaledAmplitude(bytes, 1);
public int[][] getUnscaledAmplitude(byte[] eightBitByteArray, int nbChannels)
{
int[][] toReturn = new int[nbChannels][eightBitByteArray.length / (2 * nbChannels)];
int index = 0;
for (int audioByte = 0; audioByte < eightBitByteArray.length;)
{
for (int channel = 0; channel < nbChannels; channel++)
{
// Do the byte to sample conversion.
int low = (int) eightBitByteArray[audioByte];
audioByte++;
int high = (int) eightBitByteArray[audioByte];
audioByte++;
int sample = (high << 8) + (low & 0x00ff);
toReturn[channel][index] = sample;
}
index++;
}
return toReturn;
}
Run Code Online (Sandbox Code Playgroud)
但我需要显示音频的音高,而不是幅度.快速傅里叶变换似乎得到了音调,但它需要知道比我的原始字节更多的变量,并且非常复杂和数学.
有没有办法可以做到这一点?
Oli*_*rth 49
频率(客观度量)与音调(主观量)不同.通常,音调检测是一个非常棘手的问题.
假设你只是想绘制对于现在的频率响应,你别无选择,只能使用FFT,因为它的获得时域数据的频率响应方法.(嗯,还有其他方法,例如离散余弦变换,但它们实现起来也很棘手,而且解释起来比较棘手).
如果您正在努力实现FFT,请注意它实际上只是计算离散傅立叶变换(DFT)的有效算法; 见http://en.wikipedia.org/wiki/Discrete_Fourier_transform.基本的DFT算法要容易得多(只有两个嵌套循环),但运行速度要慢很多(O(N ^ 2)而不是O(N log N)).
如果你想做一些比简单绘制频率内容更复杂的事情(比如音调检测或开窗(正如其他人建议的那样)),我担心你会学习数学的含义.
Guy*_*ton 24
快速傅立叶变换不需要知道您拥有的输入字节.不要被维基百科的文章吓到.FFT算法将采用您的输入信号(使用常见的FFT算法,样本数量需要为2的幂,例如256,512,1024),并返回具有相同大小的复数向量.因为您的输入是真实的,而不是复杂的(假想部分设置为零),返回的矢量将是对称的.其中只有一半将包含数据.由于您不关心阶段,您可以简单地取复数的大小,即sqrt(a ^ 2 + b ^ 2).只取一个复数的absoulte值也可能有效,在某些语言中,这相当于前面的表达式.
可以使用FFT的Java实现,例如:http://www.cs.princeton.edu/introcs/97data/FFT.java.html
伪代码看起来像:
Complex in[1024];
Complex out[1024];
Copy your signal into in
FFT(in, out)
for every member of out compute sqrt(a^2+b^2)
To find frequency with highest power scan for the maximum value in the first 512 points in out
Run Code Online (Sandbox Code Playgroud)
输出将包含采样频率的零到一半之间频率的输入.
由于FFT采用重复信号,因此您可能需要在输入信号中应用窗口.但一开始不要担心这个.
您可以在网上找到更多信息,例如:针对初学者的FFT
同样正如Oli所指出的,当存在多个频率时,感知音调是更复杂的现象.
| 归档时间: |
|
| 查看次数: |
34086 次 |
| 最近记录: |