|
Packit |
664db3 |
/* (C) 2007-2008 Jean-Marc Valin, CSIRO
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
/*
|
|
Packit |
664db3 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
664db3 |
modification, are permitted provided that the following conditions
|
|
Packit |
664db3 |
are met:
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions of source code must retain the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions in binary form must reproduce the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
664db3 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Neither the name of the Xiph.org Foundation nor the names of its
|
|
Packit |
664db3 |
contributors may be used to endorse or promote products derived from
|
|
Packit |
664db3 |
this software without specific prior written permission.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
664db3 |
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
664db3 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
664db3 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
|
Packit |
664db3 |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
Packit |
664db3 |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
Packit |
664db3 |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
Packit |
664db3 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
Packit |
664db3 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
Packit |
664db3 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
Packit |
664db3 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
664db3 |
#include "config.h"
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include "quant_pitch.h"
|
|
Packit |
664db3 |
#include <math.h>
|
|
Packit |
664db3 |
#include "pgain_table.h"
|
|
Packit |
664db3 |
#include "arch.h"
|
|
Packit |
664db3 |
#include "mathops.h"
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifdef FIXED_POINT
|
|
Packit |
664db3 |
#define PGAIN_ODD(codebook, i) ((celt_word16_t)(((codebook)[(i)]&0x00ffU)<<7))
|
|
Packit |
664db3 |
#define PGAIN_EVEN(codebook, i) ((celt_word16_t)(((codebook)[(i)]&0xff00U)>>1))
|
|
Packit |
664db3 |
#define PGAIN_ODD14(codebook, i) ((celt_word16_t)(((codebook)[(i)]&0x00ffU)<<6))
|
|
Packit |
664db3 |
#define PGAIN_EVEN14(codebook, i) ((celt_word16_t)(((codebook)[(i)]&0xff00U)>>2))
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#else
|
|
Packit |
664db3 |
#define PGAIN_ODD(codebook, i) ((1.f/32768.f)*(celt_word16_t)(((codebook)[(i)]&0x00ffU)<<7))
|
|
Packit |
664db3 |
#define PGAIN_EVEN(codebook, i) ((1.f/32768.f)*(celt_word16_t)(((codebook)[(i)]&0xff00U)>>1) )
|
|
Packit |
664db3 |
#define PGAIN_ODD14(codebook, i) PGAIN_ODD(codebook, i)
|
|
Packit |
664db3 |
#define PGAIN_EVEN14(codebook, i) PGAIN_EVEN(codebook, i)
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#define PGAIN(codebook, i) ((i)&1 ? PGAIN_ODD(codebook, (i)>>1) : PGAIN_EVEN(codebook, (i)>>1))
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#define Q1515ONE MULT16_16(Q15ONE,Q15ONE)
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/** Taken from Speex.Finds the index of the entry in a codebook that best matches the input*/
|
|
Packit |
664db3 |
int vq_index(const celt_pgain_t *in, const celt_uint16_t *codebook, int len, int entries)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int i,j;
|
|
Packit |
664db3 |
int ind = 0;
|
|
Packit |
664db3 |
celt_word32_t min_dist=VERY_LARGE32;
|
|
Packit |
664db3 |
int best_index=0;
|
|
Packit |
664db3 |
for (i=0;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
celt_word32_t dist=0;
|
|
Packit |
664db3 |
const celt_pgain_t *inp = in;
|
|
Packit |
664db3 |
j=0; do {
|
|
Packit |
664db3 |
celt_pgain_t tmp1 = SUB16(*inp++,PGAIN_EVEN14(codebook, ind));
|
|
Packit |
664db3 |
celt_pgain_t tmp2 = SUB16(*inp++,PGAIN_ODD14(codebook, ind));
|
|
Packit |
664db3 |
ind++;
|
|
Packit |
664db3 |
dist = MAC16_16(dist, tmp1, tmp1);
|
|
Packit |
664db3 |
dist = MAC16_16(dist, tmp2, tmp2);
|
|
Packit |
664db3 |
} while (++j<len>>1);
|
|
Packit |
664db3 |
if (dist
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
min_dist=dist;
|
|
Packit |
664db3 |
best_index=i;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
return best_index;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
int quant_pitch(celt_pgain_t *gains, int len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int i, id;
|
|
Packit |
664db3 |
celt_word32_t gain_sum = 0;
|
|
Packit |
664db3 |
/*for (i=0;i
|
|
Packit |
664db3 |
/* Convert to a representation where the MSE criterion should be near-optimal */
|
|
Packit |
664db3 |
for (i=0;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
gains[i] = SHR16(Q15ONE-celt_sqrt(Q1515ONE-MULT16_16(gains[i],gains[i])),1);
|
|
Packit |
664db3 |
gain_sum = ADD32(gain_sum, EXTEND32(gains[i]));
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
/* Is it worth encoding the pitch? */
|
|
Packit |
664db3 |
if (gain_sum > QCONST32(.3f,15))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
id = vq_index(gains, pgain_table, len, 128);
|
|
Packit |
664db3 |
/* FIXME: Remove when we're not waisting a transmitted index on 0 gains */
|
|
Packit |
664db3 |
if (id==0)
|
|
Packit |
664db3 |
id = -1;
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
id = -1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
return id;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/** Returns the pitch gain vector corresponding to a certain id */
|
|
Packit |
664db3 |
void unquant_pitch(int id, celt_pgain_t *gains, int len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int i;
|
|
Packit |
664db3 |
for (i=0;i
|
|
Packit |
664db3 |
gains[i] = celt_sqrt(Q1515ONE-MULT16_16(Q15ONE-PGAIN(pgain_table,id*len+i),Q15ONE-PGAIN(pgain_table,id*len+i)));
|
|
Packit |
664db3 |
}
|