Re: [Bluez-devel] sbc and fixed-point progress

Victor Shcherbatyuk
2005-09-03T15:33:45Z

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

Brad,

The patch includes restructured and cleaned up code for 8-subband fixed
point encoder (I didn't touch a2play yet). I've removed some of your code
(if you need it let me know), moved fixed tables to sbc_tables.h (manually),
merged floating and fixed point filter code. Now all the math is in
sbc_math.h, an option added for 32 bit fixed point, but I could not make it
sound any good, it is uses ~0% cpu producing sound of 0 quality - looks
fair, so if someone wants to experiment with it... :)

I will do 4 subband encoder too. Can not promise any dates, depends how easy
it goes...

I've played with Philips codec and I've noticed one thing. With the same
value of bitpool our codec produces bitrate half of what the Philips codec
does... So, if I set bitpool 15 for the Philips codec it will produce the
same bitrate and sound quality as our encoder produces with bitpool eq. 32 -
something might be wrong with bitallocation?

Regards,
Victor.

P.S. There is no real need in rmagnitude() as we can test the filter code
for overflowing using an test app, supplying all kind of inputs and
comparing its output with that of the floating point filer. I've done it and
currently it does not overflow, later if we need more precision? we can
tweak SCALE_STAGE1 and SCALE_STAGE2 to get maximum of precision without
overflowing....

[-- Attachment #2: sbc_fixed.patch --]
[-- Type: application/octet-stream, Size: 46999 bytes --]

? sbc/sbc_math.h
Index: sbc/gen_fixed.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/gen_fixed.c,v
retrieving revision 1.5
diff -u -r1.5 gen_fixed.c
--- sbc/gen_fixed.c 27 Aug 2005 02:17:54 -0000 1.5
+++ sbc/gen_fixed.c 3 Sep 2005 14:57:05 -0000
@@ -1,5 +1,3 @@
-#define USE_FIXED
-
#include <math.h>
#include "sbc.h"
#include "sbc_tables.h"
@@ -10,16 +8,15 @@
int i;
int j;
int bits;
+ char* scalestr;
} tables[] = {
//{"sbc_proto_4_40_f", (void *)sbc_proto_4_40, 40, 1, 28},
//{"sbc_proto_8_80_f", (void *)sbc_proto_8_80, 80, 1, 28},
- {"synmatrix4_f", (void *)synmatrix4, 8, 4, 28},
- {"synmatrix8_f", (void *)synmatrix8, 16, 8, 28},
+// {"synmatrix4_f", (void *)synmatrix4, 8, 4, 28},
+// {"synmatrix8_f", (void *)synmatrix8, 16, 8, 28},
//{"anamatrix4_f", (void *)anamatrix4, 4, 8, 28},
- {"_sbc_proto_8_f", (void *)_sbc_proto_8, 40, 1, 33},
- {"_anamatrix8_f", (void *)_anamatrix8, 8, 1, 30},
- {"_sbc_proto_4_f", (void *)_sbc_proto_4, 20, 1, 33},
- {"_anamatrix4_f", (void *)_anamatrix4, 4, 1, 30},
+ {"_sbc_proto_8", (void *)_sbc_proto_8, 40, 1, 33, "SP8"},
+ {"_anamatrix8", (void *)_anamatrix8, 8, 1, 30, "SA8"},
{0, 0, 0, 0}
};

@@ -29,10 +26,6 @@
for(entry = 0; tables[entry].name; entry++) {
if(tables[entry].j == 1) {
if (tables[entry].ref == (void *)_sbc_proto_8 || tables[entry].ref == (void *)_anamatrix8) {
- if (tables[entry].ref == (void *)_sbc_proto_8)
- printf("#define FIXED64_STAGE1 %d\n", 24);
- else
- printf("#define FIXED64_STAGE2 %d\n", 7);
printf("static const int32_t %s[%d] = {\n",
tables[entry].name, tables[entry].i);
}
@@ -54,7 +47,10 @@
printf("OVERFLOW (%f)!\n", res);
exit(1);
}
- printf("0x%08x", (int32_t)res);
+ if (tables[entry].scalestr)
+ printf("%s(0x%08x)", tables[entry].scalestr, (int32_t)res);
+ else
+ printf("0x%08x", (int32_t)res);
}
printf("\n};\n\n");
} else {
Index: sbc/sbc.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc.c,v
retrieving revision 1.53
diff -u -r1.53 sbc.c
--- sbc/sbc.c 28 Aug 2005 05:32:19 -0000 1.53
+++ sbc/sbc.c 3 Sep 2005 14:57:06 -0000
@@ -58,80 +58,9 @@
#include <sys/types.h>

#include "sbc.h"
+#include "sbc_math.h"
#include "sbc_tables.h"

-#define fabs(x) ((x) < 0 ?-(x) : (x))
-
-#ifdef USE_FIXED
-#include "sbc_tables_f.h"
-
-static int assertf(int debug, float a, sbc_fixed_t b, char *msg) {
- float c = fixedtod(b);
- float diff = fabs(a-c);
- if(fabs(diff/a) > 0.2 && diff > 0.5) {
- fprintf(stderr, "compare failed float=%f fixed=%f in %s\n", a, c, msg);
- if(debug) return 1;
- exit(1);
- } else if(debug == 1 && fabs(a) + fabs(c) > 0.001) {
- fprintf(stderr, "float=%8.8f fixed=%8.8f in %s\n", a, c, msg);
- }
- return 0;
-}
-#endif
-
-struct magnitude {
- int min;
- int max;
- char *name;
-};
-
-/*
- * record the magnitude range of a float over many samples
- */
-
-static void rmagnitude(float f, int idx, char *n) {
-#if 0
- static struct magnitude *mags = NULL;
- f = fabs(f);
- int m = 0;
-
- // virtually zero
- if(f < .0001) return;
-
- if(mags == NULL) {
- int size = sizeof(struct magnitude)*10;
- mags = malloc(size);
- memset(mags, 0, size);
- }
- if(idx < 0) {
- printf("\n");
- for(idx = 0; mags[idx].name != NULL; idx++)
- printf("%s magnitude range is (%d,%d)\n", mags[idx].name, mags[idx].min, mags[idx].max);
- return;
- }
- if(n == NULL) {
- printf("%s magnitude range is (%d,%d)\n", mags[idx].name, mags[idx].min, mags[idx].max);
- return;
- }
- while(f > 2.0) {
- f/=2.0;
- m++;
- }
- while(f < 1.0) {
- f*=2.0;
- m--;
- }
- if(m < mags[idx].min || mags[idx].min == 0) {
- mags[idx].min = m;
- mags[idx].name = n;
- }
- if(m > mags[idx].max || mags[idx].max == 0) {
- mags[idx].max = m;
- mags[idx].name = n;
- }
-#endif
-}
-
#define SBC_SYNCWORD 0x9C

/* sampling frequency */
@@ -163,28 +92,26 @@
/* This structure contains an unpacked SBC frame.
Yes, there is probably quite some unused space herein */
struct sbc_frame {
- u_int16_t sampling_frequency; /* in kHz */
- u_int8_t blocks;
+ 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;
- u_int8_t channels;
+ uint8_t channels;
enum {
LOUDNESS = SBC_AM_LOUDNESS,
SNR = SBC_AM_SNR
} allocation_method;
- u_int8_t subbands;
- u_int8_t bitpool;
- u_int8_t join; /* bit number x set means joint stereo has been used in subband x */
- u_int8_t scale_factor[2][8]; /* only the lower 4 bits of every element are to be used */
- u_int16_t audio_sample[16][2][8]; /* raw integer subband samples in the frame */
-#ifdef USE_FIXED
+ 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 */
+
sbc_fixed_t sb_sample_f[16][2][8];
- sbc_fixed_t pcm_sample_f[2][16*8];
-#endif
double sb_sample[16][2][8]; /* modified subband samples */
int16_t pcm_sample[2][16*8]; /* original pcm audio samples */
};
@@ -206,7 +133,7 @@
/*
* Calculates the CRC-8 of the first len bits in data
*/
-static const u_int8_t crc_table[256] = {
+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,
@@ -241,11 +168,11 @@
0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
};

-static u_int8_t sbc_crc8(const u_int8_t * data, size_t len)
+static uint8_t sbc_crc8(const uint8_t * data, size_t len)
{
- u_int8_t crc = 0x0f;
+ uint8_t crc = 0x0f;
size_t i;
- u_int8_t octet;
+ uint8_t octet;

for (i = 0; i < len / 8; i++)
crc = crc_table[crc ^ data[i]];
@@ -266,7 +193,7 @@
* 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], u_int8_t sf)
+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;
@@ -477,14 +404,14 @@
* -3 CRC8 incorrect
* -4 Bitpool value out of bounds
*/
-static int sbc_unpack_frame(const u_int8_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 */
- u_int8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int crc_pos = 0;

- u_int8_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 bits[2][8]; /* bits distribution */
@@ -634,9 +561,6 @@
frame->sb_sample[blk][ch][sb] =
scalefactor[ch][sb] * ((frame->audio_sample[blk][ch][sb] * 2.0 + 1.0) /
levels[ch][sb] - 1.0);
- rmagnitude(frame->sb_sample[blk][ch][sb], 0, "frame->sb_sample[][][]");
- rmagnitude(scalefactor[ch][sb], 1, "scalefactor[][]");
- rmagnitude(levels[ch][sb], 2, "levels[][]");
} else {
frame->sb_sample[blk][ch][sb] = 0;
}
@@ -744,8 +668,6 @@
state->V[ch][k] = 0;
for (i = 0; i < 8; i++) {
state->V[ch][k] += synmatrix8[k][i] * state->S[ch][i];
- rmagnitude(state->V[ch][k], 3, "state->V[ch][k]");
- rmagnitude(synmatrix8[k][i], 7, "synmatrix8[k][i]");
}
}

@@ -754,15 +676,12 @@
for (j = 0; j < 8; j++) {
state->U[ch][i * 16 + j] = state->V[ch][i * 32 + j];
state->U[ch][i * 16 + j + 8] = state->V[ch][i * 32 + j + 24];
- rmagnitude(state->U[ch][i * 16 + j], 4, "state->U[ch][i * 16 + j]");
}
}

/* Window by 80 coefficients */
for (i = 0; i < 80; i++) {
state->W[ch][i] = state->U[ch][i] * sbc_proto_8_80[i] * (-4);
- rmagnitude(state->W[ch][i], 5, "state->W[ch][i]");
- rmagnitude(sbc_proto_8_80[i]*4.0, 8, "sbc_proto_8_80[i]*4");
}

/* Calculate 8 audio samples */
@@ -770,7 +689,6 @@
state->X[ch][j] = 0;
for (i = 0; i < 10; i++) {
state->X[ch][j] += state->W[ch][j + 8 * i];
- rmagnitude(state->X[ch][j], 6, "state->X[ch][j]");
}
}

@@ -821,20 +739,6 @@
state->subbands = frame->subbands;
}

-#ifdef USE_FIXED
-static inline void _sbc_analyze_four(int32_t in[40], int32_t out[4])
-{
-}
-#else
-static inline void _sbc_analyze_four(int32_t in[40], double out[4])
-{
- double t1,t2,t3,t4,t5,t6,t7,t8, in1, in2;
- double a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20;
-
- out[0] = out[1] = out[2] = out[3] = 0;
-}
-#endif
-
static inline void sbc_analyze_four(struct sbc_encoder_state *state,
struct sbc_frame *frame, int ch, int blk)
{
@@ -845,11 +749,6 @@
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)];
-#ifdef USE_FIXED
- _sbc_analyze_four(state->X[ch], frame->sb_sample_f[blk][ch]);
-#else
- _sbc_analyze_four(state->X[ch], frame->sb_sample[blk][ch]);
-#endif

/* Windowing by 40 coefficients */
for (i = 0; i < 40; i++)
@@ -874,300 +773,174 @@
frame->sb_sample[blk][ch][i] = state->S[ch][i];
}

-#ifdef USE_FIXED
-static inline void _sbc_analyze_eight(int32_t in[80], int32_t out[8])
+static inline void _sbc_analyze_eight(const int32_t in[80], sbc_fixed_t out[8])
{
- int32_t a0_hi,a1_hi,a2_hi,a3_hi,a4_hi,a5_hi,a6_hi,a7_hi,a8_hi,a9_hi,a10_hi,a11_hi,a12_hi,a13_hi,a14_hi,a15_hi,a16_hi,a17_hi,a18_hi,a19_hi,a20_hi, a21_hi;
- int32_t a0_lo,a1_lo,a2_lo,a3_lo,a4_lo,a5_lo,a6_lo,a7_lo,a8_lo,a9_lo,a10_lo,a11_lo,a12_lo,a13_lo,a14_lo,a15_lo,a16_lo,a17_lo,a18_lo,a19_lo,a20_lo, a21_lo;
- int32_t in1, in2, t1, t2, t3, t4, t5, t6, t7, t8;
- int32_t t1_hi, t1_lo, t2_hi, t2_lo, t3_hi, t3_lo, t4_hi, t4_lo;
- int32_t t5_hi, t5_lo, t6_hi, t6_lo, t7_hi, t7_lo, t8_hi, t8_lo;
- int32_t out0_hi, out1_hi, out2_hi, out3_hi, out4_hi, out5_hi, out6_hi, out7_hi;
- int32_t out0_lo, out1_lo, out2_lo, out3_lo, out4_lo, out5_lo, out6_lo, out7_lo;
-
- t1_hi = t1_lo = t2_hi = t2_lo = t3_hi = t3_lo = t4_hi = t4_lo = 0;
- t5_hi = t5_lo = t6_hi = t6_lo = t7_hi = t7_lo = t8_hi = t8_lo = 0;
- out0_hi = out1_hi = out2_hi = out3_hi = out4_hi = out5_hi = out6_hi = out7_hi = 0;
- out0_lo = out1_lo = out2_lo = out3_lo = out4_lo = out5_lo = out6_lo = out7_lo = 0;
-
- in1 = in[16] - in[64]; in2 = in[32] - in[48];
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[0], in1);
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[1], in2);
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[2], in[4]);
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[3], in[20]);
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[4], in[36]);
- MULA64(t1_hi, t1_lo, _sbc_proto_8_f[5], in[52]);
- t1 = SCALE64(t1_hi, t1_lo, FIXED64_STAGE1);
-
- MULA64(t2_hi, t2_lo, _sbc_proto_8_f[6], in[2]);
- MULA64(t2_hi, t2_lo, _sbc_proto_8_f[7], in[18]);
- MULA64(t2_hi, t2_lo, _sbc_proto_8_f[8], in[34]);
- MULA64(t2_hi, t2_lo, _sbc_proto_8_f[9], in[50]);
- MULA64(t2_hi, t2_lo, _sbc_proto_8_f[10], in[66]);
- t2 = SCALE64(t2_hi, t2_lo, FIXED64_STAGE1);
-
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[11], in[1]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[12], in[17]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[13], in[33]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[14], in[49]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[15], in[65]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[16], in[3]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[17], in[19]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[18], in[35]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[19], in[51]);
- MULA64(t3_hi, t3_lo, _sbc_proto_8_f[20], in[67]);
- t3 = SCALE64(t3_hi, t3_lo, FIXED64_STAGE1);
-
- MULA64(t4_hi, t4_lo, _sbc_proto_8_f[21], in[5]);
- MULA64(t4_hi, t4_lo, _sbc_proto_8_f[22], in[21]);
- MULA64(t4_hi, t4_lo, _sbc_proto_8_f[23], in[37]);
- MULA64(t4_hi, t4_lo, _sbc_proto_8_f[24], in[53]);
- MULA64(t4_hi, t4_lo, _sbc_proto_8_f[25], in[69]);
- MULA64(t4_hi, t4_lo, -_sbc_proto_8_f[15], in[15]);
- MULA64(t4_hi, t4_lo, -_sbc_proto_8_f[14], in[31]);
- MULA64(t4_hi, t4_lo, -_sbc_proto_8_f[13], in[47]);
- MULA64(t4_hi, t4_lo, -_sbc_proto_8_f[12], in[63]);
- MULA64(t4_hi, t4_lo, -_sbc_proto_8_f[11], in[79]);
- t4 = SCALE64(t4_hi, t4_lo, FIXED64_STAGE1);
-
- MULA64(t5_hi, t5_lo, _sbc_proto_8_f[26], in[6]);
- MULA64(t5_hi, t5_lo, _sbc_proto_8_f[27], in[22]);
- MULA64(t5_hi, t5_lo, _sbc_proto_8_f[28], in[38]);
- MULA64(t5_hi, t5_lo, _sbc_proto_8_f[29], in[54]);
- MULA64(t5_hi, t5_lo, _sbc_proto_8_f[30], in[70]);
- MULA64(t5_hi, t5_lo, -_sbc_proto_8_f[10], in[14]);
- MULA64(t5_hi, t5_lo, -_sbc_proto_8_f[9], in[30]);
- MULA64(t5_hi, t5_lo, -_sbc_proto_8_f[8], in[46]);
- MULA64(t5_hi, t5_lo, -_sbc_proto_8_f[7], in[62]);
- MULA64(t5_hi, t5_lo, -_sbc_proto_8_f[6], in[78]);
- t5 = SCALE64(t5_hi, t5_lo, FIXED64_STAGE1);
-
- MULA64(t6_hi, t6_lo, _sbc_proto_8_f[31], in[7]);
- MULA64(t6_hi, t6_lo, _sbc_proto_8_f[32], in[23]);
- MULA64(t6_hi, t6_lo, _sbc_proto_8_f[33], in[39]);
- MULA64(t6_hi, t6_lo, _sbc_proto_8_f[34], in[55]);
- MULA64(t6_hi, t6_lo, _sbc_proto_8_f[35], in[71]);
- MULA64(t6_hi, t6_lo, -_sbc_proto_8_f[20], in[13]);
- MULA64(t6_hi, t6_lo, -_sbc_proto_8_f[19], in[29]);
- MULA64(t6_hi, t6_lo, -_sbc_proto_8_f[18], in[45]);
- MULA64(t6_hi, t6_lo, -_sbc_proto_8_f[17], in[61]);
- MULA64(t6_hi, t6_lo, -_sbc_proto_8_f[16], in[77]);
- t6 = SCALE64(t6_hi, t6_lo, FIXED64_STAGE1);
-
- in1 = in[8] + in[72];
- MULA64(t7_hi, t7_lo, _sbc_proto_8_f[36], in1);
- MULA64(t7_hi, t7_lo, _sbc_proto_8_f[37], in[24]);
- MULA64(t7_hi, t7_lo, _sbc_proto_8_f[38], in[40]);
- MULA64(t7_hi, t7_lo, _sbc_proto_8_f[37], in[56]);
- MULA64(t7_hi, t7_lo, -_sbc_proto_8_f[39], in[12]);
- MULA64(t7_hi, t7_lo, -_sbc_proto_8_f[5], in[28]);
- MULA64(t7_hi, t7_lo, -_sbc_proto_8_f[4], in[44]);
- MULA64(t7_hi, t7_lo, -_sbc_proto_8_f[3], in[60]);
- MULA64(t7_hi, t7_lo, -_sbc_proto_8_f[2], in[76]);
- t7 = SCALE64(t7_hi, t7_lo, FIXED64_STAGE1);
-
- MULA64(t8_hi, t8_lo, _sbc_proto_8_f[35], in[9]);
- MULA64(t8_hi, t8_lo, _sbc_proto_8_f[34], in[25]);
- MULA64(t8_hi, t8_lo, _sbc_proto_8_f[33], in[41]);
- MULA64(t8_hi, t8_lo, _sbc_proto_8_f[32], in[57]);
- MULA64(t8_hi, t8_lo, _sbc_proto_8_f[31], in[73]);
- MULA64(t8_hi, t8_lo, -_sbc_proto_8_f[25], in[11]);
- MULA64(t8_hi, t8_lo, -_sbc_proto_8_f[24], in[27]);
- MULA64(t8_hi, t8_lo, -_sbc_proto_8_f[23], in[43]);
- MULA64(t8_hi, t8_lo, -_sbc_proto_8_f[22], in[59]);
- MULA64(t8_hi, t8_lo, -_sbc_proto_8_f[21], in[75]);
- t8 = SCALE64(t8_hi, t8_lo, FIXED64_STAGE1);
-
- MUL64(a0_hi, a0_lo, _anamatrix8_f[0], t1);
- MUL64(a7_hi, a7_lo, _anamatrix8_f[1], t1);
- ADD64(out0_hi, out0_lo, a0_hi, a0_lo);
- ADD64(out7_hi, out7_lo, a0_hi, a0_lo);
- SUB64(out3_hi, out3_lo, a0_hi, a0_lo);
- SUB64(out4_hi, out4_lo, a0_hi, a0_lo);
- ADD64(out1_hi, out1_lo, a7_hi, a7_lo);
- ADD64(out6_hi, out6_lo, a7_hi, a7_lo);
- SUB64(out5_hi, out5_lo, a7_hi, a7_lo);
- SUB64(out2_hi, out2_lo, a7_hi, a7_lo);
-
- MUL64(a21_hi, a21_lo, _anamatrix8_f[7], t2);
- ADD64(out0_hi, out0_lo, a21_hi, a21_lo);
- ADD64(out1_hi, out1_lo, a21_hi, a21_lo);
- ADD64(out2_hi, out2_lo, a21_hi, a21_lo);
- ADD64(out3_hi, out3_lo, a21_hi, a21_lo);
- ADD64(out4_hi, out4_lo, a21_hi, a21_lo);
- ADD64(out5_hi, out5_lo, a21_hi, a21_lo);
- ADD64(out6_hi, out6_lo, a21_hi, a21_lo);
- ADD64(out7_hi, out7_lo, a21_hi, a21_lo);
-
- MUL64(a1_hi, a1_lo, _anamatrix8_f[2], t3);
- MUL64(a8_hi, a8_lo, _anamatrix8_f[3], t3);
- MUL64(a13_hi, a13_lo, _anamatrix8_f[4], t3);
- MUL64(a17_hi, a17_lo, _anamatrix8_f[5], t3);
- ADD64(out0_hi, out0_lo, a1_hi, a1_lo);
- SUB64(out7_hi, out7_lo, a1_hi, a1_lo);
- ADD64(out1_hi, out1_lo, a8_hi, a8_lo);
- SUB64(out6_hi, out6_lo, a8_hi, a8_lo);
- ADD64(out2_hi, out2_lo, a13_hi, a13_lo);
- SUB64(out5_hi, out5_lo, a13_hi, a13_lo);
- ADD64(out3_hi, out3_lo, a17_hi, a17_lo);
- SUB64(out4_hi, out4_lo, a17_hi, a17_lo);
-
- MUL64(a2_hi, a2_lo, _anamatrix8_f[3], t4);
- MUL64(a9_hi, a9_lo, _anamatrix8_f[5], t4);
- MUL64(a14_hi, a14_lo, _anamatrix8_f[2], t4);
- MUL64(a18_hi, a18_lo, _anamatrix8_f[4], t4);
- ADD64(out0_hi, out0_lo, a2_hi, a2_lo);
- SUB64(out7_hi, out7_lo, a2_hi, a2_lo);
- SUB64(out1_hi, out1_lo, a9_hi, a9_lo);
- ADD64(out6_hi, out6_lo, a9_hi, a9_lo);
- SUB64(out2_hi, out2_lo, a14_hi, a14_lo);
- ADD64(out5_hi, out5_lo, a14_hi, a14_lo);
- SUB64(out3_hi, out3_lo, a18_hi, a18_lo);
- ADD64(out4_hi, out4_lo, a18_hi, a18_lo);
-
- MUL64(a3_hi, a3_lo, _anamatrix8_f[6], t5);
- ADD64(out0_hi, out0_lo, a3_hi, a3_lo);
- ADD64(out7_hi, out7_lo, a3_hi, a3_lo);
- ADD64(out3_hi, out3_lo, a3_hi, a3_lo);
- ADD64(out4_hi, out4_lo, a3_hi, a3_lo);
- SUB64(out1_hi, out1_lo, a3_hi, a3_lo);
- SUB64(out2_hi, out2_lo, a3_hi, a3_lo);
- SUB64(out5_hi, out5_lo, a3_hi, a3_lo);
- SUB64(out6_hi, out6_lo, a3_hi, a3_lo);
-
- MUL64(a4_hi, a4_lo, _anamatrix8_f[4], t6);
- MUL64(a10_hi, a10_lo, _anamatrix8_f[2], t6);
- MUL64(a15_hi, a15_lo, _anamatrix8_f[5], t6);
- MUL64(a19_hi, a19_lo, _anamatrix8_f[3], t6);
- ADD64(out0_hi, out0_lo, a4_hi, a4_lo);
- SUB64(out7_hi, out7_lo, a4_hi, a4_lo);
- SUB64(out1_hi, out1_lo, a10_hi, a10_lo);
- ADD64(out6_hi, out6_lo, a10_hi, a10_lo);
- ADD64(out2_hi, out2_lo, a15_hi, a15_lo);
- SUB64(out5_hi, out5_lo, a15_hi, a15_lo);
- ADD64(out3_hi, out3_lo, a19_hi, a19_lo);
- SUB64(out4_hi, out4_lo, a19_hi, a19_lo);
-
- MUL64(a5_hi, a5_lo, _anamatrix8_f[1], t7);
- MUL64(a11_hi, a11_lo, _anamatrix8_f[0], t7);
- ADD64(out0_hi, out0_lo, a5_hi, a5_lo);
- ADD64(out7_hi, out7_lo, a5_hi, a5_lo);
- SUB64(out3_hi, out3_lo, a5_hi, a5_lo);
- SUB64(out4_hi, out4_lo, a5_hi, a5_lo);
- SUB64(out1_hi, out1_lo, a11_hi, a11_lo);
- SUB64(out6_hi, out6_lo, a11_hi, a11_lo);
- ADD64(out2_hi, out2_lo, a11_hi, a11_lo);
- ADD64(out5_hi, out5_lo, a11_hi, a11_lo);
-
- MUL64(a6_hi, a6_lo, _anamatrix8_f[5], t8);
- MUL64(a12_hi, a12_lo, _anamatrix8_f[4], t8);
- MUL64(a16_hi, a16_lo, _anamatrix8_f[3], t8);
- MUL64(a20_hi, a20_lo, _anamatrix8_f[2], t8);
- ADD64(out0_hi, out0_lo, a6_hi, a6_lo);
- SUB64(out7_hi, out7_lo, a6_hi, a6_lo);
- SUB64(out1_hi, out1_lo, a12_hi, a12_lo);
- ADD64(out6_hi, out6_lo, a12_hi, a12_lo);
- ADD64(out2_hi, out2_lo, a16_hi, a16_lo);
- SUB64(out5_hi, out5_lo, a16_hi, a16_lo);
- SUB64(out3_hi, out3_lo, a20_hi, a20_lo);
- ADD64(out4_hi, out4_lo, a20_hi, a20_lo);
-
- // restore original scale
- out[0] = out0_hi >> FIXED64_STAGE2;
- out[1] = out1_hi >> FIXED64_STAGE2;
- out[2] = out2_hi >> FIXED64_STAGE2;
- out[3] = out3_hi >> FIXED64_STAGE2;
- out[4] = out4_hi >> FIXED64_STAGE2;
- out[5] = out5_hi >> FIXED64_STAGE2;
- out[6] = out6_hi >> FIXED64_STAGE2;
- out[7] = out7_hi >> FIXED64_STAGE2;
+ sbc_fixed_t res;
+ int32_t t1, t2, t3, t4, t5, t6, t7, t8;

-}
-#else
-static inline void _sbc_analyze_eight(int32_t in[80], double out[8])
-{
- double t1,t2,t3,t4,t5,t6,t7,t8, in1, in2;
- double a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20;
+ SBC_FIXED_0(out[0]);SBC_FIXED_0(out[1]);SBC_FIXED_0(out[2]);SBC_FIXED_0(out[3]);
+ SBC_FIXED_0(out[4]);SBC_FIXED_0(out[5]);SBC_FIXED_0(out[6]);SBC_FIXED_0(out[7]);
+
+ MUL(res, _sbc_proto_8[0], (in[16] - in[64]));
+ 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]);
+ t1 = SCALE_STAGE1(res);
+
+ 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]);
+ t2 = SCALE_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]);
+ t3 = SCALE_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]);
+ t4 = SCALE_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]);
+ t5 = SCALE_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]);
+ t6 = SCALE_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]);
+ t7 = SCALE_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]);
+ t8 = SCALE_STAGE1(res);
+
+ MUL(out[0], _anamatrix8[0], t1);
+ MULA(out[0], _anamatrix8[7], t2);
+ MULA(out[0], _anamatrix8[2], t3);
+ MULA(out[0], _anamatrix8[3], t4);
+ MULA(out[0], _anamatrix8[6], t5);
+ MULA(out[0], _anamatrix8[4], t6);
+ MULA(out[0], _anamatrix8[1], t7);
+ MULA(out[0], _anamatrix8[5], t8);
+
+ MUL(out[1], _anamatrix8[1], t1);
+ MULA(out[1], _anamatrix8[7], t2);
+ MULA(out[1], _anamatrix8[3], t3);
+ MULA(out[1], -_anamatrix8[5], t4);
+ MULA(out[1], -_anamatrix8[6], t5);
+ MULA(out[1], -_anamatrix8[2], t6);
+ MULA(out[1], -_anamatrix8[0], t7);
+ MULA(out[1], -_anamatrix8[4], t8);
+
+ MUL(out[2], -_anamatrix8[1], t1);
+ MULA(out[2], _anamatrix8[7], t2);
+ MULA(out[2], _anamatrix8[4], t3);
+ MULA(out[2], -_anamatrix8[2], t4);
+ MULA(out[2], -_anamatrix8[6], t5);
+ MULA(out[2], _anamatrix8[5], t6);
+ MULA(out[2], _anamatrix8[0], t7);
+ MULA(out[2], _anamatrix8[3], t8);
+
+ MUL(out[3], -_anamatrix8[0], t1);
+ MULA(out[3], _anamatrix8[7], t2);
+ MULA(out[3], _anamatrix8[5], t3);
+ MULA(out[3], -_anamatrix8[4], t4);
+ MULA(out[3], _anamatrix8[6], t5);
+ MULA(out[3], _anamatrix8[3], t6);
+ MULA(out[3], -_anamatrix8[1], t7);
+ MULA(out[3], -_anamatrix8[2], t8);
+
+ MUL(out[4], -_anamatrix8[0], t1);
+ MULA(out[4], _anamatrix8[7], t2);
+ MULA(out[4], -_anamatrix8[5], t3);
+ MULA(out[4], _anamatrix8[4], t4);
+ MULA(out[4], _anamatrix8[6], t5);
+ MULA(out[4], -_anamatrix8[3], t6);
+ MULA(out[4], -_anamatrix8[1], t7);
+ MULA(out[4], _anamatrix8[2], t8);
+
+ MUL(out[5], -_anamatrix8[1], t1);
+ MULA(out[5], _anamatrix8[7], t2);
+ MULA(out[5], -_anamatrix8[4], t3);
+ MULA(out[5], _anamatrix8[2], t4);
+ MULA(out[5], -_anamatrix8[6], t5);
+ MULA(out[5], -_anamatrix8[5], t6);
+ MULA(out[5], _anamatrix8[0], t7);
+ MULA(out[5], -_anamatrix8[3], t8);
+
+ MUL(out[6], _anamatrix8[1], t1);
+ MULA(out[6], _anamatrix8[7], t2);
+ MULA(out[6], -_anamatrix8[3], t3);
+ MULA(out[6], _anamatrix8[5], t4);
+ MULA(out[6], -_anamatrix8[6], t5);
+ MULA(out[6], _anamatrix8[2], t6);
+ MULA(out[6], -_anamatrix8[0], t7);
+ MULA(out[6], _anamatrix8[4], t8);
+
+ MUL(out[7], _anamatrix8[0], t1);
+ MULA(out[7], _anamatrix8[7], t2);
+ MULA(out[7], -_anamatrix8[2], t3);
+ MULA(out[7], -_anamatrix8[3], t4);
+ MULA(out[7], _anamatrix8[6], t5);
+ MULA(out[7], -_anamatrix8[4], t6);
+ MULA(out[7], _anamatrix8[1], t7);
+ MULA(out[7], -_anamatrix8[5], t8);

- out[0] = out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;

- in1 = in[16] - in[64]; in2 = in[32] - in[48];
- t1 = _sbc_proto_8[0]*in1 + _sbc_proto_8[1]*in2 +\
- _sbc_proto_8[2]*in[4] + _sbc_proto_8[3]*in[20] + _sbc_proto_8[4]*in[36] +\
- _sbc_proto_8[5]*in[52];
-
- t2 = _sbc_proto_8[6]*in[2] + _sbc_proto_8[7]*in[18] + \
- _sbc_proto_8[8]*in[34] + _sbc_proto_8[9]*in[50] + _sbc_proto_8[10]*in[66];
-
- t3 = _sbc_proto_8[11]*in[1] + _sbc_proto_8[12]*in[17] + \
- _sbc_proto_8[13]*in[33] + _sbc_proto_8[14]*in[49] + _sbc_proto_8[15]*in[65] +\
- _sbc_proto_8[16]*in[3] + _sbc_proto_8[17]*in[19] + _sbc_proto_8[18]*in[35] +\
- _sbc_proto_8[19]*in[51] + _sbc_proto_8[20]*in[67];
-
- t4 = _sbc_proto_8[21]*in[5] + _sbc_proto_8[22]*in[21] + \
- _sbc_proto_8[23]*in[37] + _sbc_proto_8[24]*in[53] + _sbc_proto_8[25]*in[69] -\
- _sbc_proto_8[15]*in[15] - _sbc_proto_8[14]*in[31] - _sbc_proto_8[13]*in[47] -\
- _sbc_proto_8[12]*in[63] - _sbc_proto_8[11]*in[79];
-
- t5 = _sbc_proto_8[26]*in[6] + _sbc_proto_8[27]*in[22] + \
- _sbc_proto_8[28]*in[38] + _sbc_proto_8[29]*in[54] + _sbc_proto_8[30]*in[70] -\
- _sbc_proto_8[10]*in[14] - _sbc_proto_8[9]*in[30] - _sbc_proto_8[8]*in[46] -\
- _sbc_proto_8[7]*in[62] - _sbc_proto_8[6]*in[78];
-
- t6 = _sbc_proto_8[31]*in[7] + _sbc_proto_8[32]*in[23] + \
- _sbc_proto_8[33]*in[39] + _sbc_proto_8[34]*in[55] + _sbc_proto_8[35]*in[71] -\
- _sbc_proto_8[20]*in[13] - _sbc_proto_8[19]*in[29] - _sbc_proto_8[18]*in[45] -\
- _sbc_proto_8[17]*in[61] - _sbc_proto_8[16]*in[77];
-
- in1 = in[8] + in[72];
- t7 = _sbc_proto_8[36]*in1 + _sbc_proto_8[37]*in[24] + \
- _sbc_proto_8[38]*in[40] + _sbc_proto_8[37]*in[56] - _sbc_proto_8[39]*in[12] -\
- _sbc_proto_8[5]*in[28] - _sbc_proto_8[4]*in[44] - _sbc_proto_8[3]*in[60] -\
- _sbc_proto_8[2]*in[76];
-
- t8 = _sbc_proto_8[35]*in[9] + _sbc_proto_8[34]*in[25] + \
- _sbc_proto_8[33]*in[41] + _sbc_proto_8[32]*in[57] + _sbc_proto_8[31]*in[73] -\
- _sbc_proto_8[25]*in[11] - _sbc_proto_8[24]*in[27] -_sbc_proto_8[23]*in[43] -\
- _sbc_proto_8[22]*in[59] - _sbc_proto_8[21]*in[75];
-
- a0 = _anamatrix8[0]*t1;
- a7 = _anamatrix8[1]*t1;
- out[0] += a0; out[1] += a7; out[2] -= a7; out[3] -= a0; out[4] -= a0; out[5] -= a7; out[6] += a7; out[7] += a0;
-
- out[0] += t2; out[1] += t2; out[2] += t2; out[3] += t2; out[4] += t2; out[5] += t2; out[6] += t2; out[7] += t2;
-
- a1 = _anamatrix8[2]*t3;
- a8 = _anamatrix8[3]*t3;
- a13 = _anamatrix8[4]*t3;
- a17 = _anamatrix8[5]*t3;
- out[0] += a1; out[1] += a8; out[2] += a13; out[3] += a17; out[4] -= a17; out[5] -= a13; out[6] -= a8; out[7] -= a1;
-
- a2 = _anamatrix8[3]*t4;
- a9 = _anamatrix8[5]*t4;
- a14 = _anamatrix8[2]*t4;
- a18 = _anamatrix8[4]*t4;
- out[0] += a2; out[1] -= a9; out[2] -= a14; out[3] -= a18; out[4] += a18; out[5] += a14; out[6] += a9; out[7] -= a2;
-
- a4 = _anamatrix8[4]*t6;
- a10 = _anamatrix8[2]*t6;
- a15 = _anamatrix8[5]*t6;
- a19 = _anamatrix8[3]*t6;
- out[0] += a4; out[1] -= a10; out[2] += a15; out[3] += a19; out[4] -= a19; out[5] -= a15; out[6] += a10; out[7] -= a4;
-
- a3 = _anamatrix8[6]*t5;
- out[0] += a3; out[1] -= a3; out[2] -= a3; out[3] += a3; out[4] += a3; out[5] -= a3; out[6] -= a3; out[7] += a3;
-
- a5 = _anamatrix8[1]*t7;
- a11 = _anamatrix8[0]*t7;
- out[0] += a5; out[1] -= a11; out[2] += a11; out[3] -= a5; out[4] -= a5; out[5] += a11; out[6] -= a11; out[7] += a5;
-
- a6 = _anamatrix8[5]*t8;
- a12 = _anamatrix8[4]*t8;
- a16 = _anamatrix8[3]*t8;
- a20 = _anamatrix8[2]*t8;
- out[0] += a6; out[1] -= a12; out[2] += a16; out[3] -= a20; out[4] += a20; out[5] -= a16; out[6] += a12; out[7] -= a6;
}
-#endif

static inline void sbc_analyze_eight(struct sbc_encoder_state *state,
struct sbc_frame *frame, int ch, int blk)
@@ -1179,11 +952,7 @@
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)];
-#ifdef USE_FIXED
_sbc_analyze_eight(state->X[ch], frame->sb_sample_f[blk][ch]);
-#else
- _sbc_analyze_eight(state->X[ch], frame->sb_sample[blk][ch]);
-#endif
}

static int sbc_analyze_audio(struct sbc_encoder_state *state, struct sbc_frame *frame)
@@ -1229,14 +998,14 @@
* -99 not implemented
*/

-static int sbc_pack_frame(u_int8_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 */
- u_int8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int crc_pos = 0;

- u_int8_t sf; /* Sampling frequency as temporary value for table lookup */
+ 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 */
@@ -1325,11 +1094,7 @@
frame->scale_factor[ch][sb] = 0;
scalefactor[ch][sb] = 2;
for (blk = 0; blk < frame->blocks; blk++) {
-#ifdef USE_FIXED
- while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) {
-#else
- while (scalefactor[ch][sb] < fabs(frame->sb_sample[blk][ch][sb])) {
-#endif
+ while (scalefactor[ch][sb] < fabs(SCALE_STAGE2(frame->sb_sample_f[blk][ch][sb]))) {
frame->scale_factor[ch][sb]++;
scalefactor[ch][sb] *= 2;
}
@@ -1337,69 +1102,74 @@
}
}

- if (frame->channel_mode == JOINT_STEREO) {
- float 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++) {
+ if (frame->channel_mode == JOINT_STEREO) {
+ sbc_fixed_t sb_sample_j[16][2][7]; /* like frame->sb_sample but joint stereo */
+ sbc_fixed_t tmp;
+ 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[blk][0][sb]
- + frame->sb_sample[blk][1][sb]) / 2;
- sb_sample_j[blk][1][sb] = (frame->sb_sample[blk][0][sb]
- - frame->sb_sample[blk][1][sb]) / 2;
- }
- }
-
- /* 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[blk][0][sb] = sb_sample_j[blk][0][sb];
- frame->sb_sample[blk][1][sb] = sb_sample_j[blk][1][sb];
- }
- }
- }
-
- if (len * 8 < produced + frame->subbands) {
- return -1;
- } else {
- 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;
- }
- }
+ tmp = frame->sb_sample_f[blk][0][sb];
+ ADD(tmp, frame->sb_sample_f[blk][1][sb]);
+ DIV2(sb_sample_j[blk][0][sb], tmp);
+// sb_sample_j[blk][0][sb] = (frame->sb_sample_f[blk][0][sb] + frame->sb_sample_f[blk][1][sb]) / 2;
+ tmp = frame->sb_sample_f[blk][0][sb];
+ SUB(tmp, frame->sb_sample_f[blk][1][sb]);
+ DIV2(sb_sample_j[blk][1][sb], tmp);
+// sb_sample_j[blk][1][sb] = (frame->sb_sample_f[blk][0][sb] - frame->sb_sample_f[blk][1][sb]) / 2;
+ }
+ }
+
+ /* 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(SCALE_STAGE2(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;
+ } else {
+ 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;
@@ -1432,13 +1202,14 @@
for (ch = 0; ch < frame->channels; ch++) {
for (sb = 0; sb < frame->subbands; sb++) {
if (levels[ch][sb] > 0) {
+//PLEASECHECK: overflow possible? more elegant solution?
#ifdef USE_FIXED
frame->audio_sample[blk][ch][sb] =
- (u_int16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >> (frame->scale_factor[ch][sb] + 1)) +
+ (uint16_t) ((((SCALE_STAGE2(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] =
- (u_int16_t) (((frame->sb_sample[blk][ch][sb] / scalefactor[ch][sb] +
+ (uint16_t) (((frame->sb_sample_f[blk][ch][sb] / scalefactor[ch][sb] +
1.0) * levels[ch][sb]) / 2.0);
#endif
} else {
@@ -1512,7 +1283,6 @@
struct sbc_priv *priv;
char *ptr;
int i, ch, framelen, samples;
- static int modulo = 0;

if (!sbc)
return -EIO;
@@ -1562,8 +1332,6 @@

sbc->len = samples * priv->frame.channels * 2;

- if(modulo++ % 256 == 0) rmagnitude(1.0, -1, NULL);
-
return framelen;
}

Index: sbc/sbc.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc.h,v
retrieving revision 1.21
diff -u -r1.21 sbc.h
--- sbc/sbc.h 22 Aug 2005 07:11:14 -0000 1.21
+++ sbc/sbc.h 3 Sep 2005 14:57:06 -0000
@@ -29,8 +29,6 @@
extern "C" {
#endif

-#include <stdint.h>
-
#define SBC_NULL 0x00000001

struct sbc_struct {
@@ -53,90 +51,6 @@

typedef struct sbc_struct sbc_t;

-#ifdef USE_FIXED
-
-typedef int32_t sbc_fixed_t;
-
-// this must be an even number
-#define FRAC 20
-
-// FRAC/2 leading ones for sign-extended shift
-#define PAD (0xffffffff<<(32-(FRAC>>1)))
-
-// FRAC/2 trailing ones for finding the roundoff portion
-#define RMASK (0xffffffff>>(32-(FRAC>>1)))
-
-#define FIXED_ONE (1<<FRAC)
-
-// sign-extend half the number of shift (fractional) bits
-static inline sbc_fixed_t signextshift(sbc_fixed_t i) {
- if(i<0) return (i>>(FRAC>>1)) | PAD;
- return i>>(FRAC>>1);
-}
-
-static inline sbc_fixed_t itofixed(int i) { return i<<FRAC; }
-
-static inline int fixedtoi(sbc_fixed_t f) { return f>>FRAC; }
-
-static inline sbc_fixed_t dtofixed(double d) { return (sbc_fixed_t)(d * (double)FIXED_ONE); }
-
-static inline double fixedtod(sbc_fixed_t f) { return f / (double)FIXED_ONE; }
-
-static inline sbc_fixed_t fxmultquick(sbc_fixed_t a, sbc_fixed_t b) {
- sbc_fixed_t p = signextshift(a)*signextshift(b);
- return p;
-}
-
-static inline sbc_fixed_t fxmult(sbc_fixed_t a, sbc_fixed_t b) {
- // don't lose as much roundoff precision
- sbc_fixed_t ad = signextshift(a);
- sbc_fixed_t bd = signextshift(b);
- sbc_fixed_t p = (ad * bd) + signextshift(ad * (b & RMASK)) + signextshift(bd * (a & RMASK));
- return p;
-}
-
-//overflow problems?
-//static inline sbc_fixed_t fxdiv(sbc_fixed_t a, sbc_fixed_t b) { return (a<<FRAC)/b; }
-
-#define ADD64(dhi, dlo, shi, slo) { dlo += slo; dhi += shi; if ( (unsigned long)dlo < (unsigned long)slo ) dhi++;}
-#define SUB64(dhi, dlo, shi, slo) { dlo -= slo; dhi -= shi; if ( (unsigned long)dlo > (unsigned long)slo ) dhi--;}
-
-#ifdef __arm__
-// arm specific (should be fast on arm)
-
-#define MUL64(hi, lo, x, y) \
- asm ("smull %0, %1, %2, %3" \
- : "=&r" (lo), "=&r" (hi) \
- : "%r" (x), "r" (y))
-
-#define MULA64(hi, lo, x, y) \
- asm ("smlal %0, %1, %2, %3" \
- : "+r" (lo), "+r" (hi) \
- : "%r" (x), "r" (y))
-
-#define SCALE64(hi, lo, bits) \
- ({ int32_t __result; \
- asm ("movs %0, %1, lsr %3\n\t" \
- "adc %0, %0, %2, lsl %4" \
- : "=&r" (__result) \
- : "r" (lo), "r" (hi), \
- "M" (bits), "M" (32 - bits) \
- : "cc"); \
- __result; \
- })
-
-#else
-//general purpose (slow?)
-
-#define MUL64(hi, lo, a, b) {long long x; x = (long long)a * b; hi = (long)(x >> 32); lo = (long)x;}
-#define MULA64(hi, lo, a, b) {long long x; x = (long long)a * b; hi += (long)(x >> 32); lo += (long)x; if ((unsigned long)lo < (unsigned long)x) hi++;}
-#define SCALE64(hi, lo, bits) ((int32_t)((hi << (32 - bits)) | ((lo >> bits) & (0xFFFFFFFF >> bits))))
-
-#endif
-
-
-#endif
-
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);
Index: sbc/sbc_tables.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc_tables.h,v
retrieving revision 1.5
diff -u -r1.5 sbc_tables.h
--- sbc/sbc_tables.h 28 Aug 2005 05:32:19 -0000 1.5
+++ sbc/sbc_tables.h 3 Sep 2005 14:57:06 -0000
@@ -25,6 +25,8 @@
#ifndef __SBC_TABLES_H
#define __SBC_TABLES_H

+#include "sbc_math.h"
+
/* A2DP specification: Appendix B, page 69 */
static const int sbc_offset4[4][4] = {
{ -1, 0, 0, 0 },
@@ -175,6 +177,34 @@
-0.382683432365091, 0.555570233019606, -0.707106781186548, 0.831469612302547 }
};

+#ifdef USE_FIXED
+
+#ifdef USE_FIXED32
+
+#define SP8(val) (val >> SCALE_PROTO8_TBL)
+#define SA8(val) (val >> SCALE_ANA8_TBL)
+
+#else // USE_FIXED32
+
+#define SP8(val) (val)
+#define SA8(val) (val)
+
+#endif // USE_FIXED32
+
+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 _anamatrix8[8] = {
+ SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40), SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000)
+};
+
+#else // USE_FIXED
+
static const float _anamatrix8[8] = {
0.923879532511287, 0.382683432365091, 0.980785280403231, 0.831469612302547, 0.555570233019602,
0.195090322016128, 0.707106781186547, 1
@@ -189,14 +219,7 @@
1.99454557E-03, 1.78371731E-03, 1.53184105E-02, 1.45389840E-01, 8.85757525E-03, 2.10371986E-03,
2.01182533E-03, 1.29371807E-02, 1.46955073E-01, 9.02154483E-04
};
-
-static const float _anamatrix4[4] = {
- 0., 0., 0., 0.
-};
-
-static const float _sbc_proto_4[20] = {
- 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
- 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
-};
+#endif // USE_FIXED

#endif /* __SBC_TABLES_H */
+
Index: sbc/sbc_tables_f.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc_tables_f.h,v
retrieving revision 1.8
diff -u -r1.8 sbc_tables_f.h
--- sbc/sbc_tables_f.h 25 Aug 2005 23:14:50 -0000 1.8
+++ sbc/sbc_tables_f.h 3 Sep 2005 14:57:06 -0000
@@ -27,7 +27,7 @@
{ 0xf137ca20, 0xf9e08758, 0x061f78a8, 0x0ec835e0, 0x0ec835e0, 0x061f78a8, 0xf9e08758, 0xf137ca20 },
{ 0xf2b24cf0, 0x031f1708, 0x0fb14be0, 0x08e39da0, 0xf71c6260, 0xf04eb420, 0xfce0e8f8, 0x0d4db310 }
};
-
+/*
#define FIXED64_STAGE1 24
static const int32_t _sbc_proto_8_f[40] = {
0x02e5cd20, 0x22d0c200, 0x006bfe27, 0x07808930, 0x3f1c8800, 0xf8810d70, 0x002cfdc6, 0x055acf28,
@@ -42,3 +42,4 @@
0x3b20d780, 0x187de2a0, 0x3ec52f80, 0x3536cc40, 0x238e7680, 0x0c7c5c20, 0x2d413cc0, 0x40000000
};

+*/
\ No newline at end of file
--- /dev/null 2005-09-03 18:50:56.041670456 +0200
+++ sbc/sbc_math.h 2005-08-30 23:48:25.000000000 +0200
@@ -0,0 +1,108 @@
+#ifndef __SBC_MATH_H
+#define __SBC_MATH_H
+
+#include <stdint.h>
+
+#define fabs(x) ((x) < 0 ?-(x) : (x))
+
+#ifdef USE_FIXED
+
+#ifdef USE_FIXED32
+
+#define SCALE_PROTO8_TBL 18
+#define SCALE_ANA8_TBL 20
+#define SCALE_STAGE1_BITS 14
+#define SCALE_STAGE2_BITS 18
+
+typedef int32_t sbc_fixed_t;
+
+#define SBC_FIXED_0(val) {val = 0;}
+#define DIV2(dst, src) {dst = src >> 1;}
+
+#define ADD(dst, src) {dst += src;}
+#define SUB(dst, src) {dst -= src;}
+#define MUL(dst, a, b) {dst = a*b;}
+#define MULA(dst, a, b) {dst += a*b;}
+#define SCALE_STAGE1(src) (src >> SCALE_STAGE1_BITS)
+#define SCALE_STAGE2(src) (src >> SCALE_STAGE2_BITS)
+
+#else // USE_FIXED32
+
+#define SCALE_STAGE1_BITS 24
+#define SCALE_STAGE2_BITS 7
+
+struct sbc_fixed_struct{
+ int32_t hi;
+ uint32_t lo;
+};
+typedef struct sbc_fixed_struct sbc_fixed_t;
+
+#define SBC_FIXED_0(val) {val.hi = 0;val.lo = 0;}
+#define DIV2(dst, src) {dst.hi = src.hi >> 1; dst.lo = (src.lo >> 1); if (src.hi & 1) dst.lo |= 0x80000000; else dst.lo &= 0x7FFFFFFF;}
+
+#ifdef __arm__
+
+#define ADD(dst, src) \
+ asm ("adds %0, %0, %2\n\t" \
+ "adc %1, %1, %3" \
+ : "+r" (dst.lo), "+r" (dst.hi) \
+ : "%r" (src.lo), "r" (src.hi))
+
+#define SUB(dst, src) \
+ asm ("subs %0, %0, %2\n\t" \
+ "sbc %1, %1, %3" \
+ : "+r" (dst.lo), "+r" (dst.hi) \
+ : "%r" (src.lo), "r" (src.hi))
+
+#define MUL(dst, a, b) \
+ asm ("smull %0, %1, %2, %3" \
+ : "=&r" (dst.lo), "=&r" (dst.hi) \
+ : "%r" (a), "r" (b))
+
+#define MULA(dst, a, b) \
+ asm ("smlal %0, %1, %2, %3" \
+ : "+r" (dst.lo), "+r" (dst.hi) \
+ : "%r" (a), "r" (b))
+
+#define SCALE_STAGE1(src) \
+ ({ int32_t __result; \
+ asm ("movs %0, %1, lsr %3\n\t" \
+ "adc %0, %0, %2, lsl %4" \
+ : "=&r" (__result) \
+ : "r" (src.lo), "r" (src.hi), \
+ "M" (SCALE_STAGE1_BITS), "M" (32 - SCALE_STAGE1_BITS) \
+ : "cc"); \
+ __result; \
+ })
+
+#define SCALE_STAGE2(src) (src.hi >> SCALE_STAGE2_BITS)
+
+#else // _arm_
+
+#define ADD(dst, src) {dst.lo += src.lo; dst.hi += src.hi; if ( dst.lo < src.lo ) dst.hi++;}
+#define SUB(dst, src) {dst.hi -= src.hi; if ( dst.lo < src.lo ) dst.hi--; dst.lo -= src.lo;}
+#define MUL(dst, a, b) {int64_t x; x = (int64_t)a * b; dst.hi = x >> 32; dst.lo = x;}
+#define MULA(dst, a, b) {int64_t x; x = (int64_t)a * b; dst.hi += (x >> 32); dst.lo += x; if (dst.lo < (uint32_t)x) dst.hi++;}
+#define SCALE_STAGE1(src) ((int32_t)((src.hi << (32 - SCALE_STAGE1_BITS)) | ((src.lo >> SCALE_STAGE1_BITS) & (0xFFFFFFFF >> SCALE_STAGE1_BITS))))
+#define SCALE_STAGE2(src) (src.hi >> SCALE_STAGE2_BITS)
+
+#endif // __arm__
+
+#endif // USE_FIXED32
+
+#else // USE_FIXED
+
+typedef double sbc_fixed_t;
+
+#define SBC_FIXED_0(val) {val = 0;}
+#define DIV2(dst, src) {dst = src / 2;}
+#define ADD(dst, src) {dst += src;}
+#define SUB(dst, src) {dst -= src;}
+#define MUL(dst, a, b) {dst = a*b;}
+#define MULA(dst, a, b) {dst += a*b;}
+#define SCALE_STAGE1(src) (src)
+#define SCALE_STAGE2(src) (src)
+
+#endif // USE_FIXED
+
+#endif // __SBC_MATH_H