aboutsummaryrefslogtreecommitdiff
path: root/libavresample
diff options
context:
space:
mode:
Diffstat (limited to 'libavresample')
-rw-r--r--libavresample/audio_mix.c50
-rw-r--r--libavresample/x86/audio_mix.asm86
-rw-r--r--libavresample/x86/audio_mix_init.c18
-rw-r--r--libavresample/x86/util.asm34
4 files changed, 188 insertions, 0 deletions
diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
index 76f10eaab2..7ab11b0d4d 100644
--- a/libavresample/audio_mix.c
+++ b/libavresample/audio_mix.c
@@ -115,6 +115,50 @@ static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
}
}
+static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
+ int out_ch, int in_ch)
+{
+ int16_t *src0 = samples[0];
+ int16_t *src1 = samples[1];
+ int16_t *dst = src0;
+ float m0 = matrix[0][0];
+ float m1 = matrix[0][1];
+
+ while (len > 4) {
+ *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
+ *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
+ *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
+ *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
+ len -= 4;
+ }
+ while (len > 0) {
+ *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
+ len--;
+ }
+}
+
+static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
+ int out_ch, int in_ch)
+{
+ int16_t *src0 = samples[0];
+ int16_t *src1 = samples[1];
+ int16_t *dst = src0;
+ int16_t m0 = matrix[0][0];
+ int16_t m1 = matrix[0][1];
+
+ while (len > 4) {
+ *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
+ *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
+ *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
+ *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
+ len -= 4;
+ }
+ while (len > 0) {
+ *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
+ len--;
+ }
+}
+
static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
int out_ch, int in_ch)
{
@@ -229,6 +273,12 @@ static int mix_function_init(AudioMix *am)
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
+ 2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
+
+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
+ 2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
+
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
diff --git a/libavresample/x86/audio_mix.asm b/libavresample/x86/audio_mix.asm
index dbc79e585d..8a4cf061cd 100644
--- a/libavresample/x86/audio_mix.asm
+++ b/libavresample/x86/audio_mix.asm
@@ -21,6 +21,7 @@
%include "x86inc.asm"
%include "x86util.asm"
+%include "util.asm"
SECTION_TEXT
@@ -64,3 +65,88 @@ MIX_2_TO_1_FLTP_FLT
INIT_YMM avx
MIX_2_TO_1_FLTP_FLT
%endif
+
+;-----------------------------------------------------------------------------
+; void ff_mix_2_to_1_s16p_flt(int16_t **src, float **matrix, int len,
+; int out_ch, int in_ch);
+;-----------------------------------------------------------------------------
+
+%macro MIX_2_TO_1_S16P_FLT 0
+cglobal mix_2_to_1_s16p_flt, 3,4,6, src, matrix, len, src1
+ mov src1q, [srcq+gprsize]
+ mov srcq, [srcq]
+ sub src1q, srcq
+ mov matrixq, [matrixq ]
+ VBROADCASTSS m4, [matrixq ]
+ VBROADCASTSS m5, [matrixq+4]
+ ALIGN 16
+.loop:
+ mova m0, [srcq ]
+ mova m2, [srcq+src1q]
+ S16_TO_S32_SX 0, 1
+ S16_TO_S32_SX 2, 3
+ cvtdq2ps m0, m0
+ cvtdq2ps m1, m1
+ cvtdq2ps m2, m2
+ cvtdq2ps m3, m3
+ mulps m0, m4
+ mulps m1, m4
+ mulps m2, m5
+ mulps m3, m5
+ addps m0, m2
+ addps m1, m3
+ cvtps2dq m0, m0
+ cvtps2dq m1, m1
+ packssdw m0, m1
+ mova [srcq], m0
+ add srcq, mmsize
+ sub lend, mmsize/2
+ jg .loop
+ REP_RET
+%endmacro
+
+INIT_XMM sse2
+MIX_2_TO_1_S16P_FLT
+INIT_XMM sse4
+MIX_2_TO_1_S16P_FLT
+
+;-----------------------------------------------------------------------------
+; void ff_mix_2_to_1_s16p_q8(int16_t **src, int16_t **matrix, int len,
+; int out_ch, int in_ch);
+;-----------------------------------------------------------------------------
+
+INIT_XMM sse2
+cglobal mix_2_to_1_s16p_q8, 3,4,6, src, matrix, len, src1
+ mov src1q, [srcq+gprsize]
+ mov srcq, [srcq]
+ sub src1q, srcq
+ mov matrixq, [matrixq]
+ movd m4, [matrixq]
+ movd m5, [matrixq]
+ SPLATW m4, m4, 0
+ SPLATW m5, m5, 1
+ pxor m0, m0
+ punpcklwd m4, m0
+ punpcklwd m5, m0
+ ALIGN 16
+.loop:
+ mova m0, [srcq ]
+ mova m2, [srcq+src1q]
+ punpckhwd m1, m0, m0
+ punpcklwd m0, m0
+ punpckhwd m3, m2, m2
+ punpcklwd m2, m2
+ pmaddwd m0, m4
+ pmaddwd m1, m4
+ pmaddwd m2, m5
+ pmaddwd m3, m5
+ paddd m0, m2
+ paddd m1, m3
+ psrad m0, 8
+ psrad m1, 8
+ packssdw m0, m1
+ mova [srcq], m0
+ add srcq, mmsize
+ sub lend, mmsize/2
+ jg .loop
+ REP_RET
diff --git a/libavresample/x86/audio_mix_init.c b/libavresample/x86/audio_mix_init.c
index 8f8930f836..fa204d6d36 100644
--- a/libavresample/x86/audio_mix_init.c
+++ b/libavresample/x86/audio_mix_init.c
@@ -27,6 +27,14 @@ extern void ff_mix_2_to_1_fltp_flt_sse(float **src, float **matrix, int len,
extern void ff_mix_2_to_1_fltp_flt_avx(float **src, float **matrix, int len,
int out_ch, int in_ch);
+extern void ff_mix_2_to_1_s16p_flt_sse2(int16_t **src, float **matrix, int len,
+ int out_ch, int in_ch);
+extern void ff_mix_2_to_1_s16p_flt_sse4(int16_t **src, float **matrix, int len,
+ int out_ch, int in_ch);
+
+extern void ff_mix_2_to_1_s16p_q8_sse2(int16_t **src, int16_t **matrix,
+ int len, int out_ch, int in_ch);
+
av_cold void ff_audio_mix_init_x86(AudioMix *am)
{
#if HAVE_YASM
@@ -36,6 +44,16 @@ av_cold void ff_audio_mix_init_x86(AudioMix *am)
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
2, 1, 16, 8, "SSE", ff_mix_2_to_1_fltp_flt_sse);
}
+ if (mm_flags & AV_CPU_FLAG_SSE2 && HAVE_SSE) {
+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
+ 2, 1, 16, 8, "SSE2", ff_mix_2_to_1_s16p_flt_sse2);
+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
+ 2, 1, 16, 8, "SSE2", ff_mix_2_to_1_s16p_q8_sse2);
+ }
+ if (mm_flags & AV_CPU_FLAG_SSE4 && HAVE_SSE) {
+ ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
+ 2, 1, 16, 8, "SSE4", ff_mix_2_to_1_s16p_flt_sse4);
+ }
if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
2, 1, 32, 16, "AVX", ff_mix_2_to_1_fltp_flt_avx);
diff --git a/libavresample/x86/util.asm b/libavresample/x86/util.asm
new file mode 100644
index 0000000000..501f662d43
--- /dev/null
+++ b/libavresample/x86/util.asm
@@ -0,0 +1,34 @@
+;******************************************************************************
+;* x86 utility macros for libavresample
+;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
+;*
+;* This file is part of Libav.
+;*
+;* Libav is free software; you can redistribute it and/or
+;* modify it under the terms of the GNU Lesser General Public
+;* License as published by the Free Software Foundation; either
+;* version 2.1 of the License, or (at your option) any later version.
+;*
+;* Libav is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;* Lesser General Public License for more details.
+;*
+;* You should have received a copy of the GNU Lesser General Public
+;* License along with Libav; if not, write to the Free Software
+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;******************************************************************************
+
+%macro S16_TO_S32_SX 2 ; src/low dst, high dst
+%if cpuflag(sse4)
+ pmovsxwd m%2, m%1
+ psrldq m%1, 8
+ pmovsxwd m%1, m%1
+ SWAP %1, %2
+%else
+ punpckhwd m%2, m%1
+ punpcklwd m%1, m%1
+ psrad m%2, 16
+ psrad m%1, 16
+%endif
+%endmacro