bluetooth: Remove built-in/static SBC codec

SBC shared library is now available at:

http://git.kernel.org/?p=bluetooth/sbc.git;a=summary
This commit is contained in:
Luiz Augusto von Dentz 2012-08-17 17:21:50 +03:00 committed by Tanu Kaskinen
parent 6031546f66
commit 8228db051e
17 changed files with 9 additions and 4784 deletions

View file

@ -965,6 +965,9 @@ AC_ARG_ENABLE([bluez],
AS_IF([test "x$enable_bluez" != "xno"], AS_IF([test "x$enable_bluez" != "xno"],
[PKG_CHECK_MODULES(BLUEZ, [ bluez >= 3.0 ], HAVE_BLUEZ=1, HAVE_BLUEZ=0)], [PKG_CHECK_MODULES(BLUEZ, [ bluez >= 3.0 ], HAVE_BLUEZ=1, HAVE_BLUEZ=0)],
HAVE_BLUEZ=0) HAVE_BLUEZ=0)
AS_IF([test "x$enable_bluez" != "xno"],
[PKG_CHECK_MODULES(SBC, [ sbc >= 1.0 ], HAVE_BLUEZ=1, HAVE_BLUEZ=0)],
HAVE_BLUEZ=0)
AS_IF([test "x$HAVE_DBUS" != "x1"], HAVE_BLUEZ=0) AS_IF([test "x$HAVE_DBUS" != "x1"], HAVE_BLUEZ=0)
AS_IF([test "x$enable_bluez" = "xyes" && test "x$HAVE_BLUEZ" = "x0"], AS_IF([test "x$enable_bluez" = "xyes" && test "x$HAVE_BLUEZ" = "x0"],

View file

@ -1250,7 +1250,6 @@ modlibexec_LTLIBRARIES += \
libbluetooth-util.la \ libbluetooth-util.la \
module-bluetooth-proximity.la \ module-bluetooth-proximity.la \
module-bluetooth-discover.la \ module-bluetooth-discover.la \
libbluetooth-sbc.la \
module-bluetooth-policy.la \ module-bluetooth-policy.la \
module-bluetooth-device.la module-bluetooth-device.la
@ -1938,19 +1937,6 @@ module_bluetooth_discover_la_LDFLAGS = $(MODULE_LDFLAGS)
module_bluetooth_discover_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) libbluetooth-util.la module_bluetooth_discover_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) libbluetooth-util.la
module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
libbluetooth_sbc_la_SOURCES = \
modules/bluetooth/sbc/sbc.c modules/bluetooth/sbc/sbc.h \
modules/bluetooth/sbc/sbc_primitives.c modules/bluetooth/sbc/sbc_primitives.h \
modules/bluetooth/sbc/sbc_primitives_armv6.h modules/bluetooth/sbc/sbc_primitives_armv6.c \
modules/bluetooth/sbc/sbc_primitives_iwmmxt.h modules/bluetooth/sbc/sbc_primitives_iwmmxt.c \
modules/bluetooth/sbc/sbc_primitives_mmx.c modules/bluetooth/sbc/sbc_primitives_mmx.h \
modules/bluetooth/sbc/sbc_primitives_neon.c modules/bluetooth/sbc/sbc_primitives_neon.h \
modules/bluetooth/sbc/sbc_math.h \
modules/bluetooth/sbc/sbc_tables.h
libbluetooth_sbc_la_LDFLAGS = -avoid-version
libbluetooth_sbc_la_LIBADD = $(MODULE_LIBADD)
libbluetooth_sbc_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/src/modules/bluetooth/sbc
BLUETOOTH_SBC_FILES = $(subst modules/bluetooth/,,$(libbluetooth_sbc_la_SOURCES))
libbluetooth_util_la_SOURCES = modules/bluetooth/bluetooth-util.c modules/bluetooth/bluetooth-util.h libbluetooth_util_la_SOURCES = modules/bluetooth/bluetooth-util.c modules/bluetooth/bluetooth-util.h
libbluetooth_util_la_LDFLAGS = -avoid-version libbluetooth_util_la_LDFLAGS = -avoid-version
@ -1959,8 +1945,8 @@ libbluetooth_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h
module_bluetooth_device_la_LDFLAGS = $(MODULE_LDFLAGS) module_bluetooth_device_la_LDFLAGS = $(MODULE_LDFLAGS)
module_bluetooth_device_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) libbluetooth-util.la libbluetooth-sbc.la module_bluetooth_device_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(SBC_LIBS) libbluetooth-util.la
module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -I$(top_srcdir)/src/modules/bluetooth/sbc module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) $(SBC_CFLAGS)
module_bluetooth_policy_la_SOURCES = modules/bluetooth/module-bluetooth-policy.c module_bluetooth_policy_la_SOURCES = modules/bluetooth/module-bluetooth-policy.c
module_bluetooth_policy_la_LDFLAGS = $(MODULE_LDFLAGS) module_bluetooth_policy_la_LDFLAGS = $(MODULE_LDFLAGS)
@ -2022,13 +2008,6 @@ massif: pulseaudio
update-ffmpeg: update-ffmpeg:
wget -O pulsecore/ffmpeg/resample2.c http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/resample2.c?view=co wget -O pulsecore/ffmpeg/resample2.c http://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec/resample2.c?view=co
# We get things twice here, because sometimes gitweb will us just give a "Generating..." otherwise.
update-sbc:
for i in $(BLUETOOTH_SBC_FILES) ; do \
wget -O /dev/null http://git.kernel.org/\?p=bluetooth/bluez.git\;a=blob_plain\;f=$$i ; \
wget -O $(top_srcdir)/src/modules/bluetooth/$$i http://git.kernel.org/\?p=bluetooth/bluez.git\;a=blob_plain\;f=$$i ; \
done
update-reserve: update-reserve:
for i in reserve.c reserve.h reserve-monitor.c reserve-monitor.h ; do \ for i in reserve.c reserve.h reserve-monitor.c reserve-monitor.h ; do \
wget -O $(top_srcdir)/src/modules/$$i http://git.0pointer.de/\?p=reserve.git\;a=blob_plain\;f=$$i\;hb=master ; \ wget -O $(top_srcdir)/src/modules/$$i http://git.0pointer.de/\?p=reserve.git\;a=blob_plain\;f=$$i\;hb=master ; \
@ -2048,7 +2027,7 @@ update-map-file:
echo "*;" ; \ echo "*;" ; \
echo "};" ) > $(srcdir)/map-file echo "};" ) > $(srcdir)/map-file
update-all: update-ffmpeg update-sbc update-map-file update-all: update-ffmpeg update-map-file
# Force installation order of libraries. libtool relinks on install time, in # Force installation order of libraries. libtool relinks on install time, in
# which case libpulsecommon has to be installed before others, but the padsp # which case libpulsecommon has to be installed before others, but the padsp
@ -2087,4 +2066,4 @@ coverage:
@echo "" @echo ""
endif endif
.PHONY: massif update-all update-ffmpeg update-sbc update-map-file coverage .PHONY: massif update-all update-ffmpeg update-map-file coverage

View file

@ -50,9 +50,10 @@
#include <pulsecore/namereg.h> #include <pulsecore/namereg.h>
#include <pulsecore/dbus-shared.h> #include <pulsecore/dbus-shared.h>
#include <sbc/sbc.h>
#include "module-bluetooth-device-symdef.h" #include "module-bluetooth-device-symdef.h"
#include "ipc.h" #include "ipc.h"
#include "sbc.h"
#include "a2dp-codecs.h" #include "a2dp-codecs.h"
#include "rtp.h" #include "rtp.h"
#include "bluetooth-util.h" #include "bluetooth-util.h"

File diff suppressed because it is too large Load diff

View file

@ -1,113 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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);
/* Decodes ONE input block into ONE output block */
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, ssize_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 */

View file

@ -1,61 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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-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))
#if defined(__arm__) && (!defined(__thumb__) || defined(__thumb2__))
#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

View file

@ -1,554 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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_iwmmxt.h"
#include "sbc_primitives_neon.h"
#include "sbc_primitives_armv6.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 - 40], &X[0][position],
36 * sizeof(int16_t));
if (nchannels > 1)
memcpy(&X[1][SBC_X_BUFFER_SIZE - 40], &X[1][position],
36 * sizeof(int16_t));
position = SBC_X_BUFFER_SIZE - 40;
}
#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);
}
}
}
static int sbc_calc_scalefactors_j(
int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, int subbands)
{
int blk, joint = 0;
int32_t tmp0, tmp1;
uint32_t x, y;
/* last subband does not use joint stereo */
int sb = subbands - 1;
x = 1 << SCALE_OUT_BITS;
y = 1 << SCALE_OUT_BITS;
for (blk = 0; blk < blocks; blk++) {
tmp0 = fabs(sb_sample_f[blk][0][sb]);
tmp1 = fabs(sb_sample_f[blk][1][sb]);
if (tmp0 != 0)
x |= tmp0 - 1;
if (tmp1 != 0)
y |= tmp1 - 1;
}
scale_factor[0][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(x);
scale_factor[1][sb] = (31 - SCALE_OUT_BITS) - sbc_clz(y);
/* the rest of subbands can use joint stereo */
while (--sb >= 0) {
int32_t sb_sample_j[16][2];
x = 1 << SCALE_OUT_BITS;
y = 1 << SCALE_OUT_BITS;
for (blk = 0; blk < blocks; blk++) {
tmp0 = sb_sample_f[blk][0][sb];
tmp1 = sb_sample_f[blk][1][sb];
sb_sample_j[blk][0] = ASR(tmp0, 1) + ASR(tmp1, 1);
sb_sample_j[blk][1] = ASR(tmp0, 1) - ASR(tmp1, 1);
tmp0 = fabs(tmp0);
tmp1 = fabs(tmp1);
if (tmp0 != 0)
x |= tmp0 - 1;
if (tmp1 != 0)
y |= tmp1 - 1;
}
scale_factor[0][sb] = (31 - SCALE_OUT_BITS) -
sbc_clz(x);
scale_factor[1][sb] = (31 - SCALE_OUT_BITS) -
sbc_clz(y);
x = 1 << SCALE_OUT_BITS;
y = 1 << SCALE_OUT_BITS;
for (blk = 0; blk < blocks; blk++) {
tmp0 = fabs(sb_sample_j[blk][0]);
tmp1 = fabs(sb_sample_j[blk][1]);
if (tmp0 != 0)
x |= tmp0 - 1;
if (tmp1 != 0)
y |= tmp1 - 1;
}
x = (31 - SCALE_OUT_BITS) - sbc_clz(x);
y = (31 - SCALE_OUT_BITS) - sbc_clz(y);
/* decide whether to use joint stereo for this subband */
if ((scale_factor[0][sb] + scale_factor[1][sb]) > x + y) {
joint |= 1 << (subbands - 1 - sb);
scale_factor[0][sb] = x;
scale_factor[1][sb] = y;
for (blk = 0; blk < blocks; blk++) {
sb_sample_f[blk][0][sb] = sb_sample_j[blk][0];
sb_sample_f[blk][1][sb] = sb_sample_j[blk][1];
}
}
}
/* bitmask with the information about subbands using joint stereo */
return joint;
}
/*
* 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->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j;
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_ARMV6_SUPPORT
sbc_init_primitives_armv6(state);
#endif
#ifdef SBC_BUILD_WITH_IWMMXT_SUPPORT
sbc_init_primitives_iwmmxt(state);
#endif
#ifdef SBC_BUILD_WITH_NEON_SUPPORT
sbc_init_primitives_neon(state);
#endif
}

View file

@ -1,80 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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 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);
/* Scale factors calculation with joint stereo support */
int (*sbc_calc_scalefactors_j)(int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, 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

View file

@ -1,299 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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_armv6.h"
/*
* ARMv6 optimizations. The instructions are scheduled for ARM11 pipeline.
*/
#ifdef SBC_BUILD_WITH_ARMV6_SUPPORT
static void __attribute__((naked)) sbc_analyze_four_armv6()
{
/* r0 = in, r1 = out, r2 = consts */
__asm__ volatile (
"push {r1, r4-r7, lr}\n"
"push {r8-r11}\n"
"ldrd r4, r5, [r0, #0]\n"
"ldrd r6, r7, [r2, #0]\n"
"ldrd r8, r9, [r0, #16]\n"
"ldrd r10, r11, [r2, #16]\n"
"mov r14, #0x8000\n"
"smlad r3, r4, r6, r14\n"
"smlad r12, r5, r7, r14\n"
"ldrd r4, r5, [r0, #32]\n"
"ldrd r6, r7, [r2, #32]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #48]\n"
"ldrd r10, r11, [r2, #48]\n"
"smlad r3, r4, r6, r3\n"
"smlad r12, r5, r7, r12\n"
"ldrd r4, r5, [r0, #64]\n"
"ldrd r6, r7, [r2, #64]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #8]\n"
"ldrd r10, r11, [r2, #8]\n"
"smlad r3, r4, r6, r3\n" /* t1[0] is done */
"smlad r12, r5, r7, r12\n" /* t1[1] is done */
"ldrd r4, r5, [r0, #24]\n"
"ldrd r6, r7, [r2, #24]\n"
"pkhtb r3, r12, r3, asr #16\n" /* combine t1[0] and t1[1] */
"smlad r12, r8, r10, r14\n"
"smlad r14, r9, r11, r14\n"
"ldrd r8, r9, [r0, #40]\n"
"ldrd r10, r11, [r2, #40]\n"
"smlad r12, r4, r6, r12\n"
"smlad r14, r5, r7, r14\n"
"ldrd r4, r5, [r0, #56]\n"
"ldrd r6, r7, [r2, #56]\n"
"smlad r12, r8, r10, r12\n"
"smlad r14, r9, r11, r14\n"
"ldrd r8, r9, [r0, #72]\n"
"ldrd r10, r11, [r2, #72]\n"
"smlad r12, r4, r6, r12\n"
"smlad r14, r5, r7, r14\n"
"ldrd r4, r5, [r2, #80]\n" /* start loading cos table */
"smlad r12, r8, r10, r12\n" /* t1[2] is done */
"smlad r14, r9, r11, r14\n" /* t1[3] is done */
"ldrd r6, r7, [r2, #88]\n"
"ldrd r8, r9, [r2, #96]\n"
"ldrd r10, r11, [r2, #104]\n" /* cos table fully loaded */
"pkhtb r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
"smuad r4, r3, r4\n"
"smuad r5, r3, r5\n"
"smlad r4, r12, r8, r4\n"
"smlad r5, r12, r9, r5\n"
"smuad r6, r3, r6\n"
"smuad r7, r3, r7\n"
"smlad r6, r12, r10, r6\n"
"smlad r7, r12, r11, r7\n"
"pop {r8-r11}\n"
"stmia r1, {r4, r5, r6, r7}\n"
"pop {r1, r4-r7, pc}\n"
);
}
#define sbc_analyze_four(in, out, consts) \
((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
sbc_analyze_four_armv6)((in), (out), (consts))
static void __attribute__((naked)) sbc_analyze_eight_armv6()
{
/* r0 = in, r1 = out, r2 = consts */
__asm__ volatile (
"push {r1, r4-r7, lr}\n"
"push {r8-r11}\n"
"ldrd r4, r5, [r0, #24]\n"
"ldrd r6, r7, [r2, #24]\n"
"ldrd r8, r9, [r0, #56]\n"
"ldrd r10, r11, [r2, #56]\n"
"mov r14, #0x8000\n"
"smlad r3, r4, r6, r14\n"
"smlad r12, r5, r7, r14\n"
"ldrd r4, r5, [r0, #88]\n"
"ldrd r6, r7, [r2, #88]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #120]\n"
"ldrd r10, r11, [r2, #120]\n"
"smlad r3, r4, r6, r3\n"
"smlad r12, r5, r7, r12\n"
"ldrd r4, r5, [r0, #152]\n"
"ldrd r6, r7, [r2, #152]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #16]\n"
"ldrd r10, r11, [r2, #16]\n"
"smlad r3, r4, r6, r3\n" /* t1[6] is done */
"smlad r12, r5, r7, r12\n" /* t1[7] is done */
"ldrd r4, r5, [r0, #48]\n"
"ldrd r6, r7, [r2, #48]\n"
"pkhtb r3, r12, r3, asr #16\n" /* combine t1[6] and t1[7] */
"str r3, [sp, #-4]!\n" /* save to stack */
"smlad r3, r8, r10, r14\n"
"smlad r12, r9, r11, r14\n"
"ldrd r8, r9, [r0, #80]\n"
"ldrd r10, r11, [r2, #80]\n"
"smlad r3, r4, r6, r3\n"
"smlad r12, r5, r7, r12\n"
"ldrd r4, r5, [r0, #112]\n"
"ldrd r6, r7, [r2, #112]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #144]\n"
"ldrd r10, r11, [r2, #144]\n"
"smlad r3, r4, r6, r3\n"
"smlad r12, r5, r7, r12\n"
"ldrd r4, r5, [r0, #0]\n"
"ldrd r6, r7, [r2, #0]\n"
"smlad r3, r8, r10, r3\n" /* t1[4] is done */
"smlad r12, r9, r11, r12\n" /* t1[5] is done */
"ldrd r8, r9, [r0, #32]\n"
"ldrd r10, r11, [r2, #32]\n"
"pkhtb r3, r12, r3, asr #16\n" /* combine t1[4] and t1[5] */
"str r3, [sp, #-4]!\n" /* save to stack */
"smlad r3, r4, r6, r14\n"
"smlad r12, r5, r7, r14\n"
"ldrd r4, r5, [r0, #64]\n"
"ldrd r6, r7, [r2, #64]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #96]\n"
"ldrd r10, r11, [r2, #96]\n"
"smlad r3, r4, r6, r3\n"
"smlad r12, r5, r7, r12\n"
"ldrd r4, r5, [r0, #128]\n"
"ldrd r6, r7, [r2, #128]\n"
"smlad r3, r8, r10, r3\n"
"smlad r12, r9, r11, r12\n"
"ldrd r8, r9, [r0, #8]\n"
"ldrd r10, r11, [r2, #8]\n"
"smlad r3, r4, r6, r3\n" /* t1[0] is done */
"smlad r12, r5, r7, r12\n" /* t1[1] is done */
"ldrd r4, r5, [r0, #40]\n"
"ldrd r6, r7, [r2, #40]\n"
"pkhtb r3, r12, r3, asr #16\n" /* combine t1[0] and t1[1] */
"smlad r12, r8, r10, r14\n"
"smlad r14, r9, r11, r14\n"
"ldrd r8, r9, [r0, #72]\n"
"ldrd r10, r11, [r2, #72]\n"
"smlad r12, r4, r6, r12\n"
"smlad r14, r5, r7, r14\n"
"ldrd r4, r5, [r0, #104]\n"
"ldrd r6, r7, [r2, #104]\n"
"smlad r12, r8, r10, r12\n"
"smlad r14, r9, r11, r14\n"
"ldrd r8, r9, [r0, #136]\n"
"ldrd r10, r11, [r2, #136]!\n"
"smlad r12, r4, r6, r12\n"
"smlad r14, r5, r7, r14\n"
"ldrd r4, r5, [r2, #(160 - 136 + 0)]\n"
"smlad r12, r8, r10, r12\n" /* t1[2] is done */
"smlad r14, r9, r11, r14\n" /* t1[3] is done */
"ldrd r6, r7, [r2, #(160 - 136 + 8)]\n"
"smuad r4, r3, r4\n"
"smuad r5, r3, r5\n"
"pkhtb r12, r14, r12, asr #16\n" /* combine t1[2] and t1[3] */
/* r3 = t2[0:1] */
/* r12 = t2[2:3] */
"pop {r0, r14}\n" /* t2[4:5], t2[6:7] */
"ldrd r8, r9, [r2, #(160 - 136 + 32)]\n"
"smuad r6, r3, r6\n"
"smuad r7, r3, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 40)]\n"
"smlad r4, r12, r8, r4\n"
"smlad r5, r12, r9, r5\n"
"ldrd r8, r9, [r2, #(160 - 136 + 64)]\n"
"smlad r6, r12, r10, r6\n"
"smlad r7, r12, r11, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 72)]\n"
"smlad r4, r0, r8, r4\n"
"smlad r5, r0, r9, r5\n"
"ldrd r8, r9, [r2, #(160 - 136 + 96)]\n"
"smlad r6, r0, r10, r6\n"
"smlad r7, r0, r11, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 104)]\n"
"smlad r4, r14, r8, r4\n"
"smlad r5, r14, r9, r5\n"
"ldrd r8, r9, [r2, #(160 - 136 + 16 + 0)]\n"
"smlad r6, r14, r10, r6\n"
"smlad r7, r14, r11, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 16 + 8)]\n"
"stmia r1!, {r4, r5}\n"
"smuad r4, r3, r8\n"
"smuad r5, r3, r9\n"
"ldrd r8, r9, [r2, #(160 - 136 + 16 + 32)]\n"
"stmia r1!, {r6, r7}\n"
"smuad r6, r3, r10\n"
"smuad r7, r3, r11\n"
"ldrd r10, r11, [r2, #(160 - 136 + 16 + 40)]\n"
"smlad r4, r12, r8, r4\n"
"smlad r5, r12, r9, r5\n"
"ldrd r8, r9, [r2, #(160 - 136 + 16 + 64)]\n"
"smlad r6, r12, r10, r6\n"
"smlad r7, r12, r11, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 16 + 72)]\n"
"smlad r4, r0, r8, r4\n"
"smlad r5, r0, r9, r5\n"
"ldrd r8, r9, [r2, #(160 - 136 + 16 + 96)]\n"
"smlad r6, r0, r10, r6\n"
"smlad r7, r0, r11, r7\n"
"ldrd r10, r11, [r2, #(160 - 136 + 16 + 104)]\n"
"smlad r4, r14, r8, r4\n"
"smlad r5, r14, r9, r5\n"
"smlad r6, r14, r10, r6\n"
"smlad r7, r14, r11, r7\n"
"pop {r8-r11}\n"
"stmia r1!, {r4, r5, r6, r7}\n"
"pop {r1, r4-r7, pc}\n"
);
}
#define sbc_analyze_eight(in, out, consts) \
((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
sbc_analyze_eight_armv6)((in), (out), (consts))
static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_four(x + 12, out, analysis_consts_fixed4_simd_odd);
out += out_stride;
sbc_analyze_four(x + 8, out, analysis_consts_fixed4_simd_even);
out += out_stride;
sbc_analyze_four(x + 4, out, analysis_consts_fixed4_simd_odd);
out += out_stride;
sbc_analyze_four(x + 0, out, analysis_consts_fixed4_simd_even);
}
static void sbc_analyze_4b_8s_armv6(int16_t *x, int32_t *out, int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight(x + 24, out, analysis_consts_fixed8_simd_odd);
out += out_stride;
sbc_analyze_eight(x + 16, out, analysis_consts_fixed8_simd_even);
out += out_stride;
sbc_analyze_eight(x + 8, out, analysis_consts_fixed8_simd_odd);
out += out_stride;
sbc_analyze_eight(x + 0, out, analysis_consts_fixed8_simd_even);
}
void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
{
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_armv6;
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_armv6;
state->implementation_info = "ARMv6 SIMD";
}
#endif

View file

@ -1,52 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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_ARMV6_H
#define __SBC_PRIMITIVES_ARMV6_H
#include "sbc_primitives.h"
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \
defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7__) || \
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
defined(__ARM_ARCH_7M__)
#define SBC_HAVE_ARMV6 1
#endif
#if !defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15) && \
defined(__GNUC__) && defined(SBC_HAVE_ARMV6) && \
defined(__ARM_EABI__) && !defined(__ARM_NEON__) && \
(!defined(__thumb__) || defined(__thumb2__))
#define SBC_BUILD_WITH_ARMV6_SUPPORT
void sbc_init_primitives_armv6(struct sbc_encoder_state *encoder_state);
#endif
#endif

View file

@ -1,304 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* Copyright (C) 2010 Keith Mok <ek9852@gmail.com>
* 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 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_iwmmxt.h"
/*
* IWMMXT optimizations
*/
#ifdef SBC_BUILD_WITH_IWMMXT_SUPPORT
static inline void sbc_analyze_four_iwmmxt(const int16_t *in, int32_t *out,
const FIXED_T *consts)
{
__asm__ volatile (
"wldrd wr0, [%0]\n"
"tbcstw wr4, %2\n"
"wldrd wr2, [%1]\n"
"wldrd wr1, [%0, #8]\n"
"wldrd wr3, [%1, #8]\n"
"wmadds wr0, wr2, wr0\n"
" wldrd wr6, [%0, #16]\n"
"wmadds wr1, wr3, wr1\n"
" wldrd wr7, [%0, #24]\n"
"waddwss wr0, wr0, wr4\n"
" wldrd wr8, [%1, #16]\n"
"waddwss wr1, wr1, wr4\n"
" wldrd wr9, [%1, #24]\n"
" wmadds wr6, wr8, wr6\n"
" wldrd wr2, [%0, #32]\n"
" wmadds wr7, wr9, wr7\n"
" wldrd wr3, [%0, #40]\n"
" waddwss wr0, wr6, wr0\n"
" wldrd wr4, [%1, #32]\n"
" waddwss wr1, wr7, wr1\n"
" wldrd wr5, [%1, #40]\n"
" wmadds wr2, wr4, wr2\n"
"wldrd wr6, [%0, #48]\n"
" wmadds wr3, wr5, wr3\n"
"wldrd wr7, [%0, #56]\n"
" waddwss wr0, wr2, wr0\n"
"wldrd wr8, [%1, #48]\n"
" waddwss wr1, wr3, wr1\n"
"wldrd wr9, [%1, #56]\n"
"wmadds wr6, wr8, wr6\n"
" wldrd wr2, [%0, #64]\n"
"wmadds wr7, wr9, wr7\n"
" wldrd wr3, [%0, #72]\n"
"waddwss wr0, wr6, wr0\n"
" wldrd wr4, [%1, #64]\n"
"waddwss wr1, wr7, wr1\n"
" wldrd wr5, [%1, #72]\n"
" wmadds wr2, wr4, wr2\n"
"tmcr wcgr0, %4\n"
" wmadds wr3, wr5, wr3\n"
" waddwss wr0, wr2, wr0\n"
" waddwss wr1, wr3, wr1\n"
"\n"
"wsrawg wr0, wr0, wcgr0\n"
" wldrd wr4, [%1, #80]\n"
"wsrawg wr1, wr1, wcgr0\n"
" wldrd wr5, [%1, #88]\n"
"wpackwss wr0, wr0, wr0\n"
" wldrd wr6, [%1, #96]\n"
"wpackwss wr1, wr1, wr1\n"
"wmadds wr2, wr5, wr0\n"
" wldrd wr7, [%1, #104]\n"
"wmadds wr0, wr4, wr0\n"
"\n"
" wmadds wr3, wr7, wr1\n"
" wmadds wr1, wr6, wr1\n"
" waddwss wr2, wr3, wr2\n"
" waddwss wr0, wr1, wr0\n"
"\n"
"wstrd wr0, [%3]\n"
"wstrd wr2, [%3, #8]\n"
:
: "r" (in), "r" (consts),
"r" (1 << (SBC_PROTO_FIXED4_SCALE - 1)), "r" (out),
"r" (SBC_PROTO_FIXED4_SCALE)
: "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
"wr8", "wr9", "wcgr0", "memory");
}
static inline void sbc_analyze_eight_iwmmxt(const int16_t *in, int32_t *out,
const FIXED_T *consts)
{
__asm__ volatile (
"wldrd wr0, [%0]\n"
"tbcstw wr15, %2\n"
"wldrd wr1, [%0, #8]\n"
"wldrd wr2, [%0, #16]\n"
"wldrd wr3, [%0, #24]\n"
"wldrd wr4, [%1]\n"
"wldrd wr5, [%1, #8]\n"
"wldrd wr6, [%1, #16]\n"
"wldrd wr7, [%1, #24]\n"
"wmadds wr0, wr0, wr4\n"
" wldrd wr8, [%1, #32]\n"
"wmadds wr1, wr1, wr5\n"
" wldrd wr9, [%1, #40]\n"
"wmadds wr2, wr2, wr6\n"
" wldrd wr10, [%1, #48]\n"
"wmadds wr3, wr3, wr7\n"
" wldrd wr11, [%1, #56]\n"
"waddwss wr0, wr0, wr15\n"
" wldrd wr4, [%0, #32]\n"
"waddwss wr1, wr1, wr15\n"
" wldrd wr5, [%0, #40]\n"
"waddwss wr2, wr2, wr15\n"
" wldrd wr6, [%0, #48]\n"
"waddwss wr3, wr3, wr15\n"
" wldrd wr7, [%0, #56]\n"
" wmadds wr4, wr4, wr8\n"
" wldrd wr12, [%0, #64]\n"
" wmadds wr5, wr5, wr9\n"
" wldrd wr13, [%0, #72]\n"
" wmadds wr6, wr6, wr10\n"
" wldrd wr14, [%0, #80]\n"
" wmadds wr7, wr7, wr11\n"
" wldrd wr15, [%0, #88]\n"
" waddwss wr0, wr4, wr0\n"
" wldrd wr8, [%1, #64]\n"
" waddwss wr1, wr5, wr1\n"
" wldrd wr9, [%1, #72]\n"
" waddwss wr2, wr6, wr2\n"
" wldrd wr10, [%1, #80]\n"
" waddwss wr3, wr7, wr3\n"
" wldrd wr11, [%1, #88]\n"
" wmadds wr12, wr12, wr8\n"
"wldrd wr4, [%0, #96]\n"
" wmadds wr13, wr13, wr9\n"
"wldrd wr5, [%0, #104]\n"
" wmadds wr14, wr14, wr10\n"
"wldrd wr6, [%0, #112]\n"
" wmadds wr15, wr15, wr11\n"
"wldrd wr7, [%0, #120]\n"
" waddwss wr0, wr12, wr0\n"
"wldrd wr8, [%1, #96]\n"
" waddwss wr1, wr13, wr1\n"
"wldrd wr9, [%1, #104]\n"
" waddwss wr2, wr14, wr2\n"
"wldrd wr10, [%1, #112]\n"
" waddwss wr3, wr15, wr3\n"
"wldrd wr11, [%1, #120]\n"
"wmadds wr4, wr4, wr8\n"
" wldrd wr12, [%0, #128]\n"
"wmadds wr5, wr5, wr9\n"
" wldrd wr13, [%0, #136]\n"
"wmadds wr6, wr6, wr10\n"
" wldrd wr14, [%0, #144]\n"
"wmadds wr7, wr7, wr11\n"
" wldrd wr15, [%0, #152]\n"
"waddwss wr0, wr4, wr0\n"
" wldrd wr8, [%1, #128]\n"
"waddwss wr1, wr5, wr1\n"
" wldrd wr9, [%1, #136]\n"
"waddwss wr2, wr6, wr2\n"
" wldrd wr10, [%1, #144]\n"
" waddwss wr3, wr7, wr3\n"
" wldrd wr11, [%1, #152]\n"
" wmadds wr12, wr12, wr8\n"
"tmcr wcgr0, %4\n"
" wmadds wr13, wr13, wr9\n"
" wmadds wr14, wr14, wr10\n"
" wmadds wr15, wr15, wr11\n"
" waddwss wr0, wr12, wr0\n"
" waddwss wr1, wr13, wr1\n"
" waddwss wr2, wr14, wr2\n"
" waddwss wr3, wr15, wr3\n"
"\n"
"wsrawg wr0, wr0, wcgr0\n"
"wsrawg wr1, wr1, wcgr0\n"
"wsrawg wr2, wr2, wcgr0\n"
"wsrawg wr3, wr3, wcgr0\n"
"\n"
"wpackwss wr0, wr0, wr0\n"
"wpackwss wr1, wr1, wr1\n"
" wldrd wr4, [%1, #160]\n"
"wpackwss wr2, wr2, wr2\n"
" wldrd wr5, [%1, #168]\n"
"wpackwss wr3, wr3, wr3\n"
" wldrd wr6, [%1, #192]\n"
" wmadds wr4, wr4, wr0\n"
" wldrd wr7, [%1, #200]\n"
" wmadds wr5, wr5, wr0\n"
" wldrd wr8, [%1, #224]\n"
" wmadds wr6, wr6, wr1\n"
" wldrd wr9, [%1, #232]\n"
" wmadds wr7, wr7, wr1\n"
" waddwss wr4, wr6, wr4\n"
" waddwss wr5, wr7, wr5\n"
" wmadds wr8, wr8, wr2\n"
"wldrd wr6, [%1, #256]\n"
" wmadds wr9, wr9, wr2\n"
"wldrd wr7, [%1, #264]\n"
"waddwss wr4, wr8, wr4\n"
" waddwss wr5, wr9, wr5\n"
"wmadds wr6, wr6, wr3\n"
"wmadds wr7, wr7, wr3\n"
"waddwss wr4, wr6, wr4\n"
"waddwss wr5, wr7, wr5\n"
"\n"
"wstrd wr4, [%3]\n"
"wstrd wr5, [%3, #8]\n"
"\n"
"wldrd wr6, [%1, #176]\n"
"wldrd wr5, [%1, #184]\n"
"wmadds wr5, wr5, wr0\n"
"wldrd wr8, [%1, #208]\n"
"wmadds wr0, wr6, wr0\n"
"wldrd wr9, [%1, #216]\n"
"wmadds wr9, wr9, wr1\n"
"wldrd wr6, [%1, #240]\n"
"wmadds wr1, wr8, wr1\n"
"wldrd wr7, [%1, #248]\n"
"waddwss wr0, wr1, wr0\n"
"waddwss wr5, wr9, wr5\n"
"wmadds wr7, wr7, wr2\n"
"wldrd wr8, [%1, #272]\n"
"wmadds wr2, wr6, wr2\n"
"wldrd wr9, [%1, #280]\n"
"waddwss wr0, wr2, wr0\n"
"waddwss wr5, wr7, wr5\n"
"wmadds wr9, wr9, wr3\n"
"wmadds wr3, wr8, wr3\n"
"waddwss wr0, wr3, wr0\n"
"waddwss wr5, wr9, wr5\n"
"\n"
"wstrd wr0, [%3, #16]\n"
"wstrd wr5, [%3, #24]\n"
:
: "r" (in), "r" (consts),
"r" (1 << (SBC_PROTO_FIXED8_SCALE - 1)), "r" (out),
"r" (SBC_PROTO_FIXED8_SCALE)
: "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
"wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15",
"wcgr0", "memory");
}
static inline void sbc_analyze_4b_4s_iwmmxt(int16_t *x, int32_t *out,
int out_stride)
{
/* Analyze blocks */
sbc_analyze_four_iwmmxt(x + 12, out, analysis_consts_fixed4_simd_odd);
out += out_stride;
sbc_analyze_four_iwmmxt(x + 8, out, analysis_consts_fixed4_simd_even);
out += out_stride;
sbc_analyze_four_iwmmxt(x + 4, out, analysis_consts_fixed4_simd_odd);
out += out_stride;
sbc_analyze_four_iwmmxt(x + 0, out, analysis_consts_fixed4_simd_even);
}
static inline void sbc_analyze_4b_8s_iwmmxt(int16_t *x, int32_t *out,
int out_stride)
{
/* Analyze blocks */
sbc_analyze_eight_iwmmxt(x + 24, out, analysis_consts_fixed8_simd_odd);
out += out_stride;
sbc_analyze_eight_iwmmxt(x + 16, out, analysis_consts_fixed8_simd_even);
out += out_stride;
sbc_analyze_eight_iwmmxt(x + 8, out, analysis_consts_fixed8_simd_odd);
out += out_stride;
sbc_analyze_eight_iwmmxt(x + 0, out, analysis_consts_fixed8_simd_even);
}
void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *state)
{
state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_iwmmxt;
state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_iwmmxt;
state->implementation_info = "IWMMXT";
}
#endif

View file

@ -1,42 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* Copyright (C) 2010 Keith Mok <ek9852@gmail.com>
* 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 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_IWMMXT_H
#define __SBC_PRIMITIVES_IWMMXT_H
#include "sbc_primitives.h"
#if defined(__GNUC__) && defined(__IWMMXT__) && \
!defined(SBC_HIGH_PRECISION) && (SCALE_OUT_BITS == 15)
#define SBC_BUILD_WITH_IWMMXT_SUPPORT
void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *encoder_state);
#endif
#endif

View file

@ -1,375 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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)
: "cc", "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)
: "cc", "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 void sbc_calc_scalefactors_mmx(
int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, int channels, int subbands)
{
static const SBC_ALIGNED int32_t consts[2] = {
1 << SCALE_OUT_BITS,
1 << SCALE_OUT_BITS,
};
int ch, sb;
intptr_t blk;
for (ch = 0; ch < channels; ch++) {
for (sb = 0; sb < subbands; sb += 2) {
blk = (blocks - 1) * (((char *) &sb_sample_f[1][0][0] -
(char *) &sb_sample_f[0][0][0]));
__asm__ volatile (
"movq (%4), %%mm0\n"
"1:\n"
"movq (%1, %0), %%mm1\n"
"pxor %%mm2, %%mm2\n"
"pcmpgtd %%mm2, %%mm1\n"
"paddd (%1, %0), %%mm1\n"
"pcmpgtd %%mm1, %%mm2\n"
"pxor %%mm2, %%mm1\n"
"por %%mm1, %%mm0\n"
"sub %2, %0\n"
"jns 1b\n"
"movd %%mm0, %k0\n"
"psrlq $32, %%mm0\n"
"bsrl %k0, %k0\n"
"subl %5, %k0\n"
"movl %k0, (%3)\n"
"movd %%mm0, %k0\n"
"bsrl %k0, %k0\n"
"subl %5, %k0\n"
"movl %k0, 4(%3)\n"
: "+r" (blk)
: "r" (&sb_sample_f[0][ch][sb]),
"i" ((char *) &sb_sample_f[1][0][0] -
(char *) &sb_sample_f[0][0][0]),
"r" (&scale_factor[ch][sb]),
"r" (&consts),
"i" (SCALE_OUT_BITS)
: "cc", "memory");
}
}
__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->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
state->implementation_info = "MMX";
}
}
#endif

View file

@ -1,41 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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

View file

@ -1,893 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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);
}
static void sbc_calc_scalefactors_neon(
int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, int channels, int subbands)
{
int ch, sb;
for (ch = 0; ch < channels; ch++) {
for (sb = 0; sb < subbands; sb += 4) {
int blk = blocks;
int32_t *in = &sb_sample_f[0][ch][sb];
__asm__ volatile (
"vmov.s32 q0, #0\n"
"vmov.s32 q1, %[c1]\n"
"vmov.s32 q14, #1\n"
"vmov.s32 q15, %[c2]\n"
"vadd.s32 q1, q1, q14\n"
"1:\n"
"vld1.32 {d16, d17}, [%[in], :128], %[inc]\n"
"vabs.s32 q8, q8\n"
"vld1.32 {d18, d19}, [%[in], :128], %[inc]\n"
"vabs.s32 q9, q9\n"
"vld1.32 {d20, d21}, [%[in], :128], %[inc]\n"
"vabs.s32 q10, q10\n"
"vld1.32 {d22, d23}, [%[in], :128], %[inc]\n"
"vabs.s32 q11, q11\n"
"vmax.s32 q0, q0, q8\n"
"vmax.s32 q1, q1, q9\n"
"vmax.s32 q0, q0, q10\n"
"vmax.s32 q1, q1, q11\n"
"subs %[blk], %[blk], #4\n"
"bgt 1b\n"
"vmax.s32 q0, q0, q1\n"
"vsub.s32 q0, q0, q14\n"
"vclz.s32 q0, q0\n"
"vsub.s32 q0, q15, q0\n"
"vst1.32 {d0, d1}, [%[out], :128]\n"
:
[blk] "+r" (blk),
[in] "+r" (in)
:
[inc] "r" ((char *) &sb_sample_f[1][0][0] -
(char *) &sb_sample_f[0][0][0]),
[out] "r" (&scale_factor[ch][sb]),
[c1] "i" (1 << SCALE_OUT_BITS),
[c2] "i" (31 - SCALE_OUT_BITS)
: "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23", "d24", "d25", "d26",
"d27", "d28", "d29", "d30", "d31", "cc", "memory");
}
}
}
int sbc_calc_scalefactors_j_neon(
int32_t sb_sample_f[16][2][8],
uint32_t scale_factor[2][8],
int blocks, int subbands)
{
static SBC_ALIGNED int32_t joint_bits_mask[8] = {
8, 4, 2, 1, 128, 64, 32, 16
};
int joint, i;
int32_t *in0, *in1;
int32_t *in = &sb_sample_f[0][0][0];
uint32_t *out0, *out1;
uint32_t *out = &scale_factor[0][0];
int32_t *consts = joint_bits_mask;
i = subbands;
__asm__ volatile (
/*
* constants: q13 = (31 - SCALE_OUT_BITS), q14 = 1
* input: q0 = ((1 << SCALE_OUT_BITS) + 1)
* %[in0] - samples for channel 0
* %[in1] - 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\n"
"vmov.s32 q1, q0\n"
"vmov.s32 q2, q0\n"
"vmov.s32 q3, q0\n"
"mov %[i], %[blocks]\n"
"1:\n"
"vld1.32 {d18, d19}, [%[in1], :128], %[inc]\n"
"vbic.s32 q11, q9, q14\n"
"vld1.32 {d16, d17}, [%[in0], :128], %[inc]\n"
"vhadd.s32 q10, q8, q11\n"
"vhsub.s32 q11, q8, q11\n"
"vabs.s32 q8, q8\n"
"vabs.s32 q9, q9\n"
"vabs.s32 q10, q10\n"
"vabs.s32 q11, q11\n"
"vmax.s32 q0, q0, q8\n"
"vmax.s32 q1, q1, q9\n"
"vmax.s32 q2, q2, q10\n"
"vmax.s32 q3, q3, q11\n"
"subs %[i], %[i], #1\n"
"bgt 1b\n"
"vsub.s32 q0, q0, q14\n"
"vsub.s32 q1, q1, q14\n"
"vsub.s32 q2, q2, q14\n"
"vsub.s32 q3, q3, q14\n"
"vclz.s32 q0, q0\n"
"vclz.s32 q1, q1\n"
"vclz.s32 q2, q2\n"
"vclz.s32 q3, q3\n"
"vsub.s32 q0, q13, q0\n"
"vsub.s32 q1, q13, q1\n"
"vsub.s32 q2, q13, q2\n"
"vsub.s32 q3, q13, q3\n"
".endm\n"
/*
* constants: q14 = 1
* input: q15 - joint stereo selection mask
* %[in0] - value set by calc_scalefactors macro
* %[in1] - value set by calc_scalefactors macro
*/
".macro update_joint_stereo_samples\n"
"sub %[out1], %[in1], %[inc]\n"
"sub %[out0], %[in0], %[inc]\n"
"sub %[in1], %[in1], %[inc], asl #1\n"
"sub %[in0], %[in0], %[inc], asl #1\n"
"vld1.32 {d18, d19}, [%[in1], :128]\n"
"vbic.s32 q11, q9, q14\n"
"vld1.32 {d16, d17}, [%[in0], :128]\n"
"vld1.32 {d2, d3}, [%[out1], :128]\n"
"vbic.s32 q3, q1, q14\n"
"vld1.32 {d0, d1}, [%[out0], :128]\n"
"vhsub.s32 q10, q8, q11\n"
"vhadd.s32 q11, q8, q11\n"
"vhsub.s32 q2, q0, q3\n"
"vhadd.s32 q3, q0, q3\n"
"vbif.s32 q10, q9, q15\n"
"vbif.s32 d22, d16, d30\n"
"sub %[inc], %[zero], %[inc], asl #1\n"
"sub %[i], %[blocks], #2\n"
"2:\n"
"vbif.s32 d23, d17, d31\n"
"vst1.32 {d20, d21}, [%[in1], :128], %[inc]\n"
"vbif.s32 d4, d2, d30\n"
"vld1.32 {d18, d19}, [%[in1], :128]\n"
"vbif.s32 d5, d3, d31\n"
"vst1.32 {d22, d23}, [%[in0], :128], %[inc]\n"
"vbif.s32 d6, d0, d30\n"
"vld1.32 {d16, d17}, [%[in0], :128]\n"
"vbif.s32 d7, d1, d31\n"
"vst1.32 {d4, d5}, [%[out1], :128], %[inc]\n"
"vbic.s32 q11, q9, q14\n"
"vld1.32 {d2, d3}, [%[out1], :128]\n"
"vst1.32 {d6, d7}, [%[out0], :128], %[inc]\n"
"vbic.s32 q3, q1, q14\n"
"vld1.32 {d0, d1}, [%[out0], :128]\n"
"vhsub.s32 q10, q8, q11\n"
"vhadd.s32 q11, q8, q11\n"
"vhsub.s32 q2, q0, q3\n"
"vhadd.s32 q3, q0, q3\n"
"vbif.s32 q10, q9, q15\n"
"vbif.s32 d22, d16, d30\n"
"subs %[i], %[i], #2\n"
"bgt 2b\n"
"sub %[inc], %[zero], %[inc], asr #1\n"
"vbif.s32 d23, d17, d31\n"
"vst1.32 {d20, d21}, [%[in1], :128]\n"
"vbif.s32 q2, q1, q15\n"
"vst1.32 {d22, d23}, [%[in0], :128]\n"
"vbif.s32 q3, q0, q15\n"
"vst1.32 {d4, d5}, [%[out1], :128]\n"
"vst1.32 {d6, d7}, [%[out0], :128]\n"
".endm\n"
"vmov.s32 q14, #1\n"
"vmov.s32 q13, %[c2]\n"
"cmp %[i], #4\n"
"bne 8f\n"
"4:\n" /* 4 subbands */
"add %[in0], %[in], #0\n"
"add %[in1], %[in], #32\n"
"add %[out0], %[out], #0\n"
"add %[out1], %[out], #32\n"
"vmov.s32 q0, %[c1]\n"
"vadd.s32 q0, q0, q14\n"
"calc_scalefactors\n"
/* check whether to use joint stereo for subbands 0, 1, 2 */
"vadd.s32 q15, q0, q1\n"
"vadd.s32 q9, q2, q3\n"
"vmov.s32 d31[1], %[zero]\n" /* last subband -> no joint */
"vld1.32 {d16, d17}, [%[consts], :128]!\n"
"vcgt.s32 q15, q15, q9\n"
/* calculate and save to memory 'joint' variable */
/* update and save scale factors to memory */
" vand.s32 q8, q8, q15\n"
"vbit.s32 q0, q2, q15\n"
" vpadd.s32 d16, d16, d17\n"
"vbit.s32 q1, q3, q15\n"
" vpadd.s32 d16, d16, d16\n"
"vst1.32 {d0, d1}, [%[out0], :128]\n"
"vst1.32 {d2, d3}, [%[out1], :128]\n"
" vst1.32 {d16[0]}, [%[joint]]\n"
"update_joint_stereo_samples\n"
"b 9f\n"
"8:\n" /* 8 subbands */
"add %[in0], %[in], #16\n\n"
"add %[in1], %[in], #48\n"
"add %[out0], %[out], #16\n\n"
"add %[out1], %[out], #48\n"
"vmov.s32 q0, %[c1]\n"
"vadd.s32 q0, q0, q14\n"
"calc_scalefactors\n"
/* check whether to use joint stereo for subbands 4, 5, 6 */
"vadd.s32 q15, q0, q1\n"
"vadd.s32 q9, q2, q3\n"
"vmov.s32 d31[1], %[zero]\n" /* last subband -> no joint */
"vld1.32 {d16, d17}, [%[consts], :128]!\n"
"vcgt.s32 q15, q15, q9\n"
/* calculate part of 'joint' variable and save it to d24 */
/* update and save scale factors to memory */
" vand.s32 q8, q8, q15\n"
"vbit.s32 q0, q2, q15\n"
" vpadd.s32 d16, d16, d17\n"
"vbit.s32 q1, q3, q15\n"
"vst1.32 {d0, d1}, [%[out0], :128]\n"
"vst1.32 {d2, d3}, [%[out1], :128]\n"
" vpadd.s32 d24, d16, d16\n"
"update_joint_stereo_samples\n"
"add %[in0], %[in], #0\n"
"add %[in1], %[in], #32\n"
"add %[out0], %[out], #0\n\n"
"add %[out1], %[out], #32\n"
"vmov.s32 q0, %[c1]\n"
"vadd.s32 q0, q0, q14\n"
"calc_scalefactors\n"
/* check whether to use joint stereo for subbands 0, 1, 2, 3 */
"vadd.s32 q15, q0, q1\n"
"vadd.s32 q9, q2, q3\n"
"vld1.32 {d16, d17}, [%[consts], :128]!\n"
"vcgt.s32 q15, q15, q9\n"
/* combine last part of 'joint' with d24 and save to memory */
/* update and save scale factors to memory */
" vand.s32 q8, q8, q15\n"
"vbit.s32 q0, q2, q15\n"
" vpadd.s32 d16, d16, d17\n"
"vbit.s32 q1, q3, q15\n"
" vpadd.s32 d16, d16, d16\n"
"vst1.32 {d0, d1}, [%[out0], :128]\n"
" vadd.s32 d16, d16, d24\n"
"vst1.32 {d2, d3}, [%[out1], :128]\n"
" vst1.32 {d16[0]}, [%[joint]]\n"
"update_joint_stereo_samples\n"
"9:\n"
".purgem calc_scalefactors\n"
".purgem update_joint_stereo_samples\n"
:
[i] "+&r" (i),
[in] "+&r" (in),
[in0] "=&r" (in0),
[in1] "=&r" (in1),
[out] "+&r" (out),
[out0] "=&r" (out0),
[out1] "=&r" (out1),
[consts] "+&r" (consts)
:
[inc] "r" ((char *) &sb_sample_f[1][0][0] -
(char *) &sb_sample_f[0][0][0]),
[blocks] "r" (blocks),
[joint] "r" (&joint),
[c1] "i" (1 << SCALE_OUT_BITS),
[c2] "i" (31 - SCALE_OUT_BITS),
[zero] "r" (0)
: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"d16", "d17", "d18", "d19", "d20", "d21", "d22",
"d23", "d24", "d25", "d26", "d27", "d28", "d29",
"d30", "d31", "cc", "memory");
return joint;
}
#define PERM_BE(a, b, c, d) { \
(a * 2) + 1, (a * 2) + 0, \
(b * 2) + 1, (b * 2) + 0, \
(c * 2) + 1, (c * 2) + 0, \
(d * 2) + 1, (d * 2) + 0 \
}
#define PERM_LE(a, b, c, d) { \
(a * 2) + 0, (a * 2) + 1, \
(b * 2) + 0, (b * 2) + 1, \
(c * 2) + 0, (c * 2) + 1, \
(d * 2) + 0, (d * 2) + 1 \
}
static SBC_ALWAYS_INLINE int sbc_enc_process_input_4s_neon_internal(
int position,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels, int big_endian)
{
static SBC_ALIGNED uint8_t perm_be[2][8] = {
PERM_BE(7, 3, 6, 4),
PERM_BE(0, 2, 1, 5)
};
static SBC_ALIGNED uint8_t perm_le[2][8] = {
PERM_LE(7, 3, 6, 4),
PERM_LE(0, 2, 1, 5)
};
/* handle X buffer wraparound */
if (position < nsamples) {
int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 40];
int16_t *src = &X[0][position];
__asm__ volatile (
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0}, [%[src], :64]!\n"
"vst1.16 {d0}, [%[dst], :64]!\n"
:
[dst] "+r" (dst),
[src] "+r" (src)
: : "memory", "d0", "d1", "d2", "d3");
if (nchannels > 1) {
dst = &X[1][SBC_X_BUFFER_SIZE - 40];
src = &X[1][position];
__asm__ volatile (
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0}, [%[src], :64]!\n"
"vst1.16 {d0}, [%[dst], :64]!\n"
:
[dst] "+r" (dst),
[src] "+r" (src)
: : "memory", "d0", "d1", "d2", "d3");
}
position = SBC_X_BUFFER_SIZE - 40;
}
if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
/* poor 'pcm' alignment */
int16_t *x = &X[0][position];
int16_t *y = &X[1][position];
__asm__ volatile (
"vld1.8 {d0, d1}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #16\n"
"sub %[y], %[y], #16\n"
"sub %[position], %[position], #8\n"
"vld1.8 {d4, d5}, [%[pcm]]!\n"
"vuzp.16 d4, d5\n"
"vld1.8 {d20, d21}, [%[pcm]]!\n"
"vuzp.16 d20, d21\n"
"vswp d5, d20\n"
"vtbl.8 d16, {d4, d5}, d0\n"
"vtbl.8 d17, {d4, d5}, d1\n"
"vtbl.8 d18, {d20, d21}, d0\n"
"vtbl.8 d19, {d20, d21}, d1\n"
"vst1.16 {d16, d17}, [%[x], :128]\n"
"vst1.16 {d18, d19}, [%[y], :128]\n"
"subs %[nsamples], %[nsamples], #8\n"
"bgt 1b\n"
:
[x] "+r" (x),
[y] "+r" (y),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23");
} else if (nchannels > 1) {
/* proper 'pcm' alignment */
int16_t *x = &X[0][position];
int16_t *y = &X[1][position];
__asm__ volatile (
"vld1.8 {d0, d1}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #16\n"
"sub %[y], %[y], #16\n"
"sub %[position], %[position], #8\n"
"vld2.16 {d4, d5}, [%[pcm]]!\n"
"vld2.16 {d20, d21}, [%[pcm]]!\n"
"vswp d5, d20\n"
"vtbl.8 d16, {d4, d5}, d0\n"
"vtbl.8 d17, {d4, d5}, d1\n"
"vtbl.8 d18, {d20, d21}, d0\n"
"vtbl.8 d19, {d20, d21}, d1\n"
"vst1.16 {d16, d17}, [%[x], :128]\n"
"vst1.16 {d18, d19}, [%[y], :128]\n"
"subs %[nsamples], %[nsamples], #8\n"
"bgt 1b\n"
:
[x] "+r" (x),
[y] "+r" (y),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23");
} else {
int16_t *x = &X[0][position];
__asm__ volatile (
"vld1.8 {d0, d1}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #16\n"
"sub %[position], %[position], #8\n"
"vld1.8 {d4, d5}, [%[pcm]]!\n"
"vtbl.8 d16, {d4, d5}, d0\n"
"vtbl.8 d17, {d4, d5}, d1\n"
"vst1.16 {d16, d17}, [%[x], :128]\n"
"subs %[nsamples], %[nsamples], #8\n"
"bgt 1b\n"
:
[x] "+r" (x),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19");
}
return position;
}
static SBC_ALWAYS_INLINE int sbc_enc_process_input_8s_neon_internal(
int position,
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels, int big_endian)
{
static SBC_ALIGNED uint8_t perm_be[4][8] = {
PERM_BE(15, 7, 14, 8),
PERM_BE(13, 9, 12, 10),
PERM_BE(11, 3, 6, 0),
PERM_BE(5, 1, 4, 2)
};
static SBC_ALIGNED uint8_t perm_le[4][8] = {
PERM_LE(15, 7, 14, 8),
PERM_LE(13, 9, 12, 10),
PERM_LE(11, 3, 6, 0),
PERM_LE(5, 1, 4, 2)
};
/* handle X buffer wraparound */
if (position < nsamples) {
int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 72];
int16_t *src = &X[0][position];
__asm__ volatile (
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1}, [%[src], :128]!\n"
"vst1.16 {d0, d1}, [%[dst], :128]!\n"
:
[dst] "+r" (dst),
[src] "+r" (src)
: : "memory", "d0", "d1", "d2", "d3");
if (nchannels > 1) {
dst = &X[1][SBC_X_BUFFER_SIZE - 72];
src = &X[1][position];
__asm__ volatile (
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
"vld1.16 {d0, d1}, [%[src], :128]!\n"
"vst1.16 {d0, d1}, [%[dst], :128]!\n"
:
[dst] "+r" (dst),
[src] "+r" (src)
: : "memory", "d0", "d1", "d2", "d3");
}
position = SBC_X_BUFFER_SIZE - 72;
}
if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
/* poor 'pcm' alignment */
int16_t *x = &X[0][position];
int16_t *y = &X[1][position];
__asm__ volatile (
"vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #32\n"
"sub %[y], %[y], #32\n"
"sub %[position], %[position], #16\n"
"vld1.8 {d4, d5, d6, d7}, [%[pcm]]!\n"
"vuzp.16 q2, q3\n"
"vld1.8 {d20, d21, d22, d23}, [%[pcm]]!\n"
"vuzp.16 q10, q11\n"
"vswp q3, q10\n"
"vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
"vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
"vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
"vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
"vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
"vtbl.8 d16, {d20, d21, d22, d23}, d0\n"
"vtbl.8 d17, {d20, d21, d22, d23}, d1\n"
"vtbl.8 d18, {d20, d21, d22, d23}, d2\n"
"vtbl.8 d19, {d20, d21, d22, d23}, d3\n"
"vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
"subs %[nsamples], %[nsamples], #16\n"
"bgt 1b\n"
:
[x] "+r" (x),
[y] "+r" (y),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23");
} else if (nchannels > 1) {
/* proper 'pcm' alignment */
int16_t *x = &X[0][position];
int16_t *y = &X[1][position];
__asm__ volatile (
"vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #32\n"
"sub %[y], %[y], #32\n"
"sub %[position], %[position], #16\n"
"vld2.16 {d4, d5, d6, d7}, [%[pcm]]!\n"
"vld2.16 {d20, d21, d22, d23}, [%[pcm]]!\n"
"vswp q3, q10\n"
"vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
"vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
"vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
"vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
"vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
"vtbl.8 d16, {d20, d21, d22, d23}, d0\n"
"vtbl.8 d17, {d20, d21, d22, d23}, d1\n"
"vtbl.8 d18, {d20, d21, d22, d23}, d2\n"
"vtbl.8 d19, {d20, d21, d22, d23}, d3\n"
"vst1.16 {d16, d17, d18, d19}, [%[y], :128]\n"
"subs %[nsamples], %[nsamples], #16\n"
"bgt 1b\n"
:
[x] "+r" (x),
[y] "+r" (y),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23");
} else {
int16_t *x = &X[0][position];
__asm__ volatile (
"vld1.8 {d0, d1, d2, d3}, [%[perm], :128]\n"
"1:\n"
"sub %[x], %[x], #32\n"
"sub %[position], %[position], #16\n"
"vld1.8 {d4, d5, d6, d7}, [%[pcm]]!\n"
"vtbl.8 d16, {d4, d5, d6, d7}, d0\n"
"vtbl.8 d17, {d4, d5, d6, d7}, d1\n"
"vtbl.8 d18, {d4, d5, d6, d7}, d2\n"
"vtbl.8 d19, {d4, d5, d6, d7}, d3\n"
"vst1.16 {d16, d17, d18, d19}, [%[x], :128]\n"
"subs %[nsamples], %[nsamples], #16\n"
"bgt 1b\n"
:
[x] "+r" (x),
[pcm] "+r" (pcm),
[nsamples] "+r" (nsamples),
[position] "+r" (position)
:
[perm] "r" (big_endian ? perm_be : perm_le)
: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
"d5", "d6", "d7", "d16", "d17", "d18", "d19");
}
return position;
}
#undef PERM_BE
#undef PERM_LE
static int sbc_enc_process_input_4s_be_neon(int position, const uint8_t *pcm,
int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
return sbc_enc_process_input_4s_neon_internal(
position, pcm, X, nsamples, nchannels, 1);
}
static int sbc_enc_process_input_4s_le_neon(int position, const uint8_t *pcm,
int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
return sbc_enc_process_input_4s_neon_internal(
position, pcm, X, nsamples, nchannels, 0);
}
static int sbc_enc_process_input_8s_be_neon(int position, const uint8_t *pcm,
int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
return sbc_enc_process_input_8s_neon_internal(
position, pcm, X, nsamples, nchannels, 1);
}
static int sbc_enc_process_input_8s_le_neon(int position, const uint8_t *pcm,
int16_t X[2][SBC_X_BUFFER_SIZE],
int nsamples, int nchannels)
{
return sbc_enc_process_input_8s_neon_internal(
position, pcm, X, nsamples, nchannels, 0);
}
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->sbc_calc_scalefactors = sbc_calc_scalefactors_neon;
state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j_neon;
state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le_neon;
state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be_neon;
state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le_neon;
state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be_neon;
state->implementation_info = "NEON";
}
#endif

View file

@ -1,41 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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

View file

@ -1,662 +0,0 @@
/*
*
* Bluetooth low-complexity, subband codec (SBC) library
*
* 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 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 }
};
/* extra bits of precision for the synthesis filter input data */
#define SBCDEC_FIXED_EXTRA_BITS 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 + 1 + SBCDEC_FIXED_EXTRA_BITS)
#define SN8(val) ASR(val, SCALE_NPROTO8_TBL + 1 + SBCDEC_FIXED_EXTRA_BITS)
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
};