1 /************************************************************************
2  IMPORTANT NOTE : this file contains two clearly delimited sections :
3  the ARCHITECTURE section (in two parts) and the USER section. Each section
4  is governed by its own copyright and license. Please check individually
5  each section for license and copyright information.
6  *************************************************************************/
7 
8 /******************* BEGIN matlabplot.cpp ****************/
9 /************************************************************************
10  FAUST Architecture File
11  Copyright (C) 2003-2019 GRAME, Centre National de Creation Musicale
12  ---------------------------------------------------------------------
13  This Architecture section is free software; you can redistribute it
14  and/or modify it under the terms of the GNU General Public License
15  as published by the Free Software Foundation; either version 3 of
16  the License, or (at your option) any later version.
17 
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program; If not, see <http://www.gnu.org/licenses/>.
25 
26  EXCEPTION : As a special exception, you may create a larger work
27  that contains this FAUST architecture section and distribute
28  that work under terms of your choice, so long as this FAUST
29  architecture section is not modified.
30 
31  ************************************************************************
32  ************************************************************************/
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <math.h>
39 #include <errno.h>
40 #include <time.h>
41 #include <unistd.h>
42 #include <string>
43 #include <iostream>
44 #include <iomanip>
45 
46 #include "faust/gui/UI.h"
47 #include "faust/gui/console.h"
48 #include "faust/gui/meta.h"
49 #include "faust/audio/channels.h"
50 #include "faust/dsp/dsp-adapter.h"
51 #include "faust/dsp/dsp-combiner.h"
52 
53 using namespace std;
54 
55 /******************************************************************************
56  *******************************************************************************
57 
58  VECTOR INTRINSICS
59 
60  *******************************************************************************
61  *******************************************************************************/
62 
63 <<includeIntrinsic>>
64 
65 /********************END ARCHITECTURE SECTION (part 1/2)****************/
66 
67 /**************************BEGIN USER SECTION **************************/
68 
69 <<includeclass>>
70 
71 /***************************END USER SECTION ***************************/
72 
73 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
74 
75 dsp* DSP;
76 
77 std::list<GUI*> GUI::fGuiList;
78 ztimedmap GUI::gTimedZoneMap;
79 
80 #define kFrames 512
81 
main(int argc,char * argv[])82 int main(int argc, char* argv[])
83 {
84     FAUSTFLOAT start_at_sample, nb_samples, sample_rate, down_sample, up_sample, filter_type;
85 
86     DSP = new mydsp();
87 
88     CMDUI* interface = new CMDUI(argc, argv);
89     DSP->buildUserInterface(interface);
90 
91     interface->addOption("-s", &start_at_sample, 0, 0.0, 100000000.0);
92     interface->addOption("-n", &nb_samples, 16, 0.0, 100000000.0);
93     interface->addOption("-r", &sample_rate, 44100.0, 1.0, 192000.0);
94 
95     // For up/down sampling
96     interface->addOption("-ds", &down_sample, 1.0, 1.0, 16.0);
97     interface->addOption("-us", &up_sample, 1.0, 1.0, 16.0);
98     interface->addOption("-filter", &filter_type, 1.0, 1.0, 4.0);
99 
100     if ((down_sample != 1.0) && (up_sample != 1.0)) {
101         cerr << "ERROR : -ds '" << down_sample << "' and -us '" << up_sample << "' cannot be used at the same time !\n";
102         exit(1);
103     }
104 
105     // setup up/down sampling, FC factor is expressed as a Double<INT,DENOM> to allow template specialization
106     int filter = int(filter_type);
107     if (down_sample != 1.0) {
108         int ds = int(down_sample);
109         dsp* busN = new dsp_bus(DSP->getNumOutputs());
110         switch (filter) {
111             case 1:
112                 if (ds == 2) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3<Double<45,100>, 2, float> >(busN));
113                 else if (ds == 4) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3<Double<45,100>, 4, float> >(busN));
114                 else if (ds == 8) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3<Double<45,100>, 8, float> >(busN));
115                 else if (ds == 16) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3<Double<45,100>, 16, float> >(busN));
116                 else cerr << "Downsampling factor must be a power of two and <= 16\n";
117                 break;
118             case 2:
119                 if (ds == 2) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass4<Double<45,100>, 2, float> >(busN));
120                 else if (ds == 4) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass4<Double<45,100>, 4, float> >(busN));
121                 else if (ds == 8) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass4<Double<45,100>, 8, float> >(busN));
122                 else if (ds == 16) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass4<Double<45,100>, 16, float> >(busN));
123                 else cerr << "Downsampling factor must be a power of two and <= 16\n";
124                 break;
125             case 3:
126                 if (ds == 2) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3e<Double<45,100>, 2, float> >(busN));
127                 else if (ds == 4) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3e<Double<45,100>, 4, float> >(busN));
128                 else if (ds == 8) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3e<Double<45,100>, 8, float> >(busN));
129                 else if (ds == 16) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass3e<Double<45,100>, 16, float> >(busN));
130                 else cerr << "Downsampling factor must be a power of two and <= 16\n";
131                 break;
132             case 4:
133                 if (ds == 2) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass6e<Double<45,100>, 2, float> >(busN));
134                 else if (ds == 4) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass6e<Double<45,100>, 4, float> >(busN));
135                 else if (ds == 8) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass6e<Double<45,100>, 8, float> >(busN));
136                 else if (ds == 16) DSP = new dsp_sequencer(DSP, new dsp_down_sampler<LowPass6e<Double<45,100>, 16, float> >(busN));
137                 break;
138             default:
139                 cerr << "Incorrect filter type : " << filter << endl;
140                 break;
141         }
142     } else if (up_sample != 1.0) {
143         int up = int(up_sample);
144         dsp* busN = new dsp_bus(DSP->getNumOutputs());
145         switch (filter) {
146             case 1:
147                 if (up == 2) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3<Double<45,100>, 2, float> >(busN));
148                 else if (up == 4) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3<Double<45,100>, 4, float> >(busN));
149                 else if (up == 8) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3<Double<45,100>, 8, float> >(busN));
150                 else if (up == 16) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3<Double<45,100>, 16, float> >(busN));
151                 else cerr << "Upsampling factor must be a power of two and <= 16\n";
152                 break;
153             case 2:
154                 if (up == 2) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass4<Double<45,100>, 2, float> >(busN));
155                 else if (up == 4) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass4<Double<45,100>, 4, float> >(busN));
156                 else if (up == 8) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass4<Double<45,100>, 8, float> >(busN));
157                 else if (up == 16) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass4<Double<45,100>, 16, float> >(busN));
158                 else cerr << "Upsampling factor must be a power of two and <= 16\n";
159                 break;
160             case 3:
161                 if (up == 2) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3e<Double<45,100>, 2, float> >(busN));
162                 else if (up == 4) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3e<Double<45,100>, 4, float> >(busN));
163                 else if (up == 8) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3e<Double<45,100>, 8, float> >(busN));
164                 else if (up == 16) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass3e<Double<45,100>, 16, float> >(busN));
165                 else cerr << "Upsampling factor must be a power of two and <= 16\n";
166                 break;
167             case 4:
168                 if (up == 2) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass6e<Double<45,100>, 2, float> >(busN));
169                 else if (up == 4) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass6e<Double<45,100>, 4, float> >(busN));
170                 else if (up == 8) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass6e<Double<45,100>, 8, float> >(busN));
171                 else if (up == 16) DSP = new dsp_sequencer(DSP, new dsp_up_sampler<LowPass6e<Double<45,100>, 16, float> >(busN));
172                 break;
173             default:
174                 cerr << "Incorrect filter type : " << filter << endl;
175                 break;
176         }
177     }
178 
179     // SR has to be read before DSP init
180     interface->process_one_init("-r");
181 
182     // init signal processor and the user interface values
183     DSP->init(int(sample_rate));
184 
185     // modify the UI values according to the command line options, after init
186     interface->process_command();
187 
188     // prepare input channels (if any) with an impulse
189     int nins = DSP->getNumInputs();
190     channels inchan(kFrames, nins);
191     inchan.impulse(); // after each compute we will zero them
192 
193     // prepare output channels
194     int nouts = DSP->getNumOutputs();
195     channels outchan(kFrames, nouts);
196 
197     // print usage info:
198     printf("%% Usage: octave --persist thisfile.m\n\n");
199 
200     // print matlab-compatible matrix syntax followed by a plot command:
201     printf("faustout = [ ...\n");
202 
203     // skip <start> samples
204     int start = int(start_at_sample);
205     while (start > kFrames) {
206         DSP->compute(kFrames, inchan.buffers(), outchan.buffers());
207         inchan.zero();
208         start -= kFrames;
209     }
210     if (start > 0) {
211         DSP->compute(start, inchan.buffers(), outchan.buffers());
212     }
213     // end skip
214 
215     int nbsamples = int(nb_samples);
216     cout << setprecision(numeric_limits<FAUSTFLOAT>::max_digits10);
217 
218     // print by buffer
219     while (nbsamples > kFrames) {
220         DSP->compute(kFrames, inchan.buffers(), outchan.buffers());
221         inchan.zero();
222         for (int i = 0; i < kFrames; i++) {
223             for (int c = 0; c < nouts; c++) {
224                 cout << " " << outchan.buffers()[c][i];
225             }
226             if (i < kFrames-1) {
227                 printf("; ...\n");
228             } else {
229                 printf("; ...\n%%---- Chunk Boundary ----\n");
230             }
231         }
232         nbsamples -= kFrames;
233     }
234 
235     // print remaining frames
236     if (nbsamples) {
237         DSP->compute(nbsamples, inchan.buffers(), outchan.buffers());
238         inchan.zero();
239         for (int i = 0; i < nbsamples; i++) {
240             for (int c = 0; c < nouts; c++) {
241                 cout << " " << outchan.buffers()[c][i];
242             }
243             printf("; ...\n");
244         }
245     }
246     printf("];\n\n");
247     printf("plot(faustout);\n");
248     printf("title('Plot generated by %s made using ''faust -a matlabplot.cpp ...''');\n", argv[0]);
249     printf("xlabel('Time (samples)');\n");
250     printf("ylabel('Amplitude');\n");
251     if (nouts > 0) {
252         printf("legend(");
253         for (int c = 0; c < nouts; c++) {
254             printf("'channel %d'", c+1);
255             if (c < nouts-1) { printf(","); }
256         }
257         printf(");\n");
258         printf("print -dpdf %s.pdf;\n", argv[0]);
259     }
260 
261     delete DSP;
262     return 0;
263 }
264 
265 /******************* END matlabplot.cpp ****************/
266