100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package amrnb
|
|
|
|
// Separate pitch/code gain quantizers (MR122; pitch also used by MR795), ported
|
|
// from opencore-amrnb q_gain_p.cpp (q_gain_pitch) and q_gain_c.cpp
|
|
// (q_gain_code). qGainPitch picks the nearest quantized pitch gain; qGainCode
|
|
// picks the code-gain index minimizing the error to the predicted gain. The
|
|
// exact encoder counterparts of dGainPitch / dGainCode. Bit-exact with the
|
|
// reference.
|
|
|
|
const (
|
|
cNB_QUA_PITCH = 16
|
|
cNB_QUA_CODE = 32
|
|
)
|
|
|
|
// qGainPitch quantizes the pitch gain (in place) to the nearest table entry
|
|
// within gpLimit, returning the index. For MR795 it also fills three candidate
|
|
// gains/indices. Mirrors q_gain_pitch.
|
|
func qGainPitch(mode int, gpLimit int16, gain *int16, gainCand, gainCind []int16) int16 {
|
|
errMin := abs_s(sub(*gain, qua_gain_pitch[0]))
|
|
index := int16(0)
|
|
for i := int16(1); i < cNB_QUA_PITCH; i++ {
|
|
if qua_gain_pitch[i] <= gpLimit {
|
|
err := abs_s(sub(*gain, qua_gain_pitch[i]))
|
|
if err < errMin {
|
|
errMin = err
|
|
index = i
|
|
}
|
|
}
|
|
}
|
|
|
|
if mode == dMR795 {
|
|
var ii int16
|
|
switch {
|
|
case index == 0:
|
|
ii = index
|
|
case index == cNB_QUA_PITCH-1 || qua_gain_pitch[index+1] > gpLimit:
|
|
ii = index - 2
|
|
default:
|
|
ii = index - 1
|
|
}
|
|
for i := 0; i < 3; i++ {
|
|
gainCind[i] = ii
|
|
gainCand[i] = qua_gain_pitch[ii]
|
|
ii++
|
|
}
|
|
*gain = qua_gain_pitch[index]
|
|
} else if mode == dMR122 {
|
|
*gain = qua_gain_pitch[index] &^ 3
|
|
} else {
|
|
*gain = qua_gain_pitch[index]
|
|
}
|
|
return index
|
|
}
|
|
|
|
// qGainCode quantizes the fixed-codebook gain (in place) against the predicted
|
|
// gain, returning the index and the predictor-update energies. Mirrors
|
|
// q_gain_code.
|
|
func qGainCode(mode int, expGcode0, fracGcode0 int16, gain *int16) (index, quaEnerMR122, quaEner int16) {
|
|
var gQ0 int16
|
|
if mode == dMR122 {
|
|
gQ0 = *gain >> 1 // Q1 -> Q0
|
|
} else {
|
|
gQ0 = *gain
|
|
}
|
|
|
|
gcode0 := int16(pow2(expGcode0, fracGcode0))
|
|
if mode == dMR122 {
|
|
gcode0 = shl(gcode0, 4)
|
|
} else {
|
|
gcode0 = shl(gcode0, 5)
|
|
}
|
|
|
|
errMin := gQ0 - int16((int32(gcode0)*int32(qua_gain_code[0]))>>15)
|
|
if errMin < 0 {
|
|
errMin = -errMin
|
|
}
|
|
index = 0
|
|
for i := int16(1); i < cNB_QUA_CODE; i++ {
|
|
err := gQ0 - int16((int32(gcode0)*int32(qua_gain_code[i*3]))>>15)
|
|
if err < 0 {
|
|
err = -err
|
|
}
|
|
if err < errMin {
|
|
errMin = err
|
|
index = i
|
|
}
|
|
}
|
|
|
|
p := int(index) * 3
|
|
temp := int16((int32(gcode0) * int32(qua_gain_code[p])) >> 15)
|
|
if mode == dMR122 {
|
|
*gain = temp << 1
|
|
} else {
|
|
*gain = temp
|
|
}
|
|
quaEnerMR122 = qua_gain_code[p+1]
|
|
quaEner = qua_gain_code[p+2]
|
|
return
|
|
}
|