Skip to content

Commit

Permalink
Fix flac.Seek()
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkKremer committed Aug 3, 2024
1 parent 9019b85 commit cb5e727
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
14 changes: 13 additions & 1 deletion flac/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,19 @@ func (d *decoder) Seek(p int) error {
}

pos, err := d.stream.Seek(uint64(p))
d.pos = int(pos)
if err != nil {
return errors.Wrap(err, "flac")
}

toDiscard := p - int(pos)
err = d.refill()
if err != nil {
return err
}
d.buf = d.buf[toDiscard:]

d.pos = p

return err
}

Expand Down
38 changes: 32 additions & 6 deletions flac/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

func TestDecoder_ReturnBehaviour(t *testing.T) {
f, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples.flac"))
f, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples_ffmpeg.flac"))
assert.NoError(t, err)
defer f.Close()

Expand All @@ -27,12 +27,38 @@ func TestDecoder_ReturnBehaviour(t *testing.T) {
testtools.AssertStreamerHasCorrectReturnBehaviour(t, s, s.Len())
}

func TestDecoder_Stream(t *testing.T) {
flacFile, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples_ffmpeg.flac"))
assert.NoError(t, err)
defer flacFile.Close()

// Use WAV file as reference. Since both FLAC and WAV are lossless, comparing
// the samples should be possible (allowing for some floating point errors).
wavFile, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples.wav"))
assert.NoError(t, err)
defer wavFile.Close()

flacStream, _, err := flac.Decode(flacFile)
assert.NoError(t, err)

wavStream, _, err := wav.Decode(wavFile)
assert.NoError(t, err)

assert.Equal(t, wavStream.Len(), flacStream.Len())

wavSamples := testtools.Collect(wavStream)
flacSamples := testtools.Collect(flacStream)

testtools.AssertSamplesEqual(t, wavSamples, flacSamples)
}

func TestDecoder_Seek(t *testing.T) {
flacFile, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples.flac"))
flacFile, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples_ffmpeg.flac"))
assert.NoError(t, err)
defer flacFile.Close()

// Use WAV file as reference
// Use WAV file as reference. Since both FLAC and WAV are lossless, comparing
// the samples should be possible (allowing for some floating point errors).
wavFile, err := os.Open(testtools.TestFilePath("valid_44100hz_22050_samples.wav"))
assert.NoError(t, err)
defer wavFile.Close()
Expand Down Expand Up @@ -63,7 +89,7 @@ func TestDecoder_Seek(t *testing.T) {

wavSamples := testtools.CollectNum(100, wavStream)
flacSamples := testtools.CollectNum(100, flacStream)
assert.Equal(t, wavSamples, flacSamples)
testtools.AssertSamplesEqual(t, wavSamples, flacSamples)

// Test middle of 2nd frame
seekPos = (int(frameStarts[1]) + int(frameStarts[2])) / 2
Expand All @@ -76,7 +102,7 @@ func TestDecoder_Seek(t *testing.T) {

wavSamples = testtools.CollectNum(100, wavStream)
flacSamples = testtools.CollectNum(100, flacStream)
assert.Equal(t, wavSamples, flacSamples)
testtools.AssertSamplesEqual(t, wavSamples, flacSamples)

// Test end of 2nd frame
seekPos = int(frameStarts[2]) - 1
Expand All @@ -89,7 +115,7 @@ func TestDecoder_Seek(t *testing.T) {

wavSamples = testtools.CollectNum(100, wavStream)
flacSamples = testtools.CollectNum(100, flacStream)
assert.Equal(t, wavSamples, flacSamples)
testtools.AssertSamplesEqual(t, wavSamples, flacSamples)
}

func getFlacFrameStartPositions(r io.Reader) ([]uint64, error) {
Expand Down
Binary file removed internal/testdata/valid_44100hz_22050_samples.flac
Binary file not shown.
Binary file not shown.
22 changes: 22 additions & 0 deletions internal/testtools/asserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,25 @@ func AssertStreamerHasCorrectReturnBehaviour(t *testing.T, s beep.Streamer, expe
assert.Equal(t, 0, n)
assert.NoError(t, s.Err())
}

func AssertSamplesEqual(t *testing.T, expected, actual [][2]float64) {
t.Helper()

if len(expected) != len(actual) {
t.Errorf("expected sample data length to be %d, got %d", len(expected), len(actual))
return
}

const epsilon = 1e-9
equals := true
for i := range expected {
if actual[i][0] < expected[i][0]-epsilon || actual[i][0] > expected[i][0]+epsilon ||
actual[i][1] < expected[i][1]-epsilon || actual[i][1] > expected[i][1]+epsilon {
equals = false
break
}
}
if !equals {
t.Errorf("the sample data isn't equal to the expected data")
}
}

0 comments on commit cb5e727

Please sign in to comment.