flacgo/meta/streaminfo.go

117 lines
2.9 KiB
Go
Raw Normal View History

package meta
2014-08-06 03:56:33 +00:00
import (
"crypto/md5"
"errors"
"fmt"
"io"
2022-07-16 22:07:10 +00:00
"git.gammaspectra.live/S.O.N.G/flacgo/internal/bits"
2014-08-06 03:56:33 +00:00
)
2014-08-05 21:20:57 +00:00
2014-08-05 23:25:31 +00:00
// StreamInfo contains the basic properties of a FLAC audio stream, such as its
// sample rate and channel count. It is the only mandatory metadata block and
// must be present as the first metadata block of a FLAC stream.
//
// ref: https://www.xiph.org/flac/format.html#metadata_block_streaminfo
2014-08-05 21:20:57 +00:00
type StreamInfo struct {
2014-08-06 03:56:33 +00:00
// Minimum block size (in samples) used in the stream; between 16 and 65535
// samples.
2014-08-05 21:20:57 +00:00
BlockSizeMin uint16
2014-08-06 03:56:33 +00:00
// Maximum block size (in samples) used in the stream; between 16 and 65535
// samples.
2014-08-05 21:20:57 +00:00
BlockSizeMax uint16
// Minimum frame size in bytes; a 0 value implies unknown.
FrameSizeMin uint32
// Maximum frame size in bytes; a 0 value implies unknown.
FrameSizeMax uint32
// Sample rate in Hz; between 1 and 655350 Hz.
SampleRate uint32
// Number of channels; between 1 and 8 channels.
NChannels uint8
// Sample size in bits-per-sample; between 4 and 32 bits.
BitsPerSample uint8
// Total number of inter-channel samples in the stream. One second of 44.1
// KHz audio will have 44100 samples regardless of the number of channels. A
// 0 value implies unknown.
NSamples uint64
// MD5 checksum of the unencoded audio data.
2014-08-06 03:56:33 +00:00
MD5sum [md5.Size]uint8
2014-08-05 21:20:57 +00:00
}
// parseStreamInfo reads and parses the body of a StreamInfo metadata block.
func (block *Block) parseStreamInfo() error {
2014-08-06 03:56:33 +00:00
// 16 bits: BlockSizeMin.
2014-09-30 00:24:15 +00:00
br := bits.NewReader(block.lr)
2014-08-06 03:56:33 +00:00
x, err := br.Read(16)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
if x < 16 {
return fmt.Errorf("meta.Block.parseStreamInfo: invalid minimum block size (%d); expected >= 16", x)
}
si := new(StreamInfo)
block.Body = si
si.BlockSizeMin = uint16(x)
// 16 bits: BlockSizeMax.
x, err = br.Read(16)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
if x < 16 {
return fmt.Errorf("meta.Block.parseStreamInfo: invalid maximum block size (%d); expected >= 16", x)
}
si.BlockSizeMax = uint16(x)
// 24 bits: FrameSizeMin.
x, err = br.Read(24)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
si.FrameSizeMin = uint32(x)
// 24 bits: FrameSizeMax.
x, err = br.Read(24)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
si.FrameSizeMax = uint32(x)
// 20 bits: SampleRate.
x, err = br.Read(20)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
if x == 0 {
return errors.New("meta.Block.parseStreamInfo: invalid sample rate (0)")
}
si.SampleRate = uint32(x)
// 3 bits: NChannels.
x, err = br.Read(3)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
// x contains: (number of channels) - 1
si.NChannels = uint8(x + 1)
// 5 bits: BitsPerSample.
x, err = br.Read(5)
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
// x contains: (bits-per-sample) - 1
si.BitsPerSample = uint8(x + 1)
// 36 bits: NSamples.
2014-08-06 04:08:13 +00:00
si.NSamples, err = br.Read(36)
2014-08-06 03:56:33 +00:00
if err != nil {
return unexpected(err)
2014-08-06 03:56:33 +00:00
}
// 16 bytes: MD5sum.
_, err = io.ReadFull(block.lr, si.MD5sum[:])
return unexpected(err)
}