linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 00/16] mSBC investigations
@ 2013-03-29 15:58 Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 01/16] sbc: Add encoder_state to analysis functions Frédéric Dalleau
                   ` (15 more replies)
  0 siblings, 16 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Hi,

v8 fixes cosmetic issues in sbc_init_msbc, sbcenc and sbcdec.

v7 features bool instead of int for odd state. uint8_t instead of int for
increment. Little refactoring of sbcinfo and copyrights update for 2013. No
longer bumps version number.

v6 implements sbc_init_msbc(). The SBC_MSBC flag is removed from sbc.h and
replace by an internal flag in sbc_priv structure.
The decoder has been validated to mSBC packets sent by an iPhone.
The encoder couldn't be validated, but at least we know that libsbc encoded
packets can be decoded by libsbc.
I bumped version number to 1.1 to help compile time detection.

v5 shoudl fix the few remaining issues.  I could test neon and armv6
and raised verbosity of commit messages.

Regards,
Frederic


Frédéric Dalleau (16):
  sbc: Add encoder_state to analysis functions
  sbc: Break 4 blocks processing to variable steps
  sbc: Rename sbc_analyze_4b_xx to sbc_analyze_xx
  sbc: add odd member variable to sbc_encoder_state
  sbc: Add mmx primitive for 1b 8s analysis
  sbc: Add armv6 primitive for 1b 8s analysis
  sbc: Add iwmmxt primitive for 1b 8s encoding
  sbc: Add plain C primitive for 1b 8s analysis
  sbc: Use plain C primitive if doing msbc on neon
  sbc: Fix input reordering for 15 blocks case
  sbc: Add a private boolean flag to enable 15 block encoding
  sbc: Declare and implement sbc_init_msbc
  sbc: Add support for mSBC frame header
  sbc: Update sbcdec for msbc
  sbc: Update sbcenc for msbc
  sbc: Update sbcinfo for msbc

 sbc/sbc.c                   |  324 ++++++++++++++++++++++++++++---------------
 sbc/sbc.h                   |    1 +
 sbc/sbc.sym                 |    1 +
 sbc/sbc_primitives.c        |   98 ++++++++++++-
 sbc/sbc_primitives.h        |   13 +-
 sbc/sbc_primitives_armv6.c  |   27 +++-
 sbc/sbc_primitives_iwmmxt.c |   29 +++-
 sbc/sbc_primitives_mmx.c    |   29 +++-
 sbc/sbc_primitives_neon.c   |   13 +-
 src/sbcdec.c                |   23 ++-
 src/sbcenc.c                |  107 ++++++++------
 src/sbcinfo.c               |   54 ++++++--
 12 files changed, 515 insertions(+), 204 deletions(-)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v8 01/16] sbc: Add encoder_state to analysis functions
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 02/16] sbc: Break 4 blocks processing to variable steps Frédéric Dalleau
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Until now, SIMD analysis used to process 4 blocks of 8 samples at a time. This
was implemented using two constant tables: odd and even. This mean we can only
process 4, 8, 12, or 16 blocks par SBC packets.
mSBC requires 15 blocks, so to be able to analyse 1 block, it will be necessary
to know if we are processing an odd or even block. This will be done with a
new member to encoder_state.
---
 sbc/sbc.c                   |    4 ++--
 sbc/sbc_primitives.c        |    8 ++++----
 sbc/sbc_primitives.h        |    6 ++++--
 sbc/sbc_primitives_armv6.c  |    6 ++++--
 sbc/sbc_primitives_iwmmxt.c |    8 ++++----
 sbc/sbc_primitives_mmx.c    |    8 ++++----
 sbc/sbc_primitives_neon.c   |    8 ++++----
 7 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index f0c77c7..e51ed57 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -692,7 +692,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
 							frame->blocks * 4];
 			for (blk = 0; blk < frame->blocks; blk += 4) {
 				state->sbc_analyze_4b_4s(
-					x,
+					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
 					frame->sb_sample_f[blk][ch]);
@@ -707,7 +707,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
 							frame->blocks * 8];
 			for (blk = 0; blk < frame->blocks; blk += 4) {
 				state->sbc_analyze_4b_8s(
-					x,
+					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
 					frame->sb_sample_f[blk][ch]);
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index ad780d0..f8cc4b6 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -183,8 +183,8 @@ static inline void sbc_analyze_eight_simd(const int16_t *in, int32_t *out,
 			(SBC_COS_TABLE_FIXED8_SCALE - SCALE_OUT_BITS);
 }
 
-static inline void sbc_analyze_4b_4s_simd(int16_t *x,
-						int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_4s_simd(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_four_simd(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -196,8 +196,8 @@ static inline void sbc_analyze_4b_4s_simd(int16_t *x,
 	sbc_analyze_four_simd(x + 0, out, analysis_consts_fixed4_simd_even);
 }
 
-static inline void sbc_analyze_4b_8s_simd(int16_t *x,
-					  int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_eight_simd(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 17ad4f7..a7bbef1 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -41,10 +41,12 @@ struct sbc_encoder_state {
 	int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
 	/* Polyphase analysis filter for 4 subbands configuration,
 	 * it handles 4 blocks at once */
-	void (*sbc_analyze_4b_4s)(int16_t *x, int32_t *out, int out_stride);
+	void (*sbc_analyze_4b_4s)(struct sbc_encoder_state *state,
+			int16_t *x, int32_t *out, int out_stride);
 	/* Polyphase analysis filter for 8 subbands configuration,
 	 * it handles 4 blocks at once */
-	void (*sbc_analyze_4b_8s)(int16_t *x, int32_t *out, int out_stride);
+	void (*sbc_analyze_4b_8s)(struct sbc_encoder_state *state,
+			int16_t *x, int32_t *out, int out_stride);
 	/* Process input data (deinterleave, endian conversion, reordering),
 	 * depending on the number of subbands and input data byte order */
 	int (*sbc_enc_process_input_4s_le)(int position,
diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index b321272..6ad94c6 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -265,7 +265,8 @@ static void __attribute__((naked)) sbc_analyze_eight_armv6()
 	((void (*)(int16_t *, int32_t *, const FIXED_T*)) \
 		sbc_analyze_eight_armv6)((in), (out), (consts))
 
-static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
+static void sbc_analyze_4b_4s_armv6(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_four(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -277,7 +278,8 @@ static void sbc_analyze_4b_4s_armv6(int16_t *x, int32_t *out, int out_stride)
 	sbc_analyze_four(x + 0, out, analysis_consts_fixed4_simd_even);
 }
 
-static void sbc_analyze_4b_8s_armv6(int16_t *x, int32_t *out, int out_stride)
+static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_eight(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index e0bd060..39cc390 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -268,8 +268,8 @@ static inline void sbc_analyze_eight_iwmmxt(const int16_t *in, int32_t *out,
 		  "wcgr0", "memory");
 }
 
-static inline void sbc_analyze_4b_4s_iwmmxt(int16_t *x, int32_t *out,
-						int out_stride)
+static inline void sbc_analyze_4b_4s_iwmmxt(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_four_iwmmxt(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -281,8 +281,8 @@ static inline void sbc_analyze_4b_4s_iwmmxt(int16_t *x, int32_t *out,
 	sbc_analyze_four_iwmmxt(x + 0, out, analysis_consts_fixed4_simd_even);
 }
 
-static inline void sbc_analyze_4b_8s_iwmmxt(int16_t *x, int32_t *out,
-						int out_stride)
+static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_eight_iwmmxt(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index 27e9a56..cbacb4e 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -246,8 +246,8 @@ static inline void sbc_analyze_eight_mmx(const int16_t *in, int32_t *out,
 		: "cc", "memory");
 }
 
-static inline void sbc_analyze_4b_4s_mmx(int16_t *x, int32_t *out,
-						int out_stride)
+static inline void sbc_analyze_4b_4s_mmx(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_four_mmx(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -261,8 +261,8 @@ static inline void sbc_analyze_4b_4s_mmx(int16_t *x, int32_t *out,
 	__asm__ volatile ("emms\n");
 }
 
-static inline void sbc_analyze_4b_8s_mmx(int16_t *x, int32_t *out,
-						int out_stride)
+static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	sbc_analyze_eight_mmx(x + 24, out, analysis_consts_fixed8_simd_odd);
diff --git a/sbc/sbc_primitives_neon.c b/sbc/sbc_primitives_neon.c
index 5d4d0e3..aeca8df 100644
--- a/sbc/sbc_primitives_neon.c
+++ b/sbc/sbc_primitives_neon.c
@@ -211,8 +211,8 @@ static inline void _sbc_analyze_eight_neon(const int16_t *in, int32_t *out,
 			"d18", "d19");
 }
 
-static inline void sbc_analyze_4b_4s_neon(int16_t *x,
-						int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_4s_neon(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	_sbc_analyze_four_neon(x + 12, out, analysis_consts_fixed4_simd_odd);
@@ -224,8 +224,8 @@ static inline void sbc_analyze_4b_4s_neon(int16_t *x,
 	_sbc_analyze_four_neon(x + 0, out, analysis_consts_fixed4_simd_even);
 }
 
-static inline void sbc_analyze_4b_8s_neon(int16_t *x,
-						int32_t *out, int out_stride)
+static inline void sbc_analyze_4b_8s_neon(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
 {
 	/* Analyze blocks */
 	_sbc_analyze_eight_neon(x + 24, out, analysis_consts_fixed8_simd_odd);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 02/16] sbc: Break 4 blocks processing to variable steps
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 01/16] sbc: Add encoder_state to analysis functions Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 03/16] sbc: Rename sbc_analyze_4b_xx to sbc_analyze_xx Frédéric Dalleau
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Until now SBC processed 4 blocks at a time. If we want to process 15 blocks,
then we need to break this processing in one block steps. 4 blocks is still
default increment.
---
 sbc/sbc.c            |   19 +++++++++++--------
 sbc/sbc_primitives.h |    6 ++++--
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index e51ed57..4a7dd2e 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -688,30 +688,32 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
 	switch (frame->subbands) {
 	case 4:
 		for (ch = 0; ch < frame->channels; ch++) {
-			x = &state->X[ch][state->position - 16 +
-							frame->blocks * 4];
-			for (blk = 0; blk < frame->blocks; blk += 4) {
+			x = &state->X[ch][state->position - 4 *
+					state->increment + frame->blocks * 4];
+			for (blk = 0; blk < frame->blocks;
+						blk += state->increment) {
 				state->sbc_analyze_4b_4s(
 					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
 					frame->sb_sample_f[blk][ch]);
-				x -= 16;
+				x -= 4 * state->increment;
 			}
 		}
 		return frame->blocks * 4;
 
 	case 8:
 		for (ch = 0; ch < frame->channels; ch++) {
-			x = &state->X[ch][state->position - 32 +
-							frame->blocks * 8];
-			for (blk = 0; blk < frame->blocks; blk += 4) {
+			x = &state->X[ch][state->position - 8 *
+					state->increment + frame->blocks * 8];
+			for (blk = 0; blk < frame->blocks;
+						blk += state->increment) {
 				state->sbc_analyze_4b_8s(
 					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
 					frame->sb_sample_f[blk][ch]);
-				x -= 32;
+				x -= 8 * state->increment;
 			}
 		}
 		return frame->blocks * 8;
@@ -906,6 +908,7 @@ static void sbc_encoder_init(struct sbc_encoder_state *state,
 {
 	memset(&state->X, 0, sizeof(state->X));
 	state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
+	state->increment = 4;
 
 	sbc_init_primitives(state);
 }
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index a7bbef1..8606298 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -38,13 +38,15 @@
 
 struct sbc_encoder_state {
 	int position;
+	/* Number of consecutive blocks handled by the encoder */
+	uint8_t increment;
 	int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
 	/* Polyphase analysis filter for 4 subbands configuration,
-	 * it handles 4 blocks at once */
+	 * it handles "increment" blocks at once */
 	void (*sbc_analyze_4b_4s)(struct sbc_encoder_state *state,
 			int16_t *x, int32_t *out, int out_stride);
 	/* Polyphase analysis filter for 8 subbands configuration,
-	 * it handles 4 blocks at once */
+	 * it handles "increment" blocks at once */
 	void (*sbc_analyze_4b_8s)(struct sbc_encoder_state *state,
 			int16_t *x, int32_t *out, int out_stride);
 	/* Process input data (deinterleave, endian conversion, reordering),
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 03/16] sbc: Rename sbc_analyze_4b_xx to sbc_analyze_xx
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 01/16] sbc: Add encoder_state to analysis functions Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 02/16] sbc: Break 4 blocks processing to variable steps Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state Frédéric Dalleau
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc.c                   |    4 ++--
 sbc/sbc_primitives.c        |    4 ++--
 sbc/sbc_primitives.h        |    4 ++--
 sbc/sbc_primitives_armv6.c  |    4 ++--
 sbc/sbc_primitives_iwmmxt.c |    4 ++--
 sbc/sbc_primitives_mmx.c    |    4 ++--
 sbc/sbc_primitives_neon.c   |    4 ++--
 7 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index 4a7dd2e..ffdf05d 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -692,7 +692,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
 					state->increment + frame->blocks * 4];
 			for (blk = 0; blk < frame->blocks;
 						blk += state->increment) {
-				state->sbc_analyze_4b_4s(
+				state->sbc_analyze_4s(
 					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
@@ -708,7 +708,7 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
 					state->increment + frame->blocks * 8];
 			for (blk = 0; blk < frame->blocks;
 						blk += state->increment) {
-				state->sbc_analyze_4b_8s(
+				state->sbc_analyze_8s(
 					state, x,
 					frame->sb_sample_f[blk][ch],
 					frame->sb_sample_f[blk + 1][ch] -
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index f8cc4b6..dce0ed2 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -522,8 +522,8 @@ static int sbc_calc_scalefactors_j(
 void sbc_init_primitives(struct sbc_encoder_state *state)
 {
 	/* Default implementation for analyze functions */
-	state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_simd;
-	state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_simd;
+	state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
+	state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
 
 	/* Default implementation for input reordering / deinterleaving */
 	state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index 8606298..e01c957 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -43,11 +43,11 @@ struct sbc_encoder_state {
 	int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
 	/* Polyphase analysis filter for 4 subbands configuration,
 	 * it handles "increment" blocks at once */
-	void (*sbc_analyze_4b_4s)(struct sbc_encoder_state *state,
+	void (*sbc_analyze_4s)(struct sbc_encoder_state *state,
 			int16_t *x, int32_t *out, int out_stride);
 	/* Polyphase analysis filter for 8 subbands configuration,
 	 * it handles "increment" blocks at once */
-	void (*sbc_analyze_4b_8s)(struct sbc_encoder_state *state,
+	void (*sbc_analyze_8s)(struct sbc_encoder_state *state,
 			int16_t *x, int32_t *out, int out_stride);
 	/* Process input data (deinterleave, endian conversion, reordering),
 	 * depending on the number of subbands and input data byte order */
diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index 6ad94c6..068648a 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -293,8 +293,8 @@ static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
 
 void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
 {
-	state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_armv6;
-	state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_armv6;
+	state->sbc_analyze_4s = sbc_analyze_4b_4s_armv6;
+	state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
 	state->implementation_info = "ARMv6 SIMD";
 }
 
diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index 39cc390..0c8f329 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -296,8 +296,8 @@ static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
 
 void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *state)
 {
-	state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_iwmmxt;
-	state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_iwmmxt;
+	state->sbc_analyze_4s = sbc_analyze_4b_4s_iwmmxt;
+	state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
 	state->implementation_info = "IWMMXT";
 }
 
diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index cbacb4e..03070f5 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -365,8 +365,8 @@ static int check_mmx_support(void)
 void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
 {
 	if (check_mmx_support()) {
-		state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_mmx;
-		state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_mmx;
+		state->sbc_analyze_4s = sbc_analyze_4b_4s_mmx;
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
 		state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
 		state->implementation_info = "MMX";
 	}
diff --git a/sbc/sbc_primitives_neon.c b/sbc/sbc_primitives_neon.c
index aeca8df..eda4ed3 100644
--- a/sbc/sbc_primitives_neon.c
+++ b/sbc/sbc_primitives_neon.c
@@ -879,8 +879,8 @@ static int sbc_enc_process_input_8s_le_neon(int position, const uint8_t *pcm,
 
 void sbc_init_primitives_neon(struct sbc_encoder_state *state)
 {
-	state->sbc_analyze_4b_4s = sbc_analyze_4b_4s_neon;
-	state->sbc_analyze_4b_8s = sbc_analyze_4b_8s_neon;
+	state->sbc_analyze_4s = sbc_analyze_4b_4s_neon;
+	state->sbc_analyze_8s = sbc_analyze_4b_8s_neon;
 	state->sbc_calc_scalefactors = sbc_calc_scalefactors_neon;
 	state->sbc_calc_scalefactors_j = sbc_calc_scalefactors_j_neon;
 	state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le_neon;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (2 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 03/16] sbc: Rename sbc_analyze_4b_xx to sbc_analyze_xx Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-30 17:09   ` Johan Hedberg
  2013-03-29 15:58 ` [PATCH v8 05/16] sbc: Add mmx primitive for 1b 8s analysis Frédéric Dalleau
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc.c                   |    1 +
 sbc/sbc_primitives.c        |    3 +++
 sbc/sbc_primitives.h        |    1 +
 sbc/sbc_primitives_armv6.c  |    1 +
 sbc/sbc_primitives_iwmmxt.c |    1 +
 sbc/sbc_primitives_mmx.c    |    1 +
 sbc/sbc_primitives_neon.c   |    1 +
 7 files changed, 9 insertions(+)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index ffdf05d..75b30a3 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -36,6 +36,7 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index dce0ed2..cd16835 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -24,6 +24,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <limits.h>
 #include <string.h>
@@ -521,6 +522,8 @@ static int sbc_calc_scalefactors_j(
  */
 void sbc_init_primitives(struct sbc_encoder_state *state)
 {
+	state->odd = true;
+
 	/* Default implementation for analyze functions */
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
 	state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
diff --git a/sbc/sbc_primitives.h b/sbc/sbc_primitives.h
index e01c957..16f6c3b 100644
--- a/sbc/sbc_primitives.h
+++ b/sbc/sbc_primitives.h
@@ -40,6 +40,7 @@ struct sbc_encoder_state {
 	int position;
 	/* Number of consecutive blocks handled by the encoder */
 	uint8_t increment;
+	bool odd;
 	int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
 	/* Polyphase analysis filter for 4 subbands configuration,
 	 * it handles "increment" blocks at once */
diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index 068648a..dcc3ef4 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -24,6 +24,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <limits.h>
 #include "sbc.h"
diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index 0c8f329..247bb69 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <limits.h>
 #include "sbc.h"
diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index 03070f5..d723b0c 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -24,6 +24,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <limits.h>
 #include "sbc.h"
diff --git a/sbc/sbc_primitives_neon.c b/sbc/sbc_primitives_neon.c
index eda4ed3..46ac1fc 100644
--- a/sbc/sbc_primitives_neon.c
+++ b/sbc/sbc_primitives_neon.c
@@ -24,6 +24,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <limits.h>
 #include "sbc.h"
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 05/16] sbc: Add mmx primitive for 1b 8s analysis
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (3 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 06/16] sbc: Add armv6 " Frédéric Dalleau
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc_primitives_mmx.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_mmx.c b/sbc/sbc_primitives_mmx.c
index d723b0c..4c88c24 100644
--- a/sbc/sbc_primitives_mmx.c
+++ b/sbc/sbc_primitives_mmx.c
@@ -277,6 +277,19 @@ static inline void sbc_analyze_4b_8s_mmx(struct sbc_encoder_state *state,
 	__asm__ volatile ("emms\n");
 }
 
+static inline void sbc_analyze_1b_8s_mmx(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_mmx(x, out, analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+
+	__asm__ volatile ("emms\n");
+}
+
 static void sbc_calc_scalefactors_mmx(
 	int32_t sb_sample_f[16][2][8],
 	uint32_t scale_factor[2][8],
@@ -367,7 +380,10 @@ void sbc_init_primitives_mmx(struct sbc_encoder_state *state)
 {
 	if (check_mmx_support()) {
 		state->sbc_analyze_4s = sbc_analyze_4b_4s_mmx;
-		state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
+		if (state->increment == 1)
+			state->sbc_analyze_8s = sbc_analyze_1b_8s_mmx;
+		else
+			state->sbc_analyze_8s = sbc_analyze_4b_8s_mmx;
 		state->sbc_calc_scalefactors = sbc_calc_scalefactors_mmx;
 		state->implementation_info = "MMX";
 	}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 06/16] sbc: Add armv6 primitive for 1b 8s analysis
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (4 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 05/16] sbc: Add mmx primitive for 1b 8s analysis Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 07/16] sbc: Add iwmmxt primitive for 1b 8s encoding Frédéric Dalleau
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc_primitives_armv6.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_armv6.c b/sbc/sbc_primitives_armv6.c
index dcc3ef4..6651d2e 100644
--- a/sbc/sbc_primitives_armv6.c
+++ b/sbc/sbc_primitives_armv6.c
@@ -292,10 +292,26 @@ static void sbc_analyze_4b_8s_armv6(struct sbc_encoder_state *state,
 	sbc_analyze_eight(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static void sbc_analyze_1b_8s_armv6(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_armv6(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_armv6(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 void sbc_init_primitives_armv6(struct sbc_encoder_state *state)
 {
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_armv6;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_armv6;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_armv6;
 	state->implementation_info = "ARMv6 SIMD";
 }
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 07/16] sbc: Add iwmmxt primitive for 1b 8s encoding
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (5 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 06/16] sbc: Add armv6 " Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 08/16] sbc: Add plain C primitive for 1b 8s analysis Frédéric Dalleau
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc_primitives_iwmmxt.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives_iwmmxt.c b/sbc/sbc_primitives_iwmmxt.c
index 247bb69..43f77e6 100644
--- a/sbc/sbc_primitives_iwmmxt.c
+++ b/sbc/sbc_primitives_iwmmxt.c
@@ -295,10 +295,26 @@ static inline void sbc_analyze_4b_8s_iwmmxt(struct sbc_encoder_state *state,
 	sbc_analyze_eight_iwmmxt(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static inline void sbc_analyze_1b_8s_iwmmxt(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_iwmmxt(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_iwmmxt(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 void sbc_init_primitives_iwmmxt(struct sbc_encoder_state *state)
 {
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_iwmmxt;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_iwmmxt;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_iwmmxt;
 	state->implementation_info = "IWMMXT";
 }
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 08/16] sbc: Add plain C primitive for 1b 8s analysis
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (6 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 07/16] sbc: Add iwmmxt primitive for 1b 8s encoding Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 09/16] sbc: Use plain C primitive if doing msbc on neon Frédéric Dalleau
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc_primitives.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index cd16835..d85ea86 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -210,6 +210,19 @@ static inline void sbc_analyze_4b_8s_simd(struct sbc_encoder_state *state,
 	sbc_analyze_eight_simd(x + 0, out, analysis_consts_fixed8_simd_even);
 }
 
+static inline void sbc_analyze_1b_8s_simd(struct sbc_encoder_state *state,
+		int16_t *x, int32_t *out, int out_stride)
+{
+	if (state->odd)
+		sbc_analyze_eight_simd(x, out,
+					analysis_consts_fixed8_simd_odd);
+	else
+		sbc_analyze_eight_simd(x, out,
+					analysis_consts_fixed8_simd_even);
+
+	state->odd = !state->odd;
+}
+
 static inline int16_t unaligned16_be(const uint8_t *ptr)
 {
 	return (int16_t) ((ptr[0] << 8) | ptr[1]);
@@ -526,7 +539,10 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
 
 	/* Default implementation for analyze functions */
 	state->sbc_analyze_4s = sbc_analyze_4b_4s_simd;
-	state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
+	if (state->increment == 1)
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_simd;
+	else
+		state->sbc_analyze_8s = sbc_analyze_4b_8s_simd;
 
 	/* Default implementation for input reordering / deinterleaving */
 	state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 09/16] sbc: Use plain C primitive if doing msbc on neon
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (7 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 08/16] sbc: Add plain C primitive for 1b 8s analysis Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 10/16] sbc: Fix input reordering for 15 blocks case Frédéric Dalleau
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

neon has it's own optimized input reordering. Until this code gets optimized,
the neon assembly code will not work with the mSBC input reordering.
However, the plain C version of mSBC can be used in this case.
This patch makes use of plain C code if the block increment is 1 which is
typical for mSBC.
---
 sbc/sbc_primitives.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index d85ea86..2f144b4 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -569,5 +569,13 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
 #endif
 #ifdef SBC_BUILD_WITH_NEON_SUPPORT
 	sbc_init_primitives_neon(state);
+
+	if (state->increment == 1) {
+		state->sbc_analyze_8s = sbc_analyze_1b_8s_simd;
+		state->sbc_enc_process_input_4s_le = sbc_enc_process_input_4s_le;
+		state->sbc_enc_process_input_4s_be = sbc_enc_process_input_4s_be;
+		state->sbc_enc_process_input_8s_le = sbc_enc_process_input_8s_le;
+		state->sbc_enc_process_input_8s_be = sbc_enc_process_input_8s_be;
+	}
 #endif
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 10/16] sbc: Fix input reordering for 15 blocks case
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (8 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 09/16] sbc: Use plain C primitive if doing msbc on neon Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 11/16] sbc: Add a private boolean flag to enable 15 block encoding Frédéric Dalleau
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

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 2f144b4..f24bd7c 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
@@ -310,8 +311,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];
@@ -352,6 +382,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


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 11/16] sbc: Add a private boolean flag to enable 15 block encoding
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (9 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 10/16] sbc: Fix input reordering for 15 blocks case Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 12/16] sbc: Declare and implement sbc_init_msbc Frédéric Dalleau
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

This patch introduce a new private member which purpose is to encode 15
blocks. It is private to the library and can't be set from standard API.
sbc_init_msbc() function will be defined to set this flag.
---
 sbc/sbc.c |   36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index 75b30a3..137757b 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -53,6 +53,9 @@
 
 #define SBC_SYNCWORD	0x9C
 
+#define MSBC_SYNCWORD	0xAD
+#define MSBC_BLOCKS	15
+
 /* This structure contains an unpacked SBC frame.
    Yes, there is probably quite some unused space herein */
 struct sbc_frame {
@@ -904,18 +907,22 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 	}
 }
 
-static void sbc_encoder_init(struct sbc_encoder_state *state,
-					const struct sbc_frame *frame)
+static void sbc_encoder_init(bool msbc, struct sbc_encoder_state *state,
+						const struct sbc_frame *frame)
 {
 	memset(&state->X, 0, sizeof(state->X));
 	state->position = (SBC_X_BUFFER_SIZE - frame->subbands * 9) & ~7;
-	state->increment = 4;
+	if (msbc)
+		state->increment = 1;
+	else
+		state->increment = 4;
 
 	sbc_init_primitives(state);
 }
 
 struct sbc_priv {
 	int init;
+	bool msbc;
 	struct SBC_ALIGNED sbc_frame frame;
 	struct SBC_ALIGNED sbc_decoder_state dec_state;
 	struct SBC_ALIGNED sbc_encoder_state enc_state;
@@ -923,6 +930,7 @@ struct sbc_priv {
 
 static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
 {
+	sbc->flags = flags;
 	sbc->frequency = SBC_FREQ_44100;
 	sbc->mode = SBC_MODE_STEREO;
 	sbc->subbands = SBC_SB_8;
@@ -1058,12 +1066,15 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
 		priv->frame.subband_mode = sbc->subbands;
 		priv->frame.subbands = sbc->subbands ? 8 : 4;
 		priv->frame.block_mode = sbc->blocks;
-		priv->frame.blocks = 4 + (sbc->blocks * 4);
+		if (priv->msbc)
+			priv->frame.blocks = MSBC_BLOCKS;
+		else
+			priv->frame.blocks = 4 + (sbc->blocks * 4);
 		priv->frame.bitpool = sbc->bitpool;
 		priv->frame.codesize = sbc_get_codesize(sbc);
 		priv->frame.length = sbc_get_frame_length(sbc);
 
-		sbc_encoder_init(&priv->enc_state, &priv->frame);
+		sbc_encoder_init(priv->msbc, &priv->enc_state, &priv->frame);
 		priv->init = 1;
 	} else if (priv->frame.bitpool != sbc->bitpool) {
 		priv->frame.length = sbc_get_frame_length(sbc);
@@ -1142,7 +1153,10 @@ SBC_EXPORT size_t sbc_get_frame_length(sbc_t *sbc)
 		return priv->frame.length;
 
 	subbands = sbc->subbands ? 8 : 4;
-	blocks = 4 + (sbc->blocks * 4);
+	if (priv->msbc)
+		blocks = MSBC_BLOCKS;
+	else
+		blocks = 4 + (sbc->blocks * 4);
 	channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
 	joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
 	bitpool = sbc->bitpool;
@@ -1166,7 +1180,10 @@ SBC_EXPORT unsigned sbc_get_frame_duration(sbc_t *sbc)
 	priv = sbc->priv;
 	if (!priv->init) {
 		subbands = sbc->subbands ? 8 : 4;
-		blocks = 4 + (sbc->blocks * 4);
+		if (priv->msbc)
+			blocks = MSBC_BLOCKS;
+		else
+			blocks = 4 + (sbc->blocks * 4);
 	} else {
 		subbands = priv->frame.subbands;
 		blocks = priv->frame.blocks;
@@ -1203,7 +1220,10 @@ SBC_EXPORT size_t sbc_get_codesize(sbc_t *sbc)
 	priv = sbc->priv;
 	if (!priv->init) {
 		subbands = sbc->subbands ? 8 : 4;
-		blocks = 4 + (sbc->blocks * 4);
+		if (priv->msbc)
+			blocks = MSBC_BLOCKS;
+		else
+			blocks = 4 + (sbc->blocks * 4);
 		channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
 	} else {
 		subbands = priv->frame.subbands;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 12/16] sbc: Declare and implement sbc_init_msbc
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (10 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 11/16] sbc: Add a private boolean flag to enable 15 block encoding Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 13/16] sbc: Add support for mSBC frame header Frédéric Dalleau
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 sbc/sbc.c   |   34 ++++++++++++++++++++++++++++++++++
 sbc/sbc.h   |    1 +
 sbc/sbc.sym |    1 +
 3 files changed, 36 insertions(+)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index 137757b..d8282ec 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.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-2008  Brad Midgley <bmidgley@xmission.com>
+ *  Copyright (C) 2012-2013  Intel Corporation
  *
  *
  *  This library is free software; you can redistribute it and/or
@@ -966,6 +967,39 @@ SBC_EXPORT int sbc_init(sbc_t *sbc, unsigned long flags)
 	return 0;
 }
 
+SBC_EXPORT int sbc_init_msbc(sbc_t *sbc, unsigned long flags)
+{
+	struct sbc_priv *priv;
+
+	if (!sbc)
+		return -EIO;
+
+	memset(sbc, 0, sizeof(sbc_t));
+
+	sbc->priv_alloc_base = malloc(sizeof(struct sbc_priv) + SBC_ALIGN_MASK);
+	if (!sbc->priv_alloc_base)
+		return -ENOMEM;
+
+	sbc->priv = (void *) (((uintptr_t) sbc->priv_alloc_base +
+			SBC_ALIGN_MASK) & ~((uintptr_t) SBC_ALIGN_MASK));
+
+	memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+	priv = sbc->priv;
+	priv->msbc = true;
+
+	sbc_set_defaults(sbc, flags);
+
+	sbc->frequency = SBC_FREQ_16000;
+	sbc->blocks = MSBC_BLOCKS;
+	sbc->subbands = SBC_SB_8;
+	sbc->mode = SBC_MODE_MONO;
+	sbc->allocation = SBC_AM_LOUDNESS;
+	sbc->bitpool = 26;
+
+	return 0;
+}
+
 SBC_EXPORT ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
 {
 	return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
diff --git a/sbc/sbc.h b/sbc/sbc.h
index bbd45da..5f8a1fc 100644
--- a/sbc/sbc.h
+++ b/sbc/sbc.h
@@ -83,6 +83,7 @@ typedef struct sbc_struct sbc_t;
 
 int sbc_init(sbc_t *sbc, unsigned long flags);
 int sbc_reinit(sbc_t *sbc, unsigned long flags);
+int sbc_init_msbc(sbc_t *sbc, unsigned long flags);
 
 ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
 
diff --git a/sbc/sbc.sym b/sbc/sbc.sym
index 2cabcdd..3a47c12 100644
--- a/sbc/sbc.sym
+++ b/sbc/sbc.sym
@@ -1,6 +1,7 @@
 SBC_1.0 {
 global:
 	sbc_init;
+	sbc_init_msbc;
 	sbc_reinit;
 	sbc_finish;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 13/16] sbc: Add support for mSBC frame header
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (11 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 12/16] sbc: Declare and implement sbc_init_msbc Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 14/16] sbc: Update sbcdec for msbc Frédéric Dalleau
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Traditionnal SBC frame header describe encoding parameters for each frame: nr
of blocks, subbands, allocation method, and bitpool. In mSBC, only one
combination of parameter is defined. That combination cannot be expressed using
a traditionnal SBC header. Because of this, a specific header is defined with
0xAD followed by two reserved zero bytes.
---
 sbc/sbc.c |  228 +++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 138 insertions(+), 90 deletions(-)

diff --git a/sbc/sbc.c b/sbc/sbc.c
index d8282ec..70f3251 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -379,8 +379,8 @@ static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
  *  -3   CRC8 incorrect
  *  -4   Bitpool value out of bounds
  */
-static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
-								size_t len)
+static int sbc_unpack_frame_internal(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
 {
 	unsigned int consumed;
 	/* Will copy the parts of the header that are relevant to crc
@@ -395,59 +395,6 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
 	int bits[2][8];		/* bits distribution */
 	uint32_t levels[2][8];	/* levels derived from that */
 
-	if (len < 4)
-		return -1;
-
-	if (data[0] != SBC_SYNCWORD)
-		return -2;
-
-	frame->frequency = (data[1] >> 6) & 0x03;
-
-	frame->block_mode = (data[1] >> 4) & 0x03;
-	switch (frame->block_mode) {
-	case SBC_BLK_4:
-		frame->blocks = 4;
-		break;
-	case SBC_BLK_8:
-		frame->blocks = 8;
-		break;
-	case SBC_BLK_12:
-		frame->blocks = 12;
-		break;
-	case SBC_BLK_16:
-		frame->blocks = 16;
-		break;
-	}
-
-	frame->mode = (data[1] >> 2) & 0x03;
-	switch (frame->mode) {
-	case MONO:
-		frame->channels = 1;
-		break;
-	case DUAL_CHANNEL:	/* fall-through */
-	case STEREO:
-	case JOINT_STEREO:
-		frame->channels = 2;
-		break;
-	}
-
-	frame->allocation = (data[1] >> 1) & 0x01;
-
-	frame->subband_mode = (data[1] & 0x01);
-	frame->subbands = frame->subband_mode ? 8 : 4;
-
-	frame->bitpool = data[2];
-
-	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
-			frame->bitpool > 16 * frame->subbands)
-		return -4;
-
-	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
-			frame->bitpool > 32 * frame->subbands)
-		return -4;
-
-	/* data[3] is crc, we're checking it later */
-
 	consumed = 32;
 
 	crc_header[0] = data[1];
@@ -548,6 +495,90 @@ static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
 	return consumed >> 3;
 }
 
+static int sbc_unpack_frame(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
+{
+	if (len < 4)
+		return -1;
+
+	if (data[0] != SBC_SYNCWORD)
+		return -2;
+
+	frame->frequency = (data[1] >> 6) & 0x03;
+	frame->block_mode = (data[1] >> 4) & 0x03;
+
+	switch (frame->block_mode) {
+	case SBC_BLK_4:
+		frame->blocks = 4;
+		break;
+	case SBC_BLK_8:
+		frame->blocks = 8;
+		break;
+	case SBC_BLK_12:
+		frame->blocks = 12;
+		break;
+	case SBC_BLK_16:
+		frame->blocks = 16;
+		break;
+	}
+
+	frame->mode = (data[1] >> 2) & 0x03;
+
+	switch (frame->mode) {
+	case MONO:
+		frame->channels = 1;
+		break;
+	case DUAL_CHANNEL:	/* fall-through */
+	case STEREO:
+	case JOINT_STEREO:
+		frame->channels = 2;
+		break;
+	}
+
+	frame->allocation = (data[1] >> 1) & 0x01;
+
+	frame->subband_mode = (data[1] & 0x01);
+	frame->subbands = frame->subband_mode ? 8 : 4;
+
+	frame->bitpool = data[2];
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > 16 * frame->subbands)
+		return -4;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > 32 * frame->subbands)
+		return -4;
+
+	return sbc_unpack_frame_internal(data, frame, len);
+}
+
+static int msbc_unpack_frame(const uint8_t *data,
+		struct sbc_frame *frame, size_t len)
+{
+	if (len < 4)
+		return -1;
+
+	if (data[0] != MSBC_SYNCWORD)
+		return -2;
+	if (data[1] != 0)
+		return -2;
+	if (data[2] != 0)
+		return -2;
+
+	frame->frequency = SBC_FREQ_16000;
+	frame->block_mode = SBC_BLK_4;
+	frame->blocks = MSBC_BLOCKS;
+	frame->allocation = LOUDNESS;
+	frame->mode = MONO;
+	frame->channels = 1;
+	frame->subband_mode = 1;
+	frame->subbands = 8;
+	frame->bitpool = 26;
+
+	return sbc_unpack_frame_internal(data, frame, len);
+}
+
 static void sbc_decoder_init(struct sbc_decoder_state *state,
 					const struct sbc_frame *frame)
 {
@@ -792,38 +823,6 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
 	uint32_t levels[2][8];	/* levels are derived from that */
 	uint32_t sb_sample_delta[2][8];
 
-	data[0] = SBC_SYNCWORD;
-
-	data[1] = (frame->frequency & 0x03) << 6;
-
-	data[1] |= (frame->block_mode & 0x03) << 4;
-
-	data[1] |= (frame->mode & 0x03) << 2;
-
-	data[1] |= (frame->allocation & 0x01) << 1;
-
-	switch (frame_subbands) {
-	case 4:
-		/* Nothing to do */
-		break;
-	case 8:
-		data[1] |= 0x01;
-		break;
-	default:
-		return -4;
-		break;
-	}
-
-	data[2] = frame->bitpool;
-
-	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
-			frame->bitpool > frame_subbands << 4)
-		return -5;
-
-	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
-			frame->bitpool > frame_subbands << 5)
-		return -5;
-
 	/* Can't fill in crc yet */
 
 	crc_header[0] = data[1];
@@ -891,6 +890,28 @@ static SBC_ALWAYS_INLINE ssize_t sbc_pack_frame_internal(uint8_t *data,
 static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len,
 								int joint)
 {
+	int frame_subbands = 4;
+
+	data[0] = SBC_SYNCWORD;
+
+	data[1] = (frame->frequency & 0x03) << 6;
+	data[1] |= (frame->block_mode & 0x03) << 4;
+	data[1] |= (frame->mode & 0x03) << 2;
+	data[1] |= (frame->allocation & 0x01) << 1;
+
+	data[2] = frame->bitpool;
+
+	if (frame->subbands != 4)
+		frame_subbands = 8;
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > frame_subbands << 4)
+		return -5;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > frame_subbands << 5)
+		return -5;
+
 	if (frame->subbands == 4) {
 		if (frame->channels == 1)
 			return sbc_pack_frame_internal(
@@ -899,6 +920,7 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 			return sbc_pack_frame_internal(
 				data, frame, len, 4, 2, joint);
 	} else {
+		data[1] |= 0x01;
 		if (frame->channels == 1)
 			return sbc_pack_frame_internal(
 				data, frame, len, 8, 1, joint);
@@ -908,6 +930,16 @@ static ssize_t sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len
 	}
 }
 
+static ssize_t msbc_pack_frame(uint8_t *data, struct sbc_frame *frame,
+						size_t len, int joint)
+{
+	data[0] = MSBC_SYNCWORD;
+	data[1] = 0;
+	data[2] = 0;
+
+	return sbc_pack_frame_internal(data, frame, len, 8, 1, joint);
+}
+
 static void sbc_encoder_init(bool msbc, struct sbc_encoder_state *state,
 						const struct sbc_frame *frame)
 {
@@ -927,10 +959,24 @@ struct sbc_priv {
 	struct SBC_ALIGNED sbc_frame frame;
 	struct SBC_ALIGNED sbc_decoder_state dec_state;
 	struct SBC_ALIGNED sbc_encoder_state enc_state;
+	int (*unpack_frame)(const uint8_t *data, struct sbc_frame *frame,
+			size_t len);
+	ssize_t (*pack_frame)(uint8_t *data, struct sbc_frame *frame,
+			size_t len, int joint);
 };
 
 static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
 {
+	struct sbc_priv *priv = sbc->priv;
+
+	if (priv->msbc) {
+		priv->pack_frame = msbc_pack_frame;
+		priv->unpack_frame = msbc_unpack_frame;
+	} else {
+		priv->pack_frame = sbc_pack_frame;
+		priv->unpack_frame = sbc_unpack_frame;
+	}
+
 	sbc->flags = flags;
 	sbc->frequency = SBC_FREQ_44100;
 	sbc->mode = SBC_MODE_STEREO;
@@ -1017,7 +1063,7 @@ SBC_EXPORT ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
 
 	priv = sbc->priv;
 
-	framelen = sbc_unpack_frame(input, &priv->frame, input_len);
+	framelen = priv->unpack_frame(input, &priv->frame, input_len);
 
 	if (!priv->init) {
 		sbc_decoder_init(&priv->dec_state, &priv->frame);
@@ -1151,13 +1197,15 @@ SBC_EXPORT ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
 		int j = priv->enc_state.sbc_calc_scalefactors_j(
 			priv->frame.sb_sample_f, priv->frame.scale_factor,
 			priv->frame.blocks, priv->frame.subbands);
-		framelen = sbc_pack_frame(output, &priv->frame, output_len, j);
+		framelen = priv->pack_frame(output,
+				&priv->frame, output_len, j);
 	} else {
 		priv->enc_state.sbc_calc_scalefactors(
 			priv->frame.sb_sample_f, priv->frame.scale_factor,
 			priv->frame.blocks, priv->frame.channels,
 			priv->frame.subbands);
-		framelen = sbc_pack_frame(output, &priv->frame, output_len, 0);
+		framelen = priv->pack_frame(output,
+				&priv->frame, output_len, 0);
 	}
 
 	if (written)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 14/16] sbc: Update sbcdec for msbc
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (12 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 13/16] sbc: Add support for mSBC frame header Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 15/16] sbc: Update sbcenc " Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 16/16] sbc: Update sbcinfo " Frédéric Dalleau
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 src/sbcdec.c |   23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/src/sbcdec.c b/src/sbcdec.c
index 0077a82..f937ef3 100644
--- a/src/sbcdec.c
+++ b/src/sbcdec.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012-2013  Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -31,6 +32,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <getopt.h>
 #include <sys/stat.h>
@@ -44,7 +46,7 @@
 
 static int verbose = 0;
 
-static void decode(char *filename, char *output, int tofile)
+static void decode(char *filename, char *output, int tofile, bool msbc)
 {
 	unsigned char buf[BUF_SIZE], *stream;
 	struct stat st;
@@ -98,7 +100,11 @@ static void decode(char *filename, char *output, int tofile)
 		goto free;
 	}
 
-	sbc_init(&sbc, 0L);
+	if (msbc) {
+		sbc_init_msbc(&sbc, 0L);
+	} else {
+		sbc_init(&sbc, 0L);
+	}
 	sbc.endian = SBC_BE;
 
 	framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len);
@@ -228,14 +234,16 @@ static void usage(void)
 
 	printf("Options:\n"
 		"\t-h, --help           Display help\n"
-		"\t-v, --verbose        Verbose mode\n"
 		"\t-d, --device <dsp>   Sound device\n"
+		"\t-v, --verbose        Verbose mode\n"
+		"\t-m, --msbc           mSBC codec\n"
 		"\t-f, --file <file>    Decode to a file\n"
 		"\n");
 }
 
 static struct option main_options[] = {
 	{ "help",	0, 0, 'h' },
+	{ "msbc",	0, 0, 'm' },
 	{ "device",	1, 0, 'd' },
 	{ "verbose",	0, 0, 'v' },
 	{ "file",	1, 0, 'f' },
@@ -246,8 +254,9 @@ int main(int argc, char *argv[])
 {
 	char *output = NULL;
 	int i, opt, tofile = 0;
+	bool msbc = false;
 
-	while ((opt = getopt_long(argc, argv, "+hvd:f:",
+	while ((opt = getopt_long(argc, argv, "+hmvd:f:",
 						main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'h':
@@ -258,6 +267,10 @@ int main(int argc, char *argv[])
 			verbose = 1;
 			break;
 
+		case 'm':
+			msbc = true;
+			break;
+
 		case 'd':
 			free(output);
 			output = strdup(optarg);
@@ -285,7 +298,7 @@ int main(int argc, char *argv[])
 	}
 
 	for (i = 0; i < argc; i++)
-		decode(argv[i], output ? output : "/dev/dsp", tofile);
+		decode(argv[i], output ? output : "/dev/dsp", tofile, msbc);
 
 	free(output);
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 15/16] sbc: Update sbcenc for msbc
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (13 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 14/16] sbc: Update sbcdec for msbc Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  2013-03-29 15:58 ` [PATCH v8 16/16] sbc: Update sbcinfo " Frédéric Dalleau
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 src/sbcenc.c |  107 +++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 64 insertions(+), 43 deletions(-)

diff --git a/src/sbcenc.c b/src/sbcenc.c
index a723b03..c766767 100644
--- a/src/sbcenc.c
+++ b/src/sbcenc.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012-2013  Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -31,6 +32,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
 #include <getopt.h>
@@ -45,7 +47,7 @@ static int verbose = 0;
 static unsigned char input[BUF_SIZE], output[BUF_SIZE + BUF_SIZE / 4];
 
 static void encode(char *filename, int subbands, int bitpool, int joint,
-					int dualchannel, int snr, int blocks)
+				int dualchannel, int snr, int blocks, bool msbc)
 {
 	struct au_header au_hdr;
 	sbc_t sbc;
@@ -87,57 +89,69 @@ static void encode(char *filename, int subbands, int bitpool, int joint,
 		goto done;
 	}
 
-	sbc_init(&sbc, 0L);
-
-	switch (BE_INT(au_hdr.sample_rate)) {
-	case 16000:
-		sbc.frequency = SBC_FREQ_16000;
-		break;
-	case 32000:
-		sbc.frequency = SBC_FREQ_32000;
-		break;
-	case 44100:
-		sbc.frequency = SBC_FREQ_44100;
-		break;
-	case 48000:
-		sbc.frequency = SBC_FREQ_48000;
-		break;
-	}
+	if (!msbc) {
+		sbc_init(&sbc, 0L);
+
+		switch (BE_INT(au_hdr.sample_rate)) {
+		case 16000:
+			sbc.frequency = SBC_FREQ_16000;
+			break;
+		case 32000:
+			sbc.frequency = SBC_FREQ_32000;
+			break;
+		case 44100:
+			sbc.frequency = SBC_FREQ_44100;
+			break;
+		case 48000:
+			sbc.frequency = SBC_FREQ_48000;
+			break;
+		}
+
+		srate = BE_INT(au_hdr.sample_rate);
 
-	srate = BE_INT(au_hdr.sample_rate);
+		sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
 
-	sbc.subbands = subbands == 4 ? SBC_SB_4 : SBC_SB_8;
+		if (BE_INT(au_hdr.channels) == 1) {
+			sbc.mode = SBC_MODE_MONO;
+			if (joint || dualchannel) {
+				fprintf(stderr, "Audio is mono but joint or "
+					"dualchannel mode has been specified\n");
+				goto done;
+			}
+		} else if (joint && !dualchannel)
+			sbc.mode = SBC_MODE_JOINT_STEREO;
+		else if (!joint && dualchannel)
+			sbc.mode = SBC_MODE_DUAL_CHANNEL;
+		else if (!joint && !dualchannel)
+			sbc.mode = SBC_MODE_STEREO;
+		else {
+			fprintf(stderr, "Both joint and dualchannel mode have been "
+									"specified\n");
+			goto done;
+		}
 
-	if (BE_INT(au_hdr.channels) == 1) {
-		sbc.mode = SBC_MODE_MONO;
-		if (joint || dualchannel) {
-			fprintf(stderr, "Audio is mono but joint or "
-				"dualchannel mode has been specified\n");
+		sbc.endian = SBC_BE;
+		sbc.bitpool = bitpool;
+		sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
+		sbc.blocks = blocks == 4 ? SBC_BLK_4 :
+				blocks == 8 ? SBC_BLK_8 :
+					blocks == 12 ? SBC_BLK_12 : SBC_BLK_16;
+	} else {
+		if (BE_INT(au_hdr.sample_rate) != 16000 ||
+				BE_INT(au_hdr.channels) != 1 ||
+				BE_INT(au_hdr.channels) != 1) {
+			fprintf(stderr, "mSBC requires 16 bits, 16kHz, mono input\n");
 			goto done;
 		}
-	} else if (joint && !dualchannel)
-		sbc.mode = SBC_MODE_JOINT_STEREO;
-	else if (!joint && dualchannel)
-		sbc.mode = SBC_MODE_DUAL_CHANNEL;
-	else if (!joint && !dualchannel)
-		sbc.mode = SBC_MODE_STEREO;
-	else {
-		fprintf(stderr, "Both joint and dualchannel mode have been "
-								"specified\n");
-		goto done;
+
+		sbc_init_msbc(&sbc, 0);
+		sbc.endian = SBC_BE;
 	}
 
-	sbc.endian = SBC_BE;
 	/* Skip extra bytes of the header if any */
 	if (read(fd, input, BE_INT(au_hdr.hdr_size) - len) < 0)
 		goto done;
 
-	sbc.bitpool = bitpool;
-	sbc.allocation = snr ? SBC_AM_SNR : SBC_AM_LOUDNESS;
-	sbc.blocks = blocks == 4 ? SBC_BLK_4 :
-			blocks == 8 ? SBC_BLK_8 :
-				blocks == 12 ? SBC_BLK_12 : SBC_BLK_16;
-
 	if (verbose) {
 		fprintf(stderr, "encoding %s with rate %d, %d blocks, "
 			"%d subbands, %d bits, allocation method %s, "
@@ -215,6 +229,7 @@ static void usage(void)
 	printf("Options:\n"
 		"\t-h, --help           Display help\n"
 		"\t-v, --verbose        Verbose mode\n"
+		"\t-m, --msbc           mSBC codec\n"
 		"\t-s, --subbands       Number of subbands to use (4 or 8)\n"
 		"\t-b, --bitpool        Bitpool value (default is 32)\n"
 		"\t-j, --joint          Joint stereo\n"
@@ -227,6 +242,7 @@ static void usage(void)
 static struct option main_options[] = {
 	{ "help",	0, 0, 'h' },
 	{ "verbose",	0, 0, 'v' },
+	{ "msbc",	0, 0, 'm' },
 	{ "subbands",	1, 0, 's' },
 	{ "bitpool",	1, 0, 'b' },
 	{ "joint",	0, 0, 'j' },
@@ -240,8 +256,9 @@ int main(int argc, char *argv[])
 {
 	int i, opt, subbands = 8, bitpool = 32, joint = 0, dualchannel = 0;
 	int snr = 0, blocks = 16;
+	bool msbc = false;
 
-	while ((opt = getopt_long(argc, argv, "+hvs:b:jdSB:",
+	while ((opt = getopt_long(argc, argv, "+hmvs:b:jdSB:",
 						main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'h':
@@ -252,6 +269,10 @@ int main(int argc, char *argv[])
 			verbose = 1;
 			break;
 
+		case 'm':
+			msbc = true;
+			break;
+
 		case 's':
 			subbands = atoi(optarg);
 			if (subbands != 8 && subbands != 4) {
@@ -302,7 +323,7 @@ int main(int argc, char *argv[])
 
 	for (i = 0; i < argc; i++)
 		encode(argv[i], subbands, bitpool, joint, dualchannel,
-								snr, blocks);
+							snr, blocks, msbc);
 
 	return 0;
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v8 16/16] sbc: Update sbcinfo for msbc
  2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
                   ` (14 preceding siblings ...)
  2013-03-29 15:58 ` [PATCH v8 15/16] sbc: Update sbcenc " Frédéric Dalleau
@ 2013-03-29 15:58 ` Frédéric Dalleau
  15 siblings, 0 replies; 18+ messages in thread
From: Frédéric Dalleau @ 2013-03-29 15:58 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 src/sbcinfo.c |   54 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 40 insertions(+), 14 deletions(-)

diff --git a/src/sbcinfo.c b/src/sbcinfo.c
index 8cfb54a..81dec65 100644
--- a/src/sbcinfo.c
+++ b/src/sbcinfo.c
@@ -4,6 +4,7 @@
  *
  *  Copyright (C) 2008-2010  Nokia Corporation
  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2012-2013  Intel Corporation
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -31,6 +32,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
 #include <libgen.h>
@@ -61,12 +63,11 @@ struct sbc_frame_hdr {
 #error "Unknown byte order"
 #endif
 
-static int calc_frame_len(struct sbc_frame_hdr *hdr)
+static int calc_frame_len(struct sbc_frame_hdr *hdr, int nrof_blocks)
 {
-	int tmp, nrof_subbands, nrof_blocks;
+	int tmp, nrof_subbands;
 
 	nrof_subbands = (hdr->subbands + 1) * 4;
-	nrof_blocks = (hdr->blocks + 1) * 4;
 
 	switch (hdr->channel_mode) {
 	case 0x00:
@@ -89,13 +90,12 @@ static int calc_frame_len(struct sbc_frame_hdr *hdr)
 	return (nrof_subbands + ((tmp + 7) / 8));
 }
 
-static double calc_bit_rate(struct sbc_frame_hdr *hdr)
+static double calc_bit_rate(struct sbc_frame_hdr *hdr, int nrof_blocks)
 {
-	int nrof_subbands, nrof_blocks;
+	int nrof_subbands;
 	double f;
 
 	nrof_subbands = (hdr->subbands + 1) * 4;
-	nrof_blocks = (hdr->blocks + 1) * 4;
 
 	switch (hdr->sampling_frequency) {
 	case 0:
@@ -114,7 +114,7 @@ static double calc_bit_rate(struct sbc_frame_hdr *hdr)
 		return 0;
 	}
 
-	return ((8 * (calc_frame_len(hdr) + 4) * f) /
+	return ((8 * (calc_frame_len(hdr, nrof_blocks) + 4) * f) /
 			(nrof_subbands * nrof_blocks));
 }
 
@@ -176,6 +176,7 @@ static int analyze_file(char *filename)
 	int bitpool[SIZE], frame_len[SIZE];
 	int subbands, blocks, freq, method;
 	int n, p1, p2, fd, size, num;
+	bool msbc;
 	ssize_t len;
 	unsigned int count;
 
@@ -191,17 +192,32 @@ static int analyze_file(char *filename)
 		fd = fileno(stdin);
 
 	len = __read(fd, &hdr, sizeof(hdr));
-	if (len != sizeof(hdr) || hdr.syncword != 0x9c) {
+	if (len == sizeof(hdr) && hdr.syncword == 0x9c) {
+		msbc = false;
+	} else if (len == sizeof(hdr) && hdr.syncword == 0xad) {
+		msbc = true;
+	} else {
 		fprintf(stderr, "Not a SBC audio file\n");
 		return -1;
 	}
 
+	if (msbc) {
+		hdr.subbands = 1; /* 8 */
+		hdr.sampling_frequency = 0x00; /* 16000 */
+		hdr.allocation_method = 0; /* Loudness */
+		hdr.bitpool = 26;
+		hdr.channel_mode = 0x00; /* Mono */
+
+		blocks = 15;
+	} else {
+		blocks = (hdr.blocks + 1) * 4;
+	}
+
 	subbands = (hdr.subbands + 1) * 4;
-	blocks = (hdr.blocks + 1) * 4;
 	freq = hdr.sampling_frequency;
 	method = hdr.allocation_method;
 
-	count = calc_frame_len(&hdr);
+	count = calc_frame_len(&hdr, blocks);
 
 	bitpool[0] = hdr.bitpool;
 	frame_len[0] = count + 4;
@@ -213,7 +229,7 @@ static int analyze_file(char *filename)
 
 	if (lseek(fd, 0, SEEK_SET) < 0) {
 		num = 1;
-		rate = calc_bit_rate(&hdr);
+		rate = calc_bit_rate(&hdr, blocks);
 		while (count) {
 			size = count > sizeof(buf) ? sizeof(buf) : count;
 			len = __read(fd, buf, size);
@@ -237,14 +253,23 @@ static int analyze_file(char *filename)
 		if (len == 0)
 			break;
 
-		if ((size_t) len < sizeof(hdr) || hdr.syncword != 0x9c) {
+		if ((size_t) len < sizeof(hdr) || !(hdr.syncword == 0x9c ||
+				hdr.syncword == 0xad)) {
 			fprintf(stderr, "Corrupted SBC stream "
 					"(len %zd syncword 0x%02x)\n",
 					len, hdr.syncword);
 			break;
 		}
 
-		count = calc_frame_len(&hdr);
+		if (msbc) {
+			hdr.subbands = 1; /* 8 */
+			hdr.sampling_frequency = 0x00; /* 16000 */
+			hdr.allocation_method = 0; /* Loudness */
+			hdr.bitpool = 26;
+			hdr.channel_mode = 0x00; /* Mono */
+		}
+
+		count = calc_frame_len(&hdr, blocks);
 		len = count + 4;
 
 		p1 = -1;
@@ -273,10 +298,11 @@ static int analyze_file(char *filename)
 			count -= len;
 		}
 
-		rate += calc_bit_rate(&hdr);
+		rate += calc_bit_rate(&hdr, blocks);
 		num++;
 	}
 
+	printf("mSBC\t\t\t%d\n", msbc);
 	printf("Subbands\t\t%d\n", subbands);
 	printf("Block length\t\t%d\n", blocks);
 	printf("Sampling frequency\t%s\n", freq2str(freq));
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state
  2013-03-29 15:58 ` [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state Frédéric Dalleau
@ 2013-03-30 17:09   ` Johan Hedberg
  0 siblings, 0 replies; 18+ messages in thread
From: Johan Hedberg @ 2013-03-30 17:09 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth

Hi Frédéric,

On Fri, Mar 29, 2013, Frédéric Dalleau wrote:
> --- a/sbc/sbc_primitives.h
> +++ b/sbc/sbc_primitives.h
> @@ -40,6 +40,7 @@ struct sbc_encoder_state {
>  	int position;
>  	/* Number of consecutive blocks handled by the encoder */
>  	uint8_t increment;
> +	bool odd;

Since most of the code related on this variable uses function pointers
would it make sense to simply play with those pointers and have the odd
function set the pointer to the even function and vice versa? If this is
a performance critical part of the code it'd remove one if-statement.

Johan

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2013-03-30 17:09 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-29 15:58 [PATCH v8 00/16] mSBC investigations Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 01/16] sbc: Add encoder_state to analysis functions Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 02/16] sbc: Break 4 blocks processing to variable steps Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 03/16] sbc: Rename sbc_analyze_4b_xx to sbc_analyze_xx Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 04/16] sbc: add odd member variable to sbc_encoder_state Frédéric Dalleau
2013-03-30 17:09   ` Johan Hedberg
2013-03-29 15:58 ` [PATCH v8 05/16] sbc: Add mmx primitive for 1b 8s analysis Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 06/16] sbc: Add armv6 " Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 07/16] sbc: Add iwmmxt primitive for 1b 8s encoding Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 08/16] sbc: Add plain C primitive for 1b 8s analysis Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 09/16] sbc: Use plain C primitive if doing msbc on neon Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 10/16] sbc: Fix input reordering for 15 blocks case Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 11/16] sbc: Add a private boolean flag to enable 15 block encoding Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 12/16] sbc: Declare and implement sbc_init_msbc Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 13/16] sbc: Add support for mSBC frame header Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 14/16] sbc: Update sbcdec for msbc Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 15/16] sbc: Update sbcenc " Frédéric Dalleau
2013-03-29 15:58 ` [PATCH v8 16/16] sbc: Update sbcinfo " Frédéric Dalleau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).