diff options
author | Jean-Marc Valin <Jean-Marc.Valin@csiro.au> | 2007-11-30 10:35:37 +0300 |
---|---|---|
committer | Jean-Marc Valin <Jean-Marc.Valin@csiro.au> | 2007-11-30 10:35:37 +0300 |
commit | 41af42154017e323707018d5f46feaea538da7b8 (patch) | |
tree | aa9186bcc35ddf5d326e9457110b6bfeb4fcc217 /libcelt/vq.c | |
parent | 3c453121d2b2daaa2af47d99b9cbe5027611383f (diff) |
Oops, forgot to add the Ghost/ceft vq files
Diffstat (limited to 'libcelt/vq.c')
-rw-r--r-- | libcelt/vq.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/libcelt/vq.c b/libcelt/vq.c new file mode 100644 index 0000000..7be9144 --- /dev/null +++ b/libcelt/vq.c @@ -0,0 +1,220 @@ +/* (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. +*/ + +#include <math.h> +#include <stdlib.h> + +/* Algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch + a combination of pulses such that its norm is still equal to 1 */ +void alg_quant(float *x, int N, int K, float *p) +{ + float y[N]; + int i,j; + float xy = 0; + float yy = 0; + float yp = 0; + float Rpp=0; + float gain=0; + for (j=0;j<N;j++) + Rpp += p[j]*p[j]; + for (i=0;i<N;i++) + y[i] = 0; + + for (i=0;i<K;i++) + { + int best_id=0; + float max_val=-1e10; + float best_xy=0, best_yy=0, best_yp = 0; + for (j=0;j<N;j++) + { + float tmp_xy, tmp_yy, tmp_yp; + float score; + float g; + tmp_xy = xy + fabs(x[j]); + tmp_yy = yy + 2*fabs(y[j]) + 1; + if (x[j]>0) + tmp_yp = yp + p[j]; + else + tmp_yp = yp - p[j]; + g = (sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)/tmp_yy; + score = 2*g*tmp_xy - g*g*tmp_yy; + if (score>max_val) + { + max_val = score; + best_id = j; + best_xy = tmp_xy; + best_yy = tmp_yy; + best_yp = tmp_yp; + gain = g; + } + } + + xy = best_xy; + yy = best_yy; + yp = best_yp; + if (x[best_id]>0) + y[best_id] += 1; + else + y[best_id] -= 1; + } + + for (i=0;i<N;i++) + x[i] = p[i]+gain*y[i]; + +} + +/* Improved algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch + a combination of pulses such that its norm is still equal to 1. The only difference with + the quantiser above is that the search is more complete. */ +void alg_quant2(float *x, int N, int K, float *p) +{ + int L = 5; + //float tata[200]; + float y[L][N]; + //float tata2[200]; + float ny[L][N]; + int i, j, m; + float xy[L], nxy[L]; + float yy[L], nyy[L]; + float yp[L], nyp[L]; + float best_scores[L]; + float Rpp=0; + float gain[L]; + int maxL = 1; + for (j=0;j<N;j++) + Rpp += p[j]*p[j]; + for (m=0;m<L;m++) + for (i=0;i<N;i++) + y[m][i] = 0; + + for (m=0;m<L;m++) + for (i=0;i<N;i++) + ny[m][i] = 0; + + for (m=0;m<L;m++) + xy[m] = yy[m] = yp[m] = gain[m] = 0; + + for (i=0;i<K;i++) + { + int L2 = L; + if (L>maxL) + { + L2 = maxL; + maxL *= N; + } + for (m=0;m<L;m++) + best_scores[m] = -1e10; + + for (m=0;m<L2;m++) + { + for (j=0;j<N;j++) + { + //fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N); + float tmp_xy, tmp_yy, tmp_yp; + float score; + float g; + tmp_xy = xy[m] + fabs(x[j]); + tmp_yy = yy[m] + 2*fabs(y[m][j]) + 1; + if (x[j]>0) + tmp_yp = yp[m] + p[j]; + else + tmp_yp = yp[m] - p[j]; + g = (sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)/tmp_yy; + score = 2*g*tmp_xy - g*g*tmp_yy; + + if (score>best_scores[L-1]) + { + int k, n; + int id = L-1; + while (id > 0 && score > best_scores[id-1]) + id--; + + for (k=L-1;k>id;k--) + { + nxy[k] = nxy[k-1]; + nyy[k] = nyy[k-1]; + nyp[k] = nyp[k-1]; + //fprintf(stderr, "%d %d \n", N, k); + for (n=0;n<N;n++) + ny[k][n] = ny[k-1][n]; + gain[k] = gain[k-1]; + best_scores[k] = best_scores[k-1]; + } + + nxy[id] = tmp_xy; + nyy[id] = tmp_yy; + nyp[id] = tmp_yp; + gain[id] = g; + for (n=0;n<N;n++) + ny[id][n] = y[m][n]; + if (x[j]>0) + ny[id][j] += 1; + else + ny[id][j] -= 1; + best_scores[id] = score; + } + + } + + } + int k,n; + for (k=0;k<L;k++) + { + xy[k] = nxy[k]; + yy[k] = nyy[k]; + yp[k] = nyp[k]; + for (n=0;n<N;n++) + y[k][n] = ny[k][n]; + } + + } + + for (i=0;i<N;i++) + x[i] = p[i]+gain[0]*y[0][i]; + +} + +/* Just replace the band with noise of unit energy */ +void noise_quant(float *x, int N, int K, float *p) +{ + int i; + float E = 1e-10; + for (i=0;i<N;i++) + { + x[i] = (rand()%1000)/500.-1; + E += x[i]*x[i]; + } + E = 1./sqrt(E); + for (i=0;i<N;i++) + { + x[i] *= E; + } +} |