]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorJoe Groff <arcata@gmail.com>
Wed, 20 Jan 2010 19:49:59 +0000 (11:49 -0800)
committerJoe Groff <arcata@gmail.com>
Wed, 20 Jan 2010 19:49:59 +0000 (11:49 -0800)
extra/audio/engine/engine.factor
extra/audio/engine/test/test.factor
extra/game/worlds/worlds-docs.factor
extra/game/worlds/worlds.factor
extra/gpu/demos/raytrace/raytrace.factor

index 176fc3c3058104bee953b271eeb930b49a59641a..28b4900c85cf7ddbd356850ed9b7a219d45003f3 100644 (file)
@@ -56,10 +56,11 @@ M: audio-listener audio-gain gain>> ; inline
 M: audio-listener audio-velocity velocity>> ; inline
 M: audio-listener audio-orientation orientation>> ; inline
 
+GENERIC# generate-audio 1 ( generator buffer-size -- c-ptr size )
+GENERIC: generator-audio-format ( generator -- channels sample-bits sample-rate )
+
 TUPLE: audio-engine < disposable
     { voice-count integer }
-    { buffer-size integer }
-    { buffer-count integer }
     { al-device c-ptr }
     { al-context c-ptr }
     al-sources
@@ -70,17 +71,24 @@ TUPLE: audio-engine < disposable
 
 TUPLE: audio-clip < disposable
     { audio-engine audio-engine }
-    { audio audio }
     source
-    { loop? boolean }
-    { al-source integer }
-    { al-buffers uint-array }
-    { next-data-offset integer } ;
+    { al-source integer } ;
+
+TUPLE: static-audio-clip < audio-clip
+    { 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-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
         al-device [ device-name audio-device-not-found ] unless
@@ -96,12 +104,10 @@ ERROR: audio-context-not-available device-name ;
             voice-count >>voice-count
             al-device >>al-device
             al-context >>al-context
-            buffer-size >>buffer-size
-            buffer-count >>buffer-count
     ] with-destructors ;
 
 : <standard-audio-engine> ( -- engine )
-    f 16 8192 2 <audio-engine> ;
+    f 16 <audio-engine> ;
 
 <PRIVATE
 
@@ -111,12 +117,13 @@ ERROR: audio-context-not-available device-name ;
 : allocate-sources ( audio-engine -- sources )
     voice-count>> dup (uint-array) [ alGenSources ] keep ; inline
 
-:: flush-source ( source -- )
-    source alSourceStop
+:: flush-source ( al-source -- )
+    al-source alSourceStop
     0 c:<uint> :> dummy-buffer
-    source AL_BUFFERS_PROCESSED get-source-param [
-        source 1 dummy-buffer alSourceUnqueueBuffers
-    ] times ;
+    al-source AL_BUFFERS_PROCESSED get-source-param [
+        al-source 1 dummy-buffer alSourceUnqueueBuffers
+    ] times
+    al-source AL_BUFFER 0 alSourcei ;
 
 : free-sources ( sources -- )
     [ length ] keep alDeleteSources ; inline
@@ -141,44 +148,16 @@ ERROR: audio-context-not-available device-name ;
     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
+    audio-clip al-source>> :> al-source
+    audio-clip generator>> :> generator
+    audio-clip buffer-size>> :> buffer-size
+    generator buffer-size generate-audio :> ( data size )
 
-    {
-        { [ 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 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 ;
+    data [
+        al-buffer audio-clip openal-format data size audio-clip sample-rate>> alBufferData
+        al-source 1 al-buffer c:<uint> alSourceQueueBuffers
+    ] when ;
 
 : update-listener ( audio-engine -- )
     listener>> {
@@ -198,18 +177,24 @@ ERROR: audio-context-not-available device-name ;
         [ AL_ROLLOFF_FACTOR swap audio-rolloff alSourcef ]
     } 2cleave ;
 
-:: update-audio-clip ( audio-clip -- )
-    audio-clip update-source
+GENERIC: (update-audio-clip) ( audio-clip -- )
+
+M: static-audio-clip (update-audio-clip)
+    drop ;
+
+M:: streaming-audio-clip (update-audio-clip) ( audio-clip -- )
     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 ;
+    0 c:<uint> :> buffer
+    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 )
     [ length ] [ [ al-source>> ] uint-array{ } map-as ] bi ;
@@ -261,33 +246,61 @@ M: audio-engine dispose*
     [ [ alcCloseDevice*   ] when* f ] change-al-device
     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
 
     al-source [
-        audio-engine buffer-count>> :> buffer-count
         buffer-count dup (uint-array) [ alGenBuffers ] keep :> al-buffers
+        generator generator-audio-format :> ( channels sample-bits sample-rate )
 
         audio-clip new-disposable
             audio-engine >>audio-engine
-            audio >>audio
             source >>source
-            loop? >>loop?
             al-source >>al-source
+            generator >>generator
+            buffer-size >>buffer-size
+            channels >>channels
+            sample-bits >>sample-bits
+            sample-rate >>sample-rate
             al-buffers >>al-buffers
-            0 >>next-data-offset :> clip
+            :> 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 ]
-        [ al-buffers>> [ length ] keep alDeleteBuffers ]
-        [ dup audio-engine>> clips>> remove! drop ]
-    } cleave ;
+    [ dup audio-engine>> clips>> remove! drop ]
+    [ al-source>> flush-source ] bi ;
+
+M: static-audio-clip dispose*
+    [ call-next-method ]
+    [ [ 1 ] dip al-buffer>> c:<uint> alDeleteBuffers ] bi ;
+
+M: streaming-audio-clip dispose*
+    [ call-next-method ]
+    [ al-buffers>> [ length ] keep alDeleteBuffers ] bi ;
 
 : play-clip ( audio-clip -- )
     [ update-source ]
@@ -297,8 +310,11 @@ M: audio-clip dispose*
     [ [ update-source ] each ]
     [ clip-al-sources alSourcePlayv ] bi ;
 
-: <audio-clip> ( audio-engine audio source loop? -- audio-clip/f )
-    (audio-clip) dup play-clip ;
+: play-static-audio-clip ( audio-engine source audio loop? -- audio-clip/f )
+    <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 -- )
     al-source>> alSourcePause ;
index 59834a9fb240501d10dabe740659d8ee70cd0885..c81e7367c63fcd8583af5914521432a60d309d31 100644 (file)
@@ -9,8 +9,8 @@ IN: audio.engine.test
     0 :> i!
     <standard-audio-engine> :> engine
     engine 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
+    engine loop-sound T{ audio-source f { 1.0 0.0 0.0 } 1.0 { 0.0 0.0 0.0 } f } t
+        play-static-audio-clip :> loop-clip
 
     [
         i 1 + i!
@@ -19,7 +19,7 @@ IN: audio.engine.test
 
         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
+            play-static-audio-clip drop
         ] when
 
         engine update-audio
index 75aed4dbdad638aa049ebb529302123ad95d3e53..c10ae4056130bd70c3133b29d6ce9a518828bc43 100644 (file)
@@ -11,12 +11,10 @@ HELP: game-attributes
 { { $snippet "use-audio-engine?" } " specifies whether the game world should manage an " { $link audio-engine } " instance. False by default." }
 { { $snippet "audio-engine-device" } " specifies the string name of the OpenAL device the audio engine, if any, should try to open. The default value of " { $link POSTPONE: f } " attempts to open the default OpenAL device." }
 { { $snippet "audio-engine-voice-count" } " determines the number of independent voices the audio engine will make available. This determines how many individual audio clips can play simultaneously. This cannot exceed the OpenAL implementation's limit on supported voices." }
-{ { $snippet "audio-engine-buffer-size" } " determines the size in bytes of the audio buffers the audio engine will stream to the sound card." }
-{ { $snippet "audio-engine-buffer-count" } " determines the number of buffers the audio engine will allocate per audio clip played." }
 } ;
 
 HELP: game-world
-{ $class-description "A subclass of " { $link world } " that automatically sets up and manages connections to the " { $vocab-link "game.loop" } ", " { $vocab-link "game.input" } ", and " { $vocab-link "audio.engine" } " libraries. It does this by providing methods on " { $link begin-world } ", " { $link end-world } ", and " { $link draw* } ". Subclasses can provide their own world setup and teardown code by adding methods to the " { $link begin-game-world } " and " { $link end-game-world } " generic words."
+{ $class-description "A subclass of " { $link world } " that automatically sets up and manages connections to the " { $vocab-link "game.loop" } ", " { $vocab-link "game.input" } ", and " { $vocab-link "audio.engine" } " libraries. It does this by providing methods on " { $link begin-world } ", " { $link end-world } ", and " { $link draw* } ". Subclasses can provide their own world setup, teardown, and update code by adding methods to the " { $link begin-game-world } " and " { $link end-game-world } " generic words. The standard " { $snippet "world" } " generics " { $link draw-world* } " and " { $link resize-world } " can also be given methods to draw the window contents and handle resize events. The " { $snippet "draw-world*" } " method will be invoked in a tight loop by the game loop."
 $nl
 "The game-world tuple has the following publicly accessible slots:"
 { $list
@@ -49,6 +47,7 @@ ARTICLE: "game.worlds" "Game worlds"
     begin-game-world
     end-game-world
     tick-game-world
-} ;
+}
+"The standard " { $snippet "world" } " generics " { $link draw-world* } " and " { $link resize-world } " can also be given methods to draw the window contents and handle resize events. The " { $snippet "draw-world*" } " method will be invoked in a tight loop by the game loop to update the screen." ;
 
 ABOUT: "game.worlds"
index cf75d37b39c0c696605ed8482e0fc749a854e509..dd9b2431c921309793ba05d1a4f3999df74bf7d9 100644 (file)
@@ -12,8 +12,6 @@ TUPLE: game-world < world
     { use-audio-engine? boolean }
     { audio-engine-device initial: f }
     { audio-engine-voice-count initial: 16 }
-    { audio-engine-buffer-size initial: 8192 }
-    { audio-engine-buffer-count initial: 2 }
     { tick-slice float initial: 0.0 } ;
 
 GENERIC: begin-game-world ( world -- )
@@ -38,8 +36,6 @@ M: game-world draw*
     {
         [ audio-engine-device>> ]
         [ audio-engine-voice-count>> ]
-        [ audio-engine-buffer-size>> ]
-        [ audio-engine-buffer-count>> ]
     } cleave <audio-engine>
     [ start-audio* ] keep ; inline
 
@@ -63,9 +59,7 @@ TUPLE: game-attributes < world-attributes
     { use-game-input? boolean initial: f }
     { use-audio-engine? boolean initial: f }
     { audio-engine-device initial: f }
-    { audio-engine-voice-count initial: 16 }
-    { audio-engine-buffer-size initial: 8192 }
-    { audio-engine-buffer-count initial: 2 } ;
+    { audio-engine-voice-count initial: 16 } ;
 
 M: game-world apply-world-attributes
     {
@@ -74,8 +68,6 @@ M: game-world apply-world-attributes
         [ use-audio-engine?>> >>use-audio-engine? ]
         [ audio-engine-device>> >>audio-engine-device ]
         [ audio-engine-voice-count>> >>audio-engine-voice-count ]
-        [ audio-engine-buffer-size>> >>audio-engine-buffer-size ]
-        [ audio-engine-buffer-count>> >>audio-engine-buffer-count ]
         [ call-next-method ]
     } cleave ;
 
index 54912544f1defa4ed9da9a497b208cb3ce8c5877..5dcd5eeedc4871b815a9114b7ff62a2dccc297fe 100644 (file)
@@ -79,13 +79,13 @@ CONSTANT: initial-spheres {
     audio-engine world >>listener update-audio
 
     audio-engine "vocab:gpu/demos/raytrace/mirror-ball.aiff" read-audio
-    spheres first t (audio-clip)
+    spheres first t <static-audio-clip>
     audio-engine "vocab:gpu/demos/raytrace/red-ball.aiff" read-audio
-    spheres second t (audio-clip)
+    spheres second t <static-audio-clip>
     audio-engine "vocab:gpu/demos/raytrace/green-ball.aiff" read-audio
-    spheres third t (audio-clip)
+    spheres third t <static-audio-clip>
     audio-engine "vocab:gpu/demos/raytrace/yellow-ball.aiff" read-audio
-    spheres fourth t (audio-clip)
+    spheres fourth t <static-audio-clip>
     
     4array play-clips ;
 
@@ -124,7 +124,6 @@ GAME: raytrace-game {
         { grab-input? t }
         { use-game-input? t }
         { use-audio-engine? t }
-        { audio-engine-buffer-count 4 }
         { pref-dim { 1024 768 } }
         { tick-interval-micros $[ 60 fps ] }
     } ;