 
 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

        [ AL_ROLLOFF_FACTOR swap audio-rolloff alSourcef ]
    } 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 ;

: clip-al-sources ( clips -- length sources )
    [ length ] [ [ al-source>> ] uint-array{ } map-as ] bi ;

: allocate-sources ( audio-engine -- sources )
    voice-count>> dup (uint-array) [ alGenSources ] keep ; inline

:: flush-source ( al-source -- )
    al-source alSourceStop
    0 c:<uint> :> dummy-buffer
    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
