306014abef
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.
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
|