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) } }