/portaudio/test/test-stream-callback.rkt

http://github.com/jbclements/rack-portaudio · Racket · 213 lines · 167 code · 23 blank · 23 comment · 6 complexity · 89cbbad1957b2cc7a10dbaa72e6436f4 MD5 · raw file

  1. #lang racket
  2. (require "helpers.rkt"
  3. "../callback-support.rkt"
  4. ffi/unsafe
  5. ffi/vector
  6. rackunit
  7. rackunit/text-ui
  8. racket/runtime-path)
  9. (define twopi (* 2 pi))
  10. (define-runtime-path libs "../lib")
  11. (define pa-abort 2)
  12. (define pa-continue 0)
  13. (run-tests
  14. (test-suite "portaudio"
  15. (let ()
  16. (define callback-lib
  17. (ffi-lib (build-path libs (system-library-subpath) "callbacks")))
  18. (define-cstruct _stream-rec
  19. (;; the number of frames in the circular buffer
  20. [buffer-frames _int]
  21. ;; the circular buffer
  22. [buffer _pointer]
  23. ;; the last frame read by the callback
  24. [last-frame-read _uint]
  25. ;; the offset of the last byte read by the callback.
  26. [last-offset-read _uint]
  27. ;; the last frame written by Racket
  28. [last-frame-written _uint]
  29. ;; the offset of the last byte written by Racket.
  30. [last-offset-written _uint]
  31. ;; number of faults:
  32. [fault-count _int]
  33. ;; a pointer to a 4-byte cell; when it's nonzero,
  34. ;; the supplying procedure should shut down, and
  35. ;; free this cell. If it doesn't get freed, well,
  36. ;; that's four bytes wasted forever.
  37. [all-done _pointer]))
  38. (define streaming-callback
  39. (get-ffi-obj "streamingCallback"
  40. callback-lib
  41. (_fun
  42. (_pointer = #f)
  43. _pointer
  44. _ulong
  45. (_pointer = #f)
  46. (_ulong = 0)
  47. _stream-rec-pointer
  48. -> _int)))
  49. ;; changing these will mess up the "around-the-corner"-ness
  50. ;; of the tests.
  51. (define buffer-frames 2048)
  52. (define output-buffer-frames 224)
  53. (match-define
  54. (list stream-info all-done-ptr)
  55. (make-streaming-info buffer-frames))
  56. (check-equal? (stream-rec-buffer-frames stream-info)
  57. buffer-frames)
  58. (ptr-set! (stream-rec-buffer stream-info) _sint16 39 -47)
  59. (check-equal? (ptr-ref (stream-rec-buffer stream-info) _sint16 39) -47)
  60. (check-equal? (stream-rec-last-frame-read stream-info) 0)
  61. (check-equal? (stream-rec-last-offset-read stream-info) 0)
  62. (check-equal? (stream-rec-last-frame-written stream-info) 0)
  63. (check-equal? (stream-rec-last-offset-written stream-info) 0)
  64. (check-equal? (stream-rec-fault-count stream-info) 0)
  65. (check-equal? (all-done? all-done-ptr) #f)
  66. ;; randomize the buffers
  67. (for ([j (in-range (* channels buffer-frames))])
  68. (ptr-set! (stream-rec-buffer stream-info) _sint16 j (- (random 1000) 500)))
  69. (define tgt (make-s16vector (* channels output-buffer-frames) 1))
  70. (define buffer-bytes (* 2 channels buffer-frames))
  71. ;; buffer-not ready yet (frames written still zero):
  72. (set-stream-rec-last-frame-read! stream-info 7000)
  73. (set-stream-rec-last-offset-read! stream-info (modulo (* 4 7000) buffer-bytes))
  74. (check-equal? (streaming-callback
  75. (s16vector->cpointer tgt)
  76. output-buffer-frames
  77. stream-info)
  78. pa-continue)
  79. (check-equal? (stream-rec-last-frame-read stream-info) 7224)
  80. (check-equal? (stream-rec-last-offset-read stream-info)
  81. (modulo (* 4 7224) buffer-bytes))
  82. (check-equal? (stream-rec-fault-count stream-info) 1)
  83. (for ([i (in-range (* channels output-buffer-frames))])
  84. (check-equal? (s16vector-ref tgt i) 0))
  85. ;; buffer ready:
  86. (set-stream-rec-last-frame-written! stream-info 8000)
  87. (set-stream-rec-last-offset-written! stream-info (modulo (* 4 8000) buffer-bytes))
  88. (check-equal? (streaming-callback
  89. (s16vector->cpointer tgt)
  90. output-buffer-frames
  91. stream-info)
  92. pa-continue)
  93. (check-equal? (stream-rec-last-frame-read stream-info) 7448)
  94. (check-equal? (stream-rec-last-offset-read stream-info)
  95. (modulo (* 4 7448) buffer-bytes))
  96. (for ([i (in-range (* 2 output-buffer-frames))]
  97. [j (in-range (modulo (* 2 7224)
  98. (* 2 2048))
  99. (+ (modulo (* 2 7224)
  100. (* 2 2048))
  101. (* 2 output-buffer-frames)))])
  102. (check-equal? (s16vector-ref tgt i)
  103. (ptr-ref (stream-rec-buffer stream-info) _sint16 j)))
  104. ;; try an "around-the-corner" with a data failure too
  105. (set-stream-rec-last-frame-written! stream-info 8200)
  106. (set-stream-rec-last-offset-written! stream-info (modulo (* 4 8200) buffer-bytes))
  107. (set-stream-rec-last-frame-read! stream-info 8000)
  108. (set-stream-rec-last-offset-read! stream-info (modulo (* 4 8000) buffer-bytes))
  109. (check-equal? (streaming-callback
  110. (s16vector->cpointer tgt)
  111. output-buffer-frames
  112. stream-info)
  113. pa-continue)
  114. (check-equal? (stream-rec-last-frame-read stream-info) 8224)
  115. (check-equal? (stream-rec-last-offset-read stream-info) (modulo (* 4 8224)
  116. buffer-bytes))
  117. ;; end of buffer:
  118. (for ([i (in-range (* 2 192))]
  119. [j (in-range (modulo (* 2 8000)
  120. (* 2 buffer-frames))
  121. (+ (* 2 192)
  122. (modulo (* 2 8000)
  123. (* 2 buffer-frames))))])
  124. (check-equal?
  125. (s16vector-ref tgt i)
  126. (ptr-ref (stream-rec-buffer stream-info) _sint16 j)))
  127. ;; around the corner:
  128. (for ([i (in-range (* 2 192) (* 2 200))]
  129. [j (in-range (* 2 8))])
  130. (check-equal?
  131. (s16vector-ref tgt i)
  132. (ptr-ref (stream-rec-buffer stream-info) _sint16 j)))
  133. (for ([i (in-range (* 2 200) (* 2 224))])
  134. (check-equal? (s16vector-ref tgt i) 0))
  135. ;; tests for call-buffer-filler
  136. (let () (define ptr-log empty)
  137. (define ftw-log empty)
  138. (define (bogus-buffer-filler cpointer frames-to-write)
  139. (set! ptr-log (cons cpointer ptr-log))
  140. (set! ftw-log (cons frames-to-write ftw-log)))
  141. (set-stream-rec-last-frame-read! stream-info 1000)
  142. (set-stream-rec-last-offset-read! stream-info (modulo (* 4 1000) buffer-bytes))
  143. (set-stream-rec-last-frame-written! stream-info 1500)
  144. (set-stream-rec-last-offset-written! stream-info
  145. (modulo (* 4 1500) buffer-bytes))
  146. (call-buffer-filler stream-info bogus-buffer-filler)
  147. (check-equal? ptr-log (list (stream-rec-buffer stream-info)
  148. (ptr-add (stream-rec-buffer stream-info)
  149. (* 4 1500))))
  150. (check-equal? ftw-log (list 1000
  151. (- 2048 1500))))
  152. ;; check on 2nd iteration:
  153. (let () (define ptr-log empty)
  154. (define ftw-log empty)
  155. (define (bogus-buffer-filler cpointer frames-to-write)
  156. (set! ptr-log (cons cpointer ptr-log))
  157. (set! ftw-log (cons frames-to-write ftw-log)))
  158. (set-stream-rec-last-frame-read! stream-info 3048)
  159. (set-stream-rec-last-offset-read! stream-info (modulo (* 4 3048) buffer-bytes))
  160. (set-stream-rec-last-frame-written! stream-info 3548)
  161. (set-stream-rec-last-offset-written! stream-info
  162. (modulo (* 4 3548) buffer-bytes))
  163. (call-buffer-filler stream-info bogus-buffer-filler)
  164. (check-equal? ptr-log (list (stream-rec-buffer stream-info)
  165. (ptr-add (stream-rec-buffer stream-info)
  166. (* 4 1500))))
  167. (check-equal? ftw-log (list 1000
  168. (- 2048 1500))))
  169. ;; check for reader got ahead of writer:
  170. (let () (define ptr-log empty)
  171. (define ftw-log empty)
  172. (define (bogus-buffer-filler cpointer frames-to-write)
  173. (set! ptr-log (cons cpointer ptr-log))
  174. (set! ftw-log (cons frames-to-write ftw-log)))
  175. ;; 1K frames after the beginning of the tenth go-round:
  176. (define read-frame (+ 1000 (* 10 buffer-frames)))
  177. (set-stream-rec-last-frame-read! stream-info read-frame)
  178. (set-stream-rec-last-offset-read! stream-info
  179. (modulo (* 4 read-frame) buffer-bytes))
  180. ;; writer fell way way behind:
  181. (set-stream-rec-last-frame-written! stream-info 14)
  182. (set-stream-rec-last-offset-written! stream-info
  183. (modulo (* 4 14) buffer-bytes))
  184. (call-buffer-filler stream-info bogus-buffer-filler)
  185. (check-equal? ptr-log (list (stream-rec-buffer stream-info)
  186. (ptr-add (stream-rec-buffer stream-info)
  187. (* 4 1000))))
  188. (check-equal? ftw-log (list 1000
  189. (- buffer-frames 1000))))
  190. )))