FreeCalypso > hg > gsm-codec-lib
diff libtwamr/bgnscd.c @ 308:8dfb7cbe6b59
libtwamr: integrated up to bgnscd.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 16 Apr 2024 17:57:21 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtwamr/bgnscd.c Tue Apr 16 17:57:21 2024 +0000 @@ -0,0 +1,229 @@ +/************************************************************************* +* +* GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 +* R99 Version 3.3.0 +* REL-4 Version 4.1.0 +* +******************************************************************************** +* +* File : bgnscd.c +* Purpose : Background noise source charateristic detector (SCD) +* +******************************************************************************** +*/ + +/* +******************************************************************************** +* MODULE INCLUDE FILE AND VERSION ID +******************************************************************************** +*/ +#include "namespace.h" +#include "bgnscd.h" + +#include "typedef.h" +#include "basic_op.h" +#include "no_count.h" +#include "cnst.h" +#include "memops.h" +#include "gmed_n.h" +#include "sqrt_l.h" + +/* +******************************************************************************** +* LOCAL VARIABLES AND TABLES +******************************************************************************** +*/ +/*-----------------------------------------------------------------* + * Decoder constant parameters (defined in "cnst.h") * + *-----------------------------------------------------------------* + * L_FRAME : Frame size. * + * L_SUBFR : Sub-frame size. * + *-----------------------------------------------------------------*/ + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ +/* +************************************************************************** +* +* Function : Bgn_scd_reset +* Purpose : Resets state memory +* +************************************************************************** +*/ +void Bgn_scd_reset (Bgn_scdState *state) +{ + /* Static vectors to zero */ + Set_zero (state->frameEnergyHist, L_ENERGYHIST); + + /* Initialize hangover handling */ + state->bgHangover = 0; +} + +/* +************************************************************************** +* +* Function : Bgn_scd +* Purpose : Charaterice synthesis speech and detect background noise +* Returns : background noise decision; 0 = no bgn, 1 = bgn +* +************************************************************************** +*/ +Word16 Bgn_scd (Bgn_scdState *st, /* i : State variables for bgn SCD */ + Word16 ltpGainHist[], /* i : LTP gain history */ + Word16 speech[], /* o : synthesis speech frame */ + Word16 *voicedHangover /* o : # of frames after last + voiced frame */ + ) +{ + Word16 i; + Word16 prevVoiced, inbgNoise; + Word16 temp; + Word16 ltpLimit, frameEnergyMin; + Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart; + Word32 s; + + /* Update the inBackgroundNoise flag (valid for use in next frame if BFI) */ + /* it now works as a energy detector floating on top */ + /* not as good as a VAD. */ + + currEnergy = 0; move16 (); + s = (Word32) 0; move32 (); + + for (i = 0; i < L_FRAME; i++) + { + s = L_mac (s, speech[i], speech[i]); + } + + s = L_shl(s, 2); + + currEnergy = extract_h (s); + + frameEnergyMin = 32767; move16 (); + + for (i = 0; i < L_ENERGYHIST; i++) + { + test (); + if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0) + frameEnergyMin = st->frameEnergyHist[i]; move16 (); + } + + noiseFloor = shl (frameEnergyMin, 4); /* Frame Energy Margin of 16 */ + + maxEnergy = st->frameEnergyHist[0]; move16 (); + for (i = 1; i < L_ENERGYHIST-4; i++) + { + test (); + if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0) + { + maxEnergy = st->frameEnergyHist[i]; move16 (); + } + } + + maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3]; move16 (); + for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++) + { + test (); + if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0) + { + maxEnergyLastPart = st->frameEnergyHist[i]; move16 (); + } + } + + inbgNoise = 0; /* false */ move16 (); + + /* Do not consider silence as noise */ + /* Do not consider continuous high volume as noise */ + /* Or if the current noise level is very low */ + /* Mark as noise if under current noise limit */ + /* OR if the maximum energy is below the upper limit */ + + test (); test (); test (); test (); test (); + if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) && + (sub(currEnergy, FRAMEENERGYLIMIT) < 0) && + (sub(currEnergy, LOWERNOISELIMIT) > 0) && + ( (sub(currEnergy, noiseFloor) < 0) || + (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0))) + { + test (); + if (sub(add(st->bgHangover, 1), 30) > 0) + { + st->bgHangover = 30; move16 (); + } else + { + st->bgHangover = add(st->bgHangover, 1); + } + } + else + { + st->bgHangover = 0; move16 (); + } + + /* make final decision about frame state , act somewhat cautiosly */ + test (); + if (sub(st->bgHangover,1) > 0) + inbgNoise = 1; /* true */ move16 (); + + for (i = 0; i < L_ENERGYHIST-1; i++) + { + st->frameEnergyHist[i] = st->frameEnergyHist[i+1]; move16 (); + } + st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy; move16 (); + + /* prepare for voicing decision; tighten the threshold after some + time in noise */ + ltpLimit = 13926; /* 0.85 Q14 */ move16 (); + test (); + if (sub(st->bgHangover, 8) > 0) + { + ltpLimit = 15565; /* 0.95 Q14 */ move16 (); + } + test (); + if (sub(st->bgHangover, 15) > 0) + { + ltpLimit = 16383; /* 1.00 Q14 */ move16 (); + } + + /* weak sort of voicing indication. */ + prevVoiced = 0; /* false */ move16 (); + test (); + + if (sub(gmed_n(<pGainHist[4], 5), ltpLimit) > 0) + { + prevVoiced = 1; /* true */ move16 (); + } + test (); + if (sub(st->bgHangover, 20) > 0) { + if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0) + { + prevVoiced = 1; /* true */ move16 (); + } + else + { + prevVoiced = 0; /* false */ move16 (); + } + } + + test (); + if (prevVoiced) + { + *voicedHangover = 0; move16 (); + } + else + { + temp = add(*voicedHangover, 1); + test (); + if (sub(temp, 10) > 0) + { + *voicedHangover = 10; move16 (); + } + else + { + *voicedHangover = temp; move16 (); + } + } + + return inbgNoise; +}