-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLabSoundC.hpp
More file actions
252 lines (192 loc) · 6.73 KB
/
LabSoundC.hpp
File metadata and controls
252 lines (192 loc) · 6.73 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*
LabSound C
Copyright 2022 Nick Porcino & the LabSound Authors
LabSound C provides a uniform functional interface to the
LabSound library. LabSound itself is written in C++, and has
a highly polymorphic API meant to emulate close the WebAudio
interfaces. That's very handy for transliterating WebAudio code,
but less friendly for native prograaming. This API exposes
all of the functionality of LabSound, but reduces the interface
surface to a few dozen function calls.
Under the hood it maintains a full database of LabSound objects
however in order to avoid the need to expose object life cycles
outside of the implementation, all the objects are tracked using
FLECS, and managed transparently to the user. Since the
LabSound C interface itself is pass by object, all of the complexity
of object ownership is bypassed since a user of the interface
will never have a copy of anything owned by LabSound.
The only exception is the API object itself, the user is responsible
for its lifetime, and the interface is only usable after the
api object is created, and before it is destroyed.
The WebAudio interface involves a certain amount of set up,
occasionally value setting, and tear down. Other than that, it's
normal to simply let a graph run. As such, the fact that the
LabSound C interface goes through a FLECS hash to find the
backing objects for API application is not particularly of
concern, as it won't be a run time overhead, only a set up
overhead.
*/
// LSNAMESPACE is allows the introduction of a namespace to the symbols so that
// multiple libraries can include the labsound C library without symbol
// conflicts. The default is ls_1_0_ to indicate the 1.0 version of LabSound.
//
#ifndef LSNAMESPACE
//#define LSNAMESPACE ls_1_0_
#endif
// The LSCONCAT macro is used to apply a namespace to the symbols in the public
// interface.
#define LSCONCAT1(a, b) a ## b
#define LSCONCAT(a, b) LSCONCAT1(a, b)
// LSAPI may be overridden externally to control symbol visibility.
#ifndef LSAPI
#define LSAPI
#endif
#ifdef __cplusplus
#define LSEXTERNC extern "C" LSAPI
#else
#define LSEXTERNC extern LSAPI
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef LSNAMESPACE
// forward declare the LabSound C types in a namespace
#define ls_StringSlice LSCONCAT(LSNAMESPACE, StringSlice)
#define ls_NameArray LSCONCAT(LSNAMESPACE, NameArray)
#define ls_Seconds LSCONCAT(LSNAMESPACE, Seconds)
#define ls_InputPin LSCONCAT(LSNAMESPACE, InputPin)
#define ls_OutputPin LSCONCAT(LSNAMESPACE, OutputPin)
#define ls_Node LSCONCAT(LSNAMESPACE, Node)
#define ls_Connection LSCONCAT(LSNAMESPACE, Connection)
#define ls_BusData LSCONCAT(LSNAMESPACE, BusData)
#define ls_PinKind LSCONCAT(LSNAMESPACE, PinKind)
#define ls_PinDataType LSCONCAT(LSNAMESPACE, PinDataType)
#endif
typedef struct {
const char* start;
const char* end;
} ls_StringSlice;
#define ls_cstr(s) ls_StringSlice { (s), strlen(s) }
typedef struct {
ls_StringSlice* names;
int count;
} ls_NameArray;
typedef struct {
float t;
} ls_Seconds;
typedef struct {
uint64_t id;
} ls_InputPin;
const ls_InputPin ls_InputPin_empty = { 0 };
typedef struct {
uint64_t id;
} ls_OutputPin;
const ls_OutputPin ls_OutputPin_empty = { 0 };
typedef struct {
uint64_t id;
} ls_Node;
const ls_Node ls_Node_empty = { 0 };
typedef struct {
uint64_t id;
} ls_Connection;
const ls_Connection ls_Connection_empty = { 0 };
typedef struct {
uint64_t id;
} ls_BusData;
const ls_BusData ls_BusData_empty = { 0 };
typedef enum {
ls_PinKindInvalid = 0,
ls_PinKindInput, ls_PinKindOutput, ls_PinKindParam, ls_PinKindSetting
} ls_PinKind;
typedef enum {
ls_Invalid = 0,
ls_String, ls_Path, ls_Bool, ls_Int, ls_Float, ls_Bus, ls_Enum
} ls_PinDataType;
#define ls_APIDetail LSCONCAT(LSNAMESPACE, APIDetail)
struct ls_APIDetail;
#define ls_API LSCONCAT(LSNAMESPACE, API)
LSAPI
struct ls_API {
struct ls_APIDetail* _detail;
// operations on nodes
//
ls_Seconds (*node_get_timing)(struct ls_API*,
ls_Node);
ls_Seconds (*node_get_self_timing)(struct ls_API*,
ls_Node);
void (*node_diagnose)(struct ls_API*,
ls_Node);
void (*node_start)(struct ls_API*,
ls_Node, ls_Seconds);
void (*node_schedule)(struct ls_API*,
ls_Node, ls_Seconds, int32_t);
const char* (*node_scheduled_state_name)(struct ls_API*,
ls_Node);
void (*node_stop)(struct ls_API*,
ls_Node, ls_Seconds);
// getting pins from nodes
//
ls_InputPin (*node_named_input)(struct ls_API*,
ls_Node, ls_StringSlice);
ls_InputPin (*node_indexed_input)(struct ls_API*,
ls_Node, int);
ls_OutputPin (*node_named_output)(struct ls_API*,
ls_Node, ls_StringSlice);
ls_OutputPin (*node_indexed_output)(struct ls_API*,
ls_Node, int);
ls_InputPin (*node_parameter)(struct ls_API*,
ls_Node, ls_StringSlice);
ls_InputPin (*node_setting)(struct ls_API*,
ls_Node, ls_StringSlice);
void (*node_set_on_ended)(struct ls_API*,
ls_Node, void(*)());
ls_PinKind (*pin_kind)(struct ls_API*,
ls_InputPin);
ls_PinDataType (*pin_data_type)(struct ls_API*,
ls_InputPin);
// managing nodes
//
const ls_NameArray* (*node_names)(struct ls_API*);
ls_Node (*node_create)(struct ls_API*,
ls_StringSlice name, ls_StringSlice type);
void (*node_delete)(struct ls_API*,
ls_Node);
void (*create_node_output)(struct ls_API*,
ls_Node, ls_StringSlice name, int channels);
// setting and getting pin values
//
void (*set_float)(struct ls_API*,
ls_InputPin, float);
void (*set_enum)(struct ls_API*,
ls_InputPin, uint32_t);
void (*set_int)(struct ls_API*,
ls_InputPin, uint32_t);
void (*set_bool)(struct ls_API*,
ls_InputPin, bool);
void (*set_bus)(struct ls_API*,
ls_InputPin, ls_BusData);
void (*set_bus_from_file)(struct ls_API*,
ls_InputPin, ls_StringSlice path);
void (*set_named_enum)(struct ls_API*,
ls_InputPin, ls_StringSlice enum_name);
// managing busses
ls_BusData (*bus_create_from_file)(struct ls_API*,
const char* path, bool mix_to_mono);
// graph management
//
ls_Node(*destination_node)(struct ls_API*);
ls_Connection (*connect)(struct ls_API*,
ls_InputPin input, ls_OutputPin output);
// after disconnection, ls_Connection will no longer be valid
void (*disconnect)(struct ls_API*,
ls_Connection);
};
typedef struct {
void* (*malloc)(size_t);
void (*free)(void*);
} ls_Alloc;
const ls_Alloc ls_default_alloc = { malloc, free };
struct ls_API* ls_create_api_1_0(ls_Alloc);
void ls_release_api_1_0(struct ls_API*);
void ls_idle(struct ls_API*);
typedef struct ls_API LabSoundAPI;