2016-01-22 45 views
2

我在Racket中編寫了這個程序,它從一組15個音符中生成32個隨機音符,然後播放它們。每個音符的持續時間應該是0.25秒。當我運行它時會產生延遲,從而使旋律聽起來很不錯。使用rsound的球拍延遲

它如何正常運行?

這是程序:

所有的
#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)) 

回答

4

首先,來自piano-tone筆記是不是真的意味着要截斷這樣,雖然你可以用clip功能做到這一點。

其次,您的問題在於您依賴於您的計算機執行代碼的速度,這本質上是不一致的。

更好的方法是使用make-pstream。並排列備註以便稍後運行。這樣,當筆記播放時,基於你的處理器就不會有差距。

(此外,作爲一個側面說明in-range可以用來加快循環時,您使用的是他們這樣。)

把它放在一起(用夾子削減你的筆記關閉),你的程序將是這個樣子(我用幻數爲簡潔,很明顯,你會希望通過實際計算中運行得到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))) 
+1

謝謝!但現在我有一個不同的問題。我將其轉換爲可執行文件,並在所有for循環運行之前退出。我可以爲所有要播放的音符做些什麼? –

+1

發生什麼事情最有可能的是,make-pstream正在發生在另一個線程中,並且主線程在它退出之前並沒有等待它完成。解決這個問題的最簡單方法可能是在歌曲末尾添加一個「pstream-queue-callback」,指示節目何時可以結束。我會用這個來回答這個問題。 –

+0

(此外,您可以只是「睡覺」,但可能會在您的程序完成播放之前完成。 –