Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/internal/compositor_dev.h>
27 :
28 : /*
29 : Notes about the mixer:
30 : 1- spatialization is out of scope for the mixer (eg that's the sound node responsability)
31 : 2- mixing is performed by resampling input source & deinterleaving its channels into dedicated buffer.
32 : We could directly deinterleave in the main mixer ouput buffer, but this would prevent any future
33 : gain correction.
34 : */
35 : typedef struct
36 : {
37 : GF_AudioInterface *src;
38 :
39 : s32 *ch_buf[GF_AUDIO_MIXER_MAX_CHANNELS];
40 : /*resampled buffer*/
41 : u32 buffer_size;
42 :
43 : u32 bytes_per_sec, bit_depth;
44 :
45 : Bool has_prev;
46 : s32 last_channels[GF_AUDIO_MIXER_MAX_CHANNELS];
47 :
48 : u32 in_bytes_used, out_samples_written, out_samples_to_write;
49 :
50 : u32 out_samples_pos, in_samples_pos, scaled_sr, bytes_p_samp;
51 : u32 ratio_aligned;
52 :
53 : Fixed speed;
54 : Fixed pan[GF_AUDIO_MIXER_MAX_CHANNELS];
55 :
56 : s32 (*get_sample)(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride);
57 : Bool is_planar;
58 : Bool muted;
59 : } MixerInput;
60 :
61 : struct __audiomix
62 : {
63 : /*src*/
64 : GF_List *sources;
65 : /*output config*/
66 : u32 sample_rate;
67 : u32 nb_channels;
68 : u32 afmt, bit_depth;
69 : u64 channel_layout;
70 : GF_Mutex *mx;
71 : /*if set forces stereo/mono*/
72 : Bool force_channel_out;
73 : /*set to true by mixer when detecting an audio config change*/
74 : Bool must_reconfig;
75 : Bool isEmpty;
76 : Bool source_buffering;
77 : /*set to non null if this outputs directly to the driver, in which case audio formats have to be checked*/
78 : struct _audio_render *ar;
79 :
80 : Fixed max_speed;
81 :
82 : s32 *output;
83 : u32 output_size;
84 : };
85 :
86 : #define GF_S24_MAX 8388607
87 : #define GF_S24_MIN -8388608
88 :
89 :
90 : GF_EXPORT
91 653 : GF_AudioMixer *gf_mixer_new(struct _audio_render *ar)
92 : {
93 : GF_AudioMixer *am;
94 653 : am = (GF_AudioMixer *) gf_malloc(sizeof(GF_AudioMixer));
95 653 : if (!am) return NULL;
96 : memset(am, 0, sizeof(GF_AudioMixer));
97 653 : am->mx = gf_mx_new("AudioMix");
98 653 : am->sources = gf_list_new();
99 653 : am->isEmpty = GF_TRUE;
100 653 : am->ar = ar;
101 653 : am->sample_rate = 44100;
102 653 : am->afmt = GF_AUDIO_FMT_S16;
103 653 : am->bit_depth = gf_audio_fmt_bit_depth(am->afmt);
104 653 : am->nb_channels = 2;
105 653 : am->output = NULL;
106 653 : am->output_size = 0;
107 653 : am->max_speed = FIX_MAX;
108 653 : return am;
109 : }
110 :
111 188 : Bool gf_mixer_must_reconfig(GF_AudioMixer *am)
112 : {
113 188 : return am->must_reconfig;
114 : }
115 :
116 605 : void gf_mixer_set_max_speed(GF_AudioMixer *am, Double max_speed)
117 : {
118 605 : am->max_speed = FLT2FIX(max_speed);
119 605 : }
120 :
121 : GF_EXPORT
122 652 : void gf_mixer_del(GF_AudioMixer *am)
123 : {
124 652 : gf_mixer_remove_all(am);
125 652 : gf_list_del(am->sources);
126 652 : gf_mx_del(am->mx);
127 652 : if (am->output) gf_free(am->output);
128 652 : gf_free(am);
129 652 : }
130 :
131 3162 : void gf_mixer_remove_all(GF_AudioMixer *am)
132 : {
133 : u32 j;
134 3162 : gf_mixer_lock(am, GF_TRUE);
135 6386 : while (gf_list_count(am->sources)) {
136 62 : MixerInput *in = (MixerInput *)gf_list_get(am->sources, 0);
137 62 : gf_list_rem(am->sources, 0);
138 1550 : for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
139 1488 : if (in->ch_buf[j]) gf_free(in->ch_buf[j]);
140 : }
141 62 : gf_free(in);
142 : }
143 3162 : am->isEmpty = GF_TRUE;
144 3162 : gf_mixer_lock(am, GF_FALSE);
145 3162 : }
146 :
147 0 : Bool gf_mixer_is_src_present(GF_AudioMixer *am, GF_AudioInterface *ifce)
148 : {
149 : MixerInput *in;
150 65 : u32 i = 0;
151 71 : while ((in = (MixerInput *)gf_list_enum(am->sources, &i))) {
152 6 : if (in->src == ifce) return GF_TRUE;
153 : }
154 : return GF_FALSE;
155 : }
156 35 : u32 gf_mixer_get_src_count(GF_AudioMixer *am)
157 : {
158 35 : return gf_list_count(am->sources);
159 : }
160 :
161 1 : GF_Err gf_mixer_force_channel_out(GF_AudioMixer *am, u32 num_channels)
162 : {
163 1 : if (num_channels > GF_AUDIO_MIXER_MAX_CHANNELS) {
164 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Number of output channels %d higher than max channels supported %d\n", num_channels, GF_AUDIO_MIXER_MAX_CHANNELS));
165 : return GF_NOT_SUPPORTED;
166 : }
167 1 : am->force_channel_out = GF_TRUE;
168 1 : am->nb_channels = num_channels;
169 1 : return GF_OK;
170 : }
171 :
172 1 : u32 gf_mixer_get_block_align(GF_AudioMixer *am)
173 : {
174 1 : return am->nb_channels * am->bit_depth/8;
175 : }
176 :
177 : GF_EXPORT
178 225188 : void gf_mixer_lock(GF_AudioMixer *am, Bool lockIt)
179 : {
180 : //GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[AudioMixer] Thread ID %d is %s the audio mixer\n", gf_th_id(), lockIt ? "locking" : "unlocking" ));
181 225188 : if (lockIt) {
182 112594 : gf_mx_p(am->mx);
183 : } else {
184 112594 : gf_mx_v(am->mx);
185 : }
186 225188 : }
187 :
188 : GF_EXPORT
189 42 : Bool gf_mixer_empty(GF_AudioMixer *am)
190 : {
191 42 : return am->isEmpty;
192 : }
193 :
194 : GF_EXPORT
195 28645 : Bool gf_mixer_buffering(GF_AudioMixer *am)
196 : {
197 28645 : return am->source_buffering;
198 : }
199 :
200 : GF_EXPORT
201 65 : void gf_mixer_add_input(GF_AudioMixer *am, GF_AudioInterface *src)
202 : {
203 : MixerInput *in;
204 65 : if (gf_mixer_is_src_present(am, src)) return;
205 65 : gf_mixer_lock(am, GF_TRUE);
206 65 : GF_SAFEALLOC(in, MixerInput);
207 65 : if (!in) {
208 0 : gf_mixer_lock(am, GF_FALSE);
209 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Cannot allocate input source\n"));
210 : return;
211 : }
212 65 : in->src = src;
213 65 : gf_list_add(am->sources, in);
214 65 : am->must_reconfig = GF_TRUE;
215 65 : am->isEmpty = GF_FALSE;
216 65 : gf_mixer_lock(am, GF_FALSE);
217 : }
218 :
219 21 : void gf_mixer_remove_input(GF_AudioMixer *am, GF_AudioInterface *src)
220 : {
221 : u32 i, j, count;
222 21 : if (am->isEmpty) return;
223 3 : gf_mixer_lock(am, GF_TRUE);
224 3 : count = gf_list_count(am->sources);
225 3 : for (i=0; i<count; i++) {
226 3 : MixerInput *in = (MixerInput *)gf_list_get(am->sources, i);
227 3 : if (in->src != src) continue;
228 3 : gf_list_rem(am->sources, i);
229 75 : for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
230 72 : if (in->ch_buf[j]) gf_free(in->ch_buf[j]);
231 : }
232 3 : gf_free(in);
233 3 : break;
234 : }
235 3 : am->isEmpty = gf_list_count(am->sources) ? GF_FALSE : GF_TRUE;
236 : /*we don't ask for reconfig when removing a node*/
237 3 : gf_mixer_lock(am, GF_FALSE);
238 : }
239 :
240 :
241 : static GF_Err get_best_samplerate(GF_AudioMixer *am, u32 *out_sr, u32 *out_ch, u32 *out_fmt)
242 : {
243 : if (!am->ar) return GF_OK;
244 : #ifdef ENABLE_AOUT
245 : if (!am->ar->audio_out || !am->ar->audio_out->QueryOutputSampleRate) return GF_OK;
246 : return am->ar->audio_out->QueryOutputSampleRate(am->ar->audio_out, out_sr, out_ch, out_fmt);
247 : #endif
248 : return GF_OK;
249 : }
250 :
251 : GF_EXPORT
252 630 : void gf_mixer_get_config(GF_AudioMixer *am, u32 *outSR, u32 *outCH, u32 *outFMT, u64 *outChCfg)
253 : {
254 630 : (*outFMT) = am->afmt;
255 630 : (*outCH) = am->nb_channels;
256 630 : (*outSR) = am->sample_rate;
257 630 : (*outChCfg) = am->channel_layout;
258 630 : }
259 :
260 : GF_EXPORT
261 709 : GF_Err gf_mixer_set_config(GF_AudioMixer *am, u32 outSR, u32 outCH, u32 outFMT, u64 outChCfg)
262 : {
263 709 : if ((am->afmt == outFMT) && (am->nb_channels == outCH)
264 634 : && (am->sample_rate==outSR) && (am->channel_layout == outChCfg)) return GF_OK;
265 :
266 84 : if (outCH > GF_AUDIO_MIXER_MAX_CHANNELS) {
267 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Number of output channels %d higher than max channels supported %d\n", outCH, GF_AUDIO_MIXER_MAX_CHANNELS));
268 : return GF_NOT_SUPPORTED;
269 : }
270 84 : if (!outSR) {
271 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUDIO, ("[AudioMixer] Invalid output sample rate 0\n"));
272 : return GF_NOT_SUPPORTED;
273 : }
274 84 : gf_mixer_lock(am, GF_TRUE);
275 84 : am->afmt = outFMT;
276 84 : am->bit_depth = gf_audio_fmt_bit_depth(am->afmt);
277 84 : if (!am->force_channel_out)
278 84 : am->nb_channels = outCH;
279 : if (get_best_samplerate(am, &outSR, &outCH, &outFMT) == GF_OK) {
280 84 : am->sample_rate = outSR;
281 84 : if (outCH>2) am->channel_layout = outChCfg;
282 83 : else if (outCH==2) am->channel_layout = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;
283 8 : else am->channel_layout = GF_AUDIO_CH_FRONT_LEFT;
284 : }
285 : /*if main mixer recfg output*/
286 84 : if (am->ar) am->ar->need_reconfig = GF_TRUE;
287 84 : am->must_reconfig = GF_FALSE;
288 84 : gf_mixer_lock(am, GF_FALSE);
289 84 : return GF_OK;
290 : }
291 :
292 : static GFINLINE s32 make_s24_int(u8 *ptr)
293 : {
294 : s32 val;
295 : s16 res;
296 : memcpy(&res, ptr+1, 2);
297 73728 : val = res * 256;
298 73728 : val |= ptr[0];
299 : return val;
300 : }
301 :
302 : #define MIX_S16_SCALE 65535
303 : #define MIX_S24_SCALE 255
304 : #define MIX_U8_SCALE 16777215
305 :
306 82944 : s32 input_sample_s32(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
307 : {
308 : s32 *src = (s32 *)data;
309 82944 : return src[sample_offset*nb_ch + channel];
310 : }
311 36864 : s32 input_sample_s32p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
312 : {
313 : s32 *src = (s32 *)data;
314 36864 : return src[sample_offset + planar_stride*channel/4];
315 : }
316 36864 : s32 input_sample_s24(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
317 : {
318 73728 : return make_s24_int(&data[sample_offset*nb_ch*3 + 3*channel]) * MIX_S24_SCALE;
319 : }
320 36864 : s32 input_sample_s24p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
321 : {
322 73728 : return make_s24_int(&data[sample_offset*3 + channel*planar_stride]) * MIX_S24_SCALE;
323 : }
324 :
325 : #define TRUNC_FLT_DBL(_a) \
326 : if (_a<-1.0) return GF_INT_MIN;\
327 : else if (_a>1.0) return GF_INT_MAX;\
328 : return (s32) (_a * GF_INT_MAX);\
329 :
330 50304 : s32 input_sample_flt(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
331 : {
332 : Float *src = (Float *)data;
333 50304 : Float samp = src[sample_offset*nb_ch + channel];
334 50304 : TRUNC_FLT_DBL(samp);
335 : }
336 8529854 : s32 input_sample_fltp(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
337 : {
338 : Float *src = (Float *)data;
339 8529854 : Float samp = src[sample_offset + planar_stride*channel/4];
340 8529854 : TRUNC_FLT_DBL(samp);
341 : }
342 36864 : s32 input_sample_dbl(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
343 : {
344 : Double *src = (Double *)data;
345 36864 : Double samp = src[sample_offset*nb_ch + channel];
346 36864 : TRUNC_FLT_DBL(samp);
347 : }
348 36864 : s32 input_sample_dblp(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
349 : {
350 : Double *src = (Double *)data;
351 36864 : Double samp = src[sample_offset + planar_stride * channel / 8];
352 36864 : TRUNC_FLT_DBL(samp);
353 : }
354 14999908 : s32 input_sample_s16(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
355 : {
356 : s16 *src = (s16 *)data;
357 14999908 : s32 res = src[sample_offset*nb_ch + channel];
358 14999908 : return res * MIX_S16_SCALE;
359 : }
360 55296 : s32 input_sample_s16p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
361 : {
362 : s16 *src = (s16 *)data;
363 55296 : s32 res = src[sample_offset + planar_stride*channel / 2];
364 55296 : return res * MIX_S16_SCALE;
365 : }
366 36864 : s32 input_sample_u8(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
367 : {
368 36864 : s32 res = data[sample_offset*nb_ch + channel];
369 36864 : res -= 128;
370 36864 : return res * MIX_U8_SCALE;
371 : }
372 36864 : s32 input_sample_u8p(u8 *data, u32 nb_ch, u32 sample_offset, u32 channel, u32 planar_stride)
373 : {
374 36864 : s32 res = data[sample_offset + planar_stride*channel];
375 36864 : res -= 128;
376 36864 : return res * MIX_U8_SCALE;
377 : }
378 :
379 64 : static void gf_am_configure_source(MixerInput *in)
380 : {
381 64 : in->bit_depth = gf_audio_fmt_bit_depth(in->src->afmt);
382 64 : in->bytes_per_sec = in->src->samplerate * in->src->chan * in->bit_depth / 8;
383 64 : in->is_planar = gf_audio_fmt_is_planar(in->src->afmt);
384 64 : switch (in->src->afmt) {
385 2 : case GF_AUDIO_FMT_S32:
386 2 : in->get_sample = input_sample_s32;
387 2 : break;
388 1 : case GF_AUDIO_FMT_S32P:
389 1 : in->get_sample = input_sample_s32p;
390 1 : break;
391 1 : case GF_AUDIO_FMT_S24:
392 1 : in->get_sample = input_sample_s24;
393 1 : break;
394 1 : case GF_AUDIO_FMT_S24P:
395 1 : in->get_sample = input_sample_s24p;
396 1 : break;
397 4 : case GF_AUDIO_FMT_FLT:
398 4 : in->get_sample = input_sample_flt;
399 4 : break;
400 28 : case GF_AUDIO_FMT_FLTP:
401 28 : in->get_sample = input_sample_fltp;
402 28 : break;
403 1 : case GF_AUDIO_FMT_DBL:
404 1 : in->get_sample = input_sample_dbl;
405 1 : break;
406 1 : case GF_AUDIO_FMT_DBLP:
407 1 : in->get_sample = input_sample_dblp;
408 1 : break;
409 21 : case GF_AUDIO_FMT_S16:
410 21 : in->get_sample = input_sample_s16;
411 21 : break;
412 2 : case GF_AUDIO_FMT_S16P:
413 2 : in->get_sample = input_sample_s16p;
414 2 : break;
415 1 : case GF_AUDIO_FMT_U8:
416 1 : in->get_sample = input_sample_u8;
417 1 : break;
418 1 : case GF_AUDIO_FMT_U8P:
419 1 : in->get_sample = input_sample_u8p;
420 1 : break;
421 : }
422 64 : }
423 :
424 : GF_EXPORT
425 37195 : Bool gf_mixer_reconfig(GF_AudioMixer *am)
426 : {
427 : u32 i, count, numInit, max_sample_rate, max_channels, max_afmt, cfg_changed;
428 : u64 ch_layout;
429 37195 : gf_mixer_lock(am, GF_TRUE);
430 37195 : if (am->isEmpty || !am->must_reconfig) {
431 37062 : gf_mixer_lock(am, GF_FALSE);
432 37062 : return GF_FALSE;
433 : }
434 :
435 133 : if (am->ar && am->ar->config_forced) {
436 0 : am->must_reconfig = GF_FALSE;
437 0 : gf_mixer_lock(am, GF_FALSE);
438 0 : return GF_FALSE;
439 : }
440 :
441 : numInit = 0;
442 133 : max_channels = am->nb_channels;
443 133 : max_afmt = am->afmt;
444 : cfg_changed = 0;
445 : max_sample_rate = 0;
446 :
447 : ch_layout = 0;
448 :
449 133 : count = gf_list_count(am->sources);
450 : assert(count);
451 281 : for (i=0; i<count; i++) {
452 : Bool has_cfg;
453 148 : MixerInput *in = (MixerInput *) gf_list_get(am->sources, i);
454 148 : has_cfg = in->src->GetConfig(in->src, GF_TRUE);
455 148 : if (has_cfg) {
456 : /*check same cfg...*/
457 25 : if (in->src->samplerate * in->src->chan * in->bit_depth == 8*in->bytes_per_sec) {
458 24 : numInit++;
459 24 : continue;
460 : }
461 123 : } else continue;
462 : /*update out cfg*/
463 1 : if ((count==1) && (max_sample_rate != in->src->samplerate)) {
464 : // cfg_changed = 1;
465 : max_sample_rate = in->src->samplerate;
466 0 : } else if (max_sample_rate<in->src->samplerate) {
467 : // cfg_changed = 1;
468 : max_sample_rate = in->src->samplerate;
469 : }
470 1 : if ((count==1) && (max_afmt != in->src->afmt)) {
471 : cfg_changed = 1;
472 : max_afmt = in->src->afmt;
473 0 : } else if (max_afmt<in->src->afmt) {
474 : cfg_changed = 1;
475 : max_afmt = in->src->afmt;
476 : }
477 1 : if (!am->force_channel_out) {
478 1 : if ((count==1) && (max_channels!=in->src->chan)) {
479 : cfg_changed = 1;
480 : max_channels = in->src->chan;
481 : // if (in->src->forced_layout)
482 0 : ch_layout |= in->src->ch_layout;
483 : }
484 : else {
485 : u32 nb_ch = in->src->chan;
486 1 : if (in->src->forced_layout) {
487 0 : u64 cfg = in->src->ch_layout;
488 : nb_ch = 0;
489 0 : while (cfg) {
490 0 : nb_ch++;
491 0 : cfg >>= 1;
492 : }
493 0 : ch_layout |= in->src->ch_layout;
494 : }
495 1 : if (max_channels < nb_ch) {
496 : cfg_changed = 1;
497 : max_channels = nb_ch;
498 0 : if (nb_ch > 2) ch_layout |= in->src->ch_layout;
499 : }
500 : }
501 : }
502 :
503 1 : numInit++;
504 1 : gf_am_configure_source(in);
505 :
506 : /*cfg has changed, we must reconfig everything*/
507 1 : if (cfg_changed || (max_sample_rate != am->sample_rate) ) {
508 1 : in->ratio_aligned = 0;
509 1 : in->bit_depth = 0;
510 1 : memset(&in->last_channels, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
511 : }
512 : }
513 :
514 133 : if (cfg_changed || (max_sample_rate && (max_sample_rate != am->sample_rate)) ) {
515 1 : if (max_channels>2) {
516 0 : if (!ch_layout) {
517 : //TODO pickup default layout ?
518 0 : } else if (ch_layout != am->channel_layout) {
519 : /*recompute num channel based on all input channels*/
520 : max_channels = 0;
521 0 : if (ch_layout & GF_AUDIO_CH_FRONT_LEFT) max_channels ++;
522 0 : if (ch_layout & GF_AUDIO_CH_FRONT_RIGHT) max_channels ++;
523 0 : if (ch_layout & GF_AUDIO_CH_FRONT_CENTER) max_channels ++;
524 0 : if (ch_layout & GF_AUDIO_CH_LFE) max_channels ++;
525 0 : if (ch_layout & GF_AUDIO_CH_SURROUND_LEFT) max_channels ++;
526 0 : if (ch_layout & GF_AUDIO_CH_SURROUND_RIGHT) max_channels ++;
527 0 : if (ch_layout & GF_AUDIO_CH_REAR_CENTER) max_channels ++;
528 0 : if (ch_layout & GF_AUDIO_CH_REAR_SURROUND_LEFT) max_channels ++;
529 0 : if (ch_layout & GF_AUDIO_CH_REAR_SURROUND_RIGHT) max_channels ++;
530 : }
531 : } else {
532 : ch_layout = GF_AUDIO_CH_FRONT_LEFT;
533 1 : if (max_channels==2) ch_layout |= GF_AUDIO_CH_FRONT_RIGHT;
534 : }
535 1 : gf_mixer_set_config(am, max_sample_rate, max_channels, max_afmt, ch_layout);
536 : }
537 :
538 133 : if (numInit == count) am->must_reconfig = GF_FALSE;
539 133 : if (am->ar) cfg_changed = 1;
540 :
541 133 : gf_mixer_lock(am, GF_FALSE);
542 133 : return cfg_changed;
543 : }
544 :
545 : static GFINLINE u32 get_channel_out_pos(u32 in_ch, u64 out_ch_layout)
546 : {
547 : u32 i, cfg, pos;
548 : pos = 0;
549 0 : for (i=0; i<9; i++) {
550 0 : cfg = 1<<(i);
551 0 : if (out_ch_layout & cfg) {
552 0 : if (cfg == in_ch) return pos;
553 0 : pos++;
554 : }
555 : }
556 : return GF_AUDIO_MIXER_MAX_CHANNELS;
557 : }
558 :
559 : /*this is crude, we'd need a matrix or something*/
560 8046935 : static GFINLINE void gf_mixer_map_channels(s32 *inChan, u32 nb_in, u64 in_ch_layout, Bool forced_layout, u32 nb_out, u64 out_ch_layout)
561 : {
562 : u32 i;
563 8046935 : if (nb_in==1) {
564 : /*mono to stereo*/
565 31872 : if (nb_out==2) {
566 : //layout forced, don't copy
567 0 : if (in_ch_layout && forced_layout) {
568 : u32 idx = 0;
569 : while (1) {
570 0 : in_ch_layout >>= 1;
571 0 : if (!in_ch_layout) break;
572 0 : idx++;
573 : }
574 0 : if (idx) {
575 : // inChan[idx] = inChan[0];
576 : // inChan[0] = 0;
577 0 : inChan[1] = inChan[0];
578 : } else {
579 0 : inChan[1] = inChan[0];
580 : }
581 : } else {
582 0 : inChan[1] = inChan[0];
583 : }
584 : }
585 31872 : else if (nb_out>2) {
586 : /*if center channel use it (we assume we always have stereo channels)*/
587 0 : if (out_ch_layout & GF_AUDIO_CH_FRONT_CENTER) {
588 0 : inChan[2] = inChan[0];
589 0 : inChan[0] = 0;
590 0 : for (i=3; i<nb_out; i++) inChan[i] = 0;
591 : } else {
592 : /*mono to stereo*/
593 0 : inChan[1] = inChan[0];
594 0 : for (i=2; i<nb_out; i++) inChan[i] = 0;
595 : }
596 : }
597 8015063 : } else if (nb_in==2) {
598 8015063 : if (nb_out==1) {
599 0 : s64 sum = (s64)inChan[0] + (s64) inChan[1];
600 0 : inChan[0] = (s32) (sum/2);
601 : } else {
602 0 : for (i=2; i<nb_out; i++) inChan[i] = 0;
603 : }
604 : }
605 : /*same output than input channels, nothing to reorder*/
606 :
607 : /*more output than input channels*/
608 0 : else if (nb_in<nb_out) {
609 : s32 bckup[GF_AUDIO_MIXER_MAX_CHANNELS];
610 : u32 pos;
611 : u64 cfg = in_ch_layout;
612 : u32 ch = 0;
613 0 : memcpy(bckup, inChan, sizeof(s32)*nb_in);
614 0 : for (i=0; i<nb_in; i++) {
615 : /*get first in channel*/
616 0 : while (! (cfg & 1)) {
617 0 : ch++;
618 0 : cfg>>=1;
619 : /*done*/
620 0 : if (ch==10) return;
621 : }
622 0 : pos = get_channel_out_pos((1<<ch), out_ch_layout);
623 : assert(pos != GF_AUDIO_MIXER_MAX_CHANNELS);
624 0 : inChan[pos] = bckup[i];
625 0 : ch++;
626 0 : cfg>>=1;
627 : }
628 0 : for (i=nb_in; i<nb_out; i++) inChan[i] = 0;
629 : }
630 : /*less output than input channels (eg sound card doesn't support requested format*/
631 0 : else if (nb_in>nb_out) {
632 : s32 bckup[GF_AUDIO_MIXER_MAX_CHANNELS];
633 : u32 pos;
634 : u64 cfg = in_ch_layout;
635 : u32 ch = 0;
636 0 : memcpy(bckup, inChan, sizeof(s32)*nb_in);
637 0 : for (i=0; i<nb_in; i++) {
638 : /*get first in channel*/
639 0 : while (! (cfg & 1)) {
640 0 : ch++;
641 0 : cfg>>=1;
642 : /*done*/
643 0 : if (ch==10) return;
644 : }
645 0 : pos = get_channel_out_pos( (1<<ch), out_ch_layout);
646 : /*this channel is present in output, copy over*/
647 0 : if (pos < GF_AUDIO_MIXER_MAX_CHANNELS) {
648 0 : inChan[pos] = bckup[i];
649 : } else {
650 : /*map to stereo (we assume that the driver cannot handle ANY multichannel cfg)*/
651 0 : switch (1<<ch) {
652 0 : case GF_AUDIO_CH_FRONT_CENTER:
653 : case GF_AUDIO_CH_LFE:
654 : case GF_AUDIO_CH_REAR_CENTER:
655 0 : inChan[0] += bckup[i]/2;
656 0 : inChan[1] += bckup[i]/2;
657 0 : break;
658 0 : case GF_AUDIO_CH_SURROUND_LEFT:
659 : case GF_AUDIO_CH_REAR_SURROUND_LEFT:
660 0 : inChan[0] += bckup[i];
661 0 : break;
662 0 : case GF_AUDIO_CH_SURROUND_RIGHT:
663 : case GF_AUDIO_CH_REAR_SURROUND_RIGHT:
664 0 : inChan[1] += bckup[i];
665 0 : break;
666 : }
667 : }
668 0 : ch++;
669 0 : cfg>>=1;
670 : }
671 : }
672 : }
673 :
674 : #define RESAMPLE_SCALER 1000
675 :
676 42054 : static void gf_mixer_fetch_input(GF_AudioMixer *am, MixerInput *in, u32 audio_delay)
677 : {
678 : u32 j, in_ch, out_ch, prev, next, src_samp, src_size;
679 : Bool use_prev;
680 42054 : u32 planar_stride=0;
681 : s8 *in_data;
682 : s32 frac, inChan[GF_AUDIO_MIXER_MAX_CHANNELS], inChanNext[GF_AUDIO_MIXER_MAX_CHANNELS];
683 :
684 42054 : in_ch = in->src->chan;
685 42054 : out_ch = am->nb_channels;
686 42054 : use_prev = in->has_prev;
687 :
688 42054 : in_data = (s8 *) in->src->FetchFrame(in->src->callback, &src_size, &planar_stride, audio_delay);
689 42054 : if (!in_data || !src_size) {
690 : //end of stream, flush if needed
691 28072 : if (in->src->is_eos && use_prev) {
692 :
693 : } else {
694 : /*done, stop fill*/
695 28072 : in->out_samples_to_write = 0;
696 56144 : return;
697 : }
698 : }
699 :
700 : //config changed, recompute our values
701 13982 : if (!in->ratio_aligned) {
702 66 : u32 ratio = (u32) (in->src->samplerate * FIX2INT(255*in->speed) / am->sample_rate);
703 66 : if (ratio % 255) in->ratio_aligned = 2;
704 43 : else in->ratio_aligned = 1;
705 :
706 66 : in->in_samples_pos = in->out_samples_pos = 0;
707 66 : in->scaled_sr = FIX2INT(in->src->samplerate * in->speed);
708 :
709 66 : in->bytes_p_samp = in->bit_depth * in->src->chan / 8;
710 : }
711 13982 : src_samp = (u32) (src_size / in->bytes_p_samp);
712 :
713 :
714 : memset(inChan, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
715 : memset(inChanNext, 0, sizeof(s32)*GF_AUDIO_MIXER_MAX_CHANNELS);
716 :
717 : /*while output not full and input data, convert*/
718 : next = prev = 0;
719 : while (1) {
720 : u64 src_pos, src_pos_unscale, lfrac;
721 8053182 : src_pos_unscale = in->out_samples_pos;
722 8053182 : src_pos_unscale *= in->scaled_sr;
723 : src_pos = src_pos_unscale;
724 8053182 : src_pos /= am->sample_rate;
725 8053182 : lfrac = src_pos_unscale - src_pos * am->sample_rate;
726 8053182 : lfrac *= RESAMPLE_SCALER;
727 8053182 : frac = (s32) (lfrac / am->sample_rate);
728 :
729 8053182 : if (src_samp) {
730 8053182 : if (src_pos < in->in_samples_pos) {
731 : use_prev = GF_TRUE;
732 : prev = 0;
733 : next = 0;
734 : } else {
735 8045246 : prev = (u32) (src_pos - in->in_samples_pos);
736 8045246 : next = prev+1;
737 : }
738 :
739 8053182 : if (prev>=src_samp)
740 : break;
741 8052673 : if (frac && (next>=src_samp))
742 : break;
743 :
744 8047641 : if (use_prev && prev)
745 : use_prev = GF_FALSE;
746 :
747 : }
748 : //end of stream, no fraction
749 : else {
750 0 : if (!frac || (src_pos >= in->in_samples_pos)) {
751 : //so that next call will trigger EOS for this stream
752 0 : in->has_prev = GF_FALSE;
753 0 : in->in_bytes_used = src_size + 1;
754 0 : return;
755 : }
756 : frac = 0;
757 : }
758 :
759 24111051 : for (j = 0; j < in_ch; j++) {
760 16063410 : inChan[j] = use_prev ? in->last_channels[j] : in->get_sample(in_data, in_ch, prev, j, planar_stride);
761 16063410 : if (frac) {
762 7954668 : inChanNext[j] = in->get_sample(in_data, in_ch, next, j, planar_stride);
763 7954668 : inChan[j] = (s32) ( ( ((s64) inChanNext[j])*frac + ((s64)inChan[j])*(RESAMPLE_SCALER-frac)) / RESAMPLE_SCALER );
764 : }
765 : //don't apply pan when forced layout is used
766 16063410 : if (!in->src->forced_layout && (in->pan[j]!=FIX_ONE) ) {
767 6334460 : inChan[j] = (s32) ( ((s64) inChan[j]) * FIX2INT(100 * in->pan[j]) / 100);
768 : }
769 : }
770 :
771 8047641 : if (in->speed <= am->max_speed) {
772 : //map inChannel to the output channel config
773 8046935 : gf_mixer_map_channels(inChan, in_ch, in->src->ch_layout, in->src->forced_layout, out_ch, am->channel_layout);
774 :
775 24108933 : for (j=0; j<out_ch ; j++) {
776 16061998 : *(in->ch_buf[j] + in->out_samples_written) = (s32) inChan[j];
777 : }
778 : } else {
779 1412 : for (j=0; j<out_ch ; j++) {
780 1412 : *(in->ch_buf[j] + in->out_samples_written) = 0;
781 : }
782 : }
783 :
784 8047641 : in->out_samples_written ++;
785 8047641 : in->out_samples_pos ++;
786 8047641 : if (in->out_samples_written == in->out_samples_to_write)
787 : break;
788 : }
789 : //eos
790 13982 : if (!src_samp)
791 : return;
792 :
793 13982 : if (in->ratio_aligned==1) {
794 2667 : in->has_prev = GF_FALSE;
795 2667 : if (next==src_samp) {
796 2468 : in->in_bytes_used = src_size;
797 : } else {
798 199 : in->in_bytes_used = MIN(src_size, prev * in->bytes_p_samp);
799 : }
800 : } else {
801 11315 : in->in_bytes_used = (prev+1) * in->bytes_p_samp;
802 11315 : in->has_prev = GF_TRUE;
803 :
804 11315 : if (!src_samp || (in->in_bytes_used >= src_size)) {
805 5692 : in->in_bytes_used = src_size;
806 5692 : for (j=0; j<in_ch; j++) in->last_channels[j] = inChanNext[j];
807 : } else {
808 : u32 idx;
809 5623 : idx = (prev >= src_samp) ? (src_samp-1) : (prev);
810 16869 : for (j=0; j<in_ch; j++) {
811 11246 : in->last_channels[j] = in->get_sample(in_data, in_ch, idx, j, planar_stride);
812 : }
813 : }
814 : }
815 13982 : in->in_samples_pos += in->in_bytes_used / in->bytes_p_samp;
816 :
817 : /*skip full seconds done*/
818 28145 : while ((in->in_samples_pos >= in->scaled_sr) && (in->out_samples_pos >= am->sample_rate)) {
819 181 : in->in_samples_pos -= in->scaled_sr;
820 181 : in->out_samples_pos -= am->sample_rate;
821 : }
822 :
823 : /*cf below, make sure we call release*/
824 13982 : in->in_bytes_used += 1;
825 : }
826 :
827 : GF_EXPORT
828 37121 : u32 gf_mixer_get_output(GF_AudioMixer *am, void *buffer, u32 buffer_size, u32 delay)
829 : {
830 : MixerInput *in, *single_source;
831 : Fixed pan[GF_AUDIO_MIXER_MAX_CHANNELS];
832 : Bool is_muted, force_mix;
833 : u32 i, j, count, size, in_size, nb_samples, nb_written;
834 : s32 *out_mix, nb_act_src;
835 : char *data, *ptr;
836 :
837 37121 : am->source_buffering = GF_FALSE;
838 : //reset buffer whatever the state of the mixer is
839 37121 : memset(buffer, 0, buffer_size);
840 :
841 : /*the config has changed we don't write to output since settings change*/
842 37121 : if (gf_mixer_reconfig(am)) return 0;
843 :
844 37020 : gf_mixer_lock(am, GF_TRUE);
845 37020 : count = gf_list_count(am->sources);
846 37020 : if (!count) {
847 5 : gf_mixer_lock(am, GF_FALSE);
848 5 : return 0;
849 : }
850 :
851 37015 : size=0;
852 : single_source = NULL;
853 37015 : if (count!=1) goto do_mix;
854 36830 : if (am->force_channel_out) goto do_mix;
855 36814 : single_source = (MixerInput *) gf_list_get(am->sources, 0);
856 : /*if cfg changed or unknown, reconfigure the mixer if the audio renderer is attached. Otherwise, the mixer config never changes internally*/
857 36814 : if (!single_source->src->GetConfig(single_source->src, GF_FALSE)) {
858 47 : single_source->ratio_aligned = 0;
859 47 : single_source->bit_depth = 0;
860 47 : if (am->ar) {
861 5 : am->must_reconfig = GF_TRUE;
862 5 : gf_mixer_reconfig(am);
863 5 : gf_mixer_lock(am, GF_FALSE);
864 5 : return 0;
865 : } else {
866 42 : gf_mixer_reconfig(am);
867 42 : gf_mixer_lock(am, GF_FALSE);
868 42 : return 0;
869 : }
870 : }
871 :
872 36767 : single_source->muted = single_source->src->IsMuted(single_source->src->callback);
873 : /*this happens if input SR cannot be mapped to output audio hardware*/
874 36767 : if (single_source->src->samplerate != am->sample_rate) goto do_mix;
875 : /*note we don't check output cfg: if the number of channel is the same then the channel cfg is the
876 : same*/
877 2961 : if (single_source->src->chan != am->nb_channels) goto do_mix;
878 2961 : if (single_source->src->GetSpeed(single_source->src->callback)!=FIX_ONE) goto do_mix;
879 2922 : if (single_source->src->GetChannelVolume(single_source->src->callback, pan)) goto do_mix;
880 2922 : if (single_source->src->afmt != am->afmt) goto do_mix;
881 :
882 371 : single_source_mix:
883 :
884 : ptr = (char *)buffer;
885 : in_size = buffer_size;
886 371 : is_muted = single_source->muted;
887 :
888 1108 : while (buffer_size) {
889 : u32 planar_stride;
890 372 : size = 0;
891 372 : data = single_source->src->FetchFrame(single_source->src->callback, &size, &planar_stride, delay);
892 372 : if (!data || !size) {
893 6 : am->source_buffering = single_source->src->is_buffering;
894 6 : break;
895 : }
896 : /*don't copy more than possible*/
897 366 : if (size > buffer_size) size = buffer_size;
898 366 : if (!is_muted) {
899 366 : memcpy(ptr, data, size);
900 : }
901 366 : buffer_size -= size;
902 366 : ptr += size;
903 366 : single_source->src->ReleaseFrame(single_source->src->callback, size);
904 366 : delay += size * 8000 / am->bit_depth / am->sample_rate / am->nb_channels;
905 : }
906 :
907 : /*not completely filled*/
908 371 : if (!size || !buffer_size) {
909 371 : if (buffer_size) {
910 6 : if (!data) {
911 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_AUDIO, ("[AudioMixer] not enough input data (%d still to fill)\n", buffer_size));
912 : }
913 : }
914 371 : gf_mixer_lock(am, GF_FALSE);
915 371 : return (in_size - buffer_size);
916 : }
917 :
918 : //otherwise, we do have some data but we had a change in config while writing the sample - fallthrough to full mix mode
919 : buffer = ptr;
920 :
921 :
922 36597 : do_mix:
923 : nb_act_src = 0;
924 36597 : nb_samples = buffer_size / (am->nb_channels * am->bit_depth / 8);
925 : /*step 1, cfg*/
926 36597 : if (am->output_size<buffer_size) {
927 56 : am->output = (s32*)gf_realloc(am->output, sizeof(s32) * buffer_size);
928 56 : am->output_size = buffer_size;
929 : }
930 :
931 : single_source = NULL;
932 : force_mix = GF_FALSE;
933 37152 : for (i=0; i<count; i++) {
934 : Fixed speed;
935 37152 : in = (MixerInput *)gf_list_get(am->sources, i);
936 37152 : in->muted = in->src->IsMuted(in->src->callback);
937 37152 : if (in->muted) continue;
938 37120 : if (!in->bit_depth) gf_am_configure_source(in);
939 :
940 37120 : if (in->buffer_size < nb_samples) {
941 1488 : for (j=0; j<GF_AUDIO_MIXER_MAX_CHANNELS; j++) {
942 1488 : in->ch_buf[j] = (s32 *) gf_realloc(in->ch_buf[j], sizeof(s32) * nb_samples);
943 : }
944 62 : in->buffer_size = nb_samples;
945 : }
946 37120 : speed = in->src->GetSpeed(in->src->callback);
947 37120 : if (speed != in->speed) {
948 66 : in->speed = speed;
949 66 : if (in->speed<0) in->speed *= -1;
950 66 : in->ratio_aligned = 0;
951 : }
952 37120 : in->out_samples_written = 0;
953 37120 : in->in_bytes_used = 0;
954 :
955 : /*if cfg unknown or changed (AudioBuffer child...) invalidate cfg settings*/
956 37120 : if (!in->src->GetConfig(in->src, GF_FALSE)) {
957 0 : if (am->ar) {
958 0 : if (!am->must_reconfig) {
959 0 : am->must_reconfig = GF_TRUE;
960 : /*if main mixer reconfig asap*/
961 0 : gf_mixer_reconfig(am);
962 : }
963 0 : in->muted = GF_TRUE;
964 0 : continue;
965 : }
966 : //otherwise fallthrough, mixer keeps the same config
967 : force_mix = GF_TRUE;
968 : }
969 :
970 37120 : if (in->speed==0) {
971 606 : in->out_samples_to_write = 0;
972 : } else {
973 : assert(in->src->samplerate);
974 36514 : in->out_samples_to_write = nb_samples;
975 36514 : if (in->src->IsMuted(in->src->callback)) {
976 0 : memset(in->pan, 0, sizeof(Fixed)*GF_AUDIO_MIXER_MAX_CHANNELS);
977 : } else {
978 36514 : if (!force_mix && !in->src->GetChannelVolume(in->src->callback, in->pan)) {
979 : /*track first active source with same cfg as mixer*/
980 20161 : if (!single_source && (in->src->samplerate == am->sample_rate)
981 2590 : && (in->src->chan == am->nb_channels)
982 2590 : && (in->speed == FIX_ONE)
983 2551 : && (in->src->afmt == am->afmt)
984 : )
985 : single_source = in;
986 : }
987 : }
988 36514 : nb_act_src ++;
989 : }
990 : }
991 36597 : if (!nb_act_src) {
992 638 : gf_mixer_lock(am, GF_FALSE);
993 638 : return 0;
994 : }
995 :
996 : /*if only one active source in native format, process as single source (direct copy)
997 : this is needed because mediaControl on an audio object doesn't deactivate it (eg the audio
998 : object is still present in the mixer). this opt is typically useful for language selection
999 : content (cf mp4menu)*/
1000 35959 : if ((nb_act_src==1) && single_source) goto single_source_mix;
1001 :
1002 : /*step 2, fill all buffers*/
1003 : while (1) {
1004 : u32 nb_to_fill = 0;
1005 : /*fill*/
1006 83078 : for (i=0; i<count; i++) {
1007 42055 : in = (MixerInput *)gf_list_get(am->sources, i);
1008 42055 : if (in->muted) {
1009 0 : in->out_samples_to_write = 0;
1010 0 : continue;
1011 : }
1012 42055 : if (in->out_samples_to_write > in->out_samples_written) {
1013 42054 : gf_mixer_fetch_input(am, in, delay /*+ 8000 * i / am->bits_per_sample / am->sample_rate / am->nb_channels*/ );
1014 42054 : if (in->out_samples_to_write > in->out_samples_written) nb_to_fill++;
1015 : }
1016 : }
1017 : /*release - this is done in 2 steps in case 2 audio object use the same source...*/
1018 42055 : for (i=0; i<count; i++) {
1019 42055 : in = (MixerInput *)gf_list_get(am->sources, i);
1020 42055 : if (in->muted) continue;
1021 42055 : if (in->in_bytes_used>1) in->src->ReleaseFrame(in->src->callback, in->in_bytes_used-1);
1022 42055 : in->in_bytes_used = 0;
1023 : }
1024 41023 : if (!nb_to_fill) break;
1025 : //only resync on the first fill
1026 : delay=0;
1027 : }
1028 : /*step 3, mix the final buffer*/
1029 35959 : memset(am->output, 0, sizeof(s32) * buffer_size);
1030 :
1031 : nb_written = 0;
1032 72473 : for (i=0; i<count; i++) {
1033 : u32 k;
1034 36514 : out_mix = am->output;
1035 36514 : in = (MixerInput *)gf_list_get(am->sources, i);
1036 36514 : if (!in->out_samples_written) continue;
1037 : /*only write what has been filled in the source buffer (may be less than output size)*/
1038 8047641 : for (j = 0; j < in->out_samples_written; j++) {
1039 16063410 : for (k = 0; k < am->nb_channels; k++) {
1040 16063410 : s64 oval = (*out_mix);
1041 16063410 : oval += *(in->ch_buf[k] + j);
1042 16063410 : if (oval>GF_INT_MAX) oval = GF_INT_MAX;
1043 16063410 : else if (oval<GF_INT_MIN) oval = GF_INT_MIN;
1044 16063410 : (*out_mix) = (s32) oval;
1045 16063410 : out_mix += 1;
1046 : }
1047 : }
1048 8528 : if (nb_written < in->out_samples_written) nb_written = in->out_samples_written;
1049 : }
1050 :
1051 35959 : if (!nb_written) {
1052 27968 : gf_mixer_lock(am, GF_FALSE);
1053 27968 : return 0;
1054 : }
1055 :
1056 : //TODO big-endian support (output is assumed to be little endian PCM)
1057 :
1058 : //we do not re-normalize based on the number of input, this is the author's responsability
1059 7991 : out_mix = am->output;
1060 7991 : if (am->afmt == GF_AUDIO_FMT_S32) {
1061 : s32 *out_s32 = (s32 *)buffer;
1062 18432 : for (i = 0; i < nb_written; i++) {
1063 36864 : for (j = 0; j < am->nb_channels; j++) {
1064 36864 : s32 samp = (*out_mix);
1065 36864 : (*out_s32) = samp;
1066 36864 : out_s32 += 1;
1067 36864 : out_mix += 1;
1068 : }
1069 : }
1070 : }
1071 7973 : else if (am->afmt == GF_AUDIO_FMT_S32P) {
1072 : s32 *out_s32 = (s32 *) buffer;
1073 36 : for (j = 0; j < am->nb_channels; j++) {
1074 36 : out_mix = am->output + j;
1075 36900 : for (i = 0; i < nb_written; i++) {
1076 36864 : s32 samp = (*out_mix);
1077 36864 : (*out_s32) = samp;
1078 36864 : out_s32 += 1;
1079 36864 : out_mix += am->nb_channels;
1080 : }
1081 : }
1082 : }
1083 7955 : else if (am->afmt == GF_AUDIO_FMT_FLT) {
1084 : Float *out_flt = (Float *)buffer;
1085 36864 : for (i = 0; i < nb_written; i++) {
1086 73728 : for (j = 0; j < am->nb_channels; j++) {
1087 73728 : s32 samp = (*out_mix);
1088 73728 : (*out_flt) = ((Float)samp) / GF_INT_MAX;
1089 73728 : out_flt += 1;
1090 73728 : out_mix += 1;
1091 : }
1092 : }
1093 : }
1094 7919 : else if (am->afmt == GF_AUDIO_FMT_FLTP) {
1095 : Float *out_flt = (Float *)buffer;
1096 3144 : for (j = 0; j < am->nb_channels; j++) {
1097 3144 : out_mix = am->output + j;
1098 1814088 : for (i = 0; i < nb_written; i++) {
1099 1810944 : s32 samp = (*out_mix);
1100 1810944 : (*out_flt) = ((Float)samp) / GF_INT_MAX;
1101 1810944 : out_flt += 1;
1102 1810944 : out_mix += am->nb_channels;
1103 : }
1104 : }
1105 : }
1106 6347 : else if (am->afmt == GF_AUDIO_FMT_DBL) {
1107 : Double *out_dbl = (Double *)buffer;
1108 18432 : for (i = 0; i < nb_written; i++) {
1109 36864 : for (j = 0; j < am->nb_channels; j++) {
1110 36864 : s32 samp = (*out_mix);
1111 36864 : (*out_dbl) = ((Double)samp) / GF_INT_MAX;
1112 36864 : out_dbl += 1;
1113 36864 : out_mix += 1;
1114 : }
1115 : }
1116 : }
1117 6329 : else if (am->afmt == GF_AUDIO_FMT_DBLP) {
1118 : Double *out_dbl = (Double *)buffer;
1119 36 : for (j = 0; j < am->nb_channels; j++) {
1120 36 : out_mix = am->output + j;
1121 36900 : for (i = 0; i < nb_written; i++) {
1122 36864 : s32 samp = (*out_mix);
1123 36864 : (*out_dbl) = ((Double)samp) / GF_INT_MAX;
1124 36864 : out_dbl += 1;
1125 36864 : out_mix += am->nb_channels;
1126 : }
1127 : }
1128 : }
1129 6311 : else if (am->afmt == GF_AUDIO_FMT_S24) {
1130 : s8 *out_s24 = (s8 *)buffer;
1131 18432 : for (i = 0; i<nb_written; i++) {
1132 36864 : for (j = 0; j<am->nb_channels; j++) {
1133 36864 : s32 samp = (*out_mix);
1134 : // char samp_c[4];
1135 36864 : samp /= MIX_S24_SCALE;
1136 36864 : if (samp > GF_S24_MAX) samp = GF_S24_MAX;
1137 36864 : else if (samp < GF_S24_MIN) samp = GF_S24_MIN;
1138 : // memcpy(samp_c, &samp, 3);
1139 36864 : out_s24[2] = (samp>>16) & 0xFF;
1140 36864 : out_s24[1] = (samp>>8) & 0xFF;
1141 36864 : out_s24[0] = samp & 0xFF;
1142 36864 : out_s24 += 3;
1143 36864 : out_mix += 1;
1144 : }
1145 : }
1146 6293 : } else if (am->afmt == GF_AUDIO_FMT_S24P) {
1147 : s8 *out_s24 = (s8 *)buffer;
1148 36 : for (j = 0; j<am->nb_channels; j++) {
1149 36 : out_mix = am->output + j;
1150 36900 : for (i = 0; i<nb_written; i++) {
1151 36864 : s32 samp = (*out_mix);
1152 : char s16tmp[2];
1153 : u8 lsb;
1154 36864 : samp /= MIX_S24_SCALE;
1155 36864 : if (samp > GF_S24_MAX) samp = GF_S24_MAX;
1156 36864 : else if (samp < GF_S24_MIN) samp = GF_S24_MIN;
1157 : lsb = (samp) & 0xFF;
1158 36864 : samp >>= 8;
1159 : // *((s16 *) (out_s24 +1) ) = (s16)samp;
1160 36864 : *((s16 *) s16tmp) = (s16)samp;
1161 36864 : memcpy(out_s24 +1, s16tmp, 2);
1162 36864 : out_s24[0] = lsb;
1163 36864 : out_s24 += 3;
1164 36864 : out_mix += am->nb_channels;
1165 : }
1166 : }
1167 6275 : } else if (am->afmt == GF_AUDIO_FMT_S16) {
1168 : s16 *out_s16 = (s16 *)buffer;
1169 6389529 : for (i = 0; i<nb_written; i++) {
1170 12747186 : for (j = 0; j<am->nb_channels; j++) {
1171 12747186 : s32 samp = (*out_mix);
1172 12747186 : samp /= MIX_S16_SCALE;
1173 12747186 : if (samp > GF_SHORT_MAX) samp = GF_SHORT_MAX;
1174 : else if (samp < GF_SHORT_MIN) samp = GF_SHORT_MIN;
1175 12747186 : (*out_s16) = samp;
1176 12747186 : out_s16 += 1;
1177 12747186 : out_mix += 1;
1178 : }
1179 : }
1180 54 : } else if (am->afmt == GF_AUDIO_FMT_S16P) {
1181 : s16 *out_s16 = (s16 *)buffer;
1182 36 : for (j = 0; j<am->nb_channels; j++) {
1183 36 : out_mix = am->output + j;
1184 36900 : for (i = 0; i<nb_written; i++) {
1185 36864 : s32 samp = (*out_mix);
1186 36864 : samp /= MIX_S16_SCALE;
1187 36864 : if (samp > GF_SHORT_MAX) samp = GF_SHORT_MAX;
1188 : else if (samp < GF_SHORT_MIN) samp = GF_SHORT_MIN;
1189 36864 : (*out_s16) = samp;
1190 36864 : out_s16 += 1;
1191 36864 : out_mix += am->nb_channels;
1192 : }
1193 : }
1194 36 : } else if (am->afmt == GF_AUDIO_FMT_U8) {
1195 : u8 *out_u8 = (u8 *) buffer;
1196 18432 : for (i=0; i<nb_written; i++) {
1197 36864 : for (j=0; j<am->nb_channels; j++) {
1198 36864 : s32 samp = (*out_mix ) / MIX_U8_SCALE;
1199 36864 : if (samp > 127) samp = 127;
1200 : else if (samp < -128) samp = -128;
1201 36864 : samp += 128;
1202 36864 : (*out_u8) = (u8) samp;
1203 36864 : out_u8 += 1;
1204 36864 : out_mix += 1;
1205 : }
1206 : }
1207 18 : } else if (am->afmt == GF_AUDIO_FMT_U8P) {
1208 : s8 *out_s8 = (s8 *) buffer;
1209 36 : for (j=0; j<am->nb_channels; j++) {
1210 36 : out_mix = am->output + j;
1211 36900 : for (i=0; i<nb_written; i++) {
1212 36864 : s32 samp = (*out_mix ) / MIX_U8_SCALE;
1213 36864 : if (samp > 127) samp = 127;
1214 : else if (samp < -128) samp = -128;
1215 36864 : samp += 128;
1216 36864 : (*out_s8) = samp;
1217 36864 : out_s8 += 1;
1218 36864 : out_mix += am->nb_channels;
1219 : }
1220 : }
1221 : }
1222 :
1223 7991 : nb_written *= am->nb_channels * am->bit_depth / 8;
1224 :
1225 7991 : gf_mixer_lock(am, GF_FALSE);
1226 7991 : return nb_written;
1227 : }
1228 :
1229 :
|