1 /* (C) 2007 Jean-Marc Valin, CSIRO
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
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.
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.
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.
42 /* Enable this or define your own implementation if you want to speed up the
43 VQ search (used in inner loop only) */
45 #include <xmmintrin.h>
46 static inline float approx_sqrt(float x)
48 _mm_store_ss(&x, _mm_sqrt_ss(_mm_set_ss(x)));
51 static inline float approx_inv(float x)
53 _mm_store_ss(&x, _mm_rcp_ss(_mm_set_ss(x)));
57 #define approx_sqrt(x) (sqrt(x))
58 #define approx_inv(x) (1.f/(x))
61 /** All the info necessary to keep track of a hypothesis during the search */
73 void alg_quant(float *x, float *W, int N, int K, float *p, float alpha, ec_enc *enc)
89 VARDECL(struct NBest *_nbest);
90 VARDECL(struct NBest **nbest);
94 ALLOC(_y, L*N, float);
95 ALLOC(_ny, L*N, float);
97 ALLOC(_iny, L*N, int);
98 ALLOC(y, L*N, float*);
99 ALLOC(ny, L*N, float*);
100 ALLOC(iy, L*N, int*);
101 ALLOC(iny, L*N, int*);
106 ALLOC(_nbest, L, struct NBest);
107 ALLOC(nbest, L, struct NBest *);
110 nbest[m] = &_nbest[m];
126 /* We only need to initialise the zero because the first iteration only uses that */
131 xy[0] = yy[0] = yp[0] = 0;
134 while (pulsesLeft > 0)
140 /* Decide on complexity strategy */
141 pulsesAtOnce = pulsesLeft/N;
144 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
146 /*printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);*/
154 for (m=0;m<Lupdate;m++)
155 nbest[m]->score = -1e10f;
162 /*if (x[j]>0) sign=1; else sign=-1;*/
163 for (sign=-1;sign<=1;sign+=2)
165 /*fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);*/
166 float tmp_xy, tmp_yy, tmp_yp;
169 float s = sign*pulsesAtOnce;
171 /* All pulses at one location must have the same sign. */
172 if (iy[m][j]*sign < 0)
175 /* Updating the sums of the new pulse(s) */
176 tmp_xy = xy[m] + s*x[j] - alpha*s*p[j]*Rxp;
177 tmp_yy = yy[m] + 2.f*s*y[m][j] + s*s +s*s*alpha*alpha*p[j]*p[j]*Rpp - 2.f*alpha*s*p[j]*yp[m] - 2.f*s*s*alpha*p[j]*p[j];
178 tmp_yp = yp[m] + s*p[j] *(1.f-alpha*Rpp);
180 /* Compute the gain such that ||p + g*y|| = 1 */
181 g = (approx_sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)*approx_inv(tmp_yy);
182 /* Knowing that gain, what the error: (x-g*y)^2
183 (result is negated and we discard x^2 because it's constant) */
184 score = 2.f*g*tmp_xy - g*g*tmp_yy;
186 if (score>nbest[Lupdate-1]->score)
190 struct NBest *tmp_best;
192 /* Save some pointers that would be deleted and use them for the current entry*/
193 tmp_best = nbest[Lupdate-1];
194 while (id > 0 && score > nbest[id-1]->score)
197 for (k=Lupdate-1;k>id;k--)
198 nbest[k] = nbest[k-1];
200 nbest[id] = tmp_best;
201 nbest[id]->score = score;
204 nbest[id]->sign = sign;
206 nbest[id]->xy = tmp_xy;
207 nbest[id]->yy = tmp_yy;
208 nbest[id]->yp = tmp_yp;
214 /* Only now that we've made the final choice, update ny/iny and others */
215 for (k=0;k<Lupdate;k++)
220 is = nbest[k]->sign*pulsesAtOnce;
223 ny[k][n] = y[nbest[k]->orig][n] - alpha*s*p[nbest[k]->pos]*p[n];
224 ny[k][nbest[k]->pos] += s;
227 iny[k][n] = iy[nbest[k]->orig][n];
228 iny[k][nbest[k]->pos] += is;
230 xy[k] = nbest[k]->xy;
231 yy[k] = nbest[k]->yy;
232 yp[k] = nbest[k]->yp;
234 /* Swap ny/iny with y/iy */
235 for (k=0;k<Lupdate;k++)
247 pulsesLeft -= pulsesAtOnce;
253 err += (x[i]-nbest[0]->gain*y[0][i])*(x[i]-nbest[0]->gain*y[0][i]);
255 printf ("%f %d %d\n", err, K, N);*/
258 x[i] = p[i]+nbest[0]->gain*y[0][i];
259 /* Sanity checks, don't bother */
264 ABS += abs(iy[0][i]);
266 printf ("%d %d\n", K, ABS);*/
269 /*printf ("%f\n", E);*/
275 encode_pulses(iy[0], N, K, enc);
277 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
278 due to the recursive computation used in quantisation.
279 Not quite sure whether we need that or not */
286 Ryp += iy[0][i]*p[i];
289 y[0][i] = iy[0][i] - alpha*Ryp*p[i];
296 Ryy += y[0][i]*y[0][i];
298 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
301 x[i] = p[i] + g*y[0][i];
307 /** Decode pulse vector and combine the result with the pitch vector to produce
308 the final normalised signal in the current band. */
309 void alg_unquant(float *x, int N, int K, float *p, float alpha, ec_dec *dec)
312 float Rpp=0, Ryp=0, Ryy=0;
320 decode_pulses(iy, N, K, dec);
323 printf ("%d ", iy[i]);*/
331 y[i] = iy[i] - alpha*Ryp*p[i];
333 /* Recompute after the projection (I think it's right) */
341 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
344 x[i] = p[i] + g*y[i];
348 static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
350 void intra_prediction(float *x, float *W, int N, int K, float *Y, float *P, int B, int N0, ec_enc *enc)
359 int max_pos = N0-N/B;
363 for (i=0;i<max_pos*B;i+=B)
373 score = xy*xy/(.001+yy);
374 if (score > best_score)
388 /*printf ("%d %d ", sign, best);*/
389 ec_enc_uint(enc,sign,2);
390 ec_enc_uint(enc,best/B,max_pos);
391 /*printf ("%d %f\n", best, best_score);*/
403 E = pred_gain/sqrt(E);
414 /*printf ("quant ");*/
415 /*for (j=0;j<N;j++) printf ("%f ", P[j]);*/
419 void intra_unquant(float *x, int N, int K, float *Y, float *P, int B, int N0, ec_dec *dec)
427 int max_pos = N0-N/B;
431 sign = ec_dec_uint(dec, 2);
437 best = B*ec_dec_uint(dec, max_pos);
438 /*printf ("%d %d ", sign, best);*/
450 E = pred_gain/sqrt(E);
460 void intra_fold(float *x, int N, float *Y, float *P, int B, int N0, int Nmax)
472 P[j*B+i] = Y[(Nmax-N0-j-1)*B+i];
473 E += P[j*B+i]*P[j*B+i];