mirror of
https://github.com/make-42/hayai.git
synced 2025-01-19 02:47:35 +01:00
68 lines
2.1 KiB
Go
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
|