From e60429a83eb0f90003030d2193ce78519ad54259 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 19 Jul 2025 10:31:15 -0700 Subject: [PATCH] Reuse tmp buffers in calls to PCMBuffer --- decoder.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/decoder.go b/decoder.go index 66f2bb7..316d8a6 100644 --- a/decoder.go +++ b/decoder.go @@ -42,6 +42,9 @@ type Decoder struct { PCMChunk *riff.Chunk // Metadata for the current file Metadata *Metadata + + readBuf []byte + sampleBuf [4]byte } // NewDecoder creates a decoder for the passed wav reader. @@ -250,8 +253,6 @@ func (d *Decoder) FullPCMBuffer() (*audio.IntBuffer, error) { } buf := &audio.IntBuffer{Data: make([]int, 4096), Format: format, SourceBitDepth: int(d.BitDepth)} - bytesPerSample := (d.BitDepth-1)/8 + 1 - sampleBufData := make([]byte, bytesPerSample) decodeF, err := sampleDecodeFunc(int(d.BitDepth)) if err != nil { return nil, fmt.Errorf("could not get sample decode func %w", err) @@ -259,7 +260,7 @@ func (d *Decoder) FullPCMBuffer() (*audio.IntBuffer, error) { i := 0 for err == nil { - buf.Data[i], err = decodeF(d.PCMChunk, sampleBufData) + buf.Data[i], err = decodeF(d.PCMChunk, d.sampleBuf[:]) if err != nil { break } @@ -309,9 +310,9 @@ func (d *Decoder) PCMBuffer(buf *audio.IntBuffer) (n int, err error) { // populate a file buffer to avoid multiple very small reads // we need to cap the buffer size to not be bigger than the pcm chunk. size := len(buf.Data) * bPerSample - tmpBuf := make([]byte, size) + d.ensureReadBufSize(size) var m int - m, err = d.PCMChunk.R.Read(tmpBuf) + m, err = d.PCMChunk.R.Read(d.readBuf) if err != nil { if errors.Is(err, io.EOF) { return m, nil @@ -321,8 +322,7 @@ func (d *Decoder) PCMBuffer(buf *audio.IntBuffer) (n int, err error) { if m == 0 { return m, nil } - bufR := bytes.NewReader(tmpBuf[:m]) - sampleBuf := make([]byte, bPerSample, bPerSample) + bufR := bytes.NewReader(d.readBuf[:m]) var misaligned bool if m%bPerSample > 0 { misaligned = true @@ -331,7 +331,7 @@ func (d *Decoder) PCMBuffer(buf *audio.IntBuffer) (n int, err error) { // Note that we populate the buffer even if the // size of the buffer doesn't fit an even number of frames. for n = 0; n < len(buf.Data); n++ { - buf.Data[n], err = decodeF(bufR, sampleBuf) + buf.Data[n], err = decodeF(bufR, d.sampleBuf[:]) if err != nil { // the last sample isn't a full sample but just padding. if misaligned { @@ -409,6 +409,12 @@ func (d *Decoder) String() string { return d.parser.String() } +func (d *Decoder) ensureReadBufSize(size int) { + if len(d.readBuf) < size { + d.readBuf = make([]byte, size) + } +} + // readHeaders is safe to call multiple times func (d *Decoder) readHeaders() error { if d == nil || d.NumChans > 0 {