AtlatestRepositorysigil-audio

sigil-audio / tree / testtest-device-drain.sgl

1;;; Test the playback device: the device thread drains a streaming sink.
2;;;
3;;; Opens the real device (miniaudio picks the backend; with no backend
4;;; library it is the Null backend, which still consumes frames in real
5;;; time), pushes half a second of silence into a stream, waits, and checks
6;;; the depth fell. That is the one thing test-streaming-sink.sgl cannot
7;;; show: that frames leave the ring through audio_callback on the device's
8;;; thread, not only that they go in. SIGIL_AUDIO_VERBOSE=1 names the
9;;; backend that did it. Run it with PULSE_SINK pointing at a null sink.
11(import (sigil core)
12 (sigil time)
13 (sigil process)
14 (sigil audio))
16(define failures 0)
18(define (check label actual expected)
19 (if (equal? actual expected)
20 (begin (display " ok: ") (display label) (newline))
21 (begin
22 (display " FAIL: ") (display label) (newline)
23 (display " expected: ") (display expected) (newline)
24 (display " actual: ") (display actual) (newline)
25 (set! failures (+ failures 1)))))
27(define (busy-wait seconds)
28 (let ((t0 (current-second)))
29 (let loop () (when (< (- (current-second) t0) seconds) (loop)))))
31(audio-setup)
32(check "audio initialized" (audio-initialized?) #t)
34;; the backend, as the game sees it; SIGIL_AUDIO_BACKEND=null forces the
35;; silent backend, and the two predicates must agree about it
36(let ((backend (audio-backend)))
37 (display " backend: ") (display backend) (newline)
38 (check "audio-backend is a symbol" (symbol? backend) #t)
39 (check "audio-backend is a known backend"
40 (and (memq backend '(pulseaudio alsa jack wasapi dsound winmm coreaudio null other)) #t) #t)
41 (check "audio-device? is #t exactly when the backend is not null"
42 (audio-device?) (not (eq? backend 'null)))
43 (let ((forced (getenv "SIGIL_AUDIO_BACKEND")))
44 (when forced
45 (check "SIGIL_AUDIO_BACKEND picked the backend" (symbol->string backend) forced))))
47(let* ((frames 22050) ; half a second at 44100
48 (s (open-audio-stream channels: 2 buffer-frames: 32768))
49 (bv (make-bytevector (* frames 2 4) 0))
50 (accepted (push-audio-samples s bv frames)))
51 (check "the push was accepted whole" accepted frames)
52 (check "depth is the push" (audio-stream-depth s) frames)
53 (busy-wait 0.35)
54 (let ((after (audio-stream-depth s)))
55 (display " depth after 350 ms: ") (display after) (newline)
56 (check "the device thread drained at least a quarter second"
57 (< after (- frames 11025)) #t)
58 (check "and not more than was pushed" (>= after 0) #t))
59 (close-audio-stream! s))
61(audio-shutdown)
62(check "no backend after shutdown" (audio-backend) #f)
63(check "no device after shutdown" (audio-device?) #f)
64(check "audio shut down" (audio-initialized?) #f)
66(if (= failures 0)
67 (begin (display "All device-drain tests passed!") (newline))
68 (begin (display failures) (display " device-drain test(s) FAILED") (newline)
69 (exit 1)))