sourceextensions/audio/lib/Audio.xtl
1⍝# Audio.xtl -- the facade of the audio extension: decode Ogg Vorbis, MP3
2⍝# and WAV, play them on the sound device, read what is playing as arrays,
3⍝# and play arrays.
4⍝# Import: "au:" u_se< "Audio"
5⍝# Run with xetal-x (xetal-x --ext DIR puts this directory on XETAL_PATH).
6⍝# With XETAL_HEADLESS=1 (or XETAL_AUDIO=off) nothing sounds and playback
7⍝# advances a 60th of a second per au:w_indow (or au:p_layed) -- for tests.
8⍝# Each signature line is written out by the binding macro (lib/Ffi.xtlm).
9
10ᶠᶠⁱ⁼u̲se< "Ffi"
11
12⍝# au:o_pen path: an audio file (Ogg Vorbis, MP3 or WAV); its id.
13"o_pen : text -> int" ᶠᶠⁱb̲ind< "audio/open"
14⍝# au:i_nfo id: sample rate, channels, frames, seconds (-1 when unknown).
15"i_nfo : float -> floats" ᶠᶠⁱb̲ind< "audio/info"
16⍝# id au:c_hunk n: the next n frames read in order (apart from playback):
17⍝# a 2 by m matrix, left over right; fewer at the end, none after it.
18"c_hunk : float float -> floats" ᶠᶠⁱb̲ind< "audio/chunk"
19⍝# au:p_lay! id: start or resume playing; the id.
20"p_lay! : float -> int" ᶠᶠⁱb̲ind< "audio/play"
21⍝# au:p_ause! id: pause; the id.
22"p_ause! : float -> int" ᶠᶠⁱb̲ind< "audio/pause"
23⍝# id au:s_eek! seconds: move playback there; the second it landed on.
24"s_eek! : float float -> float" ᶠᶠⁱb̲ind< "audio/seek"
25⍝# au:p_osition id: the second playing now.
26"p_osition : float -> float" ᶠᶠⁱb̲ind< "audio/position"
27⍝# id au:w_indow n: the n frames ending at what plays now, 2 by n (left
28⍝# over right; zeros before the start). Call it once a frame.
29"w_indow : float float -> floats" ᶠᶠⁱb̲ind< "audio/window"
30⍝# au:s_tate id: 0 stopped (not started, or at the end), 1 playing, 2 paused.
31"s_tate : float -> int" ᶠᶠⁱb̲ind< "audio/state"
32⍝# au:c_lose! id: stop and forget a file; a voice plays out what is queued
33⍝# (or writes its WAV) first; 1.
34"c_lose! : float -> int" ᶠᶠⁱb̲ind< "audio/close"
35
36⍝## Sound out of arrays
37
38⍝# au:o_utput rate: a voice playing what the program queues, at rate
39⍝# frames a second (22050 is plenty for a synthesizer); its id.
40"o_utput : float -> int" ᶠᶠⁱb̲ind< "audio/output"
41⍝# id au:q_ueue! samples: play these after what is queued -- a vector
42⍝# (mono) or 2 by n (left over right), from -1 to 1; the seconds now
43⍝# queued ahead. With no device (XETAL_AUDIO=off) nothing sounds, and
44⍝# XETAL_AUDIO_WAV=FILE collects everything queued in a WAV file.
45"q_ueue! : float float -> float" ᶠᶠⁱb̲ind< "audio/queue"
46⍝# id au:w_ait! seconds: wait until at most that much is queued, so a
47⍝# program can stream without hurrying; the seconds played so far.
48"w_ait! : float float -> float" ᶠᶠⁱb̲ind< "audio/wait"
49⍝# au:p_layed id: the second a voice is playing now -- to draw what is
50⍝# heard (with no device, a 60th of a second more each time it is asked).
51"p_layed : float -> float" ᶠᶠⁱb̲ind< "audio/played"
52
53⍝# The native package behind these functions.
54ˡpackage ← "audio"
ᶠᶠⁱb̲ind< expands to
ˡo̲pen ← { a → pa ← a ⎕N̲PUT "ext:audio/open?text" f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/open" }
ᶠᶠⁱb̲ind< expands to
ˡi̲nfo ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/info?float=" c̲at f̲ormat s̲hape a v ← n̲umbers ⎕N̲GET "ext:audio/info" (f̲loor n̲umbers ⎕N̲GET "ext:audio/info?shape") r̲eshape v }
ᶠᶠⁱb̲ind< expands to
ˡc̲hunk ← { a b → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/chunk?float=" c̲at f̲ormat s̲hape a pb ← (f̲ormat r̲avel f̲loat b) ⎕N̲PUT "ext:audio/chunk?float=" c̲at f̲ormat s̲hape b v ← n̲umbers ⎕N̲GET "ext:audio/chunk" (f̲loor n̲umbers ⎕N̲GET "ext:audio/chunk?shape") r̲eshape v }
ᶠᶠⁱb̲ind< expands to
ˡp̲lay! ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/play?float=" c̲at f̲ormat s̲hape a f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/play" }
ᶠᶠⁱb̲ind< expands to
ˡp̲ause! ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/pause?float=" c̲at f̲ormat s̲hape a f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/pause" }
ᶠᶠⁱb̲ind< expands to
ˡs̲eek! ← { a b → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/seek?float=" c̲at f̲ormat s̲hape a pb ← (f̲ormat r̲avel f̲loat b) ⎕N̲PUT "ext:audio/seek?float=" c̲at f̲ormat s̲hape b f̲irst n̲umbers ⎕N̲GET "ext:audio/seek" }
ᶠᶠⁱb̲ind< expands to
ˡp̲osition ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/position?float=" c̲at f̲ormat s̲hape a f̲irst n̲umbers ⎕N̲GET "ext:audio/position" }
ᶠᶠⁱb̲ind< expands to
ˡw̲indow ← { a b → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/window?float=" c̲at f̲ormat s̲hape a pb ← (f̲ormat r̲avel f̲loat b) ⎕N̲PUT "ext:audio/window?float=" c̲at f̲ormat s̲hape b v ← n̲umbers ⎕N̲GET "ext:audio/window" (f̲loor n̲umbers ⎕N̲GET "ext:audio/window?shape") r̲eshape v }
ᶠᶠⁱb̲ind< expands to
ˡs̲tate ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/state?float=" c̲at f̲ormat s̲hape a f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/state" }
ᶠᶠⁱb̲ind< expands to
ˡc̲lose! ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/close?float=" c̲at f̲ormat s̲hape a f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/close" }
ᶠᶠⁱb̲ind< expands to
ˡo̲utput ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/output?float=" c̲at f̲ormat s̲hape a f̲loor f̲irst n̲umbers ⎕N̲GET "ext:audio/output" }
ᶠᶠⁱb̲ind< expands to
ˡq̲ueue! ← { a b → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/queue?float=" c̲at f̲ormat s̲hape a pb ← (f̲ormat r̲avel f̲loat b) ⎕N̲PUT "ext:audio/queue?float=" c̲at f̲ormat s̲hape b f̲irst n̲umbers ⎕N̲GET "ext:audio/queue" }
ᶠᶠⁱb̲ind< expands to
ˡw̲ait! ← { a b → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/wait?float=" c̲at f̲ormat s̲hape a pb ← (f̲ormat r̲avel f̲loat b) ⎕N̲PUT "ext:audio/wait?float=" c̲at f̲ormat s̲hape b f̲irst n̲umbers ⎕N̲GET "ext:audio/wait" }
ᶠᶠⁱb̲ind< expands to
ˡp̲layed ← { a → pa ← (f̲ormat r̲avel f̲loat a) ⎕N̲PUT "ext:audio/played?float=" c̲at f̲ormat s̲hape a f̲irst n̲umbers ⎕N̲GET "ext:audio/played" }