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,83 @@
|
||||
package amrnb
|
||||
|
||||
// This file holds the AMR-NB signal-processing state and the entry points the
|
||||
// public Encoder/Decoder call per 20 ms frame. The fixed-point DSP itself
|
||||
// (LP analysis/LSF quantization, open/closed-loop pitch, algebraic codebook
|
||||
// search, gain quantization, synthesis and post-filtering, DTX) is a large
|
||||
// bit-exact port of 3GPP TS 26.090 — see opencore-amrnb (Apache-2.0), which
|
||||
// ships both encoder and decoder.
|
||||
//
|
||||
// The structs below define where that ported state lives. The encodeFrame /
|
||||
// decodeFrame methods are the single integration seam where the per-block DSP
|
||||
// functions are orchestrated per 20 ms frame.
|
||||
//
|
||||
// NOTE: the DSP is currently STUBBED — coder()/decoder() are not yet ported, so
|
||||
// encodeFrame emits a zero-filled bitstream of the correct size and decodeFrame
|
||||
// emits silence. The public API, RFC 4867 framing, fixed-point operators and
|
||||
// SIMD kernels are complete and exercised by the pure-Go tests; the bit-exact
|
||||
// DSP lands in a later phase (see the plan).
|
||||
|
||||
// encoderState holds the persistent encoder analysis state across frames.
|
||||
type encoderState struct {
|
||||
started bool
|
||||
st coderState
|
||||
}
|
||||
|
||||
func (s *encoderState) reset() {
|
||||
s.started = true
|
||||
s.st.reset()
|
||||
}
|
||||
|
||||
// encodeFrame analyses one 160-sample frame in the given mode and returns the
|
||||
// RFC 4867 frame payload bytes (the sorted/packed speech bits, without the
|
||||
// CMR/ToC header which the caller adds). Mirrors Speech_Encode_Frame: mask the 3
|
||||
// LSBs (13-bit input), high-pass + downscale (Pre_Process), run the analysis
|
||||
// (cod_amr), then serialize (prm2bits + IETF reorder via packFrame).
|
||||
func (s *encoderState) encodeFrame(mode Mode, samples []int16) ([]byte, error) {
|
||||
if !s.started {
|
||||
s.reset()
|
||||
}
|
||||
in := make([]int16, cL_FRAME)
|
||||
for i := 0; i < cL_FRAME && i < len(samples); i++ {
|
||||
in[i] = samples[i] &^ 7 // delete 3 LSBs (13-bit input)
|
||||
}
|
||||
s.st.pre.process(in, cL_FRAME)
|
||||
|
||||
prm, err := s.st.codAmr(int(mode), in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return packFrame(prm, mode), nil
|
||||
}
|
||||
|
||||
// decoderState holds the persistent decoder synthesis state across frames.
|
||||
type decoderState struct {
|
||||
dsp decoderStateDSP
|
||||
lastMode Mode
|
||||
started bool
|
||||
}
|
||||
|
||||
func (s *decoderState) reset() {
|
||||
s.dsp.reset()
|
||||
s.lastMode = Mode1220
|
||||
s.started = true
|
||||
}
|
||||
|
||||
// decodeFrame decodes one parsed AMR-NB frame into 160 PCM samples. Good speech
|
||||
// frames are fully decoded; bad/SID/no-data frames currently emit silence
|
||||
// (error concealment and CNG are not yet ported).
|
||||
func (s *decoderState) decodeFrame(f frame) ([]int16, error) {
|
||||
if !s.started {
|
||||
s.reset()
|
||||
}
|
||||
synth := make([]int16, cAMR_NB_PCM_FRAME)
|
||||
if f.ft <= FTMode1220 { // speech
|
||||
mode := Mode(f.ft)
|
||||
s.lastMode = mode
|
||||
if f.q {
|
||||
params := mimeUnsort(f.data, mode)
|
||||
s.dsp.decodeSpeechFrame(int(mode), params, synth)
|
||||
}
|
||||
}
|
||||
return synth, nil
|
||||
}
|
||||
Reference in new issue
Block a user