2a8a82966162a52e0b281b806c6058392556cbcd
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / architecture / matlabplot.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST Architecture File
4 Copyright (C) 2007-2011 Julius O. Smith III
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20 ************************************************************************
21 ************************************************************************/
22
23 /* matlabplot.cpp = simple variation of plot.cpp */
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <limits.h>
29 #include <math.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <ctype.h>
33
34 #include <vector>
35 #include <stack>
36 #include <string>
37 #include <map>
38 #include <list>
39 #include <iostream>
40
41 // g++ -O3 -lm -lsndfile myfx.cpp
42
43 using namespace std;
44
45 struct Meta : map<const char*, const char*>
46 {
47 void declare (const char* key, const char* value) { (*this)[key]=value; }
48 };
49
50
51 //-------------------------------------------------------------------
52 // Generic min and max using c++ inline
53 //-------------------------------------------------------------------
54
55 inline int max (unsigned int a, unsigned int b) { return (a>b) ? a : b; }
56 inline int max (int a, int b) { return (a>b) ? a : b; }
57
58 inline long max (long a, long b) { return (a>b) ? a : b; }
59 inline long max (int a, long b) { return (a>b) ? a : b; }
60 inline long max (long a, int b) { return (a>b) ? a : b; }
61
62 inline float max (float a, float b) { return (a>b) ? a : b; }
63 inline float max (int a, float b) { return (a>b) ? a : b; }
64 inline float max (float a, int b) { return (a>b) ? a : b; }
65 inline float max (long a, float b) { return (a>b) ? a : b; }
66 inline float max (float a, long b) { return (a>b) ? a : b; }
67
68 inline double max (double a, double b) { return (a>b) ? a : b; }
69 inline double max (int a, double b) { return (a>b) ? a : b; }
70 inline double max (double a, int b) { return (a>b) ? a : b; }
71 inline double max (long a, double b) { return (a>b) ? a : b; }
72 inline double max (double a, long b) { return (a>b) ? a : b; }
73 inline double max (float a, double b) { return (a>b) ? a : b; }
74 inline double max (double a, float b) { return (a>b) ? a : b; }
75
76
77 inline int min (int a, int b) { return (a<b) ? a : b; }
78
79 inline long min (long a, long b) { return (a<b) ? a : b; }
80 inline long min (int a, long b) { return (a<b) ? a : b; }
81 inline long min (long a, int b) { return (a<b) ? a : b; }
82
83 inline float min (float a, float b) { return (a<b) ? a : b; }
84 inline float min (int a, float b) { return (a<b) ? a : b; }
85 inline float min (float a, int b) { return (a<b) ? a : b; }
86 inline float min (long a, float b) { return (a<b) ? a : b; }
87 inline float min (float a, long b) { return (a<b) ? a : b; }
88
89 inline double min (double a, double b) { return (a<b) ? a : b; }
90 inline double min (int a, double b) { return (a<b) ? a : b; }
91 inline double min (double a, int b) { return (a<b) ? a : b; }
92 inline double min (long a, double b) { return (a<b) ? a : b; }
93 inline double min (double a, long b) { return (a<b) ? a : b; }
94 inline double min (float a, double b) { return (a<b) ? a : b; }
95 inline double min (double a, float b) { return (a<b) ? a : b; }
96
97
98
99 inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
100
101 template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
102
103
104 /******************************************************************************
105 *******************************************************************************
106
107 VECTOR INTRINSICS
108
109 *******************************************************************************
110 *******************************************************************************/
111
112 <<includeIntrinsic>>
113
114
115
116
117 /******************************************************************************
118 *******************************************************************************
119
120 USER INTERFACE
121
122 *******************************************************************************
123 *******************************************************************************/
124
125 class UI
126 {
127 bool fStopped;
128 public:
129
130 UI() : fStopped(false) {}
131 virtual ~UI() {}
132
133 // -- active widgets
134
135 virtual void addButton(const char* label, float* zone) = 0;
136 virtual void addToggleButton(const char* label, float* zone) = 0;
137 virtual void addCheckButton(const char* label, float* zone) = 0;
138 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
139 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
140 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
141
142 // -- passive widgets
143
144 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
145 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
146 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
147 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
148
149 // -- frames and labels
150
151 virtual void openFrameBox(const char* label) = 0;
152 virtual void openTabBox(const char* label) = 0;
153 virtual void openHorizontalBox(const char* label) = 0;
154 virtual void openVerticalBox(const char* label) = 0;
155 virtual void closeBox() = 0;
156
157 virtual void show() = 0;
158 virtual void run() = 0;
159
160 void stop() { fStopped = true; }
161 bool stopped() { return fStopped; }
162
163 virtual void declare(float* zone, const char* key, const char* value) {}
164 };
165
166 struct param {
167 float* fZone;
168 float fMin;
169 float fMax;
170 param(float* z, float init, float a, float b) : fZone(z), fMin(a), fMax(b) { *z = init; }
171 };
172
173
174 class CMDUI : public UI
175 {
176 int fArgc;
177 char** fArgv;
178 vector<char*> fFiles;
179 stack<string> fPrefix;
180 map<string, param> fKeyParam;
181
182 void openAnyBox(const char* label)
183 {
184 string prefix;
185
186 if (label && label[0]) {
187 prefix = fPrefix.top() + "-" + label;
188 } else {
189 prefix = fPrefix.top();
190 }
191 fPrefix.push(prefix);
192 }
193
194 string simplify(const string& src)
195 {
196 int i=0;
197 int level=0;
198 string dst;
199
200 while (src[i] ) {
201
202 switch (level) {
203
204 case 0 :
205 case 1 :
206 case 2 :
207 // Skip the begin of the label "--foo-"
208 // until 3 '-' have been read
209 if (src[i]=='-') { level++; }
210 break;
211
212 case 3 :
213 // copy the content, but skip non alphnum
214 // and content in parenthesis
215 switch (src[i]) {
216 case '(' :
217 case '[' :
218 level++;
219 break;
220
221 case '-' :
222 dst += '-';
223 break;
224
225 default :
226 if (isalnum(src[i])) {
227 dst+= tolower(src[i]);
228 }
229
230 }
231 break;
232
233 default :
234 // here we are inside parenthesis and
235 // we skip the content until we are back to
236 // level 3
237 switch (src[i]) {
238
239 case '(' :
240 case '[' :
241 level++;
242 break;
243
244 case ')' :
245 case ']' :
246 level--;
247 break;
248
249 default :
250 break;
251 }
252
253 }
254 i++;
255 }
256 return dst;
257 }
258
259
260 public:
261
262 CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("-"); }
263 virtual ~CMDUI() {}
264
265
266 void addOption(const char* label, float* zone, float init, float min, float max)
267 {
268 string fullname = "-" + simplify(fPrefix.top() + "-" + label);
269 fKeyParam.insert(make_pair(fullname, param(zone, init, min, max)));
270 }
271
272
273 virtual void addButton(const char* label, float* zone)
274 {
275 addOption(label,zone,0,0,1);
276 }
277
278 virtual void addToggleButton(const char* label, float* zone)
279 {
280 addOption(label,zone,0,0,1);
281 }
282
283 virtual void addCheckButton(const char* label, float* zone)
284 {
285 addOption(label,zone,0,0,1);
286 }
287
288 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
289 {
290 addOption(label,zone,init,min,max);
291 }
292
293 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
294 {
295 addOption(label,zone,init,min,max);
296 }
297
298 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
299 {
300 addOption(label,zone,init,min,max);
301 }
302
303 // -- passive widgets
304
305 virtual void addNumDisplay(const char* label, float* zone, int precision) {}
306 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {}
307 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
308 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
309
310 virtual void openFrameBox(const char* label) { openAnyBox(label); }
311 virtual void openTabBox(const char* label) { openAnyBox(label); }
312 virtual void openHorizontalBox(const char* label) { openAnyBox(label); }
313 virtual void openVerticalBox(const char* label) { openAnyBox(label); }
314
315 virtual void closeBox() { fPrefix.pop(); }
316
317 virtual void show() {}
318 virtual void run() {}
319
320 void printhelp()
321 {
322 map<string, param>::iterator i;
323 cout << fArgc << "\n";
324 cout << fArgv[0] << " option list : ";
325 for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) {
326 cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] ";
327 }
328 cout << " infile outfile\n";
329 }
330
331 void process_command()
332 {
333 map<string, param>::iterator p;
334 for (int i = 1; i < fArgc; i++) {
335 if (fArgv[i][0] == '-') {
336 if ( (strcmp(fArgv[i], "-help") == 0)
337 || (strcmp(fArgv[i], "-h") == 0)
338 || (strcmp(fArgv[i], "--help") == 0) ) {
339 printhelp();
340 exit(1);
341 }
342 p = fKeyParam.find(fArgv[i]);
343 if (p == fKeyParam.end()) {
344 cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
345 printhelp();
346 exit(1);
347 }
348 char* end;
349 *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
350 i++;
351 } else {
352 fFiles.push_back(fArgv[i]);
353 }
354 }
355 }
356
357 int files() { return fFiles.size(); }
358 char* file (int n) { return fFiles[n]; }
359
360 };
361
362 //----------------------------------------------------------------
363 // d�inition du processeur de signal
364 //----------------------------------------------------------------
365
366 class dsp {
367 protected:
368 int fSamplingFreq;
369 public:
370 dsp() {}
371 virtual ~dsp() {}
372
373 virtual int getNumInputs() = 0;
374 virtual int getNumOutputs() = 0;
375 virtual void buildUserInterface(UI* interface) = 0;
376 virtual void init(int samplingRate) = 0;
377 virtual void compute(int len, float** inputs, float** outputs) = 0;
378 virtual void conclude() {}
379 };
380
381
382 //----------------------------------------------------------------------------
383 // FAUST generated code
384 //----------------------------------------------------------------------------
385
386 <<includeclass>>
387
388
389 mydsp DSP;
390
391
392 class channels
393 {
394 int fNumFrames;
395 int fNumChannels;
396 float* fBuffers[256];
397
398 public:
399
400 channels(int nframes, int nchannels)
401 {
402 assert(nchannels < 256);
403
404 fNumFrames = nframes;
405 fNumChannels = nchannels;
406
407 // allocate audio channels
408 for (int i = 0; i < fNumChannels; i++) {
409 fBuffers[i] = (float*) calloc (fNumFrames, sizeof(float));
410 }
411 }
412
413 void zero()
414 {
415 // allocate audio channels
416 for (int i = 0; i < fNumChannels; i++) {
417 for (int f = 0; f < fNumFrames; f++) {
418 fBuffers[i][f] = 0.0;
419 }
420 }
421 }
422
423 void impulse()
424 {
425 // allocate audio channels
426 for (int i = 0; i < fNumChannels; i++) {
427 fBuffers[i][0] = 1.0;
428 for (int f = 1; f < fNumFrames; f++) {
429 fBuffers[i][f] = 0.0;
430 }
431 }
432 }
433
434 ~channels()
435 {
436 // free separate input channels
437 for (int i = 0; i < fNumChannels; i++) {
438 free(fBuffers[i]);
439 }
440 }
441
442 float** buffers() { return fBuffers; }
443 };
444
445
446
447 #define kFrames 512
448
449 int main(int argc, char *argv[] )
450 {
451 float fStartAtSample;
452 float fnbsamples;
453
454
455 CMDUI* interface = new CMDUI(argc, argv);
456 DSP.buildUserInterface(interface);
457
458 interface->addOption("-s", &fStartAtSample, 0, 0.0, 100000000.0);
459 interface->addOption("-n", &fnbsamples, 16, 0.0, 100000000.0);
460
461 // if (DSP.getNumInputs() > 0) {
462 // fprintf(stderr,
463 // "*** input signals not supported by architecture file matlab.cpp\n");
464 // exit(1);
465 // }
466
467 // init signal processor and the user interface values:
468 DSP.init(44100);
469
470 // modify the UI values according to the command-line options:
471 interface->process_command();
472
473 // prepare input channels (if any) with an impulse
474 int nins = DSP.getNumInputs();
475 channels inchan (kFrames, nins);
476 inchan.impulse(); // after each compute we will zero them
477
478 // prepare output channels
479 int nouts = DSP.getNumOutputs();
480 channels outchan (kFrames, nouts);
481
482 // print usage info:
483 printf("%% Usage: octave --persist thisfile.m\n\n");
484
485 // print matlab-compatible matrix syntax followed by a plot command:
486 printf("faustout = [ ...\n");
487
488
489 // skip <start> samples
490 int start = int(fStartAtSample);
491 while (start > kFrames) {
492 DSP.compute(kFrames, inchan.buffers(), outchan.buffers());
493 inchan.zero();
494 start -= kFrames;
495 }
496 if (start > 0) {
497 DSP.compute(start, inchan.buffers(), outchan.buffers());
498 }
499 // end skip
500
501
502 int nbsamples = int(fnbsamples);
503 while (nbsamples > kFrames) {
504
505 DSP.compute(kFrames, inchan.buffers(), outchan.buffers());
506 inchan.zero();
507 for (int i = 0; i < kFrames; i++) {
508 for (int c = 0; c < nouts; c++) {
509 printf(" %g", outchan.buffers()[c][i]);
510 }
511 if (i < kFrames-1) {
512 printf("; ...\n");
513 } else {
514 printf("; ...\n%%---- Chunk Boundary ----\n");
515 }
516 }
517 nbsamples -= kFrames;
518 }
519
520 if (nbsamples) { // Write out partial-chunk buffer:
521
522 DSP.compute(nbsamples, inchan.buffers(), outchan.buffers());
523 inchan.zero();
524 for (int i = 0; i < nbsamples; i++) {
525 for (int c = 0; c < nouts; c++) {
526 printf(" %g", outchan.buffers()[c][i]);
527 }
528 printf("; ...\n");
529 }
530 }
531 printf("];\n\n");
532 printf("plot(faustout);\n");
533 printf("title('Plot generated by %s made using ''faust -a matlabplot.cpp ...''');\n",argv[0]);
534 printf("xlabel('Time (samples)');\n");
535 printf("ylabel('Amplitude');\n");
536 if (nouts>1) {
537 printf("legend(");
538 for (int c = 0; c < nouts; c++) {
539 printf("'channel %d'", c+1);
540 if (c<nouts-1) { printf(","); }
541 }
542 printf(");");
543 }
544 return 0;
545 }