fix: measure FLAC files that have data after the audio

This commit is contained in:
DiheChen committed 2026-11-05 12:13:19 +08:00
1 parent 2fb58e001e
commit 5fdeda2ede
2 files changed
+42

No files matched your search

+6
View File
@@ -318,8 +318,13 @@ func newFLACDecoder(r io.Reader) (Decoder, error) {
info := stream.Info
divisor := float64(int64(1) << (info.BitsPerSample - 1))
d := &streamDecoder{rate: int(info.SampleRate), ch: int(info.NChannels)}
var decoded uint64
d.fill = func() error {
for {
// QQ 音乐的 FLAC 在音频之后还有数据:继续读会被当成音频帧报错,整首的分析结果都会作废。NSamples 为 0 表示文件没有声明总数。
if info.NSamples > 0 && decoded >= info.NSamples {
return io.EOF
}
frame, err := stream.ParseNext()
if err != nil {
return err // 含 io.EOF
@@ -328,6 +333,7 @@ func newFLACDecoder(r io.Reader) (Decoder, error) {
continue
}
n := frame.Subframes[0].NSamples
decoded += uint64(n)
ch := len(frame.Subframes)
out := d.q.buf[d.q.grow(n*ch):]
for c, sub := range frame.Subframes {
+36
View File
@@ -271,6 +271,42 @@ func TestDecodeRejectsUndecodableMP3(t *testing.T) {
}
}
func TestDecodeFLACStopsAtDeclaredSamples(t *testing.T) {
file, err := os.ReadFile("testdata/sine.flac")
if err != nil {
t.Fatal(err)
}
want, err := Decode(bytes.NewReader(file))
if err != nil {
t.Fatal(err)
}
withTrailer := append(slices.Clone(file), 0x00, 0x01, 0x02, 0x03)
got, err := Decode(bytes.NewReader(withTrailer))
if err != nil {
t.Fatalf("音频之后有多余数据:%v", err)
}
if got.Frames() != want.Frames() {
t.Errorf("采样帧 = %d,期望 %d", got.Frames(), want.Frames())
}
// STREAMINFO 的总采样数占第 21 字节的低 4 位和之后的 4 个字节,全 0 表示未知。
undeclared := slices.Clone(file)
undeclared[21] &= 0xF0
clear(undeclared[22:26])
got, err = Decode(bytes.NewReader(undeclared))
if err != nil {
t.Fatal(err)
}
if got.Frames() != want.Frames() {
t.Errorf("未声明总采样数时采样帧 = %d,期望读到文件结束的 %d", got.Frames(), want.Frames())
}
if _, err := Decode(bytes.NewReader(file[:len(file)-200])); err == nil {
t.Error("音频比声明的少时应该报错")
}
}
func TestDamageReportsSkippedMP3Data(t *testing.T) {
decode := func(t *testing.T, file []byte) Decoder {
t.Helper()