1 /***************************************************************************
2 * Copyright (C) 2015 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 MidSide Matrix plugin
23 This plugin is inside the Sapista Plugins Bundle
24 This file implements functionalities for lr2ms and ms2lr matrices
25 ****************************************************************************/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
31
32
33 #include "dsp/vu.h"
34 #include "dsp/db.h"
35 #include "dsp/midside.h"
36
37 //Data from CMake
38 #define MATRIX_URI @Matrix_Uri@
39 #define IS_LR2MS @Matrix_Is_LR2MS@ //If is defined to 1 is in LR2MS mode otherwise is MS2LR
40
41 //Port definitions
42 #define PORT_AUDIO_IN_1 0
43 #define PORT_AUDIO_IN_2 1
44 #define PORT_AUDIO_OUT_1 2
45 #define PORT_AUDIO_OUT_2 3
46 #define PORT_GAIN_IN_1 4
47 #define PORT_GAIN_IN_2 5
48 #define PORT_GAIN_OUT_1 6
49 #define PORT_GAIN_OUT_2 7
50 #define PORT_SOLO_IN_1 8
51 #define PORT_SOLO_IN_2 9
52 #define PORT_SOLO_OUT_1 10
53 #define PORT_SOLO_OUT_2 11
54 #define PORT_VU_IN_1 12
55 #define PORT_VU_IN_2 13
56 #define PORT_VU_OUT_1 14
57 #define PORT_VU_OUT_2 15
58
59 typedef struct {
60 //Plugin ports
61 float *fInGain1; //Its L for lr2ms and M for ms2lr
62 float *fInGain2; //Its R for lr2ms and S for ms2lr
63 float *fOutGain1; //Its M for lr2ms and L for ms2lr
64 float *fOutGain2; //Its S for lr2ms and R for ms2lr
65
66 float *fSoloIn1; //Its L for lr2ms and M for ms2lr
67 float *fSoloIn2; //Its R for lr2ms and S for ms2lr
68 float *fSoloOut1; //Its M for lr2ms and L for ms2lr
69 float *fSoloOut2; //Its S for lr2ms and R for ms2lr
70
71 const float *input[2];
72 float *output[2];
73
74 float *fVuIn[2];
75 float *fVuOut[2];
76
77 //Internal data
78 Vu *InputVu[2];
79 Vu *OutputVu[2];
80 float sample_rate;
81
82 //Matrix routing vars
83 double RG_in1, RG_in2, RG_out11, RG_out12, RG_out21, RG_out22;
84
85 } MidSideMatrix;
86
cleanupMatrix(LV2_Handle instance)87 static void cleanupMatrix(LV2_Handle instance)
88 {
89 MidSideMatrix *plugin = (MidSideMatrix *)instance;
90 int i;
91 for(i=0; i<2; i++)
92 {
93 VuClean(plugin->InputVu[i]);
94 VuClean(plugin->OutputVu[i]);
95 }
96 free(instance);
97 }
98
99
connectPortMatrix(LV2_Handle instance,uint32_t port,void * data)100 static void connectPortMatrix(LV2_Handle instance, uint32_t port, void *data)
101 {
102 MidSideMatrix *plugin = (MidSideMatrix *)instance;
103 switch (port) {
104 case PORT_AUDIO_IN_1:
105 plugin->input[0] = (const float*)data;;
106 break;
107
108 case PORT_AUDIO_IN_2:
109 plugin->input[1] = (const float*)data;;
110 break;
111
112 case PORT_AUDIO_OUT_1:
113 plugin->output[0] = (float*)data;
114 break;
115
116 case PORT_AUDIO_OUT_2:
117 plugin->output[1] = (float*)data;
118 break;
119
120 case PORT_GAIN_IN_1:
121 plugin->fInGain1 = (float*)data;
122 break;
123
124 case PORT_GAIN_IN_2:
125 plugin->fInGain2 = (float*)data;
126 break;
127
128 case PORT_GAIN_OUT_1:
129 plugin->fOutGain1 = (float*)data;
130 break;
131
132 case PORT_GAIN_OUT_2:
133 plugin->fOutGain2 = (float*)data;
134 break;
135
136 case PORT_SOLO_IN_1:
137 plugin->fSoloIn1 = (float*)data;
138 break;
139
140 case PORT_SOLO_IN_2:
141 plugin->fSoloIn2 = (float*)data;
142 break;
143
144 case PORT_SOLO_OUT_1:
145 plugin->fSoloOut1 = (float*)data;
146 break;
147
148 case PORT_SOLO_OUT_2:
149 plugin->fSoloOut2 = (float*)data;
150 break;
151
152 case PORT_VU_IN_1:
153 plugin->fVuIn[0]=(float*)data;
154 break;
155
156 case PORT_VU_IN_2:
157 plugin->fVuIn[1]=(float*)data;
158 break;
159
160 case PORT_VU_OUT_1:
161 plugin->fVuOut[0]=(float*)data;
162 break;
163
164 case PORT_VU_OUT_2:
165 plugin->fVuOut[1]=(float*)data;
166 break;
167 }
168 }
169
instantiateMatrix(const LV2_Descriptor * descriptor,double s_rate,const char * path,const LV2_Feature * const * features)170 static LV2_Handle instantiateMatrix(const LV2_Descriptor *descriptor, double s_rate, const char *path, const LV2_Feature *const * features)
171 {
172 MidSideMatrix *plugin_data = (MidSideMatrix *)malloc(sizeof(MidSideMatrix));
173 plugin_data->sample_rate = s_rate;
174 plugin_data->InputVu[0] = VuInit(s_rate);
175 plugin_data->InputVu[1] = VuInit(s_rate);
176 plugin_data->OutputVu[0] = VuInit(s_rate);
177 plugin_data->OutputVu[1] = VuInit(s_rate);
178 plugin_data->RG_in1 = 0.0f;
179 plugin_data->RG_in2 = 0.0f;
180 plugin_data->RG_out11 = 0.0f;
181 plugin_data->RG_out12 = 0.0f;
182 plugin_data->RG_out21 = 0.0f;
183 plugin_data->RG_out22 = 0.0f;
184
185 return (LV2_Handle)plugin_data;
186 }
187
runMatrix(LV2_Handle instance,uint32_t sample_count)188 static void runMatrix(LV2_Handle instance, uint32_t sample_count)
189 {
190 MidSideMatrix *plugin_data = (MidSideMatrix *)instance;
191
192 const double gain_in_1 = (double) dB2Lin(*(plugin_data->fInGain1));
193 const double gain_in_2 = (double) dB2Lin(*(plugin_data->fInGain2));
194 const double gain_out_1 = (double) dB2Lin(*(plugin_data->fOutGain1));
195 const double gain_out_2 = (double) dB2Lin(*(plugin_data->fOutGain2));
196
197 const float solo_in_1 = *(plugin_data->fSoloIn1);
198 const float solo_in_2 = *(plugin_data->fSoloIn2);
199 const float solo_out_1 = *(plugin_data->fSoloOut1);
200 const float solo_out_2 = *(plugin_data->fSoloOut2);
201
202 //Set RG constants acording SOLO state
203 plugin_data-> RG_in1 = 0.0;
204 plugin_data-> RG_in2 = 0.0;
205 plugin_data->RG_out11 = 1.0;
206 plugin_data->RG_out12 = 0.0;
207 plugin_data->RG_out21 = 0.0;
208 plugin_data->RG_out22 = 1.0;
209
210 if( solo_out_1 > 0.5)
211 {
212 plugin_data-> RG_in1 = 0.0;
213 plugin_data-> RG_in2 = 0.0;
214 plugin_data->RG_out11 = 1.0;
215 plugin_data->RG_out12 = 1.0;
216 plugin_data->RG_out21 = 0.0;
217 plugin_data->RG_out22 = 0.0;
218 }
219
220 if( solo_out_2 > 0.5)
221 {
222 plugin_data-> RG_in1 = 0.0;
223 plugin_data-> RG_in2 = 0.0;
224 plugin_data->RG_out11 = 0.0;
225 plugin_data->RG_out12 = 0.0;
226 plugin_data->RG_out21 = 1.0;
227 plugin_data->RG_out22 = 1.0;
228 }
229
230 if( solo_in_1 > 0.5 )
231 {
232 plugin_data-> RG_in1 = 1.0;
233 plugin_data-> RG_in2 = 0.0;
234 plugin_data->RG_out11 = 0.0;
235 plugin_data->RG_out12 = 0.0;
236 plugin_data->RG_out21 = 0.0;
237 plugin_data->RG_out22 = 0.0;
238 }
239
240 if( solo_in_2 > 0.5)
241 {
242 plugin_data-> RG_in1 = 0.0;
243 plugin_data-> RG_in2 = 1.0;
244 plugin_data->RG_out11 = 0.0;
245 plugin_data->RG_out12 = 0.0;
246 plugin_data->RG_out21 = 0.0;
247 plugin_data->RG_out22 = 0.0;
248 }
249
250 double sgn1_pre = 0.0, sgn2_pre = 0.0, sgn1_post = 0.0, sgn2_post = 0.0; //Internal signals
251
252 for (uint32_t i = 0; i < sample_count; ++i)
253 {
254 //Input Gains
255 sgn1_pre = (double) (plugin_data->input[0][i]) * gain_in_1;
256 sgn2_pre = (double) (plugin_data->input[1][i]) * gain_in_2;
257
258
259
260 sgn1_post = sgn1_pre;
261 sgn2_post = sgn2_pre;
262 #if IS_LR2MS == 1
263 LR2MS(&sgn1_post, &sgn2_post, 1.0);
264 #else
265 MS2LR(&sgn1_post, &sgn2_post, 1.0);
266 #endif
267
268 //Output Gains
269 sgn1_post *= gain_out_1;
270 sgn2_post *= gain_out_2;
271
272 //Update VU's
273 SetSample(plugin_data->InputVu[0], (float)sgn1_pre);
274 SetSample(plugin_data->InputVu[1], (float)sgn2_pre);
275 SetSample(plugin_data->OutputVu[0], (float)sgn1_post);
276 SetSample(plugin_data->OutputVu[1], (float)sgn2_post);
277
278 //Set outputs
279 plugin_data->output[0][i] = plugin_data->RG_in1 * sgn1_pre +
280 plugin_data->RG_in2 * sgn2_pre +
281 plugin_data->RG_out11 * sgn1_post +
282 plugin_data->RG_out21 * sgn2_post;
283
284 plugin_data->output[1][i] = plugin_data->RG_in1 * sgn1_pre +
285 plugin_data->RG_in2 * sgn2_pre +
286 plugin_data->RG_out12 * sgn1_post +
287 plugin_data->RG_out22 * sgn2_post;
288 }
289
290 //Refresh VU's
291 *(plugin_data->fVuIn[0]) = ComputeVu(plugin_data->InputVu[0], sample_count);
292 *(plugin_data->fVuIn[1]) = ComputeVu(plugin_data->InputVu[1], sample_count);
293 *(plugin_data->fVuOut[0]) = ComputeVu(plugin_data->OutputVu[0], sample_count);
294 *(plugin_data->fVuOut[1]) = ComputeVu(plugin_data->OutputVu[1], sample_count);
295 }
296
297 static const LV2_Descriptor msMatrixDescriptor = {
298 MATRIX_URI,
299 instantiateMatrix,
300 connectPortMatrix,
301 NULL,
302 runMatrix,
303 NULL,
304 cleanupMatrix,
305 NULL
306 };
307
308 LV2_SYMBOL_EXPORT
lv2_descriptor(uint32_t index)309 const LV2_Descriptor *lv2_descriptor(uint32_t index)
310 {
311 switch (index) {
312 case 0:
313 return &msMatrixDescriptor;
314 default:
315 return NULL;
316 }
317 }
318