blob: 18e2df98dc95d5b731579abb80375ea4f6c0f3e2 [file] [log] [blame]
Jean-Marc Valin41af4212007-11-30 18:35:37 +11001/* (C) 2007 Jean-Marc Valin, CSIRO
2*/
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
32#include <math.h>
33#include <stdlib.h>
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110034#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110035#include "vq.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110036
37/* Algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch
38 a combination of pulses such that its norm is still equal to 1 */
39void alg_quant(float *x, int N, int K, float *p)
40{
41 float y[N];
42 int i,j;
43 float xy = 0;
44 float yy = 0;
45 float yp = 0;
46 float Rpp=0;
47 float gain=0;
48 for (j=0;j<N;j++)
49 Rpp += p[j]*p[j];
50 for (i=0;i<N;i++)
51 y[i] = 0;
52
53 for (i=0;i<K;i++)
54 {
55 int best_id=0;
56 float max_val=-1e10;
57 float best_xy=0, best_yy=0, best_yp = 0;
58 for (j=0;j<N;j++)
59 {
60 float tmp_xy, tmp_yy, tmp_yp;
61 float score;
62 float g;
63 tmp_xy = xy + fabs(x[j]);
64 tmp_yy = yy + 2*fabs(y[j]) + 1;
65 if (x[j]>0)
66 tmp_yp = yp + p[j];
67 else
68 tmp_yp = yp - p[j];
69 g = (sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)/tmp_yy;
70 score = 2*g*tmp_xy - g*g*tmp_yy;
71 if (score>max_val)
72 {
73 max_val = score;
74 best_id = j;
75 best_xy = tmp_xy;
76 best_yy = tmp_yy;
77 best_yp = tmp_yp;
78 gain = g;
79 }
80 }
81
82 xy = best_xy;
83 yy = best_yy;
84 yp = best_yp;
85 if (x[best_id]>0)
86 y[best_id] += 1;
87 else
88 y[best_id] -= 1;
89 }
90
91 for (i=0;i<N;i++)
92 x[i] = p[i]+gain*y[i];
93
94}
95
96/* Improved algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch
97 a combination of pulses such that its norm is still equal to 1. The only difference with
98 the quantiser above is that the search is more complete. */
Jean-Marc Valin9cace642007-12-06 17:44:09 +110099void alg_quant2(float *x, int N, int K, float *p, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100100{
101 int L = 5;
102 //float tata[200];
103 float y[L][N];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100104 int iy[L][N];
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100105 //float tata2[200];
106 float ny[L][N];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100107 int iny[L][N];
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100108 int i, j, m;
109 float xy[L], nxy[L];
110 float yy[L], nyy[L];
111 float yp[L], nyp[L];
112 float best_scores[L];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100113 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100114 float gain[L];
115 int maxL = 1;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100116 float alpha = .9;
117
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100118 for (j=0;j<N;j++)
119 Rpp += p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100120 for (j=0;j<N;j++)
121 Rxp += x[j]*p[j];
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100122 for (m=0;m<L;m++)
123 for (i=0;i<N;i++)
124 y[m][i] = 0;
125
126 for (m=0;m<L;m++)
127 for (i=0;i<N;i++)
128 ny[m][i] = 0;
129
130 for (m=0;m<L;m++)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100131 for (i=0;i<N;i++)
132 iy[m][i] = iny[m][i] = 0;
133
134 for (m=0;m<L;m++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100135 xy[m] = yy[m] = yp[m] = gain[m] = 0;
136
137 for (i=0;i<K;i++)
138 {
139 int L2 = L;
140 if (L>maxL)
141 {
142 L2 = maxL;
143 maxL *= N;
144 }
145 for (m=0;m<L;m++)
146 best_scores[m] = -1e10;
147
148 for (m=0;m<L2;m++)
149 {
150 for (j=0;j<N;j++)
151 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100152 int sign;
153 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100154 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100155 if (iy[m][j]*sign < 0)
156 continue;
157 //fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);
158 float tmp_xy, tmp_yy, tmp_yp;
159 float score;
160 float g;
161 float s = sign;
162 tmp_xy = xy[m] + s*x[j] - alpha*s*p[j]*Rxp;
163 tmp_yy = yy[m] + 2*s*y[m][j] + 1 +alpha*alpha*p[j]*p[j]*Rpp - 2*alpha*s*p[j]*yp[m] - 2*alpha*p[j]*p[j];
164 tmp_yp = yp[m] + s*p[j] *(1-alpha*Rpp);
165 g = (sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)/tmp_yy;
166 score = 2*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100167
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100168 if (score>best_scores[L-1])
169 {
170 int k, n;
171 int id = L-1;
172 while (id > 0 && score > best_scores[id-1])
173 id--;
174
175 for (k=L-1;k>id;k--)
176 {
177 nxy[k] = nxy[k-1];
178 nyy[k] = nyy[k-1];
179 nyp[k] = nyp[k-1];
180 //fprintf(stderr, "%d %d \n", N, k);
181 for (n=0;n<N;n++)
182 ny[k][n] = ny[k-1][n];
183 for (n=0;n<N;n++)
184 iny[k][n] = iny[k-1][n];
185 gain[k] = gain[k-1];
186 best_scores[k] = best_scores[k-1];
187 }
188
189 nxy[id] = tmp_xy;
190 nyy[id] = tmp_yy;
191 nyp[id] = tmp_yp;
192 gain[id] = g;
193 for (n=0;n<N;n++)
194 ny[id][n] = y[m][n];
195 ny[id][j] += s;
196 for (n=0;n<N;n++)
197 ny[id][n] -= alpha*s*p[j]*p[n];
198
199 for (n=0;n<N;n++)
200 iny[id][n] = iy[m][n];
201 if (s>0)
202 iny[id][j] += 1;
203 else
204 iny[id][j] -= 1;
205 best_scores[id] = score;
206 }
207 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100208 }
209
210 }
211 int k,n;
212 for (k=0;k<L;k++)
213 {
214 xy[k] = nxy[k];
215 yy[k] = nyy[k];
216 yp[k] = nyp[k];
217 for (n=0;n<N;n++)
218 y[k][n] = ny[k][n];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100219 for (n=0;n<N;n++)
220 iy[k][n] = iny[k][n];
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100221 }
222
223 }
224
225 for (i=0;i<N;i++)
226 x[i] = p[i]+gain[0]*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100227 if (0) {
228 float E=1e-15;
229 int ABS = 0;
230 for (i=0;i<N;i++)
231 ABS += abs(iy[0][i]);
232 //if (K != ABS)
233 // printf ("%d %d\n", K, ABS);
234 for (i=0;i<N;i++)
235 E += x[i]*x[i];
236 //printf ("%f\n", E);
237 E = 1/sqrt(E);
238 for (i=0;i<N;i++)
239 x[i] *= E;
240 }
Jean-Marc Valin29ccab82007-12-06 15:39:38 +1100241 int comb[K];
242 int signs[K];
243 pulse2comb(N, K, comb, signs, iy[0]);
Jean-Marc Valin9cace642007-12-06 17:44:09 +1100244 ec_enc_uint(enc,icwrs(N, K, comb, signs),ncwrs(N, K));
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100245}
246
247/* Just replace the band with noise of unit energy */
248void noise_quant(float *x, int N, int K, float *p)
249{
250 int i;
251 float E = 1e-10;
252 for (i=0;i<N;i++)
253 {
254 x[i] = (rand()%1000)/500.-1;
255 E += x[i]*x[i];
256 }
257 E = 1./sqrt(E);
258 for (i=0;i<N;i++)
259 {
260 x[i] *= E;
261 }
262}
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100263
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100264static const float pg[5] = {1.f, .82f, .75f, 0.7f, 0.6f};
265
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100266/* Finds the right offset into Y and copy it */
Jean-Marc Valin9cace642007-12-06 17:44:09 +1100267void copy_quant(float *x, int N, int K, float *Y, int B, int N0, ec_enc *enc)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100268{
269 int i,j;
270 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100271 float best_score=0;
272 float s = 1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100273 float E;
274 for (i=0;i<N0*B-N;i+=B)
275 {
276 int j;
277 float xy=0, yy=0;
278 float score;
279 for (j=0;j<N;j++)
280 {
281 xy += x[j]*Y[i+j];
282 yy += Y[i+j]*Y[i+j];
283 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100284 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100285 if (score > best_score)
286 {
287 best_score = score;
288 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100289 if (xy>0)
290 s = 1;
291 else
292 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100293 }
294 }
Jean-Marc Valin9cace642007-12-06 17:44:09 +1100295 ec_enc_uint(enc,best/B,N0-N/B);
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100296 //printf ("%d %f\n", best, best_score);
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100297 if (K==0)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100298 {
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100299 E = 1e-10;
300 for (j=0;j<N;j++)
301 {
302 x[j] = s*Y[best+j];
303 E += x[j]*x[j];
304 }
305 E = 1/sqrt(E);
306 for (j=0;j<N;j++)
307 x[j] *= E;
308 } else {
309 float P[N];
310 float pred_gain;
311 if (K>4)
312 pred_gain = .5;
313 else
314 pred_gain = pg[K];
315 E = 1e-10;
316 for (j=0;j<N;j++)
317 {
318 P[j] = s*Y[best+j];
319 E += P[j]*P[j];
320 }
321 E = .8/sqrt(E);
322 for (j=0;j<N;j++)
323 P[j] *= E;
Jean-Marc Valin9cace642007-12-06 17:44:09 +1100324 alg_quant2(x, N, K, P, enc);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100325 }
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100326}