[PATCH v9 09/16] sbc: Fix input reordering for 15 blocks case

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
---
 sbc/sbc_primitives.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

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@xxxxxxxxxxxx>
  *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@xxxxxxxxxxx>
  *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xxxxxxxxxxxx>
+ *  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
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux