1 /*
2     ambicode.c:
3 
4     Copyright (C) 2005 Samuel Groner,
5     Institute for Computer Music and Sound Technology, www.icst.net
6 
7     This file is part of Csound.
8 
9     The Csound Library is free software; you can redistribute it
10     and/or modify it under the terms of the GNU Lesser General Public
11     License as published by the Free Software Foundation; either
12     version 2.1 of the License, or (at your option) any later version.
13 
14     Csound is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU Lesser General Public License for more details.
18 
19     You should have received a copy of the GNU Lesser General Public
20     License along with Csound; if not, write to the Free Software
21     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22     02110-1301 USA
23 */
24 #include "csoundCore.h"
25 #include "interlocks.h"
26 #include <math.h>
27 
28 typedef struct {
29     OPDS    h;                                      /* required header */
30     MYFLT   *mw, *mx, *my, *mz, *mr, *ms, *mt, *mu, *mv, *mk,
31             *ml, *mm, *mn, *mo, *mp, *mq;           /* addr outarg */
32     MYFLT   *asig, *kalpha, *kbeta, *kin[4];          /* addr inargs */
33     /* private dataspace */
34     double  w, x, y, z, r, s, t, u, v, k, l, m, n, o, p, q;
35 } AMBIC;
36 
37 typedef struct {
38     OPDS    h;                                      /* required header */
39     MYFLT   *m0, *m1, *m2, *m3, *m4, *m5, *m6, *m7; /* addr outarg */
40     MYFLT   *isetup, *aw, *ax, *ay, *a[VARGMAX];    /* addr inargs */
41     /* private dataspace */
42     double  w[8], x[8], y[8], z[8], r[8], s[8], t[8], u[8],
43             v[8], k[8], l[8], m[8], n[8], o[8], p[8], q[8];
44 } AMBID;
45 
iambicode(CSOUND * csound,AMBIC * p)46 static int32_t iambicode(CSOUND *csound, AMBIC *p)
47 {
48     csound->Warning(csound,
49                     Str("bformenc is deprecated; use bformenc1 instead\n"));
50     /* check correct number of input and output arguments */
51     switch (p->OUTOCOUNT) {
52       case 4:
53 /*         { */
54 /*           /\* 2nd order *\/ */
55 /*           if (p->INOCOUNT != 5) { */
56 /*             return csound->InitError(csound, */
57 /*                                      Str("Wrong number of input arguments! " */
58 /*                                          "5 needed!")); */
59 /*           } */
60 /*           break; */
61 /*         } */
62 
63       case 9:
64 /*         { */
65 /*           /\* 3rd order *\/ */
66 /*           if (p->INOCOUNT != 6) { */
67 /*             return csound->InitError(csound, */
68 /*                                      Str("Wrong number of input arguments! " */
69 /*                                          "6 needed!")); */
70 /*           } */
71 /*           break; */
72 /*         } */
73 
74       case 16:
75 /*         { */
76 /*           /\* 4th order *\/ */
77 /*           if (p->INOCOUNT != 7) { */
78 /*             return csound->InitError(csound, */
79 /*                                      Str("Wrong number of input arguments! " */
80 /*                                          "7 needed!")); */
81 /*           } */
82 /*           break; */
83 /*         } */
84         break;
85       default:
86         {
87           return csound->InitError(csound,
88                                    Str("Wrong number of output arguments! "
89                                        "4, 9 or 16 needed!"));
90         }
91     }
92     return OK;
93 }
94 
ambicode_set_coefficients(AMBIC * p)95 static void ambicode_set_coefficients(AMBIC *p)
96 {
97     /* convert degrees to radian */
98     /* 0.017 = pi/180 */
99     double kalpha_rad = (double)(*p->kalpha)*0.0174532925199432957692369076848861;
100     double kbeta_rad = (double)(*p->kbeta)*0.0174532925199432957692369076848861;
101 
102     /* calculate ambisonic coefficients (Furse-Malham-set) */
103 
104     /* 0th order */
105     p->w = 0.707106781186547524400844362104849 /* (1.0 / sqrt(2.0)) */ ;
106 
107     /* 1st order */
108     {
109       double ck = cos(kbeta_rad);
110       p->x = cos(kalpha_rad) * ck;
111       p->y = sin(kalpha_rad) * ck;
112       p->z = sin(kbeta_rad);
113     }
114 
115     /* 2nd order */
116     p->r = 0.5 * (3.0 * p->z * p->z - 1.0);
117     p->s = 2.0 * p->x * p->z;
118     p->t = 2.0 * p->y * p->z;
119     p->u = p->x * p->x - p->y * p->y;
120     p->v = 2.0 * p->x * p->y;
121 
122     /* 3rd order */
123     p->k = 0.5 * p->z * (5.0 * p->z * p->z - 3.0);
124     p->l = (8.0 / 11.0) * p->y * (5.0 * p->z * p->z - 1.0);
125     p->m = (8.0 / 11.0) * p->x * (5.0 * p->z * p->z - 1.0);
126     p->n = 2.0 * p->x * p->y * p->z;
127     p->o = p->z * (p->x * p->x - p->y * p->y);
128     p->p = 3.0 * p->y * (3.0 * p->x * p->x - p->y * p->y);
129     p->q = 3.0 * p->x * (p->x * p->x - 3.0 * p->y * p->y);
130 }
131 
aambicode(CSOUND * csound,AMBIC * p)132 static int32_t aambicode(CSOUND *csound, AMBIC *p)
133 {
134     IGN(csound);
135     uint32_t offset = p->h.insdshead->ksmps_offset;
136     uint32_t early  = p->h.insdshead->ksmps_no_end;
137     uint32_t n, nsmps = CS_KSMPS; /* array size from orchestra */
138 
139     /* init input array pointer */
140     MYFLT *inptp = p->asig;
141 
142     /* init output array pointer 0th order */
143     MYFLT *rsltp_w = p->mw;
144 
145     /* init output array pointers 1th order */
146     MYFLT *rsltp_x = p->mx;
147     MYFLT *rsltp_y = p->my;
148     MYFLT *rsltp_z = p->mz;
149 
150     /* init output array pointers 2nd order */
151     MYFLT *rsltp_r = p->mr;
152     MYFLT *rsltp_s = p->ms;
153     MYFLT *rsltp_t = p->mt;
154     MYFLT *rsltp_u = p->mu;
155     MYFLT *rsltp_v = p->mv;
156 
157     /* init output array pointers 3rd order */
158     MYFLT *rsltp_k = p->mk;
159     MYFLT *rsltp_l = p->ml;
160     MYFLT *rsltp_m = p->mm;
161     MYFLT *rsltp_n = p->mn;
162     MYFLT *rsltp_o = p->mo;
163     MYFLT *rsltp_p = p->mp;
164     MYFLT *rsltp_q = p->mq;
165 
166     /* update coefficients */
167     ambicode_set_coefficients(p);
168 
169     if (UNLIKELY(offset)) {
170       memset(rsltp_w, '\0', offset*sizeof(MYFLT));
171       memset(rsltp_x, '\0', offset*sizeof(MYFLT));
172       memset(rsltp_y, '\0', offset*sizeof(MYFLT));
173       memset(rsltp_z, '\0', offset*sizeof(MYFLT));
174     }
175     if (UNLIKELY(early)) {
176       nsmps -= early;
177       memset(&rsltp_w[nsmps], '\0', early*sizeof(MYFLT));
178       memset(&rsltp_x[nsmps], '\0', early*sizeof(MYFLT));
179       memset(&rsltp_y[nsmps], '\0', early*sizeof(MYFLT));
180       memset(&rsltp_z[nsmps], '\0', early*sizeof(MYFLT));
181     }
182     if (p->OUTOCOUNT == 4 && p->INOCOUNT >= 5) {
183       /* 1st order */
184       for (n=offset; n<nsmps; n++) {
185         /* 0th order */
186         rsltp_w[n] = *inptp * p->w * *p->kin[0];
187 
188         /* 1st order */
189         rsltp_x[n] = inptp[n] * p->x * *p->kin[1];
190         rsltp_y[n] = inptp[n] * p->y * *p->kin[1];
191         rsltp_z[n] = inptp[n] * p->z * *p->kin[1];
192       }
193     }
194     else if (p->OUTOCOUNT == 9 && p->INOCOUNT >= 6) {
195       /* 2nd order */
196 
197       if (UNLIKELY(offset)) {
198         memset(rsltp_r, '\0', offset*sizeof(MYFLT));
199         memset(rsltp_s, '\0', offset*sizeof(MYFLT));
200         memset(rsltp_t, '\0', offset*sizeof(MYFLT));
201         memset(rsltp_u, '\0', offset*sizeof(MYFLT));
202         memset(rsltp_v, '\0', offset*sizeof(MYFLT));
203       }
204       if (UNLIKELY(early)) {
205         memset(&rsltp_r[nsmps], '\0', early*sizeof(MYFLT));
206         memset(&rsltp_s[nsmps], '\0', early*sizeof(MYFLT));
207         memset(&rsltp_t[nsmps], '\0', early*sizeof(MYFLT));
208         memset(&rsltp_u[nsmps], '\0', early*sizeof(MYFLT));
209         memset(&rsltp_v[nsmps], '\0', early*sizeof(MYFLT));
210       }
211       for (n=offset; n<nsmps; n++) {
212         /* 0th order */
213         rsltp_w[n] = inptp[n] * p->w * *p->kin[0];
214 
215         /* 1st order */
216         rsltp_x[n] = inptp[n] * p->x * *p->kin[1];
217         rsltp_y[n] = inptp[n] * p->y * *p->kin[1];
218         rsltp_z[n] = inptp[n] * p->z * *p->kin[1];
219 
220         /* 2nd order */
221         rsltp_r[n] = inptp[n] * p->r * *p->kin[2];
222         rsltp_s[n] = inptp[n] * p->s * *p->kin[2];
223         rsltp_t[n] = inptp[n] * p->t * *p->kin[2];
224         rsltp_u[n] = inptp[n] * p->u * *p->kin[2];
225         rsltp_v[n] = inptp[n] * p->v * *p->kin[2];
226 
227       }
228     }
229     else if (p->OUTOCOUNT == 16 && p->INOCOUNT >= 7) {
230       /* 3rd order */
231 
232       if (UNLIKELY(offset)) {
233         memset(rsltp_r, '\0', offset*sizeof(MYFLT));
234         memset(rsltp_s, '\0', offset*sizeof(MYFLT));
235         memset(rsltp_t, '\0', offset*sizeof(MYFLT));
236         memset(rsltp_u, '\0', offset*sizeof(MYFLT));
237         memset(rsltp_v, '\0', offset*sizeof(MYFLT));
238         memset(rsltp_k, '\0', offset*sizeof(MYFLT));
239         memset(rsltp_l, '\0', offset*sizeof(MYFLT));
240         memset(rsltp_m, '\0', offset*sizeof(MYFLT));
241         memset(rsltp_n, '\0', offset*sizeof(MYFLT));
242         memset(rsltp_o, '\0', offset*sizeof(MYFLT));
243         memset(rsltp_p, '\0', offset*sizeof(MYFLT));
244         memset(rsltp_q, '\0', offset*sizeof(MYFLT));
245       }
246       if (UNLIKELY(early)) {
247         memset(&rsltp_r[nsmps], '\0', early*sizeof(MYFLT));
248         memset(&rsltp_s[nsmps], '\0', early*sizeof(MYFLT));
249         memset(&rsltp_t[nsmps], '\0', early*sizeof(MYFLT));
250         memset(&rsltp_u[nsmps], '\0', early*sizeof(MYFLT));
251         memset(&rsltp_v[nsmps], '\0', early*sizeof(MYFLT));
252         memset(&rsltp_k[nsmps], '\0', early*sizeof(MYFLT));
253         memset(&rsltp_l[nsmps], '\0', early*sizeof(MYFLT));
254         memset(&rsltp_m[nsmps], '\0', early*sizeof(MYFLT));
255         memset(&rsltp_n[nsmps], '\0', early*sizeof(MYFLT));
256         memset(&rsltp_o[nsmps], '\0', early*sizeof(MYFLT));
257         memset(&rsltp_p[nsmps], '\0', early*sizeof(MYFLT));
258         memset(&rsltp_q[nsmps], '\0', early*sizeof(MYFLT));
259       }
260       for (n=offset; n<nsmps; n++) {
261         /* 0th order */
262         rsltp_w[n] = inptp[n] * p->w * *p->kin[0];
263 
264         /* 1st order */
265         rsltp_x[n] = inptp[n] * p->x * *p->kin[1];
266         rsltp_y[n] = inptp[n] * p->y * *p->kin[1];
267         rsltp_z[n] = inptp[n] * p->z * *p->kin[1];
268 
269         /* 2nd order */
270         rsltp_r[n] = inptp[n] * p->r * *p->kin[2];
271         rsltp_s[n] = inptp[n] * p->s * *p->kin[2];
272         rsltp_t[n] = inptp[n] * p->t * *p->kin[2];
273         rsltp_u[n] = inptp[n] * p->u * *p->kin[2];
274         rsltp_v[n] = inptp[n] * p->v * *p->kin[2];
275 
276         /* 3rd order */
277         rsltp_k[n] = inptp[n] * p->k * *p->kin[3];
278         rsltp_l[n] = inptp[n] * p->l * *p->kin[3];
279         rsltp_m[n] = inptp[n] * p->m * *p->kin[3];
280         rsltp_n[n] = inptp[n] * p->n * *p->kin[3];
281         rsltp_o[n] = inptp[n] * p->o * *p->kin[3];
282         rsltp_p[n] = inptp[n] * p->p * *p->kin[3];
283         rsltp_q[n] = inptp[n] * p->q * *p->kin[3];
284       }
285     }
286     return OK;
287 }
288 
ambideco_set_coefficients(AMBID * p,double alpha,double beta,int32_t index)289 static void ambideco_set_coefficients(AMBID *p, double alpha, double beta,
290                                       int32_t index)
291 {
292     /* convert degrees to radian */
293     /* 0.017... = pi/180 */
294     double alpha_rad = alpha * 0.0174532925199432957692369076848861;
295     double beta_rad = beta * 0.0174532925199432957692369076848861;
296 
297     /* calculate ambisonic coefficients (Furse-Malham-set) */
298 
299     /* 0th order */
300     p->w[index] = 0.707106781186547524400844362104849; /* 1/sqrt(2) */
301 
302     /* 1st order */
303     {
304       double cbeta = cos(beta_rad);
305       p->x[index] = cos(alpha_rad) * cbeta;
306       p->y[index] = sin(alpha_rad) * cbeta;
307       p->z[index] = sin(beta_rad);
308     }
309 
310     /* 2nd order */
311     p->r[index] = 0.5 * (3.0 * p->z[index] * p->z[index] - 1.0);
312     p->s[index] = 2.0 * p->x[index] * p->z[index];
313     p->t[index] = 2.0 * p->y[index] * p->z[index];
314     p->u[index] = p->x[index] * p->x[index] - p->y[index] * p->y[index];
315     p->v[index] = 2.0 * p->x[index] * p->y[index];
316 
317     /* 3rd order */
318     p->k[index] = 0.5 * p->z[index] * (5.0 * p->z[index] * p->z[index] - 3.0);
319     p->l[index] = (8.0/11.0) * p->y[index] * (5.0*p->z[index]* p->z[index] - 1.0);
320     p->m[index] = (8.0/11.0) * p->x[index] * (5.0*p->z[index]* p->z[index] - 1.0);
321     p->n[index] = 2.0 * p->x[index] * p->y[index] * p->z[index];
322     p->o[index] = p->z[index] *
323       (p->x[index] * p->x[index] - p->y[index] * p->y[index]);
324     p->p[index] = 3.0 * p->y[index] *
325       (3.0 * p->x[index] * p->x[index] - p->y[index] * p->y[index]);
326     p->q[index] = 3.0 * p->x[index] *
327       (p->x[index] * p->x[index] - 3.0 * p->y[index] * p->y[index]);
328 }
329 
iambideco(CSOUND * csound,AMBID * p)330 static int32_t iambideco(CSOUND *csound, AMBID *p)
331 {
332     int32_t setup = (int32_t)*p->isetup;
333     csound->Warning(csound,
334                     Str("bformdec is deprecated; use bformdec1 instead\n"));
335     if (setup<0) setup = -setup;
336     /* check correct number of input arguments */
337     if (UNLIKELY((p->INOCOUNT != 5)  &&
338                  (p->INOCOUNT != 10) &&
339                  (p->INOCOUNT != 17))) {
340       return csound->InitError(csound, Str("Wrong number of input arguments!"));
341     }
342 
343     switch (setup) {
344       case 1:
345         {
346           if (UNLIKELY(p->OUTOCOUNT != 2)) {
347             return csound->InitError(csound,
348                                      Str("Wrong number of output cells! "
349                                          "There must be 2 output cells."));
350           }
351           else if (*p->isetup>0) {
352             ambideco_set_coefficients(p, 330.0, 0.0, 0);    /* left */
353             ambideco_set_coefficients(p, 30.0, 0.0, 1);     /* right */
354           }
355           else {
356             int32_t i;
357             static double w[] = {0.707106781186547524400844362104849,
358                                  0.707106781186547524400844362104849};
359 /*             static double x[] = {0.0, 0.0}; */
360             static double y[] = {0.5000,-0.5000};
361 /*             static double z[] = {0.0, 0.0}; */
362 /*             static double r[] = {0.0, 0.0}; */
363 /*             static double s[] = {0.0, 0.0}; */
364 /*             static double t[] = {0.0, 0.0}; */
365 /*             static double u[] = {0.0, 0.0}; */
366 /*             static double v[] = {0.0, 0.0}; */
367             for (i=0; i<2; i++) {
368               p->w[i] = w[i];
369               p->x[i] = 0.0;
370               p->y[i] = y[i];
371               p->z[i] = 0.0;
372               p->r[i] = 0.0;
373               p->s[i] = 0.0;
374               p->t[i] = 0.0;
375               p->u[i] = 0.0;
376               p->v[i] = 0.0;
377               p->k[i] = 0.0;
378               p->l[i] = 0.0;
379               p->m[i] = 0.0;
380               p->n[i] = 0.0;
381               p->o[i] = 0.0;
382               p->p[i] = 0.0;
383               p->q[i] = 0.0;
384             }
385           }
386           break;
387         }
388 
389       case 2:
390         {
391           if (UNLIKELY(p->OUTOCOUNT != 4)) {
392             return csound->InitError(csound,
393                                      Str("Wrong number of output cells! "
394                                          "There must be 4 output cells."));
395           }
396           else if (*p->isetup>0) {
397             ambideco_set_coefficients(p, 45.0, 0.0, 0);
398             ambideco_set_coefficients(p, 135.0, 0.0, 1);
399             ambideco_set_coefficients(p, 225.0, 0.0, 2);
400             ambideco_set_coefficients(p, 315.0, 0.0, 3);
401           }
402           else {
403             int32_t i;
404             static double w[] = {0.3536, 0.3536, 0.3536, 0.3536};
405             static double x[] = {0.2434,  0.2434, -0.2434, -0.2434};
406             static double y[] = {0.2434,  -0.2434, -0.2434, 0.2434};
407 /*             static double z[] = {0.0, 0.0, 0.0, 0.0}; */
408 /*             static double r[] = {0.0, 0.0, 0.0, 0.0}; */
409 /*             static double s[] = {0.0, 0.0, 0.0, 0.0}; */
410 /*             static double t[] = {0.0, 0.0, 0.0, 0.0}; */
411 /*             static double u[] = {0.0, 0.0, 0.0, 0.0}; */
412             static double v[] = {0.0964, -0.0964, 0.0964, -0.0964};
413             for (i=0; i<4; i++) {
414               p->w[i] = w[i];
415               p->x[i] = x[i];
416               p->y[i] = y[i];
417               p->z[i] = 0.0;
418               p->r[i] = 0.0;
419               p->s[i] = 0.0;
420               p->t[i] = 0.0;
421               p->u[i] = 0.0;
422               p->v[i] = v[i];
423               p->k[i] = 0.0;
424               p->l[i] = 0.0;
425               p->m[i] = 0.0;
426               p->n[i] = 0.0;
427               p->o[i] = 0.0;
428               p->p[i] = 0.0;
429               p->q[i] = 0.0;
430             }
431           }
432           break;
433         }
434 
435       case 3: {
436         if (UNLIKELY(p->OUTOCOUNT != 5)) {
437           return csound->InitError(csound,
438                                    Str("Wrong number of output cells! "
439                                        "There must be 5 output cells."));
440         }
441         else if (*p->isetup>0) {
442           ambideco_set_coefficients(p, 330.0, 0.0, 0);  /* left */
443           ambideco_set_coefficients(p, 30.0, 0.0, 1);   /* right */
444           ambideco_set_coefficients(p, 0.0, 0.0, 2);    /* center */
445           ambideco_set_coefficients(p, 250.0, 0.0, 3);  /* surround L */
446           ambideco_set_coefficients(p, 110.0, 0.0, 4);  /* surround R */
447         }
448         else {
449           int32_t i;
450           /* Furze controlled opposites */
451           static double w[] = {0.2828, 0.2828, 0.2828, 0.2828, 0.2828};
452           static double x[] = {0.2227, -0.0851, -0.2753, -0.0851, 0.2227};
453           static double y[] = {0.1618, 0.2619, 0.0000, -0.2619, -0.1618};
454 /*           static double z[] = {0.0, 0.0, 0.0, 0.0}; */
455 /*           static double r[] = {0.0, 0.0, 0.0, 0.0}; */
456 /*           static double s[] = {0.0, 0.0, 0.0, 0.0}; */
457 /*           static double t[] = {0.0, 0.0, 0.0, 0.0}; */
458           static double u[] = {0.0238, -0.0624, 0.0771, -0.0624, 0.0238};
459           static double v[] = {0.0733, -0.0453, 0.0000, 0.0453, -0.0733};
460 
461           for (i=0; i<5; i++) {
462             p->w[i] = w[i];
463             p->x[i] = x[i];
464             p->y[i] = y[i];
465             p->z[i] = 0.0;
466             p->r[i] = 0.0;
467             p->s[i] = 0.0;
468             p->t[i] = 0.0;
469             p->u[i] = u[i];
470             p->v[i] = v[i];
471             p->k[i] = 0.0;
472             p->l[i] = 0.0;
473             p->m[i] = 0.0;
474             p->n[i] = 0.0;
475             p->o[i] = 0.0;
476             p->p[i] = 0.0;
477             p->q[i] = 0.0;
478           }
479         }
480         break;
481       }
482 
483       case 4:
484         {
485           if (UNLIKELY(p->OUTOCOUNT != 8)) {
486             return csound->InitError(csound,
487                                      Str("Wrong number of output cells! "
488                                          "There must be 8 output cells."));
489           }
490           else if (*p->isetup>0) {
491             ambideco_set_coefficients(p,  22.5, 0.0, 0);
492             ambideco_set_coefficients(p,  67.5, 0.0, 1);
493             ambideco_set_coefficients(p, 112.5, 0.0, 2);
494             ambideco_set_coefficients(p, 157.5, 0.0, 3);
495             ambideco_set_coefficients(p, 202.5, 0.0, 4);
496             ambideco_set_coefficients(p, 247.5, 0.0, 5);
497             ambideco_set_coefficients(p, 292.5, 0.0, 6);
498             ambideco_set_coefficients(p, 337.5, 0.0, 7);
499           }
500           else {
501             int32_t i;
502             static double w[] = {0.1768, 0.1768, 0.1768, 0.1768,
503                                  0.1768, 0.1768, 0.1768, 0.1768};
504             static double x[] = {0.1591, 0.0659, -0.0659,-0.1591,
505                                  -0.1591,-0.0659, 0.0659, 0.1591};
506             static double y[] = {0.0659,  0.1591, 0.1591, 0.0659,
507                                  -0.0659,-0.1591,-0.1591,-0.0659};
508 /*             static double z[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
509 /*             static double r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
510 /*             static double s[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
511 /*             static double t[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
512             static double u[] = {0.0342,-0.0342,-0.0342, 0.0342,
513                                  0.0342,-0.0342,-0.0342, 0.0342};
514             static double v[] = {0.0342, 0.0342,-0.0342,-0.0342,
515                                  0.0342, 0.0342,-0.0342,-0.0342};
516             for (i=0; i<8; i++) {
517               p->w[i] = w[i];
518               p->x[i] = x[i];
519               p->y[i] = y[i];
520               p->z[i] = 0.0;
521               p->r[i] = 0.0;
522               p->s[i] = 0.0;
523               p->t[i] = 0.0;
524               p->u[i] = u[i];
525               p->v[i] = v[i];
526               p->k[i] = 0.0;
527               p->l[i] = 0.0;
528               p->m[i] = 0.0;
529               p->n[i] = 0.0;
530               p->o[i] = 0.0;
531               p->p[i] = 0.0;
532               p->q[i] = 0.0;
533             }
534           }
535           break;
536         }
537 
538       case 5:
539         {
540           if (UNLIKELY(p->OUTOCOUNT != 8)) {
541             return csound->InitError(csound,
542                                      Str("Wrong number of output cells! "
543                                          "There must be 8 output cells."));
544           }
545           else if (*p->isetup>0) {
546             ambideco_set_coefficients(p,  45.0,  0.0, 0);
547             ambideco_set_coefficients(p,  45.0, 30.0, 1);
548             ambideco_set_coefficients(p, 135.0,  0.0, 2);
549             ambideco_set_coefficients(p, 135.0, 30.0, 3);
550             ambideco_set_coefficients(p, 225.0,  0.0, 4);
551             ambideco_set_coefficients(p, 225.0, 30.0, 5);
552             ambideco_set_coefficients(p, 315.0,  0.0, 6);
553             ambideco_set_coefficients(p, 315.0, 30.0, 7);
554           }
555           else {
556             int32_t i;
557             static double w[] = {0.1768,0.1768,0.1768,0.1768,
558                                  0.1768,0.1768,0.1768,0.1768};
559             static double x[] = {0.1140, 0.1140,-0.1140,-0.1140,
560                                  0.1140, 0.1140,-0.1140,-0.1140};
561             static double y[] = {0.1140,-0.1140,-0.1140, 0.1140,
562                                  0.1140,-0.1140,-0.1140, 0.1140};
563             static double z[] = {-0.1140,-0.1140,-0.1140,-0.1140,
564                                  0.1140, 0.1140, 0.1140, 0.1140};
565 /*             static double r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
566             static double s[] = {-0.0369,-0.0369, 0.0369, 0.0369,
567                                  0.0369, 0.0369,-0.0369,-0.0369};
568             static double t[] = {-0.0369, 0.0369, 0.0369,-0.0369,
569                                  0.0369,-0.0369,-0.0369, 0.0369};
570 /*             static double u[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; */
571             static double v[] = { 0.0369,-0.0369, 0.0369,-0.0369,
572                                   0.0369,-0.0369, 0.0369,-0.0369};
573             for (i=0; i<8; i++) {
574               p->w[i] = w[i];
575               p->x[i] = x[i];
576               p->y[i] = y[i];
577               p->z[i] = z[i];
578               p->r[i] = 0.0;
579               p->s[i] = s[i];
580               p->t[i] = t[i];
581               p->u[i] = 0.0;
582               p->v[i] = v[i];
583               p->k[i] = 0.0;
584               p->l[i] = 0.0;
585               p->m[i] = 0.0;
586               p->n[i] = 0.0;
587               p->o[i] = 0.0;
588               p->p[i] = 0.0;
589               p->q[i] = 0.0;
590             }
591           }
592          break;
593         }
594       case 6: {
595         if (UNLIKELY(p->OUTOCOUNT != 5)) {
596           return csound->InitError(csound,
597                                    Str("Wrong number of output cells! "
598                                        "There must be 5 output cells."));
599         }
600                 /*  These are Wiggins' cpefficients */
601 /*  L    30°    {0.4724,  0.7143,  0.7258,  0.0000,  0.3456}
602     R   -30°    {0.4724,  0.7143, -0.7258,  0.0000, -0.3456}
603     C   0°      {0.3226,  0.7719,  0.0000,  0.0000,  0.4724}
604    LS   110°    {0.9101, -0.7834,  0.9562, -0.0806,  0.0000}
605    RS   -110°   {0.9101, -0.7834, -0.9562, -0.0806,  0.0000}  */
606         {
607           int32_t i;
608           static double w[] = {0.4724, 0.4724, 0.3226, 0.9101, 0.9101};
609           static double x[] = {0.7143, 0.7143, 0.7719,-0.7834,-0.7834};
610           static double y[] = {0.7258,-0.7258, 0.0000, 0.9562,-0.9562};
611           static double u[] = {0.0000,0.0000,0.0000,-0.0806,-0.0806};
612           static double v[] = {0.3456,-0.3456,0.4724,0.0000,0.0000};
613           for (i=0; i<5; i++) {
614             p->w[i] = w[i];
615             p->x[i] = x[i];
616             p->y[i] = y[i];
617             p->z[i] = 0.0;
618             p->r[i] = 0.0;
619             p->s[i] = 0.0;
620             p->t[i] = 0.0;
621             p->u[i] = u[i];
622             p->v[i] = v[i];
623             p->k[i] = 0.0;
624             p->l[i] = 0.0;
625             p->m[i] = 0.0;
626             p->n[i] = 0.0;
627             p->o[i] = 0.0;
628             p->p[i] = 0.0;
629             p->q[i] = 0.0;
630           }
631         }
632         break;
633       }
634 
635       default:
636         return csound->InitError(csound, Str("Not supported setup number!"));
637     }
638     return OK;
639 }
640 
aambideco(CSOUND * csound,AMBID * p)641 static int32_t aambideco(CSOUND *csound, AMBID *p)
642 {
643      IGN(csound);
644     uint32_t offset = p->h.insdshead->ksmps_offset;
645     uint32_t early  = p->h.insdshead->ksmps_no_end;
646     uint32_t i=0, n, nsmps = CS_KSMPS;
647 
648     /* init input array pointer 0th order */
649     MYFLT *inptp_w = p->aw;
650 
651     /* init input array pointer 1st order */
652     MYFLT *inptp_x = p->ax;
653     MYFLT *inptp_y = p->ay;
654     MYFLT *inptp_z = p->a[0];
655 
656     /* init input array pointer 2nd order */
657     MYFLT *inptp_r = p->a[1];
658     MYFLT *inptp_s = p->a[2];
659     MYFLT *inptp_t = p->a[3];
660     MYFLT *inptp_u = p->a[4];
661     MYFLT *inptp_v = p->a[5];
662 
663     /* init input array pointer 3rd order */
664     MYFLT *inptp_k = p->a[6];
665     MYFLT *inptp_l = p->a[7];
666     MYFLT *inptp_m = p->a[8];
667     MYFLT *inptp_n = p->a[9];
668     MYFLT *inptp_o = p->a[10];
669     MYFLT *inptp_p = p->a[11];
670     MYFLT *inptp_q = p->a[12];
671 
672     /* init output array pointer */
673     MYFLT *rsltp[8];
674 
675     rsltp[0] = p->m0;
676     rsltp[1] = p->m1;
677     rsltp[2] = p->m2;
678     rsltp[3] = p->m3;
679     rsltp[4] = p->m4;
680     rsltp[5] = p->m5;
681     rsltp[6] = p->m6;
682     rsltp[7] = p->m7;
683     if (UNLIKELY(offset)) for (i = 0; i < p->OUTOCOUNT; i++)
684                   memset(rsltp[i], '\0', offset*sizeof(MYFLT));
685     if (UNLIKELY(early)) {
686       nsmps -= early;
687       for (i = 0; i < p->OUTOCOUNT; i++)
688         memset(&rsltp[i][nsmps], '\0', early*sizeof(MYFLT));
689     }
690     /* L = 0.5 * (0.9397*W + 0.1856*X - j*0.342*W + j*0.5099*X + 0.655*Y)
691 
692        R = 0.5 * (0.9397*W+ 0.1856*X + j*0.342*W - j*0.5099*X - 0.655*Y) */
693     if (p->INOCOUNT == 5) {
694       for (n=offset; n<nsmps; n++) {
695         /* 1st order */
696         for (i = 0; i < p->OUTOCOUNT; i++) {
697           /* calculate output for every used loudspeaker */
698           rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] +
699                         inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i];
700         }
701       }
702     }
703     else if (p->INOCOUNT == 10) {
704       for (n=offset; n<nsmps; n++) {
705         /* 2nd order */
706         for (i = 0; i < p->OUTOCOUNT; i++) {
707           /* calculate output for every used loudspeaker */
708           rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] +
709                         inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i] +
710                         inptp_r[n] * p->r[i] + inptp_s[n] * p->s[i] +
711                         inptp_t[n] * p->t[i] + inptp_u[n] * p->u[i] +
712                         inptp_v[n] * p->v[i];
713         }
714       }
715     }
716     else if (p->INOCOUNT == 17) {
717       for (n=offset; n<nsmps; n++) {
718         /* 3rd order */
719         for (i = 0; i < p->OUTOCOUNT; i++) {
720           /* calculate output for every used loudspeaker */
721           rsltp[i][n] = inptp_w[n] * p->w[i] + inptp_x[n] * p->x[i] +
722                         inptp_y[n] * p->y[i] + inptp_z[n] * p->z[i] +
723                         inptp_r[n] * p->r[i] + inptp_s[n] * p->s[i] +
724                         inptp_t[n] * p->t[i] + inptp_u[n] * p->u[i] +
725                         inptp_v[n] * p->v[i] + inptp_k[n] * p->k[i] +
726                         inptp_l[n] * p->l[i] + inptp_m[n] * p->m[i] +
727                         inptp_n[n] * p->n[i] + inptp_o[n] * p->o[i] +
728                         inptp_p[n] * p->p[i] + inptp_q[n] * p->q[i];
729         }
730       }
731     }
732     return OK;
733 }
734 
735 #define S(x)    sizeof(x)
736 
737 static OENTRY localops[] = {
738   { "bformenc", S(AMBIC), _QQ, 3, "mmmmmmmmmmmmmmmm", "akkPPPP",
739                             (SUBR)iambicode,  (SUBR)aambicode },
740   { "bformdec", S(AMBID), _QQ, 3, "mmmmmmmm", "iaaay",
741                             (SUBR)iambideco, (SUBR)aambideco }
742 };
743 
ambicode_init_(CSOUND * csound)744 int32_t ambicode_init_(CSOUND *csound)
745 {
746     return csound->AppendOpcodes(csound, &(localops[0]),
747                                  (int32_t
748                                   ) (sizeof(localops) / sizeof(OENTRY)));
749 }
750