|
|
|
/*
|
|
|
|
* Bluetooth low-complexity, subband codec (SBC)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org>
|
|
|
|
* Copyright (C) 2008-2010 Nokia Corporation
|
|
|
|
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
|
|
|
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
|
|
|
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
|
|
|
*
|
|
|
|
* This file is part of FFmpeg.
|
|
|
|
*
|
|
|
|
* FFmpeg 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.
|
|
|
|
*
|
|
|
|
* FFmpeg 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 FFmpeg; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* SBC ARM NEON optimizations
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "libavutil/arm/asm.S"
|
|
|
|
#include "neon.S"
|
|
|
|
|
|
|
|
#define SBC_PROTO_FIXED_SCALE 16
|
|
|
|
|
|
|
|
function ff_sbc_analyze_4_neon, export=1
|
|
|
|
/* TODO: merge even and odd cases (or even merge all four calls to this
|
|
|
|
* function) in order to have only aligned reads from 'in' array
|
|
|
|
* and reduce number of load instructions */
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmull.s16 q0, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmull.s16 q1, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q0, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmlal.s16 q1, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q0, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmlal.s16 q1, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q0, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmlal.s16 q1, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q0, d16, d20
|
|
|
|
vmlal.s16 q1, d17, d21
|
|
|
|
|
|
|
|
vpadd.s32 d0, d0, d1
|
|
|
|
vpadd.s32 d1, d2, d3
|
|
|
|
|
|
|
|
vrshrn.s32 d0, q0, SBC_PROTO_FIXED_SCALE
|
|
|
|
|
|
|
|
vld1.16 {d16, d17, d18, d19}, [r2, :128]!
|
|
|
|
|
|
|
|
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
|
|
|
|
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
|
|
|
|
|
|
|
|
vmull.s16 q10, d16, d0
|
|
|
|
vmull.s16 q11, d17, d0
|
|
|
|
vmlal.s16 q10, d18, d1
|
|
|
|
vmlal.s16 q11, d19, d1
|
|
|
|
|
|
|
|
vpadd.s32 d0, d20, d21 /* TODO: can be eliminated */
|
|
|
|
vpadd.s32 d1, d22, d23 /* TODO: can be eliminated */
|
|
|
|
|
|
|
|
vst1.32 {d0, d1}, [r1, :128]
|
|
|
|
|
|
|
|
bx lr
|
|
|
|
endfunc
|
|
|
|
|
|
|
|
function ff_sbc_analyze_8_neon, export=1
|
|
|
|
/* TODO: merge even and odd cases (or even merge all four calls to this
|
|
|
|
* function) in order to have only aligned reads from 'in' array
|
|
|
|
* and reduce number of load instructions */
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmull.s16 q12, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmull.s16 q13, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmull.s16 q14, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmull.s16 q15, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmlal.s16 q13, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q14, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmlal.s16 q15, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmlal.s16 q13, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q14, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmlal.s16 q15, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmlal.s16 q13, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
vmlal.s16 q14, d18, d22
|
|
|
|
vld1.16 {d16, d17}, [r0, :64]!
|
|
|
|
vmlal.s16 q15, d19, d23
|
|
|
|
vld1.16 {d20, d21}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q12, d16, d20
|
|
|
|
vld1.16 {d18, d19}, [r0, :64]!
|
|
|
|
vmlal.s16 q13, d17, d21
|
|
|
|
vld1.16 {d22, d23}, [r2, :128]!
|
|
|
|
|
|
|
|
vmlal.s16 q14, d18, d22
|
|
|
|
vmlal.s16 q15, d19, d23
|
|
|
|
|
|
|
|
vpadd.s32 d0, d24, d25
|
|
|
|
vpadd.s32 d1, d26, d27
|
|
|
|
vpadd.s32 d2, d28, d29
|
|
|
|
vpadd.s32 d3, d30, d31
|
|
|
|
|
|
|
|
vrshr.s32 q0, q0, SBC_PROTO_FIXED_SCALE
|
|
|
|
vrshr.s32 q1, q1, SBC_PROTO_FIXED_SCALE
|
|
|
|
vmovn.s32 d0, q0
|
|
|
|
vmovn.s32 d1, q1
|
|
|
|
|
|
|
|
vdup.i32 d3, d1[1] /* TODO: can be eliminated */
|
|
|
|
vdup.i32 d2, d1[0] /* TODO: can be eliminated */
|
|
|
|
vdup.i32 d1, d0[1] /* TODO: can be eliminated */
|
|
|
|
vdup.i32 d0, d0[0] /* TODO: can be eliminated */
|
|
|
|
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
|
|
vmull.s16 q12, d16, d0
|
|
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
|
|
vmull.s16 q13, d17, d0
|
|
|
|
vmull.s16 q14, d18, d0
|
|
|
|
vmull.s16 q15, d19, d0
|
|
|
|
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d1
|
|
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
|
|
vmlal.s16 q13, d17, d1
|
|
|
|
vmlal.s16 q14, d18, d1
|
|
|
|
vmlal.s16 q15, d19, d1
|
|
|
|
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d2
|
|
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
|
|
vmlal.s16 q13, d17, d2
|
|
|
|
vmlal.s16 q14, d18, d2
|
|
|
|
vmlal.s16 q15, d19, d2
|
|
|
|
|
|
|
|
vld1.16 {d16, d17}, [r2, :128]!
|
|
|
|
vmlal.s16 q12, d16, d3
|
|
|
|
vld1.16 {d18, d19}, [r2, :128]!
|
|
|
|
vmlal.s16 q13, d17, d3
|
|
|
|
vmlal.s16 q14, d18, d3
|
|
|
|
vmlal.s16 q15, d19, d3
|
|
|
|
|
|
|
|
vpadd.s32 d0, d24, d25 /* TODO: can be eliminated */
|
|
|
|
vpadd.s32 d1, d26, d27 /* TODO: can be eliminated */
|
|
|
|
vpadd.s32 d2, d28, d29 /* TODO: can be eliminated */
|
|
|
|
vpadd.s32 d3, d30, d31 /* TODO: can be eliminated */
|
|
|
|
|
|
|
|
vst1.32 {d0, d1, d2, d3}, [r1, :128]
|
|
|
|
|
|
|
|
bx lr
|
|
|
|
endfunc
|
|
|
|
|
|
|
|
function ff_sbc_calc_scalefactors_neon, export=1
|
|
|
|
@ parameters
|
|
|
|
@ r0 = sb_sample_f
|
|
|
|
@ r1 = scale_factor
|
|
|
|
@ r2 = blocks
|
|
|
|
@ r3 = channels
|
|
|
|
@ r4 = subbands
|
|
|
|
@ local variables
|
|
|
|
@ r5 = in_loop_1
|
|
|
|
@ r6 = in
|
|
|
|
@ r7 = out_loop_1
|
|
|
|
@ r8 = out
|
|
|
|
@ r9 = ch
|
|
|
|
@ r10 = sb
|
|
|
|
@ r11 = inc
|
|
|
|
@ r12 = blk
|
|
|
|
|
|
|
|
push {r1-r2, r4-r12}
|
|
|
|
ldr r4, [sp, #44]
|
|
|
|
mov r11, #64
|
|
|
|
|
|
|
|
mov r9, #0
|
|
|
|
1:
|
|
|
|
add r5, r0, r9, lsl#5
|
|
|
|
add r7, r1, r9, lsl#5
|
|
|
|
|
|
|
|
mov r10, #0
|
|
|
|
2:
|
|
|
|
add r6, r5, r10, lsl#2
|
|
|
|
add r8, r7, r10, lsl#2
|
|
|
|
mov r12, r2
|
|
|
|
|
|
|
|
vmov.s32 q0, #0
|
|
|
|
vmov.s32 q1, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
|
|
vmov.s32 q14, #1
|
|
|
|
vmov.s32 q15, #16 @ 31 - SCALE_OUT_BITS
|
|
|
|
vadd.s32 q1, q1, q14
|
|
|
|
3:
|
|
|
|
vld1.32 {d16, d17}, [r6, :128], r11
|
|
|
|
vabs.s32 q8, q8
|
|
|
|
vld1.32 {d18, d19}, [r6, :128], r11
|
|
|
|
vabs.s32 q9, q9
|
|
|
|
vld1.32 {d20, d21}, [r6, :128], r11
|
|
|
|
vabs.s32 q10, q10
|
|
|
|
vld1.32 {d22, d23}, [r6, :128], r11
|
|
|
|
vabs.s32 q11, q11
|
|
|
|
vmax.s32 q0, q0, q8
|
|
|
|
vmax.s32 q1, q1, q9
|
|
|
|
vmax.s32 q0, q0, q10
|
|
|
|
vmax.s32 q1, q1, q11
|
|
|
|
subs r12, r12, #4
|
|
|
|
bgt 3b
|
|
|
|
vmax.s32 q0, q0, q1
|
|
|
|
vsub.s32 q0, q0, q14
|
|
|
|
vclz.s32 q0, q0
|
|
|
|
vsub.s32 q0, q15, q0
|
|
|
|
vst1.32 {d0, d1}, [r8, :128]
|
|
|
|
|
|
|
|
add r10, r10, #4
|
|
|
|
cmp r10, r4
|
|
|
|
blt 2b
|
|
|
|
|
|
|
|
add r9, r9, #1
|
|
|
|
cmp r9, r3
|
|
|
|
blt 1b
|
|
|
|
|
|
|
|
pop {r1-r2, r4-r12}
|
|
|
|
bx lr
|
|
|
|
endfunc
|
|
|
|
|
|
|
|
/*
|
|
|
|
* constants: q13 = (31 - SCALE_OUT_BITS)
|
|
|
|
* q14 = 1
|
|
|
|
* input: q0 - ((1 << SCALE_OUT_BITS) + 1)
|
|
|
|
* r5 - samples for channel 0
|
|
|
|
* r6 - samples for shannel 1
|
|
|
|
* output: q0, q1 - scale factors without joint stereo
|
|
|
|
* q2, q3 - scale factors with joint stereo
|
|
|
|
* q15 - joint stereo selection mask
|
|
|
|
*/
|
|
|
|
.macro calc_scalefactors
|
|
|
|
vmov.s32 q1, q0
|
|
|
|
vmov.s32 q2, q0
|
|
|
|
vmov.s32 q3, q0
|
|
|
|
mov r3, r2
|
|
|
|
1:
|
|
|
|
vld1.32 {d18, d19}, [r6, :128], r11
|
|
|
|
vbic.s32 q11, q9, q14
|
|
|
|
vld1.32 {d16, d17}, [r5, :128], r11
|
|
|
|
vhadd.s32 q10, q8, q11
|
|
|
|
vhsub.s32 q11, q8, q11
|
|
|
|
vabs.s32 q8, q8
|
|
|
|
vabs.s32 q9, q9
|
|
|
|
vabs.s32 q10, q10
|
|
|
|
vabs.s32 q11, q11
|
|
|
|
vmax.s32 q0, q0, q8
|
|
|
|
vmax.s32 q1, q1, q9
|
|
|
|
vmax.s32 q2, q2, q10
|
|
|
|
vmax.s32 q3, q3, q11
|
|
|
|
subs r3, r3, #1
|
|
|
|
bgt 1b
|
|
|
|
vsub.s32 q0, q0, q14
|
|
|
|
vsub.s32 q1, q1, q14
|
|
|
|
vsub.s32 q2, q2, q14
|
|
|
|
vsub.s32 q3, q3, q14
|
|
|
|
vclz.s32 q0, q0
|
|
|
|
vclz.s32 q1, q1
|
|
|
|
vclz.s32 q2, q2
|
|
|
|
vclz.s32 q3, q3
|
|
|
|
vsub.s32 q0, q13, q0
|
|
|
|
vsub.s32 q1, q13, q1
|
|
|
|
vsub.s32 q2, q13, q2
|
|
|
|
vsub.s32 q3, q13, q3
|
|
|
|
.endm
|
|
|
|
|
|
|
|
/*
|
|
|
|
* constants: q14 = 1
|
|
|
|
* input: q15 - joint stereo selection mask
|
|
|
|
* r5 - value set by calc_scalefactors macro
|
|
|
|
* r6 - value set by calc_scalefactors macro
|
|
|
|
*/
|
|
|
|
.macro update_joint_stereo_samples
|
|
|
|
sub r8, r6, r11
|
|
|
|
sub r7, r5, r11
|
|
|
|
sub r6, r6, r11, asl #1
|
|
|
|
sub r5, r5, r11, asl #1
|
|
|
|
vld1.32 {d18, d19}, [r6, :128]
|
|
|
|
vbic.s32 q11, q9, q14
|
|
|
|
vld1.32 {d16, d17}, [r5, :128]
|
|
|
|
vld1.32 {d2, d3}, [r8, :128]
|
|
|
|
vbic.s32 q3, q1, q14
|
|
|
|
vld1.32 {d0, d1}, [r7, :128]
|
|
|
|
vhsub.s32 q10, q8, q11
|
|
|
|
vhadd.s32 q11, q8, q11
|
|
|
|
vhsub.s32 q2, q0, q3
|
|
|
|
vhadd.s32 q3, q0, q3
|
|
|
|
vbif.s32 q10, q9, q15
|
|
|
|
vbif.s32 d22, d16, d30
|
|
|
|
sub r11, r10, r11, asl #1
|
|
|
|
sub r3, r2, #2
|
|
|
|
2:
|
|
|
|
vbif.s32 d23, d17, d31
|
|
|
|
vst1.32 {d20, d21}, [r6, :128], r11
|
|
|
|
vbif.s32 d4, d2, d30
|
|
|
|
vld1.32 {d18, d19}, [r6, :128]
|
|
|
|
vbif.s32 d5, d3, d31
|
|
|
|
vst1.32 {d22, d23}, [r5, :128], r11
|
|
|
|
vbif.s32 d6, d0, d30
|
|
|
|
vld1.32 {d16, d17}, [r5, :128]
|
|
|
|
vbif.s32 d7, d1, d31
|
|
|
|
vst1.32 {d4, d5}, [r8, :128], r11
|
|
|
|
vbic.s32 q11, q9, q14
|
|
|
|
vld1.32 {d2, d3}, [r8, :128]
|
|
|
|
vst1.32 {d6, d7}, [r7, :128], r11
|
|
|
|
vbic.s32 q3, q1, q14
|
|
|
|
vld1.32 {d0, d1}, [r7, :128]
|
|
|
|
vhsub.s32 q10, q8, q11
|
|
|
|
vhadd.s32 q11, q8, q11
|
|
|
|
vhsub.s32 q2, q0, q3
|
|
|
|
vhadd.s32 q3, q0, q3
|
|
|
|
vbif.s32 q10, q9, q15
|
|
|
|
vbif.s32 d22, d16, d30
|
|
|
|
subs r3, r3, #2
|
|
|
|
bgt 2b
|
|
|
|
sub r11, r10, r11, asr #1
|
|
|
|
vbif.s32 d23, d17, d31
|
|
|
|
vst1.32 {d20, d21}, [r6, :128]
|
|
|
|
vbif.s32 q2, q1, q15
|
|
|
|
vst1.32 {d22, d23}, [r5, :128]
|
|
|
|
vbif.s32 q3, q0, q15
|
|
|
|
vst1.32 {d4, d5}, [r8, :128]
|
|
|
|
vst1.32 {d6, d7}, [r7, :128]
|
|
|
|
.endm
|
|
|
|
|
|
|
|
function ff_sbc_calc_scalefactors_j_neon, export=1
|
|
|
|
@ parameters
|
|
|
|
@ r0 = in = sb_sample_f
|
|
|
|
@ r1 = out = scale_factor
|
|
|
|
@ r2 = blocks
|
|
|
|
@ r3 = subbands
|
|
|
|
@ local variables
|
|
|
|
@ r4 = consts = ff_sbcdsp_joint_bits_mask
|
|
|
|
@ r5 = in0
|
|
|
|
@ r6 = in1
|
|
|
|
@ r7 = out0
|
|
|
|
@ r8 = out1
|
|
|
|
@ r10 = zero
|
|
|
|
@ r11 = inc
|
|
|
|
@ return r0 = joint
|
|
|
|
|
|
|
|
push {r3-r11}
|
|
|
|
movrelx r4, X(ff_sbcdsp_joint_bits_mask)
|
|
|
|
mov r10, #0
|
|
|
|
mov r11, #64
|
|
|
|
|
|
|
|
vmov.s32 q14, #1
|
|
|
|
vmov.s32 q13, #16 @ 31 - SCALE_OUT_BITS
|
|
|
|
|
|
|
|
cmp r3, #4
|
|
|
|
bne 8f
|
|
|
|
|
|
|
|
4: @ 4 subbands
|
|
|
|
add r5, r0, #0
|
|
|
|
add r6, r0, #32
|
|
|
|
add r7, r1, #0
|
|
|
|
add r8, r1, #32
|
|
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
|
|
vadd.s32 q0, q0, q14
|
|
|
|
|
|
|
|
calc_scalefactors
|
|
|
|
|
|
|
|
@ check whether to use joint stereo for subbands 0, 1, 2
|
|
|
|
vadd.s32 q15, q0, q1
|
|
|
|
vadd.s32 q9, q2, q3
|
|
|
|
vmov.s32 d31[1], r10 @ last subband -> no joint
|
|
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
|
|
|
|
@ calculate and save to memory 'joint' variable
|
|
|
|
@ update and save scale factors to memory
|
|
|
|
vand.s32 q8, q8, q15
|
|
|
|
vbit.s32 q0, q2, q15
|
|
|
|
vpadd.s32 d16, d16, d17
|
|
|
|
vbit.s32 q1, q3, q15
|
|
|
|
vpadd.s32 d16, d16, d16
|
|
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
|
|
vmov.32 r0, d16[0]
|
|
|
|
|
|
|
|
update_joint_stereo_samples
|
|
|
|
b 9f
|
|
|
|
|
|
|
|
8: @ 8 subbands
|
|
|
|
add r5, r0, #16
|
|
|
|
add r6, r0, #48
|
|
|
|
add r7, r1, #16
|
|
|
|
add r8, r1, #48
|
|
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
|
|
vadd.s32 q0, q0, q14
|
|
|
|
|
|
|
|
calc_scalefactors
|
|
|
|
|
|
|
|
@ check whether to use joint stereo for subbands 4, 5, 6
|
|
|
|
vadd.s32 q15, q0, q1
|
|
|
|
vadd.s32 q9, q2, q3
|
|
|
|
vmov.s32 d31[1], r10 @ last subband -> no joint
|
|
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
|
|
|
|
@ calculate part of 'joint' variable and save it to d24
|
|
|
|
@ update and save scale factors to memory
|
|
|
|
vand.s32 q8, q8, q15
|
|
|
|
vbit.s32 q0, q2, q15
|
|
|
|
vpadd.s32 d16, d16, d17
|
|
|
|
vbit.s32 q1, q3, q15
|
|
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
|
|
vpadd.s32 d24, d16, d16
|
|
|
|
|
|
|
|
update_joint_stereo_samples
|
|
|
|
|
|
|
|
add r5, r0, #0
|
|
|
|
add r6, r0, #32
|
|
|
|
add r7, r1, #0
|
|
|
|
add r8, r1, #32
|
|
|
|
vmov.s32 q0, #0x8000 @ 1 << SCALE_OUT_BITS
|
|
|
|
vadd.s32 q0, q0, q14
|
|
|
|
|
|
|
|
calc_scalefactors
|
|
|
|
|
|
|
|
@ check whether to use joint stereo for subbands 0, 1, 2, 3
|
|
|
|
vadd.s32 q15, q0, q1
|
|
|
|
vadd.s32 q9, q2, q3
|
|
|
|
vld1.32 {d16, d17}, [r4, :128]!
|
|
|
|
vcgt.s32 q15, q15, q9
|
|
|
|
|
|
|
|
@ combine last part of 'joint' with d24 and save to memory
|
|
|
|
@ update and save scale factors to memory
|
|
|
|
vand.s32 q8, q8, q15
|
|
|
|
vbit.s32 q0, q2, q15
|
|
|
|
vpadd.s32 d16, d16, d17
|
|
|
|
vbit.s32 q1, q3, q15
|
|
|
|
vpadd.s32 d16, d16, d16
|
|
|
|
vst1.32 {d0, d1}, [r7, :128]
|
|
|
|
vadd.s32 d16, d16, d24
|
|
|
|
vst1.32 {d2, d3}, [r8, :128]
|
|
|
|
vmov.32 r0, d16[0]
|
|
|
|
|
|
|
|
update_joint_stereo_samples
|
|
|
|
9:
|
|
|
|
pop {r3-r11}
|
|
|
|
bx lr
|
|
|
|
endfunc
|
|
|
|
|
|
|
|
function ff_sbc_enc_process_input_4s_neon, export=1
|
|
|
|
@ parameters
|
|
|
|
@ r0 = positioin
|
|
|
|
@ r1 = pcm
|
|
|
|
@ r2 = X
|
|
|
|
@ r3 = nsamples
|
|
|
|
@ r4 = nchannels
|
|
|
|
@ local variables
|
|
|
|
@ r5 = ff_sbc_input_perm_4
|
|
|
|
@ r6 = src / x
|
|
|
|
@ r7 = dst / y
|
|
|
|
|
|
|
|
push {r1, r3-r7}
|
|
|
|
ldr r4, [sp, #24]
|
|
|
|
movrelx r5, X(ff_sbc_input_perm_4)
|
|
|
|
|
|
|
|
@ handle X buffer wraparound
|
|
|
|
cmp r0, r3
|
|
|
|
bge 1f @ if (position < nsamples)
|
|
|
|
add r7, r2, #576 @ &X[0][SBC_X_BUFFER_SIZE - 40]
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0}, [r6, :64]!
|
|
|
|
vst1.16 {d0}, [r7, :64]!
|
|
|
|
cmp r4, #1
|
|
|
|
ble 2f @ if (nchannels > 1)
|
|
|
|
add r7, r2, #1232 @ &X[1][SBC_X_BUFFER_SIZE - 40]
|
|
|
|
add r6, r2, #656
|
|
|
|
add r6, r6, r0, lsl#1 @ &X[1][position]
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0}, [r6, :64]!
|
|
|
|
vst1.16 {d0}, [r7, :64]!
|
|
|
|
2:
|
|
|
|
mov r0, #288 @ SBC_X_BUFFER_SIZE - 40
|
|
|
|
1:
|
|
|
|
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
|
|
add r7, r6, #656 @ &X[1][position]
|
|
|
|
|
|
|
|
cmp r4, #1
|
|
|
|
ble 8f @ if (nchannels > 1)
|
|
|
|
tst r1, #1
|
|
|
|
beq 7f @ if (pcm & 1)
|
|
|
|
@ poor 'pcm' alignment
|
|
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #16
|
|
|
|
sub r7, r7, #16
|
|
|
|
sub r0, r0, #8
|
|
|
|
vld1.8 {d4, d5}, [r1]!
|
|
|
|
vuzp.16 d4, d5
|
|
|
|
vld1.8 {d20, d21}, [r1]!
|
|
|
|
vuzp.16 d20, d21
|
|
|
|
vswp d5, d20
|
|
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
|
|
vtbl.8 d18, {d20, d21}, d0
|
|
|
|
vtbl.8 d19, {d20, d21}, d1
|
|
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
|
|
vst1.16 {d18, d19}, [r7, :128]
|
|
|
|
subs r3, r3, #8
|
|
|
|
bgt 1b
|
|
|
|
b 9f
|
|
|
|
7:
|
|
|
|
@ proper 'pcm' alignment
|
|
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #16
|
|
|
|
sub r7, r7, #16
|
|
|
|
sub r0, r0, #8
|
|
|
|
vld2.16 {d4, d5}, [r1]!
|
|
|
|
vld2.16 {d20, d21}, [r1]!
|
|
|
|
vswp d5, d20
|
|
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
|
|
vtbl.8 d18, {d20, d21}, d0
|
|
|
|
vtbl.8 d19, {d20, d21}, d1
|
|
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
|
|
vst1.16 {d18, d19}, [r7, :128]
|
|
|
|
subs r3, r3, #8
|
|
|
|
bgt 1b
|
|
|
|
b 9f
|
|
|
|
8:
|
|
|
|
@ mono
|
|
|
|
vld1.8 {d0, d1}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #16
|
|
|
|
sub r0, r0, #8
|
|
|
|
vld1.8 {d4, d5}, [r1]!
|
|
|
|
vtbl.8 d16, {d4, d5}, d0
|
|
|
|
vtbl.8 d17, {d4, d5}, d1
|
|
|
|
vst1.16 {d16, d17}, [r6, :128]
|
|
|
|
subs r3, r3, #8
|
|
|
|
bgt 1b
|
|
|
|
9:
|
|
|
|
pop {r1, r3-r7}
|
|
|
|
bx lr
|
|
|
|
endfunc
|
|
|
|
|
|
|
|
function ff_sbc_enc_process_input_8s_neon, export=1
|
|
|
|
@ parameters
|
|
|
|
@ r0 = positioin
|
|
|
|
@ r1 = pcm
|
|
|
|
@ r2 = X
|
|
|
|
@ r3 = nsamples
|
|
|
|
@ r4 = nchannels
|
|
|
|
@ local variables
|
|
|
|
@ r5 = ff_sbc_input_perm_8
|
|
|
|
@ r6 = src
|
|
|
|
@ r7 = dst
|
|
|
|
|
|
|
|
push {r1, r3-r7}
|
|
|
|
ldr r4, [sp, #24]
|
|
|
|
movrelx r5, X(ff_sbc_input_perm_8)
|
|
|
|
|
|
|
|
@ handle X buffer wraparound
|
|
|
|
cmp r0, r3
|
|
|
|
bge 1f @ if (position < nsamples)
|
|
|
|
add r7, r2, #512 @ &X[0][SBC_X_BUFFER_SIZE - 72]
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1}, [r7, :128]!
|
|
|
|
cmp r4, #1
|
|
|
|
ble 2f @ if (nchannels > 1)
|
|
|
|
add r7, r2, #1168 @ &X[1][SBC_X_BUFFER_SIZE - 72]
|
|
|
|
add r6, r2, #656
|
|
|
|
add r6, r6, r0, lsl#1 @ &X[1][position]
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1, d2, d3}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1, d2, d3}, [r7, :128]!
|
|
|
|
vld1.16 {d0, d1}, [r6, :128]!
|
|
|
|
vst1.16 {d0, d1}, [r7, :128]!
|
|
|
|
2:
|
|
|
|
mov r0, #256 @ SBC_X_BUFFER_SIZE - 72
|
|
|
|
1:
|
|
|
|
|
|
|
|
add r6, r2, r0, lsl#1 @ &X[0][position]
|
|
|
|
add r7, r6, #656 @ &X[1][position]
|
|
|
|
|
|
|
|
cmp r4, #1
|
|
|
|
ble 8f @ if (nchannels > 1)
|
|
|
|
tst r1, #1
|
|
|
|
beq 7f @ if (pcm & 1)
|
|
|
|
@ poor 'pcm' alignment
|
|
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #32
|
|
|
|
sub r7, r7, #32
|
|
|
|
sub r0, r0, #16
|
|
|
|
vld1.8 {d4, d5, d6, d7}, [r1]!
|
|
|
|
vuzp.16 q2, q3
|
|
|
|
vld1.8 {d20, d21, d22, d23}, [r1]!
|
|
|
|
vuzp.16 q10, q11
|
|
|
|
vswp q3, q10
|
|
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
|
|
vtbl.8 d16, {d20, d21, d22, d23}, d0
|
|
|
|
vtbl.8 d17, {d20, d21, d22, d23}, d1
|
|
|
|
vtbl.8 d18, {d20, d21, d22, d23}, d2
|
|
|
|
vtbl.8 d19, {d20, d21, d22, d23}, d3
|
|
|
|
vst1.16 {d16, d17, d18, d19}, [r7, :128]
|
|
|
|
subs r3, r3, #16
|
|
|
|
bgt 1b
|
|
|
|
b 9f
|
|
|
|
7:
|
|
|
|
@ proper 'pcm' alignment
|
|
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #32
|
|
|
|
sub r7, r7, #32
|
|
|
|
sub r0, r0, #16
|
|
|
|
vld2.16 {d4, d5, d6, d7}, [r1]!
|
|
|
|
vld2.16 {d20, d21, d22, d23}, [r1]!
|
|
|
|
vswp q3, q10
|
|
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
|
|
vtbl.8 d16, {d20, d21, d22, d23}, d0
|
|
|
|
vtbl.8 d17, {d20, d21, d22, d23}, d1
|
|
|
|
vtbl.8 d18, {d20, d21, d22, d23}, d2
|
|
|
|
vtbl.8 d19, {d20, d21, d22, d23}, d3
|
|
|
|
vst1.16 {d16, d17, d18, d19}, [r7, :128]
|
|
|
|
subs r3, r3, #16
|
|
|
|
bgt 1b
|
|
|
|
b 9f
|
|
|
|
8:
|
|
|
|
@ mono
|
|
|
|
vld1.8 {d0, d1, d2, d3}, [r5, :128]
|
|
|
|
1:
|
|
|
|
sub r6, r6, #32
|
|
|
|
sub r0, r0, #16
|
|
|
|
vld1.8 {d4, d5, d6, d7}, [r1]!
|
|
|
|
vtbl.8 d16, {d4, d5, d6, d7}, d0
|
|
|
|
vtbl.8 d17, {d4, d5, d6, d7}, d1
|
|
|
|
vtbl.8 d18, {d4, d5, d6, d7}, d2
|
|
|
|
vtbl.8 d19, {d4, d5, d6, d7}, d3
|
|
|
|
vst1.16 {d16, d17, d18, d19}, [r6, :128]
|
|
|
|
subs r3, r3, #16
|
|
|
|
bgt 1b
|
|
|
|
9:
|
|
|
|
pop {r1, r3-r7}
|
|
|
|
bx lr
|
|
|
|
endfunc
|