1 /***************************************************************************
2  *   Copyright (C) 2011 by Pere Ràfols Soler                               *
3  *   sapista2@gmail.com                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 /***************************************************************************
22 This file is the implementation of the EQ plugin
23 This plugin is inside the Sapista Plugins Bundle
24 This file implements functionalities for a large numbers of equalizers
25 ****************************************************************************/
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <fftw3.h>
30 
31 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
32 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
33 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
34 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
35 
36 
37 #include "uris.h"
38 
39 #include "gui/eq_defines.h"
40 #include "dsp/vu.h"
41 #include "dsp/db.h"
42 #include "dsp/filter.h"
43 #include "dsp/midside.h"
44 
45 //Data from CMake
46 #define NUM_BANDS @Eq_Bands_Count@
47 #define NUM_CHANNELS @Eq_Channels_Count@
48 #define EQ_URI @Eq_Uri@
49 
50 
51 typedef struct {
52   //Plugin ports
53   float *fBypass;
54   float *fInGain;
55   float *fOutGain;
56   float *fBandGain[NUM_BANDS];
57   float *fBandFreq[NUM_BANDS];
58   float *fBandParam[NUM_BANDS];
59   float *fBandType[NUM_BANDS];
60   float *fBandEnabled[NUM_BANDS];
61   #if NUM_CHANNELS == 2
62   float *fMidSideEnable;
63   int   iMidSideMode[NUM_BANDS];
64   #endif
65   float *fInput[NUM_CHANNELS];
66   float *fOutput[NUM_CHANNELS];
67   float *fVuIn[NUM_CHANNELS];
68   float *fVuOut[NUM_CHANNELS];
69   LV2_Atom_Sequence *notify_port;
70   const LV2_Atom_Sequence* control_port;
71 
72 
73   //Features
74   LV2_URID_Map *map;
75 
76   //Forge for creating atoms
77   LV2_Atom_Forge forge;
78   LV2_Atom_Forge_Frame notify_frame;
79 
80   //Atom URID
81   Eq10qURIs uris;
82   double sampleRate;
83 
84   //Plugin DSP
85   Filter *ProcFilter[NUM_BANDS][NUM_CHANNELS]; //Dummy pointers to Filter structures, used in processing loop. Can point to PortFilter or FlatFilter depending on the MidSide option
86   Filter *PortFilter[NUM_BANDS]; //Filter used for reading LV2 ports and containing the actual coeficients
87   Filter *FlatFilter; //Allways contains coeficients for a flat filter in order to be used as a bypass in MidSide processing option
88   Buffers buf[NUM_BANDS][NUM_CHANNELS];
89   Vu *InputVu[NUM_CHANNELS];
90   Vu *OutputVu[NUM_CHANNELS];
91 
92   //FFT Analysis
93   int fft_ix, fft_ix2; //Index to follow buffers
94   double *fft_in, *fft_out;
95   double *fft_in2, *fft_out2; //Time shifted-seconf-fft-vectors
96   fftw_plan fft_p, fft_p2;
97   int fft_on;
98   double fft_normalization;
99 } EQ;
100 
cleanupEQ(LV2_Handle instance)101 static void cleanupEQ(LV2_Handle instance)
102 {
103   EQ *plugin = (EQ *)instance;
104   int i;
105 
106   FilterClean(plugin->FlatFilter);
107   for(i=0; i<NUM_BANDS; i++)
108   {
109     FilterClean(plugin->PortFilter[i]);
110   }
111 
112   for(i=0; i<NUM_CHANNELS; i++)
113   {
114     VuClean(plugin->InputVu[i]);
115     VuClean(plugin->OutputVu[i]);
116   }
117 
118   fftw_destroy_plan(plugin->fft_p);
119   fftw_free(plugin->fft_in); fftw_free(plugin->fft_out);
120   fftw_destroy_plan(plugin->fft_p2);
121   fftw_free(plugin->fft_in2); fftw_free(plugin->fft_out2);
122   free(instance);
123 }
124 
connectPortEQ(LV2_Handle instance,uint32_t port,void * data)125 static void connectPortEQ(LV2_Handle instance, uint32_t port, void *data)
126 {
127   EQ *plugin = (EQ *)instance;
128 
129   //Connect standar ports
130   switch (port)
131   {
132     case EQ_BYPASS:
133       plugin->fBypass = data;
134     break;
135 
136     case EQ_INGAIN:
137       plugin->fInGain = data;
138     break;
139 
140     case EQ_OUTGAIN:
141       plugin->fOutGain = data;
142     break;
143 
144     default:
145       //Connect audio input ports
146       if(port >= PORT_OFFSET && port < (PORT_OFFSET + NUM_CHANNELS))
147       {
148         plugin->fInput[port - PORT_OFFSET] = data;
149       }
150 
151       //Connect audio output ports
152       if(port >= (PORT_OFFSET + NUM_CHANNELS) && port < (PORT_OFFSET + 2*NUM_CHANNELS))
153       {
154         plugin->fOutput[port - PORT_OFFSET - NUM_CHANNELS] = data;
155       }
156 
157       //Connect BandGain ports
158       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + NUM_BANDS))
159       {
160         plugin->fBandGain[port - PORT_OFFSET - 2*NUM_CHANNELS] = data;
161       }
162 
163       //Connect BandFreq ports
164       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + NUM_BANDS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 2*NUM_BANDS))
165       {
166         plugin->fBandFreq[port - PORT_OFFSET - 2*NUM_CHANNELS - NUM_BANDS] = data;
167       }
168 
169       //Connect BandParam ports
170       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + 2*NUM_BANDS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 3*NUM_BANDS))
171       {
172         plugin->fBandParam[port - PORT_OFFSET - 2*NUM_CHANNELS - 2*NUM_BANDS] = data;
173       }
174 
175       //Connect BandType ports
176       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + 3*NUM_BANDS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 4*NUM_BANDS))
177       {
178         plugin->fBandType[port - PORT_OFFSET - 2*NUM_CHANNELS - 3*NUM_BANDS] = data;
179       }
180 
181       //Connect BandEnabled ports
182       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + 4*NUM_BANDS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS))
183       {
184         plugin->fBandEnabled[port - PORT_OFFSET - 2*NUM_CHANNELS - 4*NUM_BANDS] = data;
185       }
186 
187       //Connect VuInput ports
188       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + NUM_CHANNELS))
189       {
190         plugin->fVuIn[port - PORT_OFFSET - 2*NUM_CHANNELS - 5*NUM_BANDS] = data;
191       }
192 
193       //Connect VuOutput ports
194       else if(port >= (PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + NUM_CHANNELS) && port < (PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + 2*NUM_CHANNELS))
195       {
196         plugin->fVuOut[port - PORT_OFFSET - 2*NUM_CHANNELS - 5*NUM_BANDS - NUM_CHANNELS] = data;
197       }
198 
199       //Connect Atom notify_port output port to GUI
200       else if(port == PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + 2*NUM_CHANNELS)
201       {
202         plugin->notify_port = (LV2_Atom_Sequence*)data;
203       }
204 
205       //Connect Atom control_port input port from GUI
206       else if (port == PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + 2*NUM_CHANNELS + 1)
207       {
208         plugin->control_port = (const LV2_Atom_Sequence*)data;
209       }
210 
211       //Connect the MidSide Mode port only for stereo versions
212       else if (port == PORT_OFFSET + 2*NUM_CHANNELS + 5*NUM_BANDS + 2*NUM_CHANNELS + 2)
213       {
214         #if NUM_CHANNELS == 2
215         plugin->fMidSideEnable = data;
216         #endif
217       }
218     break;
219   }
220 }
221 
instantiateEQ(const LV2_Descriptor * descriptor,double s_rate,const char * path,const LV2_Feature * const * features)222 static LV2_Handle instantiateEQ(const LV2_Descriptor *descriptor, double s_rate, const char *path, const LV2_Feature *const * features)
223 {
224   int i,ch;
225   EQ *plugin_data = (EQ *)malloc(sizeof(EQ));
226   plugin_data->sampleRate = s_rate;
227 
228   plugin_data->FlatFilter = FilterInit(s_rate);
229   calcCoefs(plugin_data->FlatFilter, 0.0, 20.0, 1.0, F_PEAK, 0.0); //Create a always-flat filter in FlatFilter
230 
231   for(i=0; i<NUM_BANDS; i++)
232   {
233     plugin_data->PortFilter[i] = FilterInit(s_rate);
234     for(ch=0; ch<NUM_CHANNELS; ch++)
235     {
236       flushBuffers(&plugin_data->buf[i][ch]);
237       plugin_data->ProcFilter[i][ch] = plugin_data->PortFilter[i]; //Initially all filters points to LV2 Port controlled filters
238     }
239     #if NUM_CHANNELS == 2
240     plugin_data->iMidSideMode[i] = MS_DUAL_CHANNEL;
241     #endif
242   }
243 
244 
245   for(ch=0; ch<NUM_CHANNELS; ch++)
246   {
247     plugin_data->InputVu[ch] = VuInit(s_rate);
248     plugin_data->OutputVu[ch] = VuInit(s_rate);
249   }
250 
251 
252   // Get host features
253   for (i = 0; features[i]; ++i)
254   {
255     if (!strcmp(features[i]->URI, LV2_URID__map))
256     {
257         plugin_data->map = (LV2_URID_Map*)features[i]->data;
258     }
259   }
260   if (!plugin_data->map)
261   {
262     printf("EQ10Q Error: Host does not support urid:map\n");
263     goto fail;
264   }
265 
266   // Map URIs and initialise forge
267   map_eq10q_uris(plugin_data->map, &plugin_data->uris);
268   lv2_atom_forge_init(&plugin_data->forge, plugin_data->map);
269 
270   //Initialize FFT objects
271   plugin_data->fft_ix = 0;
272   plugin_data->fft_ix2 = FFT_N/2;
273   plugin_data->fft_in = (double*) fftw_malloc(sizeof(double) * FFT_N);
274   plugin_data->fft_in2 = (double*) fftw_malloc(sizeof(double) * FFT_N);
275   plugin_data->fft_out = (double*) fftw_malloc(sizeof(double) * FFT_N);
276   plugin_data->fft_out2 = (double*) fftw_malloc(sizeof(double) * FFT_N);
277   plugin_data->fft_p = fftw_plan_r2r_1d(FFT_N, plugin_data->fft_in, plugin_data->fft_out, FFTW_R2HC, FFTW_ESTIMATE);
278   plugin_data->fft_p2 = fftw_plan_r2r_1d(FFT_N, plugin_data->fft_in2, plugin_data->fft_out2, FFTW_R2HC, FFTW_ESTIMATE);
279   plugin_data->fft_on = 0; //Initialy no GUI then no need to compute FFT
280   plugin_data->fft_normalization = pow(2.0/ ((double) FFT_N), 2.0);
281   for(i = 0; i< FFT_N; i++)
282   {
283     plugin_data->fft_in[i] = 0;
284     plugin_data->fft_in2[i] = 0;
285     plugin_data->fft_out[i] = 0;
286     plugin_data->fft_out2[i] = 0; //First fft_out2 samples will not be calculated by FFT (first-time shift)
287   }
288   return (LV2_Handle)plugin_data;
289 
290   fail:
291     free(plugin_data);
292     return 0;
293 }
294 
runEQ_v2(LV2_Handle instance,uint32_t sample_count)295 static void runEQ_v2(LV2_Handle instance, uint32_t sample_count)
296 {
297 
298   EQ *plugin_data = (EQ *)instance;
299 
300   //Get values of control ports
301   const int iBypass = *(plugin_data->fBypass) > 0.0f ? 1 : 0;
302   const float fInGain = dB2Lin(*(plugin_data->fInGain));
303   const float fOutGain = dB2Lin(*(plugin_data->fOutGain));
304   #if NUM_CHANNELS == 2
305   const double dMidSideModeIdOn = (double)(*(plugin_data->fMidSideEnable));
306   #endif
307   int bd, pos; //loop index
308 
309 
310   //Set up forge to write directly to notify output port.
311   const uint32_t notify_capacity = plugin_data->notify_port->atom.size;
312   lv2_atom_forge_set_buffer(&plugin_data->forge, (uint8_t*)plugin_data->notify_port, notify_capacity);
313   lv2_atom_forge_sequence_head(&plugin_data->forge, &plugin_data->notify_frame, 0);
314   //printf("Notify port size %d\n", notify_capacity);
315 
316   //Interpolation coefs force to recompute
317   int recalcCoefs[NUM_BANDS];
318   int forceRecalcCoefs = 0;
319 
320   double fftInSample; //Sample to push throught the FFT buffer
321   double  sampleL; //Current processing sample left signal
322   #if NUM_CHANNELS == 2
323   double sampleR; //Current processing sample right signal
324   #endif
325 
326   //Read EQ Ports and mark to recompute if changed
327   for(bd = 0; bd<NUM_BANDS; bd++)
328   {
329     if(dB2Lin(*(plugin_data->fBandGain[bd])) != plugin_data->PortFilter[bd]->gain ||
330 	*plugin_data->fBandFreq[bd] != plugin_data->PortFilter[bd]->freq ||
331 	*plugin_data->fBandParam[bd] != plugin_data->PortFilter[bd]->q ||
332 	((int)(*plugin_data->fBandType[bd])) != plugin_data->PortFilter[bd]->iType ||
333 	((float)(0x01 & ((int)(*plugin_data->fBandEnabled[bd])))) != plugin_data->PortFilter[bd]->enable)
334     {
335       recalcCoefs[bd] = 1;
336       forceRecalcCoefs = 1;
337     }
338     else
339     {
340       recalcCoefs[bd] = 0;
341     }
342 
343     //Check mid-side ports
344     #if NUM_CHANNELS == 2
345     if((((int)(*plugin_data->fBandEnabled[bd])) >> 1) != plugin_data->iMidSideMode[bd])
346     {
347       plugin_data->iMidSideMode[bd] = ((int)(*plugin_data->fBandEnabled[bd])) >> 1;
348 
349       switch(plugin_data->iMidSideMode[bd])
350       {
351         case MS_DUAL_CHANNEL:
352           plugin_data->ProcFilter[bd][0] = plugin_data->PortFilter[bd];
353           plugin_data->ProcFilter[bd][1] = plugin_data->PortFilter[bd];
354           break;
355 
356         case MS_L_MID_MODE:
357           plugin_data->ProcFilter[bd][0] = plugin_data->PortFilter[bd];
358           plugin_data->ProcFilter[bd][1] = plugin_data->FlatFilter;
359           break;
360 
361         case MS_R_SIDE_MODE:
362           plugin_data->ProcFilter[bd][0] = plugin_data->FlatFilter;
363           plugin_data->ProcFilter[bd][1] = plugin_data->PortFilter[bd];
364           break;
365       }
366 
367     }
368     #endif
369   }
370 
371   //Read input Atom control port (Data from GUI)
372   if(plugin_data->control_port)
373   {
374     const LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(plugin_data->control_port)->body);
375     // For each incoming message...
376     while (!lv2_atom_sequence_is_end(&plugin_data->control_port->body, plugin_data->control_port->atom.size, ev))
377     {
378       // If the event is an atom:Object
379       if (ev->body.type == plugin_data->uris.atom_Object)
380       {
381         const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body;
382         if (obj->body.otype == plugin_data->uris.atom_fft_on)
383         {
384           plugin_data->fft_on = 1;
385         }
386         else if(obj->body.otype == plugin_data->uris.atom_fft_off)
387         {
388           plugin_data->fft_on = 0;
389           plugin_data->fft_ix = 0;
390           plugin_data->fft_ix2 = FFT_N/2;
391         }
392         else if(obj->body.otype == plugin_data->uris.atom_sample_rate_request)
393         {
394           //Send sample rate
395           LV2_Atom_Forge_Frame frameSR;
396           lv2_atom_forge_frame_time(&plugin_data->forge, 0);
397           lv2_atom_forge_object( &plugin_data->forge, &frameSR, 0, plugin_data->uris.atom_sample_rate_response);
398           lv2_atom_forge_key(&plugin_data->forge, plugin_data->uris.atom_sample_rate_key);
399           lv2_atom_forge_double(&plugin_data->forge, plugin_data->sampleRate);
400           lv2_atom_forge_pop(&plugin_data->forge, &frameSR);
401 
402           // Close off sequence
403           lv2_atom_forge_pop(&plugin_data->forge, &plugin_data->notify_frame);
404         }
405       }
406       ev = lv2_atom_sequence_next(ev);
407     }
408   }
409 
410   //Compute the filter
411   for (pos = 0; pos < sample_count; pos++)
412   {
413     //Get input
414     sampleL = (double)plugin_data->fInput[0][pos];
415     DENORMAL_TO_ZERO(sampleL);
416 
417     #if NUM_CHANNELS == 2
418     sampleR = (double)plugin_data->fInput[1][pos];
419     DENORMAL_TO_ZERO(sampleR);
420     #endif
421 
422     //The input amplifier
423     sampleL *= fInGain;
424     fftInSample = sampleL;
425     //Update VU input sample
426     SetSample(plugin_data->InputVu[0], sampleL);
427 
428     #if NUM_CHANNELS == 2
429     //The input amplifier
430     sampleR *= fInGain;
431     fftInSample = 0.5*sampleL + 0.5*sampleR;
432     //Update VU input sample
433     SetSample(plugin_data->InputVu[1], sampleR);
434     #endif
435 
436     //Process every band
437     if(!iBypass)
438     {
439 
440       //FFT of input data after input gain
441       if(plugin_data->fft_on)
442       {
443         //Hanning Windowing
444         plugin_data->fft_in[plugin_data->fft_ix] = fftInSample* 0.5 * (1.0-cos((2.0*PI*((double)plugin_data->fft_ix))/((double)(FFT_N-1))));
445         plugin_data->fft_in2[plugin_data->fft_ix2] = fftInSample* 0.5 * (1.0-cos((2.0*PI*((double)plugin_data->fft_ix2))/((double)(FFT_N-1))));
446 
447         plugin_data->fft_ix++;
448         plugin_data->fft_ix2++;
449 
450         if(plugin_data->fft_ix == FFT_N)
451         {
452           //FFT inout buffer full compute
453           fftw_execute(plugin_data->fft_p);
454 
455           //Compute FFT Normalized Magnitude^2
456           double real, img;
457           int ffti;
458           for(ffti = 0; ffti<= FFT_N/2; ffti++)
459           {
460             real = plugin_data->fft_out[ffti];
461             if(ffti > 0 && ffti < (FFT_N/2))
462             {
463               img = plugin_data->fft_out[FFT_N -ffti];
464             }
465             else
466             {
467               img = 0.0;
468             }
469             plugin_data->fft_out[ffti] = 0.5*(plugin_data->fft_normalization*(real*real + img*img) + plugin_data->fft_out2[ffti]);
470           }
471 
472           plugin_data->fft_ix = 0;
473 
474 
475           //Send FFT data vector
476           LV2_Atom_Forge_Frame frameFft;
477           lv2_atom_forge_frame_time(&plugin_data->forge, 0);
478           lv2_atom_forge_object( &plugin_data->forge, &frameFft, 0, plugin_data->uris.atom_fft_data_event);
479           lv2_atom_forge_key(&plugin_data->forge, plugin_data->uris.atom_fft_data_key);
480           lv2_atom_forge_vector(&plugin_data->forge, sizeof(double), plugin_data->uris.atom_Double, ((FFT_N/2) + 1), plugin_data->fft_out);
481           lv2_atom_forge_pop(&plugin_data->forge, &frameFft);
482 
483           // Close off sequence
484           lv2_atom_forge_pop(&plugin_data->forge, &plugin_data->notify_frame);
485         }
486 
487         if(plugin_data->fft_ix2 == FFT_N)
488         {
489           //FFT inout buffer full compute
490           fftw_execute(plugin_data->fft_p2);
491 
492           //Compute FFT Normalized Magnitude^2
493           double real, img;
494           int ffti;
495           for(ffti = 0; ffti<= FFT_N/2; ffti++)
496           {
497             real = plugin_data->fft_out2[ffti];
498             if(ffti > 0 && ffti < (FFT_N/2))
499             {
500               img = plugin_data->fft_out2[FFT_N -ffti];
501             }
502             else
503             {
504               img = 0.0;
505             }
506             plugin_data->fft_out2[ffti] = plugin_data->fft_normalization*(real*real + img*img);
507           }
508 
509           plugin_data->fft_ix2 = 0;
510         }
511       }
512 
513       //Coefs Interpolation
514       if(forceRecalcCoefs)
515       {
516 	for(bd = 0; bd<NUM_BANDS; bd++)
517 	{
518 	  if(recalcCoefs[bd])
519 	  {
520 	    calcCoefs(plugin_data->PortFilter[bd],
521 		    dB2Lin(*(plugin_data->fBandGain[bd])),
522 		    *plugin_data->fBandFreq[bd],
523 		    *plugin_data->fBandParam[bd],
524 		    (int)(*plugin_data->fBandType[bd]),
525 		    ((float)(0x01 & ((int)(*plugin_data->fBandEnabled[bd])))));
526 	    }
527 	  }
528 	}
529 
530 
531       //EQ PROCESSOR
532 
533         //Band0
534         #if NUM_CHANNELS == 2
535         LR2MS(&sampleL, &sampleR, dMidSideModeIdOn);
536         #endif
537 	computeFilter(plugin_data->ProcFilter[0][0], &plugin_data->buf[0][0],&sampleL);
538         #if NUM_CHANNELS == 2
539         computeFilter(plugin_data->ProcFilter[0][1], &plugin_data->buf[0][1],&sampleR);
540         #endif
541 
542 	#if NUM_BANDS >= 4
543         //BAND 1
544         computeFilter(plugin_data->ProcFilter[1][0], &plugin_data->buf[1][0],&sampleL);
545         #if NUM_CHANNELS == 2
546         computeFilter(plugin_data->ProcFilter[1][1], &plugin_data->buf[1][1],&sampleR);
547         #endif
548 
549         //BAND 2
550         computeFilter(plugin_data->ProcFilter[2][0], &plugin_data->buf[2][0],&sampleL);
551         #if NUM_CHANNELS == 2
552         computeFilter(plugin_data->ProcFilter[2][1], &plugin_data->buf[2][1],&sampleR);
553         #endif
554 
555         //BAND 3
556         computeFilter(plugin_data->ProcFilter[3][0], &plugin_data->buf[3][0],&sampleL);
557         #if NUM_CHANNELS == 2
558         computeFilter(plugin_data->ProcFilter[3][1], &plugin_data->buf[3][1],&sampleR);
559         #endif
560 	#endif
561 
562 	#if NUM_BANDS >= 6
563         //BAND 4
564         computeFilter(plugin_data->ProcFilter[4][0], &plugin_data->buf[4][0],&sampleL);
565         #if NUM_CHANNELS == 2
566         computeFilter(plugin_data->ProcFilter[4][1], &plugin_data->buf[4][1],&sampleR);
567         #endif
568 
569         //BAND 5
570         computeFilter(plugin_data->ProcFilter[5][0], &plugin_data->buf[5][0],&sampleL);
571         #if NUM_CHANNELS == 2
572         computeFilter(plugin_data->ProcFilter[5][1], &plugin_data->buf[5][1],&sampleR);
573         #endif
574         #endif
575 
576 	#if NUM_BANDS ==10
577         //BAND 6
578         computeFilter(plugin_data->ProcFilter[6][0], &plugin_data->buf[6][0],&sampleL);
579         #if NUM_CHANNELS == 2
580         computeFilter(plugin_data->ProcFilter[6][1], &plugin_data->buf[6][1],&sampleR);
581         #endif
582 
583         //BAND 7
584         computeFilter(plugin_data->ProcFilter[7][0], &plugin_data->buf[7][0],&sampleL);
585         #if NUM_CHANNELS == 2
586         computeFilter(plugin_data->ProcFilter[7][1], &plugin_data->buf[7][1],&sampleR);
587         #endif
588 
589         //BAND 8
590         computeFilter(plugin_data->ProcFilter[8][0], &plugin_data->buf[8][0],&sampleL);
591         #if NUM_CHANNELS == 2
592         computeFilter(plugin_data->ProcFilter[8][1], &plugin_data->buf[8][1],&sampleR);
593         #endif
594 
595         //BAND 9
596         computeFilter(plugin_data->ProcFilter[9][0], &plugin_data->buf[9][0],&sampleL);
597         #if NUM_CHANNELS == 2
598         computeFilter(plugin_data->ProcFilter[9][1], &plugin_data->buf[9][1],&sampleR);
599         #endif
600 	#endif
601 
602 
603       //The output amplifier
604       sampleL *= fOutGain;
605       //Update VU output sample
606       SetSample(plugin_data->OutputVu[0], sampleL);
607 
608       #if NUM_CHANNELS == 2
609       //The output amplifier
610       sampleR *= fOutGain;
611       //Update VU output sample
612       SetSample(plugin_data->OutputVu[1], sampleR);
613 
614       //Go back to LR signals, be aware that out gains and Vumeters Are M/S or L/R depending on MidSide selected mode
615       MS2LR(&sampleL, &sampleR, dMidSideModeIdOn);
616       #endif
617     }
618 
619     //Write on output
620     plugin_data->fOutput[0][pos] = (float)sampleL;
621     #if NUM_CHANNELS == 2
622     plugin_data->fOutput[1][pos] = (float)sampleR;
623     #endif
624   }
625 
626   //Update VU ports
627   *(plugin_data->fVuIn[0]) = ComputeVu(plugin_data->InputVu[0], sample_count);
628   *(plugin_data->fVuOut[0]) = ComputeVu(plugin_data->OutputVu[0], sample_count);
629   #if NUM_CHANNELS == 2
630   *(plugin_data->fVuIn[1]) = ComputeVu(plugin_data->InputVu[1], sample_count);
631   *(plugin_data->fVuOut[1]) = ComputeVu(plugin_data->OutputVu[1], sample_count);
632   #endif
633 }
634 
635 static const LV2_Descriptor eqDescriptor = {
636   EQ_URI,
637   instantiateEQ,
638   connectPortEQ,
639   NULL,
640   runEQ_v2,
641   NULL,
642   cleanupEQ,
643   NULL
644 };
645 
646 LV2_SYMBOL_EXPORT
lv2_descriptor(uint32_t index)647 const LV2_Descriptor *lv2_descriptor(uint32_t index)
648 {
649   switch (index) {
650   case 0:
651     return &eqDescriptor;
652   default:
653     return NULL;
654   }
655 }
656