OOP initial commit.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / sndfile.cpp
1 /************************************************************************
2
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 3 of
18 the License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
27
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
32
33
34 ************************************************************************
35 ************************************************************************/
36
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <limits.h>
42 #include <math.h>
43 #include <errno.h>
44 #include <time.h>
45 #include <sndfile.h>
46 #include <vector>
47 #include <stack>
48 #include <string>
49 #include <map>
50 #include <iostream>
51
52 #include "gui/GUI.h"
53 #include "audio/dsp.h"
54 #include "misc.h"
55
56 /******************************************************************************
57 *******************************************************************************
58
59 VECTOR INTRINSICS
60
61 *******************************************************************************
62 *******************************************************************************/
63
64 <<includeIntrinsic>>
65
66 /******************************************************************************
67 *******************************************************************************
68
69 USER INTERFACE
70
71 *******************************************************************************
72 *******************************************************************************/
73
74 struct param {
75 float* fZone; float fMin; float fMax;
76 param(float* z, float init, float a, float b) : fZone(z), fMin(a), fMax(b) { *z = init; }
77 };
78
79 class CMDUI : public UI
80 {
81 int fArgc;
82 char** fArgv;
83 vector<char*> fFiles;
84 stack<string> fPrefix;
85 map<string, param> fKeyParam;
86
87 void openAnyBox(const char* label)
88 {
89 string prefix;
90
91 if (label && label[0]) {
92 prefix = fPrefix.top() + "-" + label;
93 } else {
94 prefix = fPrefix.top();
95 }
96 fPrefix.push(prefix);
97 }
98
99 string simplify(const string& src)
100 {
101 int i=0;
102 int level=0;
103 string dst;
104
105 while (src[i] ) {
106
107 switch (level) {
108
109 case 0 :
110 case 1 :
111 case 2 :
112 // Skip the begin of the label "--foo-"
113 // until 3 '-' have been read
114 if (src[i]=='-') { level++; }
115 break;
116
117 case 3 :
118 // copy the content, but skip non alphnum
119 // and content in parenthesis
120 switch (src[i]) {
121 case '(' :
122 case '[' :
123 level++;
124 break;
125
126 case '-' :
127 dst += '-';
128 break;
129
130 default :
131 if (isalnum(src[i])) {
132 dst+= tolower(src[i]);
133 }
134
135 }
136 break;
137
138 default :
139 // here we are inside parenthesis and
140 // we skip the content until we are back to
141 // level 3
142 switch (src[i]) {
143
144 case '(' :
145 case '[' :
146 level++;
147 break;
148
149 case ')' :
150 case ']' :
151 level--;
152 break;
153
154 default :
155 break;
156 }
157
158 }
159 i++;
160 }
161 return dst;
162 }
163
164
165 public:
166
167 CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("-"); }
168 virtual ~CMDUI() {}
169
170
171 void addOption(const char* label, float* zone, float init, float min, float max)
172 {
173 string fullname = "-" + simplify(fPrefix.top() + "-" + label);
174 fKeyParam.insert(make_pair(fullname, param(zone, init, min, max)));
175 }
176
177
178 virtual void addButton(const char* label, float* zone)
179 {
180 addOption(label,zone,0,0,1);
181 }
182
183 virtual void addToggleButton(const char* label, float* zone)
184 {
185 addOption(label,zone,0,0,1);
186 }
187
188 virtual void addCheckButton(const char* label, float* zone)
189 {
190 addOption(label,zone,0,0,1);
191 }
192
193 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
194 {
195 addOption(label,zone,init,min,max);
196 }
197
198 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
199 {
200 addOption(label,zone,init,min,max);
201 }
202
203 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
204 {
205 addOption(label,zone,init,min,max);
206 }
207
208 // -- passive widgets
209
210 virtual void addNumDisplay(const char* label, float* zone, int precision) {}
211 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) {}
212 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
213 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
214
215 virtual void openFrameBox(const char* label) { openAnyBox(label); }
216 virtual void openTabBox(const char* label) { openAnyBox(label); }
217 virtual void openHorizontalBox(const char* label) { openAnyBox(label); }
218 virtual void openVerticalBox(const char* label) { openAnyBox(label); }
219
220 virtual void closeBox() { fPrefix.pop(); }
221
222 virtual void show() {}
223 virtual void run() {}
224
225 void printhelp()
226 {
227 map<string, param>::iterator i;
228 cout << fArgc << "\n";
229 cout << fArgv[0] << " option list : ";
230 for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) {
231 cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] ";
232 }
233 cout << " infile outfile\n";
234 }
235
236 void process_command()
237 {
238 map<string, param>::iterator p;
239 for (int i = 1; i < fArgc; i++) {
240 if (fArgv[i][0] == '-') {
241 if ( (strcmp(fArgv[i], "-help") == 0)
242 || (strcmp(fArgv[i], "-h") == 0)
243 || (strcmp(fArgv[i], "--help") == 0) ) {
244 printhelp();
245 exit(1);
246 }
247 p = fKeyParam.find(fArgv[i]);
248 if (p == fKeyParam.end()) {
249 cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
250 printhelp();
251 exit(1);
252 }
253 char* end;
254 *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
255 i++;
256 } else {
257 fFiles.push_back(fArgv[i]);
258 }
259 }
260 }
261
262 int files() { return fFiles.size(); }
263 char* file (int n) { return fFiles[n]; }
264
265 char* input_file () { cout << "input file " << fFiles[0]; return fFiles[0]; }
266 char* output_file() { cout << "output file " << fFiles[1]; return fFiles[1]; }
267
268 void process_init()
269 {
270 map<string, param>::iterator p;
271 for (int i = 1; i < fArgc; i++) {
272 if (fArgv[i][0] == '-') {
273 p = fKeyParam.find(fArgv[i]);
274 if (p == fKeyParam.end()) {
275 cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
276 exit(1);
277 }
278 char* end;
279 *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
280 i++;
281 }
282 }
283 }
284 };
285
286 /********************END ARCHITECTURE SECTION (part 1/2)****************/
287
288 /**************************BEGIN USER SECTION **************************/
289
290 <<includeclass>>
291
292 /***************************END USER SECTION ***************************/
293
294 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
295
296 mydsp DSP;
297
298
299 class Separator
300 {
301 int fNumFrames;
302 int fNumInputs;
303 int fNumOutputs;
304
305 float* fInput;
306 float* fOutputs[256];
307
308 public:
309
310 Separator(int numFrames, int numInputs, int numOutputs)
311 {
312 fNumFrames = numFrames;
313 fNumInputs = numInputs;
314 fNumOutputs = max(numInputs, numOutputs);
315
316 // allocate interleaved input channel
317 fInput = (float*) calloc(fNumFrames*fNumInputs, sizeof(float));
318
319 // allocate separate output channels
320 for (int i = 0; i < fNumOutputs; i++) {
321 fOutputs[i] = (float*) calloc (fNumFrames, sizeof(float));
322 }
323 }
324
325 ~Separator()
326 {
327 // free interleaved input channel
328 free(fInput);
329
330 // free separate output channels
331 for (int i = 0; i < fNumOutputs; i++) {
332 free(fOutputs[i]);
333 }
334 }
335
336 float* input() { return fInput; }
337
338 float** outputs() { return fOutputs; }
339
340 void separate()
341 {
342 for (int s = 0; s < fNumFrames; s++) {
343 for (int c = 0; c < fNumInputs; c++) {
344 fOutputs[c][s] = fInput[c + s*fNumInputs];
345 }
346 }
347 }
348 };
349
350 class Interleaver
351 {
352 int fNumFrames;
353 int fNumInputs;
354 int fNumOutputs;
355
356 float* fInputs[256];
357 float* fOutput;
358
359 public:
360
361 Interleaver(int numFrames, int numInputs, int numOutputs)
362 {
363 fNumFrames = numFrames;
364 fNumInputs = max(numInputs, numOutputs);
365 fNumOutputs = numOutputs;
366
367 // allocate separate input channels
368 for (int i = 0; i < fNumInputs; i++) {
369 fInputs[i] = (float*) calloc (fNumFrames, sizeof(float));
370 }
371
372 // allocate interleaved output channel
373 fOutput = (float*) calloc(fNumFrames*fNumOutputs, sizeof(float));
374
375 }
376
377 ~Interleaver()
378 {
379 // free separate input channels
380 for (int i = 0; i < fNumInputs; i++) {
381 free(fInputs[i]);
382 }
383
384 // free interleaved output channel
385 free(fOutput);
386 }
387
388 float** inputs() { return fInputs; }
389
390 float* output() { return fOutput; }
391
392 void interleave()
393 {
394 for (int s = 0; s < fNumFrames; s++) {
395 for (int c = 0; c < fNumOutputs; c++) {
396 fOutput[c + s*fNumOutputs] = fInputs[c][s];
397 }
398 }
399 }
400 };
401
402 #define kFrames 512
403
404 int main(int argc, char *argv[] )
405 {
406 SNDFILE* in_sf;
407 SNDFILE* out_sf;
408 SF_INFO in_info;
409 SF_INFO out_info;
410
411 CMDUI* interface = new CMDUI(argc, argv);
412 DSP.buildUserInterface(interface);
413 interface->process_command();
414
415 // open input file
416 in_info.format = 0;
417 in_sf = sf_open (interface->input_file(), SFM_READ, &in_info);
418 if (in_sf == NULL) { sf_perror(in_sf); exit(0); }
419
420 // open output file
421 out_info = in_info;
422 out_info.format = in_info.format;
423 out_info.channels = DSP.getNumOutputs();
424 out_sf = sf_open(interface->output_file(), SFM_WRITE, &out_info);
425 if (out_sf == NULL) { sf_perror(out_sf); exit(0); }
426
427
428 // create separator and interleaver
429 Separator sep (kFrames, in_info.channels, DSP.getNumInputs());
430 Interleaver ilv (kFrames, DSP.getNumOutputs(), DSP.getNumOutputs());
431
432 // init signal processor
433 DSP.init(in_info.samplerate);
434 //DSP.buildUserInterface(interface);
435 interface->process_init();
436
437 // process all samples
438 int nbf;
439 do {
440 nbf = sf_readf_float(in_sf, sep.input(), kFrames);
441 sep.separate();
442 DSP.compute(nbf, sep.outputs(), ilv.inputs());
443 ilv.interleave();
444 sf_writef_float(out_sf, ilv.output(), nbf);
445 //sf_write_raw(out_sf, ilv.output(), nbf);
446 } while (nbf == kFrames);
447
448 // close the input and output files
449 sf_close(in_sf);
450 sf_close(out_sf);
451 }
452
453 /********************END ARCHITECTURE SECTION (part 2/2)****************/
454
455