flacgo/meta/seektable.go

68 lines
2.1 KiB
Go
Raw Normal View History

package meta
2014-08-06 04:08:13 +00:00
import (
"encoding/binary"
"errors"
"fmt"
2014-08-06 04:08:13 +00:00
)
2014-08-06 01:08:02 +00:00
// SeekTable contains one or more pre-calculated audio frame seek points.
//
// ref: https://www.xiph.org/flac/format.html#metadata_block_seektable
type SeekTable struct {
// One or more seek points.
Points []SeekPoint
}
// parseSeekTable reads and parses the body of a SeekTable metadata block.
func (block *Block) parseSeekTable() error {
2014-08-06 04:08:13 +00:00
// The number of seek points is derived from the header length, divided by
// the size of a SeekPoint; which is 18 bytes.
n := block.Length / 18
if n < 1 {
return errors.New("meta.Block.parseSeekTable: at least one seek point is required")
}
table := &SeekTable{Points: make([]SeekPoint, n)}
block.Body = table
var prev uint64
2014-08-06 04:08:13 +00:00
for i := range table.Points {
point := &table.Points[i]
err := binary.Read(block.lr, binary.BigEndian, point)
2014-08-06 04:08:13 +00:00
if err != nil {
return unexpected(err)
2014-08-06 04:08:13 +00:00
}
// Seek points within a table must be sorted in ascending order by sample
// number. Each seek point must have a unique sample number, except for
// placeholder points.
sampleNum := point.SampleNum
if i != 0 && sampleNum != PlaceholderPoint {
switch {
case sampleNum < prev:
return fmt.Errorf("meta.Block.parseSeekTable: invalid seek point order; sample number (%d) < prev (%d)", sampleNum, prev)
case sampleNum == prev:
return fmt.Errorf("meta.Block.parseSeekTable: duplicate seek point with sample number (%d)", sampleNum)
}
}
2014-08-06 04:08:13 +00:00
}
return nil
}
// A SeekPoint specifies the byte offset and initial sample number of a given
// target frame.
//
// ref: https://www.xiph.org/flac/format.html#seekpoint
type SeekPoint struct {
// Sample number of the first sample in the target frame, or
// 0xFFFFFFFFFFFFFFFF for a placeholder point.
SampleNum uint64
// Offset in bytes from the first byte of the first frame header to the first
// byte of the target frame's header.
Offset uint64
// Number of samples in the target frame.
NSamples uint16
}
// PlaceholderPoint represent the sample number used to specify placeholder seek
// points.
const PlaceholderPoint = 0xFFFFFFFFFFFFFFFF