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

Victor Shcherbatyuk
2005-08-21T18:47:40Z

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

Hello Brad,

In the attachment is the patch to support fixed point encoding for 8-subband
sbc codec. To compie ARM specific version USE_FIXED_ARM should be defined
(currently in sbc/sbc.c should be in configuration?). It is possible I broke
your fixed point tables cause I've changed gen_fixed.c, but it should be
easy fixable.

Floating point implementation is optimized too, runs 30% faster on my
AthlonXP. General fixed point (long long) runs slower than floating on my
PC, which is strange... I do not have HW to test arm specific version real
time, hope no suprises there, but I could have missed something when
integrating it into sbc code (it decodes well, but how fast, I will try only
monday evening).

Using a2play needs to tweak 87 magic number, otherwise it drops samples?

Regards,
Victor.

P.S. There are a lot of changes, I hope I didn't miss any... Please take a
look, and let me know if something is wrong with it...

----- Original Message -----
From: "Brad Midgley" <bmidgley@xmission.com>
To: <bluez-devel@lists.sourceforge.net>
Sent: Thursday, July 28, 2005 16:59
Subject: Re: [Bluez-devel] sbc and fixed-point progress

> Victor,
>
> Great! Can you send me the output of "cvs diff -u" or the resulting sbc.c?
>
> Even if it's noisy, we will just make it optional using the compile-time
> option and improve it over time. Right now we have no way at all to encode
> on arm, so even a noisy encoder would be going in the right direction.
>
> I started working on the decoder but got stuck when I found that the
> state->W and state->X variables sometimes needed large precision and
> sometimes had large integer parts (ie in a naive fixed-point
> implementation, they would need more than 32 bits). I was contemplating
> keeping a large precision in the fixed point type but using a separate
> integer for those variables' integer part.
>
> Brad
>
> Victor Shcherbatyuk wrote:
>> Hello Brad,
>>
>> FYI,
>>
>> Yesterday I converted encoder to fixed point (I did it a dirty way, so
>> probably it doesn't have much of the value). I've converted each of the
>> tables with different precision in such a way that the operations
>> involving the tables (mults and adds) will not overflow 32 bit, and
>> where necessary I pre-shift intermediate results to prevent overlowing.
>> Currently the output is a slightly noisy, but the purpose was to
>> estimate required performance. The result is, in the current
>> implementation, using fixed point it is just about to be enough to run
>> on 400Mhz arm combined with mp3 decoder (mp3 piped though mad mp3
>> decoder to sbc encoder to a2play). This means either something is wrong
>> :) or SBC codec should be heavily optimized (3 - 5 times ?) to make it
>> reasonable (memcopies is the first thing to optimize probably)...
>>
>> Regards,
>> Victor.
>>
>>
>> -----Original Message-----
>> From: bluez-devel-admin@lists.sourceforge.net
>> [mailto:bluez-devel-admin@lists.sourceforge.net] On Behalf Of Brad
>> Midgley
>> Sent: Monday, July 04, 2005 6:03 AM
>> To: BlueZ Mailing List
>> Subject: [Bluez-devel] sbc and fixed-point progress
>>
>> Guys,
>>
>> just FYI...
>>
>> I found a decent fixed point multiply that preshifts the values before
>> multiplying them. It keeps things in 32 bits. Most of the roundoff error
>> is taken care of in two additional terms. I think the result is
>> reasonable.
>> (http://www.accu.org/acornsig/public/caugers/volume2/issue6/fixedpoint.h
>> tml)
>>
>> If you compile with fixed-point on, libsbc will run both the fixed and
>> floating point calculations and flag errors when they differ too much.
>> It seems to be working well and has helped me catch a couple of
>> fixed-point calculation problems.
>>
>> I have the decoder almost finished but I probably need to split some
>> terms into integer and fixed-point components. Loading up
>> frame->sb_sample for example can have a big integer part but we want to
>> use most of the 32 bit fixed-point type for the fractional part.
>>
>> Brad
>>
>>
>>
>> -------------------------------------------------------
>> SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
>> from IBM. Find simple to follow Roadmaps, straightforward articles,
>> informative Webcasts and more! Get everything you need to get up to
>> speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
>> _______________________________________________
>> Bluez-devel mailing list
>> Bluez-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/bluez-devel
>>
>>
>> This e-mail message contains information which is confidential and may be
>> privileged. It is intended for use by the addressee only. If you are not
>> the intended addressee, we request that you notify the sender immediately
>> and delete or destroy this e-mail message and any attachment(s), without
>> copying, saving, forwarding, disclosing or using its contents in any
>> other way. TomTom N.V., TomTom International BV or any other company
>> belonging to the TomTom group of companies will not be liable for damage
>> relating to the communication by e-mail of data, documents or any other
>> information.
>>
>>
>> -------------------------------------------------------
>> SF.Net email is Sponsored by the Better Software Conference & EXPO
>> September
>> 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
>> Agile & Plan-Driven Development * Managing Projects & Teams * Testing &
>> QA
>> Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
>> _______________________________________________
>> Bluez-devel mailing list
>> Bluez-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/bluez-devel
>
>
> -------------------------------------------------------
> SF.Net email is Sponsored by the Better Software Conference & EXPO
> September
> 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
> Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
> Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel

[-- Attachment #2: sbc-fixed.patch --]
[-- Type: application/octet-stream, Size: 41154 bytes --]

? sbc/play
? sbc/test.pcm
? sbc/test.sbc
? sbc/test1.sbc
Index: sbc/gen_fixed.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/gen_fixed.c,v
retrieving revision 1.2
diff -u -r1.2 gen_fixed.c
--- sbc/gen_fixed.c 22 Jun 2005 18:08:45 -0000 1.2
+++ sbc/gen_fixed.c 21 Aug 2005 18:26:31 -0000
@@ -1,5 +1,6 @@
#define USE_FIXED

+#include <math.h>
#include "sbc.h"
#include "sbc_tables.h"

@@ -8,13 +9,15 @@
void *ref;
int i;
int j;
+ int bits;
} tables[] = {
- {"sbc_proto_4_40_f", (void *)sbc_proto_4_40, 40, 1},
- {"sbc_proto_8_80_f", (void *)sbc_proto_8_80, 80, 1},
- {"synmatrix4_f", (void *)synmatrix4, 8, 4},
- {"synmatrix8_f", (void *)synmatrix8, 16, 8},
- {"anamatrix4_f", (void *)anamatrix4, 4, 8},
- {"anamatrix8_f", (void *)anamatrix8, 8, 16},
+ {"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},
+ {"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},
{0, 0, 0, 0}
};

@@ -23,15 +26,33 @@
float *array;
for(entry = 0; tables[entry].name; entry++) {
if(tables[entry].j == 1) {
- printf("static const sbc_fixed_t %s[%d] = {\n",
- tables[entry].name, tables[entry].i);
+ 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);
+ }
+ else
+ printf("static const sbc_fixed_t %s[%d] = {\n",
+ tables[entry].name, tables[entry].i);
array = (float *)tables[entry].ref;
for(i = 0; i < tables[entry].i; i++) {
if(i>0) {
printf(", ");
if(i%8 == 0) printf("\n");
}
- printf("0x%08x", dtofixed(array[i]));
+ double res = array[i]*pow(2, tables[entry].bits);
+ if (res > 0 )
+ res += 0.5;
+ else
+ res += -0.5;
+ if (fabs(res) > (double)(0xFFFFFFFF / 2.0)) {
+ printf("OVERFLOW (%f)!\n", res);
+ exit(1);
+ }
+ printf("0x%08x", (int32_t)res);
}
printf("\n};\n\n");
} else {
@@ -47,7 +68,16 @@
printf(", ");
if(j%8 == 0) printf("\n");
}
- printf("0x%08x", dtofixed(array[idx++]));
+ double res = array[idx++]*pow(2, tables[entry].bits);
+ if (res > 0 )
+ res += 0.5;
+ else
+ res += -0.5;
+ if (fabs(res) > (double)(0xFFFFFFFF / 2.0)) {
+ printf("OVERFLOW (%f)!\n", res);
+ exit(1);
+ }
+ printf("0x%08x", (int32_t)res);
}
printf(" }");
}
Index: sbc/sbc.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc.c,v
retrieving revision 1.47
diff -u -r1.47 sbc.c
--- sbc/sbc.c 26 Jul 2005 20:30:52 -0000 1.47
+++ sbc/sbc.c 21 Aug 2005 18:26:32 -0000
@@ -36,6 +36,8 @@

*/

+//#define USE_FIXED_ARM
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -68,7 +70,6 @@
}
return 0;
}
-
#endif

struct magnitude {
@@ -155,7 +156,7 @@
/* This structure contains an unpacked SBC frame.
Yes, there is probably quite some unused space herein */
struct sbc_frame {
- double sampling_frequency; /* in kHz */
+ u_int16_t sampling_frequency; /* in kHz */
u_int8_t blocks;
enum {
MONO = SBC_CM_MONO,
@@ -178,7 +179,7 @@
sbc_fixed_t pcm_sample_f[2][16*8];
#endif
double sb_sample[16][2][8]; /* modified subband samples */
- double pcm_sample[2][16*8]; /* original pcm audio samples */
+ int16_t pcm_sample[2][16*8]; /* original pcm audio samples */
};

struct sbc_decoder_state {
@@ -196,8 +197,9 @@

struct sbc_encoder_state {
int subbands;
- float S[2][8]; /* Subband samples */
- float X[2][80], Y[2][16], Z[2][80]; /* Vectors */
+ double S[2][8]; /* Subband samples */
+ double Y[2][16], Z[2][80]; /* Vectors */
+ int32_t X[2][80];
};

/*
@@ -497,16 +499,16 @@
sf = (data[1] >> 6) & 0x03;
switch (sf) {
case SBC_FS_16:
- frame->sampling_frequency = 16;
+ frame->sampling_frequency = 16000;
break;
case SBC_FS_32:
- frame->sampling_frequency = 32;
+ frame->sampling_frequency = 32000;
break;
case SBC_FS_44:
- frame->sampling_frequency = 44.1;
+ frame->sampling_frequency = 44100;
break;
case SBC_FS_48:
- frame->sampling_frequency = 48;
+ frame->sampling_frequency = 48000;
break;
}

@@ -794,7 +796,7 @@

/* Output 4 reconstructed Audio Samples */
for (i = 0; i < 4; i++) {
- frame->pcm_sample[ch][blk * 4 + i] = state->X[ch][i];
+ frame->pcm_sample[ch][blk * 4 + i] = (int16_t)state->X[ch][i];
#ifdef USE_FIXED
frame->pcm_sample_f[ch][blk * 4 + i] = state->X_f[ch][i];
assertf(0, frame->pcm_sample[ch][blk * 4 + i], frame->pcm_sample_f[ch][blk * 4 + i], "output samples");
@@ -891,7 +893,7 @@

/* Ouput 8 reconstructed Audio Samples */
for (i = 0; i < 8; i++) {
- frame->pcm_sample[ch][blk * 8 + i] = state->X[ch][i];
+ frame->pcm_sample[ch][blk * 8 + i] = (int16_t)state->X[ch][i];
#ifdef USE_FIXED
frame->pcm_sample_f[ch][blk * 8 + i] = state->X_f[ch][i];
assertf(0, frame->pcm_sample[ch][blk * 8 + i], frame->pcm_sample_f[ch][blk * 8 + i], "output samples");
@@ -973,39 +975,316 @@
for (i = 0; i < 4; i++)
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])
+{
+ 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;
+
+}
+#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;
+
+ 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)
+ struct sbc_frame *frame, int ch, int blk)
{
- int i, k;
+ 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)];
-
- /* Windowing by 80 coefficients */
- for (i = 0; i < 80; i++)
- state->Z[ch][i] = sbc_proto_8_80[i] * state->X[ch][i];
-
- /* Partial calculation */
- for (i = 0; i < 16; i++) {
- state->Y[ch][i] = 0;
- for (k = 0; k < 5; k++)
- state->Y[ch][i] += state->Z[ch][i + k * 16];
- }
-
- /* Calculate 8 subband samples by Matrixing */
- for (i = 0; i < 8; i++) {
- state->S[ch][i] = 0;
- for (k = 0; k < 16; k++)
- state->S[ch][i] += anamatrix8[i][k] * state->Y[ch][k];
- }
-
- /* Output 8 Subband Samples */
- for (i = 0; i < 8; i++)
- frame->sb_sample[blk][ch][i] = state->S[ch][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)
@@ -1026,8 +1305,6 @@
case 8:
for (ch = 0; ch < frame->channels; ch++)
for (blk = 0; blk < frame->blocks; blk++) {
- memset(frame->sb_sample[blk][ch], 0,
- sizeof(frame->sb_sample[blk][ch]));
sbc_analyze_eight(state, frame, ch, blk);
}

@@ -1066,7 +1343,7 @@
int bits[2][8]; /* bits distribution */
int levels[2][8]; /* levels are derived from that */

- double scalefactor[2][8]; /* derived from frame->scale_factor */
+ u_int32_t scalefactor[2][8]; /* derived from frame->scale_factor */

if (len < 4) {
return -1;
@@ -1077,16 +1354,16 @@

data[0] = SBC_SYNCWORD;

- if (frame->sampling_frequency == 16) {
+ if (frame->sampling_frequency == 16000) {
data[1] |= (SBC_FS_16 & 0x03) << 6;
sf = SBC_FS_16;
- } else if (frame->sampling_frequency == 32) {
+ } else if (frame->sampling_frequency == 32000) {
data[1] |= (SBC_FS_32 & 0x03) << 6;
sf = SBC_FS_32;
- } else if (frame->sampling_frequency == 44.1) {
+ } else if (frame->sampling_frequency == 44100) {
data[1] |= (SBC_FS_44 & 0x03) << 6;
sf = SBC_FS_44;
- } else if (frame->sampling_frequency == 48) {
+ } else if (frame->sampling_frequency == 48000) {
data[1] |= (SBC_FS_48 & 0x03) << 6;
sf = SBC_FS_48;
} else {
@@ -1149,7 +1426,11 @@
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
frame->scale_factor[ch][sb]++;
scalefactor[ch][sb] *= 2;
}
@@ -1252,9 +1533,15 @@
for (ch = 0; ch < frame->channels; ch++) {
for (sb = 0; sb < frame->subbands; sb++) {
if (levels[ch][sb] > 0) {
+#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)) +
+ levels[ch][sb]) >> 1);
+#else
frame->audio_sample[blk][ch][sb] =
- (u_int16_t) (((frame->sb_sample[blk][ch][sb] / scalefactor[ch][sb] +
- 1.0) * levels[ch][sb]) / 2.0);
+ (u_int16_t) (((frame->sb_sample[blk][ch][sb] / scalefactor[ch][sb] +
+ 1.0) * levels[ch][sb]) / 2.0);
+#endif
} else {
frame->audio_sample[blk][ch][sb] = 0;
}
@@ -1339,7 +1626,7 @@
sbc_decoder_init(&priv->dec_state, &priv->frame);
priv->init = 1;

- sbc->rate = priv->frame.sampling_frequency * 1000;
+ sbc->rate = priv->frame.sampling_frequency;
sbc->channels = priv->frame.channels;
sbc->subbands = priv->frame.subbands;
sbc->blocks = priv->frame.blocks;
@@ -1367,11 +1654,11 @@

for (i = 0; i < samples; i++) {
for (ch = 0; ch < priv->frame.channels; ch++) {
- uint16_t s;
+ int16_t s;
#ifdef USE_FIXED
s = (uint16_t)fixedtoi(priv->frame.pcm_sample_f[ch][i]);
#else
- s = (uint16_t)(priv->frame.pcm_sample[ch][i]);
+ s = priv->frame.pcm_sample[ch][i];
#endif
*ptr++ = (s & 0xff00) >> 8;
*ptr++ = (s & 0x00ff);
@@ -1397,7 +1684,7 @@
priv = sbc->priv;

if (!priv->init) {
- priv->frame.sampling_frequency = ((double) sbc->rate) / 1000;
+ priv->frame.sampling_frequency = sbc->rate;

priv->frame.channels = sbc->channels;

@@ -1420,7 +1707,7 @@
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] = ((double) s);
+ priv->frame.pcm_sample[ch][i] = s;
}
}

Index: sbc/sbc.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc.h,v
retrieving revision 1.20
diff -u -r1.20 sbc.h
--- sbc/sbc.h 4 Jul 2005 03:56:51 -0000 1.20
+++ sbc/sbc.h 21 Aug 2005 18:26:32 -0000
@@ -97,6 +97,44 @@

//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 USE_FIXED_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);
Index: sbc/sbc_tables.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbc_tables.h,v
retrieving revision 1.2
diff -u -r1.2 sbc_tables.h
--- sbc/sbc_tables.h 24 Nov 2004 06:45:21 -0000 1.2
+++ sbc/sbc_tables.h 21 Aug 2005 18:26:32 -0000
@@ -175,4 +175,19 @@
-0.382683432365091, 0.555570233019606, -0.707106781186548, 0.831469612302547 }
};

+static const float _anamatrix8[8] = {
+ 0.923879532511287, 0.382683432365091, 0.980785280403231, 0.831469612302547, 0.555570233019602,
+ 0.195090322016128, 0.707106781186547, 1
+};
+
+static const float _sbc_proto_8[40] = {
+ 5.65949455E-03, 6.79989457E-02, 8.23919487E-04, 1.46525260E-02, 1.23264551E-01,-1.46404076E-02,
+ 3.43256426E-04, 1.04584442E-02, 9.75753888E-02, -3.90751399E-02, -1.64973096E-03, 1.56575392E-04,
+ 8.02941155E-03, 8.29847604E-02, -5.31873032E-02, -3.49717448E-03, 5.54620230E-04, 1.27472337E-02,
+ 1.11196689E-01, -2.61098761E-02, -1.78805363E-04, 1.13992509E-03, 1.59045607E-02, 1.33264422E-01,
+ -4.91578039E-03, 1.61656283E-03, 1.47640170E-03, 1.62208471E-02, 1.40753508E-01, 2.92408443E-03,
+ 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
+};
+
#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.6
diff -u -r1.6 sbc_tables_f.h
--- sbc/sbc_tables_f.h 4 Jul 2005 03:56:51 -0000 1.6
+++ sbc/sbc_tables_f.h 21 Aug 2005 18:26:32 -0000
@@ -1,77 +1,72 @@
static const sbc_fixed_t sbc_proto_4_40_f[40] = {
-0x00000000, 0x00000232, 0x0000061c, 0x00000b32, 0x00000fb7, 0x00000ff1, 0x000007a4, 0xfffff378,
-0x00002cb3, 0x000053b7, 0x00007646, 0x000083dd, 0x000069fd, 0x0000191e, 0xffff89f3, 0xfffec1f6,
-0x00022b63, 0x00031eab, 0x0003f239, 0x0004825e, 0x0004b584, 0x0004825e, 0x0003f239, 0x00031eab,
-0xfffdd49d, 0xfffec1f6, 0xffff89f3, 0x0000191e, 0x000069fd, 0x000083dd, 0x00007646, 0x000053b7,
-0xffffd34d, 0xfffff378, 0x000007a4, 0x00000ff1, 0x00000fb7, 0x00000b32, 0x0000061c, 0x00000232
+0x00000000, 0x0002329d, 0x00061c5a, 0x000b3280, 0x000fb799, 0x000ff11d, 0x0007a473, 0xfff3773a,
+0x002cb3e9, 0x0053b755, 0x00764668, 0x0083ddc8, 0x0069fdc6, 0x00191e58, 0xff89f23a, 0xfec1f5e6,
+0x022b63dc, 0x031eab94, 0x03f23948, 0x04825e48, 0x04b58400, 0x04825e48, 0x03f23948, 0x031eab94,
+0xfdd49c24, 0xfec1f5e6, 0xff89f23a, 0x00191e58, 0x0069fdc6, 0x0083ddc8, 0x00764668, 0x0053b755,
+0xffd34c17, 0xfff3773a, 0x0007a473, 0x000ff11d, 0x000fb799, 0x000b3280, 0x00061c5a, 0x0002329d
};

static const sbc_fixed_t sbc_proto_8_80_f[80] = {
-0x00000000, 0x000000a4, 0x00000167, 0x00000245, 0x0000035f, 0x000004ab, 0x0000060c, 0x0000074e,
-0x0000083d, 0x0000089d, 0x0000082b, 0x0000069f, 0x000003b1, 0xffffff45, 0xfffff93f, 0xfffff1ad,
-0x0000172e, 0x000020e3, 0x00002ad6, 0x00003436, 0x00003c04, 0x00004125, 0x00004270, 0x00003ebe,
-0x000034fd, 0x00002447, 0x00000bfa, 0xffffebde, 0xffffc409, 0xffff950e, 0xffff5ff3, 0xffff2626,
-0x00011686, 0x000153e7, 0x00018fab, 0x0001c776, 0x0001f8e4, 0x000221d9, 0x00024086, 0x00025384,
-0x000259ed, 0x00025384, 0x00024086, 0x000221d9, 0x0001f8e4, 0x0001c776, 0x00018fab, 0x000153e7,
-0xfffee97a, 0xffff2626, 0xffff5ff3, 0xffff950e, 0xffffc409, 0xffffebde, 0x00000bfa, 0x00002447,
-0x000034fd, 0x00003ebe, 0x00004270, 0x00004125, 0x00003c04, 0x00003436, 0x00002ad6, 0x000020e3,
-0xffffe8d2, 0xfffff1ad, 0xfffff93f, 0xffffff45, 0x000003b1, 0x0000069f, 0x0000082b, 0x0000089d,
-0x0000083d, 0x0000074e, 0x0000060c, 0x000004ab, 0x0000035f, 0x00000245, 0x00000167, 0x000000a4
+0x00000000, 0x0000a42e, 0x000167ee, 0x00024590, 0x00035ff1, 0x0004ab4c, 0x00060c1f, 0x00074e5d,
+0x00083d8d, 0x00089de9, 0x00082b6f, 0x00069f17, 0x0003b1fa, 0xffff4482, 0xfff93e22, 0xfff1acf2,
+0x00172e69, 0x0020e373, 0x002ad679, 0x00343672, 0x003c044a, 0x00412524, 0x004270cb, 0x003ebe85,
+0x0034fd9e, 0x002447d7, 0x000bfa20, 0xffebdd6e, 0xffc4086b, 0xff950dcf, 0xff5ff2bf, 0xff262512,
+0x01168610, 0x0153e7d4, 0x018fab36, 0x01c7762e, 0x01f8e440, 0x0221d9e0, 0x024086c0, 0x0253844c,
+0x0259ed90, 0x0253844c, 0x024086c0, 0x0221d9e0, 0x01f8e440, 0x01c7762e, 0x018fab36, 0x0153e7d4,
+0xfee979f0, 0xff262512, 0xff5ff2bf, 0xff950dcf, 0xffc4086b, 0xffebdd6e, 0x000bfa20, 0x002447d7,
+0x0034fd9e, 0x003ebe85, 0x004270cb, 0x00412524, 0x003c044a, 0x00343672, 0x002ad679, 0x0020e373,
+0xffe8d197, 0xfff1acf2, 0xfff93e22, 0xffff4482, 0x0003b1fa, 0x00069f17, 0x00082b6f, 0x00089de9,
+0x00083d8d, 0x00074e5d, 0x00060c1f, 0x0004ab4c, 0x00035ff1, 0x00024590, 0x000167ee, 0x0000a42e
};

static const sbc_fixed_t synmatrix4_f[8][4] = {
-{ 0x000b504f, 0xfff4afb1, 0xfff4afb1, 0x000b504f },
-{ 0x00061f78, 0xfff137cb, 0x000ec835, 0xfff9e088 },
+{ 0x0b504f30, 0xf4afb0d0, 0xf4afb0d0, 0x0b504f30 },
+{ 0x061f78a8, 0xf137ca20, 0x0ec835e0, 0xf9e08758 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-{ 0xfff9e088, 0x000ec835, 0xfff137cb, 0x00061f78 },
-{ 0xfff4afb1, 0x000b504f, 0x000b504f, 0xfff4afb1 },
-{ 0xfff137cb, 0xfff9e088, 0x00061f78, 0x000ec835 },
-{ 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000 },
-{ 0xfff137cb, 0xfff9e088, 0x00061f78, 0x000ec835 }
+{ 0xf9e08758, 0x0ec835e0, 0xf137ca20, 0x061f78a8 },
+{ 0xf4afb0d0, 0x0b504f30, 0x0b504f30, 0xf4afb0d0 },
+{ 0xf137ca20, 0xf9e08758, 0x061f78a8, 0x0ec835e0 },
+{ 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 },
+{ 0xf137ca20, 0xf9e08758, 0x061f78a8, 0x0ec835e0 }
};

static const sbc_fixed_t synmatrix8_f[16][8] = {
-{ 0x000b504f, 0xfff4afb1, 0xfff4afb1, 0x000b504f, 0x000b504f, 0xfff4afb1, 0xfff4afb1, 0x000b504f },
-{ 0x0008e39d, 0xfff04eb5, 0x00031f17, 0x000d4db3, 0xfff2b24d, 0xfffce0e9, 0x000fb14b, 0xfff71c63 },
-{ 0x00061f78, 0xfff137cb, 0x000ec835, 0xfff9e088, 0xfff9e088, 0x000ec835, 0xfff137cb, 0x00061f78 },
-{ 0x00031f17, 0xfff71c63, 0x000d4db3, 0xfff04eb5, 0x000fb14b, 0xfff2b24d, 0x0008e39d, 0xfffce0e9 },
+{ 0x0b504f30, 0xf4afb0d0, 0xf4afb0d0, 0x0b504f30, 0x0b504f30, 0xf4afb0d0, 0xf4afb0d0, 0x0b504f30 },
+{ 0x08e39da0, 0xf04eb420, 0x031f1708, 0x0d4db310, 0xf2b24cf0, 0xfce0e8f8, 0x0fb14be0, 0xf71c6260 },
+{ 0x061f78a8, 0xf137ca20, 0x0ec835e0, 0xf9e08758, 0xf9e08758, 0x0ec835e0, 0xf137ca20, 0x061f78a8 },
+{ 0x031f1708, 0xf71c6260, 0x0d4db310, 0xf04eb420, 0x0fb14be0, 0xf2b24cf0, 0x08e39da0, 0xfce0e8f8 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
-{ 0xfffce0e9, 0x0008e39d, 0xfff2b24d, 0x000fb14b, 0xfff04eb5, 0x000d4db3, 0xfff71c63, 0x00031f17 },
-{ 0xfff9e088, 0x000ec835, 0xfff137cb, 0x00061f78, 0x00061f78, 0xfff137cb, 0x000ec835, 0xfff9e088 },
-{ 0xfff71c63, 0x000fb14b, 0xfffce0e9, 0xfff2b24d, 0x000d4db3, 0x00031f17, 0xfff04eb5, 0x0008e39d },
-{ 0xfff4afb1, 0x000b504f, 0x000b504f, 0xfff4afb1, 0xfff4afb1, 0x000b504f, 0x000b504f, 0xfff4afb1 },
-{ 0xfff2b24d, 0x00031f17, 0x000fb14b, 0x0008e39d, 0xfff71c63, 0xfff04eb5, 0xfffce0e9, 0x000d4db3 },
-{ 0xfff137cb, 0xfff9e088, 0x00061f78, 0x000ec835, 0x000ec835, 0x00061f78, 0xfff9e088, 0xfff137cb },
-{ 0xfff04eb5, 0xfff2b24d, 0xfff71c63, 0xfffce0e9, 0x00031f17, 0x0008e39d, 0x000d4db3, 0x000fb14b },
-{ 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000, 0xfff00000 },
-{ 0xfff04eb5, 0xfff2b24d, 0xfff71c63, 0xfffce0e9, 0x00031f17, 0x0008e39d, 0x000d4db3, 0x000fb14b },
-{ 0xfff137cb, 0xfff9e088, 0x00061f78, 0x000ec835, 0x000ec835, 0x00061f78, 0xfff9e088, 0xfff137cb },
-{ 0xfff2b24d, 0x00031f17, 0x000fb14b, 0x0008e39d, 0xfff71c63, 0xfff04eb5, 0xfffce0e9, 0x000d4db3 }
+{ 0xfce0e8f8, 0x08e39da0, 0xf2b24cf0, 0x0fb14be0, 0xf04eb420, 0x0d4db310, 0xf71c6260, 0x031f1708 },
+{ 0xf9e08758, 0x0ec835e0, 0xf137ca20, 0x061f78a8, 0x061f78a8, 0xf137ca20, 0x0ec835e0, 0xf9e08758 },
+{ 0xf71c6260, 0x0fb14be0, 0xfce0e8f8, 0xf2b24cf0, 0x0d4db310, 0x031f1708, 0xf04eb420, 0x08e39da0 },
+{ 0xf4afb0d0, 0x0b504f30, 0x0b504f30, 0xf4afb0d0, 0xf4afb0d0, 0x0b504f30, 0x0b504f30, 0xf4afb0d0 },
+{ 0xf2b24cf0, 0x031f1708, 0x0fb14be0, 0x08e39da0, 0xf71c6260, 0xf04eb420, 0xfce0e8f8, 0x0d4db310 },
+{ 0xf137ca20, 0xf9e08758, 0x061f78a8, 0x0ec835e0, 0x0ec835e0, 0x061f78a8, 0xf9e08758, 0xf137ca20 },
+{ 0xf04eb420, 0xf2b24cf0, 0xf71c6260, 0xfce0e8f8, 0x031f1708, 0x08e39da0, 0x0d4db310, 0x0fb14be0 },
+{ 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 },
+{ 0xf04eb420, 0xf2b24cf0, 0xf71c6260, 0xfce0e8f8, 0x031f1708, 0x08e39da0, 0x0d4db310, 0x0fb14be0 },
+{ 0xf137ca20, 0xf9e08758, 0x061f78a8, 0x0ec835e0, 0x0ec835e0, 0x061f78a8, 0xf9e08758, 0xf137ca20 },
+{ 0xf2b24cf0, 0x031f1708, 0x0fb14be0, 0x08e39da0, 0xf71c6260, 0xf04eb420, 0xfce0e8f8, 0x0d4db310 }
};

static const sbc_fixed_t anamatrix4_f[4][8] = {
-{ 0x000b504f, 0x000ec835, 0x00100000, 0x000ec835, 0x000b504f, 0x00061f78, 0x00000000, 0xfff9e088 },
-{ 0xfff4afb1, 0x00061f78, 0x00100000, 0x00061f78, 0xfff4afb1, 0xfff137cb, 0x00000000, 0x000ec835 },
-{ 0xfff4afb1, 0xfff9e088, 0x00100000, 0xfff9e088, 0xfff4afb1, 0x000ec835, 0x00000000, 0xfff137cb },
-{ 0x000b504f, 0xfff137cb, 0x00100000, 0xfff137cb, 0x000b504f, 0xfff9e088, 0x00000000, 0x00061f78 }
-};
-
-static const sbc_fixed_t anamatrix8_f[8][16] = {
-{ 0x000ec835, 0x000fb14b, 0x00100000, 0x000fb14b, 0x000ec835, 0x000d4db3, 0x000b504f, 0x0008e39d,
-0x00061f78, 0x00031f17, 0x00000000, 0xfffce0e9, 0xfff9e088, 0xfff71c63, 0xfff4afb1, 0xfff2b24d },
-{ 0x00061f78, 0x000d4db3, 0x00100000, 0x000d4db3, 0x00061f78, 0xfffce0e9, 0xfff4afb1, 0xfff04eb5,
-0xfff137cb, 0xfff71c63, 0x00000000, 0x0008e39d, 0x000ec835, 0x000fb14b, 0x000b504f, 0x00031f17 },
-{ 0xfff9e088, 0x0008e39d, 0x00100000, 0x0008e39d, 0xfff9e088, 0xfff04eb5, 0xfff4afb1, 0x00031f17,
-0x000ec835, 0x000d4db3, 0x00000000, 0xfff2b24d, 0xfff137cb, 0xfffce0e9, 0x000b504f, 0x000fb14b },
-{ 0xfff137cb, 0x00031f17, 0x00100000, 0x00031f17, 0xfff137cb, 0xfff71c63, 0x000b504f, 0x000d4db3,
-0xfff9e088, 0xfff04eb5, 0x00000000, 0x000fb14b, 0x00061f78, 0xfff2b24d, 0xfff4afb1, 0x0008e39d },
-{ 0xfff137cb, 0xfffce0e9, 0x00100000, 0xfffce0e9, 0xfff137cb, 0x0008e39d, 0x000b504f, 0xfff2b24d,
-0xfff9e088, 0x000fb14b, 0x00000000, 0xfff04eb5, 0x00061f78, 0x000d4db3, 0xfff4afb1, 0xfff71c63 },
-{ 0xfff9e088, 0xfff71c63, 0x00100000, 0xfff71c63, 0xfff9e088, 0x000fb14b, 0xfff4afb1, 0xfffce0e9,
-0x000ec835, 0xfff2b24d, 0x00000000, 0x000d4db3, 0xfff137cb, 0x00031f17, 0x000b504f, 0xfff04eb5 },
-{ 0x00061f78, 0xfff2b24d, 0x00100000, 0xfff2b24d, 0x00061f78, 0x00031f17, 0xfff4afb1, 0x000fb14b,
-0xfff137cb, 0x0008e39d, 0x00000000, 0xfff71c63, 0x000ec835, 0xfff04eb5, 0x000b504f, 0xfffce0e9 },
-{ 0x000ec835, 0xfff04eb5, 0x00100000, 0xfff04eb5, 0x000ec835, 0xfff2b24d, 0x000b504f, 0xfff71c63,
-0x00061f78, 0xfffce0e9, 0x00000000, 0x00031f17, 0xfff9e088, 0x0008e39d, 0xfff4afb1, 0x000d4db3 }
+{ 0x0b504f30, 0x0ec835e0, 0x10000000, 0x0ec835e0, 0x0b504f30, 0x061f78a8, 0x00000000, 0xf9e08758 },
+{ 0xf4afb0d0, 0x061f78a8, 0x10000000, 0x061f78a8, 0xf4afb0d0, 0xf137ca20, 0x00000000, 0x0ec835e0 },
+{ 0xf4afb0d0, 0xf9e08758, 0x10000000, 0xf9e08758, 0xf4afb0d0, 0x0ec835e0, 0x00000000, 0xf137ca20 },
+{ 0x0b504f30, 0xf137ca20, 0x10000000, 0xf137ca20, 0x0b504f30, 0xf9e08758, 0x00000000, 0x061f78a8 }
+};
+
+#define FIXED64_STAGE1 24
+static const int32_t _sbc_proto_8_f[40] = {
+0x02e5cd20, 0x22d0c200, 0x006bfe27, 0x07808930, 0x3f1c8800, 0xf8810d70, 0x002cfdc6, 0x055acf28,
+0x31f566c0, 0xebfe57e0, 0xff27c437, 0x001485cc, 0x041c6e58, 0x2a7cfa80, 0xe4c4a240, 0xfe359e4c,
+0x0048b1f8, 0x0686ce30, 0x38eec5c0, 0xf2a1b9f0, 0xffe8904a, 0x0095698a, 0x0824a480, 0x443b3c00,
+0xfd7badc8, 0x00d3e2d9, 0x00c183d2, 0x084e1950, 0x4810d800, 0x017f43fe, 0x01056dd8, 0x00e9cb9f,
+0x07d7d090, 0x4a708980, 0x0488fae8, 0x0113bd20, 0x0107b1a8, 0x069fb3c0, 0x4b3db200, 0x00763f48
+};
+
+#define FIXED64_STAGE2 7
+static const int32_t _anamatrix8_f[8] = {
+0x3b20d780, 0x187de2a0, 0x3ec52f80, 0x3536cc40, 0x238e7680, 0x0c7c5c20, 0x2d413cc0, 0x40000000
};

Index: sbc/sbcdec.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/sbc/sbcdec.c,v
retrieving revision 1.5
diff -u -r1.5 sbcdec.c
--- sbc/sbcdec.c 1 May 2005 16:36:44 -0000 1.5
+++ sbc/sbcdec.c 21 Aug 2005 18:26:32 -0000
@@ -40,7 +40,7 @@

#define BUF_SIZE 2048

-static void decode(char *filename, char *audiodevice)
+static void decode(char *filename, char *audiodevice, int tofile)
{
unsigned char buf[BUF_SIZE], *stream;
struct stat st;
@@ -82,7 +82,7 @@
pos = 0;
streamlen = st.st_size;

- ad = open(audiodevice, O_WRONLY, 0);
+ 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));
@@ -93,25 +93,25 @@

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_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_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;
+ 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) {
@@ -152,6 +152,7 @@
"\t-h, --help Display help\n"
"\t-d, --device <dsp> Sound device\n"
"\t-v, --verbose Verbose mode\n"
+ "\t-f, --file Decode to a file\n"
"\n");
}

@@ -159,15 +160,17 @@
{ "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;
- int i, opt, verbose = 0;
+ char *file = NULL;
+ int i, opt, verbose = 0, tofile = 0;

- while ((opt = getopt_long(argc, argv, "+hd:v", main_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+hd:vf:", main_options, NULL)) != -1) {
switch(opt) {
case 'h':
usage();
@@ -180,6 +183,10 @@
case 'v':
verbose = 1;
break;
+ case 'f' :
+ file = strdup(optarg);
+ tofile = 1;
+ break;

default:
exit(1);
@@ -196,7 +203,7 @@
}

for (i = 0; i < argc; i++)
- decode(argv[i], device ? device : "/dev/dsp");
+ decode(argv[i], device ? device : file ? file : "/dev/dsp", tofile);

if (device)
free(device);