feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
This commit is contained in:
1 parent
89715d1813
commit
4a2d276881
100 files changed
+11319
No files matched your search
@@ -0,0 +1,247 @@
|
||||
package amrnb
|
||||
|
||||
// Closed-loop fractional pitch search, ported from opencore-amrnb pitch_fr.cpp
|
||||
// (Pitch_fr, Norm_Corr, searchFrac, getRange) and inter_36.cpp (Interpol_3or6).
|
||||
// pitchFr refines the open-loop lag: it builds the normalized correlation of the
|
||||
// target with the filtered adaptive excitation over an integer search range,
|
||||
// picks the best integer lag, then interpolates to a fractional lag, and encodes
|
||||
// the result with encLag3/encLag6. Bit-exact with the reference.
|
||||
|
||||
const cL_INTER_SRCH = 4 // closed-loop pitch search interpolation half-length
|
||||
|
||||
// mode-dependent search parameters (pitch_fr.cpp mode_dep_parm), indexed by the
|
||||
// internal speech mode 0..7.
|
||||
var modeDepParm = [8]struct {
|
||||
maxFracLag, flag3, firstFrac, lastFrac int16
|
||||
deltaIntLow, deltaIntRange, deltaFrcLow int16
|
||||
deltaFrcRange, pitMin int16
|
||||
}{
|
||||
{84, 1, -2, 2, 5, 10, 5, 9, cPIT_MIN}, // MR475
|
||||
{84, 1, -2, 2, 5, 10, 5, 9, cPIT_MIN}, // MR515
|
||||
{84, 1, -2, 2, 3, 6, 5, 9, cPIT_MIN}, // MR59
|
||||
{84, 1, -2, 2, 3, 6, 5, 9, cPIT_MIN}, // MR67
|
||||
{84, 1, -2, 2, 3, 6, 5, 9, cPIT_MIN}, // MR74
|
||||
{84, 1, -2, 2, 3, 6, 10, 19, cPIT_MIN}, // MR795
|
||||
{84, 1, -2, 2, 3, 6, 5, 9, cPIT_MIN}, // MR102
|
||||
{94, 0, -3, 3, 3, 6, 5, 9, cPIT_MIN_MR122}, // MR122
|
||||
}
|
||||
|
||||
// pitchFrState carries the previous subframe's integer lag across subframes.
|
||||
type pitchFrState struct {
|
||||
T0prev int16
|
||||
}
|
||||
|
||||
func (st *pitchFrState) reset() { st.T0prev = 0 }
|
||||
|
||||
// getRange clamps a search range [t0min, t0max] of width deltaRange around T0.
|
||||
// Mirrors getRange.
|
||||
func getRange(T0, deltaLow, deltaRange, pitmin, pitmax int16) (t0min, t0max int16) {
|
||||
temp := T0 - deltaLow
|
||||
if temp < pitmin {
|
||||
temp = pitmin
|
||||
}
|
||||
t0min = temp
|
||||
temp += deltaRange
|
||||
if temp > pitmax {
|
||||
temp = pitmax
|
||||
t0min = pitmax - deltaRange
|
||||
}
|
||||
t0max = temp
|
||||
return t0min, t0max
|
||||
}
|
||||
|
||||
// normCorr computes the normalized correlation corr[t-tMin] of the target xn
|
||||
// with the adaptive excitation at each integer lag t in [tMin, tMax], filtered
|
||||
// by the impulse response h. exc[excOff] is the current subframe start. Mirrors
|
||||
// Norm_Corr.
|
||||
func normCorr(exc []int16, excOff int, xn, h []int16, Lsubfr int, tMin, tMax int16, corr []int16) {
|
||||
var excf, scaledExcf [cL_SUBFR]int16
|
||||
|
||||
k := -int(tMin)
|
||||
convolve(exc[excOff+k:], h, excf[:], Lsubfr)
|
||||
|
||||
var s int32
|
||||
for j := 0; j < Lsubfr; j++ {
|
||||
t := excf[j]
|
||||
scaledExcf[j] = t >> 2
|
||||
s += int32(t) * int32(t)
|
||||
}
|
||||
|
||||
var sExcf []int16
|
||||
var hFac, scaling int16
|
||||
if s <= (67108864 >> 1) {
|
||||
sExcf = excf[:]
|
||||
hFac = 12
|
||||
scaling = 0
|
||||
} else {
|
||||
sExcf = scaledExcf[:]
|
||||
hFac = 14
|
||||
scaling = 2
|
||||
}
|
||||
|
||||
xnf := xn[:Lsubfr] // hoist bounds out of the inner correlation loop
|
||||
sef := sExcf[:Lsubfr] // (both length Lsubfr)
|
||||
hf := h[:Lsubfr]
|
||||
for i := tMin; i <= tMax; i++ {
|
||||
sc := firDot(xnf, sef)
|
||||
s2 := firDot(sef, sef)
|
||||
s2 <<= 1
|
||||
s2 = invSqrt(s2)
|
||||
normH := int16(s2 >> 16)
|
||||
normL := int16((s2 >> 1) - (int32(normH) << 15))
|
||||
corrH := int16(sc >> 15)
|
||||
corrL := int16(sc - (int32(corrH) << 15))
|
||||
corr[int(i)-int(tMin)] = int16(mpy_32(corrH, corrL, normH, normL))
|
||||
|
||||
if i != tMax {
|
||||
k--
|
||||
temp := exc[excOff+k]
|
||||
for j := Lsubfr - 1; j >= 1; j-- {
|
||||
sef[j] = int16((int32(temp)*int32(hf[j]))>>uint(hFac)) + sef[j-1]
|
||||
}
|
||||
sef[0] = temp >> scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interpol3or6 interpolates the correlation around corr[off] at fractional
|
||||
// position frac (1/3 if flag3 else 1/6). Mirrors Interpol_3or6.
|
||||
func interpol3or6(corr []int16, off int, frac, flag3 int16) int16 {
|
||||
if flag3 != 0 {
|
||||
frac <<= 1
|
||||
}
|
||||
if frac < 0 {
|
||||
frac += cUP_SAMP_MAX
|
||||
off--
|
||||
}
|
||||
f := int(frac)
|
||||
s := int32(0x4000)
|
||||
k := 0
|
||||
x1 := off
|
||||
x2 := off + 1
|
||||
for i := cL_INTER_SRCH >> 1; i != 0; i-- {
|
||||
s += int32(corr[x1]) * int32(inter6Pitch[f+k])
|
||||
x1--
|
||||
s += int32(corr[x2]) * int32(inter6Pitch[(cUP_SAMP_MAX-f)+k])
|
||||
x2++
|
||||
k += cUP_SAMP_MAX
|
||||
s += int32(corr[x1]) * int32(inter6Pitch[f+k])
|
||||
x1--
|
||||
s += int32(corr[x2]) * int32(inter6Pitch[(cUP_SAMP_MAX-f)+k])
|
||||
x2++
|
||||
k <<= 1
|
||||
}
|
||||
return int16(s >> 15)
|
||||
}
|
||||
|
||||
// searchFrac refines the fractional pitch around the integer lag by maximizing
|
||||
// the interpolated correlation, then normalizes the (lag, frac) pair. Mirrors
|
||||
// searchFrac.
|
||||
func searchFrac(lag, frac *int16, lastFrac int16, corr []int16, tMin int, flag3 int16) {
|
||||
off := int(*lag) - tMin
|
||||
max := interpol3or6(corr, off, *frac, flag3)
|
||||
for i := *frac + 1; i <= lastFrac; i++ {
|
||||
ci := interpol3or6(corr, off, i, flag3)
|
||||
if ci > max {
|
||||
max = ci
|
||||
*frac = i
|
||||
}
|
||||
}
|
||||
if flag3 == 0 {
|
||||
if *frac == -3 {
|
||||
*frac = 3
|
||||
*lag--
|
||||
}
|
||||
} else {
|
||||
if *frac == -2 {
|
||||
*frac = 1
|
||||
*lag--
|
||||
}
|
||||
if *frac == 2 {
|
||||
*frac = -1
|
||||
*lag++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pitchFr performs the closed-loop fractional pitch search for one subframe and
|
||||
// returns the integer lag T0, fractional part frac, the resolution flag resu3
|
||||
// (1=1/3, 0=1/6), and the encoded analysis index. Mirrors Pitch_fr.
|
||||
func (st *pitchFrState) pitchFr(mode int, Top []int16, exc []int16, excOff int, xn, h []int16, Lsubfr, iSubfr int) (T0, frac, resu3, anaIndex int16) {
|
||||
p := modeDepParm[mode]
|
||||
maxFracLag := p.maxFracLag
|
||||
flag3 := p.flag3
|
||||
frac = p.firstFrac
|
||||
lastFrac := p.lastFrac
|
||||
|
||||
deltaSearch := int16(1)
|
||||
var t0min, t0max int16
|
||||
if iSubfr == 0 || iSubfr == cL_FRAME_BY2 {
|
||||
if (mode != dMR475 && mode != dMR515) || iSubfr != cL_FRAME_BY2 {
|
||||
deltaSearch = 0
|
||||
frameOffset := int16(1)
|
||||
if iSubfr == 0 {
|
||||
frameOffset = 0
|
||||
}
|
||||
t0min, t0max = getRange(Top[frameOffset], p.deltaIntLow, p.deltaIntRange, p.pitMin, cPIT_MAX)
|
||||
} else {
|
||||
t0min, t0max = getRange(st.T0prev, p.deltaFrcLow, p.deltaFrcRange, p.pitMin, cPIT_MAX)
|
||||
}
|
||||
} else {
|
||||
t0min, t0max = getRange(st.T0prev, p.deltaFrcLow, p.deltaFrcRange, p.pitMin, cPIT_MAX)
|
||||
}
|
||||
|
||||
tMin := int16(int(t0min) - cL_INTER_SRCH)
|
||||
tMax := int16(int(t0max) + cL_INTER_SRCH)
|
||||
corr := make([]int16, int(tMax)-int(tMin)+1)
|
||||
normCorr(exc, excOff, xn, h, Lsubfr, tMin, tMax, corr)
|
||||
|
||||
max := corr[int(t0min)-int(tMin)]
|
||||
lag := t0min
|
||||
for i := t0min + 1; i <= t0max; i++ {
|
||||
if corr[int(i)-int(tMin)] >= max {
|
||||
max = corr[int(i)-int(tMin)]
|
||||
lag = i
|
||||
}
|
||||
}
|
||||
|
||||
if deltaSearch == 0 && lag > maxFracLag {
|
||||
frac = 0
|
||||
} else if deltaSearch != 0 && (mode == dMR475 || mode == dMR515 || mode == dMR59 || mode == dMR67) {
|
||||
tmpLag := st.T0prev
|
||||
if tmpLag-t0min > 5 {
|
||||
tmpLag = t0min + 5
|
||||
}
|
||||
if t0max-tmpLag > 4 {
|
||||
tmpLag = t0max - 4
|
||||
}
|
||||
switch {
|
||||
case lag == tmpLag || lag == tmpLag-1:
|
||||
searchFrac(&lag, &frac, lastFrac, corr, int(tMin), flag3)
|
||||
case lag == tmpLag-2:
|
||||
frac = 0
|
||||
searchFrac(&lag, &frac, lastFrac, corr, int(tMin), flag3)
|
||||
case lag == tmpLag+1:
|
||||
lastFrac = 0
|
||||
searchFrac(&lag, &frac, lastFrac, corr, int(tMin), flag3)
|
||||
default:
|
||||
frac = 0
|
||||
}
|
||||
} else {
|
||||
searchFrac(&lag, &frac, lastFrac, corr, int(tMin), flag3)
|
||||
}
|
||||
|
||||
if flag3 != 0 {
|
||||
flag4 := int16(0)
|
||||
if mode == dMR475 || mode == dMR515 || mode == dMR59 || mode == dMR67 {
|
||||
flag4 = 1
|
||||
}
|
||||
anaIndex = encLag3(lag, frac, st.T0prev, t0min, t0max, deltaSearch, flag4)
|
||||
} else {
|
||||
anaIndex = encLag6(lag, frac, t0min, deltaSearch)
|
||||
}
|
||||
|
||||
st.T0prev = lag
|
||||
resu3 = flag3
|
||||
return lag, frac, resu3, anaIndex
|
||||
}
|
||||
Reference in new issue
Block a user