aboutsummaryrefslogtreecommitdiff
path: root/wav
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2017-07-28 00:51:34 -0400
committerNathan Perry <avaglir@gmail.com>2017-07-28 00:51:34 -0400
commit47877a3045c745e70b2e77a91e1f59e6f432c5df (patch)
treedfcb8b1ea145c33c04aee45dd0c46824bf5fec36 /wav
parent54359c61daadf1d61730d224675c3b4595a5b83a (diff)
try own wav impl
Diffstat (limited to 'wav')
-rw-r--r--wav/wav.go177
-rw-r--r--wav/wav_test.go15
2 files changed, 192 insertions, 0 deletions
diff --git a/wav/wav.go b/wav/wav.go
new file mode 100644
index 0000000..b82ec16
--- /dev/null
+++ b/wav/wav.go
@@ -0,0 +1,177 @@
+package wav
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+)
+
+type WavFile struct {
+ Header Header
+ Format FormatChunk
+ Data DataChunk
+}
+
+type Header struct {
+ GroupID [4]uint8
+ FileLength uint32
+ RiffType [4]uint8
+}
+
+type FormatChunk struct {
+ GroupID [4]uint8
+ ChunkSize uint32
+ FormatTag uint16
+ Channels uint16
+ SampleRate uint32
+ ByteRate uint32
+ Alignment uint16
+ BitDensity uint32
+}
+
+type DataChunk struct {
+ GroupID [4]uint8
+ ChunkSize uint32
+ Samples io.Reader
+}
+
+func Load(filename string) (*WavFile, error) {
+ file, err := os.Open(filename)
+
+ if err != nil {
+ return nil, err
+ }
+
+ load16 := func(b []byte) (uint16, error) {
+ var out uint16
+ err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out)
+ return out, err
+ }
+
+ load32 := func(b []byte) (uint32, error) {
+ var out uint32
+ err := binary.Read(bytes.NewBuffer(b), binary.LittleEndian, &out)
+ return out, err
+
+ }
+
+ b, err := ioutil.ReadAll(io.LimitReader(file, 40))
+ if err != nil {
+ return nil, err
+ }
+
+ h := Header{}
+ h.FileLength, err = load32(b[4:36])
+ if err != nil {
+ return nil, err
+ }
+ h.FileLength -= 8 // subtract RIFF/WAVE markers
+
+ for i := 0; i < 4; i++ {
+ h.GroupID[i] = b[i]
+ h.RiffType[i] = b[i+36]
+ }
+
+ fmt.Println(h)
+ fmt.Println(string(h.RiffType[:]))
+
+ if string(h.GroupID[:]) != "RIFF" { // || string(h.RiffType[:]) != "WAVE" {
+ return nil, fmt.Errorf("invalid header!")
+ }
+
+ f := FormatChunk{}
+
+ file.Seek(40, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, 36))
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 4; i++ {
+ f.GroupID[i] = b[i]
+ }
+
+ f.ChunkSize, err = load32(b[4:36])
+ if err != nil {
+ return nil, err
+ }
+
+ file.Seek(76, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, int64(f.ChunkSize)))
+ if err != nil {
+ return nil, err
+ }
+
+ f.FormatTag, err = load16(b[36:52])
+ if err != nil {
+ return nil, err
+ }
+
+ f.Channels, err = load16(b[52:68])
+ if err != nil {
+ return nil, err
+ }
+
+ f.SampleRate, err = load32(b[68:100])
+ if err != nil {
+ return nil, err
+ }
+
+ f.ByteRate, err = load32(b[100:132])
+ if err != nil {
+ return nil, err
+ }
+
+ f.Alignment, err = load16(b[132:148])
+ if err != nil {
+ return nil, err
+ }
+
+ f.BitDensity, err = load32(b[138:180])
+ if err != nil {
+ return nil, err
+ }
+
+ if string(f.GroupID[:]) != "fmt " ||
+ f.FormatTag != 1 ||
+ f.Alignment != uint16((uint32(f.Channels)*f.BitDensity/8)&0xff) {
+ return nil, fmt.Errorf("invalid format block!")
+ }
+
+ if f.BitDensity != 16 || f.Channels != 2 || f.SampleRate != 44100 {
+ return nil, fmt.Errorf("wrong pcm format!")
+ }
+
+ d := DataChunk{}
+
+ file.Seek(220, io.SeekStart)
+ b, err = ioutil.ReadAll(io.LimitReader(file, 36))
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 4; i++ {
+ d.GroupID[i] = b[i]
+ }
+
+ d.ChunkSize, err = load32(b[4:])
+ if err != nil {
+ return nil, err
+ }
+
+ if string(f.GroupID[:]) != "fmt " {
+ return nil, fmt.Errorf("invalid data block!")
+ }
+
+ file.Seek(256, io.SeekStart)
+ d.Samples = io.LimitReader(file, int64(d.ChunkSize))
+
+ return &WavFile{
+ Header: h,
+ Format: f,
+ Data: d,
+ }, nil
+}
diff --git a/wav/wav_test.go b/wav/wav_test.go
new file mode 100644
index 0000000..4fa64db
--- /dev/null
+++ b/wav/wav_test.go
@@ -0,0 +1,15 @@
+package wav
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestLoad(t *testing.T) {
+ wf, err := Load("../downloader/out.wav")
+ if err != nil {
+ t.Error(err)
+ }
+
+ fmt.Println(wf)
+}