package wav import ( "encoding/binary" "io" "github.com/pkg/errors" ) type header struct { fileSize int32 formatSize int32 formatType int16 numChans int16 sampleRate int32 byteRate int32 bytesPerFrame int16 bitsPerSample int16 dataSize int32 } func readHeader(r io.Reader) (header, error) { var ( h header er errReader ) err := er. ReadString(r, "RIFF", errors.New("missing RIFF at the beginning")). ReadBinary(r, binary.LittleEndian, &h.fileSize). ReadString(r, "WAVE", errors.New("unsupported file type")). ReadString(r, "fmt\x00", errors.New("missing format chunk marker")). ReadBinary(r, binary.LittleEndian, &h.formatSize). ReadBinary(r, binary.LittleEndian, &h.formatType). ReadBinary(r, binary.LittleEndian, &h.numChans). ReadBinary(r, binary.LittleEndian, &h.sampleRate). ReadBinary(r, binary.LittleEndian, &h.byteRate). ReadBinary(r, binary.LittleEndian, &h.bytesPerFrame). ReadBinary(r, binary.LittleEndian, &h.bitsPerSample). ReadString(r, "data", errors.New("missing data chunk marker")). ReadBinary(r, binary.LittleEndian, &h.dataSize). Err() return h, err } type errReader struct { err error } func (e *errReader) ReadString(r io.Reader, s string, notThereErr error) *errReader { if e.err != nil { return e } buf := make([]byte, len(s)) _, err := r.Read(buf) if err != nil { e.err = errors.Wrap(err, "error while reading header") return e } if string(buf) != s { e.err = errors.Wrap(err, "invalid header") } return e } func (e *errReader) ReadBinary(r io.Reader, order binary.ByteOrder, data interface{}) *errReader { if e.err != nil { return e } err := binary.Read(r, order, data) if err != nil { e.err = errors.Wrap(err, "invalid header") } return e } func (e *errReader) Err() error { return e.err }