yading@11
|
1 /*
|
yading@11
|
2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
|
yading@11
|
3 *
|
yading@11
|
4 * This file is part of Libav.
|
yading@11
|
5 *
|
yading@11
|
6 * Libav is free software; you can redistribute it and/or
|
yading@11
|
7 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
8 * License as published by the Free Software Foundation; either
|
yading@11
|
9 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
10 *
|
yading@11
|
11 * Libav is distributed in the hope that it will be useful,
|
yading@11
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
14 * Lesser General Public License for more details.
|
yading@11
|
15 *
|
yading@11
|
16 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
17 * License along with Libav; if not, write to the Free Software
|
yading@11
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
19 */
|
yading@11
|
20
|
yading@11
|
21 #include <stdint.h>
|
yading@11
|
22
|
yading@11
|
23 #include "libavutil/common.h"
|
yading@11
|
24 #include "libavutil/libm.h"
|
yading@11
|
25 #include "libavutil/samplefmt.h"
|
yading@11
|
26 #include "avresample.h"
|
yading@11
|
27 #include "internal.h"
|
yading@11
|
28 #include "audio_data.h"
|
yading@11
|
29 #include "audio_mix.h"
|
yading@11
|
30
|
yading@11
|
31 static const char *coeff_type_names[] = { "q8", "q15", "flt" };
|
yading@11
|
32
|
yading@11
|
33 struct AudioMix {
|
yading@11
|
34 AVAudioResampleContext *avr;
|
yading@11
|
35 enum AVSampleFormat fmt;
|
yading@11
|
36 enum AVMixCoeffType coeff_type;
|
yading@11
|
37 uint64_t in_layout;
|
yading@11
|
38 uint64_t out_layout;
|
yading@11
|
39 int in_channels;
|
yading@11
|
40 int out_channels;
|
yading@11
|
41
|
yading@11
|
42 int ptr_align;
|
yading@11
|
43 int samples_align;
|
yading@11
|
44 int has_optimized_func;
|
yading@11
|
45 const char *func_descr;
|
yading@11
|
46 const char *func_descr_generic;
|
yading@11
|
47 mix_func *mix;
|
yading@11
|
48 mix_func *mix_generic;
|
yading@11
|
49
|
yading@11
|
50 int in_matrix_channels;
|
yading@11
|
51 int out_matrix_channels;
|
yading@11
|
52 int output_zero[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
53 int input_skip[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
54 int output_skip[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
55 int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
56 int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
57 float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
58 void **matrix;
|
yading@11
|
59 };
|
yading@11
|
60
|
yading@11
|
61 void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
|
yading@11
|
62 enum AVMixCoeffType coeff_type, int in_channels,
|
yading@11
|
63 int out_channels, int ptr_align, int samples_align,
|
yading@11
|
64 const char *descr, void *mix_func)
|
yading@11
|
65 {
|
yading@11
|
66 if (fmt == am->fmt && coeff_type == am->coeff_type &&
|
yading@11
|
67 ( in_channels == am->in_matrix_channels || in_channels == 0) &&
|
yading@11
|
68 (out_channels == am->out_matrix_channels || out_channels == 0)) {
|
yading@11
|
69 char chan_str[16];
|
yading@11
|
70 am->mix = mix_func;
|
yading@11
|
71 am->func_descr = descr;
|
yading@11
|
72 am->ptr_align = ptr_align;
|
yading@11
|
73 am->samples_align = samples_align;
|
yading@11
|
74 if (ptr_align == 1 && samples_align == 1) {
|
yading@11
|
75 am->mix_generic = mix_func;
|
yading@11
|
76 am->func_descr_generic = descr;
|
yading@11
|
77 } else {
|
yading@11
|
78 am->has_optimized_func = 1;
|
yading@11
|
79 }
|
yading@11
|
80 if (in_channels) {
|
yading@11
|
81 if (out_channels)
|
yading@11
|
82 snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
|
yading@11
|
83 in_channels, out_channels);
|
yading@11
|
84 else
|
yading@11
|
85 snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
|
yading@11
|
86 in_channels);
|
yading@11
|
87 } else if (out_channels) {
|
yading@11
|
88 snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
|
yading@11
|
89 out_channels);
|
yading@11
|
90 } else {
|
yading@11
|
91 snprintf(chan_str, sizeof(chan_str), "[any to any] ");
|
yading@11
|
92 }
|
yading@11
|
93 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
|
yading@11
|
94 "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
|
yading@11
|
95 coeff_type_names[coeff_type], chan_str, descr);
|
yading@11
|
96 }
|
yading@11
|
97 }
|
yading@11
|
98
|
yading@11
|
99 #define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
|
yading@11
|
100
|
yading@11
|
101 #define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
|
yading@11
|
102 static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
|
yading@11
|
103 int len, int out_ch, int in_ch) \
|
yading@11
|
104 { \
|
yading@11
|
105 int i, in, out; \
|
yading@11
|
106 stype temp[AVRESAMPLE_MAX_CHANNELS]; \
|
yading@11
|
107 for (i = 0; i < len; i++) { \
|
yading@11
|
108 for (out = 0; out < out_ch; out++) { \
|
yading@11
|
109 sumtype sum = 0; \
|
yading@11
|
110 for (in = 0; in < in_ch; in++) \
|
yading@11
|
111 sum += samples[in][i] * matrix[out][in]; \
|
yading@11
|
112 temp[out] = expr; \
|
yading@11
|
113 } \
|
yading@11
|
114 for (out = 0; out < out_ch; out++) \
|
yading@11
|
115 samples[out][i] = temp[out]; \
|
yading@11
|
116 } \
|
yading@11
|
117 }
|
yading@11
|
118
|
yading@11
|
119 MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
|
yading@11
|
120 MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
|
yading@11
|
121 MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
|
yading@11
|
122 MIX_FUNC_GENERIC(S16P, Q8, int16_t, int16_t, int32_t, av_clip_int16(sum >> 8))
|
yading@11
|
123
|
yading@11
|
124 /* TODO: templatize the channel-specific C functions */
|
yading@11
|
125
|
yading@11
|
126 static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
|
yading@11
|
127 int out_ch, int in_ch)
|
yading@11
|
128 {
|
yading@11
|
129 float *src0 = samples[0];
|
yading@11
|
130 float *src1 = samples[1];
|
yading@11
|
131 float *dst = src0;
|
yading@11
|
132 float m0 = matrix[0][0];
|
yading@11
|
133 float m1 = matrix[0][1];
|
yading@11
|
134
|
yading@11
|
135 while (len > 4) {
|
yading@11
|
136 *dst++ = *src0++ * m0 + *src1++ * m1;
|
yading@11
|
137 *dst++ = *src0++ * m0 + *src1++ * m1;
|
yading@11
|
138 *dst++ = *src0++ * m0 + *src1++ * m1;
|
yading@11
|
139 *dst++ = *src0++ * m0 + *src1++ * m1;
|
yading@11
|
140 len -= 4;
|
yading@11
|
141 }
|
yading@11
|
142 while (len > 0) {
|
yading@11
|
143 *dst++ = *src0++ * m0 + *src1++ * m1;
|
yading@11
|
144 len--;
|
yading@11
|
145 }
|
yading@11
|
146 }
|
yading@11
|
147
|
yading@11
|
148 static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
|
yading@11
|
149 int out_ch, int in_ch)
|
yading@11
|
150 {
|
yading@11
|
151 int16_t *src0 = samples[0];
|
yading@11
|
152 int16_t *src1 = samples[1];
|
yading@11
|
153 int16_t *dst = src0;
|
yading@11
|
154 float m0 = matrix[0][0];
|
yading@11
|
155 float m1 = matrix[0][1];
|
yading@11
|
156
|
yading@11
|
157 while (len > 4) {
|
yading@11
|
158 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
|
yading@11
|
159 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
|
yading@11
|
160 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
|
yading@11
|
161 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
|
yading@11
|
162 len -= 4;
|
yading@11
|
163 }
|
yading@11
|
164 while (len > 0) {
|
yading@11
|
165 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
|
yading@11
|
166 len--;
|
yading@11
|
167 }
|
yading@11
|
168 }
|
yading@11
|
169
|
yading@11
|
170 static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
|
yading@11
|
171 int out_ch, int in_ch)
|
yading@11
|
172 {
|
yading@11
|
173 int16_t *src0 = samples[0];
|
yading@11
|
174 int16_t *src1 = samples[1];
|
yading@11
|
175 int16_t *dst = src0;
|
yading@11
|
176 int16_t m0 = matrix[0][0];
|
yading@11
|
177 int16_t m1 = matrix[0][1];
|
yading@11
|
178
|
yading@11
|
179 while (len > 4) {
|
yading@11
|
180 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
|
yading@11
|
181 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
|
yading@11
|
182 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
|
yading@11
|
183 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
|
yading@11
|
184 len -= 4;
|
yading@11
|
185 }
|
yading@11
|
186 while (len > 0) {
|
yading@11
|
187 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
|
yading@11
|
188 len--;
|
yading@11
|
189 }
|
yading@11
|
190 }
|
yading@11
|
191
|
yading@11
|
192 static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
|
yading@11
|
193 int out_ch, int in_ch)
|
yading@11
|
194 {
|
yading@11
|
195 float v;
|
yading@11
|
196 float *dst0 = samples[0];
|
yading@11
|
197 float *dst1 = samples[1];
|
yading@11
|
198 float *src = dst0;
|
yading@11
|
199 float m0 = matrix[0][0];
|
yading@11
|
200 float m1 = matrix[1][0];
|
yading@11
|
201
|
yading@11
|
202 while (len > 4) {
|
yading@11
|
203 v = *src++;
|
yading@11
|
204 *dst0++ = v * m1;
|
yading@11
|
205 *dst1++ = v * m0;
|
yading@11
|
206 v = *src++;
|
yading@11
|
207 *dst0++ = v * m1;
|
yading@11
|
208 *dst1++ = v * m0;
|
yading@11
|
209 v = *src++;
|
yading@11
|
210 *dst0++ = v * m1;
|
yading@11
|
211 *dst1++ = v * m0;
|
yading@11
|
212 v = *src++;
|
yading@11
|
213 *dst0++ = v * m1;
|
yading@11
|
214 *dst1++ = v * m0;
|
yading@11
|
215 len -= 4;
|
yading@11
|
216 }
|
yading@11
|
217 while (len > 0) {
|
yading@11
|
218 v = *src++;
|
yading@11
|
219 *dst0++ = v * m1;
|
yading@11
|
220 *dst1++ = v * m0;
|
yading@11
|
221 len--;
|
yading@11
|
222 }
|
yading@11
|
223 }
|
yading@11
|
224
|
yading@11
|
225 static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
|
yading@11
|
226 int out_ch, int in_ch)
|
yading@11
|
227 {
|
yading@11
|
228 float v0, v1;
|
yading@11
|
229 float *src0 = samples[0];
|
yading@11
|
230 float *src1 = samples[1];
|
yading@11
|
231 float *src2 = samples[2];
|
yading@11
|
232 float *src3 = samples[3];
|
yading@11
|
233 float *src4 = samples[4];
|
yading@11
|
234 float *src5 = samples[5];
|
yading@11
|
235 float *dst0 = src0;
|
yading@11
|
236 float *dst1 = src1;
|
yading@11
|
237 float *m0 = matrix[0];
|
yading@11
|
238 float *m1 = matrix[1];
|
yading@11
|
239
|
yading@11
|
240 while (len > 0) {
|
yading@11
|
241 v0 = *src0++;
|
yading@11
|
242 v1 = *src1++;
|
yading@11
|
243 *dst0++ = v0 * m0[0] +
|
yading@11
|
244 v1 * m0[1] +
|
yading@11
|
245 *src2 * m0[2] +
|
yading@11
|
246 *src3 * m0[3] +
|
yading@11
|
247 *src4 * m0[4] +
|
yading@11
|
248 *src5 * m0[5];
|
yading@11
|
249 *dst1++ = v0 * m1[0] +
|
yading@11
|
250 v1 * m1[1] +
|
yading@11
|
251 *src2++ * m1[2] +
|
yading@11
|
252 *src3++ * m1[3] +
|
yading@11
|
253 *src4++ * m1[4] +
|
yading@11
|
254 *src5++ * m1[5];
|
yading@11
|
255 len--;
|
yading@11
|
256 }
|
yading@11
|
257 }
|
yading@11
|
258
|
yading@11
|
259 static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
|
yading@11
|
260 int out_ch, int in_ch)
|
yading@11
|
261 {
|
yading@11
|
262 float v0, v1;
|
yading@11
|
263 float *dst0 = samples[0];
|
yading@11
|
264 float *dst1 = samples[1];
|
yading@11
|
265 float *dst2 = samples[2];
|
yading@11
|
266 float *dst3 = samples[3];
|
yading@11
|
267 float *dst4 = samples[4];
|
yading@11
|
268 float *dst5 = samples[5];
|
yading@11
|
269 float *src0 = dst0;
|
yading@11
|
270 float *src1 = dst1;
|
yading@11
|
271
|
yading@11
|
272 while (len > 0) {
|
yading@11
|
273 v0 = *src0++;
|
yading@11
|
274 v1 = *src1++;
|
yading@11
|
275 *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
|
yading@11
|
276 *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
|
yading@11
|
277 *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
|
yading@11
|
278 *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
|
yading@11
|
279 *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
|
yading@11
|
280 *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
|
yading@11
|
281 len--;
|
yading@11
|
282 }
|
yading@11
|
283 }
|
yading@11
|
284
|
yading@11
|
285 static int mix_function_init(AudioMix *am)
|
yading@11
|
286 {
|
yading@11
|
287 am->func_descr = am->func_descr_generic = "n/a";
|
yading@11
|
288 am->mix = am->mix_generic = NULL;
|
yading@11
|
289
|
yading@11
|
290 /* no need to set a mix function when we're skipping mixing */
|
yading@11
|
291 if (!am->in_matrix_channels || !am->out_matrix_channels)
|
yading@11
|
292 return 0;
|
yading@11
|
293
|
yading@11
|
294 /* any-to-any C versions */
|
yading@11
|
295
|
yading@11
|
296 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
297 0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
|
yading@11
|
298
|
yading@11
|
299 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
300 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
|
yading@11
|
301
|
yading@11
|
302 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
|
yading@11
|
303 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
|
yading@11
|
304
|
yading@11
|
305 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
|
yading@11
|
306 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
|
yading@11
|
307
|
yading@11
|
308 /* channel-specific C versions */
|
yading@11
|
309
|
yading@11
|
310 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
311 2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
|
yading@11
|
312
|
yading@11
|
313 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
314 2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
|
yading@11
|
315
|
yading@11
|
316 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
|
yading@11
|
317 2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
|
yading@11
|
318
|
yading@11
|
319 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
320 1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
|
yading@11
|
321
|
yading@11
|
322 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
323 6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
|
yading@11
|
324
|
yading@11
|
325 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
|
yading@11
|
326 2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
|
yading@11
|
327
|
yading@11
|
328 if (ARCH_X86)
|
yading@11
|
329 ff_audio_mix_init_x86(am);
|
yading@11
|
330
|
yading@11
|
331 if (!am->mix) {
|
yading@11
|
332 av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
|
yading@11
|
333 "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
|
yading@11
|
334 coeff_type_names[am->coeff_type], am->in_channels,
|
yading@11
|
335 am->out_channels);
|
yading@11
|
336 return AVERROR_PATCHWELCOME;
|
yading@11
|
337 }
|
yading@11
|
338 return 0;
|
yading@11
|
339 }
|
yading@11
|
340
|
yading@11
|
341 AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
|
yading@11
|
342 {
|
yading@11
|
343 AudioMix *am;
|
yading@11
|
344 int ret;
|
yading@11
|
345
|
yading@11
|
346 am = av_mallocz(sizeof(*am));
|
yading@11
|
347 if (!am)
|
yading@11
|
348 return NULL;
|
yading@11
|
349 am->avr = avr;
|
yading@11
|
350
|
yading@11
|
351 if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
|
yading@11
|
352 avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
|
yading@11
|
353 av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
|
yading@11
|
354 "mixing: %s\n",
|
yading@11
|
355 av_get_sample_fmt_name(avr->internal_sample_fmt));
|
yading@11
|
356 goto error;
|
yading@11
|
357 }
|
yading@11
|
358
|
yading@11
|
359 am->fmt = avr->internal_sample_fmt;
|
yading@11
|
360 am->coeff_type = avr->mix_coeff_type;
|
yading@11
|
361 am->in_layout = avr->in_channel_layout;
|
yading@11
|
362 am->out_layout = avr->out_channel_layout;
|
yading@11
|
363 am->in_channels = avr->in_channels;
|
yading@11
|
364 am->out_channels = avr->out_channels;
|
yading@11
|
365
|
yading@11
|
366 /* build matrix if the user did not already set one */
|
yading@11
|
367 if (avr->mix_matrix) {
|
yading@11
|
368 ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
|
yading@11
|
369 if (ret < 0)
|
yading@11
|
370 goto error;
|
yading@11
|
371 av_freep(&avr->mix_matrix);
|
yading@11
|
372 } else {
|
yading@11
|
373 double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
|
yading@11
|
374 sizeof(*matrix_dbl));
|
yading@11
|
375 if (!matrix_dbl)
|
yading@11
|
376 goto error;
|
yading@11
|
377
|
yading@11
|
378 ret = avresample_build_matrix(avr->in_channel_layout,
|
yading@11
|
379 avr->out_channel_layout,
|
yading@11
|
380 avr->center_mix_level,
|
yading@11
|
381 avr->surround_mix_level,
|
yading@11
|
382 avr->lfe_mix_level,
|
yading@11
|
383 avr->normalize_mix_level,
|
yading@11
|
384 matrix_dbl,
|
yading@11
|
385 avr->in_channels,
|
yading@11
|
386 avr->matrix_encoding);
|
yading@11
|
387 if (ret < 0) {
|
yading@11
|
388 av_free(matrix_dbl);
|
yading@11
|
389 goto error;
|
yading@11
|
390 }
|
yading@11
|
391
|
yading@11
|
392 ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
|
yading@11
|
393 if (ret < 0) {
|
yading@11
|
394 av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
|
yading@11
|
395 av_free(matrix_dbl);
|
yading@11
|
396 goto error;
|
yading@11
|
397 }
|
yading@11
|
398
|
yading@11
|
399 av_free(matrix_dbl);
|
yading@11
|
400 }
|
yading@11
|
401
|
yading@11
|
402 return am;
|
yading@11
|
403
|
yading@11
|
404 error:
|
yading@11
|
405 av_free(am);
|
yading@11
|
406 return NULL;
|
yading@11
|
407 }
|
yading@11
|
408
|
yading@11
|
409 void ff_audio_mix_free(AudioMix **am_p)
|
yading@11
|
410 {
|
yading@11
|
411 AudioMix *am;
|
yading@11
|
412
|
yading@11
|
413 if (!*am_p)
|
yading@11
|
414 return;
|
yading@11
|
415 am = *am_p;
|
yading@11
|
416
|
yading@11
|
417 if (am->matrix) {
|
yading@11
|
418 av_free(am->matrix[0]);
|
yading@11
|
419 am->matrix = NULL;
|
yading@11
|
420 }
|
yading@11
|
421 memset(am->matrix_q8, 0, sizeof(am->matrix_q8 ));
|
yading@11
|
422 memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
|
yading@11
|
423 memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
|
yading@11
|
424
|
yading@11
|
425 av_freep(am_p);
|
yading@11
|
426 }
|
yading@11
|
427
|
yading@11
|
428 int ff_audio_mix(AudioMix *am, AudioData *src)
|
yading@11
|
429 {
|
yading@11
|
430 int use_generic = 1;
|
yading@11
|
431 int len = src->nb_samples;
|
yading@11
|
432 int i, j;
|
yading@11
|
433
|
yading@11
|
434 /* determine whether to use the optimized function based on pointer and
|
yading@11
|
435 samples alignment in both the input and output */
|
yading@11
|
436 if (am->has_optimized_func) {
|
yading@11
|
437 int aligned_len = FFALIGN(len, am->samples_align);
|
yading@11
|
438 if (!(src->ptr_align % am->ptr_align) &&
|
yading@11
|
439 src->samples_align >= aligned_len) {
|
yading@11
|
440 len = aligned_len;
|
yading@11
|
441 use_generic = 0;
|
yading@11
|
442 }
|
yading@11
|
443 }
|
yading@11
|
444 av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
|
yading@11
|
445 src->nb_samples, am->in_channels, am->out_channels,
|
yading@11
|
446 use_generic ? am->func_descr_generic : am->func_descr);
|
yading@11
|
447
|
yading@11
|
448 if (am->in_matrix_channels && am->out_matrix_channels) {
|
yading@11
|
449 uint8_t **data;
|
yading@11
|
450 uint8_t *data0[AVRESAMPLE_MAX_CHANNELS];
|
yading@11
|
451
|
yading@11
|
452 if (am->out_matrix_channels < am->out_channels ||
|
yading@11
|
453 am->in_matrix_channels < am->in_channels) {
|
yading@11
|
454 for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
|
yading@11
|
455 if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
|
yading@11
|
456 continue;
|
yading@11
|
457 data0[j++] = src->data[i];
|
yading@11
|
458 }
|
yading@11
|
459 data = data0;
|
yading@11
|
460 } else {
|
yading@11
|
461 data = src->data;
|
yading@11
|
462 }
|
yading@11
|
463
|
yading@11
|
464 if (use_generic)
|
yading@11
|
465 am->mix_generic(data, am->matrix, len, am->out_matrix_channels,
|
yading@11
|
466 am->in_matrix_channels);
|
yading@11
|
467 else
|
yading@11
|
468 am->mix(data, am->matrix, len, am->out_matrix_channels,
|
yading@11
|
469 am->in_matrix_channels);
|
yading@11
|
470 }
|
yading@11
|
471
|
yading@11
|
472 if (am->out_matrix_channels < am->out_channels) {
|
yading@11
|
473 for (i = 0; i < am->out_channels; i++)
|
yading@11
|
474 if (am->output_zero[i])
|
yading@11
|
475 av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
|
yading@11
|
476 }
|
yading@11
|
477
|
yading@11
|
478 ff_audio_data_set_channels(src, am->out_channels);
|
yading@11
|
479
|
yading@11
|
480 return 0;
|
yading@11
|
481 }
|
yading@11
|
482
|
yading@11
|
483 int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
|
yading@11
|
484 {
|
yading@11
|
485 int i, o, i0, o0;
|
yading@11
|
486
|
yading@11
|
487 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
|
yading@11
|
488 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
|
yading@11
|
489 av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
|
yading@11
|
490 return AVERROR(EINVAL);
|
yading@11
|
491 }
|
yading@11
|
492
|
yading@11
|
493 #define GET_MATRIX_CONVERT(suffix, scale) \
|
yading@11
|
494 if (!am->matrix_ ## suffix[0]) { \
|
yading@11
|
495 av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n"); \
|
yading@11
|
496 return AVERROR(EINVAL); \
|
yading@11
|
497 } \
|
yading@11
|
498 for (o = 0, o0 = 0; o < am->out_channels; o++) { \
|
yading@11
|
499 for (i = 0, i0 = 0; i < am->in_channels; i++) { \
|
yading@11
|
500 if (am->input_skip[i] || am->output_zero[o]) \
|
yading@11
|
501 matrix[o * stride + i] = 0.0; \
|
yading@11
|
502 else \
|
yading@11
|
503 matrix[o * stride + i] = am->matrix_ ## suffix[o0][i0] * \
|
yading@11
|
504 (scale); \
|
yading@11
|
505 if (!am->input_skip[i]) \
|
yading@11
|
506 i0++; \
|
yading@11
|
507 } \
|
yading@11
|
508 if (!am->output_zero[o]) \
|
yading@11
|
509 o0++; \
|
yading@11
|
510 }
|
yading@11
|
511
|
yading@11
|
512 switch (am->coeff_type) {
|
yading@11
|
513 case AV_MIX_COEFF_TYPE_Q8:
|
yading@11
|
514 GET_MATRIX_CONVERT(q8, 1.0 / 256.0);
|
yading@11
|
515 break;
|
yading@11
|
516 case AV_MIX_COEFF_TYPE_Q15:
|
yading@11
|
517 GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);
|
yading@11
|
518 break;
|
yading@11
|
519 case AV_MIX_COEFF_TYPE_FLT:
|
yading@11
|
520 GET_MATRIX_CONVERT(flt, 1.0);
|
yading@11
|
521 break;
|
yading@11
|
522 default:
|
yading@11
|
523 av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
|
yading@11
|
524 return AVERROR(EINVAL);
|
yading@11
|
525 }
|
yading@11
|
526
|
yading@11
|
527 return 0;
|
yading@11
|
528 }
|
yading@11
|
529
|
yading@11
|
530 static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
|
yading@11
|
531 {
|
yading@11
|
532 int i, o;
|
yading@11
|
533
|
yading@11
|
534 memset(am->output_zero, 0, sizeof(am->output_zero));
|
yading@11
|
535 memset(am->input_skip, 0, sizeof(am->input_skip));
|
yading@11
|
536 memset(am->output_skip, 0, sizeof(am->output_skip));
|
yading@11
|
537
|
yading@11
|
538 /* exclude output channels if they can be zeroed instead of mixed */
|
yading@11
|
539 for (o = 0; o < am->out_channels; o++) {
|
yading@11
|
540 int zero = 1;
|
yading@11
|
541
|
yading@11
|
542 /* check if the output is always silent */
|
yading@11
|
543 for (i = 0; i < am->in_channels; i++) {
|
yading@11
|
544 if (matrix[o * stride + i] != 0.0) {
|
yading@11
|
545 zero = 0;
|
yading@11
|
546 break;
|
yading@11
|
547 }
|
yading@11
|
548 }
|
yading@11
|
549 /* check if the corresponding input channel makes a contribution to
|
yading@11
|
550 any output channel */
|
yading@11
|
551 if (o < am->in_channels) {
|
yading@11
|
552 for (i = 0; i < am->out_channels; i++) {
|
yading@11
|
553 if (matrix[i * stride + o] != 0.0) {
|
yading@11
|
554 zero = 0;
|
yading@11
|
555 break;
|
yading@11
|
556 }
|
yading@11
|
557 }
|
yading@11
|
558 }
|
yading@11
|
559 if (zero) {
|
yading@11
|
560 am->output_zero[o] = 1;
|
yading@11
|
561 am->out_matrix_channels--;
|
yading@11
|
562 }
|
yading@11
|
563 }
|
yading@11
|
564 if (am->out_matrix_channels == 0) {
|
yading@11
|
565 am->in_matrix_channels = 0;
|
yading@11
|
566 return;
|
yading@11
|
567 }
|
yading@11
|
568
|
yading@11
|
569 /* skip input channels that contribute fully only to the corresponding
|
yading@11
|
570 output channel */
|
yading@11
|
571 for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
|
yading@11
|
572 int skip = 1;
|
yading@11
|
573
|
yading@11
|
574 for (o = 0; o < am->out_channels; o++) {
|
yading@11
|
575 int i0;
|
yading@11
|
576 if ((o != i && matrix[o * stride + i] != 0.0) ||
|
yading@11
|
577 (o == i && matrix[o * stride + i] != 1.0)) {
|
yading@11
|
578 skip = 0;
|
yading@11
|
579 break;
|
yading@11
|
580 }
|
yading@11
|
581 /* if the input contributes fully to the output, also check that no
|
yading@11
|
582 other inputs contribute to this output */
|
yading@11
|
583 if (o == i) {
|
yading@11
|
584 for (i0 = 0; i0 < am->in_channels; i0++) {
|
yading@11
|
585 if (i0 != i && matrix[o * stride + i0] != 0.0) {
|
yading@11
|
586 skip = 0;
|
yading@11
|
587 break;
|
yading@11
|
588 }
|
yading@11
|
589 }
|
yading@11
|
590 }
|
yading@11
|
591 }
|
yading@11
|
592 if (skip) {
|
yading@11
|
593 am->input_skip[i] = 1;
|
yading@11
|
594 am->in_matrix_channels--;
|
yading@11
|
595 }
|
yading@11
|
596 }
|
yading@11
|
597 /* skip input channels that do not contribute to any output channel */
|
yading@11
|
598 for (; i < am->in_channels; i++) {
|
yading@11
|
599 int contrib = 0;
|
yading@11
|
600
|
yading@11
|
601 for (o = 0; o < am->out_channels; o++) {
|
yading@11
|
602 if (matrix[o * stride + i] != 0.0) {
|
yading@11
|
603 contrib = 1;
|
yading@11
|
604 break;
|
yading@11
|
605 }
|
yading@11
|
606 }
|
yading@11
|
607 if (!contrib) {
|
yading@11
|
608 am->input_skip[i] = 1;
|
yading@11
|
609 am->in_matrix_channels--;
|
yading@11
|
610 }
|
yading@11
|
611 }
|
yading@11
|
612 if (am->in_matrix_channels == 0) {
|
yading@11
|
613 am->out_matrix_channels = 0;
|
yading@11
|
614 return;
|
yading@11
|
615 }
|
yading@11
|
616
|
yading@11
|
617 /* skip output channels that only get full contribution from the
|
yading@11
|
618 corresponding input channel */
|
yading@11
|
619 for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
|
yading@11
|
620 int skip = 1;
|
yading@11
|
621 int o0;
|
yading@11
|
622
|
yading@11
|
623 for (i = 0; i < am->in_channels; i++) {
|
yading@11
|
624 if ((o != i && matrix[o * stride + i] != 0.0) ||
|
yading@11
|
625 (o == i && matrix[o * stride + i] != 1.0)) {
|
yading@11
|
626 skip = 0;
|
yading@11
|
627 break;
|
yading@11
|
628 }
|
yading@11
|
629 }
|
yading@11
|
630 /* check if the corresponding input channel makes a contribution to
|
yading@11
|
631 any other output channel */
|
yading@11
|
632 i = o;
|
yading@11
|
633 for (o0 = 0; o0 < am->out_channels; o0++) {
|
yading@11
|
634 if (o0 != i && matrix[o0 * stride + i] != 0.0) {
|
yading@11
|
635 skip = 0;
|
yading@11
|
636 break;
|
yading@11
|
637 }
|
yading@11
|
638 }
|
yading@11
|
639 if (skip) {
|
yading@11
|
640 am->output_skip[o] = 1;
|
yading@11
|
641 am->out_matrix_channels--;
|
yading@11
|
642 }
|
yading@11
|
643 }
|
yading@11
|
644 if (am->out_matrix_channels == 0) {
|
yading@11
|
645 am->in_matrix_channels = 0;
|
yading@11
|
646 return;
|
yading@11
|
647 }
|
yading@11
|
648 }
|
yading@11
|
649
|
yading@11
|
650 int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
|
yading@11
|
651 {
|
yading@11
|
652 int i, o, i0, o0, ret;
|
yading@11
|
653 char in_layout_name[128];
|
yading@11
|
654 char out_layout_name[128];
|
yading@11
|
655
|
yading@11
|
656 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
|
yading@11
|
657 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
|
yading@11
|
658 av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
|
yading@11
|
659 return AVERROR(EINVAL);
|
yading@11
|
660 }
|
yading@11
|
661
|
yading@11
|
662 if (am->matrix) {
|
yading@11
|
663 av_free(am->matrix[0]);
|
yading@11
|
664 am->matrix = NULL;
|
yading@11
|
665 }
|
yading@11
|
666
|
yading@11
|
667 am->in_matrix_channels = am->in_channels;
|
yading@11
|
668 am->out_matrix_channels = am->out_channels;
|
yading@11
|
669
|
yading@11
|
670 reduce_matrix(am, matrix, stride);
|
yading@11
|
671
|
yading@11
|
672 #define CONVERT_MATRIX(type, expr) \
|
yading@11
|
673 am->matrix_## type[0] = av_mallocz(am->out_matrix_channels * \
|
yading@11
|
674 am->in_matrix_channels * \
|
yading@11
|
675 sizeof(*am->matrix_## type[0])); \
|
yading@11
|
676 if (!am->matrix_## type[0]) \
|
yading@11
|
677 return AVERROR(ENOMEM); \
|
yading@11
|
678 for (o = 0, o0 = 0; o < am->out_channels; o++) { \
|
yading@11
|
679 if (am->output_zero[o] || am->output_skip[o]) \
|
yading@11
|
680 continue; \
|
yading@11
|
681 if (o0 > 0) \
|
yading@11
|
682 am->matrix_## type[o0] = am->matrix_## type[o0 - 1] + \
|
yading@11
|
683 am->in_matrix_channels; \
|
yading@11
|
684 for (i = 0, i0 = 0; i < am->in_channels; i++) { \
|
yading@11
|
685 double v; \
|
yading@11
|
686 if (am->input_skip[i]) \
|
yading@11
|
687 continue; \
|
yading@11
|
688 v = matrix[o * stride + i]; \
|
yading@11
|
689 am->matrix_## type[o0][i0] = expr; \
|
yading@11
|
690 i0++; \
|
yading@11
|
691 } \
|
yading@11
|
692 o0++; \
|
yading@11
|
693 } \
|
yading@11
|
694 am->matrix = (void **)am->matrix_## type;
|
yading@11
|
695
|
yading@11
|
696 if (am->in_matrix_channels && am->out_matrix_channels) {
|
yading@11
|
697 switch (am->coeff_type) {
|
yading@11
|
698 case AV_MIX_COEFF_TYPE_Q8:
|
yading@11
|
699 CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
|
yading@11
|
700 break;
|
yading@11
|
701 case AV_MIX_COEFF_TYPE_Q15:
|
yading@11
|
702 CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
|
yading@11
|
703 break;
|
yading@11
|
704 case AV_MIX_COEFF_TYPE_FLT:
|
yading@11
|
705 CONVERT_MATRIX(flt, v)
|
yading@11
|
706 break;
|
yading@11
|
707 default:
|
yading@11
|
708 av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
|
yading@11
|
709 return AVERROR(EINVAL);
|
yading@11
|
710 }
|
yading@11
|
711 }
|
yading@11
|
712
|
yading@11
|
713 ret = mix_function_init(am);
|
yading@11
|
714 if (ret < 0)
|
yading@11
|
715 return ret;
|
yading@11
|
716
|
yading@11
|
717 av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
|
yading@11
|
718 am->in_channels, am->in_layout);
|
yading@11
|
719 av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
|
yading@11
|
720 am->out_channels, am->out_layout);
|
yading@11
|
721 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
|
yading@11
|
722 in_layout_name, out_layout_name);
|
yading@11
|
723 av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
|
yading@11
|
724 am->in_matrix_channels, am->out_matrix_channels);
|
yading@11
|
725 for (o = 0; o < am->out_channels; o++) {
|
yading@11
|
726 for (i = 0; i < am->in_channels; i++) {
|
yading@11
|
727 if (am->output_zero[o])
|
yading@11
|
728 av_log(am->avr, AV_LOG_DEBUG, " (ZERO)");
|
yading@11
|
729 else if (am->input_skip[i] || am->output_skip[o])
|
yading@11
|
730 av_log(am->avr, AV_LOG_DEBUG, " (SKIP)");
|
yading@11
|
731 else
|
yading@11
|
732 av_log(am->avr, AV_LOG_DEBUG, " %0.3f ",
|
yading@11
|
733 matrix[o * am->in_channels + i]);
|
yading@11
|
734 }
|
yading@11
|
735 av_log(am->avr, AV_LOG_DEBUG, "\n");
|
yading@11
|
736 }
|
yading@11
|
737
|
yading@11
|
738 return 0;
|
yading@11
|
739 }
|