无法使用 Racket RSound 获得声音

Can't get sound using Racket RSound

我正在尝试使用 Racket Rsound 播放声音。我在 play.rkt 中有一个简单的程序,我是 运行 racket play.rkt.

使用 GUI 库中的 play-sound 可以播放我期望的声音:

#lang racket/base
(require racket/gui/base)
(play-sound "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav" #t)

输出:

$ racket play.rkt
ALSA lib pcm_dsnoop.c:618:(snd_pcm_dsnoop_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
#t ;; plays audio correctly

但是使用 RSound 没有播放任何音频:

#lang racket/base

(require rsound)
(play (rs-read "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav"))

输出与上面相同,除了最后一行是 "played sound" 而不是 #t

改为调用 andplay 也失败了:

#lang racket/base

(require rsound)
(andplay (rs-read "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav" #t))

当我 运行 直接从 Racket REPL 使用相同的代码时,它也能正确播放音频:

$ racket
Welcome to Racket v7.3.
> (require rsound)
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
> (play (rs-read "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav"))
"played sound" ;; <-- and it does.
>

所以 REPL 知道如何通过 RSound 正确播放音频,racket 可以使用 (play-sound ...) 播放,但我的程序失败了。为什么?

详情

Ubuntu 18.04

$ racket --version
Welcome to Racket v7.3.
$ uname -a
Linux toast 5.0.0-23-generic #24~18.04.1-Ubuntu SMP Mon Jul 29 16:12:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

根据the documentation for play,该函数不能在子模块main中使用。

您可以使用如下函数:

#lang racket/base
(play (rs-read "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav"))

原来程序只是在有机会真正播放声音之前就退出了!

我想这应该让我知道 RSound 是异步工作的:

Plays concurrently with an already-playing sound

这也解释了为什么 REPL 工作但 CLI 不工作,因为 REPL 在后台继续 运行 代码的同时等待用户输入。

目前,一个简单的 sleep hack 有效:

#lang racket/base
(play (rs-read "/media/tamayo/ExtraDrive1/Dropbox/fclooper/poc/sample.wav"))
(sleep 10)

(这是一个循环程序的一部分,它 运行 永远等待用户输入来做一些事情,比如换出样本声音。这显然超出了这个问题的范围,所以 sleep 是目前的解决方法,但在实际的 GUI 版本中将变得无关紧要。)