112 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { { |
113 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { { |
113 GST_AUDIO_CHANNEL_POSITION_INVALID}} |
114 GST_AUDIO_CHANNEL_POSITION_INVALID}} |
114 }; |
115 }; |
115 gint c; |
116 gint c; |
116 |
117 |
117 /* conversions from compatible (but not the same) channel schemes. This |
118 /* conversions from compatible (but not the same) channel schemes */ |
118 * goes two ways: if the sink has both pos1[0,1] and src has pos2[0] or |
|
119 * if the src has both pos1[0,1] and sink has pos2[0], then we do the |
|
120 * conversion. We hereby assume that the existance of pos1[0,1] and |
|
121 * pos2[0] are mututally exclusive. There are no checks for that, |
|
122 * unfortunately. This shouldn't lead to issues (like crashes or so), |
|
123 * though. */ |
|
124 for (c = 0; conv[c].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; c++) { |
119 for (c = 0; conv[c].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; c++) { |
125 gint pos1_0 = -1, pos1_1 = -1, pos2_0 = -1, n; |
120 gint pos1_0 = -1, pos1_1 = -1, pos1_2 = -1; |
126 |
121 gint pos2_0 = -1, pos2_1 = -1, pos2_2 = -1; |
127 /* Try to go from the given 2 channels to the given 1 channel */ |
122 gint n; |
|
123 |
128 for (n = 0; n < this->in.channels; n++) { |
124 for (n = 0; n < this->in.channels; n++) { |
129 if (this->in.pos[n] == conv[c].pos1[0]) |
125 if (this->in.pos[n] == conv[c].pos1[0]) |
130 pos1_0 = n; |
126 pos1_0 = n; |
131 else if (this->in.pos[n] == conv[c].pos1[1]) |
127 else if (this->in.pos[n] == conv[c].pos1[1]) |
132 pos1_1 = n; |
128 pos1_1 = n; |
133 } |
129 else if (this->in.pos[n] == conv[c].pos2[0]) |
134 for (n = 0; n < this->out.channels; n++) { |
130 pos1_2 = n; |
135 if (this->out.pos[n] == conv[c].pos2[0]) |
131 } |
136 pos2_0 = n; |
|
137 } |
|
138 |
|
139 if (pos1_0 != -1 && pos1_1 != -1 && pos2_0 != -1) { |
|
140 this->matrix[pos1_0][pos2_0] = 1.0; |
|
141 this->matrix[pos1_1][pos2_0] = 1.0; |
|
142 } |
|
143 |
|
144 /* Try to go from the given 1 channel to the given 2 channels */ |
|
145 pos1_0 = -1; |
|
146 pos1_1 = -1; |
|
147 pos2_0 = -1; |
|
148 |
|
149 for (n = 0; n < this->out.channels; n++) { |
132 for (n = 0; n < this->out.channels; n++) { |
150 if (this->out.pos[n] == conv[c].pos1[0]) |
133 if (this->out.pos[n] == conv[c].pos1[0]) |
151 pos1_0 = n; |
134 pos2_0 = n; |
152 else if (this->out.pos[n] == conv[c].pos1[1]) |
135 else if (this->out.pos[n] == conv[c].pos1[1]) |
153 pos1_1 = n; |
136 pos2_1 = n; |
154 } |
137 else if (this->out.pos[n] == conv[c].pos2[0]) |
155 for (n = 0; n < this->in.channels; n++) { |
138 pos2_2 = n; |
156 if (this->in.pos[n] == conv[c].pos2[0]) |
139 } |
157 pos2_0 = n; |
140 |
158 } |
141 /* The general idea here is to fill in channels from the same position |
159 |
142 * as good as possible. This means mixing left<->center and right<->center. |
160 if (pos1_0 != -1 && pos1_1 != -1 && pos2_0 != -1) { |
143 */ |
161 this->matrix[pos2_0][pos1_0] = 1.0; |
144 |
162 this->matrix[pos2_0][pos1_1] = 1.0; |
145 /* left -> center */ |
163 } |
146 if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 == -1 && pos2_2 != -1) |
|
147 this->matrix[pos1_0][pos2_2] = 1.0; |
|
148 else if (pos1_0 != -1 && pos1_2 != -1 && pos2_0 == -1 && pos2_2 != -1) |
|
149 this->matrix[pos1_0][pos2_2] = 0.5; |
|
150 else if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 != -1 && pos2_2 != -1) |
|
151 this->matrix[pos1_0][pos2_2] = 1.0; |
|
152 |
|
153 /* right -> center */ |
|
154 if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 == -1 && pos2_2 != -1) |
|
155 this->matrix[pos1_1][pos2_2] = 1.0; |
|
156 else if (pos1_1 != -1 && pos1_2 != -1 && pos2_1 == -1 && pos2_2 != -1) |
|
157 this->matrix[pos1_1][pos2_2] = 0.5; |
|
158 else if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 != -1 && pos2_2 != -1) |
|
159 this->matrix[pos1_1][pos2_2] = 1.0; |
|
160 |
|
161 /* center -> left */ |
|
162 if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 == -1 && pos2_0 != -1) |
|
163 this->matrix[pos1_2][pos2_0] = 1.0; |
|
164 else if (pos1_2 != -1 && pos1_0 != -1 && pos2_2 == -1 && pos2_0 != -1) |
|
165 this->matrix[pos1_2][pos2_0] = 0.5; |
|
166 else if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 != -1 && pos2_0 != -1) |
|
167 this->matrix[pos1_2][pos2_0] = 1.0; |
|
168 |
|
169 /* center -> right */ |
|
170 if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 == -1 && pos2_1 != -1) |
|
171 this->matrix[pos1_2][pos2_1] = 1.0; |
|
172 else if (pos1_2 != -1 && pos1_1 != -1 && pos2_2 == -1 && pos2_1 != -1) |
|
173 this->matrix[pos1_2][pos2_1] = 0.5; |
|
174 else if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 != -1 && pos2_1 != -1) |
|
175 this->matrix[pos1_2][pos2_1] = 1.0; |
164 } |
176 } |
165 } |
177 } |
166 |
178 |
167 /* |
179 /* |
168 * Detect and fill in channels not handled by the |
180 * Detect and fill in channels not handled by the |
182 gint n; |
194 gint n; |
183 |
195 |
184 for (n = 0; n < caps->channels; n++) { |
196 for (n = 0; n < caps->channels; n++) { |
185 switch (caps->pos[n]) { |
197 switch (caps->pos[n]) { |
186 case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO: |
198 case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO: |
|
199 f[1] = n; |
|
200 *has_f = TRUE; |
|
201 break; |
187 case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: |
202 case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: |
|
203 f[0] = n; |
|
204 *has_f = TRUE; |
|
205 break; |
188 case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: |
206 case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: |
|
207 f[2] = n; |
189 *has_f = TRUE; |
208 *has_f = TRUE; |
190 if (f[0] == -1) |
|
191 f[0] = n; |
|
192 else |
|
193 f[1] = n; |
|
194 break; |
209 break; |
195 case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: |
210 case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: |
|
211 c[1] = n; |
|
212 *has_c = TRUE; |
|
213 break; |
196 case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: |
214 case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: |
|
215 c[0] = n; |
|
216 *has_c = TRUE; |
|
217 break; |
197 case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: |
218 case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: |
|
219 c[2] = n; |
198 *has_c = TRUE; |
220 *has_c = TRUE; |
199 if (c[0] == -1) |
|
200 c[0] = n; |
|
201 else |
|
202 c[1] = n; |
|
203 break; |
221 break; |
204 case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: |
222 case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: |
|
223 r[1] = n; |
|
224 *has_r = TRUE; |
|
225 break; |
205 case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: |
226 case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: |
|
227 r[0] = n; |
|
228 *has_r = TRUE; |
|
229 break; |
206 case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: |
230 case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: |
|
231 r[2] = n; |
207 *has_r = TRUE; |
232 *has_r = TRUE; |
208 if (r[0] == -1) |
|
209 r[0] = n; |
|
210 else |
|
211 r[1] = n; |
|
212 break; |
233 break; |
213 case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: |
234 case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: |
|
235 s[0] = n; |
|
236 *has_s = TRUE; |
|
237 break; |
214 case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: |
238 case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: |
|
239 s[2] = n; |
215 *has_s = TRUE; |
240 *has_s = TRUE; |
216 if (s[0] == -1) |
|
217 s[0] = n; |
|
218 else |
|
219 s[1] = n; |
|
220 break; |
241 break; |
221 case GST_AUDIO_CHANNEL_POSITION_LFE: |
242 case GST_AUDIO_CHANNEL_POSITION_LFE: |
222 *has_b = TRUE; |
243 *has_b = TRUE; |
223 b[0] = n; |
244 b[1] = n; |
224 break; |
245 break; |
225 default: |
246 default: |
226 break; |
247 break; |
227 } |
248 } |
228 } |
249 } |
229 } |
250 } |
230 |
251 |
231 static void |
252 static void |
232 gst_channel_mix_fill_one_other (gfloat ** matrix, |
253 gst_channel_mix_fill_one_other (gfloat ** matrix, |
233 AudioConvertFmt * from_caps, gint * from_idx, |
254 AudioConvertFmt * from_caps, gint * from_idx, |
234 GstAudioChannelPosition from_pos_l, |
255 AudioConvertFmt * to_caps, gint * to_idx, gfloat ratio) |
235 GstAudioChannelPosition from_pos_r, |
256 { |
236 GstAudioChannelPosition from_pos_c, |
257 |
237 AudioConvertFmt * to_caps, gint * to_idx, |
258 /* src & dst have center => passthrough */ |
238 GstAudioChannelPosition to_pos_l, |
259 if (from_idx[1] != -1 && to_idx[1] != -1) { |
239 GstAudioChannelPosition to_pos_r, |
260 matrix[from_idx[1]][to_idx[1]] = ratio; |
240 GstAudioChannelPosition to_pos_c, gfloat ratio) |
261 } |
241 { |
262 |
242 gfloat in_r, out_r[2] = { 0.f, 0.f }; |
263 /* src & dst have left => passthrough */ |
243 |
264 if (from_idx[0] != -1 && to_idx[0] != -1) { |
244 /* |
265 matrix[from_idx[0]][to_idx[0]] = ratio; |
245 * The idea is that we add up from the input (which means that if we |
266 } |
246 * have stereo input, we divide their sum by two) and put that in |
267 |
247 * the matrix for their output ratio (given in $ratio). |
268 /* src & dst have right => passthrough */ |
248 * For left channels, we need to invert the signal sign (* -1). |
269 if (from_idx[2] != -1 && to_idx[2] != -1) { |
249 */ |
270 matrix[from_idx[2]][to_idx[2]] = ratio; |
250 |
271 } |
251 if (from_caps->pos[from_idx[0]] == from_pos_c) |
272 |
252 in_r = 1.0; |
273 /* src has left & dst has center => put into center */ |
253 else |
274 if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] != -1) { |
254 in_r = 0.5; |
275 matrix[from_idx[0]][to_idx[1]] = 0.5 * ratio; |
255 |
276 } else if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] == -1) { |
256 if (to_caps->pos[to_idx[0]] == to_pos_l) |
277 matrix[from_idx[0]][to_idx[1]] = ratio; |
257 out_r[0] = in_r * -ratio; |
278 } |
258 else |
279 |
259 out_r[0] = in_r * ratio; |
280 /* src has right & dst has center => put into center */ |
260 |
281 if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] != -1) { |
261 if (to_idx[1] != -1) { |
282 matrix[from_idx[2]][to_idx[1]] = 0.5 * ratio; |
262 if (to_caps->pos[to_idx[1]] == to_pos_l) |
283 } else if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] == -1) { |
263 out_r[1] = in_r * -ratio; |
284 matrix[from_idx[2]][to_idx[1]] = ratio; |
264 else |
285 } |
265 out_r[1] = in_r * ratio; |
286 |
266 } |
287 /* src has center & dst has left => passthrough */ |
267 |
288 if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] != -1) { |
268 matrix[from_idx[0]][to_idx[0]] = out_r[0]; |
289 matrix[from_idx[1]][to_idx[0]] = 0.5 * ratio; |
269 if (to_idx[1] != -1) |
290 } else if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] == -1) { |
270 matrix[from_idx[0]][to_idx[1]] = out_r[1]; |
291 matrix[from_idx[1]][to_idx[0]] = ratio; |
271 if (from_idx[1] != -1) { |
292 } |
272 matrix[from_idx[1]][to_idx[0]] = out_r[0]; |
293 |
273 if (to_idx[1] != -1) |
294 /* src has center & dst has right => passthrough */ |
274 matrix[from_idx[1]][to_idx[1]] = out_r[1]; |
295 if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] != -1) { |
275 } |
296 matrix[from_idx[1]][to_idx[2]] = 0.5 * ratio; |
276 } |
297 } else if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] == -1) { |
|
298 matrix[from_idx[1]][to_idx[2]] = ratio; |
|
299 } |
|
300 } |
|
301 |
|
302 #define RATIO_CENTER_FRONT (1.0 / sqrt (2.0)) |
|
303 #define RATIO_CENTER_SIDE (1.0 / 2.0) |
|
304 #define RATIO_CENTER_REAR (1.0 / sqrt (8.0)) |
277 |
305 |
278 #define RATIO_FRONT_CENTER (1.0 / sqrt (2.0)) |
306 #define RATIO_FRONT_CENTER (1.0 / sqrt (2.0)) |
279 #define RATIO_FRONT_REAR (1.0 / sqrt (2.0)) |
307 #define RATIO_FRONT_SIDE (1.0 / sqrt (2.0)) |
|
308 #define RATIO_FRONT_REAR (1.0 / 2.0) |
|
309 |
|
310 #define RATIO_SIDE_CENTER (1.0 / 2.0) |
|
311 #define RATIO_SIDE_FRONT (1.0 / sqrt (2.0)) |
|
312 #define RATIO_SIDE_REAR (1.0 / sqrt (2.0)) |
|
313 |
|
314 #define RATIO_CENTER_BASS (1.0 / sqrt (2.0)) |
280 #define RATIO_FRONT_BASS (1.0) |
315 #define RATIO_FRONT_BASS (1.0) |
|
316 #define RATIO_SIDE_BASS (1.0 / sqrt (2.0)) |
281 #define RATIO_REAR_BASS (1.0 / sqrt (2.0)) |
317 #define RATIO_REAR_BASS (1.0 / sqrt (2.0)) |
282 #define RATIO_CENTER_BASS (1.0 / sqrt (2.0)) |
|
283 |
318 |
284 static void |
319 static void |
285 gst_channel_mix_fill_others (AudioConvertCtx * this) |
320 gst_channel_mix_fill_others (AudioConvertCtx * this) |
286 { |
321 { |
287 gboolean in_has_front = FALSE, out_has_front = FALSE, |
322 gboolean in_has_front = FALSE, out_has_front = FALSE, |
288 in_has_center = FALSE, out_has_center = FALSE, |
323 in_has_center = FALSE, out_has_center = FALSE, |
289 in_has_rear = FALSE, out_has_rear = FALSE, |
324 in_has_rear = FALSE, out_has_rear = FALSE, |
290 in_has_side = FALSE, out_has_side = FALSE, |
325 in_has_side = FALSE, out_has_side = FALSE, |
291 in_has_bass = FALSE, out_has_bass = FALSE; |
326 in_has_bass = FALSE, out_has_bass = FALSE; |
292 gint in_f[2] = { -1, -1 }, out_f[2] = { |
327 /* LEFT, RIGHT, MONO */ |
293 -1, -1}, in_c[2] = { |
328 gint in_f[3] = { -1, -1, -1 }; |
294 -1, -1}, out_c[2] = { |
329 gint out_f[3] = { -1, -1, -1 }; |
295 -1, -1}, in_r[2] = { |
330 /* LOC, ROC, CENTER */ |
296 -1, -1}, out_r[2] = { |
331 gint in_c[3] = { -1, -1, -1 }; |
297 -1, -1}, in_s[2] = { |
332 gint out_c[3] = { -1, -1, -1 }; |
298 -1, -1}, out_s[2] = { |
333 /* RLEFT, RRIGHT, RCENTER */ |
299 -1, -1}, in_b[2] = { |
334 gint in_r[3] = { -1, -1, -1 }; |
300 -1, -1}, out_b[2] = { |
335 gint out_r[3] = { -1, -1, -1 }; |
301 -1, -1}; |
336 /* SLEFT, INVALID, SRIGHT */ |
|
337 gint in_s[3] = { -1, -1, -1 }; |
|
338 gint out_s[3] = { -1, -1, -1 }; |
|
339 /* INVALID, LFE, INVALID */ |
|
340 gint in_b[3] = { -1, -1, -1 }; |
|
341 gint out_b[3] = { -1, -1, -1 }; |
302 |
342 |
303 /* First see where (if at all) the various channels from/to |
343 /* First see where (if at all) the various channels from/to |
304 * which we want to convert are located in our matrix/array. */ |
344 * which we want to convert are located in our matrix/array. */ |
305 gst_channel_mix_detect_pos (&this->in, |
345 gst_channel_mix_detect_pos (&this->in, |
306 in_f, &in_has_front, |
346 in_f, &in_has_front, |
309 gst_channel_mix_detect_pos (&this->out, |
349 gst_channel_mix_detect_pos (&this->out, |
310 out_f, &out_has_front, |
350 out_f, &out_has_front, |
311 out_c, &out_has_center, out_r, &out_has_rear, |
351 out_c, &out_has_center, out_r, &out_has_rear, |
312 out_s, &out_has_side, out_b, &out_has_bass); |
352 out_s, &out_has_side, out_b, &out_has_bass); |
313 |
353 |
314 /* center/front */ |
354 /* The general idea here is: |
|
355 * - if the source has a channel that the destination doesn't have mix |
|
356 * it into the nearest available destination channel |
|
357 * - if the destination has a channel that the source doesn't have mix |
|
358 * the nearest source channel into the destination channel |
|
359 * |
|
360 * The ratio for the mixing becomes lower as the distance between the |
|
361 * channels gets larger |
|
362 */ |
|
363 |
|
364 /* center <-> front/side/rear */ |
315 if (!in_has_center && in_has_front && out_has_center) { |
365 if (!in_has_center && in_has_front && out_has_center) { |
316 gst_channel_mix_fill_one_other (this->matrix, |
366 gst_channel_mix_fill_one_other (this->matrix, |
317 &this->in, in_f, |
367 &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT); |
318 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
368 } else if (!in_has_center && !in_has_front && in_has_side && out_has_center) { |
319 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
369 gst_channel_mix_fill_one_other (this->matrix, |
320 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, |
370 &this->in, in_s, &this->out, out_c, RATIO_CENTER_SIDE); |
321 &this->out, out_c, |
371 } else if (!in_has_center && !in_has_front && !in_has_side && in_has_rear |
322 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, |
372 && out_has_center) { |
323 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, |
373 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, |
324 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, RATIO_FRONT_CENTER); |
374 out_c, RATIO_CENTER_REAR); |
325 } else if (in_has_center && !out_has_center && out_has_front) { |
375 } else if (in_has_center && !out_has_center && out_has_front) { |
326 gst_channel_mix_fill_one_other (this->matrix, |
376 gst_channel_mix_fill_one_other (this->matrix, |
327 &this->in, in_c, |
377 &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT); |
328 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, |
378 } else if (in_has_center && !out_has_center && !out_has_front && out_has_side) { |
329 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, |
379 gst_channel_mix_fill_one_other (this->matrix, |
330 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, |
380 &this->in, in_c, &this->out, out_s, RATIO_CENTER_SIDE); |
331 &this->out, out_f, |
381 } else if (in_has_center && !out_has_center && !out_has_front && !out_has_side |
332 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
382 && out_has_rear) { |
333 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
383 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, |
334 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_CENTER); |
384 out_r, RATIO_CENTER_REAR); |
335 } |
385 } |
336 |
386 |
337 /* rear/front */ |
387 /* front <-> center/side/rear */ |
338 if (!in_has_rear && in_has_front && out_has_rear) { |
388 if (!in_has_front && in_has_center && !in_has_side && out_has_front) { |
339 gst_channel_mix_fill_one_other (this->matrix, |
389 gst_channel_mix_fill_one_other (this->matrix, |
340 &this->in, in_f, |
390 &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT); |
341 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
391 } else if (!in_has_front && !in_has_center && in_has_side && out_has_front) { |
342 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
392 gst_channel_mix_fill_one_other (this->matrix, |
343 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, |
393 &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE); |
344 &this->out, out_r, |
394 } else if (!in_has_front && in_has_center && in_has_side && out_has_front) { |
345 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, |
395 gst_channel_mix_fill_one_other (this->matrix, |
346 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, |
396 &this->in, in_c, &this->out, out_f, 0.5 * RATIO_CENTER_FRONT); |
347 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, RATIO_FRONT_REAR); |
397 gst_channel_mix_fill_one_other (this->matrix, |
348 } else if (in_has_rear && !out_has_rear && out_has_front) { |
398 &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE); |
349 gst_channel_mix_fill_one_other (this->matrix, |
399 } else if (!in_has_front && !in_has_center && !in_has_side && in_has_rear |
350 &this->in, in_r, |
400 && out_has_front) { |
351 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, |
401 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, |
352 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, |
402 out_f, RATIO_FRONT_REAR); |
353 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, |
403 } else if (in_has_front && out_has_center && !out_has_side && !out_has_front) { |
354 &this->out, out_f, |
404 gst_channel_mix_fill_one_other (this->matrix, |
355 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
405 &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT); |
356 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
406 } else if (in_has_front && !out_has_center && out_has_side && !out_has_front) { |
357 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_REAR); |
407 gst_channel_mix_fill_one_other (this->matrix, |
358 } |
408 &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE); |
359 |
409 } else if (in_has_front && out_has_center && out_has_side && !out_has_front) { |
360 /* bass/any */ |
410 gst_channel_mix_fill_one_other (this->matrix, |
|
411 &this->in, in_f, &this->out, out_c, 0.5 * RATIO_CENTER_FRONT); |
|
412 gst_channel_mix_fill_one_other (this->matrix, |
|
413 &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE); |
|
414 } else if (in_has_front && !out_has_center && !out_has_side && !out_has_front |
|
415 && out_has_rear) { |
|
416 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_f, &this->out, |
|
417 out_r, RATIO_FRONT_REAR); |
|
418 } |
|
419 |
|
420 /* side <-> center/front/rear */ |
|
421 if (!in_has_side && in_has_front && !in_has_rear && out_has_side) { |
|
422 gst_channel_mix_fill_one_other (this->matrix, |
|
423 &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE); |
|
424 } else if (!in_has_side && !in_has_front && in_has_rear && out_has_side) { |
|
425 gst_channel_mix_fill_one_other (this->matrix, |
|
426 &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR); |
|
427 } else if (!in_has_side && in_has_front && in_has_rear && out_has_side) { |
|
428 gst_channel_mix_fill_one_other (this->matrix, |
|
429 &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE); |
|
430 gst_channel_mix_fill_one_other (this->matrix, |
|
431 &this->in, in_r, &this->out, out_s, 0.5 * RATIO_SIDE_REAR); |
|
432 } else if (!in_has_side && !in_has_front && !in_has_rear && in_has_center |
|
433 && out_has_side) { |
|
434 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, |
|
435 out_s, RATIO_CENTER_SIDE); |
|
436 } else if (in_has_side && out_has_front && !out_has_rear && !out_has_side) { |
|
437 gst_channel_mix_fill_one_other (this->matrix, |
|
438 &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE); |
|
439 } else if (in_has_side && !out_has_front && out_has_rear && !out_has_side) { |
|
440 gst_channel_mix_fill_one_other (this->matrix, |
|
441 &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR); |
|
442 } else if (in_has_side && out_has_front && out_has_rear && !out_has_side) { |
|
443 gst_channel_mix_fill_one_other (this->matrix, |
|
444 &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE); |
|
445 gst_channel_mix_fill_one_other (this->matrix, |
|
446 &this->in, in_s, &this->out, out_r, 0.5 * RATIO_SIDE_REAR); |
|
447 } else if (in_has_side && !out_has_front && !out_has_rear && out_has_center |
|
448 && !out_has_side) { |
|
449 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_s, &this->out, |
|
450 out_c, RATIO_CENTER_SIDE); |
|
451 } |
|
452 |
|
453 /* rear <-> center/front/side */ |
|
454 if (!in_has_rear && in_has_side && out_has_rear) { |
|
455 gst_channel_mix_fill_one_other (this->matrix, |
|
456 &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR); |
|
457 } else if (!in_has_rear && !in_has_side && in_has_front && out_has_rear) { |
|
458 gst_channel_mix_fill_one_other (this->matrix, |
|
459 &this->in, in_f, &this->out, out_r, RATIO_FRONT_REAR); |
|
460 } else if (!in_has_rear && !in_has_side && !in_has_front && in_has_center |
|
461 && out_has_rear) { |
|
462 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, |
|
463 out_r, RATIO_CENTER_REAR); |
|
464 } else if (in_has_rear && !out_has_rear && out_has_side) { |
|
465 gst_channel_mix_fill_one_other (this->matrix, |
|
466 &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR); |
|
467 } else if (in_has_rear && !out_has_rear && !out_has_side && out_has_front) { |
|
468 gst_channel_mix_fill_one_other (this->matrix, |
|
469 &this->in, in_r, &this->out, out_f, RATIO_FRONT_REAR); |
|
470 } else if (in_has_rear && !out_has_rear && !out_has_side && !out_has_front |
|
471 && out_has_center) { |
|
472 gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, |
|
473 out_c, RATIO_CENTER_REAR); |
|
474 } |
|
475 |
|
476 /* bass <-> any */ |
361 if (in_has_bass && !out_has_bass) { |
477 if (in_has_bass && !out_has_bass) { |
|
478 if (out_has_center) { |
|
479 gst_channel_mix_fill_one_other (this->matrix, |
|
480 &this->in, in_b, &this->out, out_c, RATIO_CENTER_BASS); |
|
481 } |
362 if (out_has_front) { |
482 if (out_has_front) { |
363 gst_channel_mix_fill_one_other (this->matrix, |
483 gst_channel_mix_fill_one_other (this->matrix, |
364 &this->in, in_b, |
484 &this->in, in_b, &this->out, out_f, RATIO_FRONT_BASS); |
365 GST_AUDIO_CHANNEL_POSITION_INVALID, |
485 } |
366 GST_AUDIO_CHANNEL_POSITION_INVALID, |
486 if (out_has_side) { |
367 GST_AUDIO_CHANNEL_POSITION_LFE, |
|
368 &this->out, out_f, |
|
369 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
|
370 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
|
371 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, RATIO_FRONT_BASS); |
|
372 } |
|
373 if (out_has_center) { |
|
374 gst_channel_mix_fill_one_other (this->matrix, |
487 gst_channel_mix_fill_one_other (this->matrix, |
375 &this->in, in_b, |
488 &this->in, in_b, &this->out, out_s, RATIO_SIDE_BASS); |
376 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
377 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
378 GST_AUDIO_CHANNEL_POSITION_LFE, |
|
379 &this->out, out_c, |
|
380 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, |
|
381 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, |
|
382 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, RATIO_CENTER_BASS); |
|
383 } |
489 } |
384 if (out_has_rear) { |
490 if (out_has_rear) { |
385 gst_channel_mix_fill_one_other (this->matrix, |
491 gst_channel_mix_fill_one_other (this->matrix, |
386 &this->in, in_b, |
492 &this->in, in_b, &this->out, out_r, RATIO_REAR_BASS); |
387 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
388 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
389 GST_AUDIO_CHANNEL_POSITION_LFE, |
|
390 &this->out, out_r, |
|
391 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, |
|
392 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, |
|
393 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, RATIO_REAR_BASS); |
|
394 } |
493 } |
395 } else if (!in_has_bass && out_has_bass) { |
494 } else if (!in_has_bass && out_has_bass) { |
|
495 if (in_has_center) { |
|
496 gst_channel_mix_fill_one_other (this->matrix, |
|
497 &this->in, in_c, &this->out, out_b, RATIO_CENTER_BASS); |
|
498 } |
396 if (in_has_front) { |
499 if (in_has_front) { |
397 gst_channel_mix_fill_one_other (this->matrix, |
500 gst_channel_mix_fill_one_other (this->matrix, |
398 &this->in, in_f, |
501 &this->in, in_f, &this->out, out_b, RATIO_FRONT_BASS); |
399 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, |
502 } |
400 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, |
503 if (in_has_side) { |
401 GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, |
|
402 &this->out, out_b, |
|
403 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
404 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
405 GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_FRONT_BASS); |
|
406 } |
|
407 if (in_has_center) { |
|
408 gst_channel_mix_fill_one_other (this->matrix, |
504 gst_channel_mix_fill_one_other (this->matrix, |
409 &this->in, in_c, |
505 &this->in, in_s, &this->out, out_b, RATIO_REAR_BASS); |
410 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, |
|
411 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, |
|
412 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, |
|
413 &this->out, out_b, |
|
414 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
415 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
416 GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_CENTER_BASS); |
|
417 } |
506 } |
418 if (in_has_rear) { |
507 if (in_has_rear) { |
419 gst_channel_mix_fill_one_other (this->matrix, |
508 gst_channel_mix_fill_one_other (this->matrix, |
420 &this->in, in_r, |
509 &this->in, in_r, &this->out, out_b, RATIO_REAR_BASS); |
421 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, |
510 } |
422 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, |
511 } |
423 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, |
|
424 &this->out, out_b, |
|
425 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
426 GST_AUDIO_CHANNEL_POSITION_INVALID, |
|
427 GST_AUDIO_CHANNEL_POSITION_LFE, RATIO_REAR_BASS); |
|
428 } |
|
429 } |
|
430 |
|
431 /* FIXME: side */ |
|
432 } |
512 } |
433 |
513 |
434 /* |
514 /* |
435 * Normalize output values. |
515 * Normalize output values. |
436 */ |
516 */ |