4 #include "bformatdec.h"
11 typedef struct BandSplitter
{
18 static void bandsplit_init(BandSplitter
*splitter
, ALfloat freq_mult
)
20 ALfloat w
= freq_mult
* F_TAU
;
23 splitter
->coeff
= (sinf(w
) - 1.0f
) / cw
;
25 splitter
->coeff
= cw
* -0.5f
;
27 splitter
->lp_z1
= 0.0f
;
28 splitter
->lp_z2
= 0.0f
;
29 splitter
->hp_z1
= 0.0f
;
32 static void bandsplit_process(BandSplitter
*splitter
, ALfloat
*restrict hpout
, ALfloat
*restrict lpout
,
33 const ALfloat
*input
, ALuint count
)
38 coeff
= splitter
->coeff
*0.5f
+ 0.5f
;
39 for(i
= 0;i
< count
;i
++)
43 d
= (x
- splitter
->lp_z1
) * coeff
;
44 x
= splitter
->lp_z1
+ d
;
45 splitter
->lp_z1
= x
+ d
;
47 d
= (x
- splitter
->lp_z2
) * coeff
;
48 x
= splitter
->lp_z2
+ d
;
49 splitter
->lp_z2
= x
+ d
;
54 coeff
= splitter
->coeff
;
55 for(i
= 0;i
< count
;i
++)
59 d
= x
- coeff
*splitter
->hp_z1
;
60 x
= splitter
->hp_z1
+ coeff
*d
;
63 hpout
[i
] = x
- lpout
[i
];
68 static const ALfloat UnitScale
[MAX_AMBI_COEFFS
] = {
69 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
,
70 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
, 1.0f
72 static const ALfloat SN3D2N3DScale
[MAX_AMBI_COEFFS
] = {
73 1.000000000f
, /* ACN 0 (W), sqrt(1) */
74 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
75 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
76 1.732050808f
, /* ACN 3 (X), sqrt(3) */
77 2.236067978f
, /* ACN 4 (V), sqrt(5) */
78 2.236067978f
, /* ACN 5 (T), sqrt(5) */
79 2.236067978f
, /* ACN 6 (R), sqrt(5) */
80 2.236067978f
, /* ACN 7 (S), sqrt(5) */
81 2.236067978f
, /* ACN 8 (U), sqrt(5) */
82 2.645751311f
, /* ACN 9 (Q), sqrt(7) */
83 2.645751311f
, /* ACN 10 (O), sqrt(7) */
84 2.645751311f
, /* ACN 11 (M), sqrt(7) */
85 2.645751311f
, /* ACN 12 (K), sqrt(7) */
86 2.645751311f
, /* ACN 13 (L), sqrt(7) */
87 2.645751311f
, /* ACN 14 (N), sqrt(7) */
88 2.645751311f
, /* ACN 15 (P), sqrt(7) */
90 static const ALfloat FuMa2N3DScale
[MAX_AMBI_COEFFS
] = {
91 1.414213562f
, /* ACN 0 (W), sqrt(2) */
92 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
93 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
94 1.732050808f
, /* ACN 3 (X), sqrt(3) */
95 1.936491673f
, /* ACN 4 (V), sqrt(15)/2 */
96 1.936491673f
, /* ACN 5 (T), sqrt(15)/2 */
97 2.236067978f
, /* ACN 6 (R), sqrt(5) */
98 1.936491673f
, /* ACN 7 (S), sqrt(15)/2 */
99 1.936491673f
, /* ACN 8 (U), sqrt(15)/2 */
100 2.091650066f
, /* ACN 9 (Q), sqrt(35/8) */
101 1.972026594f
, /* ACN 10 (O), sqrt(35)/3 */
102 2.231093404f
, /* ACN 11 (M), sqrt(224/45) */
103 2.645751311f
, /* ACN 12 (K), sqrt(7) */
104 2.231093404f
, /* ACN 13 (L), sqrt(224/45) */
105 1.972026594f
, /* ACN 14 (N), sqrt(35)/3 */
106 2.091650066f
, /* ACN 15 (P), sqrt(35/8) */
110 static const ALfloat SquareMatrixHF
[4][MAX_AMBI_COEFFS
] = {
111 { 0.353553f
, 0.204094f
, 0.0f
, 0.204094f
},
112 { 0.353553f
, -0.204094f
, 0.0f
, 0.204094f
},
113 { 0.353553f
, 0.204094f
, 0.0f
, -0.204094f
},
114 { 0.353553f
, -0.204094f
, 0.0f
, -0.204094f
},
116 static ALfloat SquareEncoder
[4][MAX_AMBI_COEFFS
];
118 static const ALfloat CubeMatrixHF
[8][MAX_AMBI_COEFFS
] = {
119 { 0.25f
, 0.14425f
, 0.14425f
, 0.14425f
},
120 { 0.25f
, -0.14425f
, 0.14425f
, 0.14425f
},
121 { 0.25f
, 0.14425f
, 0.14425f
, -0.14425f
},
122 { 0.25f
, -0.14425f
, 0.14425f
, -0.14425f
},
123 { 0.25f
, 0.14425f
, -0.14425f
, 0.14425f
},
124 { 0.25f
, -0.14425f
, -0.14425f
, 0.14425f
},
125 { 0.25f
, 0.14425f
, -0.14425f
, -0.14425f
},
126 { 0.25f
, -0.14425f
, -0.14425f
, -0.14425f
},
128 static ALfloat CubeEncoder
[8][MAX_AMBI_COEFFS
];
130 static alonce_flag encoder_inited
= AL_ONCE_FLAG_INIT
;
132 static void init_encoder(void)
136 CalcXYZCoeffs(-0.577350269f
, 0.577350269f
, -0.577350269f
, CubeEncoder
[0]);
137 CalcXYZCoeffs( 0.577350269f
, 0.577350269f
, -0.577350269f
, CubeEncoder
[1]);
138 CalcXYZCoeffs(-0.577350269f
, 0.577350269f
, 0.577350269f
, CubeEncoder
[2]);
139 CalcXYZCoeffs( 0.577350269f
, 0.577350269f
, 0.577350269f
, CubeEncoder
[3]);
140 CalcXYZCoeffs(-0.577350269f
, -0.577350269f
, -0.577350269f
, CubeEncoder
[4]);
141 CalcXYZCoeffs( 0.577350269f
, -0.577350269f
, -0.577350269f
, CubeEncoder
[5]);
142 CalcXYZCoeffs(-0.577350269f
, -0.577350269f
, 0.577350269f
, CubeEncoder
[6]);
143 CalcXYZCoeffs( 0.577350269f
, -0.577350269f
, 0.577350269f
, CubeEncoder
[7]);
145 CalcXYZCoeffs(-0.707106781f
, 0.0f
, -0.707106781f
, SquareEncoder
[0]);
146 CalcXYZCoeffs( 0.707106781f
, 0.0f
, -0.707106781f
, SquareEncoder
[1]);
147 CalcXYZCoeffs(-0.707106781f
, 0.0f
, 0.707106781f
, SquareEncoder
[2]);
148 CalcXYZCoeffs( 0.707106781f
, 0.0f
, 0.707106781f
, SquareEncoder
[3]);
152 /* Remove the skipped height-related coefficients for 2D rendering. */
153 SquareEncoder
[i
][2] = SquareEncoder
[i
][3];
154 SquareEncoder
[i
][3] = SquareEncoder
[i
][4];
155 SquareEncoder
[i
][4] = SquareEncoder
[i
][8];
156 SquareEncoder
[i
][5] = SquareEncoder
[i
][9];
157 SquareEncoder
[i
][6] = SquareEncoder
[i
][15];
158 for(j
= 7;j
< MAX_AMBI_COEFFS
;j
++)
159 SquareEncoder
[i
][j
] = 0.0f
;
164 /* NOTE: Low-frequency (LF) fields and BandSplitter filters are unused with
165 * single-band decoding
167 typedef struct BFormatDec
{
168 alignas(16) ALfloat MatrixHF
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
169 alignas(16) ALfloat MatrixLF
[MAX_OUTPUT_CHANNELS
][MAX_AMBI_COEFFS
];
171 BandSplitter XOver
[MAX_AMBI_COEFFS
];
173 ALfloat (*Samples
)[BUFFERSIZE
];
174 /* These two alias into Samples */
175 ALfloat (*SamplesHF
)[BUFFERSIZE
];
176 ALfloat (*SamplesLF
)[BUFFERSIZE
];
179 const ALfloat (*restrict MatrixHF
)[MAX_AMBI_COEFFS
];
180 const ALfloat (*restrict Encoder
)[MAX_AMBI_COEFFS
];
186 ALboolean Periphonic
;
189 BFormatDec
*bformatdec_alloc()
191 alcall_once(&encoder_inited
, init_encoder
);
192 return al_calloc(16, sizeof(BFormatDec
));
195 void bformatdec_free(BFormatDec
*dec
)
199 al_free(dec
->Samples
);
201 dec
->SamplesHF
= NULL
;
202 dec
->SamplesLF
= NULL
;
204 memset(dec
, 0, sizeof(*dec
));
209 int bformatdec_getOrder(const struct BFormatDec
*dec
)
213 if(dec
->NumChannels
> 9) return 3;
214 if(dec
->NumChannels
> 4) return 2;
215 if(dec
->NumChannels
> 1) return 1;
219 if(dec
->NumChannels
> 5) return 3;
220 if(dec
->NumChannels
> 3) return 2;
221 if(dec
->NumChannels
> 1) return 1;
226 void bformatdec_reset(BFormatDec
*dec
, const AmbDecConf
*conf
, ALuint chancount
, ALuint srate
, const ALuint chanmap
[MAX_OUTPUT_CHANNELS
])
228 static const ALuint map2DTo3D
[7] = {
231 const ALfloat
*coeff_scale
= UnitScale
;
235 al_free(dec
->Samples
);
237 dec
->SamplesHF
= NULL
;
238 dec
->SamplesLF
= NULL
;
240 dec
->NumChannels
= chancount
;
241 dec
->Samples
= al_calloc(16, dec
->NumChannels
* conf
->FreqBands
*
242 sizeof(dec
->Samples
[0]));
243 dec
->SamplesHF
= dec
->Samples
;
244 dec
->SamplesLF
= dec
->SamplesHF
+ dec
->NumChannels
;
246 if(conf
->CoeffScale
== ADS_SN3D
)
247 coeff_scale
= SN3D2N3DScale
;
248 else if(conf
->CoeffScale
== ADS_FuMa
)
249 coeff_scale
= FuMa2N3DScale
;
251 if((conf
->ChanMask
& ~0x831b))
253 dec
->UpSampler
.MatrixHF
= CubeMatrixHF
;
254 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])CubeEncoder
;
255 dec
->UpSampler
.NumChannels
= 8;
256 dec
->Periphonic
= AL_TRUE
;
260 dec
->UpSampler
.MatrixHF
= SquareMatrixHF
;
261 dec
->UpSampler
.Encoder
= (const ALfloat(*)[MAX_AMBI_COEFFS
])SquareEncoder
;
262 dec
->UpSampler
.NumChannels
= 4;
263 dec
->Periphonic
= AL_FALSE
;
266 if(conf
->FreqBands
== 1)
268 dec
->DualBand
= AL_FALSE
;
273 dec
->DualBand
= AL_TRUE
;
275 ratio
= conf
->XOverFreq
/ (ALfloat
)srate
;
276 for(i
= 0;i
< MAX_AMBI_COEFFS
;i
++)
277 bandsplit_init(&dec
->XOver
[i
], ratio
);
279 ratio
= powf(10.0f
, conf
->XOverRatio
/ 40.0f
);
280 memset(dec
->MatrixLF
, 0, sizeof(dec
->MatrixLF
));
281 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
283 ALuint chan
= chanmap
[i
];
291 ALuint l
= map2DTo3D
[j
];
292 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
293 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
294 else if(j
== 3) gain
= conf
->LFOrderGain
[2] / ratio
;
295 else if(j
== 5) gain
= conf
->LFOrderGain
[3] / ratio
;
296 if((conf
->ChanMask
&(1<<l
)))
297 dec
->MatrixLF
[chan
][j
] = conf
->LFMatrix
[i
][k
++] / coeff_scale
[l
] * gain
;
302 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
304 if(j
== 0) gain
= conf
->LFOrderGain
[0] / ratio
;
305 else if(j
== 1) gain
= conf
->LFOrderGain
[1] / ratio
;
306 else if(j
== 4) gain
= conf
->LFOrderGain
[2] / ratio
;
307 else if(j
== 9) gain
= conf
->LFOrderGain
[3] / ratio
;
308 if((conf
->ChanMask
&(1<<j
)))
309 dec
->MatrixLF
[chan
][j
] = conf
->LFMatrix
[i
][k
++] / coeff_scale
[j
] * gain
;
315 memset(dec
->MatrixHF
, 0, sizeof(dec
->MatrixHF
));
316 for(i
= 0;i
< conf
->NumSpeakers
;i
++)
318 ALuint chan
= chanmap
[i
];
326 ALuint l
= map2DTo3D
[j
];
327 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
328 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
329 else if(j
== 3) gain
= conf
->HFOrderGain
[2] * ratio
;
330 else if(j
== 5) gain
= conf
->HFOrderGain
[3] * ratio
;
331 if((conf
->ChanMask
&(1<<l
)))
332 dec
->MatrixHF
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[l
] * gain
;
337 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
339 if(j
== 0) gain
= conf
->HFOrderGain
[0] * ratio
;
340 else if(j
== 1) gain
= conf
->HFOrderGain
[1] * ratio
;
341 else if(j
== 4) gain
= conf
->HFOrderGain
[2] * ratio
;
342 else if(j
== 9) gain
= conf
->HFOrderGain
[3] * ratio
;
343 if((conf
->ChanMask
&(1<<j
)))
344 dec
->MatrixHF
[chan
][j
] = conf
->HFMatrix
[i
][k
++] / coeff_scale
[j
] * gain
;
351 static void apply_row(ALfloat
*out
, const ALfloat
*mtx
, ALfloat (*restrict in
)[BUFFERSIZE
], ALuint inchans
, ALuint todo
)
355 for(c
= 0;c
< inchans
;c
++)
357 ALfloat gain
= mtx
[c
];
358 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
360 for(i
= 0;i
< todo
;i
++)
361 out
[i
] += in
[c
][i
] * gain
;
365 void bformatdec_process(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALuint OutChannels
, ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint SamplesToDo
)
371 for(i
= 0;i
< dec
->NumChannels
;i
++)
372 bandsplit_process(&dec
->XOver
[i
], dec
->SamplesHF
[i
], dec
->SamplesLF
[i
],
373 InSamples
[i
], SamplesToDo
);
375 for(chan
= 0;chan
< OutChannels
;chan
++)
377 apply_row(OutBuffer
[chan
], dec
->MatrixHF
[chan
], dec
->SamplesHF
,
378 dec
->NumChannels
, SamplesToDo
);
379 apply_row(OutBuffer
[chan
], dec
->MatrixLF
[chan
], dec
->SamplesLF
,
380 dec
->NumChannels
, SamplesToDo
);
385 for(chan
= 0;chan
< OutChannels
;chan
++)
386 apply_row(OutBuffer
[chan
], dec
->MatrixHF
[chan
], InSamples
,
387 dec
->NumChannels
, SamplesToDo
);
392 void bformatdec_upSample(struct BFormatDec
*dec
, ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALfloat (*restrict InSamples
)[BUFFERSIZE
], ALuint InChannels
, ALuint SamplesToDo
)
396 /* This up-sampler is very simplistic. It essentially decodes the first-
397 * order content to a square channel array (or cube if height is desired),
398 * then encodes those points onto the higher order soundfield.
400 for(k
= 0;k
< dec
->UpSampler
.NumChannels
;k
++)
402 memset(dec
->Samples
[0], 0, SamplesToDo
*sizeof(ALfloat
));
403 apply_row(dec
->Samples
[0], dec
->UpSampler
.MatrixHF
[k
], InSamples
,
404 InChannels
, SamplesToDo
);
406 for(j
= 0;j
< dec
->NumChannels
;j
++)
408 ALfloat gain
= dec
->UpSampler
.Encoder
[k
][j
];
409 if(!(fabsf(gain
) > GAIN_SILENCE_THRESHOLD
))
411 for(i
= 0;i
< SamplesToDo
;i
++)
412 OutBuffer
[j
][i
] += dec
->Samples
[0][i
] * gain
;