Skip to content

Coping with damaged flac files #31

@mehrvarz

Description

@mehrvarz

Hi. With some flac files (rather rare, but still) I get "crc mismatch" messages, either on startup or at some later point during playback. In some cases I see an additional message such as this: "frame.Subframe.decodeRicePart: The flac library test cases do not yet include any audio files with Rice parameter escape codes. If possible please consider contributing this audio sample to improve the reliability of the test cases." Is it fair to assume that an internally damaged flac file could cause such a message to show up? All crc mismatch messages lead to a program abort, which is not ideal.

In some cases I didn't get a crc mismatch message, but a direct array overrun panic. I added three "if" statements to make the code skip over these situations. I have not seen a single array overrun since. See my code changes ("tmtmtm") below. Do you agree that making the decoder more robust against damaged flac files is a reasonable goal?

frame.go:

func (frame *Frame) correlate() {
	switch frame.Channels {
	case ChannelsLeftSide:
		// 2 channels: left, side; using inter-channel decorrelation.
		left := frame.Subframes[0].Samples
		side := frame.Subframes[1].Samples
		for i := range side {
			// right = left - side
			if i<len(left) {	                   // tmtmtm
				side[i] = left[i] - side[i]
			}
		}

subframe.go:

func (subframe *Subframe) decodeLPC(coeffs []int32, shift int32) error {
	if len(coeffs) != subframe.Order {
		return fmt.Errorf("frame.Subframe.decodeLPC: prediction order (%d) differs from number of coefficients (%d)", subframe.Order, len(coeffs))
	}
	if shift < 0 {
		return fmt.Errorf("frame.Subframe.decodeLPC: invalid negative shift")
	}
	for i := subframe.Order; i < subframe.NSamples; i++ {
		var sample int64
		for j, c := range coeffs {
			if i-j-1 < len(subframe.Samples) {	     // tmtmtm
				sample += int64(c) * int64(subframe.Samples[i-j-1])
			}
		}
		if i<len(subframe.Samples) {	                    // tmtmtm
			subframe.Samples[i] += int32(sample >> uint(shift))
		}
	}
	return nil
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions