From 1d75c9e9678b6d8a11a9f29f13d55a391979ebed Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 14 Jul 2024 18:33:13 +0900 Subject: [PATCH] audio/internal/convert: Seek with incomplete bytes should work Usually users use audio.Player objects and doesn't use Resampling object directly. Resampling object itself is exposed by audio.Resample, but this is usually used with audio.Player objects. Thus, this issue is not so serious in the real world. --- audio/internal/convert/resampling.go | 2 ++ audio/internal/convert/resampling_test.go | 28 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/audio/internal/convert/resampling.go b/audio/internal/convert/resampling.go index 30851ae44..967efd69a 100644 --- a/audio/internal/convert/resampling.go +++ b/audio/internal/convert/resampling.go @@ -298,5 +298,7 @@ func (r *Resampling) Seek(offset int64, whence int) (int64, error) { if r.Length() <= r.pos { r.pos = r.Length() } + size := r.bytesPerSample() + r.pos = r.pos / int64(size) * int64(size) return r.pos, nil } diff --git a/audio/internal/convert/resampling_test.go b/audio/internal/convert/resampling_test.go index ab31057e7..6dcf54a74 100644 --- a/audio/internal/convert/resampling_test.go +++ b/audio/internal/convert/resampling_test.go @@ -89,9 +89,31 @@ func TestResampling(t *testing.T) { t.Run(fmt.Sprintf("bitDepthInBytes=%d", bitDepthInBytes), func(t *testing.T) { inB := newSoundBytes(c.In, bitDepthInBytes) outS := convert.NewResampling(bytes.NewReader(inB), int64(len(inB)), c.In, c.Out, bitDepthInBytes) - gotB, err := io.ReadAll(outS) - if err != nil { - t.Fatal(err) + var gotB []byte + for { + var buf [97]byte + n, err := outS.Read(buf[:]) + gotB = append(gotB, buf[:n]...) + if err != nil { + if err != io.EOF { + t.Fatal(err) + } + break + } + cur, err := outS.Seek(0, io.SeekCurrent) + if err != nil { + t.Fatal(err) + } + // Shifting by incomplete bytes should not affect the result. + for i := 0; i < bitDepthInBytes*2-1; i++ { + pos, err := outS.Seek(int64(i), io.SeekCurrent) + if err != nil { + t.Fatal(err) + } + if cur != pos { + t.Errorf("cur: %d, pos: %d", cur, pos) + } + } } wantB := newSoundBytes(c.Out, bitDepthInBytes) if len(gotB) != len(wantB) {