forked from mewkiz/flac
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstreaminfo.go
116 lines (104 loc) · 2.88 KB
/
streaminfo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package meta
import (
"crypto/md5"
"errors"
"fmt"
"io"
"gopkg.in/mewpkg/bits.v1"
)
// 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
type StreamInfo struct {
// Minimum block size (in samples) used in the stream; between 16 and 65535
// samples.
BlockSizeMin uint16
// Maximum block size (in samples) used in the stream; between 16 and 65535
// samples.
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.
MD5sum [md5.Size]uint8
}
// parseStreamInfo reads and parses the body of an StreamInfo metadata block.
func (block *Block) parseStreamInfo() error {
// 16 bits: BlockSizeMin.
br := bits.NewReader(block.lr)
x, err := br.Read(16)
if err != nil {
return unexpected(err)
}
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)
}
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)
}
si.FrameSizeMin = uint32(x)
// 24 bits: FrameSizeMax.
x, err = br.Read(24)
if err != nil {
return unexpected(err)
}
si.FrameSizeMax = uint32(x)
// 20 bits: SampleRate.
x, err = br.Read(20)
if err != nil {
return unexpected(err)
}
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)
}
// 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)
}
// x contains: (bits-per-sample) - 1
si.BitsPerSample = uint8(x + 1)
// 36 bits: NSamples.
si.NSamples, err = br.Read(36)
if err != nil {
return unexpected(err)
}
// 16 bytes: MD5sum.
_, err = io.ReadFull(block.lr, si.MD5sum[:])
return unexpected(err)
}