audio.engine initial code dump
parent
2b96f43929
commit
ace167991d
|
@ -0,0 +1,262 @@
|
|||
USING: accessors alien audio classes.struct
|
||||
combinators combinators.short-circuit destructors generalizations
|
||||
kernel locals math openal sequences specialized-arrays strings ;
|
||||
QUALIFIED-WITH: alien.c-types c
|
||||
SPECIALIZED-ARRAYS: c:float c:uchar c:uint ;
|
||||
IN: audio.engine
|
||||
|
||||
TUPLE: audio-source
|
||||
{ position initial: { 0.0 0.0 0.0 } }
|
||||
{ gain float initial: 1.0 }
|
||||
{ velocity initial: { 0.0 0.0 0.0 } }
|
||||
{ relative? boolean initial: f } ;
|
||||
|
||||
TUPLE: audio-orientation
|
||||
{ forward initial: { 0.0 0.0 -1.0 } }
|
||||
{ up initial: { 0.0 1.0 0.0 } } ;
|
||||
|
||||
: orientation>float-array ( orientation -- float-array )
|
||||
[ forward>> first3 ]
|
||||
[ up>> first3 ] bi 6 float-array{ } nsequence ; inline
|
||||
|
||||
TUPLE: audio-listener
|
||||
{ position initial: { 0.0 0.0 0.0 } }
|
||||
{ gain float initial: 1.0 }
|
||||
{ velocity initial: { 0.0 0.0 0.0 } }
|
||||
orientation ;
|
||||
|
||||
TUPLE: audio-engine < disposable
|
||||
{ device-name string }
|
||||
{ voice-count integer }
|
||||
{ buffer-size integer }
|
||||
{ buffer-count integer }
|
||||
{ al-device c-ptr }
|
||||
{ al-context c-ptr }
|
||||
al-sources
|
||||
{ listener audio-listener }
|
||||
{ next-source integer }
|
||||
clips ;
|
||||
|
||||
TUPLE: audio-clip < disposable
|
||||
{ audio-engine audio-engine }
|
||||
{ audio audio }
|
||||
{ source audio-source }
|
||||
{ loop? boolean }
|
||||
{ al-source integer }
|
||||
{ al-buffers uint-array }
|
||||
{ next-data-offset integer } ;
|
||||
|
||||
ERROR: audio-device-not-found device-name ;
|
||||
ERROR: audio-context-not-available device-name ;
|
||||
|
||||
:: <audio-engine> ( device-name voice-count buffer-size buffer-count -- engine )
|
||||
[
|
||||
device-name alcOpenDevice :> al-device
|
||||
al-device [ device-name audio-device-not-found ] unless
|
||||
al-device |alcCloseDevice* drop
|
||||
|
||||
al-device f alcCreateContext :> al-context
|
||||
al-context [ device-name audio-context-not-available ] unless
|
||||
al-context |alcDestroyContext drop
|
||||
|
||||
al-context alcSuspendContext
|
||||
|
||||
audio-engine new
|
||||
device-name >>device-name
|
||||
voice-count >>voice-count
|
||||
al-device >>al-device
|
||||
al-context >>al-context
|
||||
] with-destructors ;
|
||||
|
||||
: <standard-audio-engine> ( -- engine )
|
||||
f 16 4096 2 <audio-engine> ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: make-engine-current ( audio-engine -- )
|
||||
al-context>> alcMakeContextCurrent drop ; inline
|
||||
|
||||
: allocate-sources ( audio-engine -- sources )
|
||||
voice-count>> dup (uint-array) [ alGenSources ] keep ; inline
|
||||
|
||||
:: flush-source ( source -- )
|
||||
source alSourceStop
|
||||
0 c:<uint> :> dummy-buffer
|
||||
source AL_BUFFERS_PROCESSED get-source-param [
|
||||
source 1 dummy-buffer alSourceUnqueueBuffers
|
||||
] times ;
|
||||
|
||||
: free-sources ( sources -- )
|
||||
[ length ] keep alDeleteSources ; inline
|
||||
|
||||
:: (get-available-source) ( sources source# stop-source# -- next-source# al-source/f )
|
||||
source# sources nth :> al-source
|
||||
source# 1 + sources length mod :> next-source#
|
||||
al-source {
|
||||
[ AL_BUFFERS_PROCESSED get-source-param 0 = ]
|
||||
[ AL_BUFFERS_QUEUED get-source-param 0 = ]
|
||||
[ AL_SOURCE_STATE get-source-param AL_STOPPED = ]
|
||||
} 1&&
|
||||
[ next-source# al-source ] [
|
||||
next-source# stop-source# =
|
||||
[ next-source# f ]
|
||||
[ sources next-source# stop-source# (get-available-source) ] if
|
||||
] if ;
|
||||
|
||||
:: get-available-source ( audio-engine -- al-source/f )
|
||||
audio-engine [ al-sources>> ] [ next-source>> ] bi dup (get-available-source)
|
||||
:> ( next-source al-source )
|
||||
audio-engine next-source >>next-source drop
|
||||
al-source ;
|
||||
|
||||
:: (queue-clip-buffer) ( audio-clip al-buffer audio data size -- )
|
||||
al-buffer audio openal-format data size audio sample-rate>> alBufferData
|
||||
audio-clip al-source>> 1 al-buffer c:<uint> alSourceQueueBuffers
|
||||
|
||||
audio-clip [ size + ] change-next-data-offset drop ; inline
|
||||
|
||||
:: queue-clip-buffer ( audio-clip al-buffer -- )
|
||||
audio-clip audio-engine>> :> audio-engine
|
||||
audio-engine buffer-size>> :> buffer-size
|
||||
audio-clip audio>> :> audio
|
||||
audio-clip next-data-offset>> :> next-data-offset
|
||||
audio size>> next-data-offset - :> remaining-audio
|
||||
|
||||
{
|
||||
{ [ remaining-audio 0 <= ] [
|
||||
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 remaining-audio (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 -- )
|
||||
listener>> {
|
||||
[ AL_POSITION swap position>> first3 alListener3f ]
|
||||
[ AL_GAIN swap gain>> alListenerf ]
|
||||
[ AL_VELOCITY swap velocity>> first3 alListener3f ]
|
||||
[ AL_ORIENTATION swap orientation>> orientation>float-array alListenerfv ]
|
||||
} cleave ;
|
||||
|
||||
: update-source ( audio-clip -- )
|
||||
[ al-source>> ] [ source>> ] bi {
|
||||
[ AL_POSITION swap position>> first3 alSource3f ]
|
||||
[ AL_GAIN swap gain>> alSourcef ]
|
||||
[ AL_VELOCITY swap velocity>> first3 alSource3f ]
|
||||
[ AL_SOURCE_RELATIVE swap relative?>> c:>c-bool alSourcei ]
|
||||
} 2cleave ;
|
||||
|
||||
:: 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 =
|
||||
[ audio-clip dispose ] [
|
||||
al-source AL_BUFFERS_PROCESSED get-source-param [
|
||||
al-source 1 buffer* alSourceUnqueueBuffers
|
||||
audio-clip buffer* c:*uint queue-clip-buffer
|
||||
] times
|
||||
] if ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
DEFER: update-audio
|
||||
|
||||
: start-audio ( audio-engine -- )
|
||||
dup al-sources>> [ drop ] [
|
||||
{
|
||||
[ make-engine-current ]
|
||||
[ al-context>> alcProcessContext ]
|
||||
[
|
||||
dup allocate-sources >>al-sources
|
||||
0 >>next-source
|
||||
V{ } clone >>clips
|
||||
drop
|
||||
]
|
||||
[ update-audio ]
|
||||
} cleave
|
||||
] if ;
|
||||
|
||||
: stop-audio ( audio-engine -- )
|
||||
dup al-sources>> [
|
||||
{
|
||||
[ make-engine-current ]
|
||||
[ clips>> [ dispose ] each ]
|
||||
[ al-sources>> free-sources ]
|
||||
[
|
||||
f >>al-sources
|
||||
f >>clips
|
||||
drop
|
||||
]
|
||||
[ al-context>> alcSuspendContext ]
|
||||
} cleave
|
||||
] [ drop ] if ;
|
||||
|
||||
M: audio-engine dispose*
|
||||
dup stop-audio
|
||||
[ [ alcDestroyContext ] when* f ] change-al-context
|
||||
[ [ alcCloseDevice* ] when* f ] change-al-device
|
||||
drop ;
|
||||
|
||||
:: <audio-clip> ( audio-engine audio source loop? -- audio-clip/f )
|
||||
audio-engine get-available-source :> al-source
|
||||
|
||||
al-source [
|
||||
audio-engine buffer-count>> :> buffer-count
|
||||
buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers
|
||||
|
||||
audio-clip new
|
||||
audio-engine >>audio-engine
|
||||
audio >>audio
|
||||
source >>source
|
||||
loop? >>loop?
|
||||
al-source >>al-source
|
||||
al-buffers >>al-buffers
|
||||
0 >>next-data-offset :> clip
|
||||
al-buffers [ clip swap queue-clip-buffer ] each
|
||||
clip audio-engine clips>> push
|
||||
|
||||
clip
|
||||
] [ f ] if ;
|
||||
|
||||
M: audio-clip dispose*
|
||||
{
|
||||
[ al-source>> flush-source ]
|
||||
[ buffer-count>> [ length ] keep alDeleteBuffers ]
|
||||
[ dup audio-engine>> clips>> remove! drop ]
|
||||
} cleave ;
|
||||
|
||||
: play-clip ( audio-clip -- )
|
||||
al-source>> alSourcePlay ;
|
||||
|
||||
: pause-clip ( audio-clip -- )
|
||||
al-source>> alSourcePause ;
|
||||
|
||||
: stop-clip ( audio-clip -- )
|
||||
dispose ;
|
||||
|
||||
: update-audio ( audio-engine -- )
|
||||
{
|
||||
[ update-listener ]
|
||||
[ clips>> [ update-audio-clip ] each ]
|
||||
} cleave ;
|
||||
|
Loading…
Reference in New Issue