You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

195 lines
9.7 KiB

/*
adaptativeCodebookSearch.c
Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author : Johan Pascal
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "typedef.h"
#include "codecParameters.h"
#include "basicOperationsMacros.h"
#include "utils.h"
#include "codebooks.h"
#include <string.h>
#include "adaptativeCodebookSearch.h"
/*** local functions ***/
void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay);
/*****************************************************************************/
/* adaptativeCodebookSearch: compute parameter P1 and P2 as in spec A.3.7 */
/* compute also adaptative codebook vector as in spec 3.7.1 */
/* parameters: */
/* -(i/o) excitationVector: [-154,0[ previous excitation as input */
/* Range [0,39[ */
/* 40 words of LPResidualSignal as substitute for current */
/* excitation (spec A.3.7) as input */
/* 40 words of adaptative codebook vector in Q0 as output */
/* Buffer in Q0 accessed in range [-154, 39] */
/* -(i/o) intPitchDelayMin: low boundary for pitch delay search */
/* -(i/o) intPitchDelayMax: low boundary for pitch delay search */
/* Boundaries are updated during first subframe search */
/* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */
/* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */
/* */
/* -(o) intPitchDelay: the integer pitch delay */
/* -(o) fracPitchDelay: the fractionnal part of pitch delay */
/* -(o) pitchDelayCodeword: P1 or P2 codeword as in spec 3.7.2 */
/* -(o) adaptativeCodebookVector: 40 words of adaptative codebook vector*/
/* as described in spec 3.7.1, in Q0. */
/* -(i) subFrameIndex: 0 for the first subframe, 40 for the second */
/* */
/*****************************************************************************/
void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDelayMin, int16_t *intPitchDelayMax, word16_t impulseResponse[], word16_t targetSignal[],
int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex)
{
int i,j;
word32_t backwardFilteredTargetSignal[L_SUBFRAME];
word32_t correlationMax = MININT32;
/* compute the backward Filtered Target Signal as specified in A.3.7: correlation of target signal and impulse response */
correlateVectors(targetSignal, impulseResponse, backwardFilteredTargetSignal); /* targetSignal in Q0, impulseResponse in Q12 -> backwardFilteredTargetSignal in Q12 */
/* maximise the sum as in spec A.3.7, eq A.7 */
for (i=*intPitchDelayMin; i<=*intPitchDelayMax; i++) {
word32_t correlation = 0;
for (j=0; j<L_SUBFRAME; j++) {
correlation = MAC16_32_Q12(correlation, excitationVector[j-i], backwardFilteredTargetSignal[j]);
}
if (correlation>correlationMax) {
correlationMax=correlation;
*intPitchDelay = i;
}
}
/* compute the adaptativeCodebookVector (with fracPitchDelay at 0) */
/* output is in excitationVector[0,L_SUBRAME[ */
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 0);
/* if we are at first subframe and intPitchDelay >= 85 -> do not compute fracPitchDelay, set it to 0 */
*fracPitchDelay=0;
if (!(subFrameIndex==0 && *intPitchDelay>=85)) {
/* compute the fracPitchDelay*/
word16_t adaptativeCodebookVector[L_SUBFRAME]; /* as the adaptativeCodebookVector is computed in the excitation vector, use this buffer to backup the one giving the highest numerator */
word32_t correlation=0;
/* search the fractionnal part to get the best correlation */
/* we already have in excitationVector for fracPitchDelay = 0 the adaptativeCodebookVector (see specA.3.7) */
correlationMax = 0;
for (i=0; i<L_SUBFRAME; i++) {
correlationMax = MAC16_32_Q12(correlationMax, excitationVector[i], backwardFilteredTargetSignal[i]);
}
/* backup the adaptativeCodebookVector */
memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t));
/* Fractionnal part = -1 */
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, -1);
for (i=0; i<L_SUBFRAME; i++) {
correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]);
}
if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */
*fracPitchDelay=-1;
correlationMax = correlation;
/* backup the adaptativeCodebookVector */
memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t));
}
/* Fractionnal part = 1 */
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 1);
correlation=0;
for (i=0; i<L_SUBFRAME; i++) {
correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]);
}
if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */
*fracPitchDelay=1;
} else { /* previously computed fractional part gives better result */
/* restore the adaptativeCodebookVector*/
memcpy(excitationVector, adaptativeCodebookVector, L_SUBFRAME*sizeof(word16_t));
}
}
/* compute the codeword and intPitchDelayMin/intPitchDelayMax if needed (first subframe only) */
if (subFrameIndex==0) { /* first subframe */
/* compute intPitchDelayMin/intPitchDelayMax as in spec A.3.7 */
*intPitchDelayMin = *intPitchDelay - 5;
if (*intPitchDelayMin < 20) {
*intPitchDelayMin = 20;
}
*intPitchDelayMax = *intPitchDelayMin + 9;
if (*intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) {
*intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY;
*intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 9;
}
/* compute the codeword as in spec 3.7.2 */
if (*intPitchDelay<=85) {
*pitchDelayCodeword = 3*(*intPitchDelay) - 58 + *fracPitchDelay;
} else {
*pitchDelayCodeword = *intPitchDelay + 112;
}
} else { /* second subframe */
/* compute the codeword as in spec 3.7.2 */
*pitchDelayCodeword = 3*(*intPitchDelay-*intPitchDelayMin) + *fracPitchDelay +2;
}
}
/*****************************************************************************/
/* generateAdaptativeCodebookVector : according to spec 3.7.1 eq40: */
/* generates the adaptative codebook vector by interpolation of past */
/* excitation */
/* Note : specA.3.7 mention that excitation vector in range [0,39[ being */
/* unknown is replaced by LP Residual signal, the ITU code use this */
/* buffer to store the adaptative codebok vector and then use it in case*/
/* of intPitchDelay<40. */
/* parameters : */
/* -(i/o) excitationVector: in Q0 the past excitation vector accessed */
/* [-154,0[. Range [0,39[ is the output in Q0 */
/* -(i) intPitchDelay: the integer pitch delay used to access the past */
/* excitation */
/* -(i) fracPitchDelay: fractional part of the pitch delay: -1, 0 or 1 */
/* */
/*****************************************************************************/
void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay)
{
int n,i,j;
word16_t *delayedExcitationVector;
word16_t *b30Increased;
word16_t *b30Decreased;
/* fracPitchDelay is in range [-1, 1], convert it to [0,2] needed by eqA.8 */
fracPitchDelay = -fracPitchDelay;
if (fracPitchDelay <0) { /* if fracPitchDelay is 1 -> pitchDelay of int+(1/3) -> int+1-(2/3)*/
intPitchDelay++;
fracPitchDelay = 2;
}
/**/
delayedExcitationVector = &(excitationVector[-intPitchDelay]); /* delayedExcitationVector is used to address the excitation vector at index -intPitchDelay (-k in eq40) */
b30Increased = &(b30[fracPitchDelay]); /* b30 increased points to b30[fracPitchDelay] : b30[t] in eq40. b30 in Q15 */
b30Decreased = &(b30[3-fracPitchDelay]); /* b30 decreased points to b30[-fracPitchDelay] : b30[3-t] in eq40. b30 in Q15 */
for (n=0; n<L_SUBFRAME; n++) {
word32_t acc = 0; /* acc in Q15 */
for (i=0, j=0; i<10; i++, j+=3) { /* j is used as a 3*i index */
acc = MAC16_16(acc, delayedExcitationVector[n-i], b30Increased[j]); /* WARNING: spec 3.7.1 and A.8 give an equation leading to delayedExcitationVector[n+i] but ITU code uses delayedExcitationVector[n-i], implemented as code */
acc = MAC16_16(acc, delayedExcitationVector[n+1+i], b30Decreased[j]);
}
excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */
}
}