mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-09 13:29:59 -05:00
build: move sbc related files to its own directory
This should make it easier to apply patches from BlueZ which also uses sbc subdir for this files.
This commit is contained in:
parent
ad85624527
commit
e4eb467010
12 changed files with 2 additions and 2 deletions
1252
src/modules/bluetooth/sbc/sbc.c
Normal file
1252
src/modules/bluetooth/sbc/sbc.c
Normal file
File diff suppressed because it is too large
Load diff
111
src/modules/bluetooth/sbc/sbc.h
Normal file
111
src/modules/bluetooth/sbc/sbc.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBC_H
|
||||
#define __SBC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* sampling frequency */
|
||||
#define SBC_FREQ_16000 0x00
|
||||
#define SBC_FREQ_32000 0x01
|
||||
#define SBC_FREQ_44100 0x02
|
||||
#define SBC_FREQ_48000 0x03
|
||||
|
||||
/* blocks */
|
||||
#define SBC_BLK_4 0x00
|
||||
#define SBC_BLK_8 0x01
|
||||
#define SBC_BLK_12 0x02
|
||||
#define SBC_BLK_16 0x03
|
||||
|
||||
/* channel mode */
|
||||
#define SBC_MODE_MONO 0x00
|
||||
#define SBC_MODE_DUAL_CHANNEL 0x01
|
||||
#define SBC_MODE_STEREO 0x02
|
||||
#define SBC_MODE_JOINT_STEREO 0x03
|
||||
|
||||
/* allocation method */
|
||||
#define SBC_AM_LOUDNESS 0x00
|
||||
#define SBC_AM_SNR 0x01
|
||||
|
||||
/* subbands */
|
||||
#define SBC_SB_4 0x00
|
||||
#define SBC_SB_8 0x01
|
||||
|
||||
/* Data endianess */
|
||||
#define SBC_LE 0x00
|
||||
#define SBC_BE 0x01
|
||||
|
||||
struct sbc_struct {
|
||||
unsigned long flags;
|
||||
|
||||
uint8_t frequency;
|
||||
uint8_t blocks;
|
||||
uint8_t subbands;
|
||||
uint8_t mode;
|
||||
uint8_t allocation;
|
||||
uint8_t bitpool;
|
||||
uint8_t endian;
|
||||
|
||||
void *priv;
|
||||
void *priv_alloc_base;
|
||||
};
|
||||
|
||||
typedef struct sbc_struct sbc_t;
|
||||
|
||||
int sbc_init(sbc_t *sbc, unsigned long flags);
|
||||
int sbc_reinit(sbc_t *sbc, unsigned long flags);
|
||||
|
||||
ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
|
||||
|
||||
ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, size_t *written);
|
||||
|
||||
/* Encodes ONE input block into ONE output block */
|
||||
ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, size_t *written);
|
||||
|
||||
/* Returns the output block size in bytes */
|
||||
size_t sbc_get_frame_length(sbc_t *sbc);
|
||||
|
||||
/* Returns the time one input/output block takes to play in msec*/
|
||||
unsigned sbc_get_frame_duration(sbc_t *sbc);
|
||||
|
||||
/* Returns the input block size in bytes */
|
||||
size_t sbc_get_codesize(sbc_t *sbc);
|
||||
|
||||
const char *sbc_get_implementation_info(sbc_t *sbc);
|
||||
void sbc_finish(sbc_t *sbc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SBC_H */
|
||||
60
src/modules/bluetooth/sbc/sbc_math.h
Normal file
60
src/modules/bluetooth/sbc/sbc_math.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define fabs(x) ((x) < 0 ? -(x) : (x))
|
||||
/* C does not provide an explicit arithmetic shift right but this will
|
||||
always be correct and every compiler *should* generate optimal code */
|
||||
#define ASR(val, bits) ((-2 >> 1 == -1) ? \
|
||||
((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
|
||||
|
||||
#define SCALE_SPROTO4_TBL 12
|
||||
#define SCALE_SPROTO8_TBL 14
|
||||
#define SCALE_NPROTO4_TBL 11
|
||||
#define SCALE_NPROTO8_TBL 11
|
||||
#define SCALE4_STAGED1_BITS 15
|
||||
#define SCALE4_STAGED2_BITS 16
|
||||
#define SCALE8_STAGED1_BITS 15
|
||||
#define SCALE8_STAGED2_BITS 16
|
||||
|
||||
typedef int32_t sbc_fixed_t;
|
||||
|
||||
#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS)
|
||||
#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS)
|
||||
#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS)
|
||||
#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS)
|
||||
|
||||
#define SBC_FIXED_0(val) { val = 0; }
|
||||
#define MUL(a, b) ((a) * (b))
|
||||
#ifdef __arm__
|
||||
#define MULA(a, b, res) ({ \
|
||||
int tmp = res; \
|
||||
__asm__( \
|
||||
"mla %0, %2, %3, %0" \
|
||||
: "=&r" (tmp) \
|
||||
: "0" (tmp), "r" (a), "r" (b)); \
|
||||
tmp; })
|
||||
#else
|
||||
#define MULA(a, b, res) ((a) * (b) + (res))
|
||||
#endif
|
||||
470
src/modules/bluetooth/sbc/sbc_primitives.c
Normal file
470
src/modules/bluetooth/sbc/sbc_primitives.c
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "sbc.h"
|
||||
#include "sbc_math.h"
|
||||
#include "sbc_tables.h"
|
||||
|
||||
#include "sbc_primitives.h"
|
||||
#include "sbc_primitives_mmx.h"
|
||||
#include "sbc_primitives_neon.h"
|
||||
|
||||
/*
|
||||
* A reference C code of analysis filter with SIMD-friendly tables
|
||||
* reordering and code layout. This code can be used to develop platform
|
||||
* specific SIMD optimizations. Also it may be used as some kind of test
|
||||
* for compiler autovectorization capabilities (who knows, if the compiler
|
||||
* is very good at this stuff, hand optimized assembly may be not strictly
|
||||
* needed for some platform).
|
||||
*
|
||||
* Note: It is also possible to make a simple variant of analysis filter,
|
||||
* which needs only a single constants table without taking care about
|
||||
* even/odd cases. This simple variant of filter can be implemented without
|
||||
* input data permutation. The only thing that would be lost is the
|
||||
* possibility to use pairwise SIMD multiplications. But for some simple
|
||||
* CPU cores without SIMD extensions it can be useful. If anybody is
|
||||
* interested in implementing such variant of a filter, sourcecode from
|
||||
* bluez versions 4.26/4.27 can be used as a reference and the history of
|
||||
* the changes in git repository done around that time may be worth checking.
|
||||
*/
|
||||
|
||||
static inline void sbc_analyze_four_simd(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
FIXED_A t1[4];
|
||||
FIXED_T t2[4];
|
||||
int hop = 0;
|
||||
|
||||
/* rounding coefficient */
|
||||
t1[0] = t1[1] = t1[2] = t1[3] =
|
||||
(FIXED_A) 1 << (SBC_PROTO_FIXED4_SCALE - 1);
|
||||
|
||||
/* low pass polyphase filter */
|
||||
for (hop = 0; hop < 40; hop += 8) {
|
||||
t1[0] += (FIXED_A) in[hop] * consts[hop];
|
||||
t1[0] += (FIXED_A) in[hop + 1] * consts[hop + 1];
|
||||
t1[1] += (FIXED_A) in[hop + 2] * consts[hop + 2];
|
||||
t1[1] += (FIXED_A) in[hop + 3] * consts[hop + 3];
|
||||
t1[2] += (FIXED_A) in[hop + 4] * consts[hop + 4];
|
||||
t1[2] += (FIXED_A) in[hop + 5] * consts[hop + 5];
|
||||
t1[3] += (FIXED_A) in[hop + 6] * consts[hop + 6];
|
||||
t1[3] += (FIXED_A) in[hop + 7] * consts[hop + 7];
|
||||
}
|
||||
|
||||
/* scaling */
|
||||
t2[0] = t1[0] >> SBC_PROTO_FIXED4_SCALE;
|
||||
t2[1] = t1[1] >> SBC_PROTO_FIXED4_SCALE;
|
||||
t2[2] = t1[2] >> SBC_PROTO_FIXED4_SCALE;
|
||||
t2[3] = t1[3] >> SBC_PROTO_FIXED4_SCALE;
|
||||
|
||||
/* do the cos transform */
|
||||
t1[0] = (FIXED_A) t2[0] * consts[40 + 0];
|
||||
t1[0] += (FIXED_A) t2[1] * consts[40 + 1];
|
||||
t1[1] = (FIXED_A) t2[0] * consts[40 + 2];
|
||||
t1[1] += (FIXED_A) t2[1] * consts[40 + 3];
|
||||
t1[2] = (FIXED_A) t2[0] * consts[40 + 4];
|
||||
t1[2] += (FIXED_A) t2[1] * consts[40 + 5];
|
||||
t1[3] = (FIXED_A) t2[0] * consts[40 + 6];
|
||||
t1[3] += (FIXED_A) t2[1] * consts[40 + 7];
|
||||
|
||||
t1[0] += (FIXED_A) t2[2] * consts[40 + 8];
|
||||
t1[0] += (FIXED_A) t2[3] * consts[40 + 9];
|
||||
t1[1] += (FIXED_A) t2[2] * consts[40 + 10];
|
||||
t1[1] += (FIXED_A) t2[3] * consts[40 + 11];
|
||||
t1[2] += (FIXED_A) t2[2] * consts[40 + 12];
|
||||
t1[2] += (FIXED_A) t2[3] * consts[40 + 13];
|
||||
t1[3] += (FIXED_A) t2[2] * consts[40 + 14];
|
||||
t1[3] += (FIXED_A) t2[3] * consts[40 + 15];
|
||||
|
||||
out[0] = t1[0] >>
|
||||
(SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
|
||||
out[1] = t1[1] >>
|
||||
(SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
|
||||
out[2] = t1[2] >>
|
||||
(SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
|
||||
out[3] = t1[3] >>
|
||||
(SBC_COS_TABLE_FIXED4_SCALE - SCALE_OUT_BITS);
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_eight_simd(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
FIXED_A t1[8];
|
||||
FIXED_T t2[8];
|
||||
int i, hop;
|
||||
|
||||
/* rounding coefficient */
|
||||
t1[0] = t1[1] = t1[2] = t1[3] = t1[4] = t1[5] = t1[6] = t1[7] =
|
||||
(FIXED_A) 1 << (SBC_PROTO_FIXED8_SCALE-1);
|
||||
|
||||
/* low pass polyphase filter */
|
||||
for (hop = 0; hop < 80; hop += 16) {
|
||||
t1[0] += (FIXED_A) in[hop] * consts[hop];
|
||||
t1[0] += (FIXED_A) in[hop + 1] * consts[hop + 1];
|
||||
t1[1] += (FIXED_A) in[hop + 2] * consts[hop + 2];
|
||||
t1[1] += (FIXED_A) in[hop + 3] * consts[hop + 3];
|
||||
t1[2] += (FIXED_A) in[hop + 4] * consts[hop + 4];
|
||||
t1[2] += (FIXED_A) in[hop + 5] * consts[hop + 5];
|
||||
t1[3] += (FIXED_A) in[hop + 6] * consts[hop + 6];
|
||||
t1[3] += (FIXED_A) in[hop + 7] * consts[hop + 7];
|
||||
t1[4] += (FIXED_A) in[hop + 8] * consts[hop + 8];
|
||||
t1[4] += (FIXED_A) in[hop + 9] * consts[hop + 9];
|
||||
t1[5] += (FIXED_A) in[hop + 10] * consts[hop + 10];
|
||||
t1[5] += (FIXED_A) in[hop + 11] * consts[hop + 11];
|
||||
t1[6] += (FIXED_A) in[hop + 12] * consts[hop + 12];
|
||||
t1[6] += (FIXED_A) in[hop + 13] * consts[hop + 13];
|
||||
t1[7] += (FIXED_A) in[hop + 14] * consts[hop + 14];
|
||||
t1[7] += (FIXED_A) in[hop + 15] * consts[hop + 15];
|
||||
}
|
||||
|
||||
/* scaling */
|
||||
t2[0] = t1[0] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[1] = t1[1] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[2] = t1[2] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[3] = t1[3] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[4] = t1[4] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[5] = t1[5] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[6] = t1[6] >> SBC_PROTO_FIXED8_SCALE;
|
||||
t2[7] = t1[7] >> SBC_PROTO_FIXED8_SCALE;
|
||||
|
||||
|
||||
/* do the cos transform */
|
||||
t1[0] = t1[1] = t1[2] = t1[3] = t1[4] = t1[5] = t1[6] = t1[7] = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
t1[0] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 0];
|
||||
t1[0] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 1];
|
||||
t1[1] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 2];
|
||||
t1[1] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 3];
|
||||
t1[2] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 4];
|
||||
t1[2] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 5];
|
||||
t1[3] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 6];
|
||||
t1[3] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 7];
|
||||
t1[4] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 8];
|
||||
t1[4] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 9];
|
||||
t1[5] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 10];
|
||||
t1[5] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 11];
|
||||
t1[6] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 12];
|
||||
t1[6] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 13];
|
||||
t1[7] += (FIXED_A) t2[i * 2 + 0] * consts[80 + i * 16 + 14];
|
||||
t1[7] += (FIXED_A) t2[i * 2 + 1] * consts[80 + i * 16 + 15];
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
out[i] = t1[i] >>
|
||||
(SBC_COS_TABLE_FIXED8_SCALE - SCALE_OUT_BITS);
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_4s_simd(int16_t *x,
|
||||
int32_t *out, int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
sbc_analyze_four_simd(x + 12, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_simd(x + 8, out, analysis_consts_fixed4_simd_even);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_simd(x + 4, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_simd(x + 0, out, analysis_consts_fixed4_simd_even);
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_8s_simd(int16_t *x,
|
||||
int32_t *out, int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
sbc_analyze_eight_simd(x + 24, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_simd(x + 16, out, analysis_consts_fixed8_simd_even);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_simd(x + 8, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_simd(x + 0, out, analysis_consts_fixed8_simd_even);
|
||||
}
|
||||
|
||||
static inline int16_t unaligned16_be(const uint8_t *ptr)
|
||||
{
|
||||
return (int16_t) ((ptr[0] << 8) | ptr[1]);
|
||||
}
|
||||
|
||||
static inline int16_t unaligned16_le(const uint8_t *ptr)
|
||||
{
|
||||
return (int16_t) (ptr[0] | (ptr[1] << 8));
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal helper functions for input data processing. In order to get
|
||||
* optimal performance, it is important to have "nsamples", "nchannels"
|
||||
* and "big_endian" arguments used with this inline function as compile
|
||||
* time constants.
|
||||
*/
|
||||
|
||||
static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s4_internal(
|
||||
int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels, int big_endian)
|
||||
{
|
||||
/* handle X buffer wraparound */
|
||||
if (position < nsamples) {
|
||||
if (nchannels > 0)
|
||||
memcpy(&X[0][SBC_X_BUFFER_SIZE - 36], &X[0][position],
|
||||
36 * sizeof(int16_t));
|
||||
if (nchannels > 1)
|
||||
memcpy(&X[1][SBC_X_BUFFER_SIZE - 36], &X[1][position],
|
||||
36 * sizeof(int16_t));
|
||||
position = SBC_X_BUFFER_SIZE - 36;
|
||||
}
|
||||
|
||||
#define PCM(i) (big_endian ? \
|
||||
unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
|
||||
|
||||
/* copy/permutate audio samples */
|
||||
while ((nsamples -= 8) >= 0) {
|
||||
position -= 8;
|
||||
if (nchannels > 0) {
|
||||
int16_t *x = &X[0][position];
|
||||
x[0] = PCM(0 + 7 * nchannels);
|
||||
x[1] = PCM(0 + 3 * nchannels);
|
||||
x[2] = PCM(0 + 6 * nchannels);
|
||||
x[3] = PCM(0 + 4 * nchannels);
|
||||
x[4] = PCM(0 + 0 * nchannels);
|
||||
x[5] = PCM(0 + 2 * nchannels);
|
||||
x[6] = PCM(0 + 1 * nchannels);
|
||||
x[7] = PCM(0 + 5 * nchannels);
|
||||
}
|
||||
if (nchannels > 1) {
|
||||
int16_t *x = &X[1][position];
|
||||
x[0] = PCM(1 + 7 * nchannels);
|
||||
x[1] = PCM(1 + 3 * nchannels);
|
||||
x[2] = PCM(1 + 6 * nchannels);
|
||||
x[3] = PCM(1 + 4 * nchannels);
|
||||
x[4] = PCM(1 + 0 * nchannels);
|
||||
x[5] = PCM(1 + 2 * nchannels);
|
||||
x[6] = PCM(1 + 1 * nchannels);
|
||||
x[7] = PCM(1 + 5 * nchannels);
|
||||
}
|
||||
pcm += 16 * nchannels;
|
||||
}
|
||||
#undef PCM
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
|
||||
int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels, int big_endian)
|
||||
{
|
||||
/* handle X buffer wraparound */
|
||||
if (position < nsamples) {
|
||||
if (nchannels > 0)
|
||||
memcpy(&X[0][SBC_X_BUFFER_SIZE - 72], &X[0][position],
|
||||
72 * sizeof(int16_t));
|
||||
if (nchannels > 1)
|
||||
memcpy(&X[1][SBC_X_BUFFER_SIZE - 72], &X[1][position],
|
||||
72 * sizeof(int16_t));
|
||||
position = SBC_X_BUFFER_SIZE - 72;
|
||||
}
|
||||
|
||||
#define PCM(i) (big_endian ? \
|
||||
unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
|
||||
|
||||
/* copy/permutate audio samples */
|
||||
while ((nsamples -= 16) >= 0) {
|
||||
position -= 16;
|
||||
if (nchannels > 0) {
|
||||
int16_t *x = &X[0][position];
|
||||
x[0] = PCM(0 + 15 * nchannels);
|
||||
x[1] = PCM(0 + 7 * nchannels);
|
||||
x[2] = PCM(0 + 14 * nchannels);
|
||||
x[3] = PCM(0 + 8 * nchannels);
|
||||
x[4] = PCM(0 + 13 * nchannels);
|
||||
x[5] = PCM(0 + 9 * nchannels);
|
||||
x[6] = PCM(0 + 12 * nchannels);
|
||||
x[7] = PCM(0 + 10 * nchannels);
|
||||
x[8] = PCM(0 + 11 * nchannels);
|
||||
x[9] = PCM(0 + 3 * nchannels);
|
||||
x[10] = PCM(0 + 6 * nchannels);
|
||||
x[11] = PCM(0 + 0 * nchannels);
|
||||
x[12] = PCM(0 + 5 * nchannels);
|
||||
x[13] = PCM(0 + 1 * nchannels);
|
||||
x[14] = PCM(0 + 4 * nchannels);
|
||||
x[15] = PCM(0 + 2 * nchannels);
|
||||
}
|
||||
if (nchannels > 1) {
|
||||
int16_t *x = &X[1][position];
|
||||
x[0] = PCM(1 + 15 * nchannels);
|
||||
x[1] = PCM(1 + 7 * nchannels);
|
||||
x[2] = PCM(1 + 14 * nchannels);
|
||||
x[3] = PCM(1 + 8 * nchannels);
|
||||
x[4] = PCM(1 + 13 * nchannels);
|
||||
x[5] = PCM(1 + 9 * nchannels);
|
||||
x[6] = PCM(1 + 12 * nchannels);
|
||||
x[7] = PCM(1 + 10 * nchannels);
|
||||
x[8] = PCM(1 + 11 * nchannels);
|
||||
x[9] = PCM(1 + 3 * nchannels);
|
||||
x[10] = PCM(1 + 6 * nchannels);
|
||||
x[11] = PCM(1 + 0 * nchannels);
|
||||
x[12] = PCM(1 + 5 * nchannels);
|
||||
x[13] = PCM(1 + 1 * nchannels);
|
||||
x[14] = PCM(1 + 4 * nchannels);
|
||||
x[15] = PCM(1 + 2 * nchannels);
|
||||
}
|
||||
pcm += 32 * nchannels;
|
||||
}
|
||||
#undef PCM
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input data processing functions. The data is endian converted if needed,
|
||||
* channels are deintrleaved and audio samples are reordered for use in
|
||||
* SIMD-friendly analysis filter function. The results are put into "X"
|
||||
* array, getting appended to the previous data (or it is better to say
|
||||
* prepended, as the buffer is filled from top to bottom). Old data is
|
||||
* discarded when neededed, but availability of (10 * nrof_subbands)
|
||||
* contiguous samples is always guaranteed for the input to the analysis
|
||||
* filter. This is achieved by copying a sufficient part of old data
|
||||
* to the top of the buffer on buffer wraparound.
|
||||
*/
|
||||
|
||||
static int sbc_enc_process_input_4s_le(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels)
|
||||
{
|
||||
if (nchannels > 1)
|
||||
return sbc_encoder_process_input_s4_internal(
|
||||
position, pcm, X, nsamples, 2, 0);
|
||||
else
|
||||
return sbc_encoder_process_input_s4_internal(
|
||||
position, pcm, X, nsamples, 1, 0);
|
||||
}
|
||||
|
||||
static int sbc_enc_process_input_4s_be(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels)
|
||||
{
|
||||
if (nchannels > 1)
|
||||
return sbc_encoder_process_input_s4_internal(
|
||||
position, pcm, X, nsamples, 2, 1);
|
||||
else
|
||||
return sbc_encoder_process_input_s4_internal(
|
||||
position, pcm, X, nsamples, 1, 1);
|
||||
}
|
||||
|
||||
static int sbc_enc_process_input_8s_le(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels)
|
||||
{
|
||||
if (nchannels > 1)
|
||||
return sbc_encoder_process_input_s8_internal(
|
||||
position, pcm, X, nsamples, 2, 0);
|
||||
else
|
||||
return sbc_encoder_process_input_s8_internal(
|
||||
position, pcm, X, nsamples, 1, 0);
|
||||
}
|
||||
|
||||
static int sbc_enc_process_input_8s_be(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels)
|
||||
{
|
||||
if (nchannels > 1)
|
||||
return sbc_encoder_process_input_s8_internal(
|
||||
position, pcm, X, nsamples, 2, 1);
|
||||
else
|
||||
return sbc_encoder_process_input_s8_internal(
|
||||
position, pcm, X, nsamples, 1, 1);
|
||||
}
|
||||
|
||||
/* Supplementary function to count the number of leading zeros */
|
||||
|
||||
static inline int sbc_clz(uint32_t x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_clz(x);
|
||||
#else
|
||||
/* TODO: this should be replaced with something better if good
|
||||
* performance is wanted when using compilers other than gcc */
|
||||
int cnt = 0;
|
||||
while (x) {
|
||||
cnt++;
|
||||
x >>= 1;
|
||||
}
|
||||
return 32 - cnt;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sbc_calc_scalefactors(
|
||||
int32_t sb_sample_f[16][2][8],
|
||||
uint32_t scale_factor[2][8],
|
||||
int blocks, int channels, int subbands)
|
||||
{
|
||||
int ch, sb, blk;
|
||||
for (ch = 0; ch < channels; ch++) {
|
||||
for (sb = 0; sb < subbands; sb++) {
|
||||
uint32_t x = 1 << SCALE_OUT_BITS;
|
||||
for (blk = 0; blk < blocks; blk++) {
|
||||
int32_t tmp = fabs(sb_sample_f[blk][ch][sb]);
|
||||
if (tmp != 0)
|
||||
x |= tmp - 1;
|
||||
}
|
||||
scale_factor[ch][sb] = (31 - SCALE_OUT_BITS) -
|
||||
sbc_clz(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect CPU features and setup function pointers
|
||||
*/
|
||||
void sbc_init_primitives(struct sbc_encoder_state *state)
|
||||
{
|
||||
/* Default implementation for analyze functions */
|
||||
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
|
||||
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
|
||||
|
||||
/* Default implementation for input reordering / deinterleaving */
|
||||
state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
|
||||
state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be;
|
||||
state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le;
|
||||
state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be;
|
||||
|
||||
/* Default implementation for scale factors calculation */
|
||||
state->sbc_calc_scalefactors = sbc_calc_scalefactors;
|
||||
state->implementation_info = "Generic C";
|
||||
|
||||
/* X86/AMD64 optimizations */
|
||||
#ifdef SBC_BUILD_WITH_MMX_SUPPORT
|
||||
sbc_init_primitives_mmx(state);
|
||||
#endif
|
||||
|
||||
/* ARM optimizations */
|
||||
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
|
||||
sbc_init_primitives_neon(state);
|
||||
#endif
|
||||
}
|
||||
75
src/modules/bluetooth/sbc/sbc_primitives.h
Normal file
75
src/modules/bluetooth/sbc/sbc_primitives.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBC_PRIMITIVES_H
|
||||
#define __SBC_PRIMITIVES_H
|
||||
|
||||
#define SCALE_OUT_BITS 15
|
||||
#define SBC_X_BUFFER_SIZE 328
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define SBC_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define SBC_ALWAYS_INLINE inline
|
||||
#endif
|
||||
|
||||
struct sbc_encoder_state {
|
||||
int position;
|
||||
int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
|
||||
/* Polyphase analysis filter for 4 subbands configuration,
|
||||
* it handles 4 blocks at once */
|
||||
void (*sbc_analyze_4b_4s)(int16_t *x, int32_t *out, int out_stride);
|
||||
/* Polyphase analysis filter for 8 subbands configuration,
|
||||
* it handles 4 blocks at once */
|
||||
void (*sbc_analyze_4b_8s)(int16_t *x, int32_t *out, int out_stride);
|
||||
/* Process input data (deinterleave, endian conversion, reordering),
|
||||
* depending on the number of subbands and input data byte order */
|
||||
int (*sbc_enc_process_input_4s_le)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_4s_be)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_8s_le)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_8s_be)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
/* Scale factors calculation */
|
||||
void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8],
|
||||
uint32_t scale_factor[2][8],
|
||||
int blocks, int channels, int subbands);
|
||||
const char *implementation_info;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize pointers to the functions which are the basic "building bricks"
|
||||
* of SBC codec. Best implementation is selected based on target CPU
|
||||
* capabilities.
|
||||
*/
|
||||
void sbc_init_primitives(struct sbc_encoder_state *encoder_state);
|
||||
|
||||
#endif
|
||||
320
src/modules/bluetooth/sbc/sbc_primitives_mmx.c
Normal file
320
src/modules/bluetooth/sbc/sbc_primitives_mmx.c
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "sbc.h"
|
||||
#include "sbc_math.h"
|
||||
#include "sbc_tables.h"
|
||||
|
||||
#include "sbc_primitives_mmx.h"
|
||||
|
||||
/*
|
||||
* MMX optimizations
|
||||
*/
|
||||
|
||||
#ifdef SBC_BUILD_WITH_MMX_SUPPORT
|
||||
|
||||
static inline void sbc_analyze_four_mmx(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
static const SBC_ALIGNED int32_t round_c[2] = {
|
||||
1 << (SBC_PROTO_FIXED4_SCALE - 1),
|
||||
1 << (SBC_PROTO_FIXED4_SCALE - 1),
|
||||
};
|
||||
asm volatile (
|
||||
"movq (%0), %%mm0\n"
|
||||
"movq 8(%0), %%mm1\n"
|
||||
"pmaddwd (%1), %%mm0\n"
|
||||
"pmaddwd 8(%1), %%mm1\n"
|
||||
"paddd (%2), %%mm0\n"
|
||||
"paddd (%2), %%mm1\n"
|
||||
"\n"
|
||||
"movq 16(%0), %%mm2\n"
|
||||
"movq 24(%0), %%mm3\n"
|
||||
"pmaddwd 16(%1), %%mm2\n"
|
||||
"pmaddwd 24(%1), %%mm3\n"
|
||||
"paddd %%mm2, %%mm0\n"
|
||||
"paddd %%mm3, %%mm1\n"
|
||||
"\n"
|
||||
"movq 32(%0), %%mm2\n"
|
||||
"movq 40(%0), %%mm3\n"
|
||||
"pmaddwd 32(%1), %%mm2\n"
|
||||
"pmaddwd 40(%1), %%mm3\n"
|
||||
"paddd %%mm2, %%mm0\n"
|
||||
"paddd %%mm3, %%mm1\n"
|
||||
"\n"
|
||||
"movq 48(%0), %%mm2\n"
|
||||
"movq 56(%0), %%mm3\n"
|
||||
"pmaddwd 48(%1), %%mm2\n"
|
||||
"pmaddwd 56(%1), %%mm3\n"
|
||||
"paddd %%mm2, %%mm0\n"
|
||||
"paddd %%mm3, %%mm1\n"
|
||||
"\n"
|
||||
"movq 64(%0), %%mm2\n"
|
||||
"movq 72(%0), %%mm3\n"
|
||||
"pmaddwd 64(%1), %%mm2\n"
|
||||
"pmaddwd 72(%1), %%mm3\n"
|
||||
"paddd %%mm2, %%mm0\n"
|
||||
"paddd %%mm3, %%mm1\n"
|
||||
"\n"
|
||||
"psrad %4, %%mm0\n"
|
||||
"psrad %4, %%mm1\n"
|
||||
"packssdw %%mm0, %%mm0\n"
|
||||
"packssdw %%mm1, %%mm1\n"
|
||||
"\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"pmaddwd 80(%1), %%mm0\n"
|
||||
"pmaddwd 88(%1), %%mm2\n"
|
||||
"\n"
|
||||
"movq %%mm1, %%mm3\n"
|
||||
"pmaddwd 96(%1), %%mm1\n"
|
||||
"pmaddwd 104(%1), %%mm3\n"
|
||||
"paddd %%mm1, %%mm0\n"
|
||||
"paddd %%mm3, %%mm2\n"
|
||||
"\n"
|
||||
"movq %%mm0, (%3)\n"
|
||||
"movq %%mm2, 8(%3)\n"
|
||||
:
|
||||
: "r" (in), "r" (consts), "r" (&round_c), "r" (out),
|
||||
"i" (SBC_PROTO_FIXED4_SCALE)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_eight_mmx(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
static const SBC_ALIGNED int32_t round_c[2] = {
|
||||
1 << (SBC_PROTO_FIXED8_SCALE - 1),
|
||||
1 << (SBC_PROTO_FIXED8_SCALE - 1),
|
||||
};
|
||||
asm volatile (
|
||||
"movq (%0), %%mm0\n"
|
||||
"movq 8(%0), %%mm1\n"
|
||||
"movq 16(%0), %%mm2\n"
|
||||
"movq 24(%0), %%mm3\n"
|
||||
"pmaddwd (%1), %%mm0\n"
|
||||
"pmaddwd 8(%1), %%mm1\n"
|
||||
"pmaddwd 16(%1), %%mm2\n"
|
||||
"pmaddwd 24(%1), %%mm3\n"
|
||||
"paddd (%2), %%mm0\n"
|
||||
"paddd (%2), %%mm1\n"
|
||||
"paddd (%2), %%mm2\n"
|
||||
"paddd (%2), %%mm3\n"
|
||||
"\n"
|
||||
"movq 32(%0), %%mm4\n"
|
||||
"movq 40(%0), %%mm5\n"
|
||||
"movq 48(%0), %%mm6\n"
|
||||
"movq 56(%0), %%mm7\n"
|
||||
"pmaddwd 32(%1), %%mm4\n"
|
||||
"pmaddwd 40(%1), %%mm5\n"
|
||||
"pmaddwd 48(%1), %%mm6\n"
|
||||
"pmaddwd 56(%1), %%mm7\n"
|
||||
"paddd %%mm4, %%mm0\n"
|
||||
"paddd %%mm5, %%mm1\n"
|
||||
"paddd %%mm6, %%mm2\n"
|
||||
"paddd %%mm7, %%mm3\n"
|
||||
"\n"
|
||||
"movq 64(%0), %%mm4\n"
|
||||
"movq 72(%0), %%mm5\n"
|
||||
"movq 80(%0), %%mm6\n"
|
||||
"movq 88(%0), %%mm7\n"
|
||||
"pmaddwd 64(%1), %%mm4\n"
|
||||
"pmaddwd 72(%1), %%mm5\n"
|
||||
"pmaddwd 80(%1), %%mm6\n"
|
||||
"pmaddwd 88(%1), %%mm7\n"
|
||||
"paddd %%mm4, %%mm0\n"
|
||||
"paddd %%mm5, %%mm1\n"
|
||||
"paddd %%mm6, %%mm2\n"
|
||||
"paddd %%mm7, %%mm3\n"
|
||||
"\n"
|
||||
"movq 96(%0), %%mm4\n"
|
||||
"movq 104(%0), %%mm5\n"
|
||||
"movq 112(%0), %%mm6\n"
|
||||
"movq 120(%0), %%mm7\n"
|
||||
"pmaddwd 96(%1), %%mm4\n"
|
||||
"pmaddwd 104(%1), %%mm5\n"
|
||||
"pmaddwd 112(%1), %%mm6\n"
|
||||
"pmaddwd 120(%1), %%mm7\n"
|
||||
"paddd %%mm4, %%mm0\n"
|
||||
"paddd %%mm5, %%mm1\n"
|
||||
"paddd %%mm6, %%mm2\n"
|
||||
"paddd %%mm7, %%mm3\n"
|
||||
"\n"
|
||||
"movq 128(%0), %%mm4\n"
|
||||
"movq 136(%0), %%mm5\n"
|
||||
"movq 144(%0), %%mm6\n"
|
||||
"movq 152(%0), %%mm7\n"
|
||||
"pmaddwd 128(%1), %%mm4\n"
|
||||
"pmaddwd 136(%1), %%mm5\n"
|
||||
"pmaddwd 144(%1), %%mm6\n"
|
||||
"pmaddwd 152(%1), %%mm7\n"
|
||||
"paddd %%mm4, %%mm0\n"
|
||||
"paddd %%mm5, %%mm1\n"
|
||||
"paddd %%mm6, %%mm2\n"
|
||||
"paddd %%mm7, %%mm3\n"
|
||||
"\n"
|
||||
"psrad %4, %%mm0\n"
|
||||
"psrad %4, %%mm1\n"
|
||||
"psrad %4, %%mm2\n"
|
||||
"psrad %4, %%mm3\n"
|
||||
"\n"
|
||||
"packssdw %%mm0, %%mm0\n"
|
||||
"packssdw %%mm1, %%mm1\n"
|
||||
"packssdw %%mm2, %%mm2\n"
|
||||
"packssdw %%mm3, %%mm3\n"
|
||||
"\n"
|
||||
"movq %%mm0, %%mm4\n"
|
||||
"movq %%mm0, %%mm5\n"
|
||||
"pmaddwd 160(%1), %%mm4\n"
|
||||
"pmaddwd 168(%1), %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm1, %%mm6\n"
|
||||
"movq %%mm1, %%mm7\n"
|
||||
"pmaddwd 192(%1), %%mm6\n"
|
||||
"pmaddwd 200(%1), %%mm7\n"
|
||||
"paddd %%mm6, %%mm4\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm2, %%mm6\n"
|
||||
"movq %%mm2, %%mm7\n"
|
||||
"pmaddwd 224(%1), %%mm6\n"
|
||||
"pmaddwd 232(%1), %%mm7\n"
|
||||
"paddd %%mm6, %%mm4\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm3, %%mm6\n"
|
||||
"movq %%mm3, %%mm7\n"
|
||||
"pmaddwd 256(%1), %%mm6\n"
|
||||
"pmaddwd 264(%1), %%mm7\n"
|
||||
"paddd %%mm6, %%mm4\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm4, (%3)\n"
|
||||
"movq %%mm5, 8(%3)\n"
|
||||
"\n"
|
||||
"movq %%mm0, %%mm5\n"
|
||||
"pmaddwd 176(%1), %%mm0\n"
|
||||
"pmaddwd 184(%1), %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm1, %%mm7\n"
|
||||
"pmaddwd 208(%1), %%mm1\n"
|
||||
"pmaddwd 216(%1), %%mm7\n"
|
||||
"paddd %%mm1, %%mm0\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm2, %%mm7\n"
|
||||
"pmaddwd 240(%1), %%mm2\n"
|
||||
"pmaddwd 248(%1), %%mm7\n"
|
||||
"paddd %%mm2, %%mm0\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm3, %%mm7\n"
|
||||
"pmaddwd 272(%1), %%mm3\n"
|
||||
"pmaddwd 280(%1), %%mm7\n"
|
||||
"paddd %%mm3, %%mm0\n"
|
||||
"paddd %%mm7, %%mm5\n"
|
||||
"\n"
|
||||
"movq %%mm0, 16(%3)\n"
|
||||
"movq %%mm5, 24(%3)\n"
|
||||
:
|
||||
: "r" (in), "r" (consts), "r" (&round_c), "r" (out),
|
||||
"i" (SBC_PROTO_FIXED8_SCALE)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_4s_mmx(int16_t *x, int32_t *out,
|
||||
int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
sbc_analyze_four_mmx(x + 12, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_mmx(x + 8, out, analysis_consts_fixed4_simd_even);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_mmx(x + 4, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_four_mmx(x + 0, out, analysis_consts_fixed4_simd_even);
|
||||
|
||||
asm volatile ("emms\n");
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_8s_mmx(int16_t *x, int32_t *out,
|
||||
int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
sbc_analyze_eight_mmx(x + 24, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_mmx(x + 16, out, analysis_consts_fixed8_simd_even);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_mmx(x + 8, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
sbc_analyze_eight_mmx(x + 0, out, analysis_consts_fixed8_simd_even);
|
||||
|
||||
asm volatile ("emms\n");
|
||||
}
|
||||
|
||||
static int check_mmx_support(void)
|
||||
{
|
||||
#ifdef __amd64__
|
||||
return 1; /* We assume that all 64-bit processors have MMX support */
|
||||
#else
|
||||
int cpuid_feature_information;
|
||||
asm volatile (
|
||||
/* According to Intel manual, CPUID instruction is supported
|
||||
* if the value of ID bit (bit 21) in EFLAGS can be modified */
|
||||
"pushf\n"
|
||||
"movl (%%esp), %0\n"
|
||||
"xorl $0x200000, (%%esp)\n" /* try to modify ID bit */
|
||||
"popf\n"
|
||||
"pushf\n"
|
||||
"xorl (%%esp), %0\n" /* check if ID bit changed */
|
||||
"jz 1f\n"
|
||||
"push %%eax\n"
|
||||
"push %%ebx\n"
|
||||
"push %%ecx\n"
|
||||
"mov $1, %%eax\n"
|
||||
"cpuid\n"
|
||||
"pop %%ecx\n"
|
||||
"pop %%ebx\n"
|
||||
"pop %%eax\n"
|
||||
"1:\n"
|
||||
"popf\n"
|
||||
: "=d" (cpuid_feature_information)
|
||||
:
|
||||
: "cc");
|
||||
return cpuid_feature_information & (1 << 23);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
|
||||
{
|
||||
if (check_mmx_support()) {
|
||||
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_mmx;
|
||||
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
|
||||
state->implementation_info = "MMX";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
40
src/modules/bluetooth/sbc/sbc_primitives_mmx.h
Normal file
40
src/modules/bluetooth/sbc/sbc_primitives_mmx.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBC_PRIMITIVES_MMX_H
|
||||
#define __SBC_PRIMITIVES_MMX_H
|
||||
|
||||
#include "sbc_primitives.h"
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__)) && \
|
||||
!defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
|
||||
|
||||
#define SBC_BUILD_WITH_MMX_SUPPORT
|
||||
|
||||
void sbc_init_primitives_mmx(struct sbc_encoder_state *encoder_state);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
246
src/modules/bluetooth/sbc/sbc_primitives_neon.c
Normal file
246
src/modules/bluetooth/sbc/sbc_primitives_neon.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "sbc.h"
|
||||
#include "sbc_math.h"
|
||||
#include "sbc_tables.h"
|
||||
|
||||
#include "sbc_primitives_neon.h"
|
||||
|
||||
/*
|
||||
* ARM NEON optimizations
|
||||
*/
|
||||
|
||||
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
|
||||
|
||||
static inline void _sbc_analyze_four_neon(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
/* 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 */
|
||||
asm volatile (
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmull.s16 q0, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmull.s16 q1, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q0, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmlal.s16 q1, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q0, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmlal.s16 q1, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q0, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmlal.s16 q1, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q0, d4, d8\n"
|
||||
"vmlal.s16 q1, d5, d9\n"
|
||||
|
||||
"vpadd.s32 d0, d0, d1\n"
|
||||
"vpadd.s32 d1, d2, d3\n"
|
||||
|
||||
"vrshrn.s32 d0, q0, %3\n"
|
||||
|
||||
"vld1.16 {d2, d3, d4, d5}, [%1, :128]!\n"
|
||||
|
||||
"vdup.i32 d1, d0[1]\n" /* TODO: can be eliminated */
|
||||
"vdup.i32 d0, d0[0]\n" /* TODO: can be eliminated */
|
||||
|
||||
"vmull.s16 q3, d2, d0\n"
|
||||
"vmull.s16 q4, d3, d0\n"
|
||||
"vmlal.s16 q3, d4, d1\n"
|
||||
"vmlal.s16 q4, d5, d1\n"
|
||||
|
||||
"vpadd.s32 d0, d6, d7\n" /* TODO: can be eliminated */
|
||||
"vpadd.s32 d1, d8, d9\n" /* TODO: can be eliminated */
|
||||
|
||||
"vst1.32 {d0, d1}, [%2, :128]\n"
|
||||
: "+r" (in), "+r" (consts)
|
||||
: "r" (out),
|
||||
"i" (SBC_PROTO_FIXED4_SCALE)
|
||||
: "memory",
|
||||
"d0", "d1", "d2", "d3", "d4", "d5",
|
||||
"d6", "d7", "d8", "d9", "d10", "d11");
|
||||
}
|
||||
|
||||
static inline void _sbc_analyze_eight_neon(const int16_t *in, int32_t *out,
|
||||
const FIXED_T *consts)
|
||||
{
|
||||
/* 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 */
|
||||
asm volatile (
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmull.s16 q6, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmull.s16 q7, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
"vmull.s16 q8, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmull.s16 q9, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q6, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmlal.s16 q7, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
"vmlal.s16 q8, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmlal.s16 q9, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q6, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmlal.s16 q7, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
"vmlal.s16 q8, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmlal.s16 q9, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q6, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmlal.s16 q7, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
"vmlal.s16 q8, d6, d10\n"
|
||||
"vld1.16 {d4, d5}, [%0, :64]!\n"
|
||||
"vmlal.s16 q9, d7, d11\n"
|
||||
"vld1.16 {d8, d9}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q6, d4, d8\n"
|
||||
"vld1.16 {d6, d7}, [%0, :64]!\n"
|
||||
"vmlal.s16 q7, d5, d9\n"
|
||||
"vld1.16 {d10, d11}, [%1, :128]!\n"
|
||||
|
||||
"vmlal.s16 q8, d6, d10\n"
|
||||
"vmlal.s16 q9, d7, d11\n"
|
||||
|
||||
"vpadd.s32 d0, d12, d13\n"
|
||||
"vpadd.s32 d1, d14, d15\n"
|
||||
"vpadd.s32 d2, d16, d17\n"
|
||||
"vpadd.s32 d3, d18, d19\n"
|
||||
|
||||
"vrshr.s32 q0, q0, %3\n"
|
||||
"vrshr.s32 q1, q1, %3\n"
|
||||
"vmovn.s32 d0, q0\n"
|
||||
"vmovn.s32 d1, q1\n"
|
||||
|
||||
"vdup.i32 d3, d1[1]\n" /* TODO: can be eliminated */
|
||||
"vdup.i32 d2, d1[0]\n" /* TODO: can be eliminated */
|
||||
"vdup.i32 d1, d0[1]\n" /* TODO: can be eliminated */
|
||||
"vdup.i32 d0, d0[0]\n" /* TODO: can be eliminated */
|
||||
|
||||
"vld1.16 {d4, d5}, [%1, :128]!\n"
|
||||
"vmull.s16 q6, d4, d0\n"
|
||||
"vld1.16 {d6, d7}, [%1, :128]!\n"
|
||||
"vmull.s16 q7, d5, d0\n"
|
||||
"vmull.s16 q8, d6, d0\n"
|
||||
"vmull.s16 q9, d7, d0\n"
|
||||
|
||||
"vld1.16 {d4, d5}, [%1, :128]!\n"
|
||||
"vmlal.s16 q6, d4, d1\n"
|
||||
"vld1.16 {d6, d7}, [%1, :128]!\n"
|
||||
"vmlal.s16 q7, d5, d1\n"
|
||||
"vmlal.s16 q8, d6, d1\n"
|
||||
"vmlal.s16 q9, d7, d1\n"
|
||||
|
||||
"vld1.16 {d4, d5}, [%1, :128]!\n"
|
||||
"vmlal.s16 q6, d4, d2\n"
|
||||
"vld1.16 {d6, d7}, [%1, :128]!\n"
|
||||
"vmlal.s16 q7, d5, d2\n"
|
||||
"vmlal.s16 q8, d6, d2\n"
|
||||
"vmlal.s16 q9, d7, d2\n"
|
||||
|
||||
"vld1.16 {d4, d5}, [%1, :128]!\n"
|
||||
"vmlal.s16 q6, d4, d3\n"
|
||||
"vld1.16 {d6, d7}, [%1, :128]!\n"
|
||||
"vmlal.s16 q7, d5, d3\n"
|
||||
"vmlal.s16 q8, d6, d3\n"
|
||||
"vmlal.s16 q9, d7, d3\n"
|
||||
|
||||
"vpadd.s32 d0, d12, d13\n" /* TODO: can be eliminated */
|
||||
"vpadd.s32 d1, d14, d15\n" /* TODO: can be eliminated */
|
||||
"vpadd.s32 d2, d16, d17\n" /* TODO: can be eliminated */
|
||||
"vpadd.s32 d3, d18, d19\n" /* TODO: can be eliminated */
|
||||
|
||||
"vst1.32 {d0, d1, d2, d3}, [%2, :128]\n"
|
||||
: "+r" (in), "+r" (consts)
|
||||
: "r" (out),
|
||||
"i" (SBC_PROTO_FIXED8_SCALE)
|
||||
: "memory",
|
||||
"d0", "d1", "d2", "d3", "d4", "d5",
|
||||
"d6", "d7", "d8", "d9", "d10", "d11",
|
||||
"d12", "d13", "d14", "d15", "d16", "d17",
|
||||
"d18", "d19");
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_4s_neon(int16_t *x,
|
||||
int32_t *out, int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
_sbc_analyze_four_neon(x + 12, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
_sbc_analyze_four_neon(x + 8, out, analysis_consts_fixed4_simd_even);
|
||||
out += out_stride;
|
||||
_sbc_analyze_four_neon(x + 4, out, analysis_consts_fixed4_simd_odd);
|
||||
out += out_stride;
|
||||
_sbc_analyze_four_neon(x + 0, out, analysis_consts_fixed4_simd_even);
|
||||
}
|
||||
|
||||
static inline void sbc_analyze_4b_8s_neon(int16_t *x,
|
||||
int32_t *out, int out_stride)
|
||||
{
|
||||
/* Analyze blocks */
|
||||
_sbc_analyze_eight_neon(x + 24, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
_sbc_analyze_eight_neon(x + 16, out, analysis_consts_fixed8_simd_even);
|
||||
out += out_stride;
|
||||
_sbc_analyze_eight_neon(x + 8, out, analysis_consts_fixed8_simd_odd);
|
||||
out += out_stride;
|
||||
_sbc_analyze_eight_neon(x + 0, out, analysis_consts_fixed8_simd_even);
|
||||
}
|
||||
|
||||
void sbc_init_primitives_neon(struct sbc_encoder_state *state)
|
||||
{
|
||||
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_neon;
|
||||
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_neon;
|
||||
state->implementation_info = "NEON";
|
||||
}
|
||||
|
||||
#endif
|
||||
40
src/modules/bluetooth/sbc/sbc_primitives_neon.h
Normal file
40
src/modules/bluetooth/sbc/sbc_primitives_neon.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBC_PRIMITIVES_NEON_H
|
||||
#define __SBC_PRIMITIVES_NEON_H
|
||||
|
||||
#include "sbc_primitives.h"
|
||||
|
||||
#if defined(__GNUC__) && defined(__ARM_NEON__) && \
|
||||
!defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
|
||||
|
||||
#define SBC_BUILD_WITH_NEON_SUPPORT
|
||||
|
||||
void sbc_init_primitives_neon(struct sbc_encoder_state *encoder_state);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
659
src/modules/bluetooth/sbc/sbc_tables.h
Normal file
659
src/modules/bluetooth/sbc/sbc_tables.h
Normal file
|
|
@ -0,0 +1,659 @@
|
|||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library 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.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* A2DP specification: Appendix B, page 69 */
|
||||
static const int sbc_offset4[4][4] = {
|
||||
{ -1, 0, 0, 0 },
|
||||
{ -2, 0, 0, 1 },
|
||||
{ -2, 0, 0, 1 },
|
||||
{ -2, 0, 0, 1 }
|
||||
};
|
||||
|
||||
/* A2DP specification: Appendix B, page 69 */
|
||||
static const int sbc_offset8[4][8] = {
|
||||
{ -2, 0, 0, 0, 0, 0, 0, 1 },
|
||||
{ -3, 0, 0, 0, 0, 0, 1, 2 },
|
||||
{ -4, 0, 0, 0, 0, 0, 1, 2 },
|
||||
{ -4, 0, 0, 0, 0, 0, 1, 2 }
|
||||
};
|
||||
|
||||
|
||||
#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
|
||||
#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
|
||||
#define SN4(val) ASR(val, SCALE_NPROTO4_TBL)
|
||||
#define SN8(val) ASR(val, SCALE_NPROTO8_TBL)
|
||||
|
||||
static const int32_t sbc_proto_4_40m0[] = {
|
||||
SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
|
||||
SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
|
||||
SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
|
||||
SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
|
||||
SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_4_40m1[] = {
|
||||
SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
|
||||
SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
|
||||
SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
|
||||
SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
|
||||
SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_8_80m0[] = {
|
||||
SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
|
||||
SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
|
||||
SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
|
||||
SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
|
||||
SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
|
||||
SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
|
||||
SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
|
||||
SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
|
||||
SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
|
||||
SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_8_80m1[] = {
|
||||
SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
|
||||
SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
|
||||
SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
|
||||
SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
|
||||
SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
|
||||
SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
|
||||
SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
|
||||
SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
|
||||
SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
|
||||
SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
|
||||
};
|
||||
|
||||
static const int32_t synmatrix4[8][4] = {
|
||||
{ SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
|
||||
{ SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
|
||||
{ SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
|
||||
{ SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
|
||||
{ SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
|
||||
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
|
||||
{ SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
|
||||
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
|
||||
};
|
||||
|
||||
static const int32_t synmatrix8[16][8] = {
|
||||
{ SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
|
||||
SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
|
||||
{ SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
|
||||
SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
|
||||
{ SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
|
||||
SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
|
||||
{ SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
|
||||
SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
|
||||
{ SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
|
||||
SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
|
||||
{ SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
|
||||
SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
|
||||
{ SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
|
||||
SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
|
||||
{ SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
|
||||
SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
|
||||
{ SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
|
||||
SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
|
||||
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
|
||||
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
|
||||
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
|
||||
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
|
||||
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
|
||||
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
|
||||
{ SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
|
||||
SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
|
||||
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
|
||||
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
|
||||
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
|
||||
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
|
||||
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
|
||||
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
|
||||
};
|
||||
|
||||
/* Uncomment the following line to enable high precision build of SBC encoder */
|
||||
|
||||
/* #define SBC_HIGH_PRECISION */
|
||||
|
||||
#ifdef SBC_HIGH_PRECISION
|
||||
#define FIXED_A int64_t /* data type for fixed point accumulator */
|
||||
#define FIXED_T int32_t /* data type for fixed point constants */
|
||||
#define SBC_FIXED_EXTRA_BITS 16
|
||||
#else
|
||||
#define FIXED_A int32_t /* data type for fixed point accumulator */
|
||||
#define FIXED_T int16_t /* data type for fixed point constants */
|
||||
#define SBC_FIXED_EXTRA_BITS 0
|
||||
#endif
|
||||
|
||||
/* A2DP specification: Section 12.8 Tables
|
||||
*
|
||||
* Original values are premultiplied by 2 for better precision (that is the
|
||||
* maximum which is possible without overflows)
|
||||
*
|
||||
* Note: in each block of 8 numbers sign was changed for elements 2 and 7
|
||||
* in order to compensate the same change applied to cos_table_fixed_4
|
||||
*/
|
||||
#define SBC_PROTO_FIXED4_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
|
||||
#define F_PROTO4(x) (FIXED_A) ((x * 2) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_PROTO4(x)
|
||||
static const FIXED_T _sbc_proto_fixed4[40] = {
|
||||
F(0.00000000E+00), F(5.36548976E-04),
|
||||
-F(1.49188357E-03), F(2.73370904E-03),
|
||||
F(3.83720193E-03), F(3.89205149E-03),
|
||||
F(1.86581691E-03), F(3.06012286E-03),
|
||||
|
||||
F(1.09137620E-02), F(2.04385087E-02),
|
||||
-F(2.88757392E-02), F(3.21939290E-02),
|
||||
F(2.58767811E-02), F(6.13245186E-03),
|
||||
-F(2.88217274E-02), F(7.76463494E-02),
|
||||
|
||||
F(1.35593274E-01), F(1.94987841E-01),
|
||||
-F(2.46636662E-01), F(2.81828203E-01),
|
||||
F(2.94315332E-01), F(2.81828203E-01),
|
||||
F(2.46636662E-01), -F(1.94987841E-01),
|
||||
|
||||
-F(1.35593274E-01), -F(7.76463494E-02),
|
||||
F(2.88217274E-02), F(6.13245186E-03),
|
||||
F(2.58767811E-02), F(3.21939290E-02),
|
||||
F(2.88757392E-02), -F(2.04385087E-02),
|
||||
|
||||
-F(1.09137620E-02), -F(3.06012286E-03),
|
||||
-F(1.86581691E-03), F(3.89205149E-03),
|
||||
F(3.83720193E-03), F(2.73370904E-03),
|
||||
F(1.49188357E-03), -F(5.36548976E-04),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* To produce this cosine matrix in Octave:
|
||||
*
|
||||
* b = zeros(4, 8);
|
||||
* for i = 0:3
|
||||
* for j = 0:7 b(i+1, j+1) = cos((i + 0.5) * (j - 2) * (pi/4))
|
||||
* endfor
|
||||
* endfor;
|
||||
* printf("%.10f, ", b');
|
||||
*
|
||||
* Note: in each block of 8 numbers sign was changed for elements 2 and 7
|
||||
*
|
||||
* Change of sign for element 2 allows to replace constant 1.0 (not
|
||||
* representable in Q15 format) with -1.0 (fine with Q15).
|
||||
* Changed sign for element 7 allows to have more similar constants
|
||||
* and simplify subband filter function code.
|
||||
*/
|
||||
#define SBC_COS_TABLE_FIXED4_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
|
||||
#define F_COS4(x) (FIXED_A) ((x) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_COS4(x)
|
||||
static const FIXED_T cos_table_fixed_4[32] = {
|
||||
F(0.7071067812), F(0.9238795325), -F(1.0000000000), F(0.9238795325),
|
||||
F(0.7071067812), F(0.3826834324), F(0.0000000000), F(0.3826834324),
|
||||
|
||||
-F(0.7071067812), F(0.3826834324), -F(1.0000000000), F(0.3826834324),
|
||||
-F(0.7071067812), -F(0.9238795325), -F(0.0000000000), -F(0.9238795325),
|
||||
|
||||
-F(0.7071067812), -F(0.3826834324), -F(1.0000000000), -F(0.3826834324),
|
||||
-F(0.7071067812), F(0.9238795325), F(0.0000000000), F(0.9238795325),
|
||||
|
||||
F(0.7071067812), -F(0.9238795325), -F(1.0000000000), -F(0.9238795325),
|
||||
F(0.7071067812), -F(0.3826834324), -F(0.0000000000), -F(0.3826834324),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/* A2DP specification: Section 12.8 Tables
|
||||
*
|
||||
* Original values are premultiplied by 4 for better precision (that is the
|
||||
* maximum which is possible without overflows)
|
||||
*
|
||||
* Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
|
||||
* in order to compensate the same change applied to cos_table_fixed_8
|
||||
*/
|
||||
#define SBC_PROTO_FIXED8_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
|
||||
#define F_PROTO8(x) (FIXED_A) ((x * 2) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_PROTO8(x)
|
||||
static const FIXED_T _sbc_proto_fixed8[80] = {
|
||||
F(0.00000000E+00), F(1.56575398E-04),
|
||||
F(3.43256425E-04), F(5.54620202E-04),
|
||||
-F(8.23919506E-04), F(1.13992507E-03),
|
||||
F(1.47640169E-03), F(1.78371725E-03),
|
||||
F(2.01182542E-03), F(2.10371989E-03),
|
||||
F(1.99454554E-03), F(1.61656283E-03),
|
||||
F(9.02154502E-04), F(1.78805361E-04),
|
||||
F(1.64973098E-03), F(3.49717454E-03),
|
||||
|
||||
F(5.65949473E-03), F(8.02941163E-03),
|
||||
F(1.04584443E-02), F(1.27472335E-02),
|
||||
-F(1.46525263E-02), F(1.59045603E-02),
|
||||
F(1.62208471E-02), F(1.53184106E-02),
|
||||
F(1.29371806E-02), F(8.85757540E-03),
|
||||
F(2.92408442E-03), -F(4.91578024E-03),
|
||||
-F(1.46404076E-02), F(2.61098752E-02),
|
||||
F(3.90751381E-02), F(5.31873032E-02),
|
||||
|
||||
F(6.79989431E-02), F(8.29847578E-02),
|
||||
F(9.75753918E-02), F(1.11196689E-01),
|
||||
-F(1.23264548E-01), F(1.33264415E-01),
|
||||
F(1.40753505E-01), F(1.45389847E-01),
|
||||
F(1.46955068E-01), F(1.45389847E-01),
|
||||
F(1.40753505E-01), F(1.33264415E-01),
|
||||
F(1.23264548E-01), -F(1.11196689E-01),
|
||||
-F(9.75753918E-02), -F(8.29847578E-02),
|
||||
|
||||
-F(6.79989431E-02), -F(5.31873032E-02),
|
||||
-F(3.90751381E-02), -F(2.61098752E-02),
|
||||
F(1.46404076E-02), -F(4.91578024E-03),
|
||||
F(2.92408442E-03), F(8.85757540E-03),
|
||||
F(1.29371806E-02), F(1.53184106E-02),
|
||||
F(1.62208471E-02), F(1.59045603E-02),
|
||||
F(1.46525263E-02), -F(1.27472335E-02),
|
||||
-F(1.04584443E-02), -F(8.02941163E-03),
|
||||
|
||||
-F(5.65949473E-03), -F(3.49717454E-03),
|
||||
-F(1.64973098E-03), -F(1.78805361E-04),
|
||||
-F(9.02154502E-04), F(1.61656283E-03),
|
||||
F(1.99454554E-03), F(2.10371989E-03),
|
||||
F(2.01182542E-03), F(1.78371725E-03),
|
||||
F(1.47640169E-03), F(1.13992507E-03),
|
||||
F(8.23919506E-04), -F(5.54620202E-04),
|
||||
-F(3.43256425E-04), -F(1.56575398E-04),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* To produce this cosine matrix in Octave:
|
||||
*
|
||||
* b = zeros(8, 16);
|
||||
* for i = 0:7
|
||||
* for j = 0:15 b(i+1, j+1) = cos((i + 0.5) * (j - 4) * (pi/8))
|
||||
* endfor endfor;
|
||||
* printf("%.10f, ", b');
|
||||
*
|
||||
* Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
|
||||
*
|
||||
* Change of sign for element 4 allows to replace constant 1.0 (not
|
||||
* representable in Q15 format) with -1.0 (fine with Q15).
|
||||
* Changed signs for elements 13, 14, 15 allow to have more similar constants
|
||||
* and simplify subband filter function code.
|
||||
*/
|
||||
#define SBC_COS_TABLE_FIXED8_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
|
||||
#define F_COS8(x) (FIXED_A) ((x) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_COS8(x)
|
||||
static const FIXED_T cos_table_fixed_8[128] = {
|
||||
F(0.7071067812), F(0.8314696123), F(0.9238795325), F(0.9807852804),
|
||||
-F(1.0000000000), F(0.9807852804), F(0.9238795325), F(0.8314696123),
|
||||
F(0.7071067812), F(0.5555702330), F(0.3826834324), F(0.1950903220),
|
||||
F(0.0000000000), F(0.1950903220), F(0.3826834324), F(0.5555702330),
|
||||
|
||||
-F(0.7071067812), -F(0.1950903220), F(0.3826834324), F(0.8314696123),
|
||||
-F(1.0000000000), F(0.8314696123), F(0.3826834324), -F(0.1950903220),
|
||||
-F(0.7071067812), -F(0.9807852804), -F(0.9238795325), -F(0.5555702330),
|
||||
-F(0.0000000000), -F(0.5555702330), -F(0.9238795325), -F(0.9807852804),
|
||||
|
||||
-F(0.7071067812), -F(0.9807852804), -F(0.3826834324), F(0.5555702330),
|
||||
-F(1.0000000000), F(0.5555702330), -F(0.3826834324), -F(0.9807852804),
|
||||
-F(0.7071067812), F(0.1950903220), F(0.9238795325), F(0.8314696123),
|
||||
F(0.0000000000), F(0.8314696123), F(0.9238795325), F(0.1950903220),
|
||||
|
||||
F(0.7071067812), -F(0.5555702330), -F(0.9238795325), F(0.1950903220),
|
||||
-F(1.0000000000), F(0.1950903220), -F(0.9238795325), -F(0.5555702330),
|
||||
F(0.7071067812), F(0.8314696123), -F(0.3826834324), -F(0.9807852804),
|
||||
-F(0.0000000000), -F(0.9807852804), -F(0.3826834324), F(0.8314696123),
|
||||
|
||||
F(0.7071067812), F(0.5555702330), -F(0.9238795325), -F(0.1950903220),
|
||||
-F(1.0000000000), -F(0.1950903220), -F(0.9238795325), F(0.5555702330),
|
||||
F(0.7071067812), -F(0.8314696123), -F(0.3826834324), F(0.9807852804),
|
||||
F(0.0000000000), F(0.9807852804), -F(0.3826834324), -F(0.8314696123),
|
||||
|
||||
-F(0.7071067812), F(0.9807852804), -F(0.3826834324), -F(0.5555702330),
|
||||
-F(1.0000000000), -F(0.5555702330), -F(0.3826834324), F(0.9807852804),
|
||||
-F(0.7071067812), -F(0.1950903220), F(0.9238795325), -F(0.8314696123),
|
||||
-F(0.0000000000), -F(0.8314696123), F(0.9238795325), -F(0.1950903220),
|
||||
|
||||
-F(0.7071067812), F(0.1950903220), F(0.3826834324), -F(0.8314696123),
|
||||
-F(1.0000000000), -F(0.8314696123), F(0.3826834324), F(0.1950903220),
|
||||
-F(0.7071067812), F(0.9807852804), -F(0.9238795325), F(0.5555702330),
|
||||
-F(0.0000000000), F(0.5555702330), -F(0.9238795325), F(0.9807852804),
|
||||
|
||||
F(0.7071067812), -F(0.8314696123), F(0.9238795325), -F(0.9807852804),
|
||||
-F(1.0000000000), -F(0.9807852804), F(0.9238795325), -F(0.8314696123),
|
||||
F(0.7071067812), -F(0.5555702330), F(0.3826834324), -F(0.1950903220),
|
||||
-F(0.0000000000), -F(0.1950903220), F(0.3826834324), -F(0.5555702330),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* Enforce 16 byte alignment for the data, which is supposed to be used
|
||||
* with SIMD optimized code.
|
||||
*/
|
||||
|
||||
#define SBC_ALIGN_BITS 4
|
||||
#define SBC_ALIGN_MASK ((1 << (SBC_ALIGN_BITS)) - 1)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define SBC_ALIGNED __attribute__((aligned(1 << (SBC_ALIGN_BITS))))
|
||||
#else
|
||||
#define SBC_ALIGNED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constant tables for the use in SIMD optimized analysis filters
|
||||
* Each table consists of two parts:
|
||||
* 1. reordered "proto" table
|
||||
* 2. reordered "cos" table
|
||||
*
|
||||
* Due to non-symmetrical reordering, separate tables for "even"
|
||||
* and "odd" cases are needed
|
||||
*/
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_even[40 + 16] = {
|
||||
#define C0 1.0932568993
|
||||
#define C1 1.3056875580
|
||||
#define C2 1.3056875580
|
||||
#define C3 1.6772280856
|
||||
|
||||
#define F(x) F_PROTO4(x)
|
||||
F(0.00000000E+00 * C0), F(3.83720193E-03 * C0),
|
||||
F(5.36548976E-04 * C1), F(2.73370904E-03 * C1),
|
||||
F(3.06012286E-03 * C2), F(3.89205149E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(1.49188357E-03 * C3),
|
||||
F(1.09137620E-02 * C0), F(2.58767811E-02 * C0),
|
||||
F(2.04385087E-02 * C1), F(3.21939290E-02 * C1),
|
||||
F(7.76463494E-02 * C2), F(6.13245186E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(2.88757392E-02 * C3),
|
||||
F(1.35593274E-01 * C0), F(2.94315332E-01 * C0),
|
||||
F(1.94987841E-01 * C1), F(2.81828203E-01 * C1),
|
||||
-F(1.94987841E-01 * C2), F(2.81828203E-01 * C2),
|
||||
F(0.00000000E+00 * C3), -F(2.46636662E-01 * C3),
|
||||
-F(1.35593274E-01 * C0), F(2.58767811E-02 * C0),
|
||||
-F(7.76463494E-02 * C1), F(6.13245186E-03 * C1),
|
||||
-F(2.04385087E-02 * C2), F(3.21939290E-02 * C2),
|
||||
F(0.00000000E+00 * C3), F(2.88217274E-02 * C3),
|
||||
-F(1.09137620E-02 * C0), F(3.83720193E-03 * C0),
|
||||
-F(3.06012286E-03 * C1), F(3.89205149E-03 * C1),
|
||||
-F(5.36548976E-04 * C2), F(2.73370904E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(1.86581691E-03 * C3),
|
||||
#undef F
|
||||
#define F(x) F_COS4(x)
|
||||
F(0.7071067812 / C0), F(0.9238795325 / C1),
|
||||
-F(0.7071067812 / C0), F(0.3826834324 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.3826834324 / C1),
|
||||
F(0.7071067812 / C0), -F(0.9238795325 / C1),
|
||||
F(0.3826834324 / C2), -F(1.0000000000 / C3),
|
||||
-F(0.9238795325 / C2), -F(1.0000000000 / C3),
|
||||
F(0.9238795325 / C2), -F(1.0000000000 / C3),
|
||||
-F(0.3826834324 / C2), -F(1.0000000000 / C3),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_odd[40 + 16] = {
|
||||
#define C0 1.3056875580
|
||||
#define C1 1.6772280856
|
||||
#define C2 1.0932568993
|
||||
#define C3 1.3056875580
|
||||
|
||||
#define F(x) F_PROTO4(x)
|
||||
F(2.73370904E-03 * C0), F(5.36548976E-04 * C0),
|
||||
-F(1.49188357E-03 * C1), F(0.00000000E+00 * C1),
|
||||
F(3.83720193E-03 * C2), F(1.09137620E-02 * C2),
|
||||
F(3.89205149E-03 * C3), F(3.06012286E-03 * C3),
|
||||
F(3.21939290E-02 * C0), F(2.04385087E-02 * C0),
|
||||
-F(2.88757392E-02 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.58767811E-02 * C2), F(1.35593274E-01 * C2),
|
||||
F(6.13245186E-03 * C3), F(7.76463494E-02 * C3),
|
||||
F(2.81828203E-01 * C0), F(1.94987841E-01 * C0),
|
||||
-F(2.46636662E-01 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.94315332E-01 * C2), -F(1.35593274E-01 * C2),
|
||||
F(2.81828203E-01 * C3), -F(1.94987841E-01 * C3),
|
||||
F(6.13245186E-03 * C0), -F(7.76463494E-02 * C0),
|
||||
F(2.88217274E-02 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.58767811E-02 * C2), -F(1.09137620E-02 * C2),
|
||||
F(3.21939290E-02 * C3), -F(2.04385087E-02 * C3),
|
||||
F(3.89205149E-03 * C0), -F(3.06012286E-03 * C0),
|
||||
-F(1.86581691E-03 * C1), F(0.00000000E+00 * C1),
|
||||
F(3.83720193E-03 * C2), F(0.00000000E+00 * C2),
|
||||
F(2.73370904E-03 * C3), -F(5.36548976E-04 * C3),
|
||||
#undef F
|
||||
#define F(x) F_COS4(x)
|
||||
F(0.9238795325 / C0), -F(1.0000000000 / C1),
|
||||
F(0.3826834324 / C0), -F(1.0000000000 / C1),
|
||||
-F(0.3826834324 / C0), -F(1.0000000000 / C1),
|
||||
-F(0.9238795325 / C0), -F(1.0000000000 / C1),
|
||||
F(0.7071067812 / C2), F(0.3826834324 / C3),
|
||||
-F(0.7071067812 / C2), -F(0.9238795325 / C3),
|
||||
-F(0.7071067812 / C2), F(0.9238795325 / C3),
|
||||
F(0.7071067812 / C2), -F(0.3826834324 / C3),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_even[80 + 64] = {
|
||||
#define C0 2.7906148894
|
||||
#define C1 2.4270044280
|
||||
#define C2 2.8015616024
|
||||
#define C3 3.1710363741
|
||||
#define C4 2.5377944043
|
||||
#define C5 2.4270044280
|
||||
#define C6 2.8015616024
|
||||
#define C7 3.1710363741
|
||||
|
||||
#define F(x) F_PROTO8(x)
|
||||
F(0.00000000E+00 * C0), F(2.01182542E-03 * C0),
|
||||
F(1.56575398E-04 * C1), F(1.78371725E-03 * C1),
|
||||
F(3.43256425E-04 * C2), F(1.47640169E-03 * C2),
|
||||
F(5.54620202E-04 * C3), F(1.13992507E-03 * C3),
|
||||
-F(8.23919506E-04 * C4), F(0.00000000E+00 * C4),
|
||||
F(2.10371989E-03 * C5), F(3.49717454E-03 * C5),
|
||||
F(1.99454554E-03 * C6), F(1.64973098E-03 * C6),
|
||||
F(1.61656283E-03 * C7), F(1.78805361E-04 * C7),
|
||||
F(5.65949473E-03 * C0), F(1.29371806E-02 * C0),
|
||||
F(8.02941163E-03 * C1), F(1.53184106E-02 * C1),
|
||||
F(1.04584443E-02 * C2), F(1.62208471E-02 * C2),
|
||||
F(1.27472335E-02 * C3), F(1.59045603E-02 * C3),
|
||||
-F(1.46525263E-02 * C4), F(0.00000000E+00 * C4),
|
||||
F(8.85757540E-03 * C5), F(5.31873032E-02 * C5),
|
||||
F(2.92408442E-03 * C6), F(3.90751381E-02 * C6),
|
||||
-F(4.91578024E-03 * C7), F(2.61098752E-02 * C7),
|
||||
F(6.79989431E-02 * C0), F(1.46955068E-01 * C0),
|
||||
F(8.29847578E-02 * C1), F(1.45389847E-01 * C1),
|
||||
F(9.75753918E-02 * C2), F(1.40753505E-01 * C2),
|
||||
F(1.11196689E-01 * C3), F(1.33264415E-01 * C3),
|
||||
-F(1.23264548E-01 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
|
||||
F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
|
||||
F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
|
||||
-F(6.79989431E-02 * C0), F(1.29371806E-02 * C0),
|
||||
-F(5.31873032E-02 * C1), F(8.85757540E-03 * C1),
|
||||
-F(3.90751381E-02 * C2), F(2.92408442E-03 * C2),
|
||||
-F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
|
||||
F(1.46404076E-02 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
|
||||
F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
|
||||
F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
|
||||
-F(5.65949473E-03 * C0), F(2.01182542E-03 * C0),
|
||||
-F(3.49717454E-03 * C1), F(2.10371989E-03 * C1),
|
||||
-F(1.64973098E-03 * C2), F(1.99454554E-03 * C2),
|
||||
-F(1.78805361E-04 * C3), F(1.61656283E-03 * C3),
|
||||
-F(9.02154502E-04 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
|
||||
F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
|
||||
F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
|
||||
#undef F
|
||||
#define F(x) F_COS8(x)
|
||||
F(0.7071067812 / C0), F(0.8314696123 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.1950903220 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.9807852804 / C1),
|
||||
F(0.7071067812 / C0), -F(0.5555702330 / C1),
|
||||
F(0.7071067812 / C0), F(0.5555702330 / C1),
|
||||
-F(0.7071067812 / C0), F(0.9807852804 / C1),
|
||||
-F(0.7071067812 / C0), F(0.1950903220 / C1),
|
||||
F(0.7071067812 / C0), -F(0.8314696123 / C1),
|
||||
F(0.9238795325 / C2), F(0.9807852804 / C3),
|
||||
F(0.3826834324 / C2), F(0.8314696123 / C3),
|
||||
-F(0.3826834324 / C2), F(0.5555702330 / C3),
|
||||
-F(0.9238795325 / C2), F(0.1950903220 / C3),
|
||||
-F(0.9238795325 / C2), -F(0.1950903220 / C3),
|
||||
-F(0.3826834324 / C2), -F(0.5555702330 / C3),
|
||||
F(0.3826834324 / C2), -F(0.8314696123 / C3),
|
||||
F(0.9238795325 / C2), -F(0.9807852804 / C3),
|
||||
-F(1.0000000000 / C4), F(0.5555702330 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.9807852804 / C5),
|
||||
-F(1.0000000000 / C4), F(0.1950903220 / C5),
|
||||
-F(1.0000000000 / C4), F(0.8314696123 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.8314696123 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.1950903220 / C5),
|
||||
-F(1.0000000000 / C4), F(0.9807852804 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.5555702330 / C5),
|
||||
F(0.3826834324 / C6), F(0.1950903220 / C7),
|
||||
-F(0.9238795325 / C6), -F(0.5555702330 / C7),
|
||||
F(0.9238795325 / C6), F(0.8314696123 / C7),
|
||||
-F(0.3826834324 / C6), -F(0.9807852804 / C7),
|
||||
-F(0.3826834324 / C6), F(0.9807852804 / C7),
|
||||
F(0.9238795325 / C6), -F(0.8314696123 / C7),
|
||||
-F(0.9238795325 / C6), F(0.5555702330 / C7),
|
||||
F(0.3826834324 / C6), -F(0.1950903220 / C7),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_odd[80 + 64] = {
|
||||
#define C0 2.5377944043
|
||||
#define C1 2.4270044280
|
||||
#define C2 2.8015616024
|
||||
#define C3 3.1710363741
|
||||
#define C4 2.7906148894
|
||||
#define C5 2.4270044280
|
||||
#define C6 2.8015616024
|
||||
#define C7 3.1710363741
|
||||
|
||||
#define F(x) F_PROTO8(x)
|
||||
F(0.00000000E+00 * C0), -F(8.23919506E-04 * C0),
|
||||
F(1.56575398E-04 * C1), F(1.78371725E-03 * C1),
|
||||
F(3.43256425E-04 * C2), F(1.47640169E-03 * C2),
|
||||
F(5.54620202E-04 * C3), F(1.13992507E-03 * C3),
|
||||
F(2.01182542E-03 * C4), F(5.65949473E-03 * C4),
|
||||
F(2.10371989E-03 * C5), F(3.49717454E-03 * C5),
|
||||
F(1.99454554E-03 * C6), F(1.64973098E-03 * C6),
|
||||
F(1.61656283E-03 * C7), F(1.78805361E-04 * C7),
|
||||
F(0.00000000E+00 * C0), -F(1.46525263E-02 * C0),
|
||||
F(8.02941163E-03 * C1), F(1.53184106E-02 * C1),
|
||||
F(1.04584443E-02 * C2), F(1.62208471E-02 * C2),
|
||||
F(1.27472335E-02 * C3), F(1.59045603E-02 * C3),
|
||||
F(1.29371806E-02 * C4), F(6.79989431E-02 * C4),
|
||||
F(8.85757540E-03 * C5), F(5.31873032E-02 * C5),
|
||||
F(2.92408442E-03 * C6), F(3.90751381E-02 * C6),
|
||||
-F(4.91578024E-03 * C7), F(2.61098752E-02 * C7),
|
||||
F(0.00000000E+00 * C0), -F(1.23264548E-01 * C0),
|
||||
F(8.29847578E-02 * C1), F(1.45389847E-01 * C1),
|
||||
F(9.75753918E-02 * C2), F(1.40753505E-01 * C2),
|
||||
F(1.11196689E-01 * C3), F(1.33264415E-01 * C3),
|
||||
F(1.46955068E-01 * C4), -F(6.79989431E-02 * C4),
|
||||
F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
|
||||
F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
|
||||
F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
|
||||
F(0.00000000E+00 * C0), F(1.46404076E-02 * C0),
|
||||
-F(5.31873032E-02 * C1), F(8.85757540E-03 * C1),
|
||||
-F(3.90751381E-02 * C2), F(2.92408442E-03 * C2),
|
||||
-F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
|
||||
F(1.29371806E-02 * C4), -F(5.65949473E-03 * C4),
|
||||
F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
|
||||
F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
|
||||
F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
|
||||
F(0.00000000E+00 * C0), -F(9.02154502E-04 * C0),
|
||||
-F(3.49717454E-03 * C1), F(2.10371989E-03 * C1),
|
||||
-F(1.64973098E-03 * C2), F(1.99454554E-03 * C2),
|
||||
-F(1.78805361E-04 * C3), F(1.61656283E-03 * C3),
|
||||
F(2.01182542E-03 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
|
||||
F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
|
||||
F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
|
||||
#undef F
|
||||
#define F(x) F_COS8(x)
|
||||
-F(1.0000000000 / C0), F(0.8314696123 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.1950903220 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.9807852804 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.5555702330 / C1),
|
||||
-F(1.0000000000 / C0), F(0.5555702330 / C1),
|
||||
-F(1.0000000000 / C0), F(0.9807852804 / C1),
|
||||
-F(1.0000000000 / C0), F(0.1950903220 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.8314696123 / C1),
|
||||
F(0.9238795325 / C2), F(0.9807852804 / C3),
|
||||
F(0.3826834324 / C2), F(0.8314696123 / C3),
|
||||
-F(0.3826834324 / C2), F(0.5555702330 / C3),
|
||||
-F(0.9238795325 / C2), F(0.1950903220 / C3),
|
||||
-F(0.9238795325 / C2), -F(0.1950903220 / C3),
|
||||
-F(0.3826834324 / C2), -F(0.5555702330 / C3),
|
||||
F(0.3826834324 / C2), -F(0.8314696123 / C3),
|
||||
F(0.9238795325 / C2), -F(0.9807852804 / C3),
|
||||
F(0.7071067812 / C4), F(0.5555702330 / C5),
|
||||
-F(0.7071067812 / C4), -F(0.9807852804 / C5),
|
||||
-F(0.7071067812 / C4), F(0.1950903220 / C5),
|
||||
F(0.7071067812 / C4), F(0.8314696123 / C5),
|
||||
F(0.7071067812 / C4), -F(0.8314696123 / C5),
|
||||
-F(0.7071067812 / C4), -F(0.1950903220 / C5),
|
||||
-F(0.7071067812 / C4), F(0.9807852804 / C5),
|
||||
F(0.7071067812 / C4), -F(0.5555702330 / C5),
|
||||
F(0.3826834324 / C6), F(0.1950903220 / C7),
|
||||
-F(0.9238795325 / C6), -F(0.5555702330 / C7),
|
||||
F(0.9238795325 / C6), F(0.8314696123 / C7),
|
||||
-F(0.3826834324 / C6), -F(0.9807852804 / C7),
|
||||
-F(0.3826834324 / C6), F(0.9807852804 / C7),
|
||||
F(0.9238795325 / C6), -F(0.8314696123 / C7),
|
||||
-F(0.9238795325 / C6), F(0.5555702330 / C7),
|
||||
F(0.3826834324 / C6), -F(0.1950903220 / C7),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue