Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -250,16 +253,14 @@ 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)
}

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
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down