Files
Cyrene_v2/internal/capability/transcode/amrnb/mode.go
T
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

129 lines
3.4 KiB
Go

// Package amrnb implements the AMR-NB (3GPP TS 26.071 / 26.090) narrowband
// speech codec in pure Go, with RFC 4867 RTP payload framing.
//
// AMR-NB operates on 8 kHz mono audio in 20 ms frames (160 samples). It defines
// eight speech coding modes (0..7) spanning 4.75 to 12.2 kbit/s, plus a comfort
// noise (SID) frame used by DTX.
package amrnb
// SampleRate is the fixed AMR-NB sampling rate in Hz.
const SampleRate = 8000
// FrameSamples is the number of PCM samples in one 20 ms AMR-NB frame.
const FrameSamples = 160
// Mode identifies an AMR-NB speech coding mode (0..7).
type Mode int
const (
Mode0475 Mode = iota // 4.75 kbit/s
Mode0515 // 5.15 kbit/s
Mode0590 // 5.90 kbit/s
Mode0670 // 6.70 kbit/s
Mode0740 // 7.40 kbit/s
Mode0795 // 7.95 kbit/s
Mode1020 // 10.2 kbit/s
Mode1220 // 12.2 kbit/s
numSpeechModes
)
// Frame type (FT) values carried in the RFC 4867 ToC byte. Values 0..7 are the
// speech modes; the remainder describe comfort noise and no-data frames. Note
// that AMR-NB places SID at FT 8 (AMR-WB uses FT 9).
const (
FTMode0475 = 0
FTMode0515 = 1
FTMode0590 = 2
FTMode0670 = 3
FTMode0740 = 4
FTMode0795 = 5
FTMode1020 = 6
FTMode1220 = 7
FTSID = 8 // comfort noise (SID)
FTSpeechLost = 14 // speech lost (RFC 4867)
FTNoData = 15 // no data
)
// modeBits is the number of speech bits per AMR-NB mode (0..7). These are the
// canonical bit counts from 3GPP TS 26.101 (and RFC 4867 Table 1a).
var modeBits = [numSpeechModes]int{
95, // 4.75
103, // 5.15
118, // 5.90
134, // 6.70
148, // 7.40
159, // 7.95
204, // 10.2
244, // 12.2
}
// sidBits is the number of bits in an AMR-NB SID (comfort noise) frame.
const sidBits = 39
// frameBitsByFT returns the number of payload bits for a given frame type and
// whether the frame type is a recognized one that carries bits. SID and speech
// modes carry bits; SPEECH_LOST and NO_DATA carry none.
func frameBitsByFT(ft int) (bits int, ok bool) {
switch {
case ft >= FTMode0475 && ft <= FTMode1220:
return modeBits[ft], true
case ft == FTSID:
return sidBits, true
case ft == FTSpeechLost, ft == FTNoData:
return 0, true
default:
return 0, false
}
}
// frameBytesByFT returns the number of octet-aligned bytes occupied by a frame
// of the given type (bits rounded up to whole octets).
func frameBytesByFT(ft int) (bytes int, ok bool) {
bits, ok := frameBitsByFT(ft)
if !ok {
return 0, false
}
return (bits + 7) / 8, true
}
// Bits returns the number of speech bits produced by this mode.
func (m Mode) Bits() int {
if m < 0 || m >= numSpeechModes {
return 0
}
return modeBits[m]
}
// Bytes returns the octet-aligned byte count of a frame in this mode.
func (m Mode) Bytes() int { return (m.Bits() + 7) / 8 }
// FrameType returns the RFC 4867 frame-type value for this mode.
func (m Mode) FrameType() int { return int(m) }
// Valid reports whether m is a defined speech mode.
func (m Mode) Valid() bool { return m >= Mode0475 && m < numSpeechModes }
// Bitrate returns the nominal bit rate of the mode in bit/s.
func (m Mode) Bitrate() int {
switch m {
case Mode0475:
return 4750
case Mode0515:
return 5150
case Mode0590:
return 5900
case Mode0670:
return 6700
case Mode0740:
return 7400
case Mode0795:
return 7950
case Mode1020:
return 10200
case Mode1220:
return 12200
default:
return 0
}
}