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,63 @@
|
||||
package transcode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Format 是小写、无点的音频格式标识("amr" / "wav" / …)。
|
||||
//
|
||||
// 口径与 mediafetch.AudioFormatOf(internal/channel/mediafetch/inline_voice.go:62)
|
||||
// 归一出的格式名、以及 voice.Audio{Format}(internal/runtime/multimodal/voice)
|
||||
// 的格式名**同一份**:全仓的「字符串 ↔ Format」转换只有本文件的 FormatOf /
|
||||
// FormatName 两处,调用方不得各写一份映射(design/25 §6.2)。
|
||||
type Format string
|
||||
|
||||
const (
|
||||
// FormatAMR 是 AMR-NB(窄带),魔数 `#!AMR\n`。
|
||||
FormatAMR Format = "amr"
|
||||
// FormatAMRWB 是 AMR-WB(宽带),魔数 `#!AMR-WB\n`。**本期不实现**
|
||||
// (design/25 §3.3 后置):登记它是为了让嗅探与报错诚实——「认得出但没这条路」
|
||||
// 比「认不出」更能说清问题。
|
||||
FormatAMRWB Format = "amr-wb"
|
||||
// FormatWAV 是 RIFF/WAVE 容器(本期只发 PCM16 一种载荷)。
|
||||
FormatWAV Format = "wav"
|
||||
)
|
||||
|
||||
// 魔数与容器标识。AMR 文件的头来自 RFC 4867 §5(存储格式);RIFF/WAVE 的四块
|
||||
// 结构见 design/25 §0.5 登记的 WAV/RIFF 规范。
|
||||
const (
|
||||
amrNBMagic = "#!AMR\n"
|
||||
amrWBMagic = "#!AMR-WB\n"
|
||||
riffMagic = "RIFF"
|
||||
waveMagic = "WAVE"
|
||||
// riffChunkSizeOffset 是 RIFF 头里 "WAVE" 标识的起始偏移("RIFF" + 4 字节长度)。
|
||||
riffChunkSizeOffset = 8
|
||||
)
|
||||
|
||||
// FormatOf 把外部格式名归一成 Format:去空白、转小写、去掉开头的点
|
||||
// (`.amr` → `amr`)。它不判断格式是否支持——「认不认得」由 Sniff /
|
||||
// FormatOf 决定,「支不支持」由 Registry.Lookup 决定,两件事分开。
|
||||
func FormatOf(name string) Format {
|
||||
return Format(strings.ToLower(strings.TrimPrefix(strings.TrimSpace(name), ".")))
|
||||
}
|
||||
|
||||
// FormatName 返回 Format 的规范字符串形式(= 归一化后的格式名)。
|
||||
func FormatName(f Format) string { return string(f) }
|
||||
|
||||
// Sniff 按魔数嗅探 data 的音频格式。嗅不出即返回 false(deny-by-default:
|
||||
// 类型不明的字节绝不进解码器)。
|
||||
func Sniff(data []byte) (Format, bool) {
|
||||
switch {
|
||||
case bytes.HasPrefix(data, []byte(amrWBMagic)):
|
||||
return FormatAMRWB, true
|
||||
case bytes.HasPrefix(data, []byte(amrNBMagic)):
|
||||
return FormatAMR, true
|
||||
case len(data) >= riffChunkSizeOffset+len(waveMagic) &&
|
||||
bytes.HasPrefix(data, []byte(riffMagic)) &&
|
||||
bytes.HasPrefix(data[riffChunkSizeOffset:], []byte(waveMagic)):
|
||||
return FormatWAV, true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user