2025-10-23 13:06:22 +07:00

117 lines
2.5 KiB
Go

package riff
import (
"encoding/binary"
"errors"
"fmt"
"io"
"io/ioutil"
"sync"
)
type Chunk struct {
ID [4]byte
Size int
Pos int
R io.Reader
okChan chan bool
Wg *sync.WaitGroup
}
func (ch *Chunk) DecodeWavHeader(p *Parser) error {
if ch == nil {
return fmt.Errorf("can't decode a nil chunk")
}
if ch.ID == FmtID {
p.wavHeaderSize = uint32(ch.Size)
if err := ch.ReadLE(&p.WavAudioFormat); err != nil {
return err
}
if err := ch.ReadLE(&p.NumChannels); err != nil {
return err
}
if err := ch.ReadLE(&p.SampleRate); err != nil {
return err
}
if err := ch.ReadLE(&p.AvgBytesPerSec); err != nil {
return err
}
if err := ch.ReadLE(&p.BlockAlign); err != nil {
return err
}
if err := ch.ReadLE(&p.BitsPerSample); err != nil {
return err
}
if ch.Size > 16 {
extra := make([]byte, ch.Size-16)
ch.ReadLE(&extra)
}
}
return nil
}
func (ch *Chunk) Done() {
if !ch.IsFullyRead() {
ch.Drain()
}
if ch.Wg != nil {
ch.Wg.Done()
}
}
func (ch *Chunk) IsFullyRead() bool {
if ch == nil || ch.R == nil {
return true
}
return ch.Size <= ch.Pos
}
func (ch *Chunk) Read(p []byte) (n int, err error) {
if ch == nil || ch.R == nil {
return 0, errors.New("nil chunk/reader pointer")
}
n, err = ch.R.Read(p)
ch.Pos += n
return n, err
}
func (ch *Chunk) ReadLE(dst interface{}) error {
if ch == nil || ch.R == nil {
return errors.New("nil chunk/reader pointer")
}
if ch.IsFullyRead() {
return io.EOF
}
ch.Pos += binary.Size(dst)
return binary.Read(ch.R, binary.LittleEndian, dst)
}
func (ch *Chunk) ReadBE(dst interface{}) error {
if ch.IsFullyRead() {
return io.EOF
}
ch.Pos += binary.Size(dst)
return binary.Read(ch.R, binary.LittleEndian, dst)
}
func (ch *Chunk) ReadByte() (byte, error) {
if ch.IsFullyRead() {
return 0, io.EOF
}
var r byte
err := ch.ReadLE(&r)
return r, err
}
func (ch *Chunk) Drain() {
bytesAhead := ch.Size - ch.Pos
for bytesAhead > 0 {
readSize := int64(bytesAhead)
if _, err := io.CopyN(ioutil.Discard, ch.R, readSize); err != nil {
return
}
bytesAhead -= int(readSize)
}
}