wav: read_hdr

This commit is contained in:
zyxar 2015-08-11 15:36:11 +08:00
parent df563fd7f2
commit 9a19449fc8
3 changed files with 147 additions and 0 deletions

BIN
data/sample.wav Normal file

Binary file not shown.

119
wav.go Normal file
View file

@ -0,0 +1,119 @@
package tta
import (
"os"
"reflect"
"unsafe"
)
const (
RIFF_SIGN = (0x46464952)
WAVE_SIGN = (0x45564157)
fmt_SIGN = (0x20746D66)
data_SIGN = (0x61746164)
WAVE_FORMAT_PCM = 1
WAVE_FORMAT_EXTENSIBLE = 0xFFFE
PCM_BUFFER_LENGTH = 5120
)
type WAVE_hdr struct {
chunk_id uint32
chunk_size uint32
format uint32
subchunk_id uint32
subchunk_size uint32
audio_format uint16
num_channels uint16
sample_rate uint32
byte_rate uint32
block_align uint16
bits_per_sample uint16
}
type WAVE_subchunk_hdr struct {
subchunk_id uint32
subchunk_size uint32
}
type WAVE_subformat struct {
f1 uint32
f2 uint16
f3 uint16
f4 [8]byte
}
type WAVE_ext_hdr struct {
cb_size uint16
valid_bits uint16
ch_mask uint32
est WAVE_subformat
}
func (this *WAVE_hdr) toSlice() []byte {
size := int(unsafe.Sizeof(*this))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(this)),
Len: int(size),
Cap: int(size),
}))
}
func (this *WAVE_subchunk_hdr) toSlice() []byte {
size := int(unsafe.Sizeof(*this))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(this)),
Len: int(size),
Cap: int(size),
}))
}
func (this *WAVE_ext_hdr) toSlice() []byte {
size := int(unsafe.Sizeof(*this))
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(this)),
Len: int(size),
Cap: int(size),
}))
}
func (this *WAVE_hdr) Read(infile *os.File) (subchunk_size uint32, err error) {
var default_subchunk_size uint32 = 16
b := this.toSlice()
// Read WAVE header
if _, err = infile.Read(b); err != nil {
return
}
if this.audio_format == WAVE_FORMAT_EXTENSIBLE {
wave_hdr_ex := WAVE_ext_hdr{}
if _, err = infile.Read(wave_hdr_ex.toSlice()); err != nil {
return
}
default_subchunk_size += uint32(unsafe.Sizeof(wave_hdr_ex))
this.audio_format = uint16(wave_hdr_ex.est.f1)
}
// Skip extra format bytes
if this.subchunk_size > default_subchunk_size {
extra_len := this.subchunk_size - default_subchunk_size
if _, err = infile.Seek(int64(extra_len), os.SEEK_SET); err != nil {
return
}
}
// Skip unsupported chunks
subchunk_hdr := WAVE_subchunk_hdr{}
for {
if _, err = infile.Read(subchunk_hdr.toSlice()); err != nil {
return
}
if subchunk_hdr.subchunk_id == data_SIGN {
break
}
if _, err = infile.Seek(int64(subchunk_hdr.subchunk_size), os.SEEK_SET); err != nil {
return
}
}
subchunk_size = subchunk_hdr.subchunk_size
return
}

28
wav_test.go Normal file
View file

@ -0,0 +1,28 @@
package tta
import (
"bytes"
"fmt"
"os"
"testing"
)
func TestReadHeader(t *testing.T) {
file, err := os.Open("./data/sample.wav")
if err != nil {
t.Fatal(err)
}
wav := WAVE_hdr{}
wav_slice := []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}
if size, err := wav.Read(file); err != nil {
t.Error(err)
} else {
b := wav.toSlice()
fmt.Printf("sample wav header: %x, %x\n", b, size)
if bytes.Compare(wav_slice, b) != 0 {
t.Error("WAVE_hdr::Read fail")
}
}
}