update wave package

This commit is contained in:
Markus Tzoe 2017-08-24 10:47:56 +08:00
parent d12ddbc1b2
commit 626fbecf50
4 changed files with 59 additions and 89 deletions

View file

@ -40,7 +40,7 @@ func Decompress(infile io.ReadWriteSeeker, outfile io.WriteSeeker, passwd string
smpSize := info.nch * ((info.bps + 7) / 8)
dataSize := info.samples * smpSize
waveHdr := wave.NewHeader(dataSize, uint16(info.nch), info.sps, uint16(info.bps), uint16(smpSize))
if err = waveHdr.Write(outfile); err != nil {
if _, err = waveHdr.WriteTo(outfile); err != nil {
return
}
bufSize := pcmBufferLength * smpSize

View file

@ -29,10 +29,8 @@ type Encoder struct {
}
func Compress(infile io.ReadSeeker, outfile io.ReadWriteSeeker, passwd string, cb Callback) (err error) {
waveHdr := wave.Header{}
var dataSize uint32
if dataSize, err = waveHdr.Read(infile); err != nil {
err = errRead
waveHdr, dataSize, err := wave.ReadHeader(infile)
if err != nil {
return
} else if dataSize >= 0x7FFFFFFF {
err = fmt.Errorf("incorrect data size info in wav file: %x", dataSize)

View file

@ -1,7 +1,6 @@
package wave
import (
"errors"
"io"
"os"
"reflect"
@ -9,18 +8,16 @@ import (
)
const (
magicRiff = 0x46464952
magicFormat = 0x20746D66
magicChunk = 0x61746164
MAGIC = 0x45564157
riff = 0x46464952 // "RIFF"
fmtChunkId = 0x20746D66 // "fmt "
dataChunkId = 0x61746164 // "data"
MAGIC = 0x45564157 // "WAVE"
formatPCM = 1
formatExt = 0xFFFE
)
var (
errPartialWritten = errors.New("partial written")
errPartialRead = errors.New("partial read")
szHeader = 36 // unsafe.Sizeof(Header{})
szSubchunkHeader = 8 // unsafe.Sizeof(SubchunkHeader{})
)
type Header struct {
@ -56,10 +53,10 @@ type ExtHeader struct {
func NewHeader(dataSize uint32, nch uint16, sps uint32, bps uint16, smpSize uint16) *Header {
return &Header{
ChunkId: magicRiff,
ChunkSize: dataSize + 36,
ChunkId: riff,
ChunkSize: dataSize + szHeader,
Format: MAGIC,
SubchunkId: magicFormat,
SubchunkId: fmtChunkId,
SubchunkSize: 16,
AudioFormat: 1,
NumChannels: nch,
@ -71,7 +68,7 @@ func NewHeader(dataSize uint32, nch uint16, sps uint32, bps uint16, smpSize uint
}
func (h *Header) Validate(maxNCH, maxBPS uint16) bool {
return (h.ChunkId == magicRiff) &&
return (h.ChunkId == riff) &&
(h.Format == MAGIC) &&
(h.NumChannels != 0) &&
(h.NumChannels <= maxNCH) &&
@ -79,60 +76,39 @@ func (h *Header) Validate(maxNCH, maxBPS uint16) bool {
(h.BitsPerSample <= maxBPS)
}
func (w *Header) Bytes() []byte {
size := int(unsafe.Sizeof(*w))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(w)),
Len: size,
Cap: size,
}))
func (h *Header) Bytes() []byte {
return slice(unsafe.Sizeof(*h), unsafe.Pointer(h))
}
func (w *SubchunkHeader) Bytes() []byte {
size := int(unsafe.Sizeof(*w))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(w)),
Len: size,
Cap: size,
}))
func (s *SubchunkHeader) Bytes() []byte {
return slice(unsafe.Sizeof(*s), unsafe.Pointer(s))
}
func (w *ExtHeader) Bytes() []byte {
size := int(unsafe.Sizeof(*w))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(w)),
Len: size,
Cap: size,
}))
func (e *ExtHeader) Bytes() []byte {
return slice(unsafe.Sizeof(*e), unsafe.Pointer(e))
}
func (w *Header) Read(fd io.ReadSeeker) (subchunkSize uint32, err error) {
var defaultSubchunkSize uint32 = 16
b := w.Bytes()
var readLen int
func ReadHeader(fd io.ReadSeeker) (h *Header, subchunkSize uint32, err error) {
var defaultSubchunkSize uint32 = 16 // PCM
h = &Header{}
b := h.Bytes()
// Read WAVE header
if readLen, err = fd.Read(b); err != nil {
return
} else if readLen != len(b) {
err = errPartialRead
if _, err = fd.Read(b); err != nil {
return
}
if w.AudioFormat == formatExt {
waveHdrEx := ExtHeader{}
if readLen, err = fd.Read(waveHdrEx.Bytes()); err != nil {
return
} else if readLen != int(unsafe.Sizeof(waveHdrEx)) {
err = errPartialRead
if h.AudioFormat == formatExt {
extheader := ExtHeader{}
if _, err = fd.Read(extheader.Bytes()); err != nil {
return
}
defaultSubchunkSize += uint32(unsafe.Sizeof(waveHdrEx))
w.AudioFormat = uint16(waveHdrEx.est.f1)
defaultSubchunkSize += uint32(unsafe.Sizeof(extheader))
h.AudioFormat = uint16(extheader.est.f1)
}
// Skip extra format bytes
if w.SubchunkSize > defaultSubchunkSize {
extraLen := w.SubchunkSize - defaultSubchunkSize
if _, err = fd.Seek(int64(extraLen), os.SEEK_SET); err != nil {
if h.SubchunkSize > defaultSubchunkSize {
extraLen := h.SubchunkSize - defaultSubchunkSize
if _, err = fd.Seek(int64(extraLen), os.SEEK_CUR); err != nil {
return
}
}
@ -140,16 +116,13 @@ func (w *Header) Read(fd io.ReadSeeker) (subchunkSize uint32, err error) {
// Skip unsupported chunks
subchunkHdr := SubchunkHeader{}
for {
if readLen, err = fd.Read(subchunkHdr.Bytes()); err != nil {
return
} else if readLen != int(unsafe.Sizeof(subchunkHdr)) {
err = errPartialRead
if _, err = fd.Read(subchunkHdr.Bytes()); err != nil {
return
}
if subchunkHdr.SubchunkId == magicChunk {
if subchunkHdr.SubchunkId == dataChunkId {
break
}
if _, err = fd.Seek(int64(subchunkHdr.SubchunkSize), os.SEEK_SET); err != nil {
if _, err = fd.Seek(int64(subchunkHdr.SubchunkSize), os.SEEK_CUR); err != nil {
return
}
}
@ -157,22 +130,25 @@ func (w *Header) Read(fd io.ReadSeeker) (subchunkSize uint32, err error) {
return
}
func (w *Header) Write(fd io.Writer) (err error) {
var writeLen int
func (h *Header) WriteTo(w io.Writer) (n int64, err error) {
// Write WAVE header
if writeLen, err = fd.Write(w.Bytes()); err != nil {
return
} else if writeLen != int(unsafe.Sizeof(*w)) {
err = errPartialWritten
writeLen, err := w.Write(h.Bytes())
n += int64(writeLen)
if err != nil {
return
}
// Write Subchunk header
subchunkHdr := SubchunkHeader{magicChunk, w.ChunkSize - 36}
if writeLen, err = fd.Write(subchunkHdr.Bytes()); err != nil {
return
} else if writeLen != int(unsafe.Sizeof(subchunkHdr)) {
err = errPartialWritten
return
}
subchunkHdr := SubchunkHeader{dataChunkId, h.ChunkSize - szHeader}
writeLen, err = w.Write(subchunkHdr.Bytes())
n += int64(writeLen)
return
}
func slice(sz uintptr, addr unsafe.Pointer) []byte {
size := int(sz)
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(addr),
Len: size,
Cap: size,
}))
}

View file

@ -6,7 +6,8 @@ import (
"testing"
)
var wavSlice = []byte{0x52, 0x49, 0x46, 0x46, 0x98, 0x03, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20,
var wavSlice = []byte{
0x52, 0x49, 0x46, 0x46, 0x98, 0x03, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00,
0x04, 0x00, 0x10, 0x00}
@ -17,11 +18,10 @@ func TestReadHeader(t *testing.T) {
t.Fatal(err)
}
defer file.Close()
wav := Header{}
if size, err := wav.Read(file); err != nil {
if wav, size, err := ReadHeader(file); err != nil {
t.Error(err)
} else {
if bytes.Compare(wavSlice, wav.Bytes()) != 0 || size != wav.ChunkSize-36 {
if bytes.Compare(wavSlice, wav.Bytes()) != 0 || size != wav.ChunkSize-szHeader {
t.Error("Header::Read fail")
}
}
@ -29,16 +29,12 @@ func TestReadHeader(t *testing.T) {
func TestWriteHeader(t *testing.T) {
t.Parallel()
filename := os.TempDir() + "/tta_tmp.wav"
file, err := os.Create(filename)
if err != nil {
t.Fatal(err)
}
defer file.Close()
defer os.Remove(filename)
var buf bytes.Buffer
wav := Header{}
copy(wav.Bytes(), wavSlice)
if err = wav.Write(file); err != nil {
if n, err := wav.WriteTo(&buf); err != nil {
t.Error(err)
} else if n != int64(szHeader+szSubchunkHeader) {
t.Errorf("write %d bytes, expected %d bytes", n, szHeader+szSubchunkHeader)
}
}