我最近一直在玩ruby,我决定开始一个简单的项目来编写一个ruby脚本来记录.wav
文件的输入声音。我发现ruby不能很好地访问硬件设备(它可能不应该),但PortAudio确实如此,我发现了PA here的一个很好的包装器(我认为它不是宝石)因为它使用ruby的ffi
附加到PortAudio,PA库可以在各种各样的地方)。我一直在弄乱PortAudio的文档和示例来弄清楚PA是如何工作的。多年来我没有写过或读过C
。
我在创建过程中应该将哪些参数传递给流,以及创建期间的缓冲区时遇到了困难。例如,frame
究竟是什么,以及它与channel
和sample rate
等其他参数的关系。我对音频编程也很陌生,所以如果有人能指点我一些关于设备级音频的一般教程等,我会很感激。
ruby-portaudio
提供了一个创建流和缓冲区的示例,将sin波写入缓冲区,然后将缓冲区发送到要播放的流。我在示例中遇到了一些问题,特别是循环块。
PortAudio.init
block_size = 1024
sr = 44100
step = 1.0/sr
time = 0.0
stream = PortAudio::Stream.open(
:sample_rate => sr,
:frames => block_size,
:output => {
:device => PortAudio::Device.default_output,
:channels => 1,
:sample_format => :float32
})
buffer = PortAudio::SampleBuffer.new(
:format => :float32,
:channels => 1,
:frames => block_size)
playing = true
Signal.trap('INT') { playing = false }
puts "Ctrl-C to exit"
stream.start
loop do
stream << buffer.fill { |frame, channel|
time += step
Math.cos(time * 2 * Math::PI * 440.0) * Math.cos(time * 2 * Math::PI)
}
break unless playing
end
stream.stop
如果我要录制,我应该将一个流读入缓冲区,然后操作该缓冲区并将其写入文件,对吧?
另外,如果我在这里咆哮错误的树,并且有更简单的方法(红宝石),那么某个方向会很好。
答案 0 :(得分:3)
让我们首先澄清您所询问的术语。为此,我将尝试以简化的方式解释音频管道。当您在示例中生成声音时,声卡会定期从您的代码中请求帧(= buffers = blocks),您可以使用示例填充这些帧。采样率定义了您在一秒钟内提供的样本数量,从而定义了样本播放的速度。帧大小(=缓冲区大小=块大小)确定您在声卡的一个请求中提供的样本数。缓冲区通常非常小,因为缓冲区大小直接影响延迟(大缓冲区=&gt;高延迟),大型数组可能很慢(特别是ruby阵列很慢)。
当您从声卡录制声音时会发生类似情况。您的函数会不时被调用,麦克风中的样本通常作为参数传递给函数(或者甚至只是对这样的缓冲区的引用)。然后,您需要处理这些样本,例如将它们写入磁盘。
我知道“在Ruby中做所有事情”的想法很诱人,因为它是如此美妙的语言。当您计划实时进行音频处理时,我建议切换到编译语言(C,C ++,Obj-C,...)。这些可以更好地处理音频,因为它们比Ruby更接近硬件,因此通常更快,这在音频处理中可能是一个很大的问题。这可能也是为什么周围有很少的Ruby音频库的原因,因此Ruby可能不适合这项工作。
顺便说一句,我尝试了ruby-portaudio,ffi-portaudio以及ruby-audio,并且没有一个在我的Macbook上正常工作(试图生成正弦波),这可悲地再次显示,Ruby不是能够处理这些东西(但是?)。