Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix FileSize for saving .wav #6

Merged
merged 7 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ require (
github.com/hajimehoshi/oto v0.7.1
github.com/jfreymuth/oggvorbis v1.0.1
github.com/mewkiz/flac v1.0.7
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/icza/bitio v1.0.0 // indirect
github.com/jfreymuth/vorbis v1.0.0 // indirect
github.com/lucasb-eyer/go-colorful v1.0.2 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 // indirect
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067 // indirect
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 // indirect
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 // indirect
golang.org/x/text v0.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
Expand Down Expand Up @@ -29,9 +31,15 @@ github.com/mewkiz/flac v1.0.7 h1:uIXEjnuXqdRaZttmSFM5v5Ukp4U6orrZsnYGGR3yow8=
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 h1:EyTNMdePWaoWsRSGQnXiSoQu0r6RS1eA557AwJhlzHU=
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 h1:idBdZTd9UioThJp8KpM/rTSinK/ChZFBE43/WtIy8zg=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
Expand All @@ -46,3 +54,7 @@ golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeo
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
105 changes: 105 additions & 0 deletions wav/decode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package wav

import (
"bytes"
"github.com/gopxl/beep"
"github.com/stretchr/testify/assert"
"testing"
)

func TestDecode(t *testing.T) {
wav := []byte{
// Riff mark
'R', 'I', 'F', 'F',
// File size without riff mark and file size
0x38, 0x00, 0x00, 0x00, // 56 bytes
// Wave mark
'W', 'A', 'V', 'E',

// Fmt mark
'f', 'm', 't', ' ',
// Format chunk size
0x10, 0x00, 0x00, 0x00, // 16 bytes
// Format type
0x01, 0x00, // 1 = PCM
// Number of channels,
0x02, 0x00,
// Sample rate
0x44, 0xAC, 0x00, 0x00, // 44100 samples/sec
// Byte rate
0x10, 0xB1, 0x02, 0x00, // 44100 * 2 bytes/sample precision * 2 channels = 176400 bytes/sec
// Bytes per frame
0x04, 0x00, // 2 bytes/sample precision * 2 channels = 4 bytes/frame
// Bits per sample
0x10, 0x00, // 2 bytes/sample precision = 16 bits/sample

// Data mark
'd', 'a', 't', 'a',
// Data size
0x14, 0x00, 0x00, 0x00, // 5 samples * 2 bytes/sample precision * 2 channels = 20 bytes
// Data
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}

r := bytes.NewReader(wav)

s, f, err := Decode(r)
if err != nil {
t.Fatalf("failed to decode the WAV file: %v", err)
}

assert.Equal(t, beep.Format{
SampleRate: 44100,
NumChannels: 2,
Precision: 2,
}, f)

assert.NoError(t, s.Err())
assert.Equal(t, 5, s.Len())
assert.Equal(t, 0, s.Position())

samples := make([][2]float64, 3)
// Stream first few bytes
n, ok := s.Stream(samples)
assert.Equal(t, 3, n)
assert.Truef(t, ok, "the decoder failed to stream the samples")
assert.Equal(t, 3, s.Position())
assert.NoError(t, s.Err())
// Drain the streamer
n, ok = s.Stream(samples)
assert.Equal(t, 2, n)
assert.Truef(t, ok, "the decoder failed to stream the samples")
assert.Equal(t, 5, s.Position())
assert.NoError(t, s.Err())
// Drain the streamer some more
n, ok = s.Stream(samples)
assert.Equal(t, 0, n)
assert.Equal(t, 5, s.Position())
assert.Falsef(t, ok, "expected the decoder to return false after it was fully drained")
assert.NoError(t, s.Err())

d, ok := s.(*decoder)
if !ok {
t.Fatal("Streamer is not a decoder")
}

assert.Equal(t, header{
RiffMark: [4]byte{'R', 'I', 'F', 'F'},
FileSize: 56, // without the riff mark and file size
WaveMark: [4]byte{'W', 'A', 'V', 'E'},
FmtMark: [4]byte{'f', 'm', 't', ' '},
FormatSize: 16,
FormatType: 1, // 1 = PCM
NumChans: 2,
SampleRate: 44100,
ByteRate: 176400, // 44100 * 2 bytes/sample precision * 2 channels = 176400 bytes/sec
BytesPerFrame: 4, // 2 bytes/sample precision * 2 channels = 4 bytes/frame
BitsPerSample: 16, // 2 bytes/sample precision = 16 bits/sample
DataMark: [4]byte{'d', 'a', 't', 'a'},
DataSize: 20, // 5 samples * 2 bytes/sample precision * 2 channels = 20 bytes
}, d.h)
}
2 changes: 1 addition & 1 deletion wav/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func Encode(w io.WriteSeeker, s beep.Streamer, format beep.Format) (err error) {
}

// finalize header
h.FileSize = int32(44 + written) // 44 is the size of the header
h.FileSize = int32(44 - 8 + written) // 44-8 is the size of the header without RIFF signature and the length of the RIFF chunk
h.DataSize = int32(written)
if _, err := w.Seek(0, io.SeekStart); err != nil {
return err
Expand Down
71 changes: 71 additions & 0 deletions wav/encode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package wav

import (
"github.com/gopxl/beep"
"github.com/orcaman/writerseeker"
"github.com/stretchr/testify/assert"
"testing"
)

func TestEncode(t *testing.T) {
var f = beep.Format{
SampleRate: 44100,
NumChannels: 2,
Precision: 2,
}
var w writerseeker.WriterSeeker
var s = beep.Silence(5)

err := Encode(&w, s, f)
if err != nil {
t.Fatalf("encoding failed with error: %v", err)
}

r := w.BytesReader()
expectedWrittenSize := 44 /* header length */ + 5*f.Precision*f.NumChannels /* number of samples * bytes per sample * number of channels */
assert.Equal(t, expectedWrittenSize, r.Len(), "the encoded file doesn't have the right size")

encoded := make([]byte, r.Len())
_, err = w.Reader().Read(encoded)
if err != nil {
t.Fatalf("failed reading the buffer: %v", err)
}

// Everything is encoded using little endian.
assert.Equal(t, []byte{
// Riff mark
'R', 'I', 'F', 'F',
// File size without riff mark and file size
0x38, 0x00, 0x00, 0x00, // 56 bytes
// Wave mark
'W', 'A', 'V', 'E',

// Fmt mark
'f', 'm', 't', ' ',
// Format chunk size
0x10, 0x00, 0x00, 0x00, // 16 bytes
// Format type
0x01, 0x00, // 1 = PCM
// Number of channels,
0x02, 0x00,
// Sample rate
0x44, 0xAC, 0x00, 0x00, // 44100 samples/sec
// Byte rate
0x10, 0xB1, 0x02, 0x00, // 44100 * 2 bytes/sample precision * 2 channels = 176400 bytes/sec
// Bytes per frame
0x04, 0x00, // 2 bytes/sample precision * 2 channels = 4 bytes/frame
// Bits per sample
0x10, 0x00, // 2 bytes/sample precision = 16 bits/sample

// Data mark
'd', 'a', 't', 'a',
// Data size
0x14, 0x00, 0x00, 0x00, // 5 samples * 2 bytes/sample precision * 2 channels = 20 bytes
// Data
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}, encoded, "the encoded file isn't formatted as expected")
}