flacgo/meta/seektable.go
mewmew 306014abef flac: Add preliminary encoding support.
Support for encoding metadata has been added.

Proper support for encoding audio samples is yet to be
implemented. For now, simply copy the original encoded
audio data from the source FLAC file.

The API mirrors that of image.Encode.

Updates #14.
2016-07-20 06:38:19 +02:00

68 lines
2.1 KiB
Go

package meta
import (
"encoding/binary"
"errors"
"fmt"
)
// 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 {
// 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
for i := range table.Points {
point := &table.Points[i]
err := binary.Read(block.lr, binary.BigEndian, point)
if err != nil {
return unexpected(err)
}
// 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)
}
}
}
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