Files
AskaEth 4a2d276881
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
2026-10-05 13:02:28 +08:00

262 lines
5.6 KiB
Go

package amrnb
// Fixed-point basic operators, ported from the ITU-T / ETSI "basicop2"
// reference (the same primitives used by opencore-amrnb).
//
// Word16 maps to int16, Word32 to int32. All operators saturate to the 16- or
// 32-bit range exactly as the reference does; Go has no implicit integer
// saturation, so every operation that can overflow clamps explicitly. The
// reference's global Overflow/Carry flags are not modelled — no AMR-NB code
// path depends on reading them back.
const (
maxInt16 = 32767
minInt16 = -32768
maxInt32 = 2147483647
minInt32 = -2147483648
)
// satWord16 clamps a 32-bit value to the int16 range.
func satWord16(v int32) int16 {
if v > maxInt16 {
return maxInt16
}
if v < minInt16 {
return minInt16
}
return int16(v)
}
// satWord32 clamps a 64-bit value to the int32 range.
func satWord32(v int64) int32 {
if v > maxInt32 {
return maxInt32
}
if v < minInt32 {
return minInt32
}
return int32(v)
}
// add returns the saturated 16-bit sum a+b.
func add(a, b int16) int16 { return satWord16(int32(a) + int32(b)) }
// sub returns the saturated 16-bit difference a-b.
func sub(a, b int16) int16 { return satWord16(int32(a) - int32(b)) }
// abs_s returns the saturated 16-bit absolute value (|-32768| -> 32767).
func abs_s(a int16) int16 {
if a == minInt16 {
return maxInt16
}
if a < 0 {
return -a
}
return a
}
// shl returns a shifted left by b bits with saturation; negative b shifts right.
func shl(a, b int16) int16 {
if b < 0 {
return shr(a, -b)
}
result := int32(a) << uint(b)
// Detect overflow by checking the shift is reversible.
if b >= 31 {
if a == 0 {
return 0
}
if a > 0 {
return maxInt16
}
return minInt16
}
return satWord16(result)
}
// shr returns a shifted right by b bits (arithmetic); negative b shifts left.
func shr(a, b int16) int16 {
if b < 0 {
return shl(a, -b)
}
if b >= 15 {
if a < 0 {
return -1
}
return 0
}
return int16(int32(a) >> uint(b))
}
// L_shl returns the saturated 32-bit left shift; negative b shifts right.
func L_shl(a int32, b int16) int32 {
if b <= 0 {
if b == 0 {
return a
}
return L_shr(a, -b)
}
if b >= 31 {
if a > 0 {
return maxInt32
}
if a < 0 {
return minInt32
}
return 0
}
// The reference shifts one bit at a time, saturating as soon as the value
// reaches the overflow region. Since |a<<k| grows monotonically, saturation
// is decided by the last pre-shift value a<<(b-1): >= 2^30 -> MAX_32,
// < -2^30 -> MIN_32; otherwise a<<b fits. Computed in int64 this is O(1) and
// bit-identical to the loop.
last := int64(a) << uint(b-1)
if last >= 0x40000000 {
return maxInt32
}
if last < -0x40000000 {
return minInt32
}
return a << uint(b)
}
// L_shr returns the 32-bit arithmetic right shift; negative b shifts left.
func L_shr(a int32, b int16) int32 {
if b < 0 {
return L_shl(a, -b)
}
if b >= 31 {
if a < 0 {
return -1
}
return 0
}
return a >> uint(b)
}
// mult returns satWord16((a*b)>>15).
func mult(a, b int16) int16 {
p := (int32(a) * int32(b)) >> 15
return satWord16(p)
}
// L_mult returns satWord32(a*b<<1) — the 32-bit product with the fractional
// left shift.
func L_mult(a, b int16) int32 {
p := int32(a) * int32(b)
if p != 0x40000000 {
return p << 1
}
return maxInt32
}
// L_add returns the saturated 32-bit sum.
func L_add(a, b int32) int32 { return satWord32(int64(a) + int64(b)) }
// L_sub returns the saturated 32-bit difference.
func L_sub(a, b int32) int32 { return satWord32(int64(a) - int64(b)) }
// L_mac returns acc + (a*b<<1), saturated.
func L_mac(acc int32, a, b int16) int32 { return L_add(acc, L_mult(a, b)) }
// L_msu returns acc - (a*b<<1), saturated.
func L_msu(acc int32, a, b int16) int32 { return L_sub(acc, L_mult(a, b)) }
// negate returns the saturated 16-bit negation.
func negate(a int16) int16 {
if a == minInt16 {
return maxInt16
}
return -a
}
// L_negate returns the saturated 32-bit negation.
func L_negate(a int32) int32 {
if a == minInt32 {
return maxInt32
}
return -a
}
// extract_h returns the high 16 bits of a 32-bit value.
func extract_h(a int32) int16 { return int16(a >> 16) }
// extract_l returns the low 16 bits of a 32-bit value.
func extract_l(a int32) int16 { return int16(a & 0xFFFF) }
// round_ returns the rounded high word: extract_h(L_add(a, 0x8000)).
func round_(a int32) int16 { return extract_h(L_add(a, 0x8000)) }
// mult_r returns the rounded multiply: satWord16(((a*b)+0x4000)>>15).
func mult_r(a, b int16) int16 {
p := (int32(a)*int32(b) + 0x4000) >> 15
return satWord16(p)
}
// L_deposit_h places a 16-bit value in the high half of a 32-bit word.
func L_deposit_h(a int16) int32 { return int32(a) << 16 }
// L_deposit_l sign-extends a 16-bit value into a 32-bit word.
func L_deposit_l(a int16) int32 { return int32(a) }
// norm_l returns the number of left shifts needed to normalize a (0 for 0).
func norm_l(a int32) int16 {
if a == 0 {
return 0
}
if a == -1 {
return 31
}
if a < 0 {
a = ^a
}
var n int16
for a < 0x40000000 {
a <<= 1
n++
}
return n
}
// norm_s returns the number of left shifts needed to normalize a 16-bit value.
func norm_s(a int16) int16 {
if a == 0 {
return 0
}
if a == -1 {
return 15
}
v := a
if v < 0 {
v = ^v
}
var n int16
for v < 0x4000 {
v <<= 1
n++
}
return n
}
// div_s returns the fractional division (a/b)<<15 for 0 <= a <= b, b != 0.
func div_s(a, b int16) int16 {
if a == 0 {
return 0
}
if a == b {
return maxInt16
}
num := int32(a)
den := int32(b)
var quot int32
for i := 0; i < 15; i++ {
quot <<= 1
num <<= 1
if num >= den {
num -= den
quot++
}
}
return int16(quot)
}