• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mewkiz / flac / 6713408042

31 Oct 2023 11:04PM UTC coverage: 68.265% (+4.9%) from 63.409%
6713408042

push

github

mewmew
internal/bits: minor updates of TestUnary for consistency

Run `goimports -w` to sort imports and change order of
"expected xx, got xx" to match other test cases
(e.g. TestZigZag).

1680 of 2461 relevant lines covered (68.26%)

4364391.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.11
/encode_frame.go
1
package flac
2

3
import (
4
        "encoding/binary"
5
        "io"
6
        "math"
7

8
        "github.com/icza/bitio"
9
        "github.com/mewkiz/flac/frame"
10
        "github.com/mewkiz/flac/internal/hashutil/crc16"
11
        "github.com/mewkiz/flac/internal/hashutil/crc8"
12
        "github.com/mewkiz/flac/internal/utf8"
13
        "github.com/mewkiz/pkg/errutil"
14
)
15

16
// --- [ Frame ] ---------------------------------------------------------------
17

18
// WriteFrame encodes the given audio frame to the output stream. The Num field
19
// of the frame header is automatically calculated by the encoder.
20
func (enc *Encoder) WriteFrame(f *frame.Frame) error {
36,895✔
21
        // Sanity checks.
36,895✔
22
        nchannels := int(enc.Info.NChannels)
36,895✔
23
        if nchannels != len(f.Subframes) {
36,895✔
24
                return errutil.Newf("subframe and channel count mismatch; expected %d, got %d", nchannels, len(f.Subframes))
×
25
        }
×
26
        nsamplesPerChannel := f.Subframes[0].NSamples
36,895✔
27
        for i, subframe := range f.Subframes {
112,124✔
28
                if nsamplesPerChannel != len(subframe.Samples) {
75,229✔
29
                        return errutil.Newf("invalid number of samples in channel %d; expected %d, got %d", i, nsamplesPerChannel, len(subframe.Samples))
×
30
                }
×
31
        }
32
        if nchannels != f.Channels.Count() {
36,895✔
33
                return errutil.Newf("channel count mismatch; expected %d, got %d", nchannels, f.Channels.Count())
×
34
        }
×
35

36
        // Create a new CRC-16 hash writer which adds the data from all write
37
        // operations to a running hash.
38
        h := crc16.NewIBM()
36,895✔
39
        hw := io.MultiWriter(h, enc.w)
36,895✔
40

36,895✔
41
        // Encode frame header.
36,895✔
42
        f.Num = enc.curNum
36,895✔
43
        if f.HasFixedBlockSize {
68,195✔
44
                enc.curNum++
31,300✔
45
        } else {
36,895✔
46
                enc.curNum += uint64(nsamplesPerChannel)
5,595✔
47
        }
5,595✔
48
        enc.nsamples += uint64(nsamplesPerChannel)
36,895✔
49
        blockSize := uint16(nsamplesPerChannel)
36,895✔
50
        if enc.blockSizeMin == 0 || blockSize < enc.blockSizeMin {
37,056✔
51
                enc.blockSizeMin = blockSize
161✔
52
        }
161✔
53
        if enc.blockSizeMax == 0 || blockSize > enc.blockSizeMax {
36,986✔
54
                enc.blockSizeMax = blockSize
91✔
55
        }
91✔
56
        // TODO: track number of bytes written to hw, to update values of
57
        // frameSizeMin and frameSizeMax.
58
        // Add unencoded audio samples to running MD5 hash.
59
        f.Hash(enc.md5sum)
36,895✔
60
        if err := enc.encodeFrameHeader(hw, f.Header); err != nil {
36,895✔
61
                return errutil.Err(err)
×
62
        }
×
63

64
        // Inter-channel decorrelation of subframe samples.
65
        f.Decorrelate()
36,895✔
66
        defer f.Correlate() // NOTE: revert decorrelation of audio samples after encoding is done (to make encode non-destructive).
36,895✔
67

36,895✔
68
        // Encode subframes.
36,895✔
69
        bw := bitio.NewWriter(hw)
36,895✔
70
        for channel, subframe := range f.Subframes {
112,124✔
71
                // The side channel requires an extra bit per sample when using
75,229✔
72
                // inter-channel decorrelation.
75,229✔
73
                bps := uint(f.BitsPerSample)
75,229✔
74
                switch f.Channels {
75,229✔
75
                case frame.ChannelsSideRight:
7,272✔
76
                        // channel 0 is the side channel.
7,272✔
77
                        if channel == 0 {
10,908✔
78
                                bps++
3,636✔
79
                        }
3,636✔
80
                case frame.ChannelsLeftSide, frame.ChannelsMidSide:
34,002✔
81
                        // channel 1 is the side channel.
34,002✔
82
                        if channel == 1 {
51,003✔
83
                                bps++
17,001✔
84
                        }
17,001✔
85
                }
86

87
                if err := encodeSubframe(bw, f.Header, subframe, bps); err != nil {
75,229✔
88
                        return errutil.Err(err)
×
89
                }
×
90
        }
91

92
        // Zero-padding to byte alignment.
93
        // Flush pending writes to subframe.
94
        if _, err := bw.Align(); err != nil {
36,895✔
95
                return errutil.Err(err)
×
96
        }
×
97

98
        // CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with 0) of
99
        // everything before the crc, back to and including the frame header sync
100
        // code.
101
        crc := h.Sum16()
36,895✔
102
        if err := binary.Write(enc.w, binary.BigEndian, crc); err != nil {
36,895✔
103
                return errutil.Err(err)
×
104
        }
×
105

106
        return nil
36,895✔
107
}
108

109
// --- [ Frame header ] --------------------------------------------------------
110

111
// encodeFrameHeader encodes the given frame header, writing to w.
112
func (enc *Encoder) encodeFrameHeader(w io.Writer, hdr frame.Header) error {
36,895✔
113
        // Create a new CRC-8 hash writer which adds the data from all write
36,895✔
114
        // operations to a running hash.
36,895✔
115
        h := crc8.NewATM()
36,895✔
116
        hw := io.MultiWriter(h, w)
36,895✔
117
        bw := bitio.NewWriter(hw)
36,895✔
118
        enc.c = bw
36,895✔
119

36,895✔
120
        //  Sync code: 11111111111110
36,895✔
121
        if err := bw.WriteBits(0x3FFE, 14); err != nil {
36,895✔
122
                return errutil.Err(err)
×
123
        }
×
124

125
        // Reserved: 0
126
        if err := bw.WriteBits(0x0, 1); err != nil {
36,895✔
127
                return errutil.Err(err)
×
128
        }
×
129

130
        // Blocking strategy:
131
        //    0 : fixed-blocksize stream; frame header encodes the frame number
132
        //    1 : variable-blocksize stream; frame header encodes the sample number
133
        if err := bw.WriteBool(!hdr.HasFixedBlockSize); err != nil {
36,895✔
134
                return errutil.Err(err)
×
135
        }
×
136

137
        // Encode block size.
138
        nblockSizeSuffixBits, err := encodeFrameHeaderBlockSize(bw, hdr.BlockSize)
36,895✔
139
        if err != nil {
36,895✔
140
                return errutil.Err(err)
×
141
        }
×
142

143
        // Encode sample rate.
144
        sampleRateSuffixBits, nsampleRateSuffixBits, err := encodeFrameHeaderSampleRate(bw, hdr.SampleRate)
36,895✔
145
        if err != nil {
36,895✔
146
                return errutil.Err(err)
×
147
        }
×
148

149
        // Encode channels assignment.
150
        if err := encodeFrameHeaderChannels(bw, hdr.Channels); err != nil {
36,895✔
151
                return errutil.Err(err)
×
152
        }
×
153

154
        // Encode bits-per-sample.
155
        if err := encodeFrameHeaderBitsPerSample(bw, hdr.BitsPerSample); err != nil {
36,895✔
156
                return errutil.Err(err)
×
157
        }
×
158

159
        // Reserved: 0
160
        if err := bw.WriteBits(0x0, 1); err != nil {
36,895✔
161
                return errutil.Err(err)
×
162
        }
×
163

164
        //    if (variable blocksize)
165
        //       <8-56>:"UTF-8" coded sample number (decoded number is 36 bits)
166
        //    else
167
        //       <8-48>:"UTF-8" coded frame number (decoded number is 31 bits)
168
        if err := utf8.Encode(bw, hdr.Num); err != nil {
36,895✔
169
                return errutil.Err(err)
×
170
        }
×
171

172
        // Write block size after the frame header (used for uncommon block sizes).
173
        if nblockSizeSuffixBits > 0 {
62,306✔
174
                // 0110 : get 8 bit (blocksize-1) from end of header
25,411✔
175
                // 0111 : get 16 bit (blocksize-1) from end of header
25,411✔
176
                if err := bw.WriteBits(uint64(hdr.BlockSize-1), nblockSizeSuffixBits); err != nil {
25,411✔
177
                        return errutil.Err(err)
×
178
                }
×
179
        }
180

181
        // Write sample rate after the frame header (used for uncommon sample rates).
182
        if nsampleRateSuffixBits > 0 {
38,068✔
183
                if err := bw.WriteBits(sampleRateSuffixBits, nsampleRateSuffixBits); err != nil {
1,173✔
184
                        return errutil.Err(err)
×
185
                }
×
186
        }
187

188
        // Flush pending writes to frame header.
189
        if _, err := bw.Align(); err != nil {
36,895✔
190
                return errutil.Err(err)
×
191
        }
×
192

193
        // CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) of
194
        // everything before the crc, including the sync code.
195
        crc := h.Sum8()
36,895✔
196
        if err := binary.Write(w, binary.BigEndian, crc); err != nil {
36,895✔
197
                return errutil.Err(err)
×
198
        }
×
199

200
        return nil
36,895✔
201
}
202

203
// ~~~ [ Block size ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204

205
// encodeFrameHeaderBlockSize encodes the block size of the frame header,
206
// writing to bw. It returns the number of bits used to store block size after
207
// the frame header.
208
func encodeFrameHeaderBlockSize(bw *bitio.Writer, blockSize uint16) (nblockSizeSuffixBits byte, err error) {
36,895✔
209
        // Block size in inter-channel samples:
36,895✔
210
        //    0000 : reserved
36,895✔
211
        //    0001 : 192 samples
36,895✔
212
        //    0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608
36,895✔
213
        //    0110 : get 8 bit (blocksize-1) from end of header
36,895✔
214
        //    0111 : get 16 bit (blocksize-1) from end of header
36,895✔
215
        //    1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768
36,895✔
216
        var bits uint64
36,895✔
217
        switch blockSize {
36,895✔
218
        case 192:
2,272✔
219
                // 0001
2,272✔
220
                bits = 0x1
2,272✔
221
        case 576, 1152, 2304, 4608:
752✔
222
                // 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608
752✔
223
                bits = 0x2 + uint64(math.Log2(float64(blockSize/576)))
752✔
224
        case 256, 512, 1024, 2048, 4096, 8192, 16384, 32768:
8,460✔
225
                // 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768
8,460✔
226
                bits = 0x8 + uint64(math.Log2(float64(blockSize/256)))
8,460✔
227
        default:
25,411✔
228
                if blockSize <= 256 {
48,908✔
229
                        // 0110 : get 8 bit (blocksize-1) from end of header
23,497✔
230
                        bits = 0x6
23,497✔
231
                        nblockSizeSuffixBits = 8
23,497✔
232
                } else {
25,411✔
233
                        // 0111 : get 16 bit (blocksize-1) from end of header
1,914✔
234
                        bits = 0x7
1,914✔
235
                        nblockSizeSuffixBits = 16
1,914✔
236
                }
1,914✔
237
        }
238
        if err := bw.WriteBits(bits, 4); err != nil {
36,895✔
239
                return 0, errutil.Err(err)
×
240
        }
×
241
        return nblockSizeSuffixBits, nil
36,895✔
242
}
243

244
// ~~~ [ Sample rate ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
245

246
// encodeFrameHeaderSampleRate encodes the sample rate of the frame header,
247
// writing to bw. It returns the bits and the number of bits used to store
248
// sample rate after the frame header.
249
func encodeFrameHeaderSampleRate(bw *bitio.Writer, sampleRate uint32) (sampleRateSuffixBits uint64, nsampleRateSuffixBits byte, err error) {
36,895✔
250
        // Sample rate:
36,895✔
251
        //    0000 : get from STREAMINFO metadata block
36,895✔
252
        //    0001 : 88.2kHz
36,895✔
253
        //    0010 : 176.4kHz
36,895✔
254
        //    0011 : 192kHz
36,895✔
255
        //    0100 : 8kHz
36,895✔
256
        //    0101 : 16kHz
36,895✔
257
        //    0110 : 22.05kHz
36,895✔
258
        //    0111 : 24kHz
36,895✔
259
        //    1000 : 32kHz
36,895✔
260
        //    1001 : 44.1kHz
36,895✔
261
        //    1010 : 48kHz
36,895✔
262
        //    1011 : 96kHz
36,895✔
263
        //    1100 : get 8 bit sample rate (in kHz) from end of header
36,895✔
264
        //    1101 : get 16 bit sample rate (in Hz) from end of header
36,895✔
265
        //    1110 : get 16 bit sample rate (in tens of Hz) from end of header
36,895✔
266
        //    1111 : invalid, to prevent sync-fooling string of 1s
36,895✔
267
        var bits uint64
36,895✔
268
        switch sampleRate {
36,895✔
269
        case 0:
×
270
                // 0000 : get from STREAMINFO metadata block
×
271
                bits = 0
×
272
        case 88200:
104✔
273
                // 0001 : 88.2kHz
104✔
274
                bits = 0x1
104✔
275
        case 176400:
×
276
                // 0010 : 176.4kHz
×
277
                bits = 0x2
×
278
        case 192000:
915✔
279
                // 0011 : 192kHz
915✔
280
                bits = 0x3
915✔
281
        case 8000:
1✔
282
                // 0100 : 8kHz
1✔
283
                bits = 0x4
1✔
284
        case 16000:
21✔
285
                // 0101 : 16kHz
21✔
286
                bits = 0x5
21✔
287
        case 22050:
36✔
288
                // 0110 : 22.05kHz
36✔
289
                bits = 0x6
36✔
290
        case 24000:
×
291
                // 0111 : 24kHz
×
292
                bits = 0x7
×
293
        case 32000:
79✔
294
                // 1000 : 32kHz
79✔
295
                bits = 0x8
79✔
296
        case 44100:
32,395✔
297
                // 1001 : 44.1kHz
32,395✔
298
                bits = 0x9
32,395✔
299
        case 48000:
1,380✔
300
                // 1010 : 48kHz
1,380✔
301
                bits = 0xA
1,380✔
302
        case 96000:
791✔
303
                // 1011 : 96kHz
791✔
304
                bits = 0xB
791✔
305
        default:
1,173✔
306
                switch {
1,173✔
307
                case sampleRate <= 255000 && sampleRate%1000 == 0:
48✔
308
                        // 1100 : get 8 bit sample rate (in kHz) from end of header
48✔
309
                        bits = 0xC
48✔
310
                        sampleRateSuffixBits = uint64(sampleRate / 1000)
48✔
311
                        nsampleRateSuffixBits = 8
48✔
312
                case sampleRate <= 65535:
109✔
313
                        // 1101 : get 16 bit sample rate (in Hz) from end of header
109✔
314
                        bits = 0xD
109✔
315
                        sampleRateSuffixBits = uint64(sampleRate)
109✔
316
                        nsampleRateSuffixBits = 16
109✔
317
                case sampleRate <= 655350 && sampleRate%10 == 0:
1,016✔
318
                        // 1110 : get 16 bit sample rate (in tens of Hz) from end of header
1,016✔
319
                        bits = 0xE
1,016✔
320
                        sampleRateSuffixBits = uint64(sampleRate / 10)
1,016✔
321
                        nsampleRateSuffixBits = 16
1,016✔
322
                default:
×
323
                        return 0, 0, errutil.Newf("unable to encode sample rate %v", sampleRate)
×
324
                }
325
        }
326
        if err := bw.WriteBits(bits, 4); err != nil {
36,895✔
327
                return 0, 0, errutil.Err(err)
×
328
        }
×
329
        return sampleRateSuffixBits, nsampleRateSuffixBits, nil
36,895✔
330
}
331

332
// ~~~ [ Channels assignment ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
333

334
// encodeFrameHeaderChannels encodes the channels assignment of the frame
335
// header, writing to bw.
336
func encodeFrameHeaderChannels(bw *bitio.Writer, channels frame.Channels) error {
36,895✔
337
        // Channel assignment.
36,895✔
338
        //    0000-0111 : (number of independent channels)-1. Where defined, the channel order follows SMPTE/ITU-R recommendations. The assignments are as follows:
36,895✔
339
        //        1 channel: mono
36,895✔
340
        //        2 channels: left, right
36,895✔
341
        //        3 channels: left, right, center
36,895✔
342
        //        4 channels: front left, front right, back left, back right
36,895✔
343
        //        5 channels: front left, front right, front center, back/surround left, back/surround right
36,895✔
344
        //        6 channels: front left, front right, front center, LFE, back/surround left, back/surround right
36,895✔
345
        //        7 channels: front left, front right, front center, LFE, back center, side left, side right
36,895✔
346
        //        8 channels: front left, front right, front center, LFE, back left, back right, side left, side right
36,895✔
347
        //    1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel
36,895✔
348
        //    1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
36,895✔
349
        //    1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
36,895✔
350
        //    1011-1111 : reserved
36,895✔
351
        var bits uint64
36,895✔
352
        switch channels {
36,895✔
353
        case frame.ChannelsMono, frame.ChannelsLR, frame.ChannelsLRC, frame.ChannelsLRLsRs, frame.ChannelsLRCLsRs, frame.ChannelsLRCLfeLsRs, frame.ChannelsLRCLfeCsSlSr, frame.ChannelsLRCLfeLsRsSlSr:
16,258✔
354
                // 1 channel: mono.
16,258✔
355
                // 2 channels: left, right.
16,258✔
356
                // 3 channels: left, right, center.
16,258✔
357
                // 4 channels: left, right, left surround, right surround.
16,258✔
358
                // 5 channels: left, right, center, left surround, right surround.
16,258✔
359
                // 6 channels: left, right, center, LFE, left surround, right surround.
16,258✔
360
                // 7 channels: left, right, center, LFE, center surround, side left, side right.
16,258✔
361
                // 8 channels: left, right, center, LFE, left surround, right surround, side left, side right.
16,258✔
362
                bits = uint64(channels.Count() - 1)
16,258✔
363
        case frame.ChannelsLeftSide:
3,591✔
364
                // 2 channels: left, side; using inter-channel decorrelation.
3,591✔
365
                // 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel
3,591✔
366
                bits = 0x8
3,591✔
367
        case frame.ChannelsSideRight:
3,636✔
368
                // 2 channels: side, right; using inter-channel decorrelation.
3,636✔
369
                // 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
3,636✔
370
                bits = 0x9
3,636✔
371
        case frame.ChannelsMidSide:
13,410✔
372
                // 2 channels: mid, side; using inter-channel decorrelation.
13,410✔
373
                // 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
13,410✔
374
                bits = 0xA
13,410✔
375
        default:
×
376
                return errutil.Newf("support for channel assignment %v not yet implemented", channels)
×
377
        }
378
        if err := bw.WriteBits(bits, 4); err != nil {
36,895✔
379
                return errutil.Err(err)
×
380
        }
×
381
        return nil
36,895✔
382
}
383

384
// ~~~ [ Bits-per-sample ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
385

386
// encodeFrameHeaderBitsPerSample encodes the bits-per-sample of the frame
387
// header, writing to bw.
388
func encodeFrameHeaderBitsPerSample(bw *bitio.Writer, bps uint8) error {
36,895✔
389
        // Sample size in bits:
36,895✔
390
        //    000 : get from STREAMINFO metadata block
36,895✔
391
        //    001 : 8 bits per sample
36,895✔
392
        //    010 : 12 bits per sample
36,895✔
393
        //    011 : reserved
36,895✔
394
        //    100 : 16 bits per sample
36,895✔
395
        //    101 : 20 bits per sample
36,895✔
396
        //    110 : 24 bits per sample
36,895✔
397
        //    111 : reserved
36,895✔
398
        var bits uint64
36,895✔
399
        switch bps {
36,895✔
400
        case 0:
×
401
                // 000 : get from STREAMINFO metadata block
×
402
                bits = 0x0
×
403
        case 8:
106✔
404
                // 001 : 8 bits per sample
106✔
405
                bits = 0x1
106✔
406
        case 12:
54✔
407
                // 010 : 12 bits per sample
54✔
408
                bits = 0x2
54✔
409
        case 16:
34,448✔
410
                // 100 : 16 bits per sample
34,448✔
411
                bits = 0x4
34,448✔
412
        case 20:
244✔
413
                // 101 : 20 bits per sample
244✔
414
                bits = 0x5
244✔
415
        case 24:
2,043✔
416
                // 110 : 24 bits per sample
2,043✔
417
                bits = 0x6
2,043✔
418
        default:
×
419
                return errutil.Newf("support for sample size %v not yet implemented", bps)
×
420
        }
421
        if err := bw.WriteBits(bits, 3); err != nil {
36,895✔
422
                return errutil.Err(err)
×
423
        }
×
424
        return nil
36,895✔
425
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc