Skip to content

Commit

Permalink
Avoid allocation when converting to/from ulaw.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennwc committed Dec 6, 2023
1 parent 41179e6 commit 26ceb61
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
2 changes: 2 additions & 0 deletions pkg/media/pcm.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func PlayAudio[T any](w Writer[T], sampleDur time.Duration, frames []T) error {

type PCM16Sample []int16

type PCM16Writer = Writer[PCM16Sample]

type MediaSampleWriter interface {
WriteSample(sample media.Sample) error
}
Expand Down
28 changes: 24 additions & 4 deletions pkg/media/ulaw/g711.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ func EncodeUlaw(lpcm []int16) []byte {
return out
}

// EncodeUlawTo encodes 16bit LPCM data to an existing G711 u-law PCM buffer.
func EncodeUlawTo(out []byte, lpcm []int16) {
if len(out) != len(lpcm) {
panic("short buffer")
}
for i := range lpcm {
out[i] = EncodeUlawFrame(lpcm[i])
}
}

// EncodeUlawFrame encodes a 16bit LPCM frame to G711 u-law PCM
func EncodeUlawFrame(frame int16) uint8 {
/*
Expand All @@ -127,14 +137,24 @@ func EncodeUlawFrame(frame int16) uint8 {
}

// DecodeUlaw decodes u-law PCM data to 16bit PCM.
func DecodeUlaw(pcm []byte) []int16 {
out := make([]int16, len(pcm))
for i := 0; i < len(pcm); i++ {
out[i] = ulaw2lpcm[pcm[i]]
func DecodeUlaw(ulaw []byte) []int16 {
out := make([]int16, len(ulaw))
for i := 0; i < len(ulaw); i++ {
out[i] = ulaw2lpcm[ulaw[i]]
}
return out
}

// DecodeUlawTo decodes u-law PCM data to an existing 16bit PCM buffer.
func DecodeUlawTo(out []int16, ulaw []byte) {
if len(out) != len(ulaw) {
panic("short buffer")
}
for i := 0; i < len(ulaw); i++ {
out[i] = ulaw2lpcm[ulaw[i]]
}
}

// DecodeUlawFrame decodes a u-law PCM frame to 16bit LPCM
func DecodeUlawFrame(frame uint8) int16 {
return ulaw2lpcm[frame]
Expand Down
51 changes: 38 additions & 13 deletions pkg/media/ulaw/ulaw.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,42 @@ func (s *Sample) Encode(data media.PCM16Sample) {
*s = EncodeUlaw(data)
}

func Decode(w media.Writer[media.PCM16Sample]) media.Writer[Sample] {
return media.WriterFunc[Sample](func(in Sample) error {
out := in.Decode()
return w.WriteSample(out)
})
}

func Encode(w media.Writer[Sample]) media.Writer[media.PCM16Sample] {
return media.WriterFunc[media.PCM16Sample](func(in media.PCM16Sample) error {
var s Sample
s.Encode(in)
return w.WriteSample(s)
})
type Writer = media.Writer[Sample]

type Decoder struct {
w media.PCM16Writer
buf media.PCM16Sample
}

func (d *Decoder) WriteSample(in Sample) error {
if len(in) >= cap(d.buf) {
d.buf = make(media.PCM16Sample, len(in))
} else {
d.buf = d.buf[:len(in)]
}
DecodeUlawTo(d.buf, in)
return d.w.WriteSample(d.buf)
}

func Decode(w media.PCM16Writer) Writer {
return &Decoder{w: w}
}

type Encoder struct {
w Writer
buf Sample
}

func (e *Encoder) WriteSample(in media.PCM16Sample) error {
if len(in) >= cap(e.buf) {
e.buf = make(Sample, len(in))
} else {
e.buf = e.buf[:len(in)]
}
EncodeUlawTo(e.buf, in)
return e.w.WriteSample(e.buf)
}

func Encode(w Writer) media.PCM16Writer {
return &Encoder{w: w}
}

0 comments on commit 26ceb61

Please sign in to comment.