summaryrefslogtreecommitdiff
path: root/sbc/sbc_primitives.c
diff options
context:
space:
mode:
authorSiarhei Siamashka <siarhei.siamashka@nokia.com>2009-01-29 02:17:36 +0200
committerMarcel Holtmann <marcel@holtmann.org>2012-07-29 19:48:28 -0700
commitb369ea3525442e56a3e2049ba4541e6b7d100e20 (patch)
tree2707749679ca9e8f5819d84af74e7740ec668c60 /sbc/sbc_primitives.c
parentea356ab95d6c48d4be6834faee0f50ee1e9571cb (diff)
downloadsbc-b369ea3525442e56a3e2049ba4541e6b7d100e20.tar.gz
sbc: SBC encoder scale factors calculation optimized with __builtin_clz
Count leading zeros operation is often implemented using a special instruction for it on various architectures (at least this is true for ARM and x86). Using __builtin_clz gcc intrinsic allows to eliminate innermost loop in scale factors calculation and improve performance. Also scale factors calculation can be optimized even more using SIMD instructions.
Diffstat (limited to 'sbc/sbc_primitives.c')
-rw-r--r--sbc/sbc_primitives.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sbc/sbc_primitives.c b/sbc/sbc_primitives.c
index 338feb9..303f3fe 100644
--- a/sbc/sbc_primitives.c
+++ b/sbc/sbc_primitives.c
@@ -401,6 +401,44 @@ static int sbc_enc_process_input_8s_be(int position,
position, pcm, X, nsamples, 1, 1);
}
+/* Supplementary function to count the number of leading zeros */
+
+static inline int sbc_clz(uint32_t x)
+{
+#ifdef __GNUC__
+ return __builtin_clz(x);
+#else
+ /* TODO: this should be replaced with something better if good
+ * performance is wanted when using compilers other than gcc */
+ int cnt = 0;
+ while (x) {
+ cnt++;
+ x >>= 1;
+ }
+ return 32 - cnt;
+#endif
+}
+
+static void sbc_calc_scalefactors(
+ int32_t sb_sample_f[16][2][8],
+ uint32_t scale_factor[2][8],
+ int blocks, int channels, int subbands)
+{
+ int ch, sb, blk;
+ for (ch = 0; ch < channels; ch++) {
+ for (sb = 0; sb < subbands; sb++) {
+ uint32_t x = 1 << SCALE_OUT_BITS;
+ for (blk = 0; blk < blocks; blk++) {
+ int32_t tmp = fabs(sb_sample_f[blk][ch][sb]);
+ if (tmp != 0)
+ x |= tmp - 1;
+ }
+ scale_factor[ch][sb] = (31 - SCALE_OUT_BITS) -
+ sbc_clz(x);
+ }
+ }
+}
+
/*
* Detect CPU features and setup function pointers
*/
@@ -416,6 +454,9 @@ void sbc_init_primitives(struct sbc_encoder_state *state)
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;
+ /* Default implementation for scale factors calculation */
+ state->sbc_calc_scalefactors = sbc_calc_scalefactors;
+
/* X86/AMD64 optimizations */
#ifdef SBC_BUILD_WITH_MMX_SUPPORT
sbc_init_primitives_mmx(state);