19cab9fdeSChristos Margiolis /*-
29cab9fdeSChristos Margiolis * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au>
39cab9fdeSChristos Margiolis *
49cab9fdeSChristos Margiolis * This software is dedicated to the memory of -
59cab9fdeSChristos Margiolis * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
69cab9fdeSChristos Margiolis *
79cab9fdeSChristos Margiolis * Barry was a man who loved his music.
89cab9fdeSChristos Margiolis *
99cab9fdeSChristos Margiolis * Redistribution and use in source and binary forms, with or without
109cab9fdeSChristos Margiolis * modification, are permitted provided that the following conditions
119cab9fdeSChristos Margiolis * are met:
129cab9fdeSChristos Margiolis * 1. Redistributions of source code must retain the above copyright
139cab9fdeSChristos Margiolis * notice, this list of conditions and the following disclaimer.
149cab9fdeSChristos Margiolis * 2. Redistributions in binary form must reproduce the above copyright
159cab9fdeSChristos Margiolis * notice, this list of conditions and the following disclaimer in the
169cab9fdeSChristos Margiolis * documentation and/or other materials provided with the distribution.
179cab9fdeSChristos Margiolis *
189cab9fdeSChristos Margiolis * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
199cab9fdeSChristos Margiolis * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
209cab9fdeSChristos Margiolis * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
219cab9fdeSChristos Margiolis * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
229cab9fdeSChristos Margiolis * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
239cab9fdeSChristos Margiolis * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
249cab9fdeSChristos Margiolis * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
259cab9fdeSChristos Margiolis * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
269cab9fdeSChristos Margiolis * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
279cab9fdeSChristos Margiolis * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
289cab9fdeSChristos Margiolis * POSSIBILITY OF SUCH DAMAGE.
299cab9fdeSChristos Margiolis */
309cab9fdeSChristos Margiolis
319cab9fdeSChristos Margiolis #include <sys/cdefs.h>
329cab9fdeSChristos Margiolis #include <sys/types.h>
339cab9fdeSChristos Margiolis #include <sys/param.h>
349cab9fdeSChristos Margiolis #include <sys/endian.h>
359cab9fdeSChristos Margiolis #include <sys/uio.h>
369cab9fdeSChristos Margiolis
379cab9fdeSChristos Margiolis #include <stdio.h>
389cab9fdeSChristos Margiolis #include <errno.h>
399cab9fdeSChristos Margiolis #include <stdbool.h>
409cab9fdeSChristos Margiolis #include <stdlib.h>
419cab9fdeSChristos Margiolis #include <string.h>
429cab9fdeSChristos Margiolis #include <unistd.h>
439cab9fdeSChristos Margiolis #include <math.h>
449cab9fdeSChristos Margiolis
459cab9fdeSChristos Margiolis #include "sbc_coeffs.h"
469cab9fdeSChristos Margiolis #include "bt.h"
479cab9fdeSChristos Margiolis
489cab9fdeSChristos Margiolis #define SYNCWORD 0x9c
499cab9fdeSChristos Margiolis #define ABS(x) (((x) < 0) ? -(x) : (x))
509cab9fdeSChristos Margiolis #define BIT30 (1U << 30)
519cab9fdeSChristos Margiolis #define BM(x) ((1LL << (x)) - 1LL)
529cab9fdeSChristos Margiolis
539cab9fdeSChristos Margiolis /* Loudness offset allocations. */
549cab9fdeSChristos Margiolis static const int loudnessoffset8[4][8] = {
559cab9fdeSChristos Margiolis {-2, 0, 0, 0, 0, 0, 0, 1},
569cab9fdeSChristos Margiolis {-3, 0, 0, 0, 0, 0, 1, 2},
579cab9fdeSChristos Margiolis {-4, 0, 0, 0, 0, 0, 1, 2},
589cab9fdeSChristos Margiolis {-4, 0, 0, 0, 0, 0, 1, 2},
599cab9fdeSChristos Margiolis };
609cab9fdeSChristos Margiolis
619cab9fdeSChristos Margiolis static const int loudnessoffset4[4][4] = {
629cab9fdeSChristos Margiolis {-1, 0, 0, 0},
639cab9fdeSChristos Margiolis {-2, 0, 0, 1},
649cab9fdeSChristos Margiolis {-2, 0, 0, 1},
659cab9fdeSChristos Margiolis {-2, 0, 0, 1},
669cab9fdeSChristos Margiolis };
679cab9fdeSChristos Margiolis
689cab9fdeSChristos Margiolis static uint8_t
calc_scalefactors_joint(struct sbc_encode * sbc)699cab9fdeSChristos Margiolis calc_scalefactors_joint(struct sbc_encode *sbc)
709cab9fdeSChristos Margiolis {
719cab9fdeSChristos Margiolis float sb_j[16][2];
729cab9fdeSChristos Margiolis uint32_t x;
739cab9fdeSChristos Margiolis uint32_t y;
749cab9fdeSChristos Margiolis uint8_t block;
759cab9fdeSChristos Margiolis uint8_t joint;
769cab9fdeSChristos Margiolis uint8_t sb;
779cab9fdeSChristos Margiolis uint8_t lz;
789cab9fdeSChristos Margiolis
799cab9fdeSChristos Margiolis joint = 0;
809cab9fdeSChristos Margiolis for (sb = 0; sb != sbc->bands - 1; sb++) {
819cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
829cab9fdeSChristos Margiolis sb_j[block][0] = (sbc->samples[block][0][sb] +
839cab9fdeSChristos Margiolis sbc->samples[block][1][sb]) / 2.0f;
849cab9fdeSChristos Margiolis sb_j[block][1] = (sbc->samples[block][0][sb] -
859cab9fdeSChristos Margiolis sbc->samples[block][1][sb]) / 2.0f;
869cab9fdeSChristos Margiolis }
879cab9fdeSChristos Margiolis
889cab9fdeSChristos Margiolis x = 1 << 15;
899cab9fdeSChristos Margiolis y = 1 << 15;
909cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
919cab9fdeSChristos Margiolis x |= (uint32_t)ABS(sb_j[block][0]);
929cab9fdeSChristos Margiolis y |= (uint32_t)ABS(sb_j[block][1]);
939cab9fdeSChristos Margiolis }
949cab9fdeSChristos Margiolis
959cab9fdeSChristos Margiolis lz = 1;
969cab9fdeSChristos Margiolis while (!(x & BIT30)) {
979cab9fdeSChristos Margiolis lz++;
989cab9fdeSChristos Margiolis x <<= 1;
999cab9fdeSChristos Margiolis }
1009cab9fdeSChristos Margiolis x = 16 - lz;
1019cab9fdeSChristos Margiolis
1029cab9fdeSChristos Margiolis lz = 1;
1039cab9fdeSChristos Margiolis while (!(y & BIT30)) {
1049cab9fdeSChristos Margiolis lz++;
1059cab9fdeSChristos Margiolis y <<= 1;
1069cab9fdeSChristos Margiolis }
1079cab9fdeSChristos Margiolis y = 16 - lz;
1089cab9fdeSChristos Margiolis
1099cab9fdeSChristos Margiolis if ((sbc->scalefactor[0][sb] + sbc->scalefactor[1][sb]) > x + y) {
1109cab9fdeSChristos Margiolis joint |= 1 << (sbc->bands - sb - 1);
1119cab9fdeSChristos Margiolis sbc->scalefactor[0][sb] = x;
1129cab9fdeSChristos Margiolis sbc->scalefactor[1][sb] = y;
1139cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
1149cab9fdeSChristos Margiolis sbc->samples[block][0][sb] = sb_j[block][0];
1159cab9fdeSChristos Margiolis sbc->samples[block][1][sb] = sb_j[block][1];
1169cab9fdeSChristos Margiolis }
1179cab9fdeSChristos Margiolis }
1189cab9fdeSChristos Margiolis }
1199cab9fdeSChristos Margiolis return (joint);
1209cab9fdeSChristos Margiolis }
1219cab9fdeSChristos Margiolis
1229cab9fdeSChristos Margiolis static void
calc_scalefactors(struct sbc_encode * sbc)1239cab9fdeSChristos Margiolis calc_scalefactors(struct sbc_encode *sbc)
1249cab9fdeSChristos Margiolis {
1259cab9fdeSChristos Margiolis uint8_t block;
1269cab9fdeSChristos Margiolis uint8_t ch;
1279cab9fdeSChristos Margiolis uint8_t sb;
1289cab9fdeSChristos Margiolis
1299cab9fdeSChristos Margiolis for (ch = 0; ch != sbc->channels; ch++) {
1309cab9fdeSChristos Margiolis for (sb = 0; sb != sbc->bands; sb++) {
1319cab9fdeSChristos Margiolis uint32_t x = 1 << 15;
1329cab9fdeSChristos Margiolis uint8_t lx = 1;
1339cab9fdeSChristos Margiolis
1349cab9fdeSChristos Margiolis for (block = 0; block != sbc->blocks; block++)
1359cab9fdeSChristos Margiolis x |= (uint32_t)ABS(sbc->samples[block][ch][sb]);
1369cab9fdeSChristos Margiolis
1379cab9fdeSChristos Margiolis while (!(x & BIT30)) {
1389cab9fdeSChristos Margiolis lx++;
1399cab9fdeSChristos Margiolis x <<= 1;
1409cab9fdeSChristos Margiolis }
1419cab9fdeSChristos Margiolis sbc->scalefactor[ch][sb] = 16 - lx;
1429cab9fdeSChristos Margiolis }
1439cab9fdeSChristos Margiolis }
1449cab9fdeSChristos Margiolis }
1459cab9fdeSChristos Margiolis
1469cab9fdeSChristos Margiolis static void
calc_bitneed(struct bt_config * cfg)1479cab9fdeSChristos Margiolis calc_bitneed(struct bt_config *cfg)
1489cab9fdeSChristos Margiolis {
1499cab9fdeSChristos Margiolis struct sbc_encode *sbc = cfg->handle.sbc_enc;
1509cab9fdeSChristos Margiolis int32_t bitneed[2][8];
1519cab9fdeSChristos Margiolis int32_t max_bitneed, bitcount;
1529cab9fdeSChristos Margiolis int32_t slicecount, bitslice;
1539cab9fdeSChristos Margiolis int32_t loudness;
1549cab9fdeSChristos Margiolis int ch, sb, start_chan = 0;
1559cab9fdeSChristos Margiolis
1569cab9fdeSChristos Margiolis if (cfg->chmode == MODE_DUAL)
1579cab9fdeSChristos Margiolis sbc->channels = 1;
1589cab9fdeSChristos Margiolis
1599cab9fdeSChristos Margiolis next_chan:
1609cab9fdeSChristos Margiolis max_bitneed = 0;
1619cab9fdeSChristos Margiolis bitcount = 0;
1629cab9fdeSChristos Margiolis slicecount = 0;
1639cab9fdeSChristos Margiolis
1649cab9fdeSChristos Margiolis if (cfg->allocm == ALLOC_SNR) {
1659cab9fdeSChristos Margiolis for (ch = start_chan; ch < sbc->channels; ch++) {
1669cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
1679cab9fdeSChristos Margiolis bitneed[ch][sb] = sbc->scalefactor[ch][sb];
1689cab9fdeSChristos Margiolis
1699cab9fdeSChristos Margiolis if (bitneed[ch][sb] > max_bitneed)
1709cab9fdeSChristos Margiolis max_bitneed = bitneed[ch][sb];
1719cab9fdeSChristos Margiolis }
1729cab9fdeSChristos Margiolis }
1739cab9fdeSChristos Margiolis } else {
1749cab9fdeSChristos Margiolis for (ch = start_chan; ch < sbc->channels; ch++) {
1759cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
1769cab9fdeSChristos Margiolis if (sbc->scalefactor[ch][sb] == 0) {
1779cab9fdeSChristos Margiolis bitneed[ch][sb] = -5;
1789cab9fdeSChristos Margiolis } else {
1799cab9fdeSChristos Margiolis if (sbc->bands == 8) {
1809cab9fdeSChristos Margiolis loudness = sbc->scalefactor[ch][sb] -
1819cab9fdeSChristos Margiolis loudnessoffset8[cfg->freq][sb];
1829cab9fdeSChristos Margiolis } else {
1839cab9fdeSChristos Margiolis loudness = sbc->scalefactor[ch][sb] -
1849cab9fdeSChristos Margiolis loudnessoffset4[cfg->freq][sb];
1859cab9fdeSChristos Margiolis }
1869cab9fdeSChristos Margiolis if (loudness > 0)
1879cab9fdeSChristos Margiolis bitneed[ch][sb] = loudness / 2;
1889cab9fdeSChristos Margiolis else
1899cab9fdeSChristos Margiolis bitneed[ch][sb] = loudness;
1909cab9fdeSChristos Margiolis }
1919cab9fdeSChristos Margiolis if (bitneed[ch][sb] > max_bitneed)
1929cab9fdeSChristos Margiolis max_bitneed = bitneed[ch][sb];
1939cab9fdeSChristos Margiolis }
1949cab9fdeSChristos Margiolis }
1959cab9fdeSChristos Margiolis }
1969cab9fdeSChristos Margiolis
1979cab9fdeSChristos Margiolis slicecount = bitcount = 0;
1989cab9fdeSChristos Margiolis bitslice = max_bitneed + 1;
1999cab9fdeSChristos Margiolis do {
2009cab9fdeSChristos Margiolis bitslice--;
2019cab9fdeSChristos Margiolis bitcount += slicecount;
2029cab9fdeSChristos Margiolis slicecount = 0;
2039cab9fdeSChristos Margiolis for (ch = start_chan; ch < sbc->channels; ch++) {
2049cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
2059cab9fdeSChristos Margiolis if ((bitneed[ch][sb] > bitslice + 1) &&
2069cab9fdeSChristos Margiolis (bitneed[ch][sb] < bitslice + 16))
2079cab9fdeSChristos Margiolis slicecount++;
2089cab9fdeSChristos Margiolis else if (bitneed[ch][sb] == bitslice + 1)
2099cab9fdeSChristos Margiolis slicecount += 2;
2109cab9fdeSChristos Margiolis }
2119cab9fdeSChristos Margiolis }
2129cab9fdeSChristos Margiolis } while (bitcount + slicecount < cfg->bitpool);
2139cab9fdeSChristos Margiolis
2149cab9fdeSChristos Margiolis /* check if exactly one more fits */
2159cab9fdeSChristos Margiolis if (bitcount + slicecount == cfg->bitpool) {
2169cab9fdeSChristos Margiolis bitcount += slicecount;
2179cab9fdeSChristos Margiolis bitslice--;
2189cab9fdeSChristos Margiolis }
2199cab9fdeSChristos Margiolis for (ch = start_chan; ch < sbc->channels; ch++) {
2209cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
2219cab9fdeSChristos Margiolis if (bitneed[ch][sb] < bitslice + 2) {
2229cab9fdeSChristos Margiolis sbc->bits[ch][sb] = 0;
2239cab9fdeSChristos Margiolis } else {
2249cab9fdeSChristos Margiolis sbc->bits[ch][sb] = bitneed[ch][sb] - bitslice;
2259cab9fdeSChristos Margiolis if (sbc->bits[ch][sb] > 16)
2269cab9fdeSChristos Margiolis sbc->bits[ch][sb] = 16;
2279cab9fdeSChristos Margiolis }
2289cab9fdeSChristos Margiolis }
2299cab9fdeSChristos Margiolis }
2309cab9fdeSChristos Margiolis
2319cab9fdeSChristos Margiolis if (cfg->chmode == MODE_DUAL)
2329cab9fdeSChristos Margiolis ch = start_chan;
2339cab9fdeSChristos Margiolis else
2349cab9fdeSChristos Margiolis ch = 0;
2359cab9fdeSChristos Margiolis sb = 0;
2369cab9fdeSChristos Margiolis while (bitcount < cfg->bitpool && sb < sbc->bands) {
2379cab9fdeSChristos Margiolis if ((sbc->bits[ch][sb] >= 2) && (sbc->bits[ch][sb] < 16)) {
2389cab9fdeSChristos Margiolis sbc->bits[ch][sb]++;
2399cab9fdeSChristos Margiolis bitcount++;
2409cab9fdeSChristos Margiolis } else if ((bitneed[ch][sb] == bitslice + 1) &&
2419cab9fdeSChristos Margiolis (cfg->bitpool > bitcount + 1)) {
2429cab9fdeSChristos Margiolis sbc->bits[ch][sb] = 2;
2439cab9fdeSChristos Margiolis bitcount += 2;
2449cab9fdeSChristos Margiolis }
2459cab9fdeSChristos Margiolis if (sbc->channels == 1 || start_chan == 1)
2469cab9fdeSChristos Margiolis sb++;
2479cab9fdeSChristos Margiolis else if (ch == 1) {
2489cab9fdeSChristos Margiolis ch = 0;
2499cab9fdeSChristos Margiolis sb++;
2509cab9fdeSChristos Margiolis } else
2519cab9fdeSChristos Margiolis ch = 1;
2529cab9fdeSChristos Margiolis }
2539cab9fdeSChristos Margiolis
2549cab9fdeSChristos Margiolis if (cfg->chmode == MODE_DUAL)
2559cab9fdeSChristos Margiolis ch = start_chan;
2569cab9fdeSChristos Margiolis else
2579cab9fdeSChristos Margiolis ch = 0;
2589cab9fdeSChristos Margiolis sb = 0;
2599cab9fdeSChristos Margiolis while (bitcount < cfg->bitpool && sb < sbc->bands) {
2609cab9fdeSChristos Margiolis if (sbc->bits[ch][sb] < 16) {
2619cab9fdeSChristos Margiolis sbc->bits[ch][sb]++;
2629cab9fdeSChristos Margiolis bitcount++;
2639cab9fdeSChristos Margiolis }
2649cab9fdeSChristos Margiolis if (sbc->channels == 1 || start_chan == 1)
2659cab9fdeSChristos Margiolis sb++;
2669cab9fdeSChristos Margiolis else if (ch == 1) {
2679cab9fdeSChristos Margiolis ch = 0;
2689cab9fdeSChristos Margiolis sb++;
2699cab9fdeSChristos Margiolis } else
2709cab9fdeSChristos Margiolis ch = 1;
2719cab9fdeSChristos Margiolis }
2729cab9fdeSChristos Margiolis
2739cab9fdeSChristos Margiolis if (cfg->chmode == MODE_DUAL && start_chan == 0) {
2749cab9fdeSChristos Margiolis start_chan = 1;
2759cab9fdeSChristos Margiolis sbc->channels = 2;
2769cab9fdeSChristos Margiolis goto next_chan;
2779cab9fdeSChristos Margiolis }
2789cab9fdeSChristos Margiolis }
2799cab9fdeSChristos Margiolis
2809cab9fdeSChristos Margiolis static void
sbc_store_bits_crc(struct sbc_encode * sbc,uint32_t numbits,uint32_t value)2819cab9fdeSChristos Margiolis sbc_store_bits_crc(struct sbc_encode *sbc, uint32_t numbits, uint32_t value)
2829cab9fdeSChristos Margiolis {
2839cab9fdeSChristos Margiolis uint32_t off = sbc->bitoffset;
2849cab9fdeSChristos Margiolis
2859cab9fdeSChristos Margiolis while (numbits-- && off != sbc->maxoffset) {
2869cab9fdeSChristos Margiolis if (value & (1 << numbits)) {
2879cab9fdeSChristos Margiolis sbc->data[off / 8] |= 1 << ((7 - off) & 7);
2889cab9fdeSChristos Margiolis sbc->crc ^= 0x80;
2899cab9fdeSChristos Margiolis }
2909cab9fdeSChristos Margiolis sbc->crc *= 2;
2919cab9fdeSChristos Margiolis if (sbc->crc & 0x100)
2929cab9fdeSChristos Margiolis sbc->crc ^= 0x11d; /* CRC-8 polynomial */
2939cab9fdeSChristos Margiolis
2949cab9fdeSChristos Margiolis off++;
2959cab9fdeSChristos Margiolis }
2969cab9fdeSChristos Margiolis sbc->bitoffset = off;
2979cab9fdeSChristos Margiolis }
2989cab9fdeSChristos Margiolis
2999cab9fdeSChristos Margiolis static int
sbc_encode(struct bt_config * cfg)3009cab9fdeSChristos Margiolis sbc_encode(struct bt_config *cfg)
3019cab9fdeSChristos Margiolis {
3029cab9fdeSChristos Margiolis struct sbc_encode *sbc = cfg->handle.sbc_enc;
3039cab9fdeSChristos Margiolis const int16_t *input = sbc->music_data;
3049cab9fdeSChristos Margiolis float delta[2][8];
3059cab9fdeSChristos Margiolis float levels[2][8];
3069cab9fdeSChristos Margiolis float mask[2][8];
3079cab9fdeSChristos Margiolis float S;
3089cab9fdeSChristos Margiolis float *X;
3099cab9fdeSChristos Margiolis float Z[80];
3109cab9fdeSChristos Margiolis float Y[80];
3119cab9fdeSChristos Margiolis float audioout;
3129cab9fdeSChristos Margiolis int16_t left[8];
3139cab9fdeSChristos Margiolis int16_t right[8];
3149cab9fdeSChristos Margiolis int16_t *data;
3159cab9fdeSChristos Margiolis int numsamples;
3169cab9fdeSChristos Margiolis int i;
3179cab9fdeSChristos Margiolis int k;
3189cab9fdeSChristos Margiolis int block;
3199cab9fdeSChristos Margiolis int chan;
3209cab9fdeSChristos Margiolis int sb;
3219cab9fdeSChristos Margiolis
3229cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
3239cab9fdeSChristos Margiolis
3249cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands; i++) {
3259cab9fdeSChristos Margiolis left[i] = *input++;
3269cab9fdeSChristos Margiolis if (sbc->channels == 2)
3279cab9fdeSChristos Margiolis right[i] = *input++;
3289cab9fdeSChristos Margiolis }
3299cab9fdeSChristos Margiolis
3309cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
3319cab9fdeSChristos Margiolis
3329cab9fdeSChristos Margiolis /* select right or left channel */
3339cab9fdeSChristos Margiolis if (chan == 0) {
3349cab9fdeSChristos Margiolis X = sbc->left;
3359cab9fdeSChristos Margiolis data = left;
3369cab9fdeSChristos Margiolis } else {
3379cab9fdeSChristos Margiolis X = sbc->right;
3389cab9fdeSChristos Margiolis data = right;
3399cab9fdeSChristos Margiolis }
3409cab9fdeSChristos Margiolis
3419cab9fdeSChristos Margiolis /* shift up old data */
3429cab9fdeSChristos Margiolis for (i = (sbc->bands * 10) - 1; i > sbc->bands - 1; i--)
3439cab9fdeSChristos Margiolis X[i] = X[i - sbc->bands];
3449cab9fdeSChristos Margiolis k = 0;
3459cab9fdeSChristos Margiolis for (i = sbc->bands - 1; i >= 0; i--)
3469cab9fdeSChristos Margiolis X[i] = data[k++];
3479cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands * 10; i++) {
3489cab9fdeSChristos Margiolis if (sbc->bands == 8)
3499cab9fdeSChristos Margiolis Z[i] = sbc_coeffs8[i] * X[i];
3509cab9fdeSChristos Margiolis else
3519cab9fdeSChristos Margiolis Z[i] = sbc_coeffs4[i] * X[i];
3529cab9fdeSChristos Margiolis }
3539cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands * 2; i++) {
3549cab9fdeSChristos Margiolis Y[i] = 0;
3559cab9fdeSChristos Margiolis for (k = 0; k < 5; k++)
3569cab9fdeSChristos Margiolis Y[i] += Z[i + k * sbc->bands * 2];
3579cab9fdeSChristos Margiolis }
3589cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands; i++) {
3599cab9fdeSChristos Margiolis S = 0;
3609cab9fdeSChristos Margiolis for (k = 0; k < sbc->bands * 2; k++) {
3619cab9fdeSChristos Margiolis if (sbc->bands == 8) {
3629cab9fdeSChristos Margiolis S += cosdata8[i][k] * Y[k];
3639cab9fdeSChristos Margiolis } else {
3649cab9fdeSChristos Margiolis S += cosdata4[i][k] * Y[k];
3659cab9fdeSChristos Margiolis }
3669cab9fdeSChristos Margiolis }
3679cab9fdeSChristos Margiolis sbc->samples[block][chan][i] = S * (1 << 15);
3689cab9fdeSChristos Margiolis }
3699cab9fdeSChristos Margiolis }
3709cab9fdeSChristos Margiolis }
3719cab9fdeSChristos Margiolis
3729cab9fdeSChristos Margiolis calc_scalefactors(sbc);
3739cab9fdeSChristos Margiolis
3749cab9fdeSChristos Margiolis if (cfg->chmode == MODE_JOINT)
3759cab9fdeSChristos Margiolis sbc->join = calc_scalefactors_joint(sbc);
3769cab9fdeSChristos Margiolis else
3779cab9fdeSChristos Margiolis sbc->join = 0;
3789cab9fdeSChristos Margiolis
3799cab9fdeSChristos Margiolis calc_bitneed(cfg);
3809cab9fdeSChristos Margiolis
3819cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
3829cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
3839cab9fdeSChristos Margiolis if (sbc->bits[chan][sb] == 0)
3849cab9fdeSChristos Margiolis continue;
3859cab9fdeSChristos Margiolis mask[chan][sb] = BM(sbc->bits[chan][sb]);
3869cab9fdeSChristos Margiolis levels[chan][sb] = mask[chan][sb] *
3879cab9fdeSChristos Margiolis (1LL << (15 - sbc->scalefactor[chan][sb]));
3889cab9fdeSChristos Margiolis delta[chan][sb] =
3899cab9fdeSChristos Margiolis (1LL << (sbc->scalefactor[chan][sb] + 16));
3909cab9fdeSChristos Margiolis }
3919cab9fdeSChristos Margiolis }
3929cab9fdeSChristos Margiolis
3939cab9fdeSChristos Margiolis numsamples = 0;
3949cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
3959cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
3969cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
3979cab9fdeSChristos Margiolis if (sbc->bits[chan][sb] == 0)
3989cab9fdeSChristos Margiolis continue;
3999cab9fdeSChristos Margiolis audioout = (levels[chan][sb] *
4009cab9fdeSChristos Margiolis (delta[chan][sb] + sbc->samples[block][chan][sb]));
4019cab9fdeSChristos Margiolis audioout /= (1LL << 32);
4029cab9fdeSChristos Margiolis
4039cab9fdeSChristos Margiolis audioout = roundf(audioout);
4049cab9fdeSChristos Margiolis
4059cab9fdeSChristos Margiolis /* range check */
4069cab9fdeSChristos Margiolis if (audioout > mask[chan][sb])
4079cab9fdeSChristos Margiolis audioout = mask[chan][sb];
4089cab9fdeSChristos Margiolis
4099cab9fdeSChristos Margiolis sbc->output[numsamples++] = audioout;
4109cab9fdeSChristos Margiolis }
4119cab9fdeSChristos Margiolis }
4129cab9fdeSChristos Margiolis }
4139cab9fdeSChristos Margiolis return (numsamples);
4149cab9fdeSChristos Margiolis }
4159cab9fdeSChristos Margiolis
4169cab9fdeSChristos Margiolis static void
sbc_decode(struct bt_config * cfg)4179cab9fdeSChristos Margiolis sbc_decode(struct bt_config *cfg)
4189cab9fdeSChristos Margiolis {
4199cab9fdeSChristos Margiolis struct sbc_encode *sbc = cfg->handle.sbc_enc;
4209cab9fdeSChristos Margiolis float delta[2][8];
4219cab9fdeSChristos Margiolis float levels[2][8];
4229cab9fdeSChristos Margiolis float audioout;
4239cab9fdeSChristos Margiolis float *X;
4249cab9fdeSChristos Margiolis float *V;
4259cab9fdeSChristos Margiolis float left[160];
4269cab9fdeSChristos Margiolis float right[160];
4279cab9fdeSChristos Margiolis float U[160];
4289cab9fdeSChristos Margiolis float W[160];
4299cab9fdeSChristos Margiolis float S[8];
4309cab9fdeSChristos Margiolis int position;
4319cab9fdeSChristos Margiolis int block;
4329cab9fdeSChristos Margiolis int chan;
4339cab9fdeSChristos Margiolis int sb;
4349cab9fdeSChristos Margiolis int i;
4359cab9fdeSChristos Margiolis int k;
4369cab9fdeSChristos Margiolis
4379cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
4389cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
4399cab9fdeSChristos Margiolis levels[chan][sb] = (1 << sbc->bits[chan][sb]) - 1;
4409cab9fdeSChristos Margiolis delta[chan][sb] = (1 << sbc->scalefactor[chan][sb]);
4419cab9fdeSChristos Margiolis }
4429cab9fdeSChristos Margiolis }
4439cab9fdeSChristos Margiolis
4449cab9fdeSChristos Margiolis i = 0;
4459cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
4469cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
4479cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
4489cab9fdeSChristos Margiolis if (sbc->bits[chan][sb] == 0) {
4499cab9fdeSChristos Margiolis audioout = 0;
4509cab9fdeSChristos Margiolis } else {
4519cab9fdeSChristos Margiolis audioout =
4529cab9fdeSChristos Margiolis ((((sbc->output[i] * 2.0f) + 1.0f) * delta[chan][sb]) /
4539cab9fdeSChristos Margiolis levels[chan][sb]) - delta[chan][sb];
4549cab9fdeSChristos Margiolis }
4559cab9fdeSChristos Margiolis sbc->output[i++] = audioout;
4569cab9fdeSChristos Margiolis }
4579cab9fdeSChristos Margiolis }
4589cab9fdeSChristos Margiolis }
4599cab9fdeSChristos Margiolis
4609cab9fdeSChristos Margiolis if (cfg->chmode == MODE_JOINT) {
4619cab9fdeSChristos Margiolis i = 0;
4629cab9fdeSChristos Margiolis while (i < (sbc->blocks * sbc->bands * sbc->channels)) {
4639cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
4649cab9fdeSChristos Margiolis if (sbc->join & (1 << (sbc->bands - sb - 1))) {
4659cab9fdeSChristos Margiolis audioout = sbc->output[i];
4669cab9fdeSChristos Margiolis sbc->output[i] = (2.0f * sbc->output[i]) +
4679cab9fdeSChristos Margiolis (2.0f * sbc->output[i + sbc->bands]);
4689cab9fdeSChristos Margiolis sbc->output[i + sbc->bands] =
4699cab9fdeSChristos Margiolis (2.0f * audioout) -
4709cab9fdeSChristos Margiolis (2.0f * sbc->output[i + sbc->bands]);
4719cab9fdeSChristos Margiolis sbc->output[i] /= 2.0f;
4729cab9fdeSChristos Margiolis sbc->output[i + sbc->bands] /= 2.0f;
4739cab9fdeSChristos Margiolis }
4749cab9fdeSChristos Margiolis i++;
4759cab9fdeSChristos Margiolis }
4769cab9fdeSChristos Margiolis i += sbc->bands;
4779cab9fdeSChristos Margiolis }
4789cab9fdeSChristos Margiolis }
4799cab9fdeSChristos Margiolis position = 0;
4809cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
4819cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
4829cab9fdeSChristos Margiolis /* select right or left channel */
4839cab9fdeSChristos Margiolis if (chan == 0) {
4849cab9fdeSChristos Margiolis X = left;
4859cab9fdeSChristos Margiolis V = sbc->left;
4869cab9fdeSChristos Margiolis } else {
4879cab9fdeSChristos Margiolis X = right;
4889cab9fdeSChristos Margiolis V = sbc->right;
4899cab9fdeSChristos Margiolis }
4909cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands; i++)
4919cab9fdeSChristos Margiolis S[i] = sbc->output[position++];
4929cab9fdeSChristos Margiolis
4939cab9fdeSChristos Margiolis for (i = (sbc->bands * 20) - 1; i >= (sbc->bands * 2); i--)
4949cab9fdeSChristos Margiolis V[i] = V[i - (sbc->bands * 2)];
4959cab9fdeSChristos Margiolis for (k = 0; k < sbc->bands * 2; k++) {
4969cab9fdeSChristos Margiolis float vk = 0;
4979cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands; i++) {
4989cab9fdeSChristos Margiolis if (sbc->bands == 8) {
4999cab9fdeSChristos Margiolis vk += cosdecdata8[i][k] * S[i];
5009cab9fdeSChristos Margiolis } else {
5019cab9fdeSChristos Margiolis vk += cosdecdata4[i][k] * S[i];
5029cab9fdeSChristos Margiolis }
5039cab9fdeSChristos Margiolis }
5049cab9fdeSChristos Margiolis V[k] = vk;
5059cab9fdeSChristos Margiolis }
5069cab9fdeSChristos Margiolis for (i = 0; i <= 4; i++) {
5079cab9fdeSChristos Margiolis for (k = 0; k < sbc->bands; k++) {
5089cab9fdeSChristos Margiolis U[(i * sbc->bands * 2) + k] =
5099cab9fdeSChristos Margiolis V[(i * sbc->bands * 4) + k];
5109cab9fdeSChristos Margiolis U[(i * sbc->bands
5119cab9fdeSChristos Margiolis * 2) + sbc->bands + k] =
5129cab9fdeSChristos Margiolis V[(i * sbc->bands * 4) +
5139cab9fdeSChristos Margiolis (sbc->bands * 3) + k];
5149cab9fdeSChristos Margiolis }
5159cab9fdeSChristos Margiolis }
5169cab9fdeSChristos Margiolis for (i = 0; i < sbc->bands * 10; i++) {
5179cab9fdeSChristos Margiolis if (sbc->bands == 4) {
5189cab9fdeSChristos Margiolis W[i] = U[i] * (sbc_coeffs4[i] * -4.0f);
5199cab9fdeSChristos Margiolis } else if (sbc->bands == 8) {
5209cab9fdeSChristos Margiolis W[i] = U[i] * (sbc_coeffs8[i] * -8.0f);
5219cab9fdeSChristos Margiolis } else {
5229cab9fdeSChristos Margiolis W[i] = 0;
5239cab9fdeSChristos Margiolis }
5249cab9fdeSChristos Margiolis }
5259cab9fdeSChristos Margiolis
5269cab9fdeSChristos Margiolis for (k = 0; k < sbc->bands; k++) {
5279cab9fdeSChristos Margiolis unsigned int offset = k + (block * sbc->bands);
5289cab9fdeSChristos Margiolis
5299cab9fdeSChristos Margiolis X[offset] = 0;
5309cab9fdeSChristos Margiolis for (i = 0; i < 10; i++) {
5319cab9fdeSChristos Margiolis X[offset] += W[k + (i * sbc->bands)];
5329cab9fdeSChristos Margiolis }
5339cab9fdeSChristos Margiolis
5349cab9fdeSChristos Margiolis if (X[offset] > 32767.0)
5359cab9fdeSChristos Margiolis X[offset] = 32767.0;
5369cab9fdeSChristos Margiolis else if (X[offset] < -32767.0)
5379cab9fdeSChristos Margiolis X[offset] = -32767.0;
5389cab9fdeSChristos Margiolis }
5399cab9fdeSChristos Margiolis }
5409cab9fdeSChristos Margiolis }
5419cab9fdeSChristos Margiolis
5429cab9fdeSChristos Margiolis for (i = 0, k = 0; k != (sbc->blocks * sbc->bands); k++) {
5439cab9fdeSChristos Margiolis sbc->music_data[i++] = left[k];
5449cab9fdeSChristos Margiolis if (sbc->channels == 2)
5459cab9fdeSChristos Margiolis sbc->music_data[i++] = right[k];
5469cab9fdeSChristos Margiolis }
5479cab9fdeSChristos Margiolis }
5489cab9fdeSChristos Margiolis
5499cab9fdeSChristos Margiolis size_t
sbc_encode_frame(struct bt_config * cfg)5509cab9fdeSChristos Margiolis sbc_encode_frame(struct bt_config *cfg)
5519cab9fdeSChristos Margiolis {
5529cab9fdeSChristos Margiolis struct sbc_encode *sbc = cfg->handle.sbc_enc;
5539cab9fdeSChristos Margiolis uint8_t config;
5549cab9fdeSChristos Margiolis uint8_t block;
5559cab9fdeSChristos Margiolis uint8_t chan;
5569cab9fdeSChristos Margiolis uint8_t sb;
5579cab9fdeSChristos Margiolis uint8_t j;
5589cab9fdeSChristos Margiolis uint8_t i;
5599cab9fdeSChristos Margiolis
5609cab9fdeSChristos Margiolis config = (cfg->freq << 6) | (cfg->blocks << 4) |
5619cab9fdeSChristos Margiolis (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
5629cab9fdeSChristos Margiolis
5639cab9fdeSChristos Margiolis sbc_encode(cfg);
5649cab9fdeSChristos Margiolis
5659cab9fdeSChristos Margiolis /* set initial CRC */
5669cab9fdeSChristos Margiolis sbc->crc = 0x5e;
5679cab9fdeSChristos Margiolis
5689cab9fdeSChristos Margiolis /* reset data position and size */
5699cab9fdeSChristos Margiolis sbc->bitoffset = 0;
5709cab9fdeSChristos Margiolis sbc->maxoffset = sizeof(sbc->data) * 8;
5719cab9fdeSChristos Margiolis
5729cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 8, SYNCWORD);
5739cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 8, config);
5749cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 8, cfg->bitpool);
5759cab9fdeSChristos Margiolis
5769cab9fdeSChristos Margiolis /* skip 8-bit CRC */
5779cab9fdeSChristos Margiolis sbc->bitoffset += 8;
5789cab9fdeSChristos Margiolis
5799cab9fdeSChristos Margiolis if (cfg->chmode == MODE_JOINT) {
5809cab9fdeSChristos Margiolis if (sbc->bands == 8)
5819cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 8, sbc->join);
5829cab9fdeSChristos Margiolis else if (sbc->bands == 4)
5839cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 4, sbc->join);
5849cab9fdeSChristos Margiolis }
5859cab9fdeSChristos Margiolis for (i = 0; i < sbc->channels; i++) {
5869cab9fdeSChristos Margiolis for (j = 0; j < sbc->bands; j++)
5879cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, 4, sbc->scalefactor[i][j]);
5889cab9fdeSChristos Margiolis }
5899cab9fdeSChristos Margiolis
5909cab9fdeSChristos Margiolis /* store 8-bit CRC */
5919cab9fdeSChristos Margiolis sbc->data[3] = (sbc->crc & 0xFF);
5929cab9fdeSChristos Margiolis
5939cab9fdeSChristos Margiolis i = 0;
5949cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
5959cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
5969cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
5979cab9fdeSChristos Margiolis if (sbc->bits[chan][sb] == 0)
5989cab9fdeSChristos Margiolis continue;
5999cab9fdeSChristos Margiolis
6009cab9fdeSChristos Margiolis sbc_store_bits_crc(sbc, sbc->bits[chan][sb], sbc->output[i++]);
6019cab9fdeSChristos Margiolis }
6029cab9fdeSChristos Margiolis }
6039cab9fdeSChristos Margiolis }
6049cab9fdeSChristos Margiolis return ((sbc->bitoffset + 7) / 8);
6059cab9fdeSChristos Margiolis }
6069cab9fdeSChristos Margiolis
6079cab9fdeSChristos Margiolis static uint32_t
sbc_load_bits_crc(struct sbc_encode * sbc,uint32_t numbits)6089cab9fdeSChristos Margiolis sbc_load_bits_crc(struct sbc_encode *sbc, uint32_t numbits)
6099cab9fdeSChristos Margiolis {
6109cab9fdeSChristos Margiolis uint32_t off = sbc->bitoffset;
6119cab9fdeSChristos Margiolis uint32_t value = 0;
6129cab9fdeSChristos Margiolis
6139cab9fdeSChristos Margiolis while (numbits-- && off != sbc->maxoffset) {
6149cab9fdeSChristos Margiolis if (sbc->rem_data_ptr[off / 8] & (1 << ((7 - off) & 7))) {
6159cab9fdeSChristos Margiolis value |= (1 << numbits);
6169cab9fdeSChristos Margiolis sbc->crc ^= 0x80;
6179cab9fdeSChristos Margiolis }
6189cab9fdeSChristos Margiolis sbc->crc *= 2;
6199cab9fdeSChristos Margiolis if (sbc->crc & 0x100)
6209cab9fdeSChristos Margiolis sbc->crc ^= 0x11d; /* CRC-8 polynomial */
6219cab9fdeSChristos Margiolis
6229cab9fdeSChristos Margiolis off++;
6239cab9fdeSChristos Margiolis }
6249cab9fdeSChristos Margiolis sbc->bitoffset = off;
6259cab9fdeSChristos Margiolis return (value);
6269cab9fdeSChristos Margiolis }
6279cab9fdeSChristos Margiolis
6289cab9fdeSChristos Margiolis size_t
sbc_decode_frame(struct bt_config * cfg,int bits)6299cab9fdeSChristos Margiolis sbc_decode_frame(struct bt_config *cfg, int bits)
6309cab9fdeSChristos Margiolis {
6319cab9fdeSChristos Margiolis struct sbc_encode *sbc = cfg->handle.sbc_enc;
6329cab9fdeSChristos Margiolis uint8_t config;
6339cab9fdeSChristos Margiolis uint8_t block;
6349cab9fdeSChristos Margiolis uint8_t chan;
6359cab9fdeSChristos Margiolis uint8_t sb;
6369cab9fdeSChristos Margiolis uint8_t j;
6379cab9fdeSChristos Margiolis uint8_t i;
6389cab9fdeSChristos Margiolis
6399cab9fdeSChristos Margiolis sbc->rem_off = 0;
6409cab9fdeSChristos Margiolis sbc->rem_len = 0;
6419cab9fdeSChristos Margiolis
6429cab9fdeSChristos Margiolis config = (cfg->freq << 6) | (cfg->blocks << 4) |
6439cab9fdeSChristos Margiolis (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands;
6449cab9fdeSChristos Margiolis
6459cab9fdeSChristos Margiolis /* set initial CRC */
6469cab9fdeSChristos Margiolis sbc->crc = 0x5e;
6479cab9fdeSChristos Margiolis
6489cab9fdeSChristos Margiolis /* reset data position and size */
6499cab9fdeSChristos Margiolis sbc->bitoffset = 0;
6509cab9fdeSChristos Margiolis sbc->maxoffset = bits;
6519cab9fdeSChristos Margiolis
6529cab9fdeSChristos Margiolis /* verify SBC header */
6539cab9fdeSChristos Margiolis if (sbc->maxoffset < (8 * 4))
6549cab9fdeSChristos Margiolis return (0);
6559cab9fdeSChristos Margiolis if (sbc_load_bits_crc(sbc, 8) != SYNCWORD)
6569cab9fdeSChristos Margiolis return (0);
6579cab9fdeSChristos Margiolis if (sbc_load_bits_crc(sbc, 8) != config)
6589cab9fdeSChristos Margiolis return (0);
6599cab9fdeSChristos Margiolis cfg->bitpool = sbc_load_bits_crc(sbc, 8);
6609cab9fdeSChristos Margiolis
6619cab9fdeSChristos Margiolis (void)sbc_load_bits_crc(sbc, 8);/* CRC */
6629cab9fdeSChristos Margiolis
6639cab9fdeSChristos Margiolis if (cfg->chmode == MODE_JOINT) {
6649cab9fdeSChristos Margiolis if (sbc->bands == 8)
6659cab9fdeSChristos Margiolis sbc->join = sbc_load_bits_crc(sbc, 8);
6669cab9fdeSChristos Margiolis else if (sbc->bands == 4)
6679cab9fdeSChristos Margiolis sbc->join = sbc_load_bits_crc(sbc, 4);
6689cab9fdeSChristos Margiolis else
6699cab9fdeSChristos Margiolis sbc->join = 0;
6709cab9fdeSChristos Margiolis } else {
6719cab9fdeSChristos Margiolis sbc->join = 0;
6729cab9fdeSChristos Margiolis }
6739cab9fdeSChristos Margiolis
6749cab9fdeSChristos Margiolis for (i = 0; i < sbc->channels; i++) {
6759cab9fdeSChristos Margiolis for (j = 0; j < sbc->bands; j++)
6769cab9fdeSChristos Margiolis sbc->scalefactor[i][j] = sbc_load_bits_crc(sbc, 4);
6779cab9fdeSChristos Margiolis }
6789cab9fdeSChristos Margiolis
6799cab9fdeSChristos Margiolis calc_bitneed(cfg);
6809cab9fdeSChristos Margiolis
6819cab9fdeSChristos Margiolis i = 0;
6829cab9fdeSChristos Margiolis for (block = 0; block < sbc->blocks; block++) {
6839cab9fdeSChristos Margiolis for (chan = 0; chan < sbc->channels; chan++) {
6849cab9fdeSChristos Margiolis for (sb = 0; sb < sbc->bands; sb++) {
6859cab9fdeSChristos Margiolis if (sbc->bits[chan][sb] == 0) {
6869cab9fdeSChristos Margiolis i++;
6879cab9fdeSChristos Margiolis continue;
6889cab9fdeSChristos Margiolis }
6899cab9fdeSChristos Margiolis sbc->output[i++] =
6909cab9fdeSChristos Margiolis sbc_load_bits_crc(sbc, sbc->bits[chan][sb]);
6919cab9fdeSChristos Margiolis }
6929cab9fdeSChristos Margiolis }
6939cab9fdeSChristos Margiolis }
6949cab9fdeSChristos Margiolis
6959cab9fdeSChristos Margiolis sbc_decode(cfg);
6969cab9fdeSChristos Margiolis
6979cab9fdeSChristos Margiolis sbc->rem_off = 0;
6989cab9fdeSChristos Margiolis sbc->rem_len = sbc->blocks * sbc->channels * sbc->bands;
6999cab9fdeSChristos Margiolis
7009cab9fdeSChristos Margiolis return ((sbc->bitoffset + 7) / 8);
7019cab9fdeSChristos Margiolis }
702