make audio.engine actually work, add audio.engine.test to exercise it

db4
Joe Groff 2010-01-19 10:29:25 -08:00
parent 5f8755a30c
commit b8d4a3e51b
4 changed files with 70 additions and 20 deletions

View File

@ -1,6 +1,6 @@
USING: accessors alien audio classes.struct USING: accessors alien audio classes.struct fry calendar alarms
combinators combinators.short-circuit destructors generalizations combinators combinators.short-circuit destructors generalizations
kernel locals math openal sequences specialized-arrays strings ; kernel literals locals math openal sequences specialized-arrays strings ;
QUALIFIED-WITH: alien.c-types c QUALIFIED-WITH: alien.c-types c
SPECIALIZED-ARRAYS: c:float c:uchar c:uint ; SPECIALIZED-ARRAYS: c:float c:uchar c:uint ;
IN: audio.engine IN: audio.engine
@ -23,10 +23,9 @@ TUPLE: audio-listener
{ position initial: { 0.0 0.0 0.0 } } { position initial: { 0.0 0.0 0.0 } }
{ gain float initial: 1.0 } { gain float initial: 1.0 }
{ velocity initial: { 0.0 0.0 0.0 } } { velocity initial: { 0.0 0.0 0.0 } }
orientation ; { orientation initial: T{ audio-orientation } } ;
TUPLE: audio-engine < disposable TUPLE: audio-engine < disposable
{ device-name string }
{ voice-count integer } { voice-count integer }
{ buffer-size integer } { buffer-size integer }
{ buffer-count integer } { buffer-count integer }
@ -35,7 +34,8 @@ TUPLE: audio-engine < disposable
al-sources al-sources
{ listener audio-listener } { listener audio-listener }
{ next-source integer } { next-source integer }
clips ; clips
update-alarm ;
TUPLE: audio-clip < disposable TUPLE: audio-clip < disposable
{ audio-engine audio-engine } { audio-engine audio-engine }
@ -61,15 +61,16 @@ ERROR: audio-context-not-available device-name ;
al-context alcSuspendContext al-context alcSuspendContext
audio-engine new audio-engine new-disposable
device-name >>device-name
voice-count >>voice-count voice-count >>voice-count
al-device >>al-device al-device >>al-device
al-context >>al-context al-context >>al-context
buffer-size >>buffer-size
buffer-count >>buffer-count
] with-destructors ; ] with-destructors ;
: <standard-audio-engine> ( -- engine ) : <standard-audio-engine> ( -- engine )
f 16 4096 2 <audio-engine> ; f 16 8192 2 <audio-engine> ;
<PRIVATE <PRIVATE
@ -95,7 +96,7 @@ ERROR: audio-context-not-available device-name ;
al-source { al-source {
[ AL_BUFFERS_PROCESSED get-source-param 0 = ] [ AL_BUFFERS_PROCESSED get-source-param 0 = ]
[ AL_BUFFERS_QUEUED get-source-param 0 = ] [ AL_BUFFERS_QUEUED get-source-param 0 = ]
[ AL_SOURCE_STATE get-source-param AL_STOPPED = ] [ AL_SOURCE_STATE get-source-param { $ AL_INITIAL $ AL_STOPPED } member? ]
} 1&& } 1&&
[ next-source# al-source ] [ [ next-source# al-source ] [
next-source# stop-source# = next-source# stop-source# =
@ -120,29 +121,33 @@ ERROR: audio-context-not-available device-name ;
audio-engine buffer-size>> :> buffer-size audio-engine buffer-size>> :> buffer-size
audio-clip audio>> :> audio audio-clip audio>> :> audio
audio-clip next-data-offset>> :> next-data-offset audio-clip next-data-offset>> :> next-data-offset
audio size>> next-data-offset - :> remaining-audio audio size>> next-data-offset - P :> remaining-audio
{ {
{ [ remaining-audio 0 <= ] [ { [ remaining-audio 0 <= ] [
audio-clip loop?>> [ audio-clip loop?>> [
"queue even wraparound" P drop
audio-clip 0 >>next-data-offset audio-clip 0 >>next-data-offset
al-buffer queue-clip-buffer al-buffer queue-clip-buffer
] when ] when
] } ] }
{ [ remaining-audio buffer-size < ] [ { [ remaining-audio buffer-size < ] [
audio-clip loop?>> [ audio-clip loop?>> [
"queue wraparound" P drop
audio data>> audio data>>
[ next-data-offset swap <displaced-alien> remaining-audio <direct-uchar-array> ] [ next-data-offset swap <displaced-alien> remaining-audio <direct-uchar-array> ]
[ buffer-size remaining-audio - <direct-uchar-array> ] bi append :> data [ buffer-size remaining-audio - <direct-uchar-array> ] bi append :> data
audio-clip al-buffer audio data remaining-audio (queue-clip-buffer) audio-clip al-buffer audio data buffer-size (queue-clip-buffer)
audio-clip [ audio size>> mod ] change-next-data-offset drop audio-clip [ audio size>> mod ] change-next-data-offset drop
] [ ] [
"queue tail" P drop
next-data-offset audio data>> <displaced-alien> :> data next-data-offset audio data>> <displaced-alien> :> data
audio-clip al-buffer audio data remaining-audio (queue-clip-buffer) audio-clip al-buffer audio data remaining-audio (queue-clip-buffer)
] if ] if
] } ] }
[ [
"queue normal" P drop
next-data-offset audio data>> <displaced-alien> :> data next-data-offset audio data>> <displaced-alien> :> data
audio-clip al-buffer audio data buffer-size (queue-clip-buffer) audio-clip al-buffer audio data buffer-size (queue-clip-buffer)
] ]
@ -170,8 +175,8 @@ ERROR: audio-context-not-available device-name ;
0 c:<uint> :> buffer* 0 c:<uint> :> buffer*
al-source AL_SOURCE_STATE get-source-param AL_STOPPED = al-source AL_SOURCE_STATE get-source-param AL_STOPPED =
[ audio-clip dispose ] [ [ "stopped" P drop audio-clip dispose ] [
al-source AL_BUFFERS_PROCESSED get-source-param [ al-source AL_BUFFERS_PROCESSED get-source-param P [
al-source 1 buffer* alSourceUnqueueBuffers al-source 1 buffer* alSourceUnqueueBuffers
audio-clip buffer* c:*uint queue-clip-buffer audio-clip buffer* c:*uint queue-clip-buffer
] times ] times
@ -181,7 +186,7 @@ PRIVATE>
DEFER: update-audio DEFER: update-audio
: start-audio ( audio-engine -- ) : start-audio* ( audio-engine -- )
dup al-sources>> [ drop ] [ dup al-sources>> [ drop ] [
{ {
[ make-engine-current ] [ make-engine-current ]
@ -192,19 +197,26 @@ DEFER: update-audio
V{ } clone >>clips V{ } clone >>clips
drop drop
] ]
[ update-audio ] [ update-listener ]
} cleave } cleave
] if ; ] if ;
: start-audio ( audio-engine -- )
dup start-audio*
dup '[ _ update-audio ] 20 milliseconds every >>update-alarm
drop ;
: stop-audio ( audio-engine -- ) : stop-audio ( audio-engine -- )
dup al-sources>> [ dup al-sources>> [
{ {
[ make-engine-current ] [ make-engine-current ]
[ clips>> [ dispose ] each ] [ update-alarm>> [ cancel-alarm ] when* ]
[ clips>> clone [ dispose ] each ]
[ al-sources>> free-sources ] [ al-sources>> free-sources ]
[ [
f >>al-sources f >>al-sources
f >>clips f >>clips
f >>update-alarm
drop drop
] ]
[ al-context>> alcSuspendContext ] [ al-context>> alcSuspendContext ]
@ -217,14 +229,14 @@ M: audio-engine dispose*
[ [ alcCloseDevice* ] when* f ] change-al-device [ [ alcCloseDevice* ] when* f ] change-al-device
drop ; drop ;
:: <audio-clip> ( audio-engine audio source loop? -- audio-clip/f ) :: (audio-clip) ( audio-engine audio source loop? -- audio-clip/f )
audio-engine get-available-source :> al-source audio-engine get-available-source :> al-source
al-source [ al-source [
audio-engine buffer-count>> :> buffer-count audio-engine buffer-count>> :> buffer-count
buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers
audio-clip new audio-clip new-disposable
audio-engine >>audio-engine audio-engine >>audio-engine
audio >>audio audio >>audio
source >>source source >>source
@ -241,12 +253,16 @@ M: audio-engine dispose*
M: audio-clip dispose* M: audio-clip dispose*
{ {
[ al-source>> flush-source ] [ al-source>> flush-source ]
[ buffer-count>> [ length ] keep alDeleteBuffers ] [ al-buffers>> [ length ] keep alDeleteBuffers ]
[ dup audio-engine>> clips>> remove! drop ] [ dup audio-engine>> clips>> remove! drop ]
} cleave ; } cleave ;
: play-clip ( audio-clip -- ) : play-clip ( audio-clip -- )
al-source>> alSourcePlay ; [ update-source ]
[ al-source>> alSourcePlay ] bi ;
: <audio-clip> ( audio-engine audio source loop? -- audio-clip/f )
(audio-clip) dup play-clip ;
: pause-clip ( audio-clip -- ) : pause-clip ( audio-clip -- )
al-source>> alSourcePause ; al-source>> alSourcePause ;
@ -256,6 +272,7 @@ M: audio-clip dispose*
: update-audio ( audio-engine -- ) : update-audio ( audio-engine -- )
{ {
[ make-engine-current ]
[ update-listener ] [ update-listener ]
[ clips>> [ update-audio-clip ] each ] [ clips>> [ update-audio-clip ] each ]
} cleave ; } cleave ;

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,33 @@
USING: accessors alarms audio audio.engine audio.wav calendar
destructors io kernel locals math math.functions ;
IN: audio.engine.test
USE: prettyprint
:: audio-engine-test ( -- )
"vocab:audio/engine/test/loop.wav" read-wav :> loop-sound
"vocab:audio/engine/test/once.wav" read-wav :> once-sound
0 :> i!
<standard-audio-engine> :> engine
engine dup . start-audio*
engine loop-sound T{ audio-source f { 1.0 0.0 0.0 } 1.0 { 0.0 0.0 0.0 } f } t <audio-clip>
:> loop-clip
[
i 1 + i!
i 0.05 * sin :> s
loop-clip source>> { s 0.0 0.0 } >>position drop
i 50 mod zero? [
engine once-sound T{ audio-source f { 0.0 0.0 0.0 } 1.0 { 0.0 0.0 0.0 } f } f
<audio-clip> drop
] when
engine update-audio
] 20 milliseconds every :> alarm
"Press Enter to stop the test." print
readln drop
alarm cancel-alarm
engine dispose ;
MAIN: audio-engine-test