summaryrefslogtreecommitdiff
path: root/project/templates/soundbinds.xhtml
blob: 4f0ff74e683d4b0b74f44e4746a0ab577069448f (plain)
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

{%- extends "base_plain.xhtml" -%}



{%- block title -%}Ada Bindings for Libao, Libsndfile, PortAudio{%- endblock -%}



{%- block footer -%}{{ plain_footer ("soundbinds.xhtml") }}{%- endblock -%}



{%- block content %}
<h4>Ada Bindings for Libao, Libsndfile, PortAudio</h4>

<p>Git repositories:
<a href="/cgi-bin/cgit.cgi/aao">aao</a>,
<a href="/cgi-bin/cgit.cgi/asndfile">asndfile</a>,
<a href="/cgi-bin/cgit.cgi/portadao">portadao</a></p>

<h5>29/7/2023</h5>

<p>Why am I making a single article about language bindings for three different libraries?
A few reasons. These three libraries are all quite small, they all cover similar and related
functionality, and all the bindings were written quickly one after the other. But ultimately I
just don't want to clutter the index up.</p>

<p>The three libraries in question:</p>
<ul>
  <li><i><a href="https://xiph.org/ao/" class="external">Libao</a>:</i> An extremely minimalist C
  library for cross platform audio playback. It does the job, but the lack of options for buffer
  data types and the lack of an asynchronous interface may make it not ideal for some uses.</li>
  <li><i><a href="https://libsndfile.github.io/libsndfile/" class="external">Libsndfile</a>:</i> A
  cross platform C library for reading and writing files containing sampled sound.</li>
  <li><i><a href="http://portaudio.com/" class="external">PortAudio</a>:</i> A slightly more
  elaborate C library for cross platform audio playback. Has the variety of buffer data types and
  the asynchronous callback interface that libao lacks.</li>
</ul>

<p>It is commonly thought that it is easy to bind a C library to another language. This is not the
case. Even for the thinnest of thin bindings and even when the other language is trying to make it
easy, there are problems. Enumerations, preprocessor macros, and callbacks are all awkward and they
are all involved here. Also, these are all thick bindings so things are even more fun. Nonetheless
it is all done. With the sole noteworthy exception of the RIFF chunk API in libsndfile, but we won't
talk about that.</p>

<p>Error codes have been converted to exceptions, initialize/shutdown functions have been rendered
automatic, manual deallocations have been made obsolete, void pointers have been wrapped up,
callbacks have been made available, and dot notation for invoking subprograms has been used
extensively. Oh, and the rather odd command API for libsndfile has been tamed. Mostly. The array
types for all the sound samples have also been defined such that conversions between the types used
in each binding should be as painless as possible, without sacrificing the strong typing Ada is
known for.</p>

<p>An excerpt of PortAudio code in C taken from an example program:</p>
<div class="precontain">
<code>
err = Pa_Initialize();
if( err != paNoError ) goto error;

err = Pa_OpenDefaultStream( &amp;stream,
                            0,
                            2,
                            paFloat32,
                            SAMPLE_RATE,
                            256,
                            patestCallback,
                            &amp;data );
if( err != paNoError ) goto error;

err = Pa_StartStream( stream );
if( err != paNoError ) goto error;

Pa_Sleep(NUM_SECONDS*1000);

err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
</code>
</div>

<p>And the corresponding code snippet in Ada:</p>
<div class="precontain">
<code>
Saw_Stream.Open_Default
   (Input_Channels  => 0,
    Output_Channels => 2,
    Format          => Portaudio.Streams.Float_32_Format,
    Sample_Rate     => 44100.0,
    Buffer_Frames   => 256,
    Callback        => Saw_Callback'Unrestricted_Access);

Saw_Stream.Start;

delay 4.0;

Saw_Stream.Stop;
Saw_Stream.Close;
</code>
</div>

<p>More detailed and complete examples can be found in each of the binding repositories.
Alternatively, the documentation for each library can be consulted. Aside from doing away with
C-isms, the function names and behaviours have been more or less imported wholesale so the
information should mostly carry over.</p>

<p>I'll admit, the only reason why I ended up creating the binding for libao is because I came
across that library first and it really is that minimalist. But I have specific purposes in mind
for the other two.</p>
{% endblock -%}