From f51ca493fb26b83dfbabc9cbba4f5ab76b273f01 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Thu, 17 Jan 2008 10:58:38 +1100 Subject: [PATCH] Looks like the bit allocation code is mostly working. Just need to actually use it now. --- libcelt/modes.c | 21 ++++++ libcelt/modes.h | 3 + libcelt/rate.c | 185 +++++++++++++++++++----------------------------- libcelt/rate.h | 60 ++++++++++++---- 4 files changed, 146 insertions(+), 123 deletions(-) diff --git a/libcelt/modes.c b/libcelt/modes.c index b345a70d..54a4b071 100644 --- a/libcelt/modes.c +++ b/libcelt/modes.c @@ -78,6 +78,12 @@ const int qpulses4s[NBANDS] ={38,31,25,21,18,16, 14, 12, 14, 12,14,15, 14, 15, 1 const int pbank1[PBANDS128+2] = {0, 2, 4, 6, 8, 12, 20, 28, PITCH_END128, 128}; //const int pbank1[PBANDS128+2] = {0, 4, 8, 12, 20, PITCH_END128, 128}; +int bitalloc0[NBANDS*5] = { 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, + 8, 7, 7, 6, 6, 6, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 16, 15, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 26, 25, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +}; #define NBANDS256 15 #define PBANDS256 8 @@ -103,6 +109,9 @@ const CELTMode mode0 = { 0.8, /**< ePredCoef */ means18, /**< eMeans */ decay18, /**< eDecay */ + + 5, /**< nbAllocVectors */ + bitalloc0, /**< allocVectors */ }; @@ -124,6 +133,9 @@ const CELTMode mode1 = { 0.7, /**< ePredCoef */ means, /**< eMeans */ decay, /**< eDecay */ + + 5, /**< nbAllocVectors */ + bitalloc0, /**< allocVectors */ }; /* Approx 58 kbps @ 44.1 kHz */ @@ -144,6 +156,9 @@ const CELTMode mode2 = { 0.8, /**< ePredCoef */ means18, /**< eMeans */ decay18, /**< eDecay */ + + 5, /**< nbAllocVectors */ + bitalloc0, /**< allocVectors */ }; const CELTMode mode3 = { @@ -163,6 +178,9 @@ const CELTMode mode3 = { 0.7, /**< ePredCoef */ means, /**< eMeans */ decay, /**< eDecay */ + + 5, /**< nbAllocVectors */ + bitalloc0, /**< allocVectors */ }; /* Stereo mode around 120 kbps */ @@ -183,6 +201,9 @@ const CELTMode mode4 = { 0.8, /**< ePredCoef */ means18, /**< eMeans */ decay18, /**< eDecay */ + + 5, /**< nbAllocVectors */ + bitalloc0, /**< allocVectors */ }; const CELTMode const *celt_mode0 = &mode0; diff --git a/libcelt/modes.h b/libcelt/modes.h index 8dd743ec..77207918 100644 --- a/libcelt/modes.h +++ b/libcelt/modes.h @@ -51,6 +51,9 @@ struct CELTMode { float ePredCoef; const float *eMeans; const int *eDecay; + + int nbAllocVectors; + const int *allocVectors; }; #endif diff --git a/libcelt/rate.c b/libcelt/rate.c index f22ab44c..2d2b6a73 100644 --- a/libcelt/rate.c +++ b/libcelt/rate.c @@ -36,10 +36,11 @@ #include "os_support.h" #include "entcode.h" +#include "rate.h" #define BITRES 4 #define BITROUND 8 -#define BITOVERFLOW 1000 +#define BITOVERFLOW 10000 #define MAX_PULSES 64 @@ -91,42 +92,16 @@ int log2_frac64(ec_uint64 val, int frac) return L; } -int bits2pulses0(int bits, int N) -{ - int i, b, prev; - /* FIXME: This is terribly inefficient. Do a bisection instead - but be careful about overflows */ - prev = 0; - i=1; - b = log2_frac64(ncwrs64(N, i),0); - while (beBands; + alloc->mode = m; alloc->len = m->nbEBands; alloc->bands = m->eBands; alloc->bits = celt_alloc(m->nbEBands*sizeof(int*)); - alloc->rev_bits = celt_alloc(m->nbEBands*sizeof(int*)); BC = m->nbMdctBlocks*m->nbChannels; prevN = -1; @@ -136,12 +111,10 @@ void alloc_init(struct alloc_data *alloc, const CELTMode *m) if (N == prevN) { alloc->bits[i] = alloc->bits[i-1]; - alloc->rev_bits[i] = alloc->rev_bits[i-1]; } else { int j; /* FIXME: We could save memory here */ alloc->bits[i] = celt_alloc(MAX_PULSES*sizeof(int)); - alloc->rev_bits[i] = celt_alloc(MAX_PULSES*sizeof(int)); for (j=0;jbits[i][j] = log2_frac64(ncwrs64(N, j),BITRES); @@ -151,8 +124,6 @@ void alloc_init(struct alloc_data *alloc, const CELTMode *m) } for (;jbits[i][j] = BITOVERFLOW; - for (j=0;j<32;j++) - alloc->rev_bits[i][j] = bits2pulses0(j, N); prevN = N; } } @@ -168,41 +139,16 @@ void alloc_clear(struct alloc_data *alloc) { prevPtr = alloc->bits[i]; celt_free(alloc->bits[i]); - celt_free(alloc->rev_bits[i]); } } celt_free(alloc->bits); - celt_free(alloc->rev_bits); -} - - -int compute_allocation(const CELTMode *m, int *pulses) -{ - int i, N, BC, bits; - const int *eBands = m->eBands; - BC = m->nbMdctBlocks*m->nbChannels; - bits = 0; - for (i=0;inbEBands;i++) - { - int q; - N = BC*(eBands[i+1]-eBands[i]); - q = pulses[i]; - if (q<=0) - { - bits += log2_frac64(eBands[i] - (eBands[i+1]-eBands[i]), 8) + (1<<8); - q = -q; - } - if (q != 0) - bits += log2_frac64(ncwrs64(N, pulses[i]), 8); - } - return (bits+255)>>8; } int bits2pulses(const struct alloc_data *alloc, int band, int bits) { int lo, hi; lo = 0; - hi = MAX_PULSES; + hi = MAX_PULSES-1; while (hi-lo != 1) { @@ -218,48 +164,23 @@ int bits2pulses(const struct alloc_data *alloc, int band, int bits) return hi; } -int vec_bits2pulses(const struct alloc_data *alloc, const int *bands, int *bits, int *pulses, int len, int B) +int vec_bits2pulses(const struct alloc_data *alloc, const int *bands, int *bits, int *pulses, int len) { - int i; + int i, BC; int sum=0; + BC = alloc->mode->nbMdctBlocks*alloc->mode->nbChannels; + for (i=0;ibits[i][pulses[i]]; } + //printf ("sum = %d\n", sum); return sum; } -#if 0 -int interp_bits2pulses(const struct alloc_data *alloc, int *bits1, int *bits2, int total, int *pulses, int len, int B) -{ - int i; - const int *bands = alloc->bands; - /* FIXME: This too is terribly inefficient. We should do a bisection instead */ - for (i=0;i<16;i++) - { - int j; - int bits[len]; - for (j=0;j total) - break; - } - if (i==0) - return -1; - else { - int j; - int bits[len]; - /* Get the previous one (that didn't bust). Should rewrite that anyway */ - i--; - for (j=0;j>1; for (j=0;j total< total<bits[j][pulses[j]] < bits[j]) + if (alloc->bits[j][pulses[j]] < bits[j] && pulses[j]bits[j][pulses[j]+1]-alloc->bits[j][pulses[j]] <= total<bits[j][pulses[j]+1]-alloc->bits[j][pulses[j]]; pulses[j] += 1; incremented = 1; + //printf ("INCREMENT %d\n", j); } } } @@ -303,23 +225,61 @@ int interp_bits2pulses(const struct alloc_data *alloc, int *bits1, int *bits2, i } return (out+BITROUND) >> BITRES; } -#endif + +int compute_allocation(const struct alloc_data *alloc, int *offsets, int total, int *pulses) +{ + int lo, hi, len; + const CELTMode *m; + + m = alloc->mode; + len = m->nbEBands; + lo = 0; + hi = m->nbAllocVectors - 1; + while (hi-lo != 1) + { + int j; + int bits[len]; + int pulses[len]; + int mid = (lo+hi) >> 1; + for (j=0;jallocVectors[mid*len+j] + offsets[j])<bands, bits, pulses, len) > total<allocVectors[lo*len+j] + offsets[j]; + bits2[j] = m->allocVectors[hi*len+j] + offsets[j]; + if (bits1[j] < 0) + bits1[j] = 0; + if (bits2[j] < 0) + bits2[j] = 0; + } + return interp_bits2pulses(alloc, bits1, bits2, total, pulses, len); + } +} #if 0 int main() { int i; - /*for(i=1;i<2000000000;i+=1738) + printf ("log(128) = %d\n", EC_ILOG(128)); + for(i=1;i<2000000000;i+=1738) { - printf ("%d %d\n", i, frac_log2(i, 10)); - }*/ - for (i=4;i<=32;i*=2) - { - int j; - for (j=0;j<30;j++) - { - printf ("%d %d %d\n", i, j, bits2pulses(j,i)); - } + printf ("%d %d\n", i, log2_frac(i, 10)); } return 0; } @@ -328,6 +288,7 @@ int main() int main() { int i; + int offsets[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int bits[18] = {10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 10, 8, 9, 10, 11, 6, 7}; int bits1[18] = {8, 7, 7, 6, 6, 6, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}; int bits2[18] = {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}; @@ -336,12 +297,14 @@ int main() struct alloc_data alloc; alloc_init(&alloc, celt_mode0); - int b = vec_bits2pulses(&alloc, bank, bits, pulses, 18, 1); - printf ("total: %d bits\n", b); - for (i=0;i<18;i++) - printf ("%d ", pulses[i]); - printf ("\n"); - b = interp_bits2pulses(&alloc, bits1, bits2, 162, pulses, 18, 1); + int b; + //b = vec_bits2pulses(&alloc, bank, bits, pulses, 18); + //printf ("total: %d bits\n", b); + //for (i=0;i<18;i++) + // printf ("%d ", pulses[i]); + //printf ("\n"); + //b = interp_bits2pulses(&alloc, bits1, bits2, 162, pulses, 18); + b = compute_allocation(&alloc, offsets, 190, pulses); printf ("total: %d bits\n", b); for (i=0;i<18;i++) printf ("%d ", pulses[i]); diff --git a/libcelt/rate.h b/libcelt/rate.h index 7867097c..4ec1a735 100644 --- a/libcelt/rate.h +++ b/libcelt/rate.h @@ -1,13 +1,49 @@ -// -// C++ Interface: rate -// -// Description: -// -// -// Author: Jean-Marc Valin , (C) 2008 -// -// Copyright: See COPYING file that comes with this distribution -// -// -int compute_allocation(const CELTMode *m, int *pulses); +/* (C) 2007 Jean-Marc Valin, CSIRO +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef RATE_H +#define RATE_H + +struct alloc_data { + const CELTMode *mode; + int len; + const int *bands; + int **bits; +}; +void alloc_init(struct alloc_data *alloc, const CELTMode *m); + +void alloc_clear(struct alloc_data *alloc); + + +int compute_allocation(const struct alloc_data *alloc, int *offsets, int total, int *pulses); + + +#endif