forked from mewkiz/flac
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencode_subframe.go
More file actions
127 lines (115 loc) · 4.03 KB
/
Copy pathencode_subframe.go
File metadata and controls
127 lines (115 loc) · 4.03 KB
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
117
118
119
120
121
122
123
124
125
126
127
package flac
import (
"github.com/icza/bitio"
"github.com/mewkiz/flac/frame"
iobits "github.com/mewkiz/flac/internal/bits"
"github.com/mewkiz/pkg/errutil"
)
// --- [ Subframe ] ------------------------------------------------------------
// encodeSubframe encodes the given subframe, writing to bw.
func encodeSubframe(bw *bitio.Writer, hdr frame.Header, subframe *frame.Subframe) error {
// Encode subframe header.
if err := encodeSubframeHeader(bw, subframe.SubHeader); err != nil {
return errutil.Err(err)
}
// Encode audio samples.
switch subframe.Pred {
case frame.PredConstant:
if err := encodeConstantSamples(bw, hdr.BitsPerSample, subframe.Samples); err != nil {
return errutil.Err(err)
}
case frame.PredVerbatim:
if err := encodeVerbatimSamples(bw, hdr, subframe.Samples); err != nil {
return errutil.Err(err)
}
//case frame.PredFixed:
// if err := encodeFixedSamples(bw, hdr, subframe.Samples, subframe.Order); err != nil {
// return errutil.Err(err)
// }
//case frame.PredFIR:
// if err := encodeFIRSamples(bw, hdr, subframe.Samples, subframe.Order); err != nil {
// return errutil.Err(err)
// }
default:
return errutil.Newf("support for prediction method %v not yet implemented", subframe.Pred)
}
return nil
}
// --- [ Subframe header ] -----------------------------------------------------
// encodeSubframeHeader encodes the given subframe header, writing to bw.
func encodeSubframeHeader(bw *bitio.Writer, hdr frame.SubHeader) error {
// Zero bit padding, to prevent sync-fooling string of 1s.
if err := bw.WriteBits(0x0, 1); err != nil {
return errutil.Err(err)
}
// Subframe type:
// 000000 : SUBFRAME_CONSTANT
// 000001 : SUBFRAME_VERBATIM
// 00001x : reserved
// 0001xx : reserved
// 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved
// 01xxxx : reserved
// 1xxxxx : SUBFRAME_LPC, xxxxx=order-1
var bits uint64
switch hdr.Pred {
case frame.PredConstant:
// 000000 : SUBFRAME_CONSTANT
bits = 0x00
case frame.PredVerbatim:
// 000001 : SUBFRAME_VERBATIM
bits = 0x01
case frame.PredFixed:
// 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved
bits = 0x08 | uint64(hdr.Order)
case frame.PredFIR:
// 1xxxxx : SUBFRAME_LPC, xxxxx=order-1
bits = 0x20 | uint64(hdr.Order-1)
}
if err := bw.WriteBits(bits, 6); err != nil {
return errutil.Err(err)
}
// <1+k> 'Wasted bits-per-sample' flag:
//
// 0 : no wasted bits-per-sample in source subblock, k=0
// 1 : k wasted bits-per-sample in source subblock, k-1 follows, unary coded; e.g. k=3 => 001 follows, k=7 => 0000001 follows.
hasWastedBits := hdr.Wasted > 0
if err := bw.WriteBool(hasWastedBits); err != nil {
return errutil.Err(err)
}
if hasWastedBits {
if err := iobits.WriteUnary(bw, uint64(hdr.Wasted)); err != nil {
return errutil.Err(err)
}
}
return nil
}
// --- [ Constant samples ] ----------------------------------------------------
// encodeConstantSamples stores the given constant sample, writing to bw.
func encodeConstantSamples(bw *bitio.Writer, bps byte, samples []int32) error {
sample := samples[0]
for _, s := range samples[1:] {
if sample != s {
return errutil.Newf("constant sample mismatch; expected %v, got %v", sample, s)
}
}
// Unencoded constant value of the subblock, n = frame's bits-per-sample.
if err := bw.WriteBits(uint64(sample), bps); err != nil {
return errutil.Err(err)
}
return nil
}
// --- [ Verbatim samples ] ----------------------------------------------------
// encodeVerbatimSamples stores the given samples verbatim (uncompressed),
// writing to bw.
func encodeVerbatimSamples(bw *bitio.Writer, hdr frame.Header, samples []int32) error {
// Unencoded subblock; n = frame's bits-per-sample, i = frame's blocksize.
if int(hdr.BlockSize) != len(samples) {
return errutil.Newf("block size and sample count mismatch; expected %d, got %d", hdr.BlockSize, len(samples))
}
for _, sample := range samples {
if err := bw.WriteBits(uint64(sample), hdr.BitsPerSample); err != nil {
return errutil.Err(err)
}
}
return nil
}