From 61f64a95d1e0e8cf4f79b799394444d4bc03b5f7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 31 Jan 2007 08:52:52 +0000 Subject: Add skeleton for embedding SBC library --- sbc/Makefile.am | 6 ++++++ sbc/sbc.c | 28 ++++++++++++++++++++++++++++ sbc/sbc.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 sbc/Makefile.am create mode 100644 sbc/sbc.c create mode 100644 sbc/sbc.h (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am new file mode 100644 index 00000000..9478d120 --- /dev/null +++ b/sbc/Makefile.am @@ -0,0 +1,6 @@ + +noinst_LTLIBRARIES = libsbc.la + +libsbc_la_SOURCES = sbc.h sbc.c + +MAINTAINERCLEANFILES = Makefile.in diff --git a/sbc/sbc.c b/sbc/sbc.c new file mode 100644 index 00000000..de479c4f --- /dev/null +++ b/sbc/sbc.c @@ -0,0 +1,28 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * 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 + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sbc.h" diff --git a/sbc/sbc.h b/sbc/sbc.h new file mode 100644 index 00000000..ae31af4c --- /dev/null +++ b/sbc/sbc.h @@ -0,0 +1,35 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * 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 + +#ifdef __cplusplus +} +#endif + +#endif /* __SBC_H */ -- cgit From 5430ca31bc276a9d07c932383910ef600ef08c87 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 21 Feb 2007 14:15:52 +0000 Subject: Add SBC utilities --- sbc/Makefile.am | 6 ++ sbc/sbcdec.c | 33 +++++++ sbc/sbcenc.c | 33 +++++++ sbc/sbcinfo.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 sbc/sbcdec.c create mode 100644 sbc/sbcenc.c create mode 100644 sbc/sbcinfo.c (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index 9478d120..d17a77d0 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -3,4 +3,10 @@ noinst_LTLIBRARIES = libsbc.la libsbc_la_SOURCES = sbc.h sbc.c +noinst_PROGRAMS = sbcinfo sbcdec sbcenc + +sbcdec_LDADD = libsbc.la + +sbcenc_LDADD = libsbc.la + MAINTAINERCLEANFILES = Makefile.in diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c new file mode 100644 index 00000000..208cdfd8 --- /dev/null +++ b/sbc/sbcdec.c @@ -0,0 +1,33 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sbc.h" + +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c new file mode 100644 index 00000000..208cdfd8 --- /dev/null +++ b/sbc/sbcenc.c @@ -0,0 +1,33 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sbc.h" + +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/sbc/sbcinfo.c b/sbc/sbcinfo.c new file mode 100644 index 00000000..e34f5618 --- /dev/null +++ b/sbc/sbcinfo.c @@ -0,0 +1,300 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sbc_frame_hdr { + uint8_t syncword:8; /* Sync word */ + uint8_t subbands:1; /* Subbands */ + uint8_t allocation_method:1; /* Allocation method */ + uint8_t channel_mode:2; /* Channel mode */ + uint8_t blocks:2; /* Blocks */ + uint8_t sampling_frequency:2; /* Sampling frequency */ + uint8_t bitpool:8; /* Bitpool */ + uint8_t crc_check:8; /* CRC check */ +} __attribute__ ((packed)); + +static int calc_frame_len(struct sbc_frame_hdr *hdr) +{ + int tmp, nrof_subbands, nrof_blocks; + + nrof_subbands = (hdr->subbands + 1) * 4; + nrof_blocks = (hdr->blocks + 1) * 4; + + switch (hdr->channel_mode) { + case 0x00: + nrof_subbands /= 2; + tmp = nrof_blocks * hdr->bitpool; + break; + case 0x01: + tmp = nrof_blocks * hdr->bitpool * 2; + break; + case 0x02: + tmp = nrof_blocks * hdr->bitpool; + break; + case 0x03: + tmp = nrof_blocks * hdr->bitpool + nrof_subbands; + break; + default: + return 0; + } + + return (nrof_subbands + ((tmp + 7) / 8)); +} + +static double calc_bit_rate(struct sbc_frame_hdr *hdr) +{ + int nrof_subbands, nrof_blocks; + double f; + + nrof_subbands = (hdr->subbands + 1) * 4; + nrof_blocks = (hdr->blocks + 1) * 4; + + switch (hdr->sampling_frequency) { + case 0: + f = 16; + break; + case 1: + f = 32; + break; + case 2: + f = 44.1; + break; + case 3: + f = 48; + break; + default: + return 0; + } + + return ((8 * (calc_frame_len(hdr) + 4) * f) / (nrof_subbands * nrof_blocks)); +} + +static char *freq2str(uint8_t freq) +{ + switch (freq) { + case 0: + return "16 kHz"; + case 1: + return "32 kHz"; + case 2: + return "44.1 kHz"; + case 3: + return "48 kHz"; + default: + return "Unknown"; + } +} + +static char *mode2str(uint8_t mode) +{ + switch (mode) { + case 0: + return "Mono"; + case 1: + return "Dual Channel"; + case 2: + return "Stereo"; + case 3: + return "Joint Stereo"; + default: + return "Unknown"; + } +} + +static ssize_t __read(int fd, void *buf, size_t count) +{ + ssize_t len, pos = 0; + + while (count > 0) { + len = read(fd, buf + pos, count); + if (len <= 0) + return len; + + count -= len; + pos += len; + } + + return pos; +} + +#define SIZE 32 + +static int analyze_file(char *filename) +{ + struct sbc_frame_hdr hdr; + unsigned char buf[64]; + double rate; + int bitpool[SIZE], frame_len[SIZE]; + int subbands, blocks, freq, mode, method; + int n, p1, p2, fd, len, size, count, num; + + if (strcmp(filename, "-")) { + printf("Filename\t\t%s\n", basename(filename)); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("Can't open file"); + return -1; + } + } else + fd = fileno(stdin); + + len = __read(fd, &hdr, sizeof(hdr)); + if (len != sizeof(hdr) || hdr.syncword != 0x9c) { + fprintf(stderr, "Not a SBC audio file\n"); + return -1; + } + + subbands = (hdr.subbands + 1) * 4; + blocks = (hdr.blocks + 1) * 4; + freq = hdr.sampling_frequency; + mode = hdr.channel_mode; + method = hdr.allocation_method; + + count = calc_frame_len(&hdr); + + bitpool[0] = hdr.bitpool; + frame_len[0] = count + 4; + + for (n = 1; n < SIZE; n++) { + bitpool[n] = 0; + frame_len[n] = 0; + } + + if (lseek(fd, 0, SEEK_SET) < 0) { + num = 1; + rate = calc_bit_rate(&hdr); + while (count) { + size = count > sizeof(buf) ? sizeof(buf) : count; + len = __read(fd, buf, size); + if (len < 0) + break; + count -= len; + } + } else { + num = 0; + rate = 0; + } + + while (1) { + len = __read(fd, &hdr, sizeof(hdr)); + if (len < 0) { + fprintf(stderr, "Unable to read frame header (error %d)\n", errno); + break; + } + + if (len == 0) + break; + + if (len < sizeof(hdr) || hdr.syncword != 0x9c) { + fprintf(stderr, "Corrupted SBC stream (len %d syncword 0x%02x)\n", + len, hdr.syncword); + break; + } + + count = calc_frame_len(&hdr); + len = count + 4; + + p1 = -1; + p2 = -1; + for (n = 0; n < SIZE; n++) { + if (p1 < 0 && (bitpool[n] == 0 || bitpool[n] == hdr.bitpool)) + p1 = n; + if (p2 < 0 && (frame_len[n] == 0 || frame_len[n] == len)) + p2 = n; + } + if (p1 >= 0) + bitpool[p1] = hdr.bitpool; + if (p2 >= 0) + frame_len[p2] = len; + + while (count) { + size = count > sizeof(buf) ? sizeof(buf) : count; + + len = __read(fd, buf, size); + if (len != size) { + fprintf(stderr, "Unable to read frame data (error %d)\n", errno); + break; + } + + count -= len; + } + + rate += calc_bit_rate(&hdr); + num++; + } + + printf("Subbands\t\t%d\n", subbands); + printf("Block length\t\t%d\n", blocks); + printf("Sampling frequency\t%s\n", freq2str(freq)); + printf("Channel mode\t\t%s\n", mode2str(hdr.channel_mode)); + printf("Allocation method\t%s\n", method ? "SNR" : "Loudness"); + printf("Bitpool\t\t\t%d", bitpool[0]); + for (n = 1; n < SIZE; n++) + if (bitpool[n] > 0) + printf(", %d", bitpool[n]); + printf("\n"); + printf("Number of frames\t%d\n", num); + printf("Frame length\t\t%d", frame_len[0]); + for (n = 1; n < SIZE; n++) + if (frame_len[n] > 0) + printf(", %d", frame_len[n]); + printf(" Bytes\n"); + if (num > 0) + printf("Bit rate\t\t%.3f kbps\n", rate / num); + + if (fd > fileno(stderr)) + close(fd); + + printf("\n"); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + + if (argc < 2) { + fprintf(stderr, "Usage: sbcinfo \n"); + exit(1); + } + + for (i = 0; i < argc - 1; i++) + if (analyze_file(argv[i + 1]) < 0) + exit(1); + + return 0; +} -- cgit From ec31984c45d9b3dd272ec3ecb9a5270a00494699 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 21 Feb 2007 14:23:25 +0000 Subject: Add SBC helper includes --- sbc/Makefile.am | 2 +- sbc/sbc.c | 5 ++ sbc/sbc_math.h | 65 ++++++++++++++++++++++ sbc/sbc_tables.h | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 sbc/sbc_math.h create mode 100644 sbc/sbc_tables.h (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index d17a77d0..4492dfa7 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,7 +1,7 @@ noinst_LTLIBRARIES = libsbc.la -libsbc_la_SOURCES = sbc.h sbc.c +libsbc_la_SOURCES = sbc.h sbc.c sbc_math.h sbc_tables.h noinst_PROGRAMS = sbcinfo sbcdec sbcenc diff --git a/sbc/sbc.c b/sbc/sbc.c index de479c4f..f14f59a9 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -25,4 +25,9 @@ #include #endif +#include + +#include "sbc_math.h" +#include "sbc_tables.h" + #include "sbc.h" diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h new file mode 100644 index 00000000..c427bee3 --- /dev/null +++ b/sbc/sbc_math.h @@ -0,0 +1,65 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * 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_PROTO4_TBL 15 +#define SCALE_ANA4_TBL 16 +#define SCALE_PROTO8_TBL 15 +#define SCALE_ANA8_TBL 16 +#define SCALE_SPROTO4_TBL 16 +#define SCALE_SPROTO8_TBL 16 +#define SCALE_NPROTO4_TBL 10 +#define SCALE_NPROTO8_TBL 12 +#define SCALE_SAMPLES 14 +#define SCALE4_STAGE1_BITS 16 +#define SCALE4_STAGE2_BITS 18 +#define SCALE4_STAGED1_BITS 15 +#define SCALE4_STAGED2_BITS 15 +#define SCALE8_STAGE1_BITS 16 +#define SCALE8_STAGE2_BITS 18 +#define SCALE8_STAGED1_BITS 15 +#define SCALE8_STAGED2_BITS 15 + +typedef int32_t sbc_fixed_t; + +#define SCALE4_STAGE1(src) ASR(src, SCALE4_STAGE1_BITS) +#define SCALE4_STAGE2(src) ASR(src, SCALE4_STAGE2_BITS) +#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS) +#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS) +#define SCALE8_STAGE1(src) ASR(src, SCALE8_STAGE1_BITS) +#define SCALE8_STAGE2(src) ASR(src, SCALE8_STAGE2_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 ADD(dst, src) { dst += src; } +#define SUB(dst, src) { dst -= src; } +#define MUL(dst, a, b) { dst = (sbc_fixed_t) a * b; } +#define MULA(dst, a, b) { dst += (sbc_fixed_t) a * b; } +#define DIV2(dst, src) { dst = ASR(src, 1); } diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h new file mode 100644 index 00000000..a170704d --- /dev/null +++ b/sbc/sbc_tables.h @@ -0,0 +1,165 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset4[4][4] = { + { -1, 0, 0, 0 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 }, + { -2, 0, 0, 1 } +}; + +/* A2DP specification: Appendix B, page 69 */ +static const int sbc_offset8[4][8] = { + { -2, 0, 0, 0, 0, 0, 0, 1 }, + { -3, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 }, + { -4, 0, 0, 0, 0, 0, 1, 2 } +}; + +#define SP4(val) ASR(val, SCALE_PROTO4_TBL) +#define SA4(val) ASR(val, SCALE_ANA4_TBL) +#define SP8(val) ASR(val, SCALE_PROTO8_TBL) +#define SA8(val) ASR(val, SCALE_ANA8_TBL) +#define SS4(val) ASR(val, SCALE_SPROTO4_TBL) +#define SS8(val) ASR(val, SCALE_SPROTO8_TBL) +#define SN4(val) ASR(val, SCALE_NPROTO4_TBL) +#define SN8(val) ASR(val, SCALE_NPROTO8_TBL) + +static const int32_t _sbc_proto_4[20] = { + SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548), + SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7), + SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737), + SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578), + SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000) +}; + +static const int32_t _anamatrix4[4] = { + SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0) +}; + +static const int32_t _sbc_proto_8[40] = { + SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930), + SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28), + SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc), + SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c), + SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0), + SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00), + SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950), + SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f), + SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20), + SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48) +}; + +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 _anamatrix8[8] = { + SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40), + SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000) +}; + +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) } +}; -- cgit From ad868bd4137e86fbf141175f411898796287ff2a Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 17 Mar 2007 13:37:31 +0000 Subject: update the sbc encoder from the working fixed-point code in the sbc project I also tagged the sbc project with "copied-to-bluez-utils" at the same time. We will do sbc work under bluez and sync it with the old sbc project if necessary. --- sbc/sbc.c | 1398 +++++++++++++++++++++++++++++++++++++++++++++++++++++- sbc/sbc.h | 30 +- sbc/sbc_math.h | 44 +- sbc/sbc_tables.h | 4 +- 4 files changed, 1453 insertions(+), 23 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index f14f59a9..1f16d70a 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -2,7 +2,9 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley * * * This library is free software; you can redistribute it and/or @@ -21,13 +23,1407 @@ * */ +/* todo items: + + use a log2 table for byte integer scale factors calculation (sum log2 results for high and low bytes) + fill bitpool by 16 bits instead of one at a time in bits allocation/bitpool generation + port to the dsp + don't consume more bytes than passed into the encoder + +*/ + #ifdef HAVE_CONFIG_H #include #endif +#include +#include #include +#include +#include +#include +#include + #include "sbc_math.h" #include "sbc_tables.h" #include "sbc.h" + +#define SBC_SYNCWORD 0x9C + +/* sampling frequency */ +#define SBC_FS_16 0x00 +#define SBC_FS_32 0x01 +#define SBC_FS_44 0x02 +#define SBC_FS_48 0x03 + +/* nrof_blocks */ +#define SBC_NB_4 0x00 +#define SBC_NB_8 0x01 +#define SBC_NB_12 0x02 +#define SBC_NB_16 0x03 + +/* channel mode */ +#define SBC_CM_MONO 0x00 +#define SBC_CM_DUAL_CHANNEL 0x01 +#define SBC_CM_STEREO 0x02 +#define SBC_CM_JOINT_STEREO 0x03 + +/* allocation mode */ +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 + +/* subbands */ +#define SBC_SB_4 0x00 +#define SBC_SB_8 0x01 + +/* This structure contains an unpacked SBC frame. + Yes, there is probably quite some unused space herein */ +struct sbc_frame { + uint16_t sampling_frequency; /* in kHz */ + uint8_t blocks; + enum { + MONO = SBC_CM_MONO, + DUAL_CHANNEL = SBC_CM_DUAL_CHANNEL, + STEREO = SBC_CM_STEREO, + JOINT_STEREO = SBC_CM_JOINT_STEREO + } channel_mode; + uint8_t channels; + enum { + LOUDNESS = SBC_AM_LOUDNESS, + SNR = SBC_AM_SNR + } allocation_method; + uint8_t subbands; + uint8_t bitpool; + uint8_t join; /* bit number x set means joint stereo has been used in subband x */ + uint8_t scale_factor[2][8]; /* only the lower 4 bits of every element are to be used */ + uint16_t audio_sample[16][2][8]; /* raw integer subband samples in the frame */ + + int32_t sb_sample_f[16][2][8]; + int32_t sb_sample[16][2][8]; /* modified subband samples */ + int16_t pcm_sample[2][16*8]; /* original pcm audio samples */ +}; + +struct sbc_decoder_state { + int subbands; + int32_t V[2][170]; + int offset[2][16]; +}; + +struct sbc_encoder_state { + int subbands; + int32_t X[2][80]; +}; + +/* + * Calculates the CRC-8 of the first len bits in data + */ +static const uint8_t crc_table[256] = { + 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, + 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, + 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, + 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, + 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, + 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, + 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, + 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, + 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, + 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, + 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, + 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, + 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, + 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F, + 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, + 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, + 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, + 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, + 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, + 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, + 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, + 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, + 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, + 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, + 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, + 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, + 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, + 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, + 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, + 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4 +}; + +static uint8_t sbc_crc8(const uint8_t * data, size_t len) +{ + uint8_t crc = 0x0f; + size_t i; + uint8_t octet; + + for (i = 0; i < len / 8; i++) + crc = crc_table[crc ^ data[i]]; + + octet = data[i]; + for (i = 0; i < len % 8; i++) { + char bit = ((octet ^ crc) & 0x80) >> 7; + + crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0); + + octet = octet << 1; + } + + return crc; +} + +/* + * Code straight from the spec to calculate the bits array + * Takes a pointer to the frame in question, a pointer to the bits array and the sampling frequency (as 2 bit integer) + */ +static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], uint8_t sf) +{ + if (frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + for (ch = 0; ch < frame->channels; ch++) { + if (frame->allocation_method == SNR) { + for (sb = 0; sb < frame->subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + } + } else { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) { + bitneed[ch][sb] = -5; + } else { + if (frame->subbands == 4) { + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + } else { + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + } + if (loudness > 0) { + bitneed[ch][sb] = loudness / 2; + } else { + bitneed[ch][sb] = loudness; + } + } + } + } + + max_bitneed = 0; + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (sb = 0; sb < frame->subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) { + slicecount++; + } else if (bitneed[ch][sb] == bitslice + 1) { + slicecount += 2; + } + } + } while (bitcount + slicecount < frame->bitpool); + + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) { + bits[ch][sb] = 0; + } else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + + sb = 0; + while (bitcount < frame->bitpool && sb < frame->subbands) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + sb++; + } + + sb = 0; + while (bitcount < frame->bitpool && sb < frame->subbands) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + sb++; + } + + } + + } else if (frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) { + int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; + int ch, sb; + + if (frame->allocation_method == SNR) { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + bitneed[ch][sb] = frame->scale_factor[ch][sb]; + } + } + } else { + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->scale_factor[ch][sb] == 0) { + bitneed[ch][sb] = -5; + } else { + if (frame->subbands == 4) { + loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; + } else { + loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; + } + if (loudness > 0) { + bitneed[ch][sb] = loudness / 2; + } else { + bitneed[ch][sb] = loudness; + } + } + } + } + } + + max_bitneed = 0; + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + + bitcount = 0; + slicecount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) { + slicecount++; + } else if (bitneed[ch][sb] == bitslice + 1) { + slicecount += 2; + } + } + } + } while (bitcount + slicecount < frame->bitpool); + if (bitcount + slicecount == frame->bitpool) { + bitcount += slicecount; + bitslice--; + } + + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) { + bits[ch][sb] = 0; + } else { + bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (bits[ch][sb] > 16) + bits[ch][sb] = 16; + } + } + } + + ch = 0; + sb = 0; + while ((bitcount < frame->bitpool) && (sb < frame->subbands)) { + if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { + bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { + bits[ch][sb] = 2; + bitcount += 2; + } + if (ch == 1) { + ch = 0; + sb++; + } else { + ch = 1; + } + } + + ch = 0; + sb = 0; + while ((bitcount < frame->bitpool) && (sb < frame->subbands)) { + if (bits[ch][sb] < 16) { + bits[ch][sb]++; + bitcount++; + } + if (ch == 1) { + ch = 0; + sb++; + } else { + ch = 1; + } + } + + } + +} + +/* + * Unpacks a SBC frame at the beginning of the stream in data, + * which has at most len bytes into frame. + * Returns the length in bytes of the packed frame, or a negative + * value on error. The error codes are: + * + * -1 Data stream too short + * -2 Sync byte incorrect + * -3 CRC8 incorrect + * -4 Bitpool value out of bounds + */ +static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_t len) +{ + int consumed; + /* Will copy the parts of the header that are relevant to crc calculation here */ + uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int crc_pos = 0; + int32_t temp; + + uint8_t sf; /* sampling_frequency, temporarily needed as array index */ + + int ch, sb, blk, bit; /* channel, subband, block and bit standard counters */ + int bits[2][8]; /* bits distribution */ + int levels[2][8]; /* levels derived from that */ + + if (len < 4) + return -1; + + if (data[0] != SBC_SYNCWORD) + return -2; + + sf = (data[1] >> 6) & 0x03; + switch (sf) { + case SBC_FS_16: + frame->sampling_frequency = 16000; + break; + case SBC_FS_32: + frame->sampling_frequency = 32000; + break; + case SBC_FS_44: + frame->sampling_frequency = 44100; + break; + case SBC_FS_48: + frame->sampling_frequency = 48000; + break; + } + + switch ((data[1] >> 4) & 0x03) { + case SBC_NB_4: + frame->blocks = 4; + break; + case SBC_NB_8: + frame->blocks = 8; + break; + case SBC_NB_12: + frame->blocks = 12; + break; + case SBC_NB_16: + frame->blocks = 16; + break; + } + + frame->channel_mode = (data[1] >> 2) & 0x03; + switch (frame->channel_mode) { + case MONO: + frame->channels = 1; + break; + case DUAL_CHANNEL: /* fall-through */ + case STEREO: + case JOINT_STEREO: + frame->channels = 2; + break; + } + + frame->allocation_method = (data[1] >> 1) & 0x01; + + frame->subbands = (data[1] & 0x01) ? 8 : 4; + + frame->bitpool = data[2]; + + if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) + && frame->bitpool > 16 * frame->subbands) + || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) + && frame->bitpool > 32 * frame->subbands)) + return -4; + + /* data[3] is crc, we're checking it later */ + + consumed = 32; + + crc_header[0] = data[1]; + crc_header[1] = data[2]; + crc_pos = 16; + + if (frame->channel_mode == JOINT_STEREO) { + if (len * 8 < consumed + frame->subbands) + return -1; + + frame->join = 0x00; + for (sb = 0; sb < frame->subbands - 1; sb++) { + frame->join |= ((data[4] >> (7 - sb)) & 0x01) << sb; + } + if (frame->subbands == 4) { + crc_header[crc_pos / 8] = data[4] & 0xf0; + } else { + crc_header[crc_pos / 8] = data[4]; + } + + consumed += frame->subbands; + crc_pos += frame->subbands; + } + + if (len * 8 < consumed + (4 * frame->subbands * frame->channels)) + return -1; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + /* FIXME assert(consumed % 4 == 0); */ + frame->scale_factor[ch][sb] = (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F; + crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7)); + + consumed += 4; + crc_pos += 4; + } + } + + if (data[3] != sbc_crc8(crc_header, crc_pos)) + return -3; + + sbc_calculate_bits(frame, bits, sf); + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + frame->audio_sample[blk][ch][sb] = 0; + if (bits[ch][sb] == 0) + continue; + + for (bit = 0; bit < bits[ch][sb]; bit++) { + int b; /* A bit */ + if (consumed > len * 8) + return -1; + + b = (data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01; + frame->audio_sample[blk][ch][sb] |= b << (bits[ch][sb] - bit - 1); + + consumed++; + } + } + } + } + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + levels[ch][sb] = (1 << bits[ch][sb]) - 1; + } + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (levels[ch][sb] > 0) { + frame->sb_sample[blk][ch][sb] = + (((frame->audio_sample[blk][ch][sb] << 16) | 0x8000) / levels[ch][sb]) - 0x8000; + + frame->sb_sample[blk][ch][sb] >>= 3; + frame->sb_sample[blk][ch][sb] = (frame->sb_sample[blk][ch][sb] << (frame->scale_factor[ch][sb] + 1)); // Q13 + + } else { + frame->sb_sample[blk][ch][sb] = 0; + } + } + } + } + + if (frame->channel_mode == JOINT_STEREO) { + for (blk = 0; blk < frame->blocks; blk++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (frame->join & (0x01 << sb)) { + temp = frame->sb_sample[blk][0][sb] + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][1][sb] = frame->sb_sample[blk][0][sb] - frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][0][sb] = temp; + } + } + } + } + + if ((consumed & 0x7) != 0) + consumed += 8 - (consumed & 0x7); + + + return consumed >> 3; +} + +static void sbc_decoder_init(struct sbc_decoder_state *state, const struct sbc_frame *frame) +{ + int i, ch; + + memset(state->V, 0, sizeof(state->V)); + state->subbands = frame->subbands; + + for (ch = 0; ch < 2; ch++) + for (i = 0; i < frame->subbands * 2; i++) + state->offset[ch][i] = (10 * i + 10); +} + +static inline void sbc_synthesize_four(struct sbc_decoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i, j, k, idx; + sbc_extended_t res; + + for(i = 0; i < 8; i++) { + /* Shifting */ + state->offset[ch][i]--; + if(state->offset[ch][i] < 0) { + state->offset[ch][i] = 79; + for(j = 0; j < 9; j++) { + state->V[ch][j+80] = state->V[ch][j]; + } + } + } + + + for(i = 0; i < 8; i++) { + /* Distribute the new matrix value to the shifted position */ + SBC_FIXED_0(res); + for (j = 0; j < 4; j++) { + MULA(res, synmatrix4[i][j], frame->sb_sample[blk][ch][j]); + } + state->V[ch][state->offset[ch][i]] = SCALE4_STAGED1(res); + } + + /* Compute the samples */ + for(idx = 0, i = 0; i < 4; i++) { + k = (i + 4) & 0xf; + SBC_FIXED_0(res); + for(j = 0; j < 10; idx++) { + MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]); + MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_4_40m1[idx]); + } + /* Store in output */ + frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(res); // Q0 + } +} + +static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i, j, k, idx; + sbc_extended_t res; + + for(i = 0; i < 16; i++) { + /* Shifting */ + state->offset[ch][i]--; + if(state->offset[ch][i] < 0) { + state->offset[ch][i] = 159; + for(j = 0; j < 9; j++) { + state->V[ch][j+160] = state->V[ch][j]; + } + } + } + + for(i = 0; i < 16; i++) { + /* Distribute the new matrix value to the shifted position */ + SBC_FIXED_0(res); + for (j = 0; j < 8; j++) { + MULA(res, synmatrix8[i][j], frame->sb_sample[blk][ch][j]); // Q28 = Q15 * Q13 + } + state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); // Q10 + } + + + /* Compute the samples */ + for(idx = 0, i = 0; i < 8; i++) { + k = (i + 8) & 0xf; + SBC_FIXED_0(res); + for(j = 0; j < 10; idx++) { + MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_8_80m0[idx]); + MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_8_80m1[idx]); + } + /* Store in output */ + frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2(res); // Q0 + + } +} + +static int sbc_synthesize_audio(struct sbc_decoder_state *state, struct sbc_frame *frame) +{ + int ch, blk; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) { + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_four(state, frame, ch, blk); + } + return frame->blocks * 4; + + case 8: + for (ch = 0; ch < frame->channels; ch++) { + for (blk = 0; blk < frame->blocks; blk++) + sbc_synthesize_eight(state, frame, ch, blk); + } + return frame->blocks * 8; + + default: + return -EIO; + } +} + +static void sbc_encoder_init(struct sbc_encoder_state *state, const struct sbc_frame *frame) +{ + memset(&state->X, 0, sizeof(state->X)); + state->subbands = frame->subbands; +} + +static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) +{ + + sbc_extended_t res; + sbc_extended_t t[8]; + + out[0] = out[1] = out[2] = out[3] = 0; + + MUL(res, _sbc_proto_4[0], (in[8] - in[32])); // Q18 + MULA(res, _sbc_proto_4[1], (in[16] - in[24])); + t[0] = SCALE4_STAGE1(res); // Q8 + + MUL(res, _sbc_proto_4[2], in[1]); + MULA(res, _sbc_proto_4[3], in[9]); + MULA(res, _sbc_proto_4[4], in[17]); + MULA(res, _sbc_proto_4[5], in[25]); + MULA(res, _sbc_proto_4[6], in[33]); + t[1] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[7], in[2]); + MULA(res, _sbc_proto_4[8], in[10]); + MULA(res, _sbc_proto_4[9], in[18]); + MULA(res, _sbc_proto_4[10], in[26]); + MULA(res, _sbc_proto_4[11], in[34]); + t[2] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[12], in[3]); + MULA(res, _sbc_proto_4[13], in[11]); + MULA(res, _sbc_proto_4[14], in[19]); + MULA(res, _sbc_proto_4[15], in[27]); + MULA(res, _sbc_proto_4[16], in[35]); + t[3] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[17], in[4]); + MULA(res, _sbc_proto_4[18], (in[12] + in[28])); + MULA(res, _sbc_proto_4[19], in[20]); + MULA(res, _sbc_proto_4[17], in[36]); + t[4] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[16], in[5]); + MULA(res, _sbc_proto_4[15], in[13]); + MULA(res, _sbc_proto_4[14], in[21]); + MULA(res, _sbc_proto_4[13], in[29]); + MULA(res, _sbc_proto_4[12], in[37]); + t[5] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[11], in[6]); + MULA(res, _sbc_proto_4[10], in[14]); + MULA(res, _sbc_proto_4[9], in[22]); + MULA(res, _sbc_proto_4[8], in[30]); + MULA(res, _sbc_proto_4[7], in[38]); + t[6] = SCALE4_STAGE1(res); + + MUL(res, _sbc_proto_4[6], in[7]); + MULA(res, _sbc_proto_4[5], in[15]); + MULA(res, _sbc_proto_4[4], in[23]); + MULA(res, _sbc_proto_4[3], in[31]); + MULA(res, _sbc_proto_4[2], in[39]); + t[7] = SCALE4_STAGE1(res); + + MUL(res, _anamatrix4[0], t[0]); + MULA(res, _anamatrix4[1], t[1]); + MULA(res, _anamatrix4[2], t[2]); + MULA(res, _anamatrix4[1], t[3]); + MULA(res, _anamatrix4[0], t[4]); + MULA(res, _anamatrix4[3], t[5]); + MULA(res, -_anamatrix4[3], t[7]); + out[0] = SCALE4_STAGE2(res); // Q0 + + MUL(res, -_anamatrix4[0], t[0]); + MULA(res, _anamatrix4[3], t[1]); + MULA(res, _anamatrix4[2], t[2]); + MULA(res, _anamatrix4[3], t[3]); + MULA(res, -_anamatrix4[0], t[4]); + MULA(res, -_anamatrix4[1], t[5]); + MULA(res, _anamatrix4[1], t[7]); + out[1] = SCALE4_STAGE2(res); + + + MUL(res, -_anamatrix4[0], t[0]); + MULA(res, -_anamatrix4[3], t[1]); + MULA(res, _anamatrix4[2], t[2]); + MULA(res, -_anamatrix4[3], t[3]); + MULA(res, -_anamatrix4[0], t[4]); + MULA(res, _anamatrix4[1], t[5]); + MULA(res, -_anamatrix4[1], t[7]); + out[2] = SCALE4_STAGE2(res); + + MUL(res, _anamatrix4[0], t[0]); + MULA(res, -_anamatrix4[1], t[1]); + MULA(res, _anamatrix4[2], t[2]); + MULA(res, -_anamatrix4[1], t[3]); + MULA(res, _anamatrix4[0], t[4]); + MULA(res, -_anamatrix4[3], t[5]); + MULA(res, _anamatrix4[3], t[7]); + out[3] = SCALE4_STAGE2(res); +} +static inline void sbc_analyze_four(struct sbc_encoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i; + /* Input 4 New Audio Samples */ + for (i = 39; i >= 4; i--) + state->X[ch][i] = state->X[ch][i - 4]; + for (i = 3; i >= 0; i--) + state->X[ch][i] = frame->pcm_sample[ch][blk * 4 + (3 - i)]; + _sbc_analyze_four(state->X[ch], frame->sb_sample_f[blk][ch]); +} + +static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) +{ + sbc_extended_t res; + sbc_extended_t t[8]; + + out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0; + + MUL(res, _sbc_proto_8[0], (in[16] - in[64])); // Q18 = Q18 * Q0 + MULA(res, _sbc_proto_8[1], (in[32] - in[48])); + MULA(res, _sbc_proto_8[2], in[4]); + MULA(res, _sbc_proto_8[3], in[20]); + MULA(res, _sbc_proto_8[4], in[36]); + MULA(res, _sbc_proto_8[5], in[52]); + t[0] = SCALE8_STAGE1(res); // Q10 + + MUL(res, _sbc_proto_8[6], in[2]); + MULA(res, _sbc_proto_8[7], in[18]); + MULA(res, _sbc_proto_8[8], in[34]); + MULA(res, _sbc_proto_8[9], in[50]); + MULA(res, _sbc_proto_8[10], in[66]); + t[1] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[11], in[1]); + MULA(res, _sbc_proto_8[12], in[17]); + MULA(res, _sbc_proto_8[13], in[33]); + MULA(res, _sbc_proto_8[14], in[49]); + MULA(res, _sbc_proto_8[15], in[65]); + MULA(res, _sbc_proto_8[16], in[3]); + MULA(res, _sbc_proto_8[17], in[19]); + MULA(res, _sbc_proto_8[18], in[35]); + MULA(res, _sbc_proto_8[19], in[51]); + MULA(res, _sbc_proto_8[20], in[67]); + t[2] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[21], in[5]); + MULA(res, _sbc_proto_8[22], in[21]); + MULA(res, _sbc_proto_8[23], in[37]); + MULA(res, _sbc_proto_8[24], in[53]); + MULA(res, _sbc_proto_8[25], in[69]); + MULA(res, -_sbc_proto_8[15], in[15]); + MULA(res, -_sbc_proto_8[14], in[31]); + MULA(res, -_sbc_proto_8[13], in[47]); + MULA(res, -_sbc_proto_8[12], in[63]); + MULA(res, -_sbc_proto_8[11], in[79]); + t[3] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[26], in[6]); + MULA(res, _sbc_proto_8[27], in[22]); + MULA(res, _sbc_proto_8[28], in[38]); + MULA(res, _sbc_proto_8[29], in[54]); + MULA(res, _sbc_proto_8[30], in[70]); + MULA(res, -_sbc_proto_8[10], in[14]); + MULA(res, -_sbc_proto_8[9], in[30]); + MULA(res, -_sbc_proto_8[8], in[46]); + MULA(res, -_sbc_proto_8[7], in[62]); + MULA(res, -_sbc_proto_8[6], in[78]); + t[4] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[31], in[7]); + MULA(res, _sbc_proto_8[32], in[23]); + MULA(res, _sbc_proto_8[33], in[39]); + MULA(res, _sbc_proto_8[34], in[55]); + MULA(res, _sbc_proto_8[35], in[71]); + MULA(res, -_sbc_proto_8[20], in[13]); + MULA(res, -_sbc_proto_8[19], in[29]); + MULA(res, -_sbc_proto_8[18], in[45]); + MULA(res, -_sbc_proto_8[17], in[61]); + MULA(res, -_sbc_proto_8[16], in[77]); + t[5] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[36], (in[8] + in[72])); + MULA(res, _sbc_proto_8[37], in[24]); + MULA(res, _sbc_proto_8[38], in[40]); + MULA(res, _sbc_proto_8[37], in[56]); + MULA(res, -_sbc_proto_8[39], in[12]); + MULA(res, -_sbc_proto_8[5], in[28]); + MULA(res, -_sbc_proto_8[4], in[44]); + MULA(res, -_sbc_proto_8[3], in[60]); + MULA(res, -_sbc_proto_8[2], in[76]); + t[6] = SCALE8_STAGE1(res); + + MUL(res, _sbc_proto_8[35], in[9]); + MULA(res, _sbc_proto_8[34], in[25]); + MULA(res, _sbc_proto_8[33], in[41]); + MULA(res, _sbc_proto_8[32], in[57]); + MULA(res, _sbc_proto_8[31], in[73]); + MULA(res, -_sbc_proto_8[25], in[11]); + MULA(res, -_sbc_proto_8[24], in[27]); + MULA(res, -_sbc_proto_8[23], in[43]); + MULA(res, -_sbc_proto_8[22], in[59]); + MULA(res, -_sbc_proto_8[21], in[75]); + t[7] = SCALE8_STAGE1(res); + + MUL(res, _anamatrix8[0], t[0]); // = Q14 * Q10 + MULA(res, _anamatrix8[7], t[1]); + MULA(res, _anamatrix8[2], t[2]); + MULA(res, _anamatrix8[3], t[3]); + MULA(res, _anamatrix8[6], t[4]); + MULA(res, _anamatrix8[4], t[5]); + MULA(res, _anamatrix8[1], t[6]); + MULA(res, _anamatrix8[5], t[7]); + out[0] = SCALE8_STAGE2(res); // Q0 + + MUL(res, _anamatrix8[1], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, _anamatrix8[3], t[2]); + MULA(res, -_anamatrix8[5], t[3]); + MULA(res, -_anamatrix8[6], t[4]); + MULA(res, -_anamatrix8[2], t[5]); + MULA(res, -_anamatrix8[0], t[6]); + MULA(res, -_anamatrix8[4], t[7]); + out[1] = SCALE8_STAGE2(res); + + MUL(res, -_anamatrix8[1], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, _anamatrix8[4], t[2]); + MULA(res, -_anamatrix8[2], t[3]); + MULA(res, -_anamatrix8[6], t[4]); + MULA(res, _anamatrix8[5], t[5]); + MULA(res, _anamatrix8[0], t[6]); + MULA(res, _anamatrix8[3], t[7]); + out[2] = SCALE8_STAGE2(res); + + MUL(res, -_anamatrix8[0], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, _anamatrix8[5], t[2]); + MULA(res, -_anamatrix8[4], t[3]); + MULA(res, _anamatrix8[6], t[4]); + MULA(res, _anamatrix8[3], t[5]); + MULA(res, -_anamatrix8[1], t[6]); + MULA(res, -_anamatrix8[2], t[7]); + out[3] = SCALE8_STAGE2(res); + + MUL(res, -_anamatrix8[0], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, -_anamatrix8[5], t[2]); + MULA(res, _anamatrix8[4], t[3]); + MULA(res, _anamatrix8[6], t[4]); + MULA(res, -_anamatrix8[3], t[5]); + MULA(res, -_anamatrix8[1], t[6]); + MULA(res, _anamatrix8[2], t[7]); + out[4] = SCALE8_STAGE2(res); + + MUL(res, -_anamatrix8[1], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, -_anamatrix8[4], t[2]); + MULA(res, _anamatrix8[2], t[3]); + MULA(res, -_anamatrix8[6], t[4]); + MULA(res, -_anamatrix8[5], t[5]); + MULA(res, _anamatrix8[0], t[6]); + MULA(res, -_anamatrix8[3], t[7]); + out[5] = SCALE8_STAGE2(res); + + MUL(res, _anamatrix8[1], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, -_anamatrix8[3], t[2]); + MULA(res, _anamatrix8[5], t[3]); + MULA(res, -_anamatrix8[6], t[4]); + MULA(res, _anamatrix8[2], t[5]); + MULA(res, -_anamatrix8[0], t[6]); + MULA(res, _anamatrix8[4], t[7]); + out[6] = SCALE8_STAGE2(res); + + MUL(res, _anamatrix8[0], t[0]); + MULA(res, _anamatrix8[7], t[1]); + MULA(res, -_anamatrix8[2], t[2]); + MULA(res, -_anamatrix8[3], t[3]); + MULA(res, _anamatrix8[6], t[4]); + MULA(res, -_anamatrix8[4], t[5]); + MULA(res, _anamatrix8[1], t[6]); + MULA(res, -_anamatrix8[5], t[7]); + out[7] = SCALE8_STAGE2(res); +} + +static inline void sbc_analyze_eight(struct sbc_encoder_state *state, + struct sbc_frame *frame, int ch, int blk) +{ + int i; + + /* Input 8 Audio Samples */ + for (i = 79; i >= 8; i--) + state->X[ch][i] = state->X[ch][i - 8]; + for (i = 7; i >= 0; i--) + state->X[ch][i] = frame->pcm_sample[ch][blk * 8 + (7 - i)]; + _sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]); +} + +static int sbc_analyze_audio(struct sbc_encoder_state *state, struct sbc_frame *frame) +{ + int ch, blk; + + switch (frame->subbands) { + case 4: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) { + sbc_analyze_four(state, frame, ch, blk); + } + return frame->blocks * 4; + + case 8: + for (ch = 0; ch < frame->channels; ch++) + for (blk = 0; blk < frame->blocks; blk++) { + sbc_analyze_eight(state, frame, ch, blk); + } + return frame->blocks * 8; + + default: + return -EIO; + } +} + +/* + * Packs the SBC frame from frame into the memory at data. At most len + * bytes will be used, should more memory be needed an appropriate + * error code will be returned. Returns the length of the packed frame + * on success or a negative value on error. + * + * The error codes are: + * -1 Not enough memory reserved + * -2 Unsupported sampling rate + * -3 Unsupported number of blocks + * -4 Unsupported number of subbands + * -5 Bitpool value out of bounds + * -99 not implemented + */ + +static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) +{ + int produced; + /* Will copy the header parts for CRC-8 calculation here */ + uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int crc_pos = 0; + + uint8_t sf; /* Sampling frequency as temporary value for table lookup */ + + int ch, sb, blk, bit; /* channel, subband, block and bit counters */ + int bits[2][8]; /* bits distribution */ + int levels[2][8]; /* levels are derived from that */ + + u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ + + if (len < 4) { + return -1; + } + + /* Clear first 4 bytes of data (that's the constant length part of the SBC header) */ + memset(data, 0, 4); + + data[0] = SBC_SYNCWORD; + + if (frame->sampling_frequency == 16000) { + data[1] |= (SBC_FS_16 & 0x03) << 6; + sf = SBC_FS_16; + } else if (frame->sampling_frequency == 32000) { + data[1] |= (SBC_FS_32 & 0x03) << 6; + sf = SBC_FS_32; + } else if (frame->sampling_frequency == 44100) { + data[1] |= (SBC_FS_44 & 0x03) << 6; + sf = SBC_FS_44; + } else if (frame->sampling_frequency == 48000) { + data[1] |= (SBC_FS_48 & 0x03) << 6; + sf = SBC_FS_48; + } else { + return -2; + } + + switch (frame->blocks) { + case 4: + data[1] |= (SBC_NB_4 & 0x03) << 4; + break; + case 8: + data[1] |= (SBC_NB_8 & 0x03) << 4; + break; + case 12: + data[1] |= (SBC_NB_12 & 0x03) << 4; + break; + case 16: + data[1] |= (SBC_NB_16 & 0x03) << 4; + break; + default: + return -3; + break; + } + + data[1] |= (frame->channel_mode & 0x03) << 2; + + data[1] |= (frame->allocation_method & 0x01) << 1; + + switch (frame->subbands) { + case 4: + /* Nothing to do */ + break; + case 8: + data[1] |= 0x01; + break; + default: + return -4; + break; + } + + data[2] = frame->bitpool; + if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) + && frame->bitpool > 16 * frame->subbands) + || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) + && frame->bitpool > 32 * frame->subbands)) { + return -5; + } + + /* Can't fill in crc yet */ + + produced = 32; + + crc_header[0] = data[1]; + crc_header[1] = data[2]; + crc_pos = 16; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + frame->scale_factor[ch][sb] = 0; + scalefactor[ch][sb] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) { + frame->scale_factor[ch][sb]++; + scalefactor[ch][sb] *= 2; + } + } + } + } + + if (frame->channel_mode == JOINT_STEREO) { + int32_t sb_sample_j[16][2][7]; /* like frame->sb_sample but joint stereo */ + int scalefactor_j[2][7], scale_factor_j[2][7]; /* scalefactor and scale_factor in joint case */ + + /* Calculate joint stereo signal */ + for (sb = 0; sb < frame->subbands - 1; sb++) { + for (blk = 0; blk < frame->blocks; blk++) { + sb_sample_j[blk][0][sb] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) >> 1; + sb_sample_j[blk][1][sb] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) >> 1; + } + } + + /* calculate scale_factor_j and scalefactor_j for joint case */ + for (ch = 0; ch < 2; ch++) { + for (sb = 0; sb < frame->subbands - 1; sb++) { + scale_factor_j[ch][sb] = 0; + scalefactor_j[ch][sb] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + while (scalefactor_j[ch][sb] < fabs(sb_sample_j[blk][ch][sb])) { + scale_factor_j[ch][sb]++; + scalefactor_j[ch][sb] *= 2; + } + } + } + } + + /* decide which subbands to join */ + frame->join = 0; + for (sb = 0; sb < frame->subbands - 1; sb++) { + if ((scalefactor[0][sb] + scalefactor[1][sb]) > + (scalefactor_j[0][sb] + scalefactor_j[1][sb]) ) { + /* use joint stereo for this subband */ + frame->join |= 1 << sb; + frame->scale_factor[0][sb] = scale_factor_j[0][sb]; + frame->scale_factor[1][sb] = scale_factor_j[1][sb]; + scalefactor[0][sb] = scalefactor_j[0][sb]; + scalefactor[1][sb] = scalefactor_j[1][sb]; + for (blk = 0; blk < frame->blocks; blk++) { + frame->sb_sample_f[blk][0][sb] = sb_sample_j[blk][0][sb]; + frame->sb_sample_f[blk][1][sb] = sb_sample_j[blk][1][sb]; + } + } + } + + if (len * 8 < produced + frame->subbands) + return -1; + + data[4] = 0; + for (sb = 0; sb < frame->subbands - 1; sb++) { + data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb); + } + if (frame->subbands == 4) { + crc_header[crc_pos / 8] = data[4] & 0xf0; + } else { + crc_header[crc_pos / 8] = data[4]; + } + + produced += frame->subbands; + crc_pos += frame->subbands; + } + + if (len * 8 < produced + (4 * frame->subbands * frame->channels)) + return -1; + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (produced % 8 == 0) + data[produced / 8] = 0; + data[produced / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (produced % 8))); + crc_header[crc_pos / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (crc_pos % 8))); + + produced += 4; + crc_pos += 4; + } + } + + data[3] = sbc_crc8(crc_header, crc_pos); + + sbc_calculate_bits(frame, bits, sf); + + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + levels[ch][sb] = (1 << bits[ch][sb]) - 1; + } + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (levels[ch][sb] > 0) { + frame->audio_sample[blk][ch][sb] = + (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + + levels[ch][sb]) >> 1); + } else { + frame->audio_sample[blk][ch][sb] = 0; + } + } + } + } + + for (blk = 0; blk < frame->blocks; blk++) { + for (ch = 0; ch < frame->channels; ch++) { + for (sb = 0; sb < frame->subbands; sb++) { + if (bits[ch][sb] != 0) { + for (bit = 0; bit < bits[ch][sb]; bit++) { + int b; /* A bit */ + if (produced > len * 8) { + return -1; + } + if (produced % 8 == 0) { + data[produced / 8] = 0; + } + b = ((frame->audio_sample[blk][ch][sb]) >> (bits[ch][sb] - bit - + 1)) & 0x01; + data[produced / 8] |= b << (7 - (produced % 8)); + produced++; + } + } + } + } + } + + if (produced % 8 != 0) { + produced += 8 - (produced % 8); + } + + return produced / 8; +} + +struct sbc_priv { + int init; + struct sbc_frame frame; + struct sbc_decoder_state dec_state; + struct sbc_encoder_state enc_state; +}; + +int sbc_init(sbc_t *sbc, unsigned long flags) +{ + if (!sbc) + return -EIO; + + memset(sbc, 0, sizeof(sbc_t)); + + sbc->priv = malloc(sizeof(struct sbc_priv)); + if (!sbc->priv) + return -ENOMEM; + + memset(sbc->priv, 0, sizeof(struct sbc_priv)); + + sbc->rate = 44100; + sbc->channels = 2; + sbc->joint = 0; + sbc->subbands = 8; + sbc->blocks = 16; + sbc->bitpool = 32; + + return 0; +} + +int sbc_decode(sbc_t *sbc, void *data, int count) +{ + struct sbc_priv *priv; + char *ptr; + int i, ch, framelen, samples; + + if (!sbc) + return -EIO; + + priv = sbc->priv; + + framelen = sbc_unpack_frame(data, &priv->frame, count); + + + if (!priv->init) { + sbc_decoder_init(&priv->dec_state, &priv->frame); + priv->init = 1; + + sbc->rate = priv->frame.sampling_frequency; + sbc->channels = priv->frame.channels; + sbc->subbands = priv->frame.subbands; + sbc->blocks = priv->frame.blocks; + sbc->bitpool = priv->frame.bitpool; + } + + samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); + + if (!sbc->data) { + sbc->size = samples * priv->frame.channels * 2; + sbc->data = malloc(sbc->size); + } + + if (sbc->size < samples * priv->frame.channels * 2) { + sbc->size = samples * priv->frame.channels * 2; + sbc->data = realloc(sbc->data, sbc->size); + } + + if (!sbc->data) { + sbc->size = 0; + return -ENOMEM; + } + + ptr = sbc->data; + + for (i = 0; i < samples; i++) { + for (ch = 0; ch < priv->frame.channels; ch++) { + int16_t s; + s = priv->frame.pcm_sample[ch][i]; + *ptr++ = (s & 0xff00) >> 8; + *ptr++ = (s & 0x00ff); + } + } + + sbc->len = samples * priv->frame.channels * 2; + + return framelen; +} + +int sbc_encode(sbc_t *sbc, void *data, int count) +{ + struct sbc_priv *priv; + char *ptr; + int i, ch, framelen, samples; + + if (!sbc) + return -EIO; + + priv = sbc->priv; + + if (!priv->init) { + priv->frame.sampling_frequency = sbc->rate; + priv->frame.channels = sbc->channels; + + if (sbc->channels > 1) { + if (sbc->joint) + priv->frame.channel_mode = JOINT_STEREO; + else + priv->frame.channel_mode = STEREO; + } else + priv->frame.channel_mode = MONO; + + priv->frame.allocation_method = SNR; + priv->frame.subbands = sbc->subbands; + priv->frame.blocks = sbc->blocks; + priv->frame.bitpool = sbc->bitpool; + + sbc_encoder_init(&priv->enc_state, &priv->frame); + priv->init = 1; + } + + ptr = data; + + for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { + for (ch = 0; ch < sbc->channels; ch++) { + int16_t s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); + ptr += 2; + priv->frame.pcm_sample[ch][i] = s; + } + } + + samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); + + if (!sbc->data) { + sbc->size = 1024; + sbc->data = malloc(sbc->size); + } + + if (!sbc->data) { + sbc->size = 0; + return -ENOMEM; + } + + framelen = sbc_pack_frame(sbc->data, &priv->frame, sbc->size); + + sbc->len = framelen; + + sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate; + + return samples * sbc->channels * 2; +} + +void sbc_finish(sbc_t *sbc) +{ + if (!sbc) + return; + + if (sbc->data) + free(sbc->data); + + if (sbc->priv) + free(sbc->priv); + + memset(sbc, 0, sizeof(sbc_t)); +} diff --git a/sbc/sbc.h b/sbc/sbc.h index ae31af4c..99ccb3e4 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -2,7 +2,9 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley * * * This library is free software; you can redistribute it and/or @@ -28,6 +30,32 @@ extern "C" { #endif +struct sbc_struct { + unsigned long flags; + + int rate; + int channels; + int joint; + int blocks; + int subbands; + int bitpool; + + void *data; + int size; + int len; + + unsigned long duration; + + void *priv; +}; + +typedef struct sbc_struct sbc_t; + +int sbc_init(sbc_t *sbc, unsigned long flags); +int sbc_decode(sbc_t *sbc, void *data, int count); +int sbc_encode(sbc_t *sbc, void *data, int count); +void sbc_finish(sbc_t *sbc); + #ifdef __cplusplus } #endif diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index c427bee3..f6247ef8 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -2,7 +2,9 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley * * * This library is free software; you can redistribute it and/or @@ -22,11 +24,12 @@ */ #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))) + ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits))) +#define ASR_64(val, bits) ((-2 >> 1 == -1) ? \ + ((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits))) #define SCALE_PROTO4_TBL 15 #define SCALE_ANA4_TBL 16 @@ -37,29 +40,30 @@ #define SCALE_NPROTO4_TBL 10 #define SCALE_NPROTO8_TBL 12 #define SCALE_SAMPLES 14 -#define SCALE4_STAGE1_BITS 16 -#define SCALE4_STAGE2_BITS 18 -#define SCALE4_STAGED1_BITS 15 -#define SCALE4_STAGED2_BITS 15 -#define SCALE8_STAGE1_BITS 16 -#define SCALE8_STAGE2_BITS 18 -#define SCALE8_STAGED1_BITS 15 -#define SCALE8_STAGED2_BITS 15 +#define SCALE4_STAGE1_BITS 10 +#define SCALE4_STAGE2_BITS 21 +#define SCALE4_STAGED1_BITS 18 +#define SCALE4_STAGED2_BITS 23 +#define SCALE8_STAGE1_BITS 8 +#define SCALE8_STAGE2_BITS 24 +#define SCALE8_STAGED1_BITS 18 +#define SCALE8_STAGED2_BITS 23 typedef int32_t sbc_fixed_t; +typedef long long sbc_extended_t; -#define SCALE4_STAGE1(src) ASR(src, SCALE4_STAGE1_BITS) -#define SCALE4_STAGE2(src) ASR(src, SCALE4_STAGE2_BITS) -#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS) -#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS) -#define SCALE8_STAGE1(src) ASR(src, SCALE8_STAGE1_BITS) -#define SCALE8_STAGE2(src) ASR(src, SCALE8_STAGE2_BITS) -#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS) -#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS) +#define SCALE4_STAGE1(src) ASR_64(src, SCALE4_STAGE1_BITS) +#define SCALE4_STAGE2(src) ASR_64(src, SCALE4_STAGE2_BITS) +#define SCALE4_STAGED1(src) ASR_64(src, SCALE4_STAGED1_BITS) +#define SCALE4_STAGED2(src) ASR_64(src, SCALE4_STAGED2_BITS) +#define SCALE8_STAGE1(src) ASR_64(src, SCALE8_STAGE1_BITS) +#define SCALE8_STAGE2(src) ASR_64(src, SCALE8_STAGE2_BITS) +#define SCALE8_STAGED1(src) ASR_64(src, SCALE8_STAGED1_BITS) +#define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS) #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } #define MUL(dst, a, b) { dst = (sbc_fixed_t) a * b; } -#define MULA(dst, a, b) { dst += (sbc_fixed_t) a * b; } +#define MULA(dst, a, b) { dst += (sbc_extended_t) a * b; } #define DIV2(dst, src) { dst = ASR(src, 1); } diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h index a170704d..2712cf23 100644 --- a/sbc/sbc_tables.h +++ b/sbc/sbc_tables.h @@ -2,7 +2,9 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley * * * This library is free software; you can redistribute it and/or -- cgit From 1d6beece31584c71a7ce730133923f2e1d0d3b7d Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 24 Mar 2007 02:56:52 +0000 Subject: add Marcel's original, unmodified sbcdec/enc clients to sbc --- sbc/sbcdec.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++- sbc/sbcenc.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 417 insertions(+), 2 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 208cdfd8..0617fe04 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -1,6 +1,6 @@ /* * - * Bluetooth low-complexity, subband codec (SBC) library + * Bluetooth low-complexity, subband codec (SBC) decoder * * Copyright (C) 2004-2007 Marcel Holtmann * @@ -25,9 +25,202 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "sbc.h" +#define BUF_SIZE 8192 + +static void decode(char *filename, char *audiodevice, int tofile) +{ + unsigned char buf[BUF_SIZE], *stream; + struct stat st; + off_t filesize; + sbc_t sbc; + int fd, ad, pos, streamlen, framelen, count, format = AFMT_S16_BE; + + if (stat(filename, &st) < 0) { + fprintf(stderr, "Can't get size of file %s: %s\n", + filename, strerror(errno)); + return; + } + + filesize = st.st_size; + stream = malloc(st.st_size); + + if (!stream) { + fprintf(stderr, "Can't allocate memory for %s: %s\n", + filename, strerror(errno)); + return; + } + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open file %s: %s\n", + filename, strerror(errno)); + goto free; + } + + if (read(fd, stream, st.st_size) != st.st_size) { + fprintf(stderr, "Can't read content of %s: %s\n", + filename, strerror(errno)); + close(fd); + goto free; + } + + close(fd); + + pos = 0; + streamlen = st.st_size; + + ad = open(audiodevice, O_WRONLY | (tofile ? (O_CREAT | O_TRUNC) : 0), tofile ? 0644 : 0); + if (ad < 0) { + fprintf(stderr, "Can't open audio device %s: %s\n", + audiodevice, strerror(errno)); + goto free; + } + + sbc_init(&sbc, 0L); + + framelen = sbc_decode(&sbc, stream, streamlen); + printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); + if (!tofile) { + if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { + fprintf(stderr, "Can't set audio format on %s: %s\n", + audiodevice, strerror(errno)); + goto close; + } + if (ioctl(ad, SNDCTL_DSP_CHANNELS, &sbc.channels) < 0) { + fprintf(stderr, "Can't set number of channels on %s: %s\n", + audiodevice, strerror(errno)); + goto close; + } + + if (ioctl(ad, SNDCTL_DSP_SPEED, &sbc.rate) < 0) { + fprintf(stderr, "Can't set audio rate on %s: %s\n", + audiodevice, strerror(errno)); + goto close; + } + } + + count = 0; + while (framelen > 0) { + // we have completed an sbc_decode at this point + // sbc.len is the length of the frame we just decoded + // count is the number of decoded bytes yet to be written + + if (count + sbc.len > BUF_SIZE) { + // buffer is too full to stuff decoded audio in + // so it must be written to the device + write(ad, buf, count); + count = 0; + } + + // sanity check + if(count + sbc.len > BUF_SIZE) { + fprintf(stderr, "buffer size of %d is too small for decoded data (%d)\n", BUF_SIZE, sbc.len + count); + exit(1); + } + + // move the latest decoded data into buf and increase the count + memcpy(buf + count, sbc.data, sbc.len); + count += sbc.len; + + // push the pointer in the file forward to the next bit to be decoded + // tell the decoder to decode up to the remaining length of the file (!) + pos += framelen; + framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); + } + + if (count > 0) + write(ad, buf, count); + +close: + sbc_finish(&sbc); + + close(ad); + +free: + free(stream); +} + +static void usage(void) +{ + printf("SBC decoder utility ver %s\n", VERSION); + printf("Copyright (c) 2004 Marcel Holtmann\n\n"); + + printf("Usage:\n" + "\tsbcdec [options] file(s)\n" + "\n"); + + printf("Options:\n" + "\t-h, --help Display help\n" + "\t-d, --device Sound device\n" + "\t-v, --verbose Verbose mode\n" + "\t-f, --file Decode to a file\n" + "\n"); +} + +static struct option main_options[] = { + { "help", 0, 0, 'h' }, + { "device", 1, 0, 'd' }, + { "verbose", 0, 0, 'v' }, + { "file", 1, 0, 'f' }, + { 0, 0, 0, 0 } +}; + int main(int argc, char *argv[]) { + char *device = NULL; + char *file = NULL; + int i, opt, verbose = 0, tofile = 0; + + while ((opt = getopt_long(argc, argv, "+hd:vf:", main_options, NULL)) != -1) { + switch(opt) { + case 'h': + usage(); + exit(0); + + case 'd': + device = strdup(optarg); + break; + + case 'v': + verbose = 1; + break; + case 'f' : + file = strdup(optarg); + tofile = 1; + break; + + default: + exit(1); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + usage(); + exit(1); + } + + for (i = 0; i < argc; i++) + decode(argv[i], device ? device : file ? file : "/dev/dsp", tofile); + + if (device) + free(device); + return 0; } diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 208cdfd8..8919fb92 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -1,6 +1,6 @@ /* * - * Bluetooth low-complexity, subband codec (SBC) library + * Bluetooth low-complexity, subband codec (SBC) encoder * * Copyright (C) 2004-2007 Marcel Holtmann * @@ -25,9 +25,231 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "sbc.h" +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) +#define LE_SHORT(v) (v) +#define LE_INT(v) (v) +#define BE_SHORT(v) bswap_16(v) +#define BE_INT(v) bswap_32(v) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define COMPOSE_ID(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24)) +#define LE_SHORT(v) bswap_16(v) +#define LE_INT(v) bswap_32(v) +#define BE_SHORT(v) (v) +#define BE_INT(v) (v) +#else +#error "Wrong endian" +#endif + +#define AU_MAGIC COMPOSE_ID('.','s','n','d') + +#define AU_FMT_ULAW 1 +#define AU_FMT_LIN8 2 +#define AU_FMT_LIN16 3 + +struct au_header { + uint32_t magic; /* '.snd' */ + uint32_t hdr_size; /* size of header (min 24) */ + uint32_t data_size; /* size of data */ + uint32_t encoding; /* see to AU_FMT_XXXX */ + uint32_t sample_rate; /* sample rate */ + uint32_t channels; /* number of channels (voices) */ +}; + +static ssize_t __read(int fd, void *buf, size_t count) +{ + ssize_t len, pos = 0; + + while (count > 0) { + len = read(fd, buf + pos, count); + if (len <= 0) + return len; + + count -= len; + pos += len; + } + + return pos; +} + +static ssize_t __write(int fd, const void *buf, size_t count) +{ + ssize_t len, pos = 0; + + while (count > 0) { + len = write(fd, buf + pos, count); + if (len <= 0) + return len; + + count -= len; + pos += len; + } + + return pos; +} + +static void encode(char *filename, int subbands, int joint) +{ + struct au_header *au_hdr; + unsigned char buf[2048]; + sbc_t sbc; + int fd, len, size, count; + + if (strcmp(filename, "-")) { + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open file %s: %s\n", + filename, strerror(errno)); + return; + } + } else + fd = fileno(stdin); + + len = __read(fd, buf, sizeof(buf)); + if (len < sizeof(*au_hdr)) { + if (fd > fileno(stderr)) + fprintf(stderr, "Can't read header from file %s: %s\n", + filename, strerror(errno)); + else + perror("Can't read audio header"); + goto done; + } + + au_hdr = (struct au_header *) buf; + + if (au_hdr->magic != AU_MAGIC || + BE_INT(au_hdr->hdr_size) > 128 || + BE_INT(au_hdr->hdr_size) < 24 || + BE_INT(au_hdr->encoding) != AU_FMT_LIN16) { + fprintf(stderr, "Data is not in Sun/NeXT audio S16_BE format\n"); + goto done; + } + + sbc_init(&sbc, 0L); + + sbc.rate = BE_INT(au_hdr->sample_rate); + sbc.channels = BE_INT(au_hdr->channels); + sbc.subbands = subbands; + sbc.joint = joint; + count = BE_INT(au_hdr->data_size); + size = len - BE_INT(au_hdr->hdr_size); + memmove(buf, buf + BE_INT(au_hdr->hdr_size), size); + + while (1) { + if (size < sizeof(buf)) { + len = __read(fd, buf + size, sizeof(buf) - size); + if (len == 0) + break; + + if (len < 0) { + perror("Can't read audio data"); + break; + } + + size += len; + } + + len = sbc_encode(&sbc, buf, size); + if (len < size) + memmove(buf, buf + len, size - len); + + size -= len; + + len = __write(fileno(stdout), sbc.data, sbc.len); + if (len == 0) + break; + + if (len < 0 || len != sbc.len) { + perror("Can't write SBC output"); + break; + } + } + + sbc_finish(&sbc); + +done: + if (fd > fileno(stderr)) + close(fd); +} + +static void usage(void) +{ + printf("SBC encoder utility ver %s\n", VERSION); + printf("Copyright (c) 2004 Marcel Holtmann\n\n"); + + printf("Usage:\n" + "\tsbcenc [options] file(s)\n" + "\n"); + + printf("Options:\n" + "\t-h, --help Display help\n" + "\t-v, --verbose Verbose mode\n" + "\t-s, --subbands Number of subbands to use (4 or 8)\n" + "\t-j, --joint Joint stereo\n" + "\n"); +} + +static struct option main_options[] = { + { "help", 0, 0, 'h' }, + { "verbose", 0, 0, 'v' }, + { "subbands", 1, 0, 's' }, + { "joint", 0, 0, 'j' }, + { 0, 0, 0, 0 } +}; + int main(int argc, char *argv[]) { + int i, opt, verbose = 0, subbands = 8, joint = 0; + + while ((opt = getopt_long(argc, argv, "+hv", main_options, NULL)) != -1) { + switch(opt) { + case 'h': + usage(); + exit(0); + + case 'v': + verbose = 1; + break; + case 's': + subbands = atoi(strdup(optarg)); + if (subbands != 8 && subbands != 4) { + fprintf(stderr, "Invalid number of sunnabds %d!\n", subbands); + exit(1); + } + break; + case 'j': + joint = 1; + break; + + default: + exit(1); + } + } + + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + usage(); + exit(1); + } + + for (i = 0; i < argc; i++) + encode(argv[i], subbands, joint); + return 0; } -- cgit From 0c96c8790268b67d973339ca4547c8021474bf1c Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 24 Mar 2007 13:58:21 +0000 Subject: examine the result of write() ops, avoid warnings --- sbc/sbcdec.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 0617fe04..3435e8f8 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,7 @@ static void decode(char *filename, char *audiodevice, int tofile) struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, format = AFMT_S16_BE; + int fd, ad, pos, streamlen, framelen, count, format = AFMT_S16_BE, written; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", @@ -121,8 +121,8 @@ static void decode(char *filename, char *audiodevice, int tofile) if (count + sbc.len > BUF_SIZE) { // buffer is too full to stuff decoded audio in // so it must be written to the device - write(ad, buf, count); - count = 0; + written = write(ad, buf, count); + if(written > 0) count -= written; } // sanity check @@ -141,8 +141,10 @@ static void decode(char *filename, char *audiodevice, int tofile) framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); } - if (count > 0) - write(ad, buf, count); + if (count > 0) { + written = write(ad, buf, count); + if(written > 0) count -= written; + } close: sbc_finish(&sbc); -- cgit From a745805cb3961ccf88f0119f28dc919ed9c571e5 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 24 Mar 2007 14:01:31 +0000 Subject: whitespace fixes --- sbc/sbc.c | 4 ++-- sbc/sbcdec.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 1f16d70a..ce6252df 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -594,7 +594,7 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, for(i = 0; i < 8; i++) { /* Shifting */ state->offset[ch][i]--; - if(state->offset[ch][i] < 0) { + if (state->offset[ch][i] < 0) { state->offset[ch][i] = 79; for(j = 0; j < 9; j++) { state->V[ch][j+80] = state->V[ch][j]; @@ -634,7 +634,7 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, for(i = 0; i < 16; i++) { /* Shifting */ state->offset[ch][i]--; - if(state->offset[ch][i] < 0) { + if (state->offset[ch][i] < 0) { state->offset[ch][i] = 159; for(j = 0; j < 9; j++) { state->V[ch][j+160] = state->V[ch][j]; diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 3435e8f8..decd758d 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -122,11 +122,11 @@ static void decode(char *filename, char *audiodevice, int tofile) // buffer is too full to stuff decoded audio in // so it must be written to the device written = write(ad, buf, count); - if(written > 0) count -= written; + if (written > 0) count -= written; } // sanity check - if(count + sbc.len > BUF_SIZE) { + if (count + sbc.len > BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded data (%d)\n", BUF_SIZE, sbc.len + count); exit(1); } @@ -143,7 +143,7 @@ static void decode(char *filename, char *audiodevice, int tofile) if (count > 0) { written = write(ad, buf, count); - if(written > 0) count -= written; + if (written > 0) count -= written; } close: -- cgit From b28533ef8bb61744e06c94f2df6704beedabd2f4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 24 Mar 2007 22:22:54 +0000 Subject: Update coding style --- sbc/sbcdec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index decd758d..b5305550 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,7 @@ static void decode(char *filename, char *audiodevice, int tofile) struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, format = AFMT_S16_BE, written; + int fd, ad, pos, streamlen, framelen, count, written, format = AFMT_S16_BE; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", @@ -122,7 +122,8 @@ static void decode(char *filename, char *audiodevice, int tofile) // buffer is too full to stuff decoded audio in // so it must be written to the device written = write(ad, buf, count); - if (written > 0) count -= written; + if (written > 0) + count -= written; } // sanity check @@ -143,7 +144,8 @@ static void decode(char *filename, char *audiodevice, int tofile) if (count > 0) { written = write(ad, buf, count); - if (written > 0) count -= written; + if (written > 0) + count -= written; } close: -- cgit From 5daebe3831a85cc39a74c25798fb5123f2bdc633 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 10 Apr 2007 11:03:02 +0000 Subject: Only compile SBC library if ALSA is enabled --- sbc/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index 4492dfa7..ab8898af 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,4 +1,5 @@ +if ALSA noinst_LTLIBRARIES = libsbc.la libsbc_la_SOURCES = sbc.h sbc.c sbc_math.h sbc_tables.h @@ -8,5 +9,6 @@ noinst_PROGRAMS = sbcinfo sbcdec sbcenc sbcdec_LDADD = libsbc.la sbcenc_LDADD = libsbc.la +endif MAINTAINERCLEANFILES = Makefile.in -- cgit From 46e860574f3d6d70d961e38270522764191cea20 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 11 Aug 2007 10:56:46 +0000 Subject: Don't hardcode allocation method to SNR --- sbc/sbc.c | 2 +- sbc/sbc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index ce6252df..d485a5fd 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1374,7 +1374,7 @@ int sbc_encode(sbc_t *sbc, void *data, int count) } else priv->frame.channel_mode = MONO; - priv->frame.allocation_method = SNR; + priv->frame.allocation_method = sbc->allocation; priv->frame.subbands = sbc->subbands; priv->frame.blocks = sbc->blocks; priv->frame.bitpool = sbc->bitpool; diff --git a/sbc/sbc.h b/sbc/sbc.h index 99ccb3e4..70881c12 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -36,6 +36,7 @@ struct sbc_struct { int rate; int channels; int joint; + int allocation; int blocks; int subbands; int bitpool; -- cgit From b1618922db92f9bc65b0841f66eb71742bc1b553 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 21 Aug 2007 21:32:09 +0000 Subject: Add swap member to sbc struct and fix pcm plugin to not swap the buffer. --- sbc/sbc.c | 18 +++++++++++++++--- sbc/sbc.h | 1 + sbc/sbcdec.c | 1 + sbc/sbcenc.c | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index d485a5fd..d27c1e9a 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1289,6 +1289,7 @@ int sbc_init(sbc_t *sbc, unsigned long flags) sbc->subbands = 8; sbc->blocks = 16; sbc->bitpool = 32; + sbc->swap = 0; return 0; } @@ -1341,8 +1342,14 @@ int sbc_decode(sbc_t *sbc, void *data, int count) for (ch = 0; ch < priv->frame.channels; ch++) { int16_t s; s = priv->frame.pcm_sample[ch][i]; - *ptr++ = (s & 0xff00) >> 8; - *ptr++ = (s & 0x00ff); + + if (sbc->swap) { + *ptr++ = (s & 0xff00) >> 8; + *ptr++ = (s & 0x00ff); + } else { + *ptr++ = (s & 0x00ff); + *ptr++ = (s & 0xff00) >> 8; + } } } @@ -1387,7 +1394,12 @@ int sbc_encode(sbc_t *sbc, void *data, int count) for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { for (ch = 0; ch < sbc->channels; ch++) { - int16_t s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); + int16_t s; + + if (sbc->swap) + s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); + else + s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8; ptr += 2; priv->frame.pcm_sample[ch][i] = s; } diff --git a/sbc/sbc.h b/sbc/sbc.h index 70881c12..11d9740d 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -40,6 +40,7 @@ struct sbc_struct { int blocks; int subbands; int bitpool; + int swap; void *data; int size; diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index b5305550..d84a631b 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -90,6 +90,7 @@ static void decode(char *filename, char *audiodevice, int tofile) } sbc_init(&sbc, 0L); + sbc.swap = 1; framelen = sbc_decode(&sbc, stream, streamlen); printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 8919fb92..2334f8d3 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -144,6 +144,7 @@ static void encode(char *filename, int subbands, int joint) sbc.channels = BE_INT(au_hdr->channels); sbc.subbands = subbands; sbc.joint = joint; + sbc.swap = 1; count = BE_INT(au_hdr->data_size); size = len - BE_INT(au_hdr->hdr_size); memmove(buf, buf + BE_INT(au_hdr->hdr_size), size); -- cgit From cbc3614749e2b545c3d31d996d202020bbecff61 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 22 Aug 2007 14:51:54 +0000 Subject: Build SBC library only when ALSA or GStreamer is enabled --- sbc/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index ab8898af..46cb30be 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,5 +1,5 @@ -if ALSA +if SBC noinst_LTLIBRARIES = libsbc.la libsbc_la_SOURCES = sbc.h sbc.c sbc_math.h sbc_tables.h -- cgit From 5689ce1423a12a2c20aef9e48146282e978c4adb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 13:23:51 +0000 Subject: Update copyright information --- sbc/sbc.c | 2 +- sbc/sbc.h | 2 +- sbc/sbc_math.h | 2 +- sbc/sbc_tables.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index d27c1e9a..ca683e86 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * diff --git a/sbc/sbc.h b/sbc/sbc.h index 11d9740d..e8375b26 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index f6247ef8..d01799c9 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h index 2712cf23..5e00caca 100644 --- a/sbc/sbc_tables.h +++ b/sbc/sbc_tables.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * -- cgit From 60dc1ff7491b901c9a849f4c0a1d60a9ed12bf68 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 13:27:46 +0000 Subject: Fix output handling of decoder --- sbc/sbcdec.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index d84a631b..ebf9ae7c 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -40,7 +40,7 @@ #define BUF_SIZE 8192 -static void decode(char *filename, char *audiodevice, int tofile) +static void decode(char *filename, char *output, int tofile) { unsigned char buf[BUF_SIZE], *stream; struct stat st; @@ -82,10 +82,14 @@ static void decode(char *filename, char *audiodevice, int tofile) pos = 0; streamlen = st.st_size; - ad = open(audiodevice, O_WRONLY | (tofile ? (O_CREAT | O_TRUNC) : 0), tofile ? 0644 : 0); + if (tofile) + ad = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0644); + else + ad = open(output, O_WRONLY, 0); + if (ad < 0) { - fprintf(stderr, "Can't open audio device %s: %s\n", - audiodevice, strerror(errno)); + fprintf(stderr, "Can't open output %s: %s\n", + output, strerror(errno)); goto free; } @@ -97,18 +101,18 @@ static void decode(char *filename, char *audiodevice, int tofile) if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { fprintf(stderr, "Can't set audio format on %s: %s\n", - audiodevice, strerror(errno)); + output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_CHANNELS, &sbc.channels) < 0) { fprintf(stderr, "Can't set number of channels on %s: %s\n", - audiodevice, strerror(errno)); + output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_SPEED, &sbc.rate) < 0) { fprintf(stderr, "Can't set audio rate on %s: %s\n", - audiodevice, strerror(errno)); + output, strerror(errno)); goto close; } } @@ -161,7 +165,7 @@ free: static void usage(void) { printf("SBC decoder utility ver %s\n", VERSION); - printf("Copyright (c) 2004 Marcel Holtmann\n\n"); + printf("Copyright (c) 2004-2007 Marcel Holtmann\n\n"); printf("Usage:\n" "\tsbcdec [options] file(s)\n" @@ -169,9 +173,9 @@ static void usage(void) printf("Options:\n" "\t-h, --help Display help\n" - "\t-d, --device Sound device\n" "\t-v, --verbose Verbose mode\n" - "\t-f, --file Decode to a file\n" + "\t-d, --device Sound device\n" + "\t-f, --file Decode to a file\n" "\n"); } @@ -185,25 +189,30 @@ static struct option main_options[] = { int main(int argc, char *argv[]) { - char *device = NULL; - char *file = NULL; + char *output = NULL; int i, opt, verbose = 0, tofile = 0; - while ((opt = getopt_long(argc, argv, "+hd:vf:", main_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+hvd:f:", main_options, NULL)) != -1) { switch(opt) { case 'h': usage(); exit(0); - case 'd': - device = strdup(optarg); - break; - case 'v': verbose = 1; break; + + case 'd': + if (output) + free(output); + output = strdup(optarg); + tofile = 0; + break; + case 'f' : - file = strdup(optarg); + if (output) + free(output); + output = strdup(optarg); tofile = 1; break; @@ -222,10 +231,10 @@ int main(int argc, char *argv[]) } for (i = 0; i < argc; i++) - decode(argv[i], device ? device : file ? file : "/dev/dsp", tofile); + decode(argv[i], output ? output : "/dev/dsp", tofile); - if (device) - free(device); + if (output) + free(output); return 0; } -- cgit From aec1793366001cdda187e851f9e37113678d7ee8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 25 Aug 2007 13:35:53 +0000 Subject: Fix parameter handling of encoder --- sbc/sbcenc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 2334f8d3..48e01021 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -189,7 +189,7 @@ done: static void usage(void) { printf("SBC encoder utility ver %s\n", VERSION); - printf("Copyright (c) 2004 Marcel Holtmann\n\n"); + printf("Copyright (c) 2004-2007 Marcel Holtmann\n\n"); printf("Usage:\n" "\tsbcenc [options] file(s)\n" @@ -198,8 +198,8 @@ static void usage(void) printf("Options:\n" "\t-h, --help Display help\n" "\t-v, --verbose Verbose mode\n" - "\t-s, --subbands Number of subbands to use (4 or 8)\n" - "\t-j, --joint Joint stereo\n" + "\t-s, --subbands Number of subbands to use (4 or 8)\n" + "\t-j, --joint Joint stereo\n" "\n"); } @@ -215,7 +215,7 @@ int main(int argc, char *argv[]) { int i, opt, verbose = 0, subbands = 8, joint = 0; - while ((opt = getopt_long(argc, argv, "+hv", main_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+hvs:j", main_options, NULL)) != -1) { switch(opt) { case 'h': usage(); @@ -224,13 +224,15 @@ int main(int argc, char *argv[]) case 'v': verbose = 1; break; + case 's': subbands = atoi(strdup(optarg)); if (subbands != 8 && subbands != 4) { - fprintf(stderr, "Invalid number of sunnabds %d!\n", subbands); + fprintf(stderr, "Invalid subbands %d!\n", subbands); exit(1); } break; + case 'j': joint = 1; break; -- cgit From c82412ad9e399b9b6391ef73c24f36ff83983e9d Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sun, 26 Aug 2007 01:05:25 +0000 Subject: indicate 0 bytes consumed in encoder if input is too short. caller is responsible for filling the end of the input if it really wants the frame encoded (ie with silence at the end) --- sbc/sbc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index ca683e86..240a5d24 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -28,7 +28,6 @@ use a log2 table for byte integer scale factors calculation (sum log2 results for high and low bytes) fill bitpool by 16 bits instead of one at a time in bits allocation/bitpool generation port to the dsp - don't consume more bytes than passed into the encoder */ @@ -1390,6 +1389,10 @@ int sbc_encode(sbc_t *sbc, void *data, int count) priv->init = 1; } + /* input must be large enough to encode a complete frame */ + if (count < priv->frame.subbands * priv->frame.blocks * sbc->channels * 2) + return 0; + ptr = data; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { -- cgit From d9bccae488ef82fc0e1d927b30db9228bfd91169 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 26 Aug 2007 13:54:24 +0000 Subject: Add simple implementation of sbc_parse() --- sbc/sbc.c | 5 +++++ sbc/sbc.h | 1 + 2 files changed, 6 insertions(+) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 240a5d24..7cd267b1 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1293,6 +1293,11 @@ int sbc_init(sbc_t *sbc, unsigned long flags) return 0; } +int sbc_parse(sbc_t *sbc, void *data, int count) +{ + return sbc_decode(sbc, data, count); +} + int sbc_decode(sbc_t *sbc, void *data, int count) { struct sbc_priv *priv; diff --git a/sbc/sbc.h b/sbc/sbc.h index e8375b26..72512c02 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -54,6 +54,7 @@ struct sbc_struct { typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); +int sbc_parse(sbc_t *sbc, void *data, int count); int sbc_decode(sbc_t *sbc, void *data, int count); int sbc_encode(sbc_t *sbc, void *data, int count); void sbc_finish(sbc_t *sbc); -- cgit From 34207c770a372a5d847fe60423dc82a358faab6b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 27 Aug 2007 13:38:17 +0000 Subject: Make SBC frame header endian safe --- sbc/sbcinfo.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'sbc') diff --git a/sbc/sbcinfo.c b/sbc/sbcinfo.c index e34f5618..e8fb398f 100644 --- a/sbc/sbcinfo.c +++ b/sbc/sbcinfo.c @@ -34,6 +34,7 @@ #include #include +#if __BYTE_ORDER == __LITTLE_ENDIAN struct sbc_frame_hdr { uint8_t syncword:8; /* Sync word */ uint8_t subbands:1; /* Subbands */ @@ -44,6 +45,20 @@ struct sbc_frame_hdr { uint8_t bitpool:8; /* Bitpool */ uint8_t crc_check:8; /* CRC check */ } __attribute__ ((packed)); +#elif __BYTE_ORDER == __BIG_ENDIAN +struct sbc_frame_hdr { + uint8_t syncword:8; /* Sync word */ + uint8_t sampling_frequency:2; /* Sampling frequency */ + uint8_t blocks:2; /* Blocks */ + uint8_t channel_mode:2; /* Channel mode */ + uint8_t allocation_method:1; /* Allocation method */ + uint8_t subbands:1; /* Subbands */ + uint8_t bitpool:8; /* Bitpool */ + uint8_t crc_check:8; /* CRC check */ +} __attribute__ ((packed)); +#else +#error "Unknown byte order" +#endif static int calc_frame_len(struct sbc_frame_hdr *hdr) { -- cgit From c434c0b49544551f784c34fec4ef220423ad2a51 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 4 Oct 2007 05:15:07 +0000 Subject: optimizations for 2nd stage of 4-subband encoder disabled but in place so indt folks don't duplicate the optimization effort --- sbc/sbc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 7cd267b1..c9728ec9 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -701,6 +701,10 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; +#if 0 + /* temporary results */ + sbc_extended_t s[2], p[6], d[4]; +#endif out[0] = out[1] = out[2] = out[3] = 0; MUL(res, _sbc_proto_4[0], (in[8] - in[32])); // Q18 @@ -755,6 +759,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[2], in[39]); t[7] = SCALE4_STAGE1(res); +#if 1 MUL(res, _anamatrix4[0], t[0]); MULA(res, _anamatrix4[1], t[1]); MULA(res, _anamatrix4[2], t[2]); @@ -791,6 +796,24 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, -_anamatrix4[3], t[5]); MULA(res, _anamatrix4[3], t[7]); out[3] = SCALE4_STAGE2(res); +#else + s[0] = t[1] + t[3]; + s[1] = t[5] - t[6]; + MUL(p[0], _anamatrix4[0], t[0] + t[4]); + MUL(p[1], _anamatrix4[1], s[0]); + MUL(p[2], _anamatrix4[2], t[2]); + MUL(p[3], _anamatrix4[3], s[0]); + MUL(p[4], _anamatrix4[3], s[1]); + MUL(p[5], _anamatrix4[1], s[1]); + d[0] = p[0] + p[2]; + d[1] = p[2] - p[0]; + d[2] = p[1] + p[4]; + d[3] = p[3] - p[5]; + out[0] = SCALE4_STAGE2(d[0] + d[2]); + out[1] = SCALE4_STAGE2(d[1] + d[3]); + out[2] = SCALE4_STAGE2(d[1] - d[3]); + out[3] = SCALE4_STAGE2(d[0] - d[2]); +#endif } static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) -- cgit From 6ee3949547dfad9aadc975646f455bde96ae06c6 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 4 Oct 2007 07:42:57 +0000 Subject: a (disabled for now) cpu optimization for the bottom half of the 8 subbands encoder. seems to work fine. --- sbc/sbc.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c9728ec9..1cf83329 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -832,6 +832,10 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; +#if 0 + /* temporary results */ + sbc_extended_t s[8]; +#endif out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0; MUL(res, _sbc_proto_8[0], (in[16] - in[64])); // Q18 = Q18 * Q0 @@ -920,6 +924,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); +#if 1 MUL(res, _anamatrix8[0], t[0]); // = Q14 * Q10 MULA(res, _anamatrix8[7], t[1]); MULA(res, _anamatrix8[2], t[2]); @@ -999,6 +1004,38 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, _anamatrix8[1], t[6]); MULA(res, -_anamatrix8[5], t[7]); out[7] = SCALE8_STAGE2(res); +#else + MUL(s[0], _anamatrix8[0], t[0]); + MULA(s[0], _anamatrix8[1], t[6]); + MUL(s[1], _anamatrix8[7], t[1]); + MUL(s[2], _anamatrix8[2], t[3]); + MULA(s[2], _anamatrix8[3], t[4]); + MULA(s[2], _anamatrix8[4], t[5]); + MULA(s[2], _anamatrix8[5], t[7]); + MUL(s[3], _anamatrix8[6], t[4]); + MUL(s[4], _anamatrix8[3], t[2]); + MULA(s[4], -_anamatrix8[5], t[3]); + MULA(s[4], -_anamatrix8[2], t[5]); + MULA(s[4], -_anamatrix8[4], t[7]); + MUL(s[5], _anamatrix8[4], t[2]); + MULA(s[5], -_anamatrix8[2], t[3]); + MULA(s[5], _anamatrix8[5], t[5]); + MULA(s[5], _anamatrix8[3], t[7]); + MUL(s[6], _anamatrix8[1], t[0]); + MULA(s[6], -_anamatrix8[0], t[6]); + MUL(s[7], _anamatrix8[5], t[2]); + MULA(s[7], -_anamatrix8[4], t[3]); + MULA(s[7], _anamatrix8[3], t[5]); + MULA(s[7], _anamatrix8[2], t[7]); + out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]); + out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]); + out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]); + out[3] = SCALE8_STAGE2(-s[0] + s[1] + s[3] + s[7]); + out[4] = SCALE8_STAGE2(-s[0] + s[1] + s[3] - s[7]); + out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] + s[6]); + out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]); + out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]); +#endif } static inline void sbc_analyze_eight(struct sbc_encoder_state *state, -- cgit From aaad5f279f2fc2156799ebc6d171a76113724de4 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 4 Oct 2007 08:08:59 +0000 Subject: off-by-one problem in 8 subband optimization --- sbc/sbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 1cf83329..25244e0d 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1008,8 +1008,8 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MUL(s[0], _anamatrix8[0], t[0]); MULA(s[0], _anamatrix8[1], t[6]); MUL(s[1], _anamatrix8[7], t[1]); - MUL(s[2], _anamatrix8[2], t[3]); - MULA(s[2], _anamatrix8[3], t[4]); + MUL(s[2], _anamatrix8[2], t[2]); + MULA(s[2], _anamatrix8[3], t[3]); MULA(s[2], _anamatrix8[4], t[5]); MULA(s[2], _anamatrix8[5], t[7]); MUL(s[3], _anamatrix8[6], t[4]); -- cgit From 4cbaa35cb32fe5fe0f79e7f323cff3075a9f5b42 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 4 Oct 2007 16:05:40 +0000 Subject: fix & enable 8-subband second half optimization --- sbc/sbc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 25244e0d..dcff5382 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -796,7 +796,8 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, -_anamatrix4[3], t[5]); MULA(res, _anamatrix4[3], t[7]); out[3] = SCALE4_STAGE2(res); -#else +#endif +#if 0 s[0] = t[1] + t[3]; s[1] = t[5] - t[6]; MUL(p[0], _anamatrix4[0], t[0] + t[4]); @@ -832,7 +833,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; -#if 0 +#if 1 /* temporary results */ sbc_extended_t s[8]; #endif @@ -924,7 +925,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); -#if 1 +#if 0 MUL(res, _anamatrix8[0], t[0]); // = Q14 * Q10 MULA(res, _anamatrix8[7], t[1]); MULA(res, _anamatrix8[2], t[2]); @@ -1026,7 +1027,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MUL(s[7], _anamatrix8[5], t[2]); MULA(s[7], -_anamatrix8[4], t[3]); MULA(s[7], _anamatrix8[3], t[5]); - MULA(s[7], _anamatrix8[2], t[7]); + MULA(s[7], -_anamatrix8[2], t[7]); out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]); out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]); out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]); -- cgit From 7fbcefdd87d222c04023dcb1b3ff3cf5aeae8613 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 4 Oct 2007 18:28:17 +0000 Subject: enable 4 subband lower half optimizations --- sbc/sbc.c | 55 +++++++++++++++++++++++-------------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index dcff5382..a5cbf803 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -700,12 +700,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; - -#if 0 - /* temporary results */ - sbc_extended_t s[2], p[6], d[4]; -#endif - out[0] = out[1] = out[2] = out[3] = 0; + sbc_extended_t s[4]; MUL(res, _sbc_proto_4[0], (in[8] - in[32])); // Q18 MULA(res, _sbc_proto_4[1], (in[16] - in[24])); @@ -744,14 +739,15 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[13], in[29]); MULA(res, _sbc_proto_4[12], in[37]); t[5] = SCALE4_STAGE1(res); - +#if 0 + /* don't compute... this term always multiplies with cos(pi) = 0*/ MUL(res, _sbc_proto_4[11], in[6]); MULA(res, _sbc_proto_4[10], in[14]); MULA(res, _sbc_proto_4[9], in[22]); MULA(res, _sbc_proto_4[8], in[30]); MULA(res, _sbc_proto_4[7], in[38]); t[6] = SCALE4_STAGE1(res); - +#endif MUL(res, _sbc_proto_4[6], in[7]); MULA(res, _sbc_proto_4[5], in[15]); MULA(res, _sbc_proto_4[4], in[23]); @@ -759,7 +755,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[2], in[39]); t[7] = SCALE4_STAGE1(res); -#if 1 +#if 0 MUL(res, _anamatrix4[0], t[0]); MULA(res, _anamatrix4[1], t[1]); MULA(res, _anamatrix4[2], t[2]); @@ -796,24 +792,24 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, -_anamatrix4[3], t[5]); MULA(res, _anamatrix4[3], t[7]); out[3] = SCALE4_STAGE2(res); -#endif -#if 0 - s[0] = t[1] + t[3]; - s[1] = t[5] - t[6]; - MUL(p[0], _anamatrix4[0], t[0] + t[4]); - MUL(p[1], _anamatrix4[1], s[0]); - MUL(p[2], _anamatrix4[2], t[2]); - MUL(p[3], _anamatrix4[3], s[0]); - MUL(p[4], _anamatrix4[3], s[1]); - MUL(p[5], _anamatrix4[1], s[1]); - d[0] = p[0] + p[2]; - d[1] = p[2] - p[0]; - d[2] = p[1] + p[4]; - d[3] = p[3] - p[5]; - out[0] = SCALE4_STAGE2(d[0] + d[2]); - out[1] = SCALE4_STAGE2(d[1] + d[3]); - out[2] = SCALE4_STAGE2(d[1] - d[3]); - out[3] = SCALE4_STAGE2(d[0] - d[2]); +#else + /* some of these multiplies could be factored more but something overflows */ + /* eg replace the first two lines with MUL(s[0], _anamatrix4[0], t[0] + t[4]) */ + MUL(s[0], _anamatrix4[0], t[0]); + MULA(s[0], _anamatrix4[0], t[4]); + MUL(s[1], _anamatrix4[2], t[2]); + MUL(s[2], _anamatrix4[1], t[1]); + MULA(s[2], _anamatrix4[1], t[3]); + MULA(s[2], _anamatrix4[3], t[5]); + MULA(s[2], -_anamatrix4[3], t[7]); + MUL(s[3], _anamatrix4[3], t[1]); + MULA(s[3], _anamatrix4[3], t[3]); + MULA(s[3], -_anamatrix4[1], t[5]); + MULA(s[3], _anamatrix4[1], t[7]); + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); + out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); + out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); + out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2]); #endif } static inline void sbc_analyze_four(struct sbc_encoder_state *state, @@ -832,12 +828,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) { sbc_extended_t res; sbc_extended_t t[8]; - -#if 1 - /* temporary results */ sbc_extended_t s[8]; -#endif - out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0; MUL(res, _sbc_proto_8[0], (in[16] - in[64])); // Q18 = Q18 * Q0 MULA(res, _sbc_proto_8[1], (in[32] - in[48])); -- cgit From 99b92496ace832a5c75776a55126d731ee42df43 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 5 Oct 2007 05:42:55 +0000 Subject: fix MUL* macros with () factor more multiplies in 4-subband encoder --- sbc/sbc.c | 17 +++++------------ sbc/sbc_math.h | 4 ++-- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a5cbf803..c262f16d 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -793,19 +793,12 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _anamatrix4[3], t[7]); out[3] = SCALE4_STAGE2(res); #else - /* some of these multiplies could be factored more but something overflows */ - /* eg replace the first two lines with MUL(s[0], _anamatrix4[0], t[0] + t[4]) */ - MUL(s[0], _anamatrix4[0], t[0]); - MULA(s[0], _anamatrix4[0], t[4]); + MUL(s[0], _anamatrix4[0], t[0] + t[4]); MUL(s[1], _anamatrix4[2], t[2]); - MUL(s[2], _anamatrix4[1], t[1]); - MULA(s[2], _anamatrix4[1], t[3]); - MULA(s[2], _anamatrix4[3], t[5]); - MULA(s[2], -_anamatrix4[3], t[7]); - MUL(s[3], _anamatrix4[3], t[1]); - MULA(s[3], _anamatrix4[3], t[3]); - MULA(s[3], -_anamatrix4[1], t[5]); - MULA(s[3], _anamatrix4[1], t[7]); + MUL(s[2], _anamatrix4[1], t[1] + t[3]); + MULA(s[2], _anamatrix4[3], t[5] + t[7]); + MUL(s[3], _anamatrix4[3], t[1] + t[3]); + MULA(s[3], _anamatrix4[1], - t[5] + t[7]); out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index d01799c9..e4f82bce 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -64,6 +64,6 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } -#define MUL(dst, a, b) { dst = (sbc_fixed_t) a * b; } -#define MULA(dst, a, b) { dst += (sbc_extended_t) a * b; } +#define MUL(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } +#define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } -- cgit From 3820937249249165f9ee41a74954dca81a843eeb Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 6 Oct 2007 00:01:51 +0000 Subject: clean out dead code --- sbc/sbc.c | 137 +++----------------------------------------------------------- 1 file changed, 5 insertions(+), 132 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c262f16d..a7f8888c 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -739,15 +739,9 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[13], in[29]); MULA(res, _sbc_proto_4[12], in[37]); t[5] = SCALE4_STAGE1(res); -#if 0 - /* don't compute... this term always multiplies with cos(pi) = 0*/ - MUL(res, _sbc_proto_4[11], in[6]); - MULA(res, _sbc_proto_4[10], in[14]); - MULA(res, _sbc_proto_4[9], in[22]); - MULA(res, _sbc_proto_4[8], in[30]); - MULA(res, _sbc_proto_4[7], in[38]); - t[6] = SCALE4_STAGE1(res); -#endif + + /* don't compute t[6]... this term always multiplies with cos(pi/2) = 0 */ + MUL(res, _sbc_proto_4[6], in[7]); MULA(res, _sbc_proto_4[5], in[15]); MULA(res, _sbc_proto_4[4], in[23]); @@ -755,55 +749,16 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[2], in[39]); t[7] = SCALE4_STAGE1(res); -#if 0 - MUL(res, _anamatrix4[0], t[0]); - MULA(res, _anamatrix4[1], t[1]); - MULA(res, _anamatrix4[2], t[2]); - MULA(res, _anamatrix4[1], t[3]); - MULA(res, _anamatrix4[0], t[4]); - MULA(res, _anamatrix4[3], t[5]); - MULA(res, -_anamatrix4[3], t[7]); - out[0] = SCALE4_STAGE2(res); // Q0 - - MUL(res, -_anamatrix4[0], t[0]); - MULA(res, _anamatrix4[3], t[1]); - MULA(res, _anamatrix4[2], t[2]); - MULA(res, _anamatrix4[3], t[3]); - MULA(res, -_anamatrix4[0], t[4]); - MULA(res, -_anamatrix4[1], t[5]); - MULA(res, _anamatrix4[1], t[7]); - out[1] = SCALE4_STAGE2(res); - - - MUL(res, -_anamatrix4[0], t[0]); - MULA(res, -_anamatrix4[3], t[1]); - MULA(res, _anamatrix4[2], t[2]); - MULA(res, -_anamatrix4[3], t[3]); - MULA(res, -_anamatrix4[0], t[4]); - MULA(res, _anamatrix4[1], t[5]); - MULA(res, -_anamatrix4[1], t[7]); - out[2] = SCALE4_STAGE2(res); - - MUL(res, _anamatrix4[0], t[0]); - MULA(res, -_anamatrix4[1], t[1]); - MULA(res, _anamatrix4[2], t[2]); - MULA(res, -_anamatrix4[1], t[3]); - MULA(res, _anamatrix4[0], t[4]); - MULA(res, -_anamatrix4[3], t[5]); - MULA(res, _anamatrix4[3], t[7]); - out[3] = SCALE4_STAGE2(res); -#else MUL(s[0], _anamatrix4[0], t[0] + t[4]); MUL(s[1], _anamatrix4[2], t[2]); MUL(s[2], _anamatrix4[1], t[1] + t[3]); MULA(s[2], _anamatrix4[3], t[5] + t[7]); MUL(s[3], _anamatrix4[3], t[1] + t[3]); MULA(s[3], _anamatrix4[1], - t[5] + t[7]); - out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); // Q0 out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2]); -#endif } static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) @@ -909,88 +864,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); -#if 0 - MUL(res, _anamatrix8[0], t[0]); // = Q14 * Q10 - MULA(res, _anamatrix8[7], t[1]); - MULA(res, _anamatrix8[2], t[2]); - MULA(res, _anamatrix8[3], t[3]); - MULA(res, _anamatrix8[6], t[4]); - MULA(res, _anamatrix8[4], t[5]); - MULA(res, _anamatrix8[1], t[6]); - MULA(res, _anamatrix8[5], t[7]); - out[0] = SCALE8_STAGE2(res); // Q0 - - MUL(res, _anamatrix8[1], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, _anamatrix8[3], t[2]); - MULA(res, -_anamatrix8[5], t[3]); - MULA(res, -_anamatrix8[6], t[4]); - MULA(res, -_anamatrix8[2], t[5]); - MULA(res, -_anamatrix8[0], t[6]); - MULA(res, -_anamatrix8[4], t[7]); - out[1] = SCALE8_STAGE2(res); - - MUL(res, -_anamatrix8[1], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, _anamatrix8[4], t[2]); - MULA(res, -_anamatrix8[2], t[3]); - MULA(res, -_anamatrix8[6], t[4]); - MULA(res, _anamatrix8[5], t[5]); - MULA(res, _anamatrix8[0], t[6]); - MULA(res, _anamatrix8[3], t[7]); - out[2] = SCALE8_STAGE2(res); - - MUL(res, -_anamatrix8[0], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, _anamatrix8[5], t[2]); - MULA(res, -_anamatrix8[4], t[3]); - MULA(res, _anamatrix8[6], t[4]); - MULA(res, _anamatrix8[3], t[5]); - MULA(res, -_anamatrix8[1], t[6]); - MULA(res, -_anamatrix8[2], t[7]); - out[3] = SCALE8_STAGE2(res); - - MUL(res, -_anamatrix8[0], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, -_anamatrix8[5], t[2]); - MULA(res, _anamatrix8[4], t[3]); - MULA(res, _anamatrix8[6], t[4]); - MULA(res, -_anamatrix8[3], t[5]); - MULA(res, -_anamatrix8[1], t[6]); - MULA(res, _anamatrix8[2], t[7]); - out[4] = SCALE8_STAGE2(res); - - MUL(res, -_anamatrix8[1], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, -_anamatrix8[4], t[2]); - MULA(res, _anamatrix8[2], t[3]); - MULA(res, -_anamatrix8[6], t[4]); - MULA(res, -_anamatrix8[5], t[5]); - MULA(res, _anamatrix8[0], t[6]); - MULA(res, -_anamatrix8[3], t[7]); - out[5] = SCALE8_STAGE2(res); - - MUL(res, _anamatrix8[1], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, -_anamatrix8[3], t[2]); - MULA(res, _anamatrix8[5], t[3]); - MULA(res, -_anamatrix8[6], t[4]); - MULA(res, _anamatrix8[2], t[5]); - MULA(res, -_anamatrix8[0], t[6]); - MULA(res, _anamatrix8[4], t[7]); - out[6] = SCALE8_STAGE2(res); - - MUL(res, _anamatrix8[0], t[0]); - MULA(res, _anamatrix8[7], t[1]); - MULA(res, -_anamatrix8[2], t[2]); - MULA(res, -_anamatrix8[3], t[3]); - MULA(res, _anamatrix8[6], t[4]); - MULA(res, -_anamatrix8[4], t[5]); - MULA(res, _anamatrix8[1], t[6]); - MULA(res, -_anamatrix8[5], t[7]); - out[7] = SCALE8_STAGE2(res); -#else - MUL(s[0], _anamatrix8[0], t[0]); + MUL(s[0], _anamatrix8[0], t[0]); // = Q14 * Q10 MULA(s[0], _anamatrix8[1], t[6]); MUL(s[1], _anamatrix8[7], t[1]); MUL(s[2], _anamatrix8[2], t[2]); @@ -1020,7 +894,6 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] + s[6]); out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]); out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]); -#endif } static inline void sbc_analyze_eight(struct sbc_encoder_state *state, -- cgit From 8fab528b8616b9a194dfe497ee9cc0fa455bab58 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 6 Oct 2007 00:34:35 +0000 Subject: a little more factoring --- sbc/sbc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a7f8888c..6fcf6e24 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -616,7 +616,7 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, k = (i + 4) & 0xf; SBC_FIXED_0(res); for(j = 0; j < 10; idx++) { - MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]); + MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]); MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_4_40m1[idx]); } /* Store in output */ @@ -727,10 +727,9 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[16], in[35]); t[3] = SCALE4_STAGE1(res); - MUL(res, _sbc_proto_4[17], in[4]); - MULA(res, _sbc_proto_4[18], (in[12] + in[28])); + MUL(res, _sbc_proto_4[17], in[4] + in[36]); + MULA(res, _sbc_proto_4[18], in[12] + in[28]); MULA(res, _sbc_proto_4[19], in[20]); - MULA(res, _sbc_proto_4[17], in[36]); t[4] = SCALE4_STAGE1(res); MUL(res, _sbc_proto_4[16], in[5]); @@ -841,10 +840,9 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, -_sbc_proto_8[16], in[77]); t[5] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[36], (in[8] + in[72])); - MULA(res, _sbc_proto_8[37], in[24]); + MUL(res, _sbc_proto_8[36], in[8] + in[72]); + MULA(res, _sbc_proto_8[37], in[24] + in[56]); MULA(res, _sbc_proto_8[38], in[40]); - MULA(res, _sbc_proto_8[37], in[56]); MULA(res, -_sbc_proto_8[39], in[12]); MULA(res, -_sbc_proto_8[5], in[28]); MULA(res, -_sbc_proto_8[4], in[44]); -- cgit From f06a303b02c9188efd7cb00c2cce19b14098874b Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Wed, 17 Oct 2007 07:36:25 +0000 Subject: 8-subband encoder had a sign error that made high frequencies noisy --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 6fcf6e24..94e5c752 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -889,7 +889,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]); out[3] = SCALE8_STAGE2(-s[0] + s[1] + s[3] + s[7]); out[4] = SCALE8_STAGE2(-s[0] + s[1] + s[3] - s[7]); - out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] + s[6]); + out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] - s[6]); out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]); out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]); } -- cgit From 5a3f10131eaeaa9336b8f8c501e0051a2ee69ec5 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 25 Oct 2007 02:25:34 +0000 Subject: Frederic's conformance tests it needs build system integration, including -lsndfile to link this app should compile only if libsndfile-dev is present 'make install' should ignore it --- sbc/sbctester.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 sbc/sbctester.c (limited to 'sbc') diff --git a/sbc/sbctester.c b/sbc/sbctester.c new file mode 100644 index 00000000..55ab28c0 --- /dev/null +++ b/sbc/sbctester.c @@ -0,0 +1,358 @@ +/* * + * Copyright (C) 2007 by Frederic Dalleau * + * fdalleau@free.fr * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +/* + +A2DP Test Specification Chapter 4.6 (p 25) +namely SBC codec conformance test +This is a test procedure for SBC + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#define MAXCHANNELS 2 +#define MAXFRAMESTESTED infostst->frames +#define TSTSAMPLEFACTOR(x) (x) +#define DEFACCURACY 7 + +/* temporary */ +#ifndef VERSION +#define VERSION "1" +#endif + +void usage() +{ + printf("SBC codec conformance test (see Chapter 4.6, p. 25) ver %s\n", VERSION); + printf("Copyright (c) 2007 Frederic Dalleau\n\n"); + + //printf("This is a mandatory test case, but alternative methods exists.\n\n"); + + printf("Usage:\n" + "\tsbctester reference.wav checkfile.wav\n" + "\tsbctester integer\n" + "\n"); + + printf("\tTo test the encoder:\n"); + printf("\tUse a reference codec to encode original.wav to reference.sbc\n"); + printf("\tUse sbcenc to encode original.wav to checkfile.sbc\n"); + printf("\tDecode both file using the reference decoder\n"); + printf("\trun sbctester with these two wav files to get the result\n"); + + printf("\n\tA file called out.csv is generated to use the data in a spreadsheet application or database.\n\n"); +} + +double sampletobits(short sample16, int verbose) +{ + double bits = 0; + int i; + unsigned short bit; + + if (verbose) + printf("=======> sampletobits(%hd, %04hX)\n", sample16, sample16); + + // Bit 0 is MSB + if (sample16 < 0) + bits = -1; + + if (verbose) + printf("%d", (sample16 < 0) ? 1 : 0); + + // Bit 15 is LSB + for (i = 1; i < 16; i++) { + bit = (unsigned short) sample16; + bit >>= 15 - i; + bit %= 2; + + if (verbose) + printf("%d", bit); + + if (bit) + bits += (1.0 / pow(2.0, i)); + } + + if (verbose) + printf("\n"); + return bits; +} + +int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy, char *csvname) +{ + int i, j, err = 0, verdict = 0; + short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; + double refbits, tstbits; + double rms; + double rms_accu[MAXCHANNELS]; + double rms_level[MAXCHANNELS]; + double rms_limit = 1.0 / (pow(2.0, accuracy - 1) * pow(12.0, 0.5)); + FILE *csv = NULL; + int r1, r2; + + if (csvname) + csv = fopen(csvname, "wt"); + + if (csv) { + fprintf(csv, "num;"); + for (j = 0; j < infostst->channels; j++) + fprintf(csv, "ref channel %d;tst channel %d;", j, j); + fprintf(csv, "\r\n"); + } + + sf_seek(sndref, 0, SEEK_SET); + sf_seek(sndtst, 0, SEEK_SET); + memset(rms_accu, 0, sizeof(rms_accu)); + memset(rms_level, 0, sizeof(rms_level)); + + for (i = 0; i < MAXFRAMESTESTED; i++) { + if (csv) + fprintf(csv, "%d;", i); + + r1 = sf_read_short(sndref, refsample, infostst->channels); + if (r1 != infostst->channels) { + printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); + err = -1; + goto error; + } + + r2 = sf_read_short(sndtst, tstsample, infostst->channels); + if (r2 != infostst->channels) { + printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); + err = -1; + goto error; + } + + for (j = 0; j < infostst->channels; j++) { + if (csv) + fprintf(csv, "%d;%d;", refsample[j], tstsample[j]); + + refbits = sampletobits(refsample[j], 0); + tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0); + + rms_accu[j] += pow(tstbits - refbits, 2.0); + } + + if (csv) + fprintf(csv, "\r\n"); + } + + printf("Limit: %f\n", rms_limit); + + for (j = 0; j < infostst->channels; j++) { + printf("Channel %d\n", j); + printf("Accumulated %f\n", rms_accu[j]); + rms_accu[j] /= (double) infostst->frames; + printf("Accumulated / %f = %f\n", (double) infostst->frames, rms_accu[j]); + rms_level[j] = sqrt(rms_accu[j]); + printf("Level = %f (%f x %f = %f)\n", rms_level[j], rms_level[j], rms_level[j], rms_level[j] * rms_level[j]); + } + + verdict = 1; + for (j = 0; j < infostst->channels; j++) { + printf("Channel %d: %f\n", j, rms_level[j]); + + if (rms_level[j] > rms_limit) + verdict = 0; + } + + printf("%s return %d\n", __FUNCTION__, verdict); + + + error: + + if (csv) + fclose(csv); + + return (err < 0) ? err : verdict; +} + +int check_sample() +{ + return 0; +} + +int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy) +{ + int i, j, err = 0, verdict = 0; + short refsample[MAXCHANNELS], tstsample[MAXCHANNELS], refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; + double refbits, tstbits; + double rms_absolute = 1.0 / (pow(2, accuracy - 2)); + double calc_max[MAXCHANNELS]; + int calc_count = 0; + short r1, r2; + double cur_diff; + + memset(&refmax, 0, sizeof(refmax)); + memset(&tstmax, 0, sizeof(tstmax)); + memset(&calc_max, 0, sizeof(calc_max)); + memset(&refsample, 0, sizeof(refsample)); + memset(&tstsample, 0, sizeof(tstsample)); + + verdict = 1; + sf_seek(sndref, 0, SEEK_SET); + sf_seek(sndtst, 0, SEEK_SET); + + printf("Absolute max: %f\n", rms_absolute); + for (i = 0; i < MAXFRAMESTESTED; i++) { + r1 = sf_read_short(sndref, refsample, infostst->channels); + + if (r1 != infostst->channels) { + printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); + err = -1; + goto error; + } + + r2 = sf_read_short(sndtst, tstsample, infostst->channels); + if (r2 != infostst->channels) { + printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); + err = -1; + goto error; + } + + for (j = 0; j < infostst->channels; j++) { + refbits = sampletobits(refsample[j], 0); + tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0); + + cur_diff = fabs(tstbits - refbits); + + if (cur_diff > rms_absolute) { + calc_count++; + //printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute); + verdict = 0; + } + if (cur_diff > calc_max[j]) { + calc_max[j] = cur_diff; + refmax[j] = refsample[j]; + tstmax[j] = tstsample[j]; + } + } + } + + for (j = 0; j < infostst->channels; j++) { + printf("Calculated max: %f (%hd-%hd=%hd)\n", calc_max[j], tstmax[j], refmax[j], tstmax[j] - refmax[j]); + } + + printf("%s return %d\n", __FUNCTION__, verdict); + + error: + + return (err < 0) ? err : verdict; +} + +int main(int argc, char *argv[]) +{ + int err = 0; + int rms_absolute, pass_rms, pass_absolute, pass, accuracy; + char *ref; + char *tst; + SNDFILE *sndref = NULL; + SNDFILE *sndtst = NULL; + SF_INFO infosref; + SF_INFO infostst; + + if (argc == 2) { + double db; + + printf("Test sampletobits\n"); + db = sampletobits((short) atoi(argv[1]), 1); + printf("db = %f\n", db); + exit(0); + } + + if (argc < 3) { + usage(); + exit(1); + } + + ref = argv[1]; + tst = argv[2]; + + // open both files + printf("opening reference %s\n", ref); + + sndref = sf_open(ref, SFM_READ, &infosref); + if (!sndref) { + printf("Failed to open reference file\n"); + err = -1; + goto error; + } + + printf("opening testfile %s\n", tst); + sndtst = sf_open(tst, SFM_READ, &infostst); + if (!sndtst) { + printf("Failed to open test file\n"); + err = -1; + goto error; + } + + printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int) infosref.frames, (int) infosref.samplerate, (int) infosref.channels); + printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int) infostst.frames, (int) infostst.samplerate, (int) infostst.channels); + + // check number of channels + if (infosref.channels > 2 || infostst.channels > 2) { + printf("Too many channels\n"); + err = -1; + goto error; + } + // compare number of samples + if (infosref.samplerate != infostst.samplerate || infosref.channels != infostst.channels) { + printf("Cannot compare files with different charasteristics\n"); + err = -1; + goto error; + } + + accuracy = DEFACCURACY; + printf("Accuracy: %d\n", accuracy); + + // Condition 1 rms level + pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst, accuracy, "out.csv"); + + if (pass_rms < 0) { + err = pass_rms; + goto error; + } + // Condition 2 absolute difference + pass_absolute = check_absolute_diff(sndref, &infosref, sndtst, &infostst, accuracy); + + if (pass_absolute < 0) { + err = pass_absolute; + goto error; + } + // Verdict + pass = pass_rms && pass_absolute; + printf("Verdict: %s\n", pass ? "pass" : "fail"); + + error: + + if (sndref) + sf_close(sndref); + + if (sndtst) + sf_close(sndtst); + + return err; +} -- cgit From a6b3daeb44d9b6f0d47fbe0cbfc6612c061352cd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 25 Oct 2007 10:51:03 +0000 Subject: First round of cleanups --- sbc/sbctester.c | 112 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 57 deletions(-) (limited to 'sbc') diff --git a/sbc/sbctester.c b/sbc/sbctester.c index 55ab28c0..0b35a335 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -1,30 +1,26 @@ -/* * - * Copyright (C) 2007 by Frederic Dalleau * - * fdalleau@free.fr * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program 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 General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - /* - -A2DP Test Specification Chapter 4.6 (p 25) -namely SBC codec conformance test -This is a test procedure for SBC - -*/ + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2007 Marcel Holtmann + * Copyright (C) 2007 Frederic Dalleau + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ #ifdef HAVE_CONFIG_H #include @@ -41,18 +37,11 @@ This is a test procedure for SBC #define TSTSAMPLEFACTOR(x) (x) #define DEFACCURACY 7 -/* temporary */ -#ifndef VERSION -#define VERSION "1" -#endif - -void usage() +static void usage() { - printf("SBC codec conformance test (see Chapter 4.6, p. 25) ver %s\n", VERSION); + printf("SBC conformance test ver %s\n", VERSION); printf("Copyright (c) 2007 Frederic Dalleau\n\n"); - //printf("This is a mandatory test case, but alternative methods exists.\n\n"); - printf("Usage:\n" "\tsbctester reference.wav checkfile.wav\n" "\tsbctester integer\n" @@ -67,7 +56,7 @@ void usage() printf("\n\tA file called out.csv is generated to use the data in a spreadsheet application or database.\n\n"); } -double sampletobits(short sample16, int verbose) +static double sampletobits(short sample16, int verbose) { double bits = 0; int i; @@ -98,10 +87,13 @@ double sampletobits(short sample16, int verbose) if (verbose) printf("\n"); + return bits; } -int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy, char *csvname) +static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, + SNDFILE * sndtst, SF_INFO * infostst, + int accuracy, char *csvname) { int i, j, err = 0, verdict = 0; short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; @@ -134,14 +126,16 @@ int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, r1 = sf_read_short(sndref, refsample, infostst->channels); if (r1 != infostst->channels) { - printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); + printf("Failed to read reference data: %s (r1=%d, channels=%d)", + sf_strerror(sndref), r1, infostst->channels); err = -1; goto error; } r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { - printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); + printf("Failed to read test data: %s (r2=%d, channels=%d)\n", + sf_strerror(sndtst), r2, infostst->channels); err = -1; goto error; } @@ -168,7 +162,8 @@ int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, rms_accu[j] /= (double) infostst->frames; printf("Accumulated / %f = %f\n", (double) infostst->frames, rms_accu[j]); rms_level[j] = sqrt(rms_accu[j]); - printf("Level = %f (%f x %f = %f)\n", rms_level[j], rms_level[j], rms_level[j], rms_level[j] * rms_level[j]); + printf("Level = %f (%f x %f = %f)\n", + rms_level[j], rms_level[j], rms_level[j], rms_level[j] * rms_level[j]); } verdict = 1; @@ -181,24 +176,24 @@ int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, printf("%s return %d\n", __FUNCTION__, verdict); - - error: - +error: if (csv) fclose(csv); return (err < 0) ? err : verdict; } -int check_sample() +static int check_sample() { return 0; } -int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy) +static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, + SNDFILE * sndtst, SF_INFO * infostst, int accuracy) { int i, j, err = 0, verdict = 0; - short refsample[MAXCHANNELS], tstsample[MAXCHANNELS], refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; + short refsample[MAXCHANNELS], tstsample[MAXCHANNELS], + short refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; double refbits, tstbits; double rms_absolute = 1.0 / (pow(2, accuracy - 2)); double calc_max[MAXCHANNELS]; @@ -221,14 +216,16 @@ int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, r1 = sf_read_short(sndref, refsample, infostst->channels); if (r1 != infostst->channels) { - printf("Failed to read reference data:%s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); + printf("Failed to read reference data: %s (r1=%d, channels=%d)", + sf_strerror(sndref), r1, infostst->channels); err = -1; goto error; } r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { - printf("Failed to read test data:%s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); + printf("Failed to read test data: %s (r2=%d, channels=%d)\n", + sf_strerror(sndtst), r2, infostst->channels); err = -1; goto error; } @@ -253,13 +250,13 @@ int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, } for (j = 0; j < infostst->channels; j++) { - printf("Calculated max: %f (%hd-%hd=%hd)\n", calc_max[j], tstmax[j], refmax[j], tstmax[j] - refmax[j]); + printf("Calculated max: %f (%hd-%hd=%hd)\n", + calc_max[j], tstmax[j], refmax[j], tstmax[j] - refmax[j]); } printf("%s return %d\n", __FUNCTION__, verdict); - error: - +error: return (err < 0) ? err : verdict; } @@ -291,7 +288,6 @@ int main(int argc, char *argv[]) ref = argv[1]; tst = argv[2]; - // open both files printf("opening reference %s\n", ref); sndref = sf_open(ref, SFM_READ, &infosref); @@ -309,8 +305,10 @@ int main(int argc, char *argv[]) goto error; } - printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int) infosref.frames, (int) infosref.samplerate, (int) infosref.channels); - printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", (int) infostst.frames, (int) infostst.samplerate, (int) infostst.channels); + printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", + (int) infosref.frames, (int) infosref.samplerate, (int) infosref.channels); + printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", + (int) infostst.frames, (int) infostst.samplerate, (int) infostst.channels); // check number of channels if (infosref.channels > 2 || infostst.channels > 2) { @@ -319,7 +317,8 @@ int main(int argc, char *argv[]) goto error; } // compare number of samples - if (infosref.samplerate != infostst.samplerate || infosref.channels != infostst.channels) { + if (infosref.samplerate != infostst.samplerate || + infosref.channels != infostst.channels) { printf("Cannot compare files with different charasteristics\n"); err = -1; goto error; @@ -346,8 +345,7 @@ int main(int argc, char *argv[]) pass = pass_rms && pass_absolute; printf("Verdict: %s\n", pass ? "pass" : "fail"); - error: - +error: if (sndref) sf_close(sndref); -- cgit From 582a5f9cca7f8ae1f41076c8c3bc9c3bae851b09 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 25 Oct 2007 11:06:39 +0000 Subject: Add build magic around sbctester program --- sbc/Makefile.am | 14 +++++++++++++- sbc/sbctester.c | 10 ++-------- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index 46cb30be..840fbfef 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,14 +1,26 @@ +if SNDFILE +sndfile_programs = sbctester +else +sndfile_programs = +endif + if SBC noinst_LTLIBRARIES = libsbc.la libsbc_la_SOURCES = sbc.h sbc.c sbc_math.h sbc_tables.h -noinst_PROGRAMS = sbcinfo sbcdec sbcenc +noinst_PROGRAMS = sbcinfo sbcdec sbcenc $(sndfile_programs) sbcdec_LDADD = libsbc.la sbcenc_LDADD = libsbc.la + +if SNDFILE +sbctester_LDADD = @SNDFILE_LIBS@ endif +endif + +AM_CFLAGS = @SNDFILE_CFLAGS@ MAINTAINERCLEANFILES = Makefile.in diff --git a/sbc/sbctester.c b/sbc/sbctester.c index 0b35a335..9d719e2e 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -98,7 +98,6 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, int i, j, err = 0, verdict = 0; short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; double refbits, tstbits; - double rms; double rms_accu[MAXCHANNELS]; double rms_level[MAXCHANNELS]; double rms_limit = 1.0 / (pow(2.0, accuracy - 1) * pow(12.0, 0.5)); @@ -183,16 +182,11 @@ error: return (err < 0) ? err : verdict; } -static int check_sample() -{ - return 0; -} - static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy) { int i, j, err = 0, verdict = 0; - short refsample[MAXCHANNELS], tstsample[MAXCHANNELS], + short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; short refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; double refbits, tstbits; double rms_absolute = 1.0 / (pow(2, accuracy - 2)); @@ -263,7 +257,7 @@ error: int main(int argc, char *argv[]) { int err = 0; - int rms_absolute, pass_rms, pass_absolute, pass, accuracy; + int pass_rms, pass_absolute, pass, accuracy; char *ref; char *tst; SNDFILE *sndref = NULL; -- cgit From 15b172d3ff3e3968b0383ae50e32e9868067791c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 25 Oct 2007 12:38:01 +0000 Subject: More cleanups --- sbc/sbctester.c | 94 ++++++++++++++++++++++++++------------------------------- 1 file changed, 42 insertions(+), 52 deletions(-) (limited to 'sbc') diff --git a/sbc/sbctester.c b/sbc/sbctester.c index 9d719e2e..f85d0bac 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -33,13 +33,12 @@ #include #define MAXCHANNELS 2 -#define MAXFRAMESTESTED infostst->frames -#define TSTSAMPLEFACTOR(x) (x) #define DEFACCURACY 7 static void usage() { printf("SBC conformance test ver %s\n", VERSION); + printf("Copyright (c) 2007 Marcel Holtmann\n\n"); printf("Copyright (c) 2007 Frederic Dalleau\n\n"); printf("Usage:\n" @@ -59,11 +58,11 @@ static void usage() static double sampletobits(short sample16, int verbose) { double bits = 0; - int i; unsigned short bit; + int i; if (verbose) - printf("=======> sampletobits(%hd, %04hX)\n", sample16, sample16); + printf("===> sampletobits(%hd, %04hX)\n", sample16, sample16); // Bit 0 is MSB if (sample16 < 0) @@ -95,14 +94,13 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy, char *csvname) { - int i, j, err = 0, verdict = 0; short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; double refbits, tstbits; double rms_accu[MAXCHANNELS]; double rms_level[MAXCHANNELS]; double rms_limit = 1.0 / (pow(2.0, accuracy - 1) * pow(12.0, 0.5)); FILE *csv = NULL; - int r1, r2; + int i, j, r1, r2, verdict; if (csvname) csv = fopen(csvname, "wt"); @@ -116,10 +114,11 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, sf_seek(sndref, 0, SEEK_SET); sf_seek(sndtst, 0, SEEK_SET); + memset(rms_accu, 0, sizeof(rms_accu)); memset(rms_level, 0, sizeof(rms_level)); - for (i = 0; i < MAXFRAMESTESTED; i++) { + for (i = 0; i < infostst->frames; i++) { if (csv) fprintf(csv, "%d;", i); @@ -127,16 +126,18 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, if (r1 != infostst->channels) { printf("Failed to read reference data: %s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); - err = -1; - goto error; + if (csv) + fclose(csv); + return -1; } r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { printf("Failed to read test data: %s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); - err = -1; - goto error; + if (csv) + fclose(csv); + return -1; } for (j = 0; j < infostst->channels; j++) { @@ -144,7 +145,7 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, fprintf(csv, "%d;%d;", refsample[j], tstsample[j]); refbits = sampletobits(refsample[j], 0); - tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0); + tstbits = sampletobits(tstsample[j], 0); rms_accu[j] += pow(tstbits - refbits, 2.0); } @@ -162,10 +163,12 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, printf("Accumulated / %f = %f\n", (double) infostst->frames, rms_accu[j]); rms_level[j] = sqrt(rms_accu[j]); printf("Level = %f (%f x %f = %f)\n", - rms_level[j], rms_level[j], rms_level[j], rms_level[j] * rms_level[j]); + rms_level[j], rms_level[j], rms_level[j], + rms_level[j] * rms_level[j]); } verdict = 1; + for (j = 0; j < infostst->channels; j++) { printf("Channel %d: %f\n", j, rms_level[j]); @@ -175,17 +178,12 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, printf("%s return %d\n", __FUNCTION__, verdict); -error: - if (csv) - fclose(csv); - - return (err < 0) ? err : verdict; + return verdict; } static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, SNDFILE * sndtst, SF_INFO * infostst, int accuracy) { - int i, j, err = 0, verdict = 0; short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; short refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; double refbits, tstbits; @@ -194,6 +192,7 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, int calc_count = 0; short r1, r2; double cur_diff; + int i, j, verdict; memset(&refmax, 0, sizeof(refmax)); memset(&tstmax, 0, sizeof(tstmax)); @@ -201,32 +200,31 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, memset(&refsample, 0, sizeof(refsample)); memset(&tstsample, 0, sizeof(tstsample)); - verdict = 1; sf_seek(sndref, 0, SEEK_SET); sf_seek(sndtst, 0, SEEK_SET); + verdict = 1; + printf("Absolute max: %f\n", rms_absolute); - for (i = 0; i < MAXFRAMESTESTED; i++) { + for (i = 0; i < infostst->frames; i++) { r1 = sf_read_short(sndref, refsample, infostst->channels); if (r1 != infostst->channels) { printf("Failed to read reference data: %s (r1=%d, channels=%d)", sf_strerror(sndref), r1, infostst->channels); - err = -1; - goto error; + return -1; } r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { printf("Failed to read test data: %s (r2=%d, channels=%d)\n", sf_strerror(sndtst), r2, infostst->channels); - err = -1; - goto error; + return -1; } for (j = 0; j < infostst->channels; j++) { refbits = sampletobits(refsample[j], 0); - tstbits = sampletobits(TSTSAMPLEFACTOR(tstsample[j]), 0); + tstbits = sampletobits(tstsample[j], 0); cur_diff = fabs(tstbits - refbits); @@ -235,6 +233,7 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, //printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute); verdict = 0; } + if (cur_diff > calc_max[j]) { calc_max[j] = cur_diff; refmax[j] = refsample[j]; @@ -250,20 +249,18 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, printf("%s return %d\n", __FUNCTION__, verdict); -error: - return (err < 0) ? err : verdict; + return verdict; } int main(int argc, char *argv[]) { - int err = 0; - int pass_rms, pass_absolute, pass, accuracy; - char *ref; - char *tst; SNDFILE *sndref = NULL; SNDFILE *sndtst = NULL; SF_INFO infosref; SF_INFO infostst; + char *ref; + char *tst; + int pass_rms, pass_absolute, pass, accuracy; if (argc == 2) { double db; @@ -287,16 +284,15 @@ int main(int argc, char *argv[]) sndref = sf_open(ref, SFM_READ, &infosref); if (!sndref) { printf("Failed to open reference file\n"); - err = -1; - goto error; + exit(1); } printf("opening testfile %s\n", tst); sndtst = sf_open(tst, SFM_READ, &infostst); if (!sndtst) { printf("Failed to open test file\n"); - err = -1; - goto error; + sf_close(sndref); + exit(1); } printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", @@ -307,14 +303,13 @@ int main(int argc, char *argv[]) // check number of channels if (infosref.channels > 2 || infostst.channels > 2) { printf("Too many channels\n"); - err = -1; goto error; } + // compare number of samples if (infosref.samplerate != infostst.samplerate || infosref.channels != infostst.channels) { printf("Cannot compare files with different charasteristics\n"); - err = -1; goto error; } @@ -323,28 +318,23 @@ int main(int argc, char *argv[]) // Condition 1 rms level pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst, accuracy, "out.csv"); - - if (pass_rms < 0) { - err = pass_rms; + if (pass_rms < 0) goto error; - } + // Condition 2 absolute difference pass_absolute = check_absolute_diff(sndref, &infosref, sndtst, &infostst, accuracy); - - if (pass_absolute < 0) { - err = pass_absolute; + if (pass_absolute < 0) goto error; - } + // Verdict pass = pass_rms && pass_absolute; printf("Verdict: %s\n", pass ? "pass" : "fail"); -error: - if (sndref) - sf_close(sndref); + return 0; - if (sndtst) - sf_close(sndtst); +error: + sf_close(sndref); + sf_close(sndtst); - return err; + exit(1); } -- cgit From 221a91a439f128912f6989d13ddf9926ad0a1572 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 25 Oct 2007 12:41:13 +0000 Subject: Move the usage function around --- sbc/sbctester.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'sbc') diff --git a/sbc/sbctester.c b/sbc/sbctester.c index f85d0bac..15e63c2a 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -35,26 +35,6 @@ #define MAXCHANNELS 2 #define DEFACCURACY 7 -static void usage() -{ - printf("SBC conformance test ver %s\n", VERSION); - printf("Copyright (c) 2007 Marcel Holtmann\n\n"); - printf("Copyright (c) 2007 Frederic Dalleau\n\n"); - - printf("Usage:\n" - "\tsbctester reference.wav checkfile.wav\n" - "\tsbctester integer\n" - "\n"); - - printf("\tTo test the encoder:\n"); - printf("\tUse a reference codec to encode original.wav to reference.sbc\n"); - printf("\tUse sbcenc to encode original.wav to checkfile.sbc\n"); - printf("\tDecode both file using the reference decoder\n"); - printf("\trun sbctester with these two wav files to get the result\n"); - - printf("\n\tA file called out.csv is generated to use the data in a spreadsheet application or database.\n\n"); -} - static double sampletobits(short sample16, int verbose) { double bits = 0; @@ -252,6 +232,27 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, return verdict; } +static void usage() +{ + printf("SBC conformance test ver %s\n", VERSION); + printf("Copyright (c) 2007 Marcel Holtmann\n"); + printf("Copyright (c) 2007 Frederic Dalleau\n\n"); + + printf("Usage:\n" + "\tsbctester reference.wav checkfile.wav\n" + "\tsbctester integer\n" + "\n"); + + printf("To test the encoder:\n"); + printf("\tUse a reference codec to encode original.wav to reference.sbc\n"); + printf("\tUse sbcenc to encode original.wav to checkfile.sbc\n"); + printf("\tDecode both file using the reference decoder\n"); + printf("\tRun sbctester with these two wav files to get the result\n\n"); + + printf("\tA file called out.csv is generated to use the data in a\n"); + printf("\tspreadsheet application or database.\n\n"); +} + int main(int argc, char *argv[]) { SNDFILE *sndref = NULL; -- cgit From 9138f99acb799d7ce702afb357c134042f933f4b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 1 Nov 2007 15:27:38 +0000 Subject: Coding style cleanup --- sbc/sbc.c | 297 ++++++++++++++++++++++++++++++-------------------------- sbc/sbcdec.c | 36 ++++--- sbc/sbcenc.c | 3 +- sbc/sbcinfo.c | 14 ++- sbc/sbctester.c | 64 +++++++----- 5 files changed, 229 insertions(+), 185 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 94e5c752..3e65603d 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -25,9 +25,9 @@ /* todo items: - use a log2 table for byte integer scale factors calculation (sum log2 results for high and low bytes) - fill bitpool by 16 bits instead of one at a time in bits allocation/bitpool generation - port to the dsp + use a log2 table for byte integer scale factors calculation (sum log2 results + for high and low bytes) fill bitpool by 16 bits instead of one at a time in + bits allocation/bitpool generation port to the dsp */ @@ -77,7 +77,7 @@ #define SBC_SB_4 0x00 #define SBC_SB_8 0x01 -/* This structure contains an unpacked SBC frame. +/* This structure contains an unpacked SBC frame. Yes, there is probably quite some unused space herein */ struct sbc_frame { uint16_t sampling_frequency; /* in kHz */ @@ -95,13 +95,19 @@ struct sbc_frame { } allocation_method; uint8_t subbands; uint8_t bitpool; - uint8_t join; /* bit number x set means joint stereo has been used in subband x */ - uint8_t scale_factor[2][8]; /* only the lower 4 bits of every element are to be used */ - uint16_t audio_sample[16][2][8]; /* raw integer subband samples in the frame */ + + /* bit number x set means joint stereo has been used in subband x */ + uint8_t join; + + /* only the lower 4 bits of every element are to be used */ + uint8_t scale_factor[2][8]; + + /* raw integer subband samples in the frame */ + uint16_t audio_sample[16][2][8]; int32_t sb_sample_f[16][2][8]; - int32_t sb_sample[16][2][8]; /* modified subband samples */ - int16_t pcm_sample[2][16*8]; /* original pcm audio samples */ + int32_t sb_sample[16][2][8]; /* modified subband samples */ + int16_t pcm_sample[2][16*8]; /* original pcm audio samples */ }; struct sbc_decoder_state { @@ -175,8 +181,9 @@ static uint8_t sbc_crc8(const uint8_t * data, size_t len) } /* - * Code straight from the spec to calculate the bits array - * Takes a pointer to the frame in question, a pointer to the bits array and the sampling frequency (as 2 bit integer) + * Code straight from the spec to calculate the bits array + * Takes a pointer to the frame in question, a pointer to the bits array and + * the sampling frequency (as 2 bit integer) */ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], uint8_t sf) { @@ -186,24 +193,21 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui for (ch = 0; ch < frame->channels; ch++) { if (frame->allocation_method == SNR) { - for (sb = 0; sb < frame->subbands; sb++) { + for (sb = 0; sb < frame->subbands; sb++) bitneed[ch][sb] = frame->scale_factor[ch][sb]; - } } else { for (sb = 0; sb < frame->subbands; sb++) { - if (frame->scale_factor[ch][sb] == 0) { + if (frame->scale_factor[ch][sb] == 0) bitneed[ch][sb] = -5; - } else { - if (frame->subbands == 4) { + else { + if (frame->subbands == 4) loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; - } else { + else loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; - } - if (loudness > 0) { + if (loudness > 0) bitneed[ch][sb] = loudness / 2; - } else { + else bitneed[ch][sb] = loudness; - } } } } @@ -222,11 +226,10 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui bitcount += slicecount; slicecount = 0; for (sb = 0; sb < frame->subbands; sb++) { - if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) slicecount++; - } else if (bitneed[ch][sb] == bitslice + 1) { + else if (bitneed[ch][sb] == bitslice + 1) slicecount += 2; - } } } while (bitcount + slicecount < frame->bitpool); @@ -236,9 +239,9 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui } for (sb = 0; sb < frame->subbands; sb++) { - if (bitneed[ch][sb] < bitslice + 2) { + if (bitneed[ch][sb] < bitslice + 2) bits[ch][sb] = 0; - } else { + else { bits[ch][sb] = bitneed[ch][sb] - bitslice; if (bits[ch][sb] > 16) bits[ch][sb] = 16; @@ -274,26 +277,23 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui if (frame->allocation_method == SNR) { for (ch = 0; ch < 2; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { + for (sb = 0; sb < frame->subbands; sb++) bitneed[ch][sb] = frame->scale_factor[ch][sb]; - } } } else { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { - if (frame->scale_factor[ch][sb] == 0) { + if (frame->scale_factor[ch][sb] == 0) bitneed[ch][sb] = -5; - } else { - if (frame->subbands == 4) { + else { + if (frame->subbands == 4) loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; - } else { + else loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; - } - if (loudness > 0) { + if (loudness > 0) bitneed[ch][sb] = loudness / 2; - } else { + else bitneed[ch][sb] = loudness; - } } } } @@ -316,11 +316,10 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui slicecount = 0; for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { - if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) { + if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) slicecount++; - } else if (bitneed[ch][sb] == bitslice + 1) { + else if (bitneed[ch][sb] == bitslice + 1) slicecount += 2; - } } } } while (bitcount + slicecount < frame->bitpool); @@ -354,9 +353,8 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui if (ch == 1) { ch = 0; sb++; - } else { + } else ch = 1; - } } ch = 0; @@ -369,16 +367,15 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui if (ch == 1) { ch = 0; sb++; - } else { + } else ch = 1; - } } } } -/* +/* * Unpacks a SBC frame at the beginning of the stream in data, * which has at most len bytes into frame. * Returns the length in bytes of the packed frame, or a negative @@ -389,17 +386,21 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui * -3 CRC8 incorrect * -4 Bitpool value out of bounds */ -static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_t len) +static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, + size_t len) { int consumed; - /* Will copy the parts of the header that are relevant to crc calculation here */ + /* Will copy the parts of the header that are relevant to crc + * calculation here */ uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int crc_pos = 0; int32_t temp; - uint8_t sf; /* sampling_frequency, temporarily needed as array index */ + uint8_t sf; /* sampling_frequency, temporarily needed as + array index */ - int ch, sb, blk, bit; /* channel, subband, block and bit standard counters */ + int ch, sb, blk, bit; /* channel, subband, block and bit standard + counters */ int bits[2][8]; /* bits distribution */ int levels[2][8]; /* levels derived from that */ @@ -458,10 +459,12 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ frame->bitpool = data[2]; - if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) - && frame->bitpool > 16 * frame->subbands) - || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) - && frame->bitpool > 32 * frame->subbands)) + if (((frame->channel_mode == MONO || + frame->channel_mode == DUAL_CHANNEL) && + frame->bitpool > 16 * frame->subbands) || + ((frame->channel_mode == STEREO || + frame->channel_mode == JOINT_STEREO) && + frame->bitpool > 32 * frame->subbands)) return -4; /* data[3] is crc, we're checking it later */ @@ -477,14 +480,12 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ return -1; frame->join = 0x00; - for (sb = 0; sb < frame->subbands - 1; sb++) { + for (sb = 0; sb < frame->subbands - 1; sb++) frame->join |= ((data[4] >> (7 - sb)) & 0x01) << sb; - } - if (frame->subbands == 4) { + if (frame->subbands == 4) crc_header[crc_pos / 8] = data[4] & 0xf0; - } else { + else crc_header[crc_pos / 8] = data[4]; - } consumed += frame->subbands; crc_pos += frame->subbands; @@ -496,8 +497,10 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { /* FIXME assert(consumed % 4 == 0); */ - frame->scale_factor[ch][sb] = (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F; - crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7)); + frame->scale_factor[ch][sb] = + (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F; + crc_header[crc_pos >> 3] |= + frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7)); consumed += 4; crc_pos += 4; @@ -522,7 +525,8 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ return -1; b = (data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01; - frame->audio_sample[blk][ch][sb] |= b << (bits[ch][sb] - bit - 1); + frame->audio_sample[blk][ch][sb] |= + b << (bits[ch][sb] - bit - 1); consumed++; } @@ -531,24 +535,27 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ } for (ch = 0; ch < frame->channels; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { + for (sb = 0; sb < frame->subbands; sb++) levels[ch][sb] = (1 << bits[ch][sb]) - 1; - } } for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (levels[ch][sb] > 0) { - frame->sb_sample[blk][ch][sb] = - (((frame->audio_sample[blk][ch][sb] << 16) | 0x8000) / levels[ch][sb]) - 0x8000; + frame->sb_sample[blk][ch][sb] = + (((frame->audio_sample[blk][ch][sb] << 16) | 0x8000) / + levels[ch][sb]) - 0x8000; frame->sb_sample[blk][ch][sb] >>= 3; - frame->sb_sample[blk][ch][sb] = (frame->sb_sample[blk][ch][sb] << (frame->scale_factor[ch][sb] + 1)); // Q13 - } else { + /* Q13 */ + frame->sb_sample[blk][ch][sb] = + (frame->sb_sample[blk][ch][sb] << + (frame->scale_factor[ch][sb] + 1)); + + } else frame->sb_sample[blk][ch][sb] = 0; - } } } } @@ -557,8 +564,11 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ for (blk = 0; blk < frame->blocks; blk++) { for (sb = 0; sb < frame->subbands; sb++) { if (frame->join & (0x01 << sb)) { - temp = frame->sb_sample[blk][0][sb] + frame->sb_sample[blk][1][sb]; - frame->sb_sample[blk][1][sb] = frame->sb_sample[blk][0][sb] - frame->sb_sample[blk][1][sb]; + temp = frame->sb_sample[blk][0][sb] + + frame->sb_sample[blk][1][sb]; + frame->sb_sample[blk][1][sb] = + frame->sb_sample[blk][0][sb] - + frame->sb_sample[blk][1][sb]; frame->sb_sample[blk][0][sb] = temp; } } @@ -568,11 +578,11 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, size_ if ((consumed & 0x7) != 0) consumed += 8 - (consumed & 0x7); - return consumed >> 3; } -static void sbc_decoder_init(struct sbc_decoder_state *state, const struct sbc_frame *frame) +static void sbc_decoder_init(struct sbc_decoder_state *state, + const struct sbc_frame *frame) { int i, ch; @@ -595,19 +605,16 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, state->offset[ch][i]--; if (state->offset[ch][i] < 0) { state->offset[ch][i] = 79; - for(j = 0; j < 9; j++) { + for(j = 0; j < 9; j++) state->V[ch][j+80] = state->V[ch][j]; - } } } - for(i = 0; i < 8; i++) { /* Distribute the new matrix value to the shifted position */ SBC_FIXED_0(res); - for (j = 0; j < 4; j++) { + for (j = 0; j < 4; j++) MULA(res, synmatrix4[i][j], frame->sb_sample[blk][ch][j]); - } state->V[ch][state->offset[ch][i]] = SCALE4_STAGED1(res); } @@ -616,11 +623,14 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, k = (i + 4) & 0xf; SBC_FIXED_0(res); for(j = 0; j < 10; idx++) { - MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]); - MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_4_40m1[idx]); + MULA(res, state->V[ch][state->offset[ch][i]+j++], + sbc_proto_4_40m0[idx]); + MULA(res, state->V[ch][state->offset[ch][k]+j++], + sbc_proto_4_40m1[idx]); } - /* Store in output */ - frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(res); // Q0 + + /* Store in output, Q0 */ + frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(res); } } @@ -635,9 +645,8 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, state->offset[ch][i]--; if (state->offset[ch][i] < 0) { state->offset[ch][i] = 159; - for(j = 0; j < 9; j++) { - state->V[ch][j+160] = state->V[ch][j]; - } + for(j = 0; j < 9; j++) + state->V[ch][j+160] = state->V[ch][j]; } } @@ -645,11 +654,12 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, /* Distribute the new matrix value to the shifted position */ SBC_FIXED_0(res); for (j = 0; j < 8; j++) { - MULA(res, synmatrix8[i][j], frame->sb_sample[blk][ch][j]); // Q28 = Q15 * Q13 + /* Q28 = Q15 * Q13 */ + MULA(res, synmatrix8[i][j], frame->sb_sample[blk][ch][j]); } - state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); // Q10 + /* Q10 */ + state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); } - /* Compute the samples */ for(idx = 0, i = 0; i < 8; i++) { @@ -665,10 +675,11 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, } } -static int sbc_synthesize_audio(struct sbc_decoder_state *state, struct sbc_frame *frame) +static int sbc_synthesize_audio(struct sbc_decoder_state *state, + struct sbc_frame *frame) { int ch, blk; - + switch (frame->subbands) { case 4: for (ch = 0; ch < frame->channels; ch++) { @@ -689,7 +700,8 @@ static int sbc_synthesize_audio(struct sbc_decoder_state *state, struct sbc_fram } } -static void sbc_encoder_init(struct sbc_encoder_state *state, const struct sbc_frame *frame) +static void sbc_encoder_init(struct sbc_encoder_state *state, + const struct sbc_frame *frame) { memset(&state->X, 0, sizeof(state->X)); state->subbands = frame->subbands; @@ -702,9 +714,9 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) sbc_extended_t t[8]; sbc_extended_t s[4]; - MUL(res, _sbc_proto_4[0], (in[8] - in[32])); // Q18 + MUL(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ MULA(res, _sbc_proto_4[1], (in[16] - in[24])); - t[0] = SCALE4_STAGE1(res); // Q8 + t[0] = SCALE4_STAGE1(res); /* Q8 */ MUL(res, _sbc_proto_4[2], in[1]); MULA(res, _sbc_proto_4[3], in[9]); @@ -739,7 +751,8 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(res, _sbc_proto_4[12], in[37]); t[5] = SCALE4_STAGE1(res); - /* don't compute t[6]... this term always multiplies with cos(pi/2) = 0 */ + /* don't compute t[6]... this term always multiplies + * with cos(pi/2) = 0 */ MUL(res, _sbc_proto_4[6], in[7]); MULA(res, _sbc_proto_4[5], in[15]); @@ -754,7 +767,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MULA(s[2], _anamatrix4[3], t[5] + t[7]); MUL(s[3], _anamatrix4[3], t[1] + t[3]); MULA(s[3], _anamatrix4[1], - t[5] + t[7]); - out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); // Q0 + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); /* Q0 */ out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2]); @@ -776,14 +789,14 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; sbc_extended_t s[8]; - - MUL(res, _sbc_proto_8[0], (in[16] - in[64])); // Q18 = Q18 * Q0 + + MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ MULA(res, _sbc_proto_8[1], (in[32] - in[48])); MULA(res, _sbc_proto_8[2], in[4]); MULA(res, _sbc_proto_8[3], in[20]); MULA(res, _sbc_proto_8[4], in[36]); MULA(res, _sbc_proto_8[5], in[52]); - t[0] = SCALE8_STAGE1(res); // Q10 + t[0] = SCALE8_STAGE1(res); /* Q10 */ MUL(res, _sbc_proto_8[6], in[2]); MULA(res, _sbc_proto_8[7], in[18]); @@ -862,7 +875,7 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); - MUL(s[0], _anamatrix8[0], t[0]); // = Q14 * Q10 + MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ MULA(s[0], _anamatrix8[1], t[6]); MUL(s[1], _anamatrix8[7], t[1]); MUL(s[2], _anamatrix8[2], t[2]); @@ -895,7 +908,8 @@ static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) } static inline void sbc_analyze_eight(struct sbc_encoder_state *state, - struct sbc_frame *frame, int ch, int blk) + struct sbc_frame *frame, int ch, + int blk) { int i; @@ -907,23 +921,22 @@ static inline void sbc_analyze_eight(struct sbc_encoder_state *state, _sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]); } -static int sbc_analyze_audio(struct sbc_encoder_state *state, struct sbc_frame *frame) +static int sbc_analyze_audio(struct sbc_encoder_state *state, + struct sbc_frame *frame) { int ch, blk; switch (frame->subbands) { case 4: for (ch = 0; ch < frame->channels; ch++) - for (blk = 0; blk < frame->blocks; blk++) { + for (blk = 0; blk < frame->blocks; blk++) sbc_analyze_four(state, frame, ch, blk); - } return frame->blocks * 4; case 8: for (ch = 0; ch < frame->channels; ch++) - for (blk = 0; blk < frame->blocks; blk++) { + for (blk = 0; blk < frame->blocks; blk++) sbc_analyze_eight(state, frame, ch, blk); - } return frame->blocks * 8; default: @@ -933,9 +946,9 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state, struct sbc_frame * /* * Packs the SBC frame from frame into the memory at data. At most len - * bytes will be used, should more memory be needed an appropriate + * bytes will be used, should more memory be needed an appropriate * error code will be returned. Returns the length of the packed frame - * on success or a negative value on error. + * on success or a negative value on error. * * The error codes are: * -1 Not enough memory reserved @@ -953,7 +966,8 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int crc_pos = 0; - uint8_t sf; /* Sampling frequency as temporary value for table lookup */ + /* Sampling frequency as temporary value for table lookup */ + uint8_t sf; int ch, sb, blk, bit; /* channel, subband, block and bit counters */ int bits[2][8]; /* bits distribution */ @@ -965,7 +979,8 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) return -1; } - /* Clear first 4 bytes of data (that's the constant length part of the SBC header) */ + /* Clear first 4 bytes of data (that's the constant length part of the + * SBC header) */ memset(data, 0, 4); data[0] = SBC_SYNCWORD; @@ -1021,12 +1036,13 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) } data[2] = frame->bitpool; - if (((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) - && frame->bitpool > 16 * frame->subbands) - || ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) - && frame->bitpool > 32 * frame->subbands)) { + if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && + frame->bitpool > 16 * frame->subbands) + return -5; + + if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && + frame->bitpool > 32 * frame->subbands) return -5; - } /* Can't fill in crc yet */ @@ -1050,14 +1066,20 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) } if (frame->channel_mode == JOINT_STEREO) { - int32_t sb_sample_j[16][2][7]; /* like frame->sb_sample but joint stereo */ - int scalefactor_j[2][7], scale_factor_j[2][7]; /* scalefactor and scale_factor in joint case */ + /* like frame->sb_sample but joint stereo */ + int32_t sb_sample_j[16][2][7]; + /* scalefactor and scale_factor in joint case */ + int scalefactor_j[2][7], scale_factor_j[2][7]; /* Calculate joint stereo signal */ for (sb = 0; sb < frame->subbands - 1; sb++) { for (blk = 0; blk < frame->blocks; blk++) { - sb_sample_j[blk][0][sb] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) >> 1; - sb_sample_j[blk][1][sb] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) >> 1; + sb_sample_j[blk][0][sb] = + (frame->sb_sample_f[blk][0][sb] + + frame->sb_sample_f[blk][1][sb]) >> 1; + sb_sample_j[blk][1][sb] = + (frame->sb_sample_f[blk][0][sb] - + frame->sb_sample_f[blk][1][sb]) >> 1; } } @@ -1087,8 +1109,10 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) scalefactor[0][sb] = scalefactor_j[0][sb]; scalefactor[1][sb] = scalefactor_j[1][sb]; for (blk = 0; blk < frame->blocks; blk++) { - frame->sb_sample_f[blk][0][sb] = sb_sample_j[blk][0][sb]; - frame->sb_sample_f[blk][1][sb] = sb_sample_j[blk][1][sb]; + frame->sb_sample_f[blk][0][sb] = + sb_sample_j[blk][0][sb]; + frame->sb_sample_f[blk][1][sb] = + sb_sample_j[blk][1][sb]; } } } @@ -1097,15 +1121,13 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) return -1; data[4] = 0; - for (sb = 0; sb < frame->subbands - 1; sb++) { + for (sb = 0; sb < frame->subbands - 1; sb++) data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb); - } - if (frame->subbands == 4) { + if (frame->subbands == 4) crc_header[crc_pos / 8] = data[4] & 0xf0; - } else { + else crc_header[crc_pos / 8] = data[4]; - } - + produced += frame->subbands; crc_pos += frame->subbands; } @@ -1130,21 +1152,20 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) sbc_calculate_bits(frame, bits, sf); for (ch = 0; ch < frame->channels; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { + for (sb = 0; sb < frame->subbands; sb++) levels[ch][sb] = (1 << bits[ch][sb]) - 1; - } } for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { - if (levels[ch][sb] > 0) { + if (levels[ch][sb] > 0) frame->audio_sample[blk][ch][sb] = - (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + - levels[ch][sb]) >> 1); - } else { + (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> + (frame->scale_factor[ch][sb] + 1)) + + levels[ch][sb]) >> 1); + else frame->audio_sample[blk][ch][sb] = 0; - } } } } @@ -1155,14 +1176,12 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) if (bits[ch][sb] != 0) { for (bit = 0; bit < bits[ch][sb]; bit++) { int b; /* A bit */ - if (produced > len * 8) { + if (produced > len * 8) return -1; - } - if (produced % 8 == 0) { + if (produced % 8 == 0) data[produced / 8] = 0; - } - b = ((frame->audio_sample[blk][ch][sb]) >> (bits[ch][sb] - bit - - 1)) & 0x01; + b = ((frame->audio_sample[blk][ch][sb]) >> + (bits[ch][sb] - bit - 1)) & 0x01; data[produced / 8] |= b << (7 - (produced % 8)); produced++; } @@ -1171,9 +1190,8 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) } } - if (produced % 8 != 0) { + if (produced % 8 != 0) produced += 8 - (produced % 8); - } return produced / 8; } @@ -1226,7 +1244,6 @@ int sbc_decode(sbc_t *sbc, void *data, int count) priv = sbc->priv; framelen = sbc_unpack_frame(data, &priv->frame, count); - if (!priv->init) { sbc_decoder_init(&priv->dec_state, &priv->frame); diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index ebf9ae7c..866b8448 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,8 @@ static void decode(char *filename, char *output, int tofile) struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, written, format = AFMT_S16_BE; + int fd, ad, pos, streamlen, framelen, count, written; + int format = AFMT_S16_BE; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", @@ -101,48 +102,53 @@ static void decode(char *filename, char *output, int tofile) if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { fprintf(stderr, "Can't set audio format on %s: %s\n", - output, strerror(errno)); + output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_CHANNELS, &sbc.channels) < 0) { - fprintf(stderr, "Can't set number of channels on %s: %s\n", - output, strerror(errno)); + fprintf(stderr, + "Can't set number of channels on %s: %s\n", + output, strerror(errno)); goto close; } if (ioctl(ad, SNDCTL_DSP_SPEED, &sbc.rate) < 0) { fprintf(stderr, "Can't set audio rate on %s: %s\n", - output, strerror(errno)); + output, strerror(errno)); goto close; } } count = 0; while (framelen > 0) { - // we have completed an sbc_decode at this point - // sbc.len is the length of the frame we just decoded - // count is the number of decoded bytes yet to be written + /* we have completed an sbc_decode at this point sbc.len is the + * length of the frame we just decoded count is the number of + * decoded bytes yet to be written */ if (count + sbc.len > BUF_SIZE) { - // buffer is too full to stuff decoded audio in - // so it must be written to the device + /* buffer is too full to stuff decoded audio in so it + * must be written to the device */ written = write(ad, buf, count); if (written > 0) count -= written; } - // sanity check + /* sanity check */ if (count + sbc.len > BUF_SIZE) { - fprintf(stderr, "buffer size of %d is too small for decoded data (%d)\n", BUF_SIZE, sbc.len + count); + fprintf(stderr, + "buffer size of %d is too small for decoded" + " data (%d)\n", BUF_SIZE, sbc.len + count); exit(1); } - // move the latest decoded data into buf and increase the count + /* move the latest decoded data into buf and increase + * the count */ memcpy(buf + count, sbc.data, sbc.len); count += sbc.len; - // push the pointer in the file forward to the next bit to be decoded - // tell the decoder to decode up to the remaining length of the file (!) + /* push the pointer in the file forward to the next bit to be + * decoded tell the decoder to decode up to the remaining + * length of the file (!) */ pos += framelen; framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); } diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 48e01021..94b9f642 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -228,7 +228,8 @@ int main(int argc, char *argv[]) case 's': subbands = atoi(strdup(optarg)); if (subbands != 8 && subbands != 4) { - fprintf(stderr, "Invalid subbands %d!\n", subbands); + fprintf(stderr, "Invalid subbands %d!\n", + subbands); exit(1); } break; diff --git a/sbc/sbcinfo.c b/sbc/sbcinfo.c index e8fb398f..7b6d416d 100644 --- a/sbc/sbcinfo.c +++ b/sbc/sbcinfo.c @@ -113,7 +113,8 @@ static double calc_bit_rate(struct sbc_frame_hdr *hdr) return 0; } - return ((8 * (calc_frame_len(hdr) + 4) * f) / (nrof_subbands * nrof_blocks)); + return ((8 * (calc_frame_len(hdr) + 4) * f) / + (nrof_subbands * nrof_blocks)); } static char *freq2str(uint8_t freq) @@ -226,7 +227,8 @@ static int analyze_file(char *filename) while (1) { len = __read(fd, &hdr, sizeof(hdr)); if (len < 0) { - fprintf(stderr, "Unable to read frame header (error %d)\n", errno); + fprintf(stderr, "Unable to read frame header" + " (error %d)\n", errno); break; } @@ -234,8 +236,9 @@ static int analyze_file(char *filename) break; if (len < sizeof(hdr) || hdr.syncword != 0x9c) { - fprintf(stderr, "Corrupted SBC stream (len %d syncword 0x%02x)\n", - len, hdr.syncword); + fprintf(stderr, "Corrupted SBC stream " + "(len %d syncword 0x%02x)\n", + len, hdr.syncword); break; } @@ -260,7 +263,8 @@ static int analyze_file(char *filename) len = __read(fd, buf, size); if (len != size) { - fprintf(stderr, "Unable to read frame data (error %d)\n", errno); + fprintf(stderr, "Unable to read frame data " + "(error %d)\n", errno); break; } diff --git a/sbc/sbctester.c b/sbc/sbctester.c index 15e63c2a..af4d1244 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -44,14 +44,14 @@ static double sampletobits(short sample16, int verbose) if (verbose) printf("===> sampletobits(%hd, %04hX)\n", sample16, sample16); - // Bit 0 is MSB + /* Bit 0 is MSB */ if (sample16 < 0) bits = -1; if (verbose) printf("%d", (sample16 < 0) ? 1 : 0); - // Bit 15 is LSB + /* Bit 15 is LSB */ for (i = 1; i < 16; i++) { bit = (unsigned short) sample16; bit >>= 15 - i; @@ -104,8 +104,10 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, r1 = sf_read_short(sndref, refsample, infostst->channels); if (r1 != infostst->channels) { - printf("Failed to read reference data: %s (r1=%d, channels=%d)", - sf_strerror(sndref), r1, infostst->channels); + printf("Failed to read reference data: %s " + "(r1=%d, channels=%d)", + sf_strerror(sndref), r1, + infostst->channels); if (csv) fclose(csv); return -1; @@ -113,8 +115,10 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { - printf("Failed to read test data: %s (r2=%d, channels=%d)\n", - sf_strerror(sndtst), r2, infostst->channels); + printf("Failed to read test data: %s " + "(r2=%d, channels=%d)\n", + sf_strerror(sndtst), r2, + infostst->channels); if (csv) fclose(csv); return -1; @@ -122,7 +126,8 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, for (j = 0; j < infostst->channels; j++) { if (csv) - fprintf(csv, "%d;%d;", refsample[j], tstsample[j]); + fprintf(csv, "%d;%d;", refsample[j], + tstsample[j]); refbits = sampletobits(refsample[j], 0); tstbits = sampletobits(tstsample[j], 0); @@ -140,7 +145,8 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, printf("Channel %d\n", j); printf("Accumulated %f\n", rms_accu[j]); rms_accu[j] /= (double) infostst->frames; - printf("Accumulated / %f = %f\n", (double) infostst->frames, rms_accu[j]); + printf("Accumulated / %f = %f\n", (double) infostst->frames, + rms_accu[j]); rms_level[j] = sqrt(rms_accu[j]); printf("Level = %f (%f x %f = %f)\n", rms_level[j], rms_level[j], rms_level[j], @@ -162,7 +168,8 @@ static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref, } static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, - SNDFILE * sndtst, SF_INFO * infostst, int accuracy) + SNDFILE * sndtst, SF_INFO * infostst, + int accuracy) { short refsample[MAXCHANNELS], tstsample[MAXCHANNELS]; short refmax[MAXCHANNELS], tstmax[MAXCHANNELS]; @@ -190,15 +197,19 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, r1 = sf_read_short(sndref, refsample, infostst->channels); if (r1 != infostst->channels) { - printf("Failed to read reference data: %s (r1=%d, channels=%d)", - sf_strerror(sndref), r1, infostst->channels); + printf("Failed to read reference data: %s " + "(r1=%d, channels=%d)", + sf_strerror(sndref), r1, + infostst->channels); return -1; } r2 = sf_read_short(sndtst, tstsample, infostst->channels); if (r2 != infostst->channels) { - printf("Failed to read test data: %s (r2=%d, channels=%d)\n", - sf_strerror(sndtst), r2, infostst->channels); + printf("Failed to read test data: %s " + "(r2=%d, channels=%d)\n", + sf_strerror(sndtst), r2, + infostst->channels); return -1; } @@ -210,7 +221,7 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, if (cur_diff > rms_absolute) { calc_count++; - //printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute); + /* printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute); */ verdict = 0; } @@ -224,7 +235,8 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, for (j = 0; j < infostst->channels; j++) { printf("Calculated max: %f (%hd-%hd=%hd)\n", - calc_max[j], tstmax[j], refmax[j], tstmax[j] - refmax[j]); + calc_max[j], tstmax[j], refmax[j], + tstmax[j] - refmax[j]); } printf("%s return %d\n", __FUNCTION__, verdict); @@ -297,17 +309,19 @@ int main(int argc, char *argv[]) } printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", - (int) infosref.frames, (int) infosref.samplerate, (int) infosref.channels); + (int) infosref.frames, (int) infosref.samplerate, + (int) infosref.channels); printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n", - (int) infostst.frames, (int) infostst.samplerate, (int) infostst.channels); + (int) infostst.frames, (int) infostst.samplerate, + (int) infostst.channels); - // check number of channels + /* check number of channels */ if (infosref.channels > 2 || infostst.channels > 2) { printf("Too many channels\n"); goto error; } - // compare number of samples + /* compare number of samples */ if (infosref.samplerate != infostst.samplerate || infosref.channels != infostst.channels) { printf("Cannot compare files with different charasteristics\n"); @@ -317,17 +331,19 @@ int main(int argc, char *argv[]) accuracy = DEFACCURACY; printf("Accuracy: %d\n", accuracy); - // Condition 1 rms level - pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst, accuracy, "out.csv"); + /* Condition 1 rms level */ + pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst, + accuracy, "out.csv"); if (pass_rms < 0) goto error; - // Condition 2 absolute difference - pass_absolute = check_absolute_diff(sndref, &infosref, sndtst, &infostst, accuracy); + /* Condition 2 absolute difference */ + pass_absolute = check_absolute_diff(sndref, &infosref, sndtst, + &infostst, accuracy); if (pass_absolute < 0) goto error; - // Verdict + /* Verdict */ pass = pass_rms && pass_absolute; printf("Verdict: %s\n", pass ? "pass" : "fail"); -- cgit From a4bc7122fb5c7e4545cf8055cf71d1e88515998f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 1 Nov 2007 15:29:21 +0000 Subject: Some more whitespace fixes --- sbc/sbc_math.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index e4f82bce..97389c29 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -40,14 +40,14 @@ #define SCALE_NPROTO4_TBL 10 #define SCALE_NPROTO8_TBL 12 #define SCALE_SAMPLES 14 -#define SCALE4_STAGE1_BITS 10 -#define SCALE4_STAGE2_BITS 21 +#define SCALE4_STAGE1_BITS 10 +#define SCALE4_STAGE2_BITS 21 #define SCALE4_STAGED1_BITS 18 #define SCALE4_STAGED2_BITS 23 #define SCALE8_STAGE1_BITS 8 -#define SCALE8_STAGE2_BITS 24 +#define SCALE8_STAGE2_BITS 24 #define SCALE8_STAGED1_BITS 18 -#define SCALE8_STAGED2_BITS 23 +#define SCALE8_STAGED2_BITS 23 typedef int32_t sbc_fixed_t; typedef long long sbc_extended_t; -- cgit From ec233a1f849d1880697ef741f19906a4f9fcbc05 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 2 Nov 2007 09:05:57 +0000 Subject: More coding style cleanup --- sbc/sbc.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 3e65603d..76df0652 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -159,7 +159,7 @@ static const uint8_t crc_table[256] = { 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4 }; -static uint8_t sbc_crc8(const uint8_t * data, size_t len) +static uint8_t sbc_crc8(const uint8_t *data, size_t len) { uint8_t crc = 0x0f; size_t i; @@ -323,6 +323,7 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui } } } while (bitcount + slicecount < frame->bitpool); + if (bitcount + slicecount == frame->bitpool) { bitcount += slicecount; bitslice--; @@ -386,7 +387,7 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui * -3 CRC8 incorrect * -4 Bitpool value out of bounds */ -static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, +static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, size_t len) { int consumed; @@ -459,12 +460,12 @@ static int sbc_unpack_frame(const uint8_t * data, struct sbc_frame *frame, frame->bitpool = data[2]; - if (((frame->channel_mode == MONO || - frame->channel_mode == DUAL_CHANNEL) && - frame->bitpool > 16 * frame->subbands) || - ((frame->channel_mode == STEREO || - frame->channel_mode == JOINT_STEREO) && - frame->bitpool > 32 * frame->subbands)) + if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && + frame->bitpool > 16 * frame->subbands) + return -4; + + if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && + frame->bitpool > 32 * frame->subbands) return -4; /* data[3] is crc, we're checking it later */ @@ -600,17 +601,17 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, int i, j, k, idx; sbc_extended_t res; - for(i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { /* Shifting */ state->offset[ch][i]--; if (state->offset[ch][i] < 0) { state->offset[ch][i] = 79; - for(j = 0; j < 9; j++) + for (j = 0; j < 9; j++) state->V[ch][j+80] = state->V[ch][j]; } } - for(i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { /* Distribute the new matrix value to the shifted position */ SBC_FIXED_0(res); for (j = 0; j < 4; j++) @@ -619,10 +620,10 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, } /* Compute the samples */ - for(idx = 0, i = 0; i < 4; i++) { + for (idx = 0, i = 0; i < 4; i++) { k = (i + 4) & 0xf; SBC_FIXED_0(res); - for(j = 0; j < 10; idx++) { + for (j = 0; j < 10; idx++) { MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_4_40m0[idx]); MULA(res, state->V[ch][state->offset[ch][k]+j++], @@ -640,17 +641,17 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, int i, j, k, idx; sbc_extended_t res; - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { /* Shifting */ state->offset[ch][i]--; if (state->offset[ch][i] < 0) { state->offset[ch][i] = 159; - for(j = 0; j < 9; j++) + for (j = 0; j < 9; j++) state->V[ch][j+160] = state->V[ch][j]; } } - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { /* Distribute the new matrix value to the shifted position */ SBC_FIXED_0(res); for (j = 0; j < 8; j++) { @@ -662,10 +663,10 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, } /* Compute the samples */ - for(idx = 0, i = 0; i < 8; i++) { + for (idx = 0, i = 0; i < 8; i++) { k = (i + 8) & 0xf; SBC_FIXED_0(res); - for(j = 0; j < 10; idx++) { + for (j = 0; j < 10; idx++) { MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_8_80m0[idx]); MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_8_80m1[idx]); } @@ -772,6 +773,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2]); } + static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { @@ -959,7 +961,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state, * -99 not implemented */ -static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) +static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) { int produced; /* Will copy the header parts for CRC-8 calculation here */ @@ -975,9 +977,8 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ - if (len < 4) { + if (len < 4) return -1; - } /* Clear first 4 bytes of data (that's the constant length part of the * SBC header) */ @@ -997,9 +998,8 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) } else if (frame->sampling_frequency == 48000) { data[1] |= (SBC_FS_48 & 0x03) << 6; sf = SBC_FS_48; - } else { + } else return -2; - } switch (frame->blocks) { case 4: @@ -1036,6 +1036,7 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) } data[2] = frame->bitpool; + if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && frame->bitpool > 16 * frame->subbands) return -5; @@ -1123,6 +1124,7 @@ static int sbc_pack_frame(uint8_t * data, struct sbc_frame *frame, size_t len) data[4] = 0; for (sb = 0; sb < frame->subbands - 1; sb++) data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb); + if (frame->subbands == 4) crc_header[crc_pos / 8] = data[4] & 0xf0; else -- cgit From 316166212f59f4bc7bad778ff46e8b6986c52874 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 5 Nov 2007 15:54:50 +0000 Subject: correction in the 4 subband optimization --- sbc/sbc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 76df0652..c95862a0 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -713,7 +713,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) sbc_extended_t res; sbc_extended_t t[8]; - sbc_extended_t s[4]; + sbc_extended_t s[5]; MUL(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ MULA(res, _sbc_proto_4[1], (in[16] - in[24])); @@ -765,13 +765,14 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) MUL(s[0], _anamatrix4[0], t[0] + t[4]); MUL(s[1], _anamatrix4[2], t[2]); MUL(s[2], _anamatrix4[1], t[1] + t[3]); - MULA(s[2], _anamatrix4[3], t[5] + t[7]); + MULA(s[2], _anamatrix4[3], t[5]); MUL(s[3], _anamatrix4[3], t[1] + t[3]); MULA(s[3], _anamatrix4[1], - t[5] + t[7]); - out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2]); /* Q0 */ + MUL(s[4], _anamatrix4[3], t[7]); + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2] + s[4]); /* Q0 */ out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); - out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2]); + out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2] - s[4]); } static inline void sbc_analyze_four(struct sbc_encoder_state *state, -- cgit From 397d6c2b3bc7661f978c1777442d33fd86ada21e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 12 Nov 2007 18:15:59 +0000 Subject: Make sbc codec to write directly in application buffers and so avoiding memcpys. --- sbc/sbc.c | 98 ++++++++++++++++++++++++++++++++++++------------------------ sbc/sbc.h | 14 ++++----- sbc/sbcdec.c | 20 ++++++------- sbc/sbcenc.c | 23 +++++++------- 4 files changed, 88 insertions(+), 67 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c95862a0..ec1cc37d 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -95,6 +95,8 @@ struct sbc_frame { } allocation_method; uint8_t subbands; uint8_t bitpool; + uint8_t codesize; + uint8_t length; /* bit number x set means joint stereo has been used in subband x */ uint8_t join; @@ -1230,23 +1232,24 @@ int sbc_init(sbc_t *sbc, unsigned long flags) return 0; } -int sbc_parse(sbc_t *sbc, void *data, int count) +int sbc_parse(sbc_t *sbc, void *input, int input_len) { - return sbc_decode(sbc, data, count); + return sbc_decode(sbc, input, input_len, NULL, 0, NULL); } -int sbc_decode(sbc_t *sbc, void *data, int count) +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; - framelen = sbc_unpack_frame(data, &priv->frame, count); + framelen = sbc_unpack_frame(input, &priv->frame, input_len); if (!priv->init) { sbc_decoder_init(&priv->dec_state, &priv->frame); @@ -1257,26 +1260,23 @@ int sbc_decode(sbc_t *sbc, void *data, int count) sbc->subbands = priv->frame.subbands; sbc->blocks = priv->frame.blocks; sbc->bitpool = priv->frame.bitpool; + + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); } - samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); + if (!output) + return framelen; - if (!sbc->data) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = malloc(sbc->size); - } + if (written) + *written = 0; - if (sbc->size < samples * priv->frame.channels * 2) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = realloc(sbc->data, sbc->size); - } + samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + ptr = output; - ptr = sbc->data; + if (output_len < samples * priv->frame.channels * 2) + samples = output_len / (priv->frame.channels * 2); for (i = 0; i < samples; i++) { for (ch = 0; ch < priv->frame.channels; ch++) { @@ -1293,22 +1293,27 @@ int sbc_decode(sbc_t *sbc, void *data, int count) } } - sbc->len = samples * priv->frame.channels * 2; + if (written) + *written = samples * priv->frame.channels * 2; return framelen; } -int sbc_encode(sbc_t *sbc, void *data, int count) +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; + if (written) + *written = 0; + if (!priv->init) { priv->frame.sampling_frequency = sbc->rate; priv->frame.channels = sbc->channels; @@ -1325,16 +1330,22 @@ int sbc_encode(sbc_t *sbc, void *data, int count) priv->frame.subbands = sbc->subbands; priv->frame.blocks = sbc->blocks; priv->frame.bitpool = sbc->bitpool; + priv->frame.codesize = sbc_get_codesize(sbc); + priv->frame.length = sbc_get_frame_length(sbc); sbc_encoder_init(&priv->enc_state, &priv->frame); priv->init = 1; } /* input must be large enough to encode a complete frame */ - if (count < priv->frame.subbands * priv->frame.blocks * sbc->channels * 2) + if (input_len < priv->frame.codesize) return 0; - ptr = data; + /* output must be large enough to receive the encoded frame */ + if (!output || output_len < priv->frame.length) + return -ENOSPC; + + ptr = input; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { for (ch = 0; ch < sbc->channels; ch++) { @@ -1351,19 +1362,10 @@ int sbc_encode(sbc_t *sbc, void *data, int count) samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); - if (!sbc->data) { - sbc->size = 1024; - sbc->data = malloc(sbc->size); - } - - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + framelen = sbc_pack_frame(output, &priv->frame, output_len); - framelen = sbc_pack_frame(sbc->data, &priv->frame, sbc->size); - - sbc->len = framelen; + if (written) + *written = framelen; sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate; @@ -1375,11 +1377,29 @@ void sbc_finish(sbc_t *sbc) if (!sbc) return; - if (sbc->data) - free(sbc->data); - if (sbc->priv) free(sbc->priv); memset(sbc, 0, sizeof(sbc_t)); } + +int sbc_get_frame_length(sbc_t *sbc) +{ + int ret; + + ret = 4 + (4 * sbc->subbands * sbc->channels) / 8; + + /* This term is not always evenly devide so we round it up */ + if (sbc->channels == 1) + ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; + else + ret += ((sbc->joint * sbc->subbands + sbc->blocks * sbc->bitpool) + + 7) / 8; + + return ret; +} + +int sbc_get_codesize(sbc_t *sbc) +{ + return sbc->subbands * sbc->blocks * sbc->channels * 2; +} diff --git a/sbc/sbc.h b/sbc/sbc.h index 72512c02..d55587d0 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -42,10 +42,6 @@ struct sbc_struct { int bitpool; int swap; - void *data; - int size; - int len; - unsigned long duration; void *priv; @@ -54,9 +50,13 @@ struct sbc_struct { typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); -int sbc_parse(sbc_t *sbc, void *data, int count); -int sbc_decode(sbc_t *sbc, void *data, int count); -int sbc_encode(sbc_t *sbc, void *data, int count); +int sbc_parse(sbc_t *sbc, void *input, int input_len); +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *len); +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written); +int sbc_get_frame_length(sbc_t *sbc); +int sbc_get_codesize(sbc_t *sbc); void sbc_finish(sbc_t *sbc); #ifdef __cplusplus diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 866b8448..09a211a1 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,7 @@ static void decode(char *filename, char *output, int tofile) struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, written; + int fd, ad, pos, streamlen, framelen, count, written, len; int format = AFMT_S16_BE; if (stat(filename, &st) < 0) { @@ -97,7 +97,7 @@ static void decode(char *filename, char *output, int tofile) sbc_init(&sbc, 0L); sbc.swap = 1; - framelen = sbc_decode(&sbc, stream, streamlen); + framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len); printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { @@ -125,7 +125,7 @@ static void decode(char *filename, char *output, int tofile) * length of the frame we just decoded count is the number of * decoded bytes yet to be written */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { /* buffer is too full to stuff decoded audio in so it * must be written to the device */ written = write(ad, buf, count); @@ -134,23 +134,23 @@ static void decode(char *filename, char *output, int tofile) } /* sanity check */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded" - " data (%d)\n", BUF_SIZE, sbc.len + count); + " data (%d)\n", BUF_SIZE, len + count); exit(1); } - /* move the latest decoded data into buf and increase - * the count */ - memcpy(buf + count, sbc.data, sbc.len); - count += sbc.len; + /* increase the count */ + count += len; /* push the pointer in the file forward to the next bit to be * decoded tell the decoder to decode up to the remaining * length of the file (!) */ pos += framelen; - framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); + framelen = sbc_decode(&sbc, stream + pos, streamlen - pos, + buf + count, sizeof(buf) - count, + &len); } if (count > 0) { diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 94b9f642..cba31c7b 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -104,9 +104,9 @@ static ssize_t __write(int fd, const void *buf, size_t count) static void encode(char *filename, int subbands, int joint) { struct au_header *au_hdr; - unsigned char buf[2048]; + unsigned char input[2048], output[2048]; sbc_t sbc; - int fd, len, size, count; + int fd, len, size, count, encoded; if (strcmp(filename, "-")) { fd = open(filename, O_RDONLY); @@ -118,7 +118,7 @@ static void encode(char *filename, int subbands, int joint) } else fd = fileno(stdin); - len = __read(fd, buf, sizeof(buf)); + len = __read(fd, input, sizeof(input)); if (len < sizeof(*au_hdr)) { if (fd > fileno(stderr)) fprintf(stderr, "Can't read header from file %s: %s\n", @@ -128,7 +128,7 @@ static void encode(char *filename, int subbands, int joint) goto done; } - au_hdr = (struct au_header *) buf; + au_hdr = (struct au_header *) input; if (au_hdr->magic != AU_MAGIC || BE_INT(au_hdr->hdr_size) > 128 || @@ -147,11 +147,11 @@ static void encode(char *filename, int subbands, int joint) sbc.swap = 1; count = BE_INT(au_hdr->data_size); size = len - BE_INT(au_hdr->hdr_size); - memmove(buf, buf + BE_INT(au_hdr->hdr_size), size); + memmove(input, input + BE_INT(au_hdr->hdr_size), size); while (1) { - if (size < sizeof(buf)) { - len = __read(fd, buf + size, sizeof(buf) - size); + if (size < sizeof(input)) { + len = __read(fd, input + size, sizeof(input) - size); if (len == 0) break; @@ -163,17 +163,18 @@ static void encode(char *filename, int subbands, int joint) size += len; } - len = sbc_encode(&sbc, buf, size); + len = sbc_encode(&sbc, input, size, output, sizeof(output), + &encoded); if (len < size) - memmove(buf, buf + len, size - len); + memmove(input, input + len, size - len); size -= len; - len = __write(fileno(stdout), sbc.data, sbc.len); + len = __write(fileno(stdout), output, encoded); if (len == 0) break; - if (len < 0 || len != sbc.len) { + if (len < 0 || len != encoded) { perror("Can't write SBC output"); break; } -- cgit From 6d94a5b2e34c55611f2d6ea70c241971e65afc8c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 13 Nov 2007 20:04:12 +0000 Subject: Add sbc_reinit. --- sbc/sbc.c | 38 ++++++++++++++++++++++++++++++-------- sbc/sbc.h | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index ec1cc37d..12906718 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1208,6 +1208,17 @@ struct sbc_priv { struct sbc_encoder_state enc_state; }; +static void sbc_fill_defaults(sbc_t *sbc, unsigned long flags) +{ + sbc->rate = 44100; + sbc->channels = 2; + sbc->joint = 0; + sbc->subbands = 8; + sbc->blocks = 16; + sbc->bitpool = 32; + sbc->swap = 0; +} + int sbc_init(sbc_t *sbc, unsigned long flags) { if (!sbc) @@ -1221,13 +1232,7 @@ int sbc_init(sbc_t *sbc, unsigned long flags) memset(sbc->priv, 0, sizeof(struct sbc_priv)); - sbc->rate = 44100; - sbc->channels = 2; - sbc->joint = 0; - sbc->subbands = 8; - sbc->blocks = 16; - sbc->bitpool = 32; - sbc->swap = 0; + sbc_fill_defaults(sbc, flags); return 0; } @@ -1389,7 +1394,7 @@ int sbc_get_frame_length(sbc_t *sbc) ret = 4 + (4 * sbc->subbands * sbc->channels) / 8; - /* This term is not always evenly devide so we round it up */ + /* This term is not always evenly divide so we round it up */ if (sbc->channels == 1) ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; else @@ -1403,3 +1408,20 @@ int sbc_get_codesize(sbc_t *sbc) { return sbc->subbands * sbc->blocks * sbc->channels * 2; } + +int sbc_reinit(sbc_t *sbc, unsigned long flags) +{ + struct sbc_priv *priv; + + if (!sbc || !sbc->priv) + return -EIO; + + priv = sbc->priv; + + if (priv->init == 1) + memset(sbc->priv, 0, sizeof(struct sbc_priv)); + + sbc_fill_defaults(sbc, flags); + + return 0; +} diff --git a/sbc/sbc.h b/sbc/sbc.h index d55587d0..08c3e020 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -50,6 +50,7 @@ struct sbc_struct { typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); +int sbc_reinit(sbc_t *sbc, unsigned long flags); int sbc_parse(sbc_t *sbc, void *input, int input_len); int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, int output_len, int *len); -- cgit From 54e6e9fcea08bce3bc2b01fb562a74feafaa52be Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 13 Nov 2007 20:59:17 +0000 Subject: Change name of sbc_fill_defaults to sbc_set_defaults. --- sbc/sbc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 12906718..50af4a1e 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1208,7 +1208,7 @@ struct sbc_priv { struct sbc_encoder_state enc_state; }; -static void sbc_fill_defaults(sbc_t *sbc, unsigned long flags) +static void sbc_set_defaults(sbc_t *sbc, unsigned long flags) { sbc->rate = 44100; sbc->channels = 2; @@ -1232,7 +1232,7 @@ int sbc_init(sbc_t *sbc, unsigned long flags) memset(sbc->priv, 0, sizeof(struct sbc_priv)); - sbc_fill_defaults(sbc, flags); + sbc_set_defaults(sbc, flags); return 0; } @@ -1421,7 +1421,7 @@ int sbc_reinit(sbc_t *sbc, unsigned long flags) if (priv->init == 1) memset(sbc->priv, 0, sizeof(struct sbc_priv)); - sbc_fill_defaults(sbc, flags); + sbc_set_defaults(sbc, flags); return 0; } -- cgit From 8db224b3cae791b950abcc826259ef342161f454 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 23 Nov 2007 14:24:23 +0000 Subject: Introduce sbc_get_frame_duration. --- sbc/sbc.c | 7 +++++-- sbc/sbc.h | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 50af4a1e..c090dd83 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1372,8 +1372,6 @@ int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, if (written) *written = framelen; - sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate; - return samples * sbc->channels * 2; } @@ -1404,6 +1402,11 @@ int sbc_get_frame_length(sbc_t *sbc) return ret; } +int sbc_get_frame_duration(sbc_t *sbc) +{ + return (1000000 * sbc->blocks * sbc->subbands) / sbc->rate; +} + int sbc_get_codesize(sbc_t *sbc) { return sbc->subbands * sbc->blocks * sbc->channels * 2; diff --git a/sbc/sbc.h b/sbc/sbc.h index 08c3e020..cdf0d83e 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -42,8 +42,6 @@ struct sbc_struct { int bitpool; int swap; - unsigned long duration; - void *priv; }; @@ -57,6 +55,7 @@ int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, int output_len, int *written); int sbc_get_frame_length(sbc_t *sbc); +int sbc_get_frame_duration(sbc_t *sbc); int sbc_get_codesize(sbc_t *sbc); void sbc_finish(sbc_t *sbc); -- cgit From 75d93a32258f2c0158c05014fce4d791660a4e45 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 27 Nov 2007 02:42:29 +0000 Subject: rework joint subband test--uses a lot less stack space, simplify multiple loops into one, unroll one tiny loop --- sbc/sbc.c | 58 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c090dd83..880e1b47 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1071,52 +1071,56 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) if (frame->channel_mode == JOINT_STEREO) { /* like frame->sb_sample but joint stereo */ - int32_t sb_sample_j[16][2][7]; + int32_t sb_sample_j[16][2]; /* scalefactor and scale_factor in joint case */ - int scalefactor_j[2][7], scale_factor_j[2][7]; + u_int32_t scalefactor_j[2]; + uint8_t scale_factor_j[2]; + + frame->join = 0; - /* Calculate joint stereo signal */ for (sb = 0; sb < frame->subbands - 1; sb++) { + /* Calculate joint stereo signal */ for (blk = 0; blk < frame->blocks; blk++) { - sb_sample_j[blk][0][sb] = + sb_sample_j[blk][0] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) >> 1; - sb_sample_j[blk][1][sb] = + sb_sample_j[blk][1] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) >> 1; } - } - /* calculate scale_factor_j and scalefactor_j for joint case */ - for (ch = 0; ch < 2; ch++) { - for (sb = 0; sb < frame->subbands - 1; sb++) { - scale_factor_j[ch][sb] = 0; - scalefactor_j[ch][sb] = 2; - for (blk = 0; blk < frame->blocks; blk++) { - while (scalefactor_j[ch][sb] < fabs(sb_sample_j[blk][ch][sb])) { - scale_factor_j[ch][sb]++; - scalefactor_j[ch][sb] *= 2; - } + /* calculate scale_factor_j and scalefactor_j for joint case */ + scale_factor_j[0] = 0; + scalefactor_j[0] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) { + scale_factor_j[0]++; + scalefactor_j[0] *= 2; + } + } + scale_factor_j[1] = 0; + scalefactor_j[1] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) { + scale_factor_j[1]++; + scalefactor_j[1] *= 2; } } - } - /* decide which subbands to join */ - frame->join = 0; - for (sb = 0; sb < frame->subbands - 1; sb++) { + /* decide whether to join this subband */ if ((scalefactor[0][sb] + scalefactor[1][sb]) > - (scalefactor_j[0][sb] + scalefactor_j[1][sb]) ) { + (scalefactor_j[0] + scalefactor_j[1]) ) { /* use joint stereo for this subband */ frame->join |= 1 << sb; - frame->scale_factor[0][sb] = scale_factor_j[0][sb]; - frame->scale_factor[1][sb] = scale_factor_j[1][sb]; - scalefactor[0][sb] = scalefactor_j[0][sb]; - scalefactor[1][sb] = scalefactor_j[1][sb]; + frame->scale_factor[0][sb] = scale_factor_j[0]; + frame->scale_factor[1][sb] = scale_factor_j[1]; + scalefactor[0][sb] = scalefactor_j[0]; + scalefactor[1][sb] = scalefactor_j[1]; for (blk = 0; blk < frame->blocks; blk++) { frame->sb_sample_f[blk][0][sb] = - sb_sample_j[blk][0][sb]; + sb_sample_j[blk][0]; frame->sb_sample_f[blk][1][sb] = - sb_sample_j[blk][1][sb]; + sb_sample_j[blk][1]; } } } -- cgit From 6a2bcc32bffe68e452c2ce7e0bb328b1f7b7b9bb Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 27 Nov 2007 03:15:36 +0000 Subject: combine the blk loops inside the joint conditional --- sbc/sbc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 880e1b47..d5ccf1fa 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1079,28 +1079,25 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) frame->join = 0; for (sb = 0; sb < frame->subbands - 1; sb++) { - /* Calculate joint stereo signal */ + scale_factor_j[0] = 0; + scalefactor_j[0] = 2; + scale_factor_j[1] = 0; + scalefactor_j[1] = 2; + for (blk = 0; blk < frame->blocks; blk++) { + /* Calculate joint stereo signal */ sb_sample_j[blk][0] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) >> 1; sb_sample_j[blk][1] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) >> 1; - } - /* calculate scale_factor_j and scalefactor_j for joint case */ - scale_factor_j[0] = 0; - scalefactor_j[0] = 2; - for (blk = 0; blk < frame->blocks; blk++) { + /* calculate scale_factor_j and scalefactor_j for joint case */ while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) { scale_factor_j[0]++; scalefactor_j[0] *= 2; } - } - scale_factor_j[1] = 0; - scalefactor_j[1] = 2; - for (blk = 0; blk < frame->blocks; blk++) { while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) { scale_factor_j[1]++; scalefactor_j[1] *= 2; -- cgit From 4a2b8a2e67d13e8ed974e2e91e093383493883a7 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 27 Nov 2007 06:22:48 +0000 Subject: eliminate extra loop for bitneed compute make a couple while loops easier to read as for loops --- sbc/sbc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index d5ccf1fa..de88f82a 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -194,9 +194,13 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui int ch, sb; for (ch = 0; ch < frame->channels; ch++) { + max_bitneed = 0; if (frame->allocation_method == SNR) { - for (sb = 0; sb < frame->subbands; sb++) + for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } } else { for (sb = 0; sb < frame->subbands; sb++) { if (frame->scale_factor[ch][sb] == 0) @@ -211,15 +215,11 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui else bitneed[ch][sb] = loudness; } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; } } - max_bitneed = 0; - for (sb = 0; sb < frame->subbands; sb++) { - if (bitneed[ch][sb] > max_bitneed) - max_bitneed = bitneed[ch][sb]; - } - bitcount = 0; slicecount = 0; bitslice = max_bitneed + 1; @@ -250,8 +250,7 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui } } - sb = 0; - while (bitcount < frame->bitpool && sb < frame->subbands) { + for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) { if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { bits[ch][sb]++; bitcount++; @@ -259,16 +258,13 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui bits[ch][sb] = 2; bitcount += 2; } - sb++; } - sb = 0; - while (bitcount < frame->bitpool && sb < frame->subbands) { + for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) { if (bits[ch][sb] < 16) { bits[ch][sb]++; bitcount++; } - sb++; } } -- cgit From 41c458777419bf2ff42a911d1315d81b30607ba5 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 27 Nov 2007 06:47:38 +0000 Subject: eliminate another max_bitneed loop, eliminate extraneous loop termination tests --- sbc/sbc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index de88f82a..ebf4a9d0 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -273,10 +273,14 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; + max_bitneed = 0; if (frame->allocation_method == SNR) { for (ch = 0; ch < 2; ch++) { - for (sb = 0; sb < frame->subbands; sb++) + for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } } } else { for (ch = 0; ch < 2; ch++) { @@ -293,18 +297,12 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui else bitneed[ch][sb] = loudness; } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; } } } - max_bitneed = 0; - for (ch = 0; ch < 2; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { - if (bitneed[ch][sb] > max_bitneed) - max_bitneed = bitneed[ch][sb]; - } - } - bitcount = 0; slicecount = 0; bitslice = max_bitneed + 1; @@ -341,7 +339,7 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui ch = 0; sb = 0; - while ((bitcount < frame->bitpool) && (sb < frame->subbands)) { + while (bitcount < frame->bitpool) { if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { bits[ch][sb]++; bitcount++; @@ -352,13 +350,14 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui if (ch == 1) { ch = 0; sb++; + if (sb >= frame->subbands) break; } else ch = 1; } ch = 0; sb = 0; - while ((bitcount < frame->bitpool) && (sb < frame->subbands)) { + while (bitcount < frame->bitpool) { if (bits[ch][sb] < 16) { bits[ch][sb]++; bitcount++; @@ -366,6 +365,7 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui if (ch == 1) { ch = 0; sb++; + if (sb >= frame->subbands) break; } else ch = 1; } -- cgit From 56dc26cadc212be0727b64e522723d45673d67a3 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 29 Nov 2007 20:23:22 +0000 Subject: Remove unnecessary checks for output buffer length and some optimizations. --- sbc/sbc.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index ebf4a9d0..c3d39478 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -976,9 +976,6 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ - if (len < 4) - return -1; - /* Clear first 4 bytes of data (that's the constant length part of the * SBC header) */ memset(data, 0, 4); @@ -1037,11 +1034,11 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[2] = frame->bitpool; if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && - frame->bitpool > 16 * frame->subbands) + frame->bitpool > frame->subbands << 4) return -5; if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && - frame->bitpool > 32 * frame->subbands) + frame->bitpool > frame->subbands << 5) return -5; /* Can't fill in crc yet */ @@ -1118,31 +1115,25 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } } - if (len * 8 < produced + frame->subbands) - return -1; - data[4] = 0; for (sb = 0; sb < frame->subbands - 1; sb++) data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb); if (frame->subbands == 4) - crc_header[crc_pos / 8] = data[4] & 0xf0; + crc_header[crc_pos >> 3] = data[4] & 0xf0; else - crc_header[crc_pos / 8] = data[4]; + crc_header[crc_pos >> 3] = data[4]; produced += frame->subbands; crc_pos += frame->subbands; } - if (len * 8 < produced + (4 * frame->subbands * frame->channels)) - return -1; - for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (produced % 8 == 0) data[produced / 8] = 0; - data[produced / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (produced % 8))); - crc_header[crc_pos / 8] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (crc_pos % 8))); + data[produced >> 3] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (produced % 8))); + crc_header[crc_pos >> 3] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (crc_pos % 8))); produced += 4; crc_pos += 4; @@ -1168,23 +1159,15 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) levels[ch][sb]) >> 1); else frame->audio_sample[blk][ch][sb] = 0; - } - } - } - for (blk = 0; blk < frame->blocks; blk++) { - for (ch = 0; ch < frame->channels; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { if (bits[ch][sb] != 0) { for (bit = 0; bit < bits[ch][sb]; bit++) { int b; /* A bit */ - if (produced > len * 8) - return -1; if (produced % 8 == 0) - data[produced / 8] = 0; + data[produced >> 3] = 0; b = ((frame->audio_sample[blk][ch][sb]) >> (bits[ch][sb] - bit - 1)) & 0x01; - data[produced / 8] |= b << (7 - (produced % 8)); + data[produced >> 3] |= b << (7 - (produced % 8)); produced++; } } @@ -1195,7 +1178,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) if (produced % 8 != 0) produced += 8 - (produced % 8); - return produced / 8; + return produced >> 3; } struct sbc_priv { -- cgit From 4161e8201ea54fe605b2aa14d864e0bad941c5d8 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 29 Nov 2007 21:48:12 +0000 Subject: don't use the audio_sample array inside the frame struct it's totally unnecessary to keep all these temporary results around --- sbc/sbc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c3d39478..904227b5 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -969,6 +969,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) /* Sampling frequency as temporary value for table lookup */ uint8_t sf; + uint16_t audio_sample; int ch, sb, blk, bit; /* channel, subband, block and bit counters */ int bits[2][8]; /* bits distribution */ @@ -1153,19 +1154,19 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (levels[ch][sb] > 0) - frame->audio_sample[blk][ch][sb] = + audio_sample = (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + levels[ch][sb]) >> 1); else - frame->audio_sample[blk][ch][sb] = 0; + audio_sample = 0; if (bits[ch][sb] != 0) { for (bit = 0; bit < bits[ch][sb]; bit++) { int b; /* A bit */ if (produced % 8 == 0) data[produced >> 3] = 0; - b = ((frame->audio_sample[blk][ch][sb]) >> + b = ((audio_sample) >> (bits[ch][sb] - bit - 1)) & 0x01; data[produced >> 3] |= b << (7 - (produced % 8)); produced++; @@ -1175,10 +1176,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } } - if (produced % 8 != 0) - produced += 8 - (produced % 8); - - return produced >> 3; + return (produced + 7) >> 3; } struct sbc_priv { -- cgit From 76e595a98b7b73ee54ae17e6162f05ad81c9b654 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 30 Nov 2007 01:20:01 +0000 Subject: change inner loop bit packing to use shift-in-place instead of complex ops --- sbc/sbc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 904227b5..a785c48d 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1162,20 +1162,21 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) audio_sample = 0; if (bits[ch][sb] != 0) { + audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { - int b; /* A bit */ - if (produced % 8 == 0) - data[produced >> 3] = 0; - b = ((audio_sample) >> - (bits[ch][sb] - bit - 1)) & 0x01; - data[produced >> 3] |= b << (7 - (produced % 8)); + data[produced >> 3] <<= 1; + if(audio_sample & 0x8000) + data[produced >> 3] |= 0x1; + audio_sample <<= 1; produced++; } } } } } - + /* align the last byte */ + if(produced % 8) data[produced >> 3] <<= 8 - (produced % 8); + return (produced + 7) >> 3; } -- cgit From 87f83cd60537de472248311f48b6eb4cde6801d4 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 30 Nov 2007 15:53:04 +0000 Subject: combine two conditionals in bit packing --- sbc/sbc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a785c48d..001910a5 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1153,15 +1153,11 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { - if (levels[ch][sb] > 0) + if (levels[ch][sb] > 0) { audio_sample = (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + levels[ch][sb]) >> 1); - else - audio_sample = 0; - - if (bits[ch][sb] != 0) { audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { data[produced >> 3] <<= 1; -- cgit From 2e6b3caf16b973b4bcf71ae1f31d5c8276939f70 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 13 Dec 2007 17:16:20 +0000 Subject: don't need to memset the data header --- sbc/sbc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 001910a5..647760bb 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -977,23 +977,19 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */ - /* Clear first 4 bytes of data (that's the constant length part of the - * SBC header) */ - memset(data, 0, 4); - data[0] = SBC_SYNCWORD; if (frame->sampling_frequency == 16000) { - data[1] |= (SBC_FS_16 & 0x03) << 6; + data[1] = (SBC_FS_16 & 0x03) << 6; sf = SBC_FS_16; } else if (frame->sampling_frequency == 32000) { - data[1] |= (SBC_FS_32 & 0x03) << 6; + data[1] = (SBC_FS_32 & 0x03) << 6; sf = SBC_FS_32; } else if (frame->sampling_frequency == 44100) { - data[1] |= (SBC_FS_44 & 0x03) << 6; + data[1] = (SBC_FS_44 & 0x03) << 6; sf = SBC_FS_44; } else if (frame->sampling_frequency == 48000) { - data[1] |= (SBC_FS_48 & 0x03) << 6; + data[1] = (SBC_FS_48 & 0x03) << 6; sf = SBC_FS_48; } else return -2; -- cgit From c5e43eefcc34641b875f2565c1c4b5b4616d3f58 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 00:13:07 +0000 Subject: roll back the shift-in-place bitpack optimization while we figure out if it tickles a bug or creates a bug for 4 subbands --- sbc/sbc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 647760bb..86efadcf 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1154,20 +1154,19 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + levels[ch][sb]) >> 1); - audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { - data[produced >> 3] <<= 1; - if(audio_sample & 0x8000) - data[produced >> 3] |= 0x1; - audio_sample <<= 1; + int b; /* A bit */ + if (produced % 8 == 0) + data[produced >> 3] = 0; + b = ((audio_sample) >> + (bits[ch][sb] - bit - 1)) & 0x01; + data[produced >> 3] |= b << (7 - (produced % 8)); produced++; } } } } } - /* align the last byte */ - if(produced % 8) data[produced >> 3] <<= 8 - (produced % 8); return (produced + 7) >> 3; } -- cgit From 356a8b48cde75a93680350454c293dc8913f4104 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 00:15:33 +0000 Subject: be more strict about calculating from joint since client may set it to a funky value other than 0/1 --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 86efadcf..960a5bc5 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1366,7 +1366,7 @@ int sbc_get_frame_length(sbc_t *sbc) if (sbc->channels == 1) ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; else - ret += ((sbc->joint * sbc->subbands + sbc->blocks * sbc->bitpool) + ret += (((sbc->joint? sbc->subbands:0) + sbc->blocks * sbc->bitpool) + 7) / 8; return ret; -- cgit From 5acc7043cf566207181bb5030ebcd9e401b097df Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 00:46:09 +0000 Subject: coding style on ?: --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 960a5bc5..9a4d8800 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1366,7 +1366,7 @@ int sbc_get_frame_length(sbc_t *sbc) if (sbc->channels == 1) ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; else - ret += (((sbc->joint? sbc->subbands:0) + sbc->blocks * sbc->bitpool) + ret += (((sbc->joint ? sbc->subbands : 0) + sbc->blocks * sbc->bitpool) + 7) / 8; return ret; -- cgit From c1ce3b25c4981ae88218fa46921969260b3afc43 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 06:07:52 +0000 Subject: shift-in-place opt is back in, with a bugfix for the 4-subband case --- sbc/sbc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 9a4d8800..a192ad83 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1137,6 +1137,10 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } } + /* this is temporary until we use an in-place shift above */ + if(produced % 8) + data[produced >> 3] >>= 8 - (produced % 8); + data[3] = sbc_crc8(crc_header, crc_pos); sbc_calculate_bits(frame, bits, sf); @@ -1154,20 +1158,24 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) + levels[ch][sb]) >> 1); + audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { - int b; /* A bit */ - if (produced % 8 == 0) - data[produced >> 3] = 0; - b = ((audio_sample) >> - (bits[ch][sb] - bit - 1)) & 0x01; - data[produced >> 3] |= b << (7 - (produced % 8)); + data[produced >> 3] <<= 1; + if(audio_sample & 0x8000) + data[produced >> 3] |= 0x1; + audio_sample <<= 1; produced++; } } } } } - + + /* align the last byte */ + if(produced % 8) { + data[produced >> 3] <<= 8 - (produced % 8); + } + return (produced + 7) >> 3; } -- cgit From 9a14d423e7def6933b4df4bae8e9185a62b346ea Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 06:43:06 +0000 Subject: push in-place-shift optimization up into scalefactors section --- sbc/sbc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a192ad83..36f6696b 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1123,23 +1123,29 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) produced += frame->subbands; crc_pos += frame->subbands; + + /* this is temporary until we use an in-place shift above */ + if(produced % 8) { + data[produced >> 3] >>= 8 - (produced % 8); + crc_header[crc_pos >> 3] >>= 8 - (crc_pos % 8); + } } for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { - if (produced % 8 == 0) - data[produced / 8] = 0; - data[produced >> 3] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (produced % 8))); - crc_header[crc_pos >> 3] |= ((frame->scale_factor[ch][sb] & 0x0F) << (4 - (crc_pos % 8))); + data[produced >> 3] <<= 4; + crc_header[crc_pos >> 3] <<= 4; + data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F; + crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F; produced += 4; crc_pos += 4; } } - /* this is temporary until we use an in-place shift above */ - if(produced % 8) - data[produced >> 3] >>= 8 - (produced % 8); + /* align the last crc byte */ + if(crc_pos % 8) + crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); data[3] = sbc_crc8(crc_header, crc_pos); -- cgit From 1da4920f71140a3d9478f013a1ff000197f9a1eb Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 14 Dec 2007 06:54:19 +0000 Subject: smooth out last shift-in-place wrinkle --- sbc/sbc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 36f6696b..cf27b38e 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1114,21 +1114,12 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[4] = 0; for (sb = 0; sb < frame->subbands - 1; sb++) - data[4] |= ((frame->join >> sb) & 0x01) << (7 - sb); + data[4] |= ((frame->join >> sb) & 0x01) << (frame->subbands - 1 - sb); - if (frame->subbands == 4) - crc_header[crc_pos >> 3] = data[4] & 0xf0; - else - crc_header[crc_pos >> 3] = data[4]; + crc_header[crc_pos >> 3] = data[4]; produced += frame->subbands; crc_pos += frame->subbands; - - /* this is temporary until we use an in-place shift above */ - if(produced % 8) { - data[produced >> 3] >>= 8 - (produced % 8); - crc_header[crc_pos >> 3] >>= 8 - (crc_pos % 8); - } } for (ch = 0; ch < frame->channels; ch++) { -- cgit From 40d383bb1ed20bcc638e738c8d0fb7a79008b126 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 8 Jan 2008 20:56:17 +0000 Subject: optimizations: use memmove instead of a loop, unroll short loop --- sbc/sbc.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index cf27b38e..991a5e1a 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -776,12 +776,16 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int i; - /* Input 4 New Audio Samples */ - for (i = 39; i >= 4; i--) - state->X[ch][i] = state->X[ch][i - 4]; - for (i = 3; i >= 0; i--) - state->X[ch][i] = frame->pcm_sample[ch][blk * 4 + (3 - i)]; + int32_t *x = state->X[ch]; + int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; + + /* Input 4 Audio Samples */ + memmove(x + 4, x, 36 * sizeof(*x)); + x[3] = pcm[0]; + x[2] = pcm[1]; + x[1] = pcm[2]; + x[0] = pcm[3]; + _sbc_analyze_four(state->X[ch], frame->sb_sample_f[blk][ch]); } @@ -912,13 +916,20 @@ static inline void sbc_analyze_eight(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int i; + int32_t *x = state->X[ch]; + int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; /* Input 8 Audio Samples */ - for (i = 79; i >= 8; i--) - state->X[ch][i] = state->X[ch][i - 8]; - for (i = 7; i >= 0; i--) - state->X[ch][i] = frame->pcm_sample[ch][blk * 8 + (7 - i)]; + memmove(x + 8, x, 72 * sizeof(*x)); + x[7] = pcm[0]; + x[6] = pcm[1]; + x[5] = pcm[2]; + x[4] = pcm[3]; + x[3] = pcm[4]; + x[2] = pcm[5]; + x[1] = pcm[6]; + x[0] = pcm[7]; + _sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]); } -- cgit From 0dda8d7230df625baf35aeb9dd72b20d0923aebd Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 11 Jan 2008 20:28:18 +0000 Subject: tweak to the memmove for 4 subbands --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 991a5e1a..0472762e 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -777,7 +777,7 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { int32_t *x = state->X[ch]; - int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; + int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; /* Input 4 Audio Samples */ memmove(x + 4, x, 36 * sizeof(*x)); -- cgit From d4d085c9a00d2d457b1a97b46b5f52bf68cd4a1a Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 14 Jan 2008 14:40:57 +0000 Subject: take out memmove in sbc analyze --- sbc/sbc.c | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 0472762e..8e2aff62 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -120,7 +120,8 @@ struct sbc_decoder_state { struct sbc_encoder_state { int subbands; - int32_t X[2][80]; + int position[2]; + int32_t X[2][160]; }; /* @@ -704,6 +705,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, { memset(&state->X, 0, sizeof(state->X)); state->subbands = frame->subbands; + state->position[0] = state->position[1] = 80; } static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) @@ -776,17 +778,20 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int32_t *x = state->X[ch]; + int32_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; - /* Input 4 Audio Samples */ - memmove(x + 4, x, 36 * sizeof(*x)); - x[3] = pcm[0]; - x[2] = pcm[1]; - x[1] = pcm[2]; - x[0] = pcm[3]; + /* Input 8 Audio Samples */ + x[40] = x[0] = pcm[3]; + x[41] = x[1] = pcm[2]; + x[42] = x[2] = pcm[1]; + x[43] = x[3] = pcm[0]; + + _sbc_analyze_four(x, frame->sb_sample_f[blk][ch]); - _sbc_analyze_four(state->X[ch], frame->sb_sample_f[blk][ch]); + state->position[ch] -= 4; + if (state->position[ch] < 0) + state->position[ch] = 36; } static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) @@ -916,21 +921,24 @@ static inline void sbc_analyze_eight(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int32_t *x = state->X[ch]; + int32_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; /* Input 8 Audio Samples */ - memmove(x + 8, x, 72 * sizeof(*x)); - x[7] = pcm[0]; - x[6] = pcm[1]; - x[5] = pcm[2]; - x[4] = pcm[3]; - x[3] = pcm[4]; - x[2] = pcm[5]; - x[1] = pcm[6]; - x[0] = pcm[7]; - - _sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]); + x[80] = x[0] = pcm[7]; + x[81] = x[1] = pcm[6]; + x[82] = x[2] = pcm[5]; + x[83] = x[3] = pcm[4]; + x[84] = x[4] = pcm[3]; + x[85] = x[5] = pcm[2]; + x[86] = x[6] = pcm[1]; + x[87] = x[7] = pcm[0]; + + _sbc_analyze_eight(x, frame->sb_sample_f[blk][ch]); + + state->position[ch] -= 8; + if (state->position[ch] < 0) + state->position[ch] = 72; } static int sbc_analyze_audio(struct sbc_encoder_state *state, -- cgit From 23f3e84ba43efde94aa52c77455ff28662ed2b79 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 14 Jan 2008 15:03:23 +0000 Subject: fix initialization --- sbc/sbc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 8e2aff62..d8385bd8 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -705,7 +705,10 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, { memset(&state->X, 0, sizeof(state->X)); state->subbands = frame->subbands; - state->position[0] = state->position[1] = 80; + if(frame->subbands == 8) + state->position[0] = state->position[1] = 72; + else + state->position[0] = state->position[1] = 36; } static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) -- cgit From 8c72b28a0ccaf232e871863d32fedb9da750e6eb Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 14 Jan 2008 20:03:42 +0000 Subject: comment typo --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index d8385bd8..ac40dc26 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -784,7 +784,7 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, int32_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; - /* Input 8 Audio Samples */ + /* Input 4 Audio Samples */ x[40] = x[0] = pcm[3]; x[41] = x[1] = pcm[2]; x[42] = x[2] = pcm[1]; -- cgit From 910d62035726402a249d13b58b4b52baa9e7466e Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 14 Jan 2008 22:15:17 +0000 Subject: coding style --- sbc/sbc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index ac40dc26..3202e602 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -705,10 +705,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, { memset(&state->X, 0, sizeof(state->X)); state->subbands = frame->subbands; - if(frame->subbands == 8) - state->position[0] = state->position[1] = 72; - else - state->position[0] = state->position[1] = 36; + state->position[0] = state->position[1] = 9 * frame->subbands; } static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) @@ -1157,7 +1154,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } /* align the last crc byte */ - if(crc_pos % 8) + if (crc_pos % 8) crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); data[3] = sbc_crc8(crc_header, crc_pos); @@ -1180,7 +1177,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) audio_sample <<= 16 - bits[ch][sb]; for (bit = 0; bit < bits[ch][sb]; bit++) { data[produced >> 3] <<= 1; - if(audio_sample & 0x8000) + if (audio_sample & 0x8000) data[produced >> 3] |= 0x1; audio_sample <<= 1; produced++; @@ -1191,7 +1188,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } /* align the last byte */ - if(produced % 8) { + if (produced % 8) { data[produced >> 3] <<= 8 - (produced % 8); } -- cgit From f6dd2c738c08de510d8eb2d2f81c1c9f10521cd2 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 17 Jan 2008 04:35:14 +0000 Subject: codec has been using 32-bit (MUL) and 64-bit (MULA) multiplies straighten things out so MUL/MULA are both 64 bit create MUL32/MULA32 for anyone who really needs a 32-bit product --- sbc/sbc_math.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 97389c29..fae2a0c5 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -64,6 +64,8 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } -#define MUL(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } +#define MUL32(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } +#define MULA32(dst, a, b) { dst += (sbc_fixed_t) (a) * (b); } +#define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } -- cgit From 66fe637352aeb2b5d376bff7095a7a5fd209a426 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 19 Jan 2008 15:56:52 +0000 Subject: update copyrights --- sbc/sbc.c | 2 +- sbc/sbc_math.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 3202e602..9e6156ec 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -4,7 +4,7 @@ * * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz - * Copyright (C) 2005-2006 Brad Midgley + * Copyright (C) 2005-2008 Brad Midgley * * * This library is free software; you can redistribute it and/or diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index fae2a0c5..f5879fbf 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -4,7 +4,7 @@ * * Copyright (C) 2004-2007 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz - * Copyright (C) 2005-2006 Brad Midgley + * Copyright (C) 2005-2008 Brad Midgley * * * This library is free software; you can redistribute it and/or -- cgit From dae52eacbae42da81c3a569c28c4f09755f4f93b Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 26 Jan 2008 05:24:50 +0000 Subject: pcm input array should be 16 not 32 bits use 32-bit product when multiplying two values limited to 16 bits each --- sbc/sbc.c | 150 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 75 insertions(+), 75 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 9e6156ec..a83dc7ce 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -121,7 +121,7 @@ struct sbc_decoder_state { struct sbc_encoder_state { int subbands; int position[2]; - int32_t X[2][160]; + int16_t X[2][160]; }; /* @@ -708,11 +708,11 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, state->position[0] = state->position[1] = 9 * frame->subbands; } -static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) -{ +static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) +{ sbc_extended_t res; - sbc_extended_t t[8]; + sbc_fixed_t t[8]; sbc_extended_t s[5]; MUL(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ @@ -778,7 +778,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int32_t *x = &state->X[ch][state->position[ch]]; + int16_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; /* Input 4 Audio Samples */ @@ -794,95 +794,95 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, state->position[ch] = 36; } -static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) +static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) { sbc_extended_t res; - sbc_extended_t t[8]; + sbc_fixed_t t[8]; sbc_extended_t s[8]; - MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ - MULA(res, _sbc_proto_8[1], (in[32] - in[48])); - MULA(res, _sbc_proto_8[2], in[4]); - MULA(res, _sbc_proto_8[3], in[20]); - MULA(res, _sbc_proto_8[4], in[36]); - MULA(res, _sbc_proto_8[5], in[52]); + MUL32(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ + MULA32(res, _sbc_proto_8[1], (in[32] - in[48])); + MULA32(res, _sbc_proto_8[2], in[4]); + MULA32(res, _sbc_proto_8[3], in[20]); + MULA32(res, _sbc_proto_8[4], in[36]); + MULA32(res, _sbc_proto_8[5], in[52]); t[0] = SCALE8_STAGE1(res); /* Q10 */ - MUL(res, _sbc_proto_8[6], in[2]); - MULA(res, _sbc_proto_8[7], in[18]); - MULA(res, _sbc_proto_8[8], in[34]); - MULA(res, _sbc_proto_8[9], in[50]); - MULA(res, _sbc_proto_8[10], in[66]); + MUL32(res, _sbc_proto_8[6], in[2]); + MULA32(res, _sbc_proto_8[7], in[18]); + MULA32(res, _sbc_proto_8[8], in[34]); + MULA32(res, _sbc_proto_8[9], in[50]); + MULA32(res, _sbc_proto_8[10], in[66]); t[1] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[11], in[1]); - MULA(res, _sbc_proto_8[12], in[17]); - MULA(res, _sbc_proto_8[13], in[33]); - MULA(res, _sbc_proto_8[14], in[49]); - MULA(res, _sbc_proto_8[15], in[65]); - MULA(res, _sbc_proto_8[16], in[3]); - MULA(res, _sbc_proto_8[17], in[19]); - MULA(res, _sbc_proto_8[18], in[35]); - MULA(res, _sbc_proto_8[19], in[51]); - MULA(res, _sbc_proto_8[20], in[67]); + MUL32(res, _sbc_proto_8[11], in[1]); + MULA32(res, _sbc_proto_8[12], in[17]); + MULA32(res, _sbc_proto_8[13], in[33]); + MULA32(res, _sbc_proto_8[14], in[49]); + MULA32(res, _sbc_proto_8[15], in[65]); + MULA32(res, _sbc_proto_8[16], in[3]); + MULA32(res, _sbc_proto_8[17], in[19]); + MULA32(res, _sbc_proto_8[18], in[35]); + MULA32(res, _sbc_proto_8[19], in[51]); + MULA32(res, _sbc_proto_8[20], in[67]); t[2] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[21], in[5]); - MULA(res, _sbc_proto_8[22], in[21]); - MULA(res, _sbc_proto_8[23], in[37]); - MULA(res, _sbc_proto_8[24], in[53]); - MULA(res, _sbc_proto_8[25], in[69]); - MULA(res, -_sbc_proto_8[15], in[15]); - MULA(res, -_sbc_proto_8[14], in[31]); - MULA(res, -_sbc_proto_8[13], in[47]); - MULA(res, -_sbc_proto_8[12], in[63]); - MULA(res, -_sbc_proto_8[11], in[79]); + MUL32(res, _sbc_proto_8[21], in[5]); + MULA32(res, _sbc_proto_8[22], in[21]); + MULA32(res, _sbc_proto_8[23], in[37]); + MULA32(res, _sbc_proto_8[24], in[53]); + MULA32(res, _sbc_proto_8[25], in[69]); + MULA32(res, -_sbc_proto_8[15], in[15]); + MULA32(res, -_sbc_proto_8[14], in[31]); + MULA32(res, -_sbc_proto_8[13], in[47]); + MULA32(res, -_sbc_proto_8[12], in[63]); + MULA32(res, -_sbc_proto_8[11], in[79]); t[3] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[26], in[6]); - MULA(res, _sbc_proto_8[27], in[22]); - MULA(res, _sbc_proto_8[28], in[38]); - MULA(res, _sbc_proto_8[29], in[54]); - MULA(res, _sbc_proto_8[30], in[70]); - MULA(res, -_sbc_proto_8[10], in[14]); - MULA(res, -_sbc_proto_8[9], in[30]); - MULA(res, -_sbc_proto_8[8], in[46]); - MULA(res, -_sbc_proto_8[7], in[62]); - MULA(res, -_sbc_proto_8[6], in[78]); + MUL32(res, _sbc_proto_8[26], in[6]); + MULA32(res, _sbc_proto_8[27], in[22]); + MULA32(res, _sbc_proto_8[28], in[38]); + MULA32(res, _sbc_proto_8[29], in[54]); + MULA32(res, _sbc_proto_8[30], in[70]); + MULA32(res, -_sbc_proto_8[10], in[14]); + MULA32(res, -_sbc_proto_8[9], in[30]); + MULA32(res, -_sbc_proto_8[8], in[46]); + MULA32(res, -_sbc_proto_8[7], in[62]); + MULA32(res, -_sbc_proto_8[6], in[78]); t[4] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[31], in[7]); - MULA(res, _sbc_proto_8[32], in[23]); - MULA(res, _sbc_proto_8[33], in[39]); - MULA(res, _sbc_proto_8[34], in[55]); - MULA(res, _sbc_proto_8[35], in[71]); - MULA(res, -_sbc_proto_8[20], in[13]); - MULA(res, -_sbc_proto_8[19], in[29]); - MULA(res, -_sbc_proto_8[18], in[45]); - MULA(res, -_sbc_proto_8[17], in[61]); - MULA(res, -_sbc_proto_8[16], in[77]); + MUL32(res, _sbc_proto_8[31], in[7]); + MULA32(res, _sbc_proto_8[32], in[23]); + MULA32(res, _sbc_proto_8[33], in[39]); + MULA32(res, _sbc_proto_8[34], in[55]); + MULA32(res, _sbc_proto_8[35], in[71]); + MULA32(res, -_sbc_proto_8[20], in[13]); + MULA32(res, -_sbc_proto_8[19], in[29]); + MULA32(res, -_sbc_proto_8[18], in[45]); + MULA32(res, -_sbc_proto_8[17], in[61]); + MULA32(res, -_sbc_proto_8[16], in[77]); t[5] = SCALE8_STAGE1(res); MUL(res, _sbc_proto_8[36], in[8] + in[72]); MULA(res, _sbc_proto_8[37], in[24] + in[56]); - MULA(res, _sbc_proto_8[38], in[40]); - MULA(res, -_sbc_proto_8[39], in[12]); - MULA(res, -_sbc_proto_8[5], in[28]); - MULA(res, -_sbc_proto_8[4], in[44]); - MULA(res, -_sbc_proto_8[3], in[60]); - MULA(res, -_sbc_proto_8[2], in[76]); + MULA32(res, _sbc_proto_8[38], in[40]); + MULA32(res, -_sbc_proto_8[39], in[12]); + MULA32(res, -_sbc_proto_8[5], in[28]); + MULA32(res, -_sbc_proto_8[4], in[44]); + MULA32(res, -_sbc_proto_8[3], in[60]); + MULA32(res, -_sbc_proto_8[2], in[76]); t[6] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[35], in[9]); - MULA(res, _sbc_proto_8[34], in[25]); - MULA(res, _sbc_proto_8[33], in[41]); - MULA(res, _sbc_proto_8[32], in[57]); - MULA(res, _sbc_proto_8[31], in[73]); - MULA(res, -_sbc_proto_8[25], in[11]); - MULA(res, -_sbc_proto_8[24], in[27]); - MULA(res, -_sbc_proto_8[23], in[43]); - MULA(res, -_sbc_proto_8[22], in[59]); - MULA(res, -_sbc_proto_8[21], in[75]); + MUL32(res, _sbc_proto_8[35], in[9]); + MULA32(res, _sbc_proto_8[34], in[25]); + MULA32(res, _sbc_proto_8[33], in[41]); + MULA32(res, _sbc_proto_8[32], in[57]); + MULA32(res, _sbc_proto_8[31], in[73]); + MULA32(res, -_sbc_proto_8[25], in[11]); + MULA32(res, -_sbc_proto_8[24], in[27]); + MULA32(res, -_sbc_proto_8[23], in[43]); + MULA32(res, -_sbc_proto_8[22], in[59]); + MULA32(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ @@ -921,7 +921,7 @@ static inline void sbc_analyze_eight(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int32_t *x = &state->X[ch][state->position[ch]]; + int16_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; /* Input 8 Audio Samples */ -- cgit From c9b510105937825c04c729b4bb02b87596b795fb Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 26 Jan 2008 19:45:54 +0000 Subject: shorten the encoder tables to 16 bits, take out mula32/mul32 for now for simplicity --- sbc/sbc.c | 134 +++++++++++++++++++++++++++---------------------------- sbc/sbc_math.h | 10 ++--- sbc/sbc_tables.h | 8 ++-- 3 files changed, 75 insertions(+), 77 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a83dc7ce..cfcf6432 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -800,89 +800,89 @@ static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) sbc_fixed_t t[8]; sbc_extended_t s[8]; - MUL32(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ - MULA32(res, _sbc_proto_8[1], (in[32] - in[48])); - MULA32(res, _sbc_proto_8[2], in[4]); - MULA32(res, _sbc_proto_8[3], in[20]); - MULA32(res, _sbc_proto_8[4], in[36]); - MULA32(res, _sbc_proto_8[5], in[52]); + MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ + MULA(res, _sbc_proto_8[1], (in[32] - in[48])); + MULA(res, _sbc_proto_8[2], in[4]); + MULA(res, _sbc_proto_8[3], in[20]); + MULA(res, _sbc_proto_8[4], in[36]); + MULA(res, _sbc_proto_8[5], in[52]); t[0] = SCALE8_STAGE1(res); /* Q10 */ - MUL32(res, _sbc_proto_8[6], in[2]); - MULA32(res, _sbc_proto_8[7], in[18]); - MULA32(res, _sbc_proto_8[8], in[34]); - MULA32(res, _sbc_proto_8[9], in[50]); - MULA32(res, _sbc_proto_8[10], in[66]); + MUL(res, _sbc_proto_8[6], in[2]); + MULA(res, _sbc_proto_8[7], in[18]); + MULA(res, _sbc_proto_8[8], in[34]); + MULA(res, _sbc_proto_8[9], in[50]); + MULA(res, _sbc_proto_8[10], in[66]); t[1] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[11], in[1]); - MULA32(res, _sbc_proto_8[12], in[17]); - MULA32(res, _sbc_proto_8[13], in[33]); - MULA32(res, _sbc_proto_8[14], in[49]); - MULA32(res, _sbc_proto_8[15], in[65]); - MULA32(res, _sbc_proto_8[16], in[3]); - MULA32(res, _sbc_proto_8[17], in[19]); - MULA32(res, _sbc_proto_8[18], in[35]); - MULA32(res, _sbc_proto_8[19], in[51]); - MULA32(res, _sbc_proto_8[20], in[67]); + MUL(res, _sbc_proto_8[11], in[1]); + MULA(res, _sbc_proto_8[12], in[17]); + MULA(res, _sbc_proto_8[13], in[33]); + MULA(res, _sbc_proto_8[14], in[49]); + MULA(res, _sbc_proto_8[15], in[65]); + MULA(res, _sbc_proto_8[16], in[3]); + MULA(res, _sbc_proto_8[17], in[19]); + MULA(res, _sbc_proto_8[18], in[35]); + MULA(res, _sbc_proto_8[19], in[51]); + MULA(res, _sbc_proto_8[20], in[67]); t[2] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[21], in[5]); - MULA32(res, _sbc_proto_8[22], in[21]); - MULA32(res, _sbc_proto_8[23], in[37]); - MULA32(res, _sbc_proto_8[24], in[53]); - MULA32(res, _sbc_proto_8[25], in[69]); - MULA32(res, -_sbc_proto_8[15], in[15]); - MULA32(res, -_sbc_proto_8[14], in[31]); - MULA32(res, -_sbc_proto_8[13], in[47]); - MULA32(res, -_sbc_proto_8[12], in[63]); - MULA32(res, -_sbc_proto_8[11], in[79]); + MUL(res, _sbc_proto_8[21], in[5]); + MULA(res, _sbc_proto_8[22], in[21]); + MULA(res, _sbc_proto_8[23], in[37]); + MULA(res, _sbc_proto_8[24], in[53]); + MULA(res, _sbc_proto_8[25], in[69]); + MULA(res, -_sbc_proto_8[15], in[15]); + MULA(res, -_sbc_proto_8[14], in[31]); + MULA(res, -_sbc_proto_8[13], in[47]); + MULA(res, -_sbc_proto_8[12], in[63]); + MULA(res, -_sbc_proto_8[11], in[79]); t[3] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[26], in[6]); - MULA32(res, _sbc_proto_8[27], in[22]); - MULA32(res, _sbc_proto_8[28], in[38]); - MULA32(res, _sbc_proto_8[29], in[54]); - MULA32(res, _sbc_proto_8[30], in[70]); - MULA32(res, -_sbc_proto_8[10], in[14]); - MULA32(res, -_sbc_proto_8[9], in[30]); - MULA32(res, -_sbc_proto_8[8], in[46]); - MULA32(res, -_sbc_proto_8[7], in[62]); - MULA32(res, -_sbc_proto_8[6], in[78]); + MUL(res, _sbc_proto_8[26], in[6]); + MULA(res, _sbc_proto_8[27], in[22]); + MULA(res, _sbc_proto_8[28], in[38]); + MULA(res, _sbc_proto_8[29], in[54]); + MULA(res, _sbc_proto_8[30], in[70]); + MULA(res, -_sbc_proto_8[10], in[14]); + MULA(res, -_sbc_proto_8[9], in[30]); + MULA(res, -_sbc_proto_8[8], in[46]); + MULA(res, -_sbc_proto_8[7], in[62]); + MULA(res, -_sbc_proto_8[6], in[78]); t[4] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[31], in[7]); - MULA32(res, _sbc_proto_8[32], in[23]); - MULA32(res, _sbc_proto_8[33], in[39]); - MULA32(res, _sbc_proto_8[34], in[55]); - MULA32(res, _sbc_proto_8[35], in[71]); - MULA32(res, -_sbc_proto_8[20], in[13]); - MULA32(res, -_sbc_proto_8[19], in[29]); - MULA32(res, -_sbc_proto_8[18], in[45]); - MULA32(res, -_sbc_proto_8[17], in[61]); - MULA32(res, -_sbc_proto_8[16], in[77]); + MUL(res, _sbc_proto_8[31], in[7]); + MULA(res, _sbc_proto_8[32], in[23]); + MULA(res, _sbc_proto_8[33], in[39]); + MULA(res, _sbc_proto_8[34], in[55]); + MULA(res, _sbc_proto_8[35], in[71]); + MULA(res, -_sbc_proto_8[20], in[13]); + MULA(res, -_sbc_proto_8[19], in[29]); + MULA(res, -_sbc_proto_8[18], in[45]); + MULA(res, -_sbc_proto_8[17], in[61]); + MULA(res, -_sbc_proto_8[16], in[77]); t[5] = SCALE8_STAGE1(res); MUL(res, _sbc_proto_8[36], in[8] + in[72]); MULA(res, _sbc_proto_8[37], in[24] + in[56]); - MULA32(res, _sbc_proto_8[38], in[40]); - MULA32(res, -_sbc_proto_8[39], in[12]); - MULA32(res, -_sbc_proto_8[5], in[28]); - MULA32(res, -_sbc_proto_8[4], in[44]); - MULA32(res, -_sbc_proto_8[3], in[60]); - MULA32(res, -_sbc_proto_8[2], in[76]); + MULA(res, _sbc_proto_8[38], in[40]); + MULA(res, -_sbc_proto_8[39], in[12]); + MULA(res, -_sbc_proto_8[5], in[28]); + MULA(res, -_sbc_proto_8[4], in[44]); + MULA(res, -_sbc_proto_8[3], in[60]); + MULA(res, -_sbc_proto_8[2], in[76]); t[6] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[35], in[9]); - MULA32(res, _sbc_proto_8[34], in[25]); - MULA32(res, _sbc_proto_8[33], in[41]); - MULA32(res, _sbc_proto_8[32], in[57]); - MULA32(res, _sbc_proto_8[31], in[73]); - MULA32(res, -_sbc_proto_8[25], in[11]); - MULA32(res, -_sbc_proto_8[24], in[27]); - MULA32(res, -_sbc_proto_8[23], in[43]); - MULA32(res, -_sbc_proto_8[22], in[59]); - MULA32(res, -_sbc_proto_8[21], in[75]); + MUL(res, _sbc_proto_8[35], in[9]); + MULA(res, _sbc_proto_8[34], in[25]); + MULA(res, _sbc_proto_8[33], in[41]); + MULA(res, _sbc_proto_8[32], in[57]); + MULA(res, _sbc_proto_8[31], in[73]); + MULA(res, -_sbc_proto_8[25], in[11]); + MULA(res, -_sbc_proto_8[24], in[27]); + MULA(res, -_sbc_proto_8[23], in[43]); + MULA(res, -_sbc_proto_8[22], in[59]); + MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index f5879fbf..5aeddac1 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -31,20 +31,20 @@ #define ASR_64(val, bits) ((-2 >> 1 == -1) ? \ ((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits))) -#define SCALE_PROTO4_TBL 15 +#define SCALE_PROTO4_TBL 16 #define SCALE_ANA4_TBL 16 -#define SCALE_PROTO8_TBL 15 +#define SCALE_PROTO8_TBL 16 #define SCALE_ANA8_TBL 16 #define SCALE_SPROTO4_TBL 16 #define SCALE_SPROTO8_TBL 16 #define SCALE_NPROTO4_TBL 10 #define SCALE_NPROTO8_TBL 12 #define SCALE_SAMPLES 14 -#define SCALE4_STAGE1_BITS 10 +#define SCALE4_STAGE1_BITS 9 #define SCALE4_STAGE2_BITS 21 #define SCALE4_STAGED1_BITS 18 #define SCALE4_STAGED2_BITS 23 -#define SCALE8_STAGE1_BITS 8 +#define SCALE8_STAGE1_BITS 7 #define SCALE8_STAGE2_BITS 24 #define SCALE8_STAGED1_BITS 18 #define SCALE8_STAGED2_BITS 23 @@ -64,8 +64,6 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } -#define MUL32(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } -#define MULA32(dst, a, b) { dst += (sbc_fixed_t) (a) * (b); } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h index 5e00caca..0da2a2d3 100644 --- a/sbc/sbc_tables.h +++ b/sbc/sbc_tables.h @@ -48,7 +48,7 @@ static const int sbc_offset8[4][8] = { #define SN4(val) ASR(val, SCALE_NPROTO4_TBL) #define SN8(val) ASR(val, SCALE_NPROTO8_TBL) -static const int32_t _sbc_proto_4[20] = { +static const int16_t _sbc_proto_4[20] = { SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548), SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7), SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737), @@ -56,11 +56,11 @@ static const int32_t _sbc_proto_4[20] = { SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000) }; -static const int32_t _anamatrix4[4] = { +static const int16_t _anamatrix4[4] = { SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0) }; -static const int32_t _sbc_proto_8[40] = { +static const int16_t _sbc_proto_8[40] = { SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930), SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28), SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc), @@ -115,7 +115,7 @@ static const int32_t sbc_proto_8_80m1[] = { SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a) }; -static const int32_t _anamatrix8[8] = { +static const int16_t _anamatrix8[8] = { SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40), SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000) }; -- cgit From c2ce7c2d410cfb0e67c1635ebf60fc06ae864f33 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sun, 27 Jan 2008 03:35:53 +0000 Subject: get 32-bit products whenever we're sure the multiplicands are both 16 bits --- sbc/sbc.c | 190 ++++++++++++++++++++++++++++----------------------------- sbc/sbc_math.h | 2 + 2 files changed, 97 insertions(+), 95 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index cfcf6432..f83c3485 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -715,51 +715,51 @@ static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) sbc_fixed_t t[8]; sbc_extended_t s[5]; - MUL(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ - MULA(res, _sbc_proto_4[1], (in[16] - in[24])); + MUL32(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ + MULA32(res, _sbc_proto_4[1], (in[16] - in[24])); t[0] = SCALE4_STAGE1(res); /* Q8 */ - MUL(res, _sbc_proto_4[2], in[1]); - MULA(res, _sbc_proto_4[3], in[9]); - MULA(res, _sbc_proto_4[4], in[17]); - MULA(res, _sbc_proto_4[5], in[25]); - MULA(res, _sbc_proto_4[6], in[33]); + MUL32(res, _sbc_proto_4[2], in[1]); + MULA32(res, _sbc_proto_4[3], in[9]); + MULA32(res, _sbc_proto_4[4], in[17]); + MULA32(res, _sbc_proto_4[5], in[25]); + MULA32(res, _sbc_proto_4[6], in[33]); t[1] = SCALE4_STAGE1(res); - MUL(res, _sbc_proto_4[7], in[2]); - MULA(res, _sbc_proto_4[8], in[10]); - MULA(res, _sbc_proto_4[9], in[18]); - MULA(res, _sbc_proto_4[10], in[26]); - MULA(res, _sbc_proto_4[11], in[34]); + MUL32(res, _sbc_proto_4[7], in[2]); + MULA32(res, _sbc_proto_4[8], in[10]); + MULA32(res, _sbc_proto_4[9], in[18]); + MULA32(res, _sbc_proto_4[10], in[26]); + MULA32(res, _sbc_proto_4[11], in[34]); t[2] = SCALE4_STAGE1(res); - MUL(res, _sbc_proto_4[12], in[3]); - MULA(res, _sbc_proto_4[13], in[11]); - MULA(res, _sbc_proto_4[14], in[19]); - MULA(res, _sbc_proto_4[15], in[27]); - MULA(res, _sbc_proto_4[16], in[35]); + MUL32(res, _sbc_proto_4[12], in[3]); + MULA32(res, _sbc_proto_4[13], in[11]); + MULA32(res, _sbc_proto_4[14], in[19]); + MULA32(res, _sbc_proto_4[15], in[27]); + MULA32(res, _sbc_proto_4[16], in[35]); t[3] = SCALE4_STAGE1(res); MUL(res, _sbc_proto_4[17], in[4] + in[36]); MULA(res, _sbc_proto_4[18], in[12] + in[28]); - MULA(res, _sbc_proto_4[19], in[20]); + MULA32(res, _sbc_proto_4[19], in[20]); t[4] = SCALE4_STAGE1(res); - MUL(res, _sbc_proto_4[16], in[5]); - MULA(res, _sbc_proto_4[15], in[13]); - MULA(res, _sbc_proto_4[14], in[21]); - MULA(res, _sbc_proto_4[13], in[29]); - MULA(res, _sbc_proto_4[12], in[37]); + MUL32(res, _sbc_proto_4[16], in[5]); + MULA32(res, _sbc_proto_4[15], in[13]); + MULA32(res, _sbc_proto_4[14], in[21]); + MULA32(res, _sbc_proto_4[13], in[29]); + MULA32(res, _sbc_proto_4[12], in[37]); t[5] = SCALE4_STAGE1(res); /* don't compute t[6]... this term always multiplies * with cos(pi/2) = 0 */ - MUL(res, _sbc_proto_4[6], in[7]); - MULA(res, _sbc_proto_4[5], in[15]); - MULA(res, _sbc_proto_4[4], in[23]); - MULA(res, _sbc_proto_4[3], in[31]); - MULA(res, _sbc_proto_4[2], in[39]); + MUL32(res, _sbc_proto_4[6], in[7]); + MULA32(res, _sbc_proto_4[5], in[15]); + MULA32(res, _sbc_proto_4[4], in[23]); + MULA32(res, _sbc_proto_4[3], in[31]); + MULA32(res, _sbc_proto_4[2], in[39]); t[7] = SCALE4_STAGE1(res); MUL(s[0], _anamatrix4[0], t[0] + t[4]); @@ -800,89 +800,89 @@ static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) sbc_fixed_t t[8]; sbc_extended_t s[8]; - MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ - MULA(res, _sbc_proto_8[1], (in[32] - in[48])); - MULA(res, _sbc_proto_8[2], in[4]); - MULA(res, _sbc_proto_8[3], in[20]); - MULA(res, _sbc_proto_8[4], in[36]); - MULA(res, _sbc_proto_8[5], in[52]); + MUL32(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ + MULA32(res, _sbc_proto_8[1], (in[32] - in[48])); + MULA32(res, _sbc_proto_8[2], in[4]); + MULA32(res, _sbc_proto_8[3], in[20]); + MULA32(res, _sbc_proto_8[4], in[36]); + MULA32(res, _sbc_proto_8[5], in[52]); t[0] = SCALE8_STAGE1(res); /* Q10 */ - MUL(res, _sbc_proto_8[6], in[2]); - MULA(res, _sbc_proto_8[7], in[18]); - MULA(res, _sbc_proto_8[8], in[34]); - MULA(res, _sbc_proto_8[9], in[50]); - MULA(res, _sbc_proto_8[10], in[66]); + MUL32(res, _sbc_proto_8[6], in[2]); + MULA32(res, _sbc_proto_8[7], in[18]); + MULA32(res, _sbc_proto_8[8], in[34]); + MULA32(res, _sbc_proto_8[9], in[50]); + MULA32(res, _sbc_proto_8[10], in[66]); t[1] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[11], in[1]); - MULA(res, _sbc_proto_8[12], in[17]); - MULA(res, _sbc_proto_8[13], in[33]); - MULA(res, _sbc_proto_8[14], in[49]); - MULA(res, _sbc_proto_8[15], in[65]); - MULA(res, _sbc_proto_8[16], in[3]); - MULA(res, _sbc_proto_8[17], in[19]); - MULA(res, _sbc_proto_8[18], in[35]); - MULA(res, _sbc_proto_8[19], in[51]); - MULA(res, _sbc_proto_8[20], in[67]); + MUL32(res, _sbc_proto_8[11], in[1]); + MULA32(res, _sbc_proto_8[12], in[17]); + MULA32(res, _sbc_proto_8[13], in[33]); + MULA32(res, _sbc_proto_8[14], in[49]); + MULA32(res, _sbc_proto_8[15], in[65]); + MULA32(res, _sbc_proto_8[16], in[3]); + MULA32(res, _sbc_proto_8[17], in[19]); + MULA32(res, _sbc_proto_8[18], in[35]); + MULA32(res, _sbc_proto_8[19], in[51]); + MULA32(res, _sbc_proto_8[20], in[67]); t[2] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[21], in[5]); - MULA(res, _sbc_proto_8[22], in[21]); - MULA(res, _sbc_proto_8[23], in[37]); - MULA(res, _sbc_proto_8[24], in[53]); - MULA(res, _sbc_proto_8[25], in[69]); - MULA(res, -_sbc_proto_8[15], in[15]); - MULA(res, -_sbc_proto_8[14], in[31]); - MULA(res, -_sbc_proto_8[13], in[47]); - MULA(res, -_sbc_proto_8[12], in[63]); - MULA(res, -_sbc_proto_8[11], in[79]); + MUL32(res, _sbc_proto_8[21], in[5]); + MULA32(res, _sbc_proto_8[22], in[21]); + MULA32(res, _sbc_proto_8[23], in[37]); + MULA32(res, _sbc_proto_8[24], in[53]); + MULA32(res, _sbc_proto_8[25], in[69]); + MULA32(res, -_sbc_proto_8[15], in[15]); + MULA32(res, -_sbc_proto_8[14], in[31]); + MULA32(res, -_sbc_proto_8[13], in[47]); + MULA32(res, -_sbc_proto_8[12], in[63]); + MULA32(res, -_sbc_proto_8[11], in[79]); t[3] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[26], in[6]); - MULA(res, _sbc_proto_8[27], in[22]); - MULA(res, _sbc_proto_8[28], in[38]); - MULA(res, _sbc_proto_8[29], in[54]); - MULA(res, _sbc_proto_8[30], in[70]); - MULA(res, -_sbc_proto_8[10], in[14]); - MULA(res, -_sbc_proto_8[9], in[30]); - MULA(res, -_sbc_proto_8[8], in[46]); - MULA(res, -_sbc_proto_8[7], in[62]); - MULA(res, -_sbc_proto_8[6], in[78]); + MUL32(res, _sbc_proto_8[26], in[6]); + MULA32(res, _sbc_proto_8[27], in[22]); + MULA32(res, _sbc_proto_8[28], in[38]); + MULA32(res, _sbc_proto_8[29], in[54]); + MULA32(res, _sbc_proto_8[30], in[70]); + MULA32(res, -_sbc_proto_8[10], in[14]); + MULA32(res, -_sbc_proto_8[9], in[30]); + MULA32(res, -_sbc_proto_8[8], in[46]); + MULA32(res, -_sbc_proto_8[7], in[62]); + MULA32(res, -_sbc_proto_8[6], in[78]); t[4] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[31], in[7]); - MULA(res, _sbc_proto_8[32], in[23]); - MULA(res, _sbc_proto_8[33], in[39]); - MULA(res, _sbc_proto_8[34], in[55]); - MULA(res, _sbc_proto_8[35], in[71]); - MULA(res, -_sbc_proto_8[20], in[13]); - MULA(res, -_sbc_proto_8[19], in[29]); - MULA(res, -_sbc_proto_8[18], in[45]); - MULA(res, -_sbc_proto_8[17], in[61]); - MULA(res, -_sbc_proto_8[16], in[77]); + MUL32(res, _sbc_proto_8[31], in[7]); + MULA32(res, _sbc_proto_8[32], in[23]); + MULA32(res, _sbc_proto_8[33], in[39]); + MULA32(res, _sbc_proto_8[34], in[55]); + MULA32(res, _sbc_proto_8[35], in[71]); + MULA32(res, -_sbc_proto_8[20], in[13]); + MULA32(res, -_sbc_proto_8[19], in[29]); + MULA32(res, -_sbc_proto_8[18], in[45]); + MULA32(res, -_sbc_proto_8[17], in[61]); + MULA32(res, -_sbc_proto_8[16], in[77]); t[5] = SCALE8_STAGE1(res); MUL(res, _sbc_proto_8[36], in[8] + in[72]); MULA(res, _sbc_proto_8[37], in[24] + in[56]); - MULA(res, _sbc_proto_8[38], in[40]); - MULA(res, -_sbc_proto_8[39], in[12]); - MULA(res, -_sbc_proto_8[5], in[28]); - MULA(res, -_sbc_proto_8[4], in[44]); - MULA(res, -_sbc_proto_8[3], in[60]); - MULA(res, -_sbc_proto_8[2], in[76]); + MULA32(res, _sbc_proto_8[38], in[40]); + MULA32(res, -_sbc_proto_8[39], in[12]); + MULA32(res, -_sbc_proto_8[5], in[28]); + MULA32(res, -_sbc_proto_8[4], in[44]); + MULA32(res, -_sbc_proto_8[3], in[60]); + MULA32(res, -_sbc_proto_8[2], in[76]); t[6] = SCALE8_STAGE1(res); - MUL(res, _sbc_proto_8[35], in[9]); - MULA(res, _sbc_proto_8[34], in[25]); - MULA(res, _sbc_proto_8[33], in[41]); - MULA(res, _sbc_proto_8[32], in[57]); - MULA(res, _sbc_proto_8[31], in[73]); - MULA(res, -_sbc_proto_8[25], in[11]); - MULA(res, -_sbc_proto_8[24], in[27]); - MULA(res, -_sbc_proto_8[23], in[43]); - MULA(res, -_sbc_proto_8[22], in[59]); - MULA(res, -_sbc_proto_8[21], in[75]); + MUL32(res, _sbc_proto_8[35], in[9]); + MULA32(res, _sbc_proto_8[34], in[25]); + MULA32(res, _sbc_proto_8[33], in[41]); + MULA32(res, _sbc_proto_8[32], in[57]); + MULA32(res, _sbc_proto_8[31], in[73]); + MULA32(res, -_sbc_proto_8[25], in[11]); + MULA32(res, -_sbc_proto_8[24], in[27]); + MULA32(res, -_sbc_proto_8[23], in[43]); + MULA32(res, -_sbc_proto_8[22], in[59]); + MULA32(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 5aeddac1..c8c72c75 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -64,6 +64,8 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } +#define MUL32(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } +#define MULA32(dst, a, b) { dst += (sbc_fixed_t) (a) * (b); } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } -- cgit From d352bd04383f1c1a5ec17e267cb8d0ce70720519 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sun, 27 Jan 2008 04:29:08 +0000 Subject: avoid an (unlikely) overflow --- sbc/sbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index f83c3485..0cb839b6 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -715,8 +715,8 @@ static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) sbc_fixed_t t[8]; sbc_extended_t s[5]; - MUL32(res, _sbc_proto_4[0], (in[8] - in[32])); /* Q18 */ - MULA32(res, _sbc_proto_4[1], (in[16] - in[24])); + MUL(res, _sbc_proto_4[0], in[8] - in[32]); /* Q18 */ + MULA(res, _sbc_proto_4[1], in[16] - in[24]); t[0] = SCALE4_STAGE1(res); /* Q8 */ MUL32(res, _sbc_proto_4[2], in[1]); -- cgit From ba255beb79afb9c00ae5b71821f84f911aa8d1fe Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 28 Jan 2008 10:38:40 +0000 Subject: Whitespace cleanup --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 0cb839b6..c9ea5b5c 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1154,7 +1154,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } /* align the last crc byte */ - if (crc_pos % 8) + if (crc_pos % 8) crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8); data[3] = sbc_crc8(crc_header, crc_pos); -- cgit From 38158dc5dd8e7c62ad2decfec395e3ec2c7e280b Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 28 Jan 2008 17:26:22 +0000 Subject: remove 16x16 mult optimization--gcc actually generates more costly code --- sbc/sbc.c | 186 +++++++++++++++++++++++++++---------------------------- sbc/sbc_math.h | 10 ++- sbc/sbc_tables.h | 8 +-- 3 files changed, 101 insertions(+), 103 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index c9ea5b5c..97614fb9 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -719,47 +719,47 @@ static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) MULA(res, _sbc_proto_4[1], in[16] - in[24]); t[0] = SCALE4_STAGE1(res); /* Q8 */ - MUL32(res, _sbc_proto_4[2], in[1]); - MULA32(res, _sbc_proto_4[3], in[9]); - MULA32(res, _sbc_proto_4[4], in[17]); - MULA32(res, _sbc_proto_4[5], in[25]); - MULA32(res, _sbc_proto_4[6], in[33]); + MUL(res, _sbc_proto_4[2], in[1]); + MULA(res, _sbc_proto_4[3], in[9]); + MULA(res, _sbc_proto_4[4], in[17]); + MULA(res, _sbc_proto_4[5], in[25]); + MULA(res, _sbc_proto_4[6], in[33]); t[1] = SCALE4_STAGE1(res); - MUL32(res, _sbc_proto_4[7], in[2]); - MULA32(res, _sbc_proto_4[8], in[10]); - MULA32(res, _sbc_proto_4[9], in[18]); - MULA32(res, _sbc_proto_4[10], in[26]); - MULA32(res, _sbc_proto_4[11], in[34]); + MUL(res, _sbc_proto_4[7], in[2]); + MULA(res, _sbc_proto_4[8], in[10]); + MULA(res, _sbc_proto_4[9], in[18]); + MULA(res, _sbc_proto_4[10], in[26]); + MULA(res, _sbc_proto_4[11], in[34]); t[2] = SCALE4_STAGE1(res); - MUL32(res, _sbc_proto_4[12], in[3]); - MULA32(res, _sbc_proto_4[13], in[11]); - MULA32(res, _sbc_proto_4[14], in[19]); - MULA32(res, _sbc_proto_4[15], in[27]); - MULA32(res, _sbc_proto_4[16], in[35]); + MUL(res, _sbc_proto_4[12], in[3]); + MULA(res, _sbc_proto_4[13], in[11]); + MULA(res, _sbc_proto_4[14], in[19]); + MULA(res, _sbc_proto_4[15], in[27]); + MULA(res, _sbc_proto_4[16], in[35]); t[3] = SCALE4_STAGE1(res); MUL(res, _sbc_proto_4[17], in[4] + in[36]); MULA(res, _sbc_proto_4[18], in[12] + in[28]); - MULA32(res, _sbc_proto_4[19], in[20]); + MULA(res, _sbc_proto_4[19], in[20]); t[4] = SCALE4_STAGE1(res); - MUL32(res, _sbc_proto_4[16], in[5]); - MULA32(res, _sbc_proto_4[15], in[13]); - MULA32(res, _sbc_proto_4[14], in[21]); - MULA32(res, _sbc_proto_4[13], in[29]); - MULA32(res, _sbc_proto_4[12], in[37]); + MUL(res, _sbc_proto_4[16], in[5]); + MULA(res, _sbc_proto_4[15], in[13]); + MULA(res, _sbc_proto_4[14], in[21]); + MULA(res, _sbc_proto_4[13], in[29]); + MULA(res, _sbc_proto_4[12], in[37]); t[5] = SCALE4_STAGE1(res); /* don't compute t[6]... this term always multiplies * with cos(pi/2) = 0 */ - MUL32(res, _sbc_proto_4[6], in[7]); - MULA32(res, _sbc_proto_4[5], in[15]); - MULA32(res, _sbc_proto_4[4], in[23]); - MULA32(res, _sbc_proto_4[3], in[31]); - MULA32(res, _sbc_proto_4[2], in[39]); + MUL(res, _sbc_proto_4[6], in[7]); + MULA(res, _sbc_proto_4[5], in[15]); + MULA(res, _sbc_proto_4[4], in[23]); + MULA(res, _sbc_proto_4[3], in[31]); + MULA(res, _sbc_proto_4[2], in[39]); t[7] = SCALE4_STAGE1(res); MUL(s[0], _anamatrix4[0], t[0] + t[4]); @@ -800,89 +800,89 @@ static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) sbc_fixed_t t[8]; sbc_extended_t s[8]; - MUL32(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ - MULA32(res, _sbc_proto_8[1], (in[32] - in[48])); - MULA32(res, _sbc_proto_8[2], in[4]); - MULA32(res, _sbc_proto_8[3], in[20]); - MULA32(res, _sbc_proto_8[4], in[36]); - MULA32(res, _sbc_proto_8[5], in[52]); + MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ + MULA(res, _sbc_proto_8[1], (in[32] - in[48])); + MULA(res, _sbc_proto_8[2], in[4]); + MULA(res, _sbc_proto_8[3], in[20]); + MULA(res, _sbc_proto_8[4], in[36]); + MULA(res, _sbc_proto_8[5], in[52]); t[0] = SCALE8_STAGE1(res); /* Q10 */ - MUL32(res, _sbc_proto_8[6], in[2]); - MULA32(res, _sbc_proto_8[7], in[18]); - MULA32(res, _sbc_proto_8[8], in[34]); - MULA32(res, _sbc_proto_8[9], in[50]); - MULA32(res, _sbc_proto_8[10], in[66]); + MUL(res, _sbc_proto_8[6], in[2]); + MULA(res, _sbc_proto_8[7], in[18]); + MULA(res, _sbc_proto_8[8], in[34]); + MULA(res, _sbc_proto_8[9], in[50]); + MULA(res, _sbc_proto_8[10], in[66]); t[1] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[11], in[1]); - MULA32(res, _sbc_proto_8[12], in[17]); - MULA32(res, _sbc_proto_8[13], in[33]); - MULA32(res, _sbc_proto_8[14], in[49]); - MULA32(res, _sbc_proto_8[15], in[65]); - MULA32(res, _sbc_proto_8[16], in[3]); - MULA32(res, _sbc_proto_8[17], in[19]); - MULA32(res, _sbc_proto_8[18], in[35]); - MULA32(res, _sbc_proto_8[19], in[51]); - MULA32(res, _sbc_proto_8[20], in[67]); + MUL(res, _sbc_proto_8[11], in[1]); + MULA(res, _sbc_proto_8[12], in[17]); + MULA(res, _sbc_proto_8[13], in[33]); + MULA(res, _sbc_proto_8[14], in[49]); + MULA(res, _sbc_proto_8[15], in[65]); + MULA(res, _sbc_proto_8[16], in[3]); + MULA(res, _sbc_proto_8[17], in[19]); + MULA(res, _sbc_proto_8[18], in[35]); + MULA(res, _sbc_proto_8[19], in[51]); + MULA(res, _sbc_proto_8[20], in[67]); t[2] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[21], in[5]); - MULA32(res, _sbc_proto_8[22], in[21]); - MULA32(res, _sbc_proto_8[23], in[37]); - MULA32(res, _sbc_proto_8[24], in[53]); - MULA32(res, _sbc_proto_8[25], in[69]); - MULA32(res, -_sbc_proto_8[15], in[15]); - MULA32(res, -_sbc_proto_8[14], in[31]); - MULA32(res, -_sbc_proto_8[13], in[47]); - MULA32(res, -_sbc_proto_8[12], in[63]); - MULA32(res, -_sbc_proto_8[11], in[79]); + MUL(res, _sbc_proto_8[21], in[5]); + MULA(res, _sbc_proto_8[22], in[21]); + MULA(res, _sbc_proto_8[23], in[37]); + MULA(res, _sbc_proto_8[24], in[53]); + MULA(res, _sbc_proto_8[25], in[69]); + MULA(res, -_sbc_proto_8[15], in[15]); + MULA(res, -_sbc_proto_8[14], in[31]); + MULA(res, -_sbc_proto_8[13], in[47]); + MULA(res, -_sbc_proto_8[12], in[63]); + MULA(res, -_sbc_proto_8[11], in[79]); t[3] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[26], in[6]); - MULA32(res, _sbc_proto_8[27], in[22]); - MULA32(res, _sbc_proto_8[28], in[38]); - MULA32(res, _sbc_proto_8[29], in[54]); - MULA32(res, _sbc_proto_8[30], in[70]); - MULA32(res, -_sbc_proto_8[10], in[14]); - MULA32(res, -_sbc_proto_8[9], in[30]); - MULA32(res, -_sbc_proto_8[8], in[46]); - MULA32(res, -_sbc_proto_8[7], in[62]); - MULA32(res, -_sbc_proto_8[6], in[78]); + MUL(res, _sbc_proto_8[26], in[6]); + MULA(res, _sbc_proto_8[27], in[22]); + MULA(res, _sbc_proto_8[28], in[38]); + MULA(res, _sbc_proto_8[29], in[54]); + MULA(res, _sbc_proto_8[30], in[70]); + MULA(res, -_sbc_proto_8[10], in[14]); + MULA(res, -_sbc_proto_8[9], in[30]); + MULA(res, -_sbc_proto_8[8], in[46]); + MULA(res, -_sbc_proto_8[7], in[62]); + MULA(res, -_sbc_proto_8[6], in[78]); t[4] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[31], in[7]); - MULA32(res, _sbc_proto_8[32], in[23]); - MULA32(res, _sbc_proto_8[33], in[39]); - MULA32(res, _sbc_proto_8[34], in[55]); - MULA32(res, _sbc_proto_8[35], in[71]); - MULA32(res, -_sbc_proto_8[20], in[13]); - MULA32(res, -_sbc_proto_8[19], in[29]); - MULA32(res, -_sbc_proto_8[18], in[45]); - MULA32(res, -_sbc_proto_8[17], in[61]); - MULA32(res, -_sbc_proto_8[16], in[77]); + MUL(res, _sbc_proto_8[31], in[7]); + MULA(res, _sbc_proto_8[32], in[23]); + MULA(res, _sbc_proto_8[33], in[39]); + MULA(res, _sbc_proto_8[34], in[55]); + MULA(res, _sbc_proto_8[35], in[71]); + MULA(res, -_sbc_proto_8[20], in[13]); + MULA(res, -_sbc_proto_8[19], in[29]); + MULA(res, -_sbc_proto_8[18], in[45]); + MULA(res, -_sbc_proto_8[17], in[61]); + MULA(res, -_sbc_proto_8[16], in[77]); t[5] = SCALE8_STAGE1(res); MUL(res, _sbc_proto_8[36], in[8] + in[72]); MULA(res, _sbc_proto_8[37], in[24] + in[56]); - MULA32(res, _sbc_proto_8[38], in[40]); - MULA32(res, -_sbc_proto_8[39], in[12]); - MULA32(res, -_sbc_proto_8[5], in[28]); - MULA32(res, -_sbc_proto_8[4], in[44]); - MULA32(res, -_sbc_proto_8[3], in[60]); - MULA32(res, -_sbc_proto_8[2], in[76]); + MULA(res, _sbc_proto_8[38], in[40]); + MULA(res, -_sbc_proto_8[39], in[12]); + MULA(res, -_sbc_proto_8[5], in[28]); + MULA(res, -_sbc_proto_8[4], in[44]); + MULA(res, -_sbc_proto_8[3], in[60]); + MULA(res, -_sbc_proto_8[2], in[76]); t[6] = SCALE8_STAGE1(res); - MUL32(res, _sbc_proto_8[35], in[9]); - MULA32(res, _sbc_proto_8[34], in[25]); - MULA32(res, _sbc_proto_8[33], in[41]); - MULA32(res, _sbc_proto_8[32], in[57]); - MULA32(res, _sbc_proto_8[31], in[73]); - MULA32(res, -_sbc_proto_8[25], in[11]); - MULA32(res, -_sbc_proto_8[24], in[27]); - MULA32(res, -_sbc_proto_8[23], in[43]); - MULA32(res, -_sbc_proto_8[22], in[59]); - MULA32(res, -_sbc_proto_8[21], in[75]); + MUL(res, _sbc_proto_8[35], in[9]); + MULA(res, _sbc_proto_8[34], in[25]); + MULA(res, _sbc_proto_8[33], in[41]); + MULA(res, _sbc_proto_8[32], in[57]); + MULA(res, _sbc_proto_8[31], in[73]); + MULA(res, -_sbc_proto_8[25], in[11]); + MULA(res, -_sbc_proto_8[24], in[27]); + MULA(res, -_sbc_proto_8[23], in[43]); + MULA(res, -_sbc_proto_8[22], in[59]); + MULA(res, -_sbc_proto_8[21], in[75]); t[7] = SCALE8_STAGE1(res); MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index c8c72c75..625d4dd0 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -31,20 +31,20 @@ #define ASR_64(val, bits) ((-2 >> 1 == -1) ? \ ((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits))) -#define SCALE_PROTO4_TBL 16 +#define SCALE_PROTO4_TBL 15 #define SCALE_ANA4_TBL 16 -#define SCALE_PROTO8_TBL 16 +#define SCALE_PROTO8_TBL 15 #define SCALE_ANA8_TBL 16 #define SCALE_SPROTO4_TBL 16 #define SCALE_SPROTO8_TBL 16 #define SCALE_NPROTO4_TBL 10 #define SCALE_NPROTO8_TBL 12 #define SCALE_SAMPLES 14 -#define SCALE4_STAGE1_BITS 9 +#define SCALE4_STAGE1_BITS 10 #define SCALE4_STAGE2_BITS 21 #define SCALE4_STAGED1_BITS 18 #define SCALE4_STAGED2_BITS 23 -#define SCALE8_STAGE1_BITS 7 +#define SCALE8_STAGE1_BITS 8 #define SCALE8_STAGE2_BITS 24 #define SCALE8_STAGED1_BITS 18 #define SCALE8_STAGED2_BITS 23 @@ -64,8 +64,6 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } -#define MUL32(dst, a, b) { dst = (sbc_fixed_t) (a) * (b); } -#define MULA32(dst, a, b) { dst += (sbc_fixed_t) (a) * (b); } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h index 0da2a2d3..5e00caca 100644 --- a/sbc/sbc_tables.h +++ b/sbc/sbc_tables.h @@ -48,7 +48,7 @@ static const int sbc_offset8[4][8] = { #define SN4(val) ASR(val, SCALE_NPROTO4_TBL) #define SN8(val) ASR(val, SCALE_NPROTO8_TBL) -static const int16_t _sbc_proto_4[20] = { +static const int32_t _sbc_proto_4[20] = { SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548), SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7), SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737), @@ -56,11 +56,11 @@ static const int16_t _sbc_proto_4[20] = { SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000) }; -static const int16_t _anamatrix4[4] = { +static const int32_t _anamatrix4[4] = { SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0) }; -static const int16_t _sbc_proto_8[40] = { +static const int32_t _sbc_proto_8[40] = { SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930), SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28), SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc), @@ -115,7 +115,7 @@ static const int32_t sbc_proto_8_80m1[] = { SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a) }; -static const int16_t _anamatrix8[8] = { +static const int32_t _anamatrix8[8] = { SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40), SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000) }; -- cgit From 05a6e1afb3b0111e8fafcb8ca2d1ca8674390c11 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 28 Jan 2008 17:32:36 +0000 Subject: arm-assembly from cidoca for MULA --- sbc/sbc_math.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 625d4dd0..68b0f197 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -65,5 +65,13 @@ typedef long long sbc_extended_t; #define ADD(dst, src) { dst += src; } #define SUB(dst, src) { dst -= src; } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } -#define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } + +#ifdef __arm__ +#define MULA(res, a, b) __asm__( \ + "smlal %Q0, %R0, %2, %3" \ + : "=&r" (res) \ + : "0" (res), "r" (a), "r" (b)); +#else +#define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } +#endif -- cgit From 358888c52324aadb2d9814f2f5df5183706f70f7 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 28 Jan 2008 17:48:21 +0000 Subject: change function signature so the arm optimization will work --- sbc/sbc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 97614fb9..7d57b283 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -708,10 +708,15 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, state->position[0] = state->position[1] = 9 * frame->subbands; } - +#ifdef __arm__ +void _sbc_analyze_four(const int16_t *in, int32_t *out) +{ + sbc_extended_t register res asm("r4"); +#else static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) { sbc_extended_t res; +#endif sbc_fixed_t t[8]; sbc_extended_t s[5]; @@ -794,9 +799,15 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, state->position[ch] = 36; } +#ifdef __arm__ +void _sbc_analyze_eight(const int16_t *in, int32_t *out) +{ + sbc_extended_t register res asm("r4"); +#else static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) { sbc_extended_t res; +#endif sbc_fixed_t t[8]; sbc_extended_t s[8]; -- cgit From 6d205fda030a21d99ea5064b9501d58a11b6efa5 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Mon, 28 Jan 2008 18:00:51 +0000 Subject: revert arm conditional code --- sbc/sbc.c | 13 +------------ sbc/sbc_math.h | 8 -------- 2 files changed, 1 insertion(+), 20 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 7d57b283..97614fb9 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -708,15 +708,10 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, state->position[0] = state->position[1] = 9 * frame->subbands; } -#ifdef __arm__ -void _sbc_analyze_four(const int16_t *in, int32_t *out) -{ - sbc_extended_t register res asm("r4"); -#else + static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) { sbc_extended_t res; -#endif sbc_fixed_t t[8]; sbc_extended_t s[5]; @@ -799,15 +794,9 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, state->position[ch] = 36; } -#ifdef __arm__ -void _sbc_analyze_eight(const int16_t *in, int32_t *out) -{ - sbc_extended_t register res asm("r4"); -#else static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) { sbc_extended_t res; -#endif sbc_fixed_t t[8]; sbc_extended_t s[8]; diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 68b0f197..8c5ec3a7 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -66,12 +66,4 @@ typedef long long sbc_extended_t; #define SUB(dst, src) { dst -= src; } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } #define DIV2(dst, src) { dst = ASR(src, 1); } - -#ifdef __arm__ -#define MULA(res, a, b) __asm__( \ - "smlal %Q0, %R0, %2, %3" \ - : "=&r" (res) \ - : "0" (res), "r" (a), "r" (b)); -#else #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } -#endif -- cgit From c6d9a4373d855d72d7d7fe63718cd4dc79fd3881 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 29 Jan 2008 18:56:13 +0000 Subject: revert 16-bit state.X change (bad on arm) --- sbc/sbc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 97614fb9..a4f7b7dd 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -121,7 +121,7 @@ struct sbc_decoder_state { struct sbc_encoder_state { int subbands; int position[2]; - int16_t X[2][160]; + int32_t X[2][160]; }; /* @@ -709,7 +709,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, } -static inline void _sbc_analyze_four(const int16_t *in, int32_t *out) +static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) { sbc_extended_t res; sbc_fixed_t t[8]; @@ -794,7 +794,7 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, state->position[ch] = 36; } -static inline void _sbc_analyze_eight(const int16_t *in, int32_t *out) +static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) { sbc_extended_t res; sbc_fixed_t t[8]; @@ -921,7 +921,7 @@ static inline void sbc_analyze_eight(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int16_t *x = &state->X[ch][state->position[ch]]; + int32_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 8]; /* Input 8 Audio Samples */ -- cgit From 4b8bfb24c7666cb0b6eb26abe9a7d5072e3f9c4e Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Tue, 29 Jan 2008 19:47:49 +0000 Subject: one more .X 32-bitism --- sbc/sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index a4f7b7dd..e46c2b0f 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -778,7 +778,7 @@ static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) static inline void sbc_analyze_four(struct sbc_encoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int16_t *x = &state->X[ch][state->position[ch]]; + int32_t *x = &state->X[ch][state->position[ch]]; int16_t *pcm = &frame->pcm_sample[ch][blk * 4]; /* Input 4 Audio Samples */ -- cgit From a0832282a87d370ec5383b036015b013277d9041 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Wed, 30 Jan 2008 20:28:37 +0000 Subject: fix off-by-one in sbcdec --- sbc/sbcdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbc') diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 09a211a1..2fa3cbb9 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -125,7 +125,7 @@ static void decode(char *filename, char *output, int tofile) * length of the frame we just decoded count is the number of * decoded bytes yet to be written */ - if (count + len > BUF_SIZE) { + if (count + len >= BUF_SIZE) { /* buffer is too full to stuff decoded audio in so it * must be written to the device */ written = write(ad, buf, count); @@ -134,7 +134,7 @@ static void decode(char *filename, char *output, int tofile) } /* sanity check */ - if (count + len > BUF_SIZE) { + if (count + len >= BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded" " data (%d)\n", BUF_SIZE, len + count); -- cgit From 7f760a2f3624f26ac0569ed70405e11498aad308 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Wed, 30 Jan 2008 20:29:24 +0000 Subject: remove unused macros --- sbc/sbc_math.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 8c5ec3a7..2229d605 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -62,8 +62,5 @@ typedef long long sbc_extended_t; #define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS) #define SBC_FIXED_0(val) { val = 0; } -#define ADD(dst, src) { dst += src; } -#define SUB(dst, src) { dst -= src; } #define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } -#define DIV2(dst, src) { dst = ASR(src, 1); } #define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } -- cgit From 82540ead6bfe7d0398256b48500e6fbecb0e28e1 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Wed, 30 Jan 2008 20:37:49 +0000 Subject: change MUL/MULA semantics --- sbc/sbc.c | 339 +++++++++++++++++++++++++++++---------------------------- sbc/sbc_math.h | 4 +- 2 files changed, 173 insertions(+), 170 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index e46c2b0f..260e31c4 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -614,7 +614,8 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, /* Distribute the new matrix value to the shifted position */ SBC_FIXED_0(res); for (j = 0; j < 4; j++) - MULA(res, synmatrix4[i][j], frame->sb_sample[blk][ch][j]); + res = MULA(synmatrix4[i][j], + frame->sb_sample[blk][ch][j], res); state->V[ch][state->offset[ch][i]] = SCALE4_STAGED1(res); } @@ -623,10 +624,10 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, k = (i + 4) & 0xf; SBC_FIXED_0(res); for (j = 0; j < 10; idx++) { - MULA(res, state->V[ch][state->offset[ch][i]+j++], - sbc_proto_4_40m0[idx]); - MULA(res, state->V[ch][state->offset[ch][k]+j++], - sbc_proto_4_40m1[idx]); + res = MULA(state->V[ch][state->offset[ch][i]+j++], + sbc_proto_4_40m0[idx], res); + res = MULA(state->V[ch][state->offset[ch][k]+j++], + sbc_proto_4_40m1[idx], res); } /* Store in output, Q0 */ @@ -655,7 +656,8 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, SBC_FIXED_0(res); for (j = 0; j < 8; j++) { /* Q28 = Q15 * Q13 */ - MULA(res, synmatrix8[i][j], frame->sb_sample[blk][ch][j]); + res = MULA(synmatrix8[i][j], + frame->sb_sample[blk][ch][j], res); } /* Q10 */ state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); @@ -666,8 +668,10 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, k = (i + 8) & 0xf; SBC_FIXED_0(res); for (j = 0; j < 10; idx++) { - MULA(res, state->V[ch][state->offset[ch][i]+j++], sbc_proto_8_80m0[idx]); - MULA(res, state->V[ch][state->offset[ch][k]+j++], sbc_proto_8_80m1[idx]); + res = MULA(state->V[ch][state->offset[ch][i]+j++], + sbc_proto_8_80m0[idx], res); + res = MULA(state->V[ch][state->offset[ch][k]+j++], + sbc_proto_8_80m1[idx], res); } /* Store in output */ frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2(res); // Q0 @@ -708,67 +712,66 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, state->position[0] = state->position[1] = 9 * frame->subbands; } - static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) { - sbc_extended_t res; sbc_fixed_t t[8]; sbc_extended_t s[5]; - MUL(res, _sbc_proto_4[0], in[8] - in[32]); /* Q18 */ - MULA(res, _sbc_proto_4[1], in[16] - in[24]); - t[0] = SCALE4_STAGE1(res); /* Q8 */ - - MUL(res, _sbc_proto_4[2], in[1]); - MULA(res, _sbc_proto_4[3], in[9]); - MULA(res, _sbc_proto_4[4], in[17]); - MULA(res, _sbc_proto_4[5], in[25]); - MULA(res, _sbc_proto_4[6], in[33]); - t[1] = SCALE4_STAGE1(res); - - MUL(res, _sbc_proto_4[7], in[2]); - MULA(res, _sbc_proto_4[8], in[10]); - MULA(res, _sbc_proto_4[9], in[18]); - MULA(res, _sbc_proto_4[10], in[26]); - MULA(res, _sbc_proto_4[11], in[34]); - t[2] = SCALE4_STAGE1(res); - - MUL(res, _sbc_proto_4[12], in[3]); - MULA(res, _sbc_proto_4[13], in[11]); - MULA(res, _sbc_proto_4[14], in[19]); - MULA(res, _sbc_proto_4[15], in[27]); - MULA(res, _sbc_proto_4[16], in[35]); - t[3] = SCALE4_STAGE1(res); - - MUL(res, _sbc_proto_4[17], in[4] + in[36]); - MULA(res, _sbc_proto_4[18], in[12] + in[28]); - MULA(res, _sbc_proto_4[19], in[20]); - t[4] = SCALE4_STAGE1(res); - - MUL(res, _sbc_proto_4[16], in[5]); - MULA(res, _sbc_proto_4[15], in[13]); - MULA(res, _sbc_proto_4[14], in[21]); - MULA(res, _sbc_proto_4[13], in[29]); - MULA(res, _sbc_proto_4[12], in[37]); - t[5] = SCALE4_STAGE1(res); + t[0] = SCALE4_STAGE1( /* Q8 */ + MULA(_sbc_proto_4[0], in[8] - in[32], /* Q18 */ + MUL( _sbc_proto_4[1], in[16] - in[24]))); + + t[1] = SCALE4_STAGE1( + MULA(_sbc_proto_4[2], in[1], + MULA(_sbc_proto_4[3], in[9], + MULA(_sbc_proto_4[4], in[17], + MULA(_sbc_proto_4[5], in[25], + MUL( _sbc_proto_4[6], in[33])))))); + + t[2] = SCALE4_STAGE1( + MULA(_sbc_proto_4[7], in[2], + MULA(_sbc_proto_4[8], in[10], + MULA(_sbc_proto_4[9], in[18], + MULA(_sbc_proto_4[10], in[26], + MUL( _sbc_proto_4[11], in[34])))))); + + t[3] = SCALE4_STAGE1( + MULA(_sbc_proto_4[12], in[3], + MULA(_sbc_proto_4[13], in[11], + MULA(_sbc_proto_4[14], in[19], + MULA(_sbc_proto_4[15], in[27], + MUL( _sbc_proto_4[16], in[35])))))); + + t[4] = SCALE4_STAGE1( + MULA(_sbc_proto_4[17], in[4] + in[36], + MULA(_sbc_proto_4[18], in[12] + in[28], + MUL( _sbc_proto_4[19], in[20])))); + + t[5] = SCALE4_STAGE1( + MULA(_sbc_proto_4[16], in[5], + MULA(_sbc_proto_4[15], in[13], + MULA(_sbc_proto_4[14], in[21], + MULA(_sbc_proto_4[13], in[29], + MUL( _sbc_proto_4[12], in[37])))))); /* don't compute t[6]... this term always multiplies * with cos(pi/2) = 0 */ - MUL(res, _sbc_proto_4[6], in[7]); - MULA(res, _sbc_proto_4[5], in[15]); - MULA(res, _sbc_proto_4[4], in[23]); - MULA(res, _sbc_proto_4[3], in[31]); - MULA(res, _sbc_proto_4[2], in[39]); - t[7] = SCALE4_STAGE1(res); - - MUL(s[0], _anamatrix4[0], t[0] + t[4]); - MUL(s[1], _anamatrix4[2], t[2]); - MUL(s[2], _anamatrix4[1], t[1] + t[3]); - MULA(s[2], _anamatrix4[3], t[5]); - MUL(s[3], _anamatrix4[3], t[1] + t[3]); - MULA(s[3], _anamatrix4[1], - t[5] + t[7]); - MUL(s[4], _anamatrix4[3], t[7]); + t[7] = SCALE4_STAGE1( + MULA(_sbc_proto_4[6], in[7], + MULA(_sbc_proto_4[5], in[15], + MULA(_sbc_proto_4[4], in[23], + MULA(_sbc_proto_4[3], in[31], + MUL( _sbc_proto_4[2], in[39])))))); + + s[0] = MUL( _anamatrix4[0], t[0] + t[4]); + s[1] = MUL( _anamatrix4[2], t[2]); + s[2] = MULA(_anamatrix4[1], t[1] + t[3], + MUL(_anamatrix4[3], t[5])); + s[3] = MULA(_anamatrix4[3], t[1] + t[3], + MUL(_anamatrix4[1], -t[5] + t[7])); + s[4] = MUL( _anamatrix4[3], t[7]); + out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2] + s[4]); /* Q0 */ out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]); out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]); @@ -796,117 +799,117 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) { - sbc_extended_t res; sbc_fixed_t t[8]; sbc_extended_t s[8]; - MUL(res, _sbc_proto_8[0], (in[16] - in[64])); /* Q18 = Q18 * Q0 */ - MULA(res, _sbc_proto_8[1], (in[32] - in[48])); - MULA(res, _sbc_proto_8[2], in[4]); - MULA(res, _sbc_proto_8[3], in[20]); - MULA(res, _sbc_proto_8[4], in[36]); - MULA(res, _sbc_proto_8[5], in[52]); - t[0] = SCALE8_STAGE1(res); /* Q10 */ - - MUL(res, _sbc_proto_8[6], in[2]); - MULA(res, _sbc_proto_8[7], in[18]); - MULA(res, _sbc_proto_8[8], in[34]); - MULA(res, _sbc_proto_8[9], in[50]); - MULA(res, _sbc_proto_8[10], in[66]); - t[1] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[11], in[1]); - MULA(res, _sbc_proto_8[12], in[17]); - MULA(res, _sbc_proto_8[13], in[33]); - MULA(res, _sbc_proto_8[14], in[49]); - MULA(res, _sbc_proto_8[15], in[65]); - MULA(res, _sbc_proto_8[16], in[3]); - MULA(res, _sbc_proto_8[17], in[19]); - MULA(res, _sbc_proto_8[18], in[35]); - MULA(res, _sbc_proto_8[19], in[51]); - MULA(res, _sbc_proto_8[20], in[67]); - t[2] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[21], in[5]); - MULA(res, _sbc_proto_8[22], in[21]); - MULA(res, _sbc_proto_8[23], in[37]); - MULA(res, _sbc_proto_8[24], in[53]); - MULA(res, _sbc_proto_8[25], in[69]); - MULA(res, -_sbc_proto_8[15], in[15]); - MULA(res, -_sbc_proto_8[14], in[31]); - MULA(res, -_sbc_proto_8[13], in[47]); - MULA(res, -_sbc_proto_8[12], in[63]); - MULA(res, -_sbc_proto_8[11], in[79]); - t[3] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[26], in[6]); - MULA(res, _sbc_proto_8[27], in[22]); - MULA(res, _sbc_proto_8[28], in[38]); - MULA(res, _sbc_proto_8[29], in[54]); - MULA(res, _sbc_proto_8[30], in[70]); - MULA(res, -_sbc_proto_8[10], in[14]); - MULA(res, -_sbc_proto_8[9], in[30]); - MULA(res, -_sbc_proto_8[8], in[46]); - MULA(res, -_sbc_proto_8[7], in[62]); - MULA(res, -_sbc_proto_8[6], in[78]); - t[4] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[31], in[7]); - MULA(res, _sbc_proto_8[32], in[23]); - MULA(res, _sbc_proto_8[33], in[39]); - MULA(res, _sbc_proto_8[34], in[55]); - MULA(res, _sbc_proto_8[35], in[71]); - MULA(res, -_sbc_proto_8[20], in[13]); - MULA(res, -_sbc_proto_8[19], in[29]); - MULA(res, -_sbc_proto_8[18], in[45]); - MULA(res, -_sbc_proto_8[17], in[61]); - MULA(res, -_sbc_proto_8[16], in[77]); - t[5] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[36], in[8] + in[72]); - MULA(res, _sbc_proto_8[37], in[24] + in[56]); - MULA(res, _sbc_proto_8[38], in[40]); - MULA(res, -_sbc_proto_8[39], in[12]); - MULA(res, -_sbc_proto_8[5], in[28]); - MULA(res, -_sbc_proto_8[4], in[44]); - MULA(res, -_sbc_proto_8[3], in[60]); - MULA(res, -_sbc_proto_8[2], in[76]); - t[6] = SCALE8_STAGE1(res); - - MUL(res, _sbc_proto_8[35], in[9]); - MULA(res, _sbc_proto_8[34], in[25]); - MULA(res, _sbc_proto_8[33], in[41]); - MULA(res, _sbc_proto_8[32], in[57]); - MULA(res, _sbc_proto_8[31], in[73]); - MULA(res, -_sbc_proto_8[25], in[11]); - MULA(res, -_sbc_proto_8[24], in[27]); - MULA(res, -_sbc_proto_8[23], in[43]); - MULA(res, -_sbc_proto_8[22], in[59]); - MULA(res, -_sbc_proto_8[21], in[75]); - t[7] = SCALE8_STAGE1(res); - - MUL(s[0], _anamatrix8[0], t[0]); /* = Q14 * Q10 */ - MULA(s[0], _anamatrix8[1], t[6]); - MUL(s[1], _anamatrix8[7], t[1]); - MUL(s[2], _anamatrix8[2], t[2]); - MULA(s[2], _anamatrix8[3], t[3]); - MULA(s[2], _anamatrix8[4], t[5]); - MULA(s[2], _anamatrix8[5], t[7]); - MUL(s[3], _anamatrix8[6], t[4]); - MUL(s[4], _anamatrix8[3], t[2]); - MULA(s[4], -_anamatrix8[5], t[3]); - MULA(s[4], -_anamatrix8[2], t[5]); - MULA(s[4], -_anamatrix8[4], t[7]); - MUL(s[5], _anamatrix8[4], t[2]); - MULA(s[5], -_anamatrix8[2], t[3]); - MULA(s[5], _anamatrix8[5], t[5]); - MULA(s[5], _anamatrix8[3], t[7]); - MUL(s[6], _anamatrix8[1], t[0]); - MULA(s[6], -_anamatrix8[0], t[6]); - MUL(s[7], _anamatrix8[5], t[2]); - MULA(s[7], -_anamatrix8[4], t[3]); - MULA(s[7], _anamatrix8[3], t[5]); - MULA(s[7], -_anamatrix8[2], t[7]); + t[0] = SCALE8_STAGE1( /* Q10 */ + MULA(_sbc_proto_8[0], (in[16] - in[64]), /* Q18 = Q18 * Q0 */ + MULA(_sbc_proto_8[1], (in[32] - in[48]), + MULA(_sbc_proto_8[2], in[4], + MULA(_sbc_proto_8[3], in[20], + MULA(_sbc_proto_8[4], in[36], + MUL( _sbc_proto_8[5], in[52]))))))); + + t[1] = SCALE8_STAGE1( + MULA(_sbc_proto_8[6], in[2], + MULA(_sbc_proto_8[7], in[18], + MULA(_sbc_proto_8[8], in[34], + MULA(_sbc_proto_8[9], in[50], + MUL(_sbc_proto_8[10], in[66])))))); + + t[2] = SCALE8_STAGE1( + MULA(_sbc_proto_8[11], in[1], + MULA(_sbc_proto_8[12], in[17], + MULA(_sbc_proto_8[13], in[33], + MULA(_sbc_proto_8[14], in[49], + MULA(_sbc_proto_8[15], in[65], + MULA(_sbc_proto_8[16], in[3], + MULA(_sbc_proto_8[17], in[19], + MULA(_sbc_proto_8[18], in[35], + MULA(_sbc_proto_8[19], in[51], + MUL( _sbc_proto_8[20], in[67]))))))))))); + + t[3] = SCALE8_STAGE1( + MULA( _sbc_proto_8[21], in[5], + MULA( _sbc_proto_8[22], in[21], + MULA( _sbc_proto_8[23], in[37], + MULA( _sbc_proto_8[24], in[53], + MULA( _sbc_proto_8[25], in[69], + MULA(-_sbc_proto_8[15], in[15], + MULA(-_sbc_proto_8[14], in[31], + MULA(-_sbc_proto_8[13], in[47], + MULA(-_sbc_proto_8[12], in[63], + MUL( -_sbc_proto_8[11], in[79]))))))))))); + + t[4] = SCALE8_STAGE1( + MULA( _sbc_proto_8[26], in[6], + MULA( _sbc_proto_8[27], in[22], + MULA( _sbc_proto_8[28], in[38], + MULA( _sbc_proto_8[29], in[54], + MULA( _sbc_proto_8[30], in[70], + MULA(-_sbc_proto_8[10], in[14], + MULA(-_sbc_proto_8[9], in[30], + MULA(-_sbc_proto_8[8], in[46], + MULA(-_sbc_proto_8[7], in[62], + MUL( -_sbc_proto_8[6], in[78]))))))))))); + + t[5] = SCALE8_STAGE1( + MULA( _sbc_proto_8[31], in[7], + MULA( _sbc_proto_8[32], in[23], + MULA( _sbc_proto_8[33], in[39], + MULA( _sbc_proto_8[34], in[55], + MULA( _sbc_proto_8[35], in[71], + MULA(-_sbc_proto_8[20], in[13], + MULA(-_sbc_proto_8[19], in[29], + MULA(-_sbc_proto_8[18], in[45], + MULA(-_sbc_proto_8[17], in[61], + MUL( -_sbc_proto_8[16], in[77]))))))))))); + + t[6] = SCALE8_STAGE1( + MULA( _sbc_proto_8[36], (in[8] + in[72]), + MULA( _sbc_proto_8[37], (in[24] + in[56]), + MULA( _sbc_proto_8[38], in[40], + MULA(-_sbc_proto_8[39], in[12], + MULA(-_sbc_proto_8[5], in[28], + MULA(-_sbc_proto_8[4], in[44], + MULA(-_sbc_proto_8[3], in[60], + MUL( -_sbc_proto_8[2], in[76]))))))))); + + t[7] = SCALE8_STAGE1( + MULA( _sbc_proto_8[35], in[9], + MULA( _sbc_proto_8[34], in[25], + MULA( _sbc_proto_8[33], in[41], + MULA( _sbc_proto_8[32], in[57], + MULA( _sbc_proto_8[31], in[73], + MULA(-_sbc_proto_8[25], in[11], + MULA(-_sbc_proto_8[24], in[27], + MULA(-_sbc_proto_8[23], in[43], + MULA(-_sbc_proto_8[22], in[59], + MUL( -_sbc_proto_8[21], in[75]))))))))))); + + s[0] = MULA( _anamatrix8[0], t[0], + MUL( _anamatrix8[1], t[6])); + s[1] = MUL( _anamatrix8[7], t[1]); + s[2] = MULA( _anamatrix8[2], t[2], + MULA( _anamatrix8[3], t[3], + MULA( _anamatrix8[4], t[5], + MUL( _anamatrix8[5], t[7])))); + s[3] = MUL( _anamatrix8[6], t[4]); + s[4] = MULA( _anamatrix8[3], t[2], + MULA(-_anamatrix8[5], t[3], + MULA(-_anamatrix8[2], t[5], + MUL( -_anamatrix8[4], t[7])))); + s[5] = MULA( _anamatrix8[4], t[2], + MULA(-_anamatrix8[2], t[3], + MULA( _anamatrix8[5], t[5], + MUL( _anamatrix8[3], t[7])))); + s[6] = MULA( _anamatrix8[1], t[0], + MUL( -_anamatrix8[0], t[6])); + s[7] = MULA( _anamatrix8[5], t[2], + MULA(-_anamatrix8[4], t[3], + MULA( _anamatrix8[3], t[5], + MUL( -_anamatrix8[2], t[7])))); + out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]); out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]); out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]); diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 2229d605..9aa8c366 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -62,5 +62,5 @@ typedef long long sbc_extended_t; #define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS) #define SBC_FIXED_0(val) { val = 0; } -#define MUL(dst, a, b) { dst = (sbc_extended_t) (a) * (b); } -#define MULA(dst, a, b) { dst += (sbc_extended_t) (a) * (b); } +#define MUL(a, b) ((sbc_extended_t)(a) * (b)) +#define MULA(a, b, res) ((sbc_extended_t)(a) * (b) + (res)) -- cgit From e51de7f6fb5385c9df62842ce9cf92f9fd33f040 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Wed, 30 Jan 2008 20:39:33 +0000 Subject: arm assembly version of MULA --- sbc/sbc_math.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sbc') diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 9aa8c366..8db67ca8 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -63,4 +63,14 @@ typedef long long sbc_extended_t; #define SBC_FIXED_0(val) { val = 0; } #define MUL(a, b) ((sbc_extended_t)(a) * (b)) +#ifdef __arm__ +#define MULA(a, b, res) ({ \ + long long tmp = res; \ + __asm__( \ + "smlal %Q0, %R0, %2, %3" \ + : "=&r" (tmp) \ + : "0" (tmp), "r" (a), "r" (b)); \ + tmp; }) +#else #define MULA(a, b, res) ((sbc_extended_t)(a) * (b) + (res)) +#endif -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- sbc/sbc.c | 3 +-- sbc/sbc.h | 2 +- sbc/sbc_math.h | 2 +- sbc/sbc_tables.h | 2 +- sbc/sbcdec.c | 4 ++-- sbc/sbcenc.c | 4 ++-- sbc/sbcinfo.c | 2 +- sbc/sbctester.c | 8 ++++---- 8 files changed, 13 insertions(+), 14 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 260e31c4..642a7676 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2008 Brad Midgley * @@ -43,7 +43,6 @@ #include #include - #include "sbc_math.h" #include "sbc_tables.h" diff --git a/sbc/sbc.h b/sbc/sbc.h index cdf0d83e..8d31c9d4 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 8db67ca8..007a1e9c 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2008 Brad Midgley * diff --git a/sbc/sbc_tables.h b/sbc/sbc_tables.h index 5e00caca..7ac4e68b 100644 --- a/sbc/sbc_tables.h +++ b/sbc/sbc_tables.h @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * Copyright (C) 2004-2005 Henryk Ploetz * Copyright (C) 2005-2006 Brad Midgley * diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 2fa3cbb9..6c0b4bfa 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) decoder * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -171,7 +171,7 @@ free: static void usage(void) { printf("SBC decoder utility ver %s\n", VERSION); - printf("Copyright (c) 2004-2007 Marcel Holtmann\n\n"); + printf("Copyright (c) 2004-2008 Marcel Holtmann\n\n"); printf("Usage:\n" "\tsbcdec [options] file(s)\n" diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index cba31c7b..cf5e1533 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) encoder * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -190,7 +190,7 @@ done: static void usage(void) { printf("SBC encoder utility ver %s\n", VERSION); - printf("Copyright (c) 2004-2007 Marcel Holtmann\n\n"); + printf("Copyright (c) 2004-2008 Marcel Holtmann\n\n"); printf("Usage:\n" "\tsbcenc [options] file(s)\n" diff --git a/sbc/sbcinfo.c b/sbc/sbcinfo.c index 7b6d416d..c1f0631a 100644 --- a/sbc/sbcinfo.c +++ b/sbc/sbcinfo.c @@ -2,7 +2,7 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/sbc/sbctester.c b/sbc/sbctester.c index af4d1244..260f34ae 100644 --- a/sbc/sbctester.c +++ b/sbc/sbctester.c @@ -2,8 +2,8 @@ * * Bluetooth low-complexity, subband codec (SBC) library * - * Copyright (C) 2007 Marcel Holtmann - * Copyright (C) 2007 Frederic Dalleau + * Copyright (C) 2007-2008 Marcel Holtmann + * Copyright (C) 2007-2008 Frederic Dalleau * * * This program is free software; you can redistribute it and/or modify @@ -247,8 +247,8 @@ static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref, static void usage() { printf("SBC conformance test ver %s\n", VERSION); - printf("Copyright (c) 2007 Marcel Holtmann\n"); - printf("Copyright (c) 2007 Frederic Dalleau\n\n"); + printf("Copyright (c) 2007-2008 Marcel Holtmann\n"); + printf("Copyright (c) 2007-2008 Frederic Dalleau\n\n"); printf("Usage:\n" "\tsbctester reference.wav checkfile.wav\n" -- cgit From ff51f4b0b2724754184baa08b09a47cad7b7b4d5 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 15 Feb 2008 18:06:32 +0000 Subject: fix for decoder noise at high bitpools --- sbc/sbc.c | 12 ++---------- sbc/sbc_math.h | 16 ++++++++-------- 2 files changed, 10 insertions(+), 18 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 642a7676..bc0b771c 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -543,16 +543,8 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, for (sb = 0; sb < frame->subbands; sb++) { if (levels[ch][sb] > 0) { frame->sb_sample[blk][ch][sb] = - (((frame->audio_sample[blk][ch][sb] << 16) | 0x8000) / - levels[ch][sb]) - 0x8000; - - frame->sb_sample[blk][ch][sb] >>= 3; - - /* Q13 */ - frame->sb_sample[blk][ch][sb] = - (frame->sb_sample[blk][ch][sb] << - (frame->scale_factor[ch][sb] + 1)); - + (((frame->audio_sample[blk][ch][sb] << 1) | 1) << frame->scale_factor[ch][sb])/ + levels[ch][sb] - (1 << frame->scale_factor[ch][sb]); } else frame->sb_sample[blk][ch][sb] = 0; } diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 007a1e9c..6c3fe2f2 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -40,14 +40,14 @@ #define SCALE_NPROTO4_TBL 10 #define SCALE_NPROTO8_TBL 12 #define SCALE_SAMPLES 14 -#define SCALE4_STAGE1_BITS 10 -#define SCALE4_STAGE2_BITS 21 -#define SCALE4_STAGED1_BITS 18 -#define SCALE4_STAGED2_BITS 23 -#define SCALE8_STAGE1_BITS 8 -#define SCALE8_STAGE2_BITS 24 -#define SCALE8_STAGED1_BITS 18 -#define SCALE8_STAGED2_BITS 23 +#define SCALE4_STAGE1_BITS 16 +#define SCALE4_STAGE2_BITS 16 +#define SCALE4_STAGED1_BITS 14 +#define SCALE4_STAGED2_BITS 14 +#define SCALE8_STAGE1_BITS 16 +#define SCALE8_STAGE2_BITS 16 +#define SCALE8_STAGED1_BITS 14 +#define SCALE8_STAGED2_BITS 14 typedef int32_t sbc_fixed_t; typedef long long sbc_extended_t; -- cgit From ce342bf2524b69b19ea5a4ad604faf1aa40ad19c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 19 Feb 2008 19:47:25 +0000 Subject: Introduce sbc new API. --- sbc/sbc.c | 310 ++++++++++++++++++++++++++++++----------------------------- sbc/sbc.h | 47 +++++++-- sbc/sbcdec.c | 31 +++++- sbc/sbcenc.c | 30 +++++- 4 files changed, 247 insertions(+), 171 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index bc0b771c..0b0bbc94 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -50,55 +49,31 @@ #define SBC_SYNCWORD 0x9C -/* sampling frequency */ -#define SBC_FS_16 0x00 -#define SBC_FS_32 0x01 -#define SBC_FS_44 0x02 -#define SBC_FS_48 0x03 - -/* nrof_blocks */ -#define SBC_NB_4 0x00 -#define SBC_NB_8 0x01 -#define SBC_NB_12 0x02 -#define SBC_NB_16 0x03 - -/* channel mode */ -#define SBC_CM_MONO 0x00 -#define SBC_CM_DUAL_CHANNEL 0x01 -#define SBC_CM_STEREO 0x02 -#define SBC_CM_JOINT_STEREO 0x03 - -/* allocation mode */ -#define SBC_AM_LOUDNESS 0x00 -#define SBC_AM_SNR 0x01 - -/* subbands */ -#define SBC_SB_4 0x00 -#define SBC_SB_8 0x01 - /* This structure contains an unpacked SBC frame. Yes, there is probably quite some unused space herein */ struct sbc_frame { - uint16_t sampling_frequency; /* in kHz */ + uint8_t frequency; + uint8_t block_mode; uint8_t blocks; enum { - MONO = SBC_CM_MONO, - DUAL_CHANNEL = SBC_CM_DUAL_CHANNEL, - STEREO = SBC_CM_STEREO, - JOINT_STEREO = SBC_CM_JOINT_STEREO - } channel_mode; + MONO = SBC_MODE_MONO, + DUAL_CHANNEL = SBC_MODE_DUAL_CHANNEL, + STEREO = SBC_MODE_STEREO, + JOINT_STEREO = SBC_MODE_JOINT_STEREO + } mode; uint8_t channels; enum { LOUDNESS = SBC_AM_LOUDNESS, SNR = SBC_AM_SNR - } allocation_method; + } allocation; + uint8_t subband_mode; uint8_t subbands; uint8_t bitpool; uint8_t codesize; uint8_t length; /* bit number x set means joint stereo has been used in subband x */ - uint8_t join; + uint8_t joint; /* only the lower 4 bits of every element are to be used */ uint8_t scale_factor[2][8]; @@ -187,15 +162,17 @@ static uint8_t sbc_crc8(const uint8_t *data, size_t len) * Takes a pointer to the frame in question, a pointer to the bits array and * the sampling frequency (as 2 bit integer) */ -static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], uint8_t sf) +static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]) { - if (frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) { + uint8_t sf = frame->frequency; + + if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; for (ch = 0; ch < frame->channels; ch++) { max_bitneed = 0; - if (frame->allocation_method == SNR) { + if (frame->allocation == SNR) { for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; if (bitneed[ch][sb] > max_bitneed) @@ -269,12 +246,12 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], ui } - } else if (frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) { + } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; max_bitneed = 0; - if (frame->allocation_method == SNR) { + if (frame->allocation == SNR) { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; @@ -395,9 +372,6 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, int crc_pos = 0; int32_t temp; - uint8_t sf; /* sampling_frequency, temporarily needed as - array index */ - int ch, sb, blk, bit; /* channel, subband, block and bit standard counters */ int bits[2][8]; /* bits distribution */ @@ -409,39 +383,26 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, if (data[0] != SBC_SYNCWORD) return -2; - sf = (data[1] >> 6) & 0x03; - switch (sf) { - case SBC_FS_16: - frame->sampling_frequency = 16000; - break; - case SBC_FS_32: - frame->sampling_frequency = 32000; - break; - case SBC_FS_44: - frame->sampling_frequency = 44100; - break; - case SBC_FS_48: - frame->sampling_frequency = 48000; - break; - } + frame->frequency = (data[1] >> 6) & 0x03; - switch ((data[1] >> 4) & 0x03) { - case SBC_NB_4: + frame->block_mode = (data[1] >> 4) & 0x03; + switch (frame->block_mode) { + case SBC_BLK_4: frame->blocks = 4; break; - case SBC_NB_8: + case SBC_BLK_8: frame->blocks = 8; break; - case SBC_NB_12: + case SBC_BLK_12: frame->blocks = 12; break; - case SBC_NB_16: + case SBC_BLK_16: frame->blocks = 16; break; } - frame->channel_mode = (data[1] >> 2) & 0x03; - switch (frame->channel_mode) { + frame->mode = (data[1] >> 2) & 0x03; + switch (frame->mode) { case MONO: frame->channels = 1; break; @@ -452,17 +413,18 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, break; } - frame->allocation_method = (data[1] >> 1) & 0x01; + frame->allocation = (data[1] >> 1) & 0x01; - frame->subbands = (data[1] & 0x01) ? 8 : 4; + frame->subband_mode = (data[1] & 0x01); + frame->subbands = frame->subband_mode ? 8 : 4; frame->bitpool = data[2]; - if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && + if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) && frame->bitpool > 16 * frame->subbands) return -4; - if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && + if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) && frame->bitpool > 32 * frame->subbands) return -4; @@ -474,13 +436,13 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, crc_header[1] = data[2]; crc_pos = 16; - if (frame->channel_mode == JOINT_STEREO) { + if (frame->mode == JOINT_STEREO) { if (len * 8 < consumed + frame->subbands) return -1; - frame->join = 0x00; + frame->joint = 0x00; for (sb = 0; sb < frame->subbands - 1; sb++) - frame->join |= ((data[4] >> (7 - sb)) & 0x01) << sb; + frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb; if (frame->subbands == 4) crc_header[crc_pos / 8] = data[4] & 0xf0; else @@ -509,7 +471,7 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, if (data[3] != sbc_crc8(crc_header, crc_pos)) return -3; - sbc_calculate_bits(frame, bits, sf); + sbc_calculate_bits(frame, bits); for (blk = 0; blk < frame->blocks; blk++) { for (ch = 0; ch < frame->channels; ch++) { @@ -551,10 +513,10 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, } } - if (frame->channel_mode == JOINT_STEREO) { + if (frame->mode == JOINT_STEREO) { for (blk = 0; blk < frame->blocks; blk++) { for (sb = 0; sb < frame->subbands; sb++) { - if (frame->join & (0x01 << sb)) { + if (frame->joint & (0x01 << sb)) { temp = frame->sb_sample[blk][0][sb] + frame->sb_sample[blk][1][sb]; frame->sb_sample[blk][1][sb] = @@ -980,8 +942,6 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int crc_pos = 0; - /* Sampling frequency as temporary value for table lookup */ - uint8_t sf; uint16_t audio_sample; int ch, sb, blk, bit; /* channel, subband, block and bit counters */ @@ -992,42 +952,13 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[0] = SBC_SYNCWORD; - if (frame->sampling_frequency == 16000) { - data[1] = (SBC_FS_16 & 0x03) << 6; - sf = SBC_FS_16; - } else if (frame->sampling_frequency == 32000) { - data[1] = (SBC_FS_32 & 0x03) << 6; - sf = SBC_FS_32; - } else if (frame->sampling_frequency == 44100) { - data[1] = (SBC_FS_44 & 0x03) << 6; - sf = SBC_FS_44; - } else if (frame->sampling_frequency == 48000) { - data[1] = (SBC_FS_48 & 0x03) << 6; - sf = SBC_FS_48; - } else - return -2; + data[1] = (frame->frequency & 0x03) << 6; - switch (frame->blocks) { - case 4: - data[1] |= (SBC_NB_4 & 0x03) << 4; - break; - case 8: - data[1] |= (SBC_NB_8 & 0x03) << 4; - break; - case 12: - data[1] |= (SBC_NB_12 & 0x03) << 4; - break; - case 16: - data[1] |= (SBC_NB_16 & 0x03) << 4; - break; - default: - return -3; - break; - } + data[1] |= (frame->block_mode & 0x03) << 4; - data[1] |= (frame->channel_mode & 0x03) << 2; + data[1] |= (frame->mode & 0x03) << 2; - data[1] |= (frame->allocation_method & 0x01) << 1; + data[1] |= (frame->allocation & 0x01) << 1; switch (frame->subbands) { case 4: @@ -1043,11 +974,11 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[2] = frame->bitpool; - if ((frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) && + if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) && frame->bitpool > frame->subbands << 4) return -5; - if ((frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) && + if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) && frame->bitpool > frame->subbands << 5) return -5; @@ -1072,14 +1003,14 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) } } - if (frame->channel_mode == JOINT_STEREO) { + if (frame->mode == JOINT_STEREO) { /* like frame->sb_sample but joint stereo */ int32_t sb_sample_j[16][2]; /* scalefactor and scale_factor in joint case */ u_int32_t scalefactor_j[2]; uint8_t scale_factor_j[2]; - frame->join = 0; + frame->joint = 0; for (sb = 0; sb < frame->subbands - 1; sb++) { scale_factor_j[0] = 0; @@ -1111,7 +1042,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) if ((scalefactor[0][sb] + scalefactor[1][sb]) > (scalefactor_j[0] + scalefactor_j[1]) ) { /* use joint stereo for this subband */ - frame->join |= 1 << sb; + frame->joint |= 1 << sb; frame->scale_factor[0][sb] = scale_factor_j[0]; frame->scale_factor[1][sb] = scale_factor_j[1]; scalefactor[0][sb] = scalefactor_j[0]; @@ -1127,7 +1058,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[4] = 0; for (sb = 0; sb < frame->subbands - 1; sb++) - data[4] |= ((frame->join >> sb) & 0x01) << (frame->subbands - 1 - sb); + data[4] |= ((frame->joint >> sb) & 0x01) << (frame->subbands - 1 - sb); crc_header[crc_pos >> 3] = data[4]; @@ -1153,7 +1084,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len) data[3] = sbc_crc8(crc_header, crc_pos); - sbc_calculate_bits(frame, bits, sf); + sbc_calculate_bits(frame, bits); for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) @@ -1198,13 +1129,18 @@ struct sbc_priv { static void sbc_set_defaults(sbc_t *sbc, unsigned long flags) { - sbc->rate = 44100; - sbc->channels = 2; - sbc->joint = 0; - sbc->subbands = 8; - sbc->blocks = 16; + sbc->frequency = SBC_FREQ_44100; + sbc->mode = SBC_MODE_STEREO; + sbc->subbands = SBC_SB_8; + sbc->blocks = SBC_BLK_16; sbc->bitpool = 32; - sbc->swap = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + sbc->endian = SBC_LE; +#elif __BYTE_ORDER == __BIG_ENDIAN + sbc->endian = SBC_BE; +#else +#error "Unknown byte order" +#endif } int sbc_init(sbc_t *sbc, unsigned long flags) @@ -1248,10 +1184,11 @@ int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, sbc_decoder_init(&priv->dec_state, &priv->frame); priv->init = 1; - sbc->rate = priv->frame.sampling_frequency; - sbc->channels = priv->frame.channels; - sbc->subbands = priv->frame.subbands; - sbc->blocks = priv->frame.blocks; + sbc->frequency = priv->frame.frequency; + sbc->mode = priv->frame.mode; + sbc->subbands = priv->frame.subband_mode; + sbc->blocks = priv->frame.block_mode; + sbc->allocation = priv->frame.allocation; sbc->bitpool = priv->frame.bitpool; priv->frame.codesize = sbc_get_codesize(sbc); @@ -1276,7 +1213,13 @@ int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, int16_t s; s = priv->frame.pcm_sample[ch][i]; - if (sbc->swap) { +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (sbc->endian == SBC_BE) { +#elif __BYTE_ORDER == __BIG_ENDIAN + if (sbc->endian == SBC_LE) { +#else +#error "Unknown byte order" +#endif *ptr++ = (s & 0xff00) >> 8; *ptr++ = (s & 0x00ff); } else { @@ -1308,20 +1251,14 @@ int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, *written = 0; if (!priv->init) { - priv->frame.sampling_frequency = sbc->rate; - priv->frame.channels = sbc->channels; - - if (sbc->channels > 1) { - if (sbc->joint) - priv->frame.channel_mode = JOINT_STEREO; - else - priv->frame.channel_mode = STEREO; - } else - priv->frame.channel_mode = MONO; - - priv->frame.allocation_method = sbc->allocation; - priv->frame.subbands = sbc->subbands; - priv->frame.blocks = sbc->blocks; + priv->frame.frequency = sbc->frequency; + priv->frame.mode = sbc->mode; + priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + priv->frame.allocation = sbc->allocation; + priv->frame.subband_mode = sbc->subbands; + priv->frame.subbands = sbc->subbands ? 8 : 4; + priv->frame.block_mode = sbc->blocks; + priv->frame.blocks = 4 + (sbc->blocks * 4); priv->frame.bitpool = sbc->bitpool; priv->frame.codesize = sbc_get_codesize(sbc); priv->frame.length = sbc_get_frame_length(sbc); @@ -1341,10 +1278,15 @@ int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, ptr = input; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { - for (ch = 0; ch < sbc->channels; ch++) { + for (ch = 0; ch < priv->frame.channels; ch++) { int16_t s; - - if (sbc->swap) +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (sbc->endian == SBC_BE) +#elif __BYTE_ORDER == __BIG_ENDIAN + if (sbc->endian == SBC_LE) +#else +#error "Unknown byte order" +#endif s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff); else s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8; @@ -1360,7 +1302,7 @@ int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, if (written) *written = framelen; - return samples * sbc->channels * 2; + return samples * priv->frame.channels * 2; } void sbc_finish(sbc_t *sbc) @@ -1377,27 +1319,89 @@ void sbc_finish(sbc_t *sbc) int sbc_get_frame_length(sbc_t *sbc) { int ret; + uint8_t subbands, channels, blocks, joint; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0; + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + channels = priv->frame.channels; + joint = priv->frame.joint; + } - ret = 4 + (4 * sbc->subbands * sbc->channels) / 8; + ret = 4 + (4 * subbands * channels) / 8; /* This term is not always evenly divide so we round it up */ - if (sbc->channels == 1) - ret += ((sbc->blocks * sbc->channels * sbc->bitpool) + 7) / 8; + if (channels == 1) + ret += ((blocks * channels * sbc->bitpool) + 7) / 8; else - ret += (((sbc->joint ? sbc->subbands : 0) + sbc->blocks * sbc->bitpool) - + 7) / 8; + ret += (((joint ? subbands : 0) + blocks * sbc->bitpool) + 7) + / 8; return ret; } int sbc_get_frame_duration(sbc_t *sbc) { - return (1000000 * sbc->blocks * sbc->subbands) / sbc->rate; + uint8_t subbands, blocks; + uint16_t frequency; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + } + + switch (sbc->frequency) { + case SBC_FREQ_16000: + frequency = 16000; + break; + + case SBC_FREQ_32000: + frequency = 32000; + break; + + case SBC_FREQ_44100: + frequency = 44100; + break; + + case SBC_FREQ_48000: + frequency = 48000; + break; + default: + return 0; + } + + return (1000000 * blocks * subbands) / frequency; } int sbc_get_codesize(sbc_t *sbc) { - return sbc->subbands * sbc->blocks * sbc->channels * 2; + uint8_t subbands, channels, blocks; + struct sbc_priv *priv; + + priv = sbc->priv; + if (!priv->init) { + subbands = sbc->subbands ? 8 : 4; + blocks = 4 + (sbc->blocks * 4); + channels = sbc->mode == SBC_MODE_MONO ? 1 : 2; + } else { + subbands = priv->frame.subbands; + blocks = priv->frame.blocks; + channels = priv->frame.channels; + } + + return subbands * blocks * channels * 2; } int sbc_reinit(sbc_t *sbc, unsigned long flags) diff --git a/sbc/sbc.h b/sbc/sbc.h index 8d31c9d4..ab47e329 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -30,17 +30,48 @@ extern "C" { #endif +#include + +/* 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; - int rate; - int channels; - int joint; - int allocation; - int blocks; - int subbands; - int bitpool; - int swap; + uint8_t frequency; + uint8_t blocks; + uint8_t subbands; + uint8_t mode; + uint8_t allocation; + uint8_t bitpool; + uint8_t endian; void *priv; }; diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 6c0b4bfa..5ac02b44 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -47,7 +47,7 @@ static void decode(char *filename, char *output, int tofile) off_t filesize; sbc_t sbc; int fd, ad, pos, streamlen, framelen, count, written, len; - int format = AFMT_S16_BE; + int format = AFMT_S16_BE, frequency, channels; if (stat(filename, &st) < 0) { fprintf(stderr, "Can't get size of file %s: %s\n", @@ -95,24 +95,45 @@ static void decode(char *filename, char *output, int tofile) } sbc_init(&sbc, 0L); - sbc.swap = 1; + sbc.endian = SBC_BE; framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len); - printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); + channels = sbc.mode == SBC_MODE_MONO ? 1 : 2; + switch (sbc.frequency) { + case SBC_FREQ_16000: + frequency = 16000; + break; + + case SBC_FREQ_32000: + frequency = 32000; + break; + + case SBC_FREQ_44100: + frequency = 44100; + break; + + case SBC_FREQ_48000: + frequency = 48000; + break; + default: + frequency = 0; + } + + printf("%d Hz, %d channels\n", frequency, channels); if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { fprintf(stderr, "Can't set audio format on %s: %s\n", output, strerror(errno)); goto close; } - if (ioctl(ad, SNDCTL_DSP_CHANNELS, &sbc.channels) < 0) { + if (ioctl(ad, SNDCTL_DSP_CHANNELS, &channels) < 0) { fprintf(stderr, "Can't set number of channels on %s: %s\n", output, strerror(errno)); goto close; } - if (ioctl(ad, SNDCTL_DSP_SPEED, &sbc.rate) < 0) { + if (ioctl(ad, SNDCTL_DSP_SPEED, &frequency) < 0) { fprintf(stderr, "Can't set audio rate on %s: %s\n", output, strerror(errno)); goto close; diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index cf5e1533..e17f8fdb 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -140,11 +140,31 @@ static void encode(char *filename, int subbands, int joint) sbc_init(&sbc, 0L); - sbc.rate = BE_INT(au_hdr->sample_rate); - sbc.channels = BE_INT(au_hdr->channels); - sbc.subbands = subbands; - sbc.joint = joint; - sbc.swap = 1; + switch (BE_INT(au_hdr->sample_rate)) { + case 16000: + sbc.frequency = SBC_FREQ_16000; + break; + case 32000: + sbc.frequency = SBC_FREQ_32000; + break; + case 44100: + sbc.frequency = SBC_FREQ_44100; + break; + case 48000: + sbc.frequency = SBC_FREQ_48000; + break; + } + + sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8; + + if (BE_INT(au_hdr->channels) == 1) + sbc.mode = SBC_MODE_MONO; + else if (joint) + sbc.mode = SBC_MODE_JOINT_STEREO; + else + sbc.mode = SBC_MODE_STEREO; + + sbc.endian = SBC_BE; count = BE_INT(au_hdr->data_size); size = len - BE_INT(au_hdr->hdr_size); memmove(input, input + BE_INT(au_hdr->hdr_size), size); -- cgit From 4170955ad1f97eb8b7bf4f96025a654dab531571 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 22 Feb 2008 13:41:02 +0000 Subject: Replace 64bits multiplies by 32bits to further optimize the code --- sbc/sbc.c | 10 ++++------ sbc/sbc_math.h | 54 +++++++++++++++++++++++++----------------------------- 2 files changed, 29 insertions(+), 35 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 0b0bbc94..21a68063 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -551,7 +551,7 @@ static inline void sbc_synthesize_four(struct sbc_decoder_state *state, struct sbc_frame *frame, int ch, int blk) { int i, j, k, idx; - sbc_extended_t res; + sbc_fixed_t res; for (i = 0; i < 8; i++) { /* Shifting */ @@ -592,7 +592,7 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, struct sbc_frame *frame, int ch, int blk) { int i, j, k, idx; - sbc_extended_t res; + sbc_fixed_t res; for (i = 0; i < 16; i++) { /* Shifting */ @@ -667,8 +667,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state, static inline void _sbc_analyze_four(const int32_t *in, int32_t *out) { - sbc_fixed_t t[8]; - sbc_extended_t s[5]; + sbc_fixed_t t[8], s[5]; t[0] = SCALE4_STAGE1( /* Q8 */ MULA(_sbc_proto_4[0], in[8] - in[32], /* Q18 */ @@ -752,8 +751,7 @@ static inline void sbc_analyze_four(struct sbc_encoder_state *state, static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out) { - sbc_fixed_t t[8]; - sbc_extended_t s[8]; + sbc_fixed_t t[8], s[8]; t[0] = SCALE8_STAGE1( /* Q10 */ MULA(_sbc_proto_8[0], (in[16] - in[64]), /* Q18 = Q18 * Q0 */ diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 6c3fe2f2..5d3da8d9 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -28,49 +28,45 @@ 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 ASR_64(val, bits) ((-2 >> 1 == -1) ? \ - ((long long)(val)) >> (bits) : ((long long) (val)) / (1 << (bits))) #define SCALE_PROTO4_TBL 15 #define SCALE_ANA4_TBL 16 -#define SCALE_PROTO8_TBL 15 -#define SCALE_ANA8_TBL 16 -#define SCALE_SPROTO4_TBL 16 -#define SCALE_SPROTO8_TBL 16 -#define SCALE_NPROTO4_TBL 10 -#define SCALE_NPROTO8_TBL 12 -#define SCALE_SAMPLES 14 +#define SCALE_PROTO8_TBL 16 +#define SCALE_ANA8_TBL 17 +#define SCALE_SPROTO4_TBL 15 +#define SCALE_SPROTO8_TBL 14 +#define SCALE_NPROTO4_TBL 13 +#define SCALE_NPROTO8_TBL 11 #define SCALE4_STAGE1_BITS 16 -#define SCALE4_STAGE2_BITS 16 -#define SCALE4_STAGED1_BITS 14 -#define SCALE4_STAGED2_BITS 14 -#define SCALE8_STAGE1_BITS 16 -#define SCALE8_STAGE2_BITS 16 -#define SCALE8_STAGED1_BITS 14 -#define SCALE8_STAGED2_BITS 14 +#define SCALE4_STAGE2_BITS 15 +#define SCALE4_STAGED1_BITS 12 +#define SCALE4_STAGED2_BITS 16 +#define SCALE8_STAGE1_BITS 15 +#define SCALE8_STAGE2_BITS 15 +#define SCALE8_STAGED1_BITS 15 +#define SCALE8_STAGED2_BITS 16 typedef int32_t sbc_fixed_t; -typedef long long sbc_extended_t; -#define SCALE4_STAGE1(src) ASR_64(src, SCALE4_STAGE1_BITS) -#define SCALE4_STAGE2(src) ASR_64(src, SCALE4_STAGE2_BITS) -#define SCALE4_STAGED1(src) ASR_64(src, SCALE4_STAGED1_BITS) -#define SCALE4_STAGED2(src) ASR_64(src, SCALE4_STAGED2_BITS) -#define SCALE8_STAGE1(src) ASR_64(src, SCALE8_STAGE1_BITS) -#define SCALE8_STAGE2(src) ASR_64(src, SCALE8_STAGE2_BITS) -#define SCALE8_STAGED1(src) ASR_64(src, SCALE8_STAGED1_BITS) -#define SCALE8_STAGED2(src) ASR_64(src, SCALE8_STAGED2_BITS) +#define SCALE4_STAGE1(src) ASR(src, SCALE4_STAGE1_BITS) +#define SCALE4_STAGE2(src) ASR(src, SCALE4_STAGE2_BITS) +#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS) +#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS) +#define SCALE8_STAGE1(src) ASR(src, SCALE8_STAGE1_BITS) +#define SCALE8_STAGE2(src) ASR(src, SCALE8_STAGE2_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) ((sbc_extended_t)(a) * (b)) +#define MUL(a, b) ((a) * (b)) #ifdef __arm__ #define MULA(a, b, res) ({ \ - long long tmp = res; \ + int tmp = res; \ __asm__( \ - "smlal %Q0, %R0, %2, %3" \ + "mla %0, %2, %3, %0" \ : "=&r" (tmp) \ : "0" (tmp), "r" (a), "r" (b)); \ tmp; }) #else -#define MULA(a, b, res) ((sbc_extended_t)(a) * (b) + (res)) +#define MULA(a, b, res) ((a) * (b) + (res)) #endif -- cgit From 7a68b05beaed5944dcd88f23002c9f55a2f74ba6 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Fri, 29 Feb 2008 03:56:22 +0000 Subject: Cidorvan's 4-subband overflow fixes --- sbc/sbc.c | 2 +- sbc/sbc_math.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 21a68063..5fc4752f 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -375,7 +375,7 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, int ch, sb, blk, bit; /* channel, subband, block and bit standard counters */ int bits[2][8]; /* bits distribution */ - int levels[2][8]; /* levels derived from that */ + uint32_t levels[2][8]; /* levels derived from that */ if (len < 4) return -1; diff --git a/sbc/sbc_math.h b/sbc/sbc_math.h index 5d3da8d9..b3d87a62 100644 --- a/sbc/sbc_math.h +++ b/sbc/sbc_math.h @@ -30,16 +30,16 @@ ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits))) #define SCALE_PROTO4_TBL 15 -#define SCALE_ANA4_TBL 16 +#define SCALE_ANA4_TBL 17 #define SCALE_PROTO8_TBL 16 #define SCALE_ANA8_TBL 17 -#define SCALE_SPROTO4_TBL 15 +#define SCALE_SPROTO4_TBL 12 #define SCALE_SPROTO8_TBL 14 -#define SCALE_NPROTO4_TBL 13 +#define SCALE_NPROTO4_TBL 11 #define SCALE_NPROTO8_TBL 11 -#define SCALE4_STAGE1_BITS 16 -#define SCALE4_STAGE2_BITS 15 -#define SCALE4_STAGED1_BITS 12 +#define SCALE4_STAGE1_BITS 15 +#define SCALE4_STAGE2_BITS 16 +#define SCALE4_STAGED1_BITS 15 #define SCALE4_STAGED2_BITS 16 #define SCALE8_STAGE1_BITS 15 #define SCALE8_STAGE2_BITS 15 -- cgit From bfac4c082bca5e5ffb4874ed6be0a7e336b719d5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 5 Mar 2008 20:22:05 +0000 Subject: Enable gcc -O3 optimizations for SBC --- sbc/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index 840fbfef..9079305a 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -10,6 +10,8 @@ noinst_LTLIBRARIES = libsbc.la libsbc_la_SOURCES = sbc.h sbc.c sbc_math.h sbc_tables.h +libsbc_la_CFLAGS = -finline-functions -funswitch-loops -fgcse-after-reload + noinst_PROGRAMS = sbcinfo sbcdec sbcenc $(sndfile_programs) sbcdec_LDADD = libsbc.la -- cgit From 51a5483169faa3b64b50970891a545192836ee9b Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Thu, 6 Mar 2008 14:04:43 +0000 Subject: decoder optimization, now using nested multiply calls --- sbc/sbc.c | 99 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 51 insertions(+), 48 deletions(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 5fc4752f..beacfd6e 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -550,41 +550,42 @@ static void sbc_decoder_init(struct sbc_decoder_state *state, static inline void sbc_synthesize_four(struct sbc_decoder_state *state, struct sbc_frame *frame, int ch, int blk) { - int i, j, k, idx; - sbc_fixed_t res; + int i, k, idx; + int32_t *v = state->V[ch]; + int *offset = state->offset[ch]; for (i = 0; i < 8; i++) { /* Shifting */ - state->offset[ch][i]--; - if (state->offset[ch][i] < 0) { - state->offset[ch][i] = 79; - for (j = 0; j < 9; j++) - state->V[ch][j+80] = state->V[ch][j]; + offset[i]--; + if (offset[i] < 0) { + offset[i] = 79; + memcpy(v + 80, v, 9 * sizeof(*v)); } - } - for (i = 0; i < 8; i++) { /* Distribute the new matrix value to the shifted position */ - SBC_FIXED_0(res); - for (j = 0; j < 4; j++) - res = MULA(synmatrix4[i][j], - frame->sb_sample[blk][ch][j], res); - state->V[ch][state->offset[ch][i]] = SCALE4_STAGED1(res); + v[offset[i]] = SCALE4_STAGED1( + MULA(synmatrix4[i][0], frame->sb_sample[blk][ch][0], + MULA(synmatrix4[i][1], frame->sb_sample[blk][ch][1], + MULA(synmatrix4[i][2], frame->sb_sample[blk][ch][2], + MUL (synmatrix4[i][3], frame->sb_sample[blk][ch][3]))))); } /* Compute the samples */ - for (idx = 0, i = 0; i < 4; i++) { + for (idx = 0, i = 0; i < 4; i++, idx += 5) { k = (i + 4) & 0xf; - SBC_FIXED_0(res); - for (j = 0; j < 10; idx++) { - res = MULA(state->V[ch][state->offset[ch][i]+j++], - sbc_proto_4_40m0[idx], res); - res = MULA(state->V[ch][state->offset[ch][k]+j++], - sbc_proto_4_40m1[idx], res); - } /* Store in output, Q0 */ - frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(res); + frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2( + MULA(v[offset[i] + 0], sbc_proto_4_40m0[idx + 0], + MULA(v[offset[k] + 1], sbc_proto_4_40m1[idx + 0], + MULA(v[offset[i] + 2], sbc_proto_4_40m0[idx + 1], + MULA(v[offset[k] + 3], sbc_proto_4_40m1[idx + 1], + MULA(v[offset[i] + 4], sbc_proto_4_40m0[idx + 2], + MULA(v[offset[k] + 5], sbc_proto_4_40m1[idx + 2], + MULA(v[offset[i] + 6], sbc_proto_4_40m0[idx + 3], + MULA(v[offset[k] + 7], sbc_proto_4_40m1[idx + 3], + MULA(v[offset[i] + 8], sbc_proto_4_40m0[idx + 4], + MUL( v[offset[k] + 9], sbc_proto_4_40m1[idx + 4]))))))))))); } } @@ -592,43 +593,45 @@ static inline void sbc_synthesize_eight(struct sbc_decoder_state *state, struct sbc_frame *frame, int ch, int blk) { int i, j, k, idx; - sbc_fixed_t res; + int *offset = state->offset[ch]; for (i = 0; i < 16; i++) { /* Shifting */ - state->offset[ch][i]--; - if (state->offset[ch][i] < 0) { - state->offset[ch][i] = 159; + offset[i]--; + if (offset[i] < 0) { + offset[i] = 159; for (j = 0; j < 9; j++) - state->V[ch][j+160] = state->V[ch][j]; + state->V[ch][j + 160] = state->V[ch][j]; } - } - for (i = 0; i < 16; i++) { /* Distribute the new matrix value to the shifted position */ - SBC_FIXED_0(res); - for (j = 0; j < 8; j++) { - /* Q28 = Q15 * Q13 */ - res = MULA(synmatrix8[i][j], - frame->sb_sample[blk][ch][j], res); - } - /* Q10 */ - state->V[ch][state->offset[ch][i]] = SCALE8_STAGED1(res); + state->V[ch][offset[i]] = SCALE8_STAGED1( + MULA(synmatrix8[i][0], frame->sb_sample[blk][ch][0], + MULA(synmatrix8[i][1], frame->sb_sample[blk][ch][1], + MULA(synmatrix8[i][2], frame->sb_sample[blk][ch][2], + MULA(synmatrix8[i][3], frame->sb_sample[blk][ch][3], + MULA(synmatrix8[i][4], frame->sb_sample[blk][ch][4], + MULA(synmatrix8[i][5], frame->sb_sample[blk][ch][5], + MULA(synmatrix8[i][6], frame->sb_sample[blk][ch][6], + MUL( synmatrix8[i][7], frame->sb_sample[blk][ch][7]))))))))); } /* Compute the samples */ - for (idx = 0, i = 0; i < 8; i++) { + for (idx = 0, i = 0; i < 8; i++, idx += 5) { k = (i + 8) & 0xf; - SBC_FIXED_0(res); - for (j = 0; j < 10; idx++) { - res = MULA(state->V[ch][state->offset[ch][i]+j++], - sbc_proto_8_80m0[idx], res); - res = MULA(state->V[ch][state->offset[ch][k]+j++], - sbc_proto_8_80m1[idx], res); - } - /* Store in output */ - frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2(res); // Q0 + /* Store in output */ + frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2( // Q0 + MULA(state->V[ch][offset[i] + 0], sbc_proto_8_80m0[idx + 0], + MULA(state->V[ch][offset[k] + 1], sbc_proto_8_80m1[idx + 0], + MULA(state->V[ch][offset[i] + 2], sbc_proto_8_80m0[idx + 1], + MULA(state->V[ch][offset[k] + 3], sbc_proto_8_80m1[idx + 1], + MULA(state->V[ch][offset[i] + 4], sbc_proto_8_80m0[idx + 2], + MULA(state->V[ch][offset[k] + 5], sbc_proto_8_80m1[idx + 2], + MULA(state->V[ch][offset[i] + 6], sbc_proto_8_80m0[idx + 3], + MULA(state->V[ch][offset[k] + 7], sbc_proto_8_80m1[idx + 3], + MULA(state->V[ch][offset[i] + 8], sbc_proto_8_80m0[idx + 4], + MUL( state->V[ch][offset[k] + 9], sbc_proto_8_80m1[idx + 4]))))))))))); } } -- cgit From 9e446dba514577bd52f93f492903f0e4eb9941c7 Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 8 Mar 2008 05:21:26 +0000 Subject: Cidorvan found another place where the spec had us saving a bunch of values that were used immediately. Just compute and use instead of saving. In the decoder. --- sbc/Makefile.am | 3 +-- sbc/sbc.c | 37 +++++++++++++------------------------ 2 files changed, 14 insertions(+), 26 deletions(-) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index 9079305a..afc197a0 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,4 +1,3 @@ - if SNDFILE sndfile_programs = sbctester else @@ -23,6 +22,6 @@ sbctester_LDADD = @SNDFILE_LIBS@ endif endif -AM_CFLAGS = @SNDFILE_CFLAGS@ +AM_CFLAGS = @SNDFILE_CFLAGS@ -O3 MAINTAINERCLEANFILES = Makefile.in diff --git a/sbc/sbc.c b/sbc/sbc.c index beacfd6e..1a19ac79 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -79,7 +79,6 @@ struct sbc_frame { uint8_t scale_factor[2][8]; /* raw integer subband samples in the frame */ - uint16_t audio_sample[16][2][8]; int32_t sb_sample_f[16][2][8]; int32_t sb_sample[16][2][8]; /* modified subband samples */ @@ -372,6 +371,7 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, int crc_pos = 0; int32_t temp; + int audio_sample; int ch, sb, blk, bit; /* channel, subband, block and bit standard counters */ int bits[2][8]; /* bits distribution */ @@ -473,28 +473,6 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, sbc_calculate_bits(frame, bits); - for (blk = 0; blk < frame->blocks; blk++) { - for (ch = 0; ch < frame->channels; ch++) { - for (sb = 0; sb < frame->subbands; sb++) { - frame->audio_sample[blk][ch][sb] = 0; - if (bits[ch][sb] == 0) - continue; - - for (bit = 0; bit < bits[ch][sb]; bit++) { - int b; /* A bit */ - if (consumed > len * 8) - return -1; - - b = (data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01; - frame->audio_sample[blk][ch][sb] |= - b << (bits[ch][sb] - bit - 1); - - consumed++; - } - } - } - } - for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) levels[ch][sb] = (1 << bits[ch][sb]) - 1; @@ -504,8 +482,19 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame, for (ch = 0; ch < frame->channels; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (levels[ch][sb] > 0) { + audio_sample = 0; + for (bit = 0; bit < bits[ch][sb]; bit++) { + if (consumed > len * 8) + return -1; + + if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01) + audio_sample |= 1 << (bits[ch][sb] - bit - 1); + + consumed++; + } + frame->sb_sample[blk][ch][sb] = - (((frame->audio_sample[blk][ch][sb] << 1) | 1) << frame->scale_factor[ch][sb])/ + (((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) / levels[ch][sb] - (1 << frame->scale_factor[ch][sb]); } else frame->sb_sample[blk][ch][sb] = 0; -- cgit From 114762c0ab927bfd19872856d7dba6a375c759ce Mon Sep 17 00:00:00 2001 From: Brad Midgley Date: Sat, 8 Mar 2008 05:22:43 +0000 Subject: rollback an unintended commit on Makefile.am --- sbc/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sbc') diff --git a/sbc/Makefile.am b/sbc/Makefile.am index afc197a0..9079305a 100644 --- a/sbc/Makefile.am +++ b/sbc/Makefile.am @@ -1,3 +1,4 @@ + if SNDFILE sndfile_programs = sbctester else @@ -22,6 +23,6 @@ sbctester_LDADD = @SNDFILE_LIBS@ endif endif -AM_CFLAGS = @SNDFILE_CFLAGS@ -O3 +AM_CFLAGS = @SNDFILE_CFLAGS@ MAINTAINERCLEANFILES = Makefile.in -- cgit From 45c36dbd276501aa76d9798a8fafe6c202db7276 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jun 2008 13:20:50 +0000 Subject: Avoid direct inclusion of malloc.h --- sbc/sbc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sbc') diff --git a/sbc/sbc.c b/sbc/sbc.c index 1a19ac79..6303421f 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include -- cgit