summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Dalleau <frederic.dalleau@linux.intel.com>2013-04-08 15:24:11 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2013-04-15 11:03:40 +0300
commite9bc3e0083a2e8a23d8191b66b7e371af936040d (patch)
treed62cb29f4f22d62ac3205e20172025ca469020f5
parentc115634f9e4a586f8189b2eba499097c331a1cf6 (diff)
downloadsbc-e9bc3e0083a2e8a23d8191b66b7e371af936040d.tar.gz
sbc: Fix input reordering for 15 blocks case
SBC analysis handles 8 samples at a time. The optimisation requires 8 samples forming an "odd" block, followed by 8 samples, forming an "even" block. Until now SBC was used for encoding 4, 8, 12, or 16 blocks in a frame. Reordering took a frame and for each 16 samples (ie 2 blocks) it produced one "odd" block and one "even" block. A mSBC frame encodes 15 blocks of 8 samples. 14 blocks are processed as before, two at a time. If 8 samples are remaining, it will form the first half of two blocks (a bit of an "odd" block, and a bit of an "even" block). When processing the next frame, we detect eight samples were missing at previous iteration and the two block can be finished. This reordering is possible because only one sample is moved (x[-7]) AND the first coefficient in the coef table is 0. Thus x[0] doesn't need to be set and 0 can be used in calculation instead. Note that x[-7] is not used in analysis for this block. see: analysis_consts_fixed8_simd_odd. To detect that two blocks are not completed, the number of processed samples can be used. This value is stored in position. position starts at SBC_X_BUFFER_SIZE-72 and is decremented by 16 as long as two blocks can be formed. If only 8 samples are remaining in input, then position is decremented by 8 *arbitrarly*, thus indicating that some samples are pending. During next frame reordering, position will be decremented by 8 again, back to a 16 multiple. This logic works for SBC_X_BUFFER_SIZE-72 multiple of 16 and bigger than 8*2*15+72=312 and less than 8*3*15+72=432. The current value of 328 matches this constraint and X buffer is shifted every two frames (30 blocks) in mSBC. This way, we don't need to care about x[-7] when shifting, we also know that it won't be before X.
-rw-r--r--sbc/sbc_primitives.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index bf9937d..ff343cf 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -6,6 +6,7 @@
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
+ * Copyright (C) 2012-2013 Intel Corporation
*
*
* This library is free software; you can redistribute it and/or
@@ -313,8 +314,37 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
#define PCM(i) (big_endian ? \
unaligned16_be(pcm + (i) * 2) : unaligned16_le(pcm + (i) * 2))
+ if (position % 16 == 8) {
+ position -= 8;
+ nsamples -= 8;
+ if (nchannels > 0) {
+ int16_t *x = &X[0][position];
+ x[0] = PCM(0 + (15-8) * nchannels);
+ x[2] = PCM(0 + (14-8) * nchannels);
+ x[3] = PCM(0 + (8-8) * nchannels);
+ x[4] = PCM(0 + (13-8) * nchannels);
+ x[5] = PCM(0 + (9-8) * nchannels);
+ x[6] = PCM(0 + (12-8) * nchannels);
+ x[7] = PCM(0 + (10-8) * nchannels);
+ x[8] = PCM(0 + (11-8) * nchannels);
+ }
+ if (nchannels > 1) {
+ int16_t *x = &X[1][position];
+ x[0] = PCM(1 + (15-8) * nchannels);
+ x[2] = PCM(1 + (14-8) * nchannels);
+ x[3] = PCM(1 + (8-8) * nchannels);
+ x[4] = PCM(1 + (13-8) * nchannels);
+ x[5] = PCM(1 + (9-8) * nchannels);
+ x[6] = PCM(1 + (12-8) * nchannels);
+ x[7] = PCM(1 + (10-8) * nchannels);
+ x[8] = PCM(1 + (11-8) * nchannels);
+ }
+
+ pcm += 16 * nchannels;
+ }
+
/* copy/permutate audio samples */
- while ((nsamples -= 16) >= 0) {
+ while (nsamples >= 16) {
position -= 16;
if (nchannels > 0) {
int16_t *x = &X[0][position];
@@ -355,6 +385,33 @@ static SBC_ALWAYS_INLINE int sbc_encoder_process_input_s8_internal(
x[15] = PCM(1 + 2 * nchannels);
}
pcm += 32 * nchannels;
+ nsamples -= 16;
+ }
+
+ if (nsamples == 8) {
+ position -= 8;
+ if (nchannels > 0) {
+ int16_t *x = &X[0][position];
+ x[-7] = PCM(0 + 7 * nchannels);
+ x[1] = PCM(0 + 3 * nchannels);
+ x[2] = PCM(0 + 6 * nchannels);
+ x[3] = PCM(0 + 0 * nchannels);
+ x[4] = PCM(0 + 5 * nchannels);
+ x[5] = PCM(0 + 1 * nchannels);
+ x[6] = PCM(0 + 4 * nchannels);
+ x[7] = PCM(0 + 2 * nchannels);
+ }
+ if (nchannels > 1) {
+ int16_t *x = &X[1][position];
+ x[-7] = PCM(1 + 7 * nchannels);
+ x[1] = PCM(1 + 3 * nchannels);
+ x[2] = PCM(1 + 6 * nchannels);
+ x[3] = PCM(1 + 0 * nchannels);
+ x[4] = PCM(1 + 5 * nchannels);
+ x[5] = PCM(1 + 1 * nchannels);
+ x[6] = PCM(1 + 4 * nchannels);
+ x[7] = PCM(1 + 2 * nchannels);
+ }
}
#undef PCM