1#include <stdio.h>
2
3#ifndef SDNC_H
4#define SDNC_H
5
6#define MAX_INPUTS 16
7#define MAX_OUTPUTS 16
8
9#define MAX_SNDC_PATH 16
10#define MAX_PATH_LENGTH 128
11#define MAX_MOD_NAME_LEN 16
12#define MAX_ERR_LEN 256
13#define MAX_IMPORT_DEPTH 32
14
15#define MAX_ENTRIES 128
16#define MAX_FIELDS 128
17#define MAX_IMPORT 128
18#define MAX_EXPORT 128
19
20
21/*** SNDC_PATH management ***/
22
23extern char sndcPath[MAX_SNDC_PATH][MAX_PATH_LENGTH];
24
25int path_init();
26
27/****************/
28
29
30/*** Parser ***/
31
32struct Ref {
33 char* name;
34 char* field;
35};
36
37struct Field {
38 char* name;
39 enum FieldType {
40 FIELD_FLOAT,
41 FIELD_STRING,
42 FIELD_REF
43 } type;
44 union FieldData {
45 float f;
46 char* str;
47 struct Ref ref;
48 struct Entry* node;
49 } data;
50};
51
52struct Entry {
53 char* name;
54 char* type;
55 struct Field fields[MAX_FIELDS];
56 size_t numFields;
57};
58
59struct Export {
60 char* symbol;
61 struct Ref ref;
62 enum ExportType {
63 EXP_INPUT,
64 EXP_OUTPUT
65 } type;
66};
67
68struct Import {
69 char* fileName;
70 char* importName;
71};
72
73struct SNDCFile {
74 struct Import imports[MAX_IMPORT];
75 struct Export exports[MAX_EXPORT];
76 struct Entry entries[MAX_ENTRIES];
77 size_t numEntries, numImport, numExport;
78
79 char* path;
80};
81
82char* str_cpy(const char* s);
83int parse_sndc(struct SNDCFile* file, const char* name);
84int parse_sndc_s(struct SNDCFile* file, const char* buf);
85int parse_sndc_f(struct SNDCFile* file, FILE* in);
86void free_sndc(struct SNDCFile* file);
87
88/****************/
89
90
91/*** Data and Buffer ***/
92
93enum InterpType {
94 INTERP_STEP,
95 INTERP_LINEAR,
96 INTERP_SINE
97};
98
99struct Buffer {
100 float* data;
101 size_t size;
102 size_t samplingRate;
103 enum InterpType interp;
104 char shared; /* data won't be freed if this is set to 1 */
105};
106
107void buffer_free(struct Buffer* buf);
108
109struct Data {
110 enum DataType {
111 DATA_BUFFER = 1 << 0,
112 DATA_FLOAT = 1 << 1,
113 DATA_STRING = 1 << 2
114 } type;
115 union DataContent {
116 struct Buffer buf;
117 float f;
118 char* str;
119 } content;
120 char ready;
121};
122
123void data_init(struct Data* data);
124void data_free(struct Data* data);
125struct Buffer* data_make_buf(struct Data* data,
126 size_t numSamples,
127 size_t samplingRate,
128 enum InterpType interp);
129void data_dump(FILE* fd, const struct Data* data);
130
131
132/****************/
133
134
135/*** Node ***/
136
137struct Module;
138
139struct Node {
140 /* NB: nodes are responsible for checking the validity of their inputs and
141 * setting the type / initializing their outputs
142 */
143 struct Data* inputs[MAX_INPUTS];
144 struct Data* outputs[MAX_OUTPUTS];
145
146 int (*setup)(struct Node*);
147 int (*process)(struct Node*);
148 int (*teardown)(struct Node* node);
149
150 const char* name;
151 const char* path;
152 char isSetup;
153 const struct Module* module;
154 struct Stack* stack; /* nodes must be part of a Stack */
155 void* data;
156
157 char errStr[MAX_ERR_LEN];
158};
159
160void node_init(struct Node* node);
161void node_free(struct Node* node);
162void node_flush_output(struct Node* node);
163int node_check_inputs(struct Node* node);
164struct Data* node_get_input(struct Node* node, const char* name);
165struct Data* node_get_output(struct Node* node, const char* name);
166void node_dump(FILE* fd, const struct Node* node);
167
168#define NODE_ERR(node, ...) \
169 snprintf(node->errStr, MAX_ERR_LEN, __VA_ARGS__)
170
171/****************/
172
173
174/*** Module management ***/
175
176struct DataDesc {
177 const char* name;
178 int type;
179 enum DataReq {
180 OPTIONAL = 0,
181 REQUIRED
182 } req;
183 const char* description;
184
185 float min;
186 float max;
187 const char* values;
188};
189
190struct Module {
191 const char* name;
192 const char* category;
193 const char* desc;
194 struct DataDesc inputs[MAX_INPUTS];
195 struct DataDesc outputs[MAX_OUTPUTS];
196
197 int (*setup)(struct Node* node);
198 int (*process)(struct Node* node);
199 int (*teardown)(struct Node* node);
200
201 struct SNDCFile* file;
202};
203
204extern const struct Module* modules[];
205extern const size_t numModules;
206
207const struct Module* module_find(const char* name);
208int module_get_input_slot(const struct Module* module, const char* name);
209int module_get_output_slot(const struct Module* module, const char* name);
210int module_import(struct Module* module, const char* name, const char* file);
211void module_free_import(struct Module* module);
212
213/****************/
214
215
216/*** Stack management ***/
217struct Stack {
218 struct Module** imports;
219 struct Data** data;
220 struct Node** nodes;
221 size_t numNodes, numData, numImports;
222 int importDepth;
223
224 char* path; /* NULL if Stack is not loaded from a file */
225 char verbose;
226
227 int failedNode;
228 char stackErr[MAX_ERR_LEN];
229};
230
231void stack_init(struct Stack* stack);
232void stack_free(struct Stack* stack);
233
234struct Node* stack_node_new(struct Stack* stack, const char* name);
235int stack_node_set_module(struct Stack* stack,
236 struct Node* node,
237 const struct Module* module);
238
239struct Data* stack_data_new(struct Stack* stack);
240struct Module* stack_import_new(struct Stack* stack);
241struct Node* stack_get_node(struct Stack* stack, const char* name);
242int stack_process(struct Stack* stack);
243int stack_load(struct Stack* stack, struct SNDCFile* file);
244int stack_setup(struct Stack* stack);
245void stack_reset(struct Stack* stack);
246const struct Module* stack_find_module(const struct Stack* stack,
247 const char* name);
248/* replaces every instance of "prev" with "new" in all nodes' input and output
249 * data slots
250 */
251void stack_update_data_ptr(struct Stack* stack,
252 struct Data* prev,
253 struct Data* new);
254void stack_dump(FILE* fd, const struct Stack* s);
255
256#define STACK_ERR(stack, ...) \
257 snprintf(stack->stackErr, MAX_ERR_LEN, __VA_ARGS__)
258
259/****************/
260
261
262/*** sndk file format ***/
263struct Note {
264 size_t beat;
265 size_t div;
266 int pitchID;
267
268 float freq;
269 float veloc;
270 float sustain;
271};
272
273int sndk_load(const char* filename,
274 struct Note** notes,
275 size_t* numNotes);
276int sndk_load_fixed(const char* filename,
277 struct Note* notes,
278 size_t* numNotes,
279 size_t size);
280int sndk_write(const char* filename,
281 const struct Note* notes,
282 size_t numNotes);
283float pitch_to_freq(int pitchID);
284#endif
285