119 lines
2.1 KiB
Go
119 lines
2.1 KiB
Go
package opus
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
type Header struct {
|
|
Mode string
|
|
SampleRate uint16
|
|
FrameSize time.Duration
|
|
Channels byte
|
|
Frames byte
|
|
}
|
|
|
|
func UnmarshalHeader(b []byte) *Header {
|
|
// https://datatracker.ietf.org/doc/html/rfc6716#section-3.1
|
|
b0 := b[0]
|
|
config := b0 >> 3
|
|
return &Header{
|
|
Mode: parseMode(config),
|
|
SampleRate: parseSampleRate(config),
|
|
FrameSize: parseFrameSize(config),
|
|
Channels: parseChannels(b0 >> 2 & 0b1),
|
|
Frames: parseFrames(b0 & 0b11),
|
|
}
|
|
}
|
|
|
|
func parseMode(config byte) string {
|
|
if config <= 11 {
|
|
return "silk"
|
|
}
|
|
if config <= 15 {
|
|
return "hybrid"
|
|
}
|
|
return "celt"
|
|
}
|
|
|
|
func parseSampleRate(config byte) uint16 {
|
|
switch config {
|
|
case 0, 1, 2, 3, 16, 17, 18, 19:
|
|
return 8000 // NB (narrowband)
|
|
case 4, 5, 6, 7:
|
|
return 12000 // MB (medium-band)
|
|
case 8, 9, 10, 11, 20, 21, 22, 23:
|
|
return 16000 // WB (wideband)
|
|
case 12, 13, 24, 25, 26, 27:
|
|
return 24000 // SWB (super-wideband)
|
|
case 14, 15, 28, 29, 30, 31:
|
|
return 48000 // FB (fullband)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func parseFrameSize(config byte) time.Duration {
|
|
switch config {
|
|
case 0, 4, 8, 12, 14, 18, 22, 26, 30:
|
|
return 10_000_000
|
|
case 1, 5, 9, 13, 15, 19, 23, 27, 31:
|
|
return 20_000_000
|
|
case 2, 6, 10:
|
|
return 40_000_000
|
|
case 3, 7, 11:
|
|
return 60_000_000
|
|
case 16, 20, 24, 28:
|
|
return 2_500_000
|
|
case 17, 21, 25, 29:
|
|
return 5_000_000
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func parseChannels(s byte) byte {
|
|
if s == 1 {
|
|
return 2
|
|
}
|
|
return 1
|
|
}
|
|
|
|
func parseFrames(c byte) byte {
|
|
switch c {
|
|
case 0:
|
|
return 1
|
|
case 1, 2:
|
|
return 2
|
|
}
|
|
return 0xFF
|
|
}
|
|
|
|
func JoinFrames(b1, b2 []byte) []byte {
|
|
// can't join
|
|
if b1[0]&0b11 != 0 || b2[0]&0b11 != 0 {
|
|
return append(b1, b2...)
|
|
}
|
|
|
|
size1, size2 := len(b1)-1, len(b2)-1
|
|
|
|
// join same sizes
|
|
if size1 == size2 {
|
|
b := make([]byte, 1+size1+size2)
|
|
copy(b, b1)
|
|
copy(b[1+size1:], b2[1:])
|
|
b[0] |= 0b01
|
|
return b
|
|
}
|
|
|
|
b := make([]byte, 1, 3+size1+size2)
|
|
b[0] = b1[0] | 0b10
|
|
if size1 >= 252 {
|
|
b0 := 252 + byte(size1)&0b11
|
|
b = append(b, b0, byte(size1/4)-b0)
|
|
} else {
|
|
b = append(b, byte(size1))
|
|
}
|
|
|
|
b = append(b, b1[1:]...)
|
|
b = append(b, b2[1:]...)
|
|
return b
|
|
}
|