audio.engine improvements: support static and streaming audio clips. let openal handle static sources to avoid factor timer vagaries. rename (audio-clip) to <static-audio-clip>/<streaming-audio-clip>, and <audio-clip> to play-static-audio-clip/play-streaming-audio-clip
parent
67472040a9
commit
7a27d8a92b
|
@ -56,10 +56,11 @@ M: audio-listener audio-gain gain>> ; inline
|
||||||
M: audio-listener audio-velocity velocity>> ; inline
|
M: audio-listener audio-velocity velocity>> ; inline
|
||||||
M: audio-listener audio-orientation orientation>> ; inline
|
M: audio-listener audio-orientation orientation>> ; inline
|
||||||
|
|
||||||
|
GENERIC# generate-audio 1 ( generator buffer-size -- c-ptr )
|
||||||
|
GENERIC: generator-audio-format ( generator -- channels sample-bits sample-rate )
|
||||||
|
|
||||||
TUPLE: audio-engine < disposable
|
TUPLE: audio-engine < disposable
|
||||||
{ voice-count integer }
|
{ voice-count integer }
|
||||||
{ buffer-size integer }
|
|
||||||
{ buffer-count integer }
|
|
||||||
{ al-device c-ptr }
|
{ al-device c-ptr }
|
||||||
{ al-context c-ptr }
|
{ al-context c-ptr }
|
||||||
al-sources
|
al-sources
|
||||||
|
@ -70,17 +71,24 @@ TUPLE: audio-engine < disposable
|
||||||
|
|
||||||
TUPLE: audio-clip < disposable
|
TUPLE: audio-clip < disposable
|
||||||
{ audio-engine audio-engine }
|
{ audio-engine audio-engine }
|
||||||
{ audio audio }
|
|
||||||
source
|
source
|
||||||
{ loop? boolean }
|
{ al-source integer } ;
|
||||||
{ al-source integer }
|
|
||||||
{ al-buffers uint-array }
|
TUPLE: static-audio-clip < audio-clip
|
||||||
{ next-data-offset integer } ;
|
{ al-buffer integer } ;
|
||||||
|
|
||||||
|
TUPLE: streaming-audio-clip < audio-clip
|
||||||
|
generator
|
||||||
|
{ buffer-size integer }
|
||||||
|
{ channels integer }
|
||||||
|
{ sample-bits integer }
|
||||||
|
{ sample-rate integer }
|
||||||
|
{ al-buffers uint-array } ;
|
||||||
|
|
||||||
ERROR: audio-device-not-found device-name ;
|
ERROR: audio-device-not-found device-name ;
|
||||||
ERROR: audio-context-not-available device-name ;
|
ERROR: audio-context-not-available device-name ;
|
||||||
|
|
||||||
:: <audio-engine> ( device-name voice-count buffer-size buffer-count -- engine )
|
:: <audio-engine> ( device-name voice-count -- engine )
|
||||||
[
|
[
|
||||||
device-name alcOpenDevice :> al-device
|
device-name alcOpenDevice :> al-device
|
||||||
al-device [ device-name audio-device-not-found ] unless
|
al-device [ device-name audio-device-not-found ] unless
|
||||||
|
@ -96,12 +104,10 @@ ERROR: audio-context-not-available 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 8192 2 <audio-engine> ;
|
f 16 <audio-engine> ;
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
|
@ -111,12 +117,13 @@ ERROR: audio-context-not-available device-name ;
|
||||||
: allocate-sources ( audio-engine -- sources )
|
: allocate-sources ( audio-engine -- sources )
|
||||||
voice-count>> dup (uint-array) [ alGenSources ] keep ; inline
|
voice-count>> dup (uint-array) [ alGenSources ] keep ; inline
|
||||||
|
|
||||||
:: flush-source ( source -- )
|
:: flush-source ( al-source -- )
|
||||||
source alSourceStop
|
al-source alSourceStop
|
||||||
0 c:<uint> :> dummy-buffer
|
0 c:<uint> :> dummy-buffer
|
||||||
source AL_BUFFERS_PROCESSED get-source-param [
|
al-source AL_BUFFERS_PROCESSED get-source-param [
|
||||||
source 1 dummy-buffer alSourceUnqueueBuffers
|
al-source 1 dummy-buffer alSourceUnqueueBuffers
|
||||||
] times ;
|
] times
|
||||||
|
al-source AL_BUFFER 0 alSourcei ;
|
||||||
|
|
||||||
: free-sources ( sources -- )
|
: free-sources ( sources -- )
|
||||||
[ length ] keep alDeleteSources ; inline
|
[ length ] keep alDeleteSources ; inline
|
||||||
|
@ -148,37 +155,13 @@ ERROR: audio-context-not-available device-name ;
|
||||||
audio-clip [ size + ] change-next-data-offset drop ; inline
|
audio-clip [ size + ] change-next-data-offset drop ; inline
|
||||||
|
|
||||||
:: queue-clip-buffer ( audio-clip al-buffer -- )
|
:: queue-clip-buffer ( audio-clip al-buffer -- )
|
||||||
audio-clip audio-engine>> :> audio-engine
|
audio-clip al-source>> :> al-source
|
||||||
audio-engine buffer-size>> :> buffer-size
|
audio-clip generator>> :> generator
|
||||||
audio-clip audio>> :> audio
|
audio-clip buffer-size>> :> buffer-size
|
||||||
audio-clip next-data-offset>> :> next-data-offset
|
generator buffer-size generate-audio :> data
|
||||||
audio size>> next-data-offset - :> remaining-audio
|
|
||||||
|
|
||||||
{
|
al-buffer audio-clip openal-format data size audio-clip sample-rate>> alBufferData
|
||||||
{ [ remaining-audio 0 <= ] [
|
al-source 1 al-buffer c:<uint> alSourceQueueBuffers ;
|
||||||
audio-clip loop?>> [
|
|
||||||
audio-clip 0 >>next-data-offset
|
|
||||||
al-buffer queue-clip-buffer
|
|
||||||
] when
|
|
||||||
] }
|
|
||||||
{ [ remaining-audio buffer-size < ] [
|
|
||||||
audio-clip loop?>> [
|
|
||||||
audio data>>
|
|
||||||
[ next-data-offset swap <displaced-alien> remaining-audio <direct-uchar-array> ]
|
|
||||||
[ buffer-size remaining-audio - <direct-uchar-array> ] bi append :> data
|
|
||||||
audio-clip al-buffer audio data buffer-size (queue-clip-buffer)
|
|
||||||
|
|
||||||
audio-clip [ audio size>> mod ] change-next-data-offset drop
|
|
||||||
] [
|
|
||||||
next-data-offset audio data>> <displaced-alien> :> data
|
|
||||||
audio-clip al-buffer audio data remaining-audio (queue-clip-buffer)
|
|
||||||
] if
|
|
||||||
] }
|
|
||||||
[
|
|
||||||
next-data-offset audio data>> <displaced-alien> :> data
|
|
||||||
audio-clip al-buffer audio data buffer-size (queue-clip-buffer)
|
|
||||||
]
|
|
||||||
} cond ;
|
|
||||||
|
|
||||||
: update-listener ( audio-engine -- )
|
: update-listener ( audio-engine -- )
|
||||||
listener>> {
|
listener>> {
|
||||||
|
@ -198,18 +181,24 @@ ERROR: audio-context-not-available device-name ;
|
||||||
[ AL_ROLLOFF_FACTOR swap audio-rolloff alSourcef ]
|
[ AL_ROLLOFF_FACTOR swap audio-rolloff alSourcef ]
|
||||||
} 2cleave ;
|
} 2cleave ;
|
||||||
|
|
||||||
:: update-audio-clip ( audio-clip -- )
|
GENERIC: (update-audio-clip) ( audio-clip -- )
|
||||||
audio-clip update-source
|
|
||||||
audio-clip al-source>> :> al-source
|
|
||||||
0 c:<uint> :> buffer*
|
|
||||||
|
|
||||||
al-source AL_SOURCE_STATE get-source-param AL_STOPPED =
|
M: static-audio-clip (update-audio-clip)
|
||||||
[ audio-clip dispose ] [
|
drop ;
|
||||||
al-source AL_BUFFERS_PROCESSED get-source-param [
|
|
||||||
al-source 1 buffer* alSourceUnqueueBuffers
|
M:: streaming-audio-clip (update-audio-clip) ( audio-clip -- )
|
||||||
audio-clip buffer* c:*uint queue-clip-buffer
|
audio-clip al-source>> :> al-source
|
||||||
] times
|
0 c:<uint> :> buffer
|
||||||
] if ;
|
al-source AL_BUFFERS_PROCESSED get-source-param [
|
||||||
|
al-source 1 buffer alSourceUnqueueBuffers
|
||||||
|
audio-clip buffer c:*uint queue-clip-buffer
|
||||||
|
] times ;
|
||||||
|
|
||||||
|
: update-audio-clip ( audio-clip -- )
|
||||||
|
[ update-source ] [
|
||||||
|
dup al-source>> AL_SOURCE_STATE get-source-param AL_STOPPED =
|
||||||
|
[ dispose ] [ (update-audio-clip) ] if
|
||||||
|
] bi ;
|
||||||
|
|
||||||
: clip-al-sources ( clips -- length sources )
|
: clip-al-sources ( clips -- length sources )
|
||||||
[ length ] [ [ al-source>> ] uint-array{ } map-as ] bi ;
|
[ length ] [ [ al-source>> ] uint-array{ } map-as ] bi ;
|
||||||
|
@ -261,33 +250,59 @@ 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 )
|
:: <static-audio-clip> ( audio-engine audio source loop? -- audio-clip/f )
|
||||||
|
audio-engine get-available-source :> al-source
|
||||||
|
|
||||||
|
al-source [
|
||||||
|
1 0 c:<uint> [ alGenBuffers ] keep c:*uint :> al-buffer
|
||||||
|
al-buffer audio { [ openal-format ] [ data>> ] [ size>> ] [ sample-rate>> ] } cleave
|
||||||
|
alBufferData
|
||||||
|
|
||||||
|
al-source AL_BUFFER al-buffer alSourcei
|
||||||
|
al-source AL_LOOPING loop? c:>c-bool alSourcei
|
||||||
|
|
||||||
|
static-audio-clip new-disposable
|
||||||
|
audio-engine >>audio-engine
|
||||||
|
source >>source
|
||||||
|
al-source >>al-source
|
||||||
|
al-buffer >>al-buffer :> clip
|
||||||
|
clip audio-engine clips>> push
|
||||||
|
clip
|
||||||
|
] [ f ] if ;
|
||||||
|
|
||||||
|
:: <streaming-audio-clip> ( audio-engine source generator buffer-size buffer-count -- 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
|
|
||||||
buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers
|
buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers
|
||||||
|
generator generator-audio-format :> ( channels sample-bits sample-rate )
|
||||||
|
|
||||||
audio-clip new-disposable
|
audio-clip new-disposable
|
||||||
audio-engine >>audio-engine
|
audio-engine >>audio-engine
|
||||||
audio >>audio
|
|
||||||
source >>source
|
source >>source
|
||||||
loop? >>loop?
|
|
||||||
al-source >>al-source
|
al-source >>al-source
|
||||||
|
generator >>generator
|
||||||
|
buffer-size >>buffer-size
|
||||||
|
channels >>channels
|
||||||
|
sample-bits >>sample-bits
|
||||||
|
sample-rate >>sample-rate
|
||||||
al-buffers >>al-buffers
|
al-buffers >>al-buffers
|
||||||
0 >>next-data-offset :> clip
|
|
||||||
al-buffers [ clip swap queue-clip-buffer ] each
|
al-buffers [ clip swap queue-clip-buffer ] each
|
||||||
clip audio-engine clips>> push
|
clip audio-engine clips>> push
|
||||||
|
|
||||||
clip
|
clip
|
||||||
] [ f ] if ;
|
] [ f ] if ;
|
||||||
|
|
||||||
M: audio-clip dispose*
|
M: audio-clip dispose*
|
||||||
{
|
[ audio-engine>> clips>> remove! drop ]
|
||||||
[ al-source>> flush-source ]
|
[ al-source>> flush-source ] bi ;
|
||||||
[ al-buffers>> [ length ] keep alDeleteBuffers ]
|
|
||||||
[ dup audio-engine>> clips>> remove! drop ]
|
M: static-audio-clip dispose*
|
||||||
} cleave ;
|
[ call-next-method ]
|
||||||
|
[ [ 1 ] dip al-buffer>> <uint> alDeleteBuffers ] bi ;
|
||||||
|
|
||||||
|
M: streaming-audio-clip dispose*
|
||||||
|
[ call-next-method ]
|
||||||
|
[ al-buffers>> [ length ] keep alDeleteBuffers ] bi ;
|
||||||
|
|
||||||
: play-clip ( audio-clip -- )
|
: play-clip ( audio-clip -- )
|
||||||
[ update-source ]
|
[ update-source ]
|
||||||
|
@ -297,8 +312,11 @@ M: audio-clip dispose*
|
||||||
[ [ update-source ] each ]
|
[ [ update-source ] each ]
|
||||||
[ clip-al-sources alSourcePlayv ] bi ;
|
[ clip-al-sources alSourcePlayv ] bi ;
|
||||||
|
|
||||||
: <audio-clip> ( audio-engine audio source loop? -- audio-clip/f )
|
: play-static-audio-clip ( audio-engine source audio loop? -- audio-clip/f )
|
||||||
(audio-clip) dup play-clip ;
|
<static-audio-clip> dup [ play-clip ] when* ;
|
||||||
|
|
||||||
|
: play-streaming-audio-clip ( audio-engine source generator buffer-size buffer-count -- audio-clip/f )
|
||||||
|
<streaming-audio-clip> dup [ play-clip ] when* ;
|
||||||
|
|
||||||
: pause-clip ( audio-clip -- )
|
: pause-clip ( audio-clip -- )
|
||||||
al-source>> alSourcePause ;
|
al-source>> alSourcePause ;
|
||||||
|
|
Loading…
Reference in New Issue