我建立这应该在服务器上运行,并分析声音文件的工具。 我想为我的其他所有工具都写在红宝石以及为此在红宝石。 但我无法找到实现这一点的一个好方法。
很多的例子,我发现一直在做可视化工具和图形化的东西。 我只需要FFT数据,仅此而已。 我需要都得到了音频数据,并做就可以了FFT。 我的最终目标是要计算一些东西,如平均/中位数/模式,第25百分位,和第75百分位在所有频率(加权幅度),BPM的,也许还有一些其他好的特性以后能够聚集类似的声音混合在一起。
首先,我试图用红宝石的音频和fftw3但我从来没有去两个真的一起工作。 该文档是也不好,所以我真的不知道什么样的数据正在抛去。 接下来,我试图用bplay / BREC和限制我的Ruby脚本只使用STDIN和对(仍然使用fftw3)执行FFT。 但我不能让bplay / BREC工作,因为服务器没有声卡,我没能只是直接将音频输出到标准输出而不去音频设备第一。
下面是我得到的最接近:
# extracting audio from wav with ruby-audio
buf = RubyAudio::Buffer.float(1024)
RubyAudio::Sound.open(fname) do |snd|
while snd.read(buf) != 0
# ???
end
end
# performing FFT on audio
def get_fft(input, window_size)
data = input.read(window_size).unpack("s*")
na = NArray.to_na(data)
fft = FFTW3.fft(na).to_a[0, window_size/2]
return fft
end
所以,现在我被卡住,无法找到谷歌什么比较好的结果。 因此,也许你这样的家伙能帮助我吗?
谢谢!
下面是什么,我想实现最终的解决方案,非常感谢兰德尔库克的有益的建议。 该代码提取红宝石WAV文件的声波和FFT:
require "ruby-audio"
require "fftw3"
fname = ARGV[0]
window_size = 1024
wave = Array.new
fft = Array.new(window_size/2,[])
begin
buf = RubyAudio::Buffer.float(window_size)
RubyAudio::Sound.open(fname) do |snd|
while snd.read(buf) != 0
wave.concat(buf.to_a)
na = NArray.to_na(buf.to_a)
fft_slice = FFTW3.fft(na).to_a[0, window_size/2]
j=0
fft_slice.each { |x| fft[j] << x; j+=1 }
end
end
rescue => err
log.error "error reading audio file: " + err
exit
end
# now I can work on analyzing the "fft" and "wave" arrays...
我觉得这里有两个问题。 一个是获得样本,另一个是执行FFT。
要获取样本,主要有两个步骤:解码和缩混。 为了解码WAV文件,你只需要解析头,所以你可以知道如何解释样本。 对于MP3文件,你需要做一个全解码。 一旦音频已经被解码,如果是不感兴趣的单独地处理立体声信道,则可能需要将其缩混成单,由于FFT需要一个单个信道作为输入。 如果你不介意冒险红宝石之外,在SOX工具让一切变得简单。 例如sox song.mp3 -b 16 song.raw channels 1
应一个MP3转换为纯PCM样本(即16位整数)的单文件。 BTW,快速搜索揭示了红宝石/音频库(也许是在你的文章中提到的)。 它看起来相当不错,特别是因为它包装libsndfile。
为了执行FFT,我看到三个选项。 一种是使用此代码段的代码执行FFT。 我不是红宝石的专家,但它看起来像它可能是确定。 第二个选择是使用NArray 。 它有一吨的数学方法,包括FFTW,可在一个单独的模块,一个压缩包供其在NArray页面中间的链接。 第三个选项是编写自己的代码FFT。 这不是一个特别复杂的算法,并可以给你很好的与数字处理红宝石(如果你需要)。
你也许是意识到了这一点,但FFT预计复杂的输入,并产生复杂的输出。 音频信号是真实的,当然,所以输入的虚分量应该总是零( a + 0*i
)。 由于您的输入是真实的,输出将是对称输出数组的中点。 您可以放心地忽略的上半部分。 如果你想在一个特定频率上的能量(它们间隔线性多达一半的采样率),你需要计算复数值(幅度sqrt(real*real + imag*imag)
一两件事:由于频率零(信号的DC偏移)和奈奎斯特频率(采样率的一半)具有无相位分量,一些FFT实现把它们放在一起成相同的复杂的容器(一个在实分量,一个在的虚分量,通常第一仓的)。 你可以创建一些简单的信号(全1的只是一个直流信号,并交替+ 1,-1的奈奎斯特信号),看到FFT输出的样子。