带有 rsound 的球拍延迟

Racket latency with rsound

我用 Racket 编写了这个程序,它从一组 15 个音符中生成 32 个随机音符,然后播放它们。每个音符的持续时间应为 0.25 秒。当我 运行 时,它会产生延迟,使旋律听起来不合拍。

怎么才能运行正常呢?

这是程序:

#lang racket
(provide (all-defined-out))
(require rsound)
(require rsound/piano-tones)


(define-syntax-rule (note y x)
    (begin
       (play (piano-tone y))
       (sleep x)
       (stop)))

(define (random-element list)
  (list-ref list (random (length list))))

(define-syntax-rule (random-note)
  (note (random-element '(40 42 43 45 47 48 50 52 54 55 57 59 60 62 64)) 0.25))


(for ([i 32])
  (random-note))

首先,来自piano-tone are not really meant to be truncated like that, although you can do it with the clip的笔记起作用了。

其次,你这里的问题是你依赖于你的计算机执行代码的速度,这在本质上是不一致的。

更好的方法是使用 make-pstream。并稍后将笔记排队到 运行。这样在播放音符时就不会出现基于处理器的间隙。

(另外,作为旁注,当您像这样使用循环时,in-range 可用于加速循环。)

把它们放在一起(使用 clip 剪掉你的笔记),你的程序看起来像这样(为了简洁我使用了幻数,显然你会想 运行 通过实际计算得到0.25 秒):

#lang racket

(require rsound
         rsound/piano-tones)

(define stream (make-pstream))

(define count 10000)
(define (note y x)
  (pstream-queue stream (clip (piano-tone y) 0 10000) count)
  (set! count (+ count x)))

(define (random-element list)
  (list-ref list (random (length list))))

(define (random-note)
  (note (random-element '(40 42 43 45 47 48 50 52 54 55 57 59 60 62 64)) 10000))

(for ([i (in-range 32)])
  (random-note))

最后,如果您想将所有这些打包成一个可执行文件,程序将在队列完成之前终止。因此,在等待队列完成的程序末尾创建一个忙循环(通过使用 pstream-queue-callback)。

将此添加到程序末尾:

(define ok-to-exit? #f)
(pstream-queue-callback stream (lambda () (set! ok-to-exit? #t)) count)

(let loop ()
  (sleep 0.1)
  (unless ok-to-exit?
    (loop)))