lavr: replace the SSE version of ff_conv_fltp_to_flt_6ch() with SSE4 and AVX
[ffmpeg.git] / libavresample / audio_mix.c
1 /*
2  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <stdint.h>
22
23 #include "libavutil/libm.h"
24 #include "libavutil/samplefmt.h"
25 #include "avresample.h"
26 #include "internal.h"
27 #include "audio_data.h"
28 #include "audio_mix.h"
29
30 static const char *coeff_type_names[] = { "q8", "q15", "flt" };
31
32 void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
33                            enum AVMixCoeffType coeff_type, int in_channels,
34                            int out_channels, int ptr_align, int samples_align,
35                            const char *descr, void *mix_func)
36 {
37     if (fmt == am->fmt && coeff_type == am->coeff_type &&
38         ( in_channels ==  am->in_channels ||  in_channels == 0) &&
39         (out_channels == am->out_channels || out_channels == 0)) {
40         char chan_str[16];
41         am->mix           = mix_func;
42         am->func_descr    = descr;
43         am->ptr_align     = ptr_align;
44         am->samples_align = samples_align;
45         if (ptr_align == 1 && samples_align == 1) {
46             am->mix_generic        = mix_func;
47             am->func_descr_generic = descr;
48         } else {
49             am->has_optimized_func = 1;
50         }
51         if (in_channels) {
52             if (out_channels)
53                 snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
54                          in_channels, out_channels);
55             else
56                 snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
57                          in_channels);
58         } else if (out_channels) {
59                 snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
60                          out_channels);
61         }
62         av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
63                "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
64                coeff_type_names[coeff_type],
65                (in_channels || out_channels) ? chan_str : "", descr);
66     }
67 }
68
69 #define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
70
71 #define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr)            \
72 static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix,       \
73                                      int len, int out_ch, int in_ch)        \
74 {                                                                           \
75     int i, in, out;                                                         \
76     stype temp[AVRESAMPLE_MAX_CHANNELS];                                    \
77     for (i = 0; i < len; i++) {                                             \
78         for (out = 0; out < out_ch; out++) {                                \
79             sumtype sum = 0;                                                \
80             for (in = 0; in < in_ch; in++)                                  \
81                 sum += samples[in][i] * matrix[out][in];                    \
82             temp[out] = expr;                                               \
83         }                                                                   \
84         for (out = 0; out < out_ch; out++)                                  \
85             samples[out][i] = temp[out];                                    \
86     }                                                                       \
87 }
88
89 MIX_FUNC_GENERIC(FLTP, FLT, float,   float,   float,   sum)
90 MIX_FUNC_GENERIC(S16P, FLT, int16_t, float,   float,   av_clip_int16(lrintf(sum)))
91 MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
92 MIX_FUNC_GENERIC(S16P, Q8,  int16_t, int16_t, int32_t, av_clip_int16(sum >>  8))
93
94 /* TODO: templatize the channel-specific C functions */
95
96 static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
97                                   int out_ch, int in_ch)
98 {
99     float *src0 = samples[0];
100     float *src1 = samples[1];
101     float *dst  = src0;
102     float m0    = matrix[0][0];
103     float m1    = matrix[0][1];
104
105     while (len > 4) {
106         *dst++ = *src0++ * m0 + *src1++ * m1;
107         *dst++ = *src0++ * m0 + *src1++ * m1;
108         *dst++ = *src0++ * m0 + *src1++ * m1;
109         *dst++ = *src0++ * m0 + *src1++ * m1;
110         len -= 4;
111     }
112     while (len > 0) {
113         *dst++ = *src0++ * m0 + *src1++ * m1;
114         len--;
115     }
116 }
117
118 static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
119                                   int out_ch, int in_ch)
120 {
121     float v;
122     float *dst0 = samples[0];
123     float *dst1 = samples[1];
124     float *src  = dst0;
125     float m0    = matrix[0][0];
126     float m1    = matrix[1][0];
127
128     while (len > 4) {
129         v = *src++;
130         *dst0++ = v * m1;
131         *dst1++ = v * m0;
132         v = *src++;
133         *dst0++ = v * m1;
134         *dst1++ = v * m0;
135         v = *src++;
136         *dst0++ = v * m1;
137         *dst1++ = v * m0;
138         v = *src++;
139         *dst0++ = v * m1;
140         *dst1++ = v * m0;
141         len -= 4;
142     }
143     while (len > 0) {
144         v = *src++;
145         *dst0++ = v * m1;
146         *dst1++ = v * m0;
147         len--;
148     }
149 }
150
151 static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
152                                   int out_ch, int in_ch)
153 {
154     float v0, v1;
155     float *src0 = samples[0];
156     float *src1 = samples[1];
157     float *src2 = samples[2];
158     float *src3 = samples[3];
159     float *src4 = samples[4];
160     float *src5 = samples[5];
161     float *dst0 = src0;
162     float *dst1 = src1;
163     float *m0   = matrix[0];
164     float *m1   = matrix[1];
165
166     while (len > 0) {
167         v0 = *src0++;
168         v1 = *src1++;
169         *dst0++ = v0      * m0[0] +
170                   v1      * m0[1] +
171                   *src2   * m0[2] +
172                   *src3   * m0[3] +
173                   *src4   * m0[4] +
174                   *src5   * m0[5];
175         *dst1++ = v0      * m1[0] +
176                   v1      * m1[1] +
177                   *src2++ * m1[2] +
178                   *src3++ * m1[3] +
179                   *src4++ * m1[4] +
180                   *src5++ * m1[5];
181         len--;
182     }
183 }
184
185 static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
186                                   int out_ch, int in_ch)
187 {
188     float v0, v1;
189     float *dst0 = samples[0];
190     float *dst1 = samples[1];
191     float *dst2 = samples[2];
192     float *dst3 = samples[3];
193     float *dst4 = samples[4];
194     float *dst5 = samples[5];
195     float *src0 = dst0;
196     float *src1 = dst1;
197
198     while (len > 0) {
199         v0 = *src0++;
200         v1 = *src1++;
201         *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
202         *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
203         *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
204         *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
205         *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
206         *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
207         len--;
208     }
209 }
210
211 static int mix_function_init(AudioMix *am)
212 {
213     /* any-to-any C versions */
214
215     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
216                           0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
217
218     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
219                           0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
220
221     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
222                           0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
223
224     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
225                           0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
226
227     /* channel-specific C versions */
228
229     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
230                           2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
231
232     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
233                           1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
234
235     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
236                           6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
237
238     ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
239                           2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
240
241     if (ARCH_X86)
242         ff_audio_mix_init_x86(am);
243
244     if (!am->mix) {
245         av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
246                "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
247                coeff_type_names[am->coeff_type], am->in_channels,
248                am->out_channels);
249         return AVERROR_PATCHWELCOME;
250     }
251     return 0;
252 }
253
254 int ff_audio_mix_init(AVAudioResampleContext *avr)
255 {
256     int ret;
257
258     /* build matrix if the user did not already set one */
259     if (!avr->am->matrix) {
260         int i, j;
261         char in_layout_name[128];
262         char out_layout_name[128];
263         double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
264                                         sizeof(*matrix_dbl));
265         if (!matrix_dbl)
266             return AVERROR(ENOMEM);
267
268         ret = avresample_build_matrix(avr->in_channel_layout,
269                                       avr->out_channel_layout,
270                                       avr->center_mix_level,
271                                       avr->surround_mix_level,
272                                       avr->lfe_mix_level, 1, matrix_dbl,
273                                       avr->in_channels);
274         if (ret < 0) {
275             av_free(matrix_dbl);
276             return ret;
277         }
278
279         av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
280                                      avr->in_channels, avr->in_channel_layout);
281         av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
282                                      avr->out_channels, avr->out_channel_layout);
283         av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
284                in_layout_name, out_layout_name);
285         for (i = 0; i < avr->out_channels; i++) {
286             for (j = 0; j < avr->in_channels; j++) {
287                 av_log(avr, AV_LOG_DEBUG, "  %0.3f ",
288                        matrix_dbl[i * avr->in_channels + j]);
289             }
290             av_log(avr, AV_LOG_DEBUG, "\n");
291         }
292
293         ret = avresample_set_matrix(avr, matrix_dbl, avr->in_channels);
294         if (ret < 0) {
295             av_free(matrix_dbl);
296             return ret;
297         }
298         av_free(matrix_dbl);
299     }
300
301     avr->am->fmt          = avr->internal_sample_fmt;
302     avr->am->coeff_type   = avr->mix_coeff_type;
303     avr->am->in_layout    = avr->in_channel_layout;
304     avr->am->out_layout   = avr->out_channel_layout;
305     avr->am->in_channels  = avr->in_channels;
306     avr->am->out_channels = avr->out_channels;
307
308     ret = mix_function_init(avr->am);
309     if (ret < 0)
310         return ret;
311
312     return 0;
313 }
314
315 void ff_audio_mix_close(AudioMix *am)
316 {
317     if (!am)
318         return;
319     if (am->matrix) {
320         av_free(am->matrix[0]);
321         am->matrix = NULL;
322     }
323     memset(am->matrix_q8,  0, sizeof(am->matrix_q8 ));
324     memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
325     memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
326 }
327
328 int ff_audio_mix(AudioMix *am, AudioData *src)
329 {
330     int use_generic = 1;
331     int len = src->nb_samples;
332
333     /* determine whether to use the optimized function based on pointer and
334        samples alignment in both the input and output */
335     if (am->has_optimized_func) {
336         int aligned_len = FFALIGN(len, am->samples_align);
337         if (!(src->ptr_align % am->ptr_align) &&
338             src->samples_align >= aligned_len) {
339             len = aligned_len;
340             use_generic = 0;
341         }
342     }
343     av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
344             src->nb_samples, am->in_channels, am->out_channels,
345             use_generic ? am->func_descr_generic : am->func_descr);
346
347     if (use_generic)
348         am->mix_generic(src->data, am->matrix, len, am->out_channels,
349                         am->in_channels);
350     else
351         am->mix(src->data, am->matrix, len, am->out_channels, am->in_channels);
352
353     ff_audio_data_set_channels(src, am->out_channels);
354
355     return 0;
356 }