rev: 21c5e6d2f665d0e8b4ff917a51b664c895dab2ed tukan/tukan/audio.sc -rw-r--r-- 2.8 KiB View raw Log this file
21c5e6d2f665 — Leonard Ritter * renamed project from Liminal to Tukan 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#import-from (require "SDL2")
    \ SDL_AudioSpec SDL_AudioDeviceID SDL_OpenAudioDevice SDL_GetError
    \ SDL_PauseAudioDevice SDL_CloseAudioDevice AUDIO_F32 SDL_AUDIO_ALLOW_FORMAT_CHANGE
    \ SDL_QueueAudio SDL_GetQueuedAudioSize SDL_Delay
using import .sdl

let AUDIO_F32LSB = 0x8120 #< 32-bit floating point samples
let AUDIO_F32MSB = 0x9120 #< As above, but big-endian byte order
let AUDIO_F32 = AUDIO_F32LSB

global device = (SDL_AudioDeviceID 0)

global samplerate = 0
global buffersize = 0
global sampletime = 0.0

fn play (enable)
    "void <- (bool)"
    SDL_PauseAudioDevice device (? enable 0 1)

fn init ()
    "void <- ()"
    var want =
        SDL_AudioSpec
            freq = 44100
            format = AUDIO_F32
            channels = 2
            samples = 4096
    var have = (SDL_AudioSpec)

    #memset want 0 (sizeof SDL_AudioSpec)

    device =
        SDL_OpenAudioDevice null 0 want have SDL_AUDIO_ALLOW_FORMAT_CHANGE
    if (device == 0)
        print "Failed to open audio: " (SDL_GetError)
    else
        if (have.format != want.format)
            print "No Float32 audio format available"
        samplerate = have.freq
        buffersize = have.samples
        sampletime = 1.0 / (f32 samplerate)
    return;

fn queue (data samplecount)
    "void <- (&float uint)"
    SDL_QueueAudio device (bitcast data (pointer void)) (samplecount * 2 * (sizeof f32))

fn queued-bytes ()
    "uint <- ()"
    SDL_GetQueuedAudioSize device

fn queued ()
    "uint <- ()"
    (queued-bytes) / (2:u32 * (sizeof f32))

fn queue-empty? ()
    "bool <- ()"
    (queued) == 0

fn play-until-empty ()
    "void <- ()"
    play true
    while (not (queue-empty?))
        SDL_Delay 100

fn exit ()
    "void <- ()"
    SDL_CloseAudioDevice device

fn sampletime~ ()
    Generator
        label (fret fdone time)
            fret
                time + 1:u32
                (f64 time) / (f64 samplerate)
        unconst 0:u32

if main-module?
    SDL_Init SDL_INIT_AUDIO
    init;
    print "samplerate: " samplerate
    print "buffersize: " buffersize
    let SAMPLESIZE = 44100
    var time = 0:u32
    fn queue_audio ()
        var samples @ (2 * SAMPLESIZE) : f32
        for i in (range 0 SAMPLESIZE)
            let t = (time / (u32 samplerate))
            let s = (sin (440.0 * pi * 2.0 * t))
            samples @ (i * 2) = s
            samples @ (i * 2 + 1) = s
            time = time + 1:u32
        queue samples SAMPLESIZE

    queue_audio;
    play true
    for i in (range 32)
        queue_audio;
        SDL_Delay 500
    play-until-empty;
    exit;
    SDL_Quit;

do
    let
        init
        exit
        play
        queue
        queued
        queued-bytes
        queue-empty?
        play-until-empty
        samplerate
        sampletime
        buffersize
        sampletime~

    locals;