使用 ruby​​-alsa

发布于 2024-10-09 16:50:55 字数 1975 浏览 0 评论 0原文

我终于得到了我的代码引用 ruby​​-alsa 库,但我再次陷入困境。最终,我希望发生的是当从客户端调用操作时在服务器上播放音频文件。因此,我的控制器中有以下代码:

File.open('./public/audio/test.wav', 'r') do |f|
  ALSA::PCM::Playback.open do |playback|
    playback.write do |length|
      f.read length
    end
  end
end

通过阅读 ALSA 库的 RDoc ,我的印象是我应该使用 write_in_background 方法 来自 ALSA::PCM::Playback 类。不幸的是,我无法获得正确的语法来使该方法发挥作用。为了简单地验证 ALSA 是否正常工作,我尝试使用 Playback.write 方法(请注意上面的代码)。上面的代码在语法上是正确的;然而,它只播放一微秒的声音,然后停止。我的猜测是请求结束得如此之快,它没有足够的时间来播放任何可识别的内容。

如前所述,我的最终目标是让最终用户调用在服务器上播放音频的操作。文件不应该在 HTTP 请求结束时停止播放——它应该继续播放,直到调用另一个停止播放的操作。知道了这一点,有人可以帮助我获得正确的调用 write_in_background 方法的语法和参数吗?恐怕我目前拥有的 ruby-alsa 文档 还不够有帮助对我来说(作为 Ruby 的新手)。

更新:如果我将上面对 write 方法的调用替换为对 write_to_background 方法的调用,则会收到以下运行时错误:无法添加 pcm 处理程序(功能未实现)

更新 2:< /strong> 我尝试使用不同的 WAV 文件和以下代码,它以极快的速度播放。

File.open('./public/audio/sample.wav', 'r') do |f|
  ALSA::PCM::Playback.open do |playback|
    playback.write do |length|
      @temp = length
      f.read length
    end
    sleep 4
  end
end

看来这里可能发生了多种情况。我相信第一个是参考采样率(长度== 44100,这是CD质量)。我必须研究如何以不同的速率播放音频文件。然而除此之外,我仍然困惑于如何让它在后台播放。虽然睡眠证明 ALSA 有效,但它在现实场景中效果不佳。

更新3:让采样率位正常工作,尽管它暂时依赖于一个幻数:

File.open('./public/audio/sample.wav', 'r') do |f|
  ALSA::PCM::Playback.open "default", {:channels => 1, :sample_rate => 11025} do |playback|
    playback.write do |length|
      @temp = length
      f.read length
    end
    sleep 4
  end
end

此时,我的 ruby​​ 代码通过 ALSA 播放音频,但我不知道如何制作它在后台连续播放,无需睡眠。

I finally got my code to reference the ruby-alsa library, but I'm stuck again. Eventually, what I'd like to happen is have an audio file play on the server when an action is invoked from the client side. As such, I have the following code in my controller:

File.open('./public/audio/test.wav', 'r') do |f|
  ALSA::PCM::Playback.open do |playback|
    playback.write do |length|
      f.read length
    end
  end
end

By reading the RDoc for the ALSA library, I get the impression I should be using the write_in_background method from the ALSA::PCM::Playback class. Unfortunately, I can't get the syntax right for getting this method to work. To simply verify I have ALSA working properly, I attempted to use the Playback.write method (note code above). The above code is syntactically correct; however, it plays a sound only for a microsecond, then stops. My guess is the request ends so quickly, it doesn't have enough time to play anything recognizable.

As previously mentioned, my ultimate goal is to have an end-user invoke an action that plays audio back on the server. The file should not stop playing at the end of the HTTP request --it should continue until another action is invoked that stops playback. Knowing that, could somebody please help me with getting the syntax and parameters right for calling the write_in_background method? I'm afraid the ruby-alsa documentation I have at this time hasn't been helpful enough for me (as a complete newbie at Ruby).

Update: If I replace the above call to the write method with a call to the write_to_background method, I get the following runtime error: cannot add pcm handler (Function not implemented)

Update 2: I tried this with a different WAV file and the following code and it plays at warp speed.

File.open('./public/audio/sample.wav', 'r') do |f|
  ALSA::PCM::Playback.open do |playback|
    playback.write do |length|
      @temp = length
      f.read length
    end
    sleep 4
  end
end

It appears there may be a combination of things going on here. I believe the first is in reference to the sample rate (length == 44100, which is CD quality). I'll have to look into how to play back audio files at a different rate. Beyond that, however, I'm still stuck on how to get it to play in the background. While the sleep proves ALSA is working, it won't work well in a real-world scenario.

Update 3: Got the sample rate bit working even though it temporarily relies on a magic number:

File.open('./public/audio/sample.wav', 'r') do |f|
  ALSA::PCM::Playback.open "default", {:channels => 1, :sample_rate => 11025} do |playback|
    playback.write do |length|
      @temp = length
      f.read length
    end
    sleep 4
  end
end

At this point, I have my ruby code playing audio through ALSA, but I'm not sure how to make it play continuously in the background without requiring the sleep.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无言温柔 2024-10-16 16:50:55

在自己的线程上启动它怎么样?

Thread.new do
  File.open('myfile.wav', 'rb') do |f|
    ALSA::PCM::Playback.open do |playback|
      playback.write do |length|
        f.read length
     end
    end
  end
end.join

编辑
好吧,如果这不起作用,我猜它已经启动了自己的线程。期间睡觉怎么样?第一次尝试:

  File.open('myfile.wav', 'rb') do |f|
    ALSA::PCM::Playback.open do |playback|
      playback.write do |length|
        f.read length
     end
    end
  end
  sleep 4 # seconds

How about kicking it off on its own thread?

Thread.new do
  File.open('myfile.wav', 'rb') do |f|
    ALSA::PCM::Playback.open do |playback|
      playback.write do |length|
        f.read length
     end
    end
  end
end.join

Edit:
OK, if that doesn't work, I'm guessing it kicks off its own thread already. How about sleeping for the duration? First try:

  File.open('myfile.wav', 'rb') do |f|
    ALSA::PCM::Playback.open do |playback|
      playback.write do |length|
        f.read length
     end
    end
  end
  sleep 4 # seconds
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文