129 lines
3.4 KiB
Go
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
|
|
}
|
|
}
|