• 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

68.75
/frame/frame.go
1
// Package frame implements access to FLAC audio frames.
2
//
3
// A brief introduction of the FLAC audio format [1] follows. FLAC encoders
4
// divide the audio stream into blocks through a process called blocking [2]. A
5
// block contains the unencoded audio samples from all channels during a short
6
// period of time. Each audio block is divided into subblocks, one per channel.
7
//
8
// There is often a correlation between the left and right channel of stereo
9
// audio. Using inter-channel decorrelation [3] it is possible to store only one
10
// of the channels and the difference between the channels, or store the average
11
// of the channels and their difference. An encoder decorrelates audio samples
12
// as follows:
13
//
14
//        mid = (left + right)/2 // average of the channels
15
//        side = left - right    // difference between the channels
16
//
17
// The blocks are encoded using a variety of prediction methods [4][5] and
18
// stored in frames. Blocks and subblocks contains unencoded audio samples while
19
// frames and subframes contain encoded audio samples. A FLAC stream contains
20
// one or more audio frames.
21
//
22
//        [1]: https://www.xiph.org/flac/format.html#architecture
23
//        [2]: https://www.xiph.org/flac/format.html#blocking
24
//        [3]: https://www.xiph.org/flac/format.html#interchannel
25
//        [4]: https://www.xiph.org/flac/format.html#prediction
26
//        [5]: https://godoc.org/github.com/mewkiz/flac/frame#Pred
27
package frame
28

29
import (
30
        "encoding/binary"
31
        "errors"
32
        "fmt"
33
        "hash"
34
        "io"
35
        "log"
36

37
        "github.com/mewkiz/flac/internal/bits"
38
        "github.com/mewkiz/flac/internal/hashutil"
39
        "github.com/mewkiz/flac/internal/hashutil/crc16"
40
        "github.com/mewkiz/flac/internal/hashutil/crc8"
41
        "github.com/mewkiz/flac/internal/utf8"
42
)
43

44
// A Frame contains the header and subframes of an audio frame. It holds the
45
// encoded samples from a block (a part) of the audio stream. Each subframe
46
// holding the samples from one of its channel.
47
//
48
// ref: https://www.xiph.org/flac/format.html#frame
49
type Frame struct {
50
        // Audio frame header.
51
        Header
52
        // One subframe per channel, containing encoded audio samples.
53
        Subframes []*Subframe
54
        // CRC-16 hash sum, calculated by read operations on hr.
55
        crc hashutil.Hash16
56
        // A bit reader, wrapping read operations to hr.
57
        br *bits.Reader
58
        // A CRC-16 hash reader, wrapping read operations to r.
59
        hr io.Reader
60
        // Underlying io.Reader.
61
        r io.Reader
62
}
63

64
// New creates a new Frame for accessing the audio samples of r. It reads and
65
// parses an audio frame header. It returns io.EOF to signal a graceful end of
66
// FLAC stream.
67
//
68
// Call Frame.Parse to parse the audio samples of its subframes.
69
func New(r io.Reader) (frame *Frame, err error) {
37,902✔
70
        // Create a new CRC-16 hash reader which adds the data from all read
37,902✔
71
        // operations to a running hash.
37,902✔
72
        crc := crc16.NewIBM()
37,902✔
73
        hr := io.TeeReader(r, crc)
37,902✔
74

37,902✔
75
        // Parse frame header.
37,902✔
76
        frame = &Frame{crc: crc, hr: hr, r: r}
37,902✔
77
        err = frame.parseHeader()
37,902✔
78
        return frame, err
37,902✔
79
}
37,902✔
80

81
// Parse reads and parses the header, and the audio samples from each subframe
82
// of a frame. If the samples are inter-channel decorrelated between the
83
// subframes, it correlates them. It returns io.EOF to signal a graceful end of
84
// FLAC stream.
85
//
86
// ref: https://www.xiph.org/flac/format.html#interchannel
87
func Parse(r io.Reader) (frame *Frame, err error) {
37,902✔
88
        // Parse frame header.
37,902✔
89
        frame, err = New(r)
37,902✔
90
        if err != nil {
37,979✔
91
                return frame, err
77✔
92
        }
77✔
93

94
        // Parse subframes.
95
        err = frame.Parse()
37,825✔
96
        return frame, err
37,825✔
97
}
98

99
// Parse reads and parses the audio samples from each subframe of the frame. If
100
// the samples are inter-channel decorrelated between the subframes, it
101
// correlates them.
102
//
103
// ref: https://www.xiph.org/flac/format.html#interchannel
104
func (frame *Frame) Parse() error {
37,825✔
105
        // Parse subframes.
37,825✔
106
        frame.Subframes = make([]*Subframe, frame.Channels.Count())
37,825✔
107
        var err error
37,825✔
108
        for channel := range frame.Subframes {
115,997✔
109
                // The side channel requires an extra bit per sample when using
78,172✔
110
                // inter-channel decorrelation.
78,172✔
111
                bps := uint(frame.BitsPerSample)
78,172✔
112
                switch frame.Channels {
78,172✔
113
                case ChannelsSideRight:
7,288✔
114
                        // channel 0 is the side channel.
7,288✔
115
                        if channel == 0 {
10,932✔
116
                                bps++
3,644✔
117
                        }
3,644✔
118
                case ChannelsLeftSide, ChannelsMidSide:
35,080✔
119
                        // channel 1 is the side channel.
35,080✔
120
                        if channel == 1 {
52,620✔
121
                                bps++
17,540✔
122
                        }
17,540✔
123
                }
124

125
                // Parse subframe.
126
                frame.Subframes[channel], err = frame.parseSubframe(frame.br, bps)
78,172✔
127
                if err != nil {
78,172✔
128
                        return err
×
129
                }
×
130
        }
131

132
        // Inter-channel correlation of subframe samples.
133
        frame.Correlate()
37,825✔
134

37,825✔
135
        // 2 bytes: CRC-16 checksum.
37,825✔
136
        var want uint16
37,825✔
137
        if err = binary.Read(frame.r, binary.BigEndian, &want); err != nil {
37,825✔
138
                return unexpected(err)
×
139
        }
×
140
        got := frame.crc.Sum16()
37,825✔
141
        if got != want {
37,825✔
142
                return fmt.Errorf("frame.Frame.Parse: CRC-16 checksum mismatch; expected 0x%04X, got 0x%04X", want, got)
×
143
        }
×
144

145
        return nil
37,825✔
146
}
147

148
// Hash adds the decoded audio samples of the frame to a running MD5 hash. It
149
// can be used in conjunction with StreamInfo.MD5sum to verify the integrity of
150
// the decoded audio samples.
151
//
152
// Note: The audio samples of the frame must be decoded before calling Hash.
153
func (frame *Frame) Hash(md5sum hash.Hash) {
37,825✔
154
        // Write decoded samples to a running MD5 hash.
37,825✔
155
        bps := frame.BitsPerSample
37,825✔
156
        var buf [3]byte
37,825✔
157
        for i := 0; i < int(frame.BlockSize); i++ {
40,952,358✔
158
                for _, subframe := range frame.Subframes {
146,038,132✔
159
                        sample := subframe.Samples[i]
105,123,599✔
160
                        switch {
105,123,599✔
161
                        case 1 <= bps && bps <= 8:
777,482✔
162
                                buf[0] = uint8(sample)
777,482✔
163
                                md5sum.Write(buf[:1])
777,482✔
164
                        case 9 <= bps && bps <= 16:
56,893,141✔
165
                                buf[0] = uint8(sample)
56,893,141✔
166
                                buf[1] = uint8(sample >> 8)
56,893,141✔
167
                                md5sum.Write(buf[:2])
56,893,141✔
168
                        case 17 <= bps && bps <= 24:
47,452,976✔
169
                                buf[0] = uint8(sample)
47,452,976✔
170
                                buf[1] = uint8(sample >> 8)
47,452,976✔
171
                                buf[2] = uint8(sample >> 16)
47,452,976✔
172
                                md5sum.Write(buf[:])
47,452,976✔
173
                        default:
×
174
                                log.Printf("frame.Frame.Hash: support for %d-bit sample size not yet implemented", bps)
×
175
                        }
176
                }
177
        }
178
}
179

180
// A Header contains the basic properties of an audio frame, such as its sample
181
// rate and channel count. To facilitate random access decoding each frame
182
// header starts with a sync-code. This allows the decoder to synchronize and
183
// locate the start of a frame header.
184
//
185
// ref: https://www.xiph.org/flac/format.html#frame_header
186
type Header struct {
187
        // Specifies if the block size is fixed or variable.
188
        HasFixedBlockSize bool
189
        // Block size in inter-channel samples, i.e. the number of audio samples in
190
        // each subframe.
191
        BlockSize uint16
192
        // Sample rate in Hz; a 0 value implies unknown, get sample rate from
193
        // StreamInfo.
194
        SampleRate uint32
195
        // Specifies the number of channels (subframes) that exist in the frame,
196
        // their order and possible inter-channel decorrelation.
197
        Channels Channels
198
        // Sample size in bits-per-sample; a 0 value implies unknown, get sample size
199
        // from StreamInfo.
200
        BitsPerSample uint8
201
        // Specifies the frame number if the block size is fixed, and the first
202
        // sample number in the frame otherwise. When using fixed block size, the
203
        // first sample number in the frame can be derived by multiplying the frame
204
        // number with the block size (in samples).
205
        Num uint64
206
}
207

208
// Errors returned by Frame.parseHeader.
209
var (
210
        ErrInvalidSync = errors.New("frame.Frame.parseHeader: invalid sync-code")
211
)
212

213
// parseHeader reads and parses the header of an audio frame.
214
func (frame *Frame) parseHeader() error {
37,902✔
215
        // Create a new CRC-8 hash reader which adds the data from all read
37,902✔
216
        // operations to a running hash.
37,902✔
217
        h := crc8.NewATM()
37,902✔
218
        hr := io.TeeReader(frame.hr, h)
37,902✔
219

37,902✔
220
        // Create bit reader.
37,902✔
221
        br := bits.NewReader(hr)
37,902✔
222
        frame.br = br
37,902✔
223

37,902✔
224
        // 14 bits: sync-code (11111111111110)
37,902✔
225
        x, err := br.Read(14)
37,902✔
226
        if err != nil {
37,979✔
227
                // This is the only place an audio frame may return io.EOF, which signals
77✔
228
                // a graceful end of a FLAC stream.
77✔
229
                return err
77✔
230
        }
77✔
231
        if x != 0x3FFE {
37,825✔
232
                return ErrInvalidSync
×
233
        }
×
234

235
        // 1 bit: reserved.
236
        x, err = br.Read(1)
37,825✔
237
        if err != nil {
37,825✔
238
                return unexpected(err)
×
239
        }
×
240
        if x != 0 {
37,825✔
241
                return errors.New("frame.Frame.parseHeader: non-zero reserved value")
×
242
        }
×
243

244
        // 1 bit: HasFixedBlockSize.
245
        x, err = br.Read(1)
37,825✔
246
        if err != nil {
37,825✔
247
                return unexpected(err)
×
248
        }
×
249
        if x == 0 {
69,718✔
250
                frame.HasFixedBlockSize = true
31,893✔
251
        }
31,893✔
252

253
        // 4 bits: BlockSize. The block size parsing is simplified by deferring it to
254
        // the end of the header.
255
        blockSize, err := br.Read(4)
37,825✔
256
        if err != nil {
37,825✔
257
                return unexpected(err)
×
258
        }
×
259

260
        // 4 bits: SampleRate. The sample rate parsing is simplified by deferring it
261
        // to the end of the header.
262
        sampleRate, err := br.Read(4)
37,825✔
263
        if err != nil {
37,825✔
264
                return unexpected(err)
×
265
        }
×
266

267
        // Parse channels.
268
        if err := frame.parseChannels(br); err != nil {
37,825✔
269
                return err
×
270
        }
×
271

272
        // Parse bits per sample.
273
        if err := frame.parseBitsPerSample(br); err != nil {
37,825✔
274
                return err
×
275
        }
×
276

277
        // 1 bit: reserved.
278
        x, err = br.Read(1)
37,825✔
279
        if err != nil {
37,825✔
280
                return unexpected(err)
×
281
        }
×
282
        if x != 0 {
37,825✔
283
                return errors.New("frame.Frame.parseHeader: non-zero reserved value")
×
284
        }
×
285

286
        // if (fixed block size)
287
        //    1-6 bytes: UTF-8 encoded frame number.
288
        // else
289
        //    1-7 bytes: UTF-8 encoded sample number.
290
        frame.Num, err = utf8.Decode(hr)
37,825✔
291
        if err != nil {
37,825✔
292
                return unexpected(err)
×
293
        }
×
294

295
        // Parse block size.
296
        if err := frame.parseBlockSize(br, blockSize); err != nil {
37,825✔
297
                return err
×
298
        }
×
299

300
        // Parse sample rate.
301
        if err := frame.parseSampleRate(br, sampleRate); err != nil {
37,825✔
302
                return err
×
303
        }
×
304

305
        // 1 byte: CRC-8 checksum.
306
        var want uint8
37,825✔
307
        if err = binary.Read(frame.hr, binary.BigEndian, &want); err != nil {
37,825✔
308
                return unexpected(err)
×
309
        }
×
310
        got := h.Sum8()
37,825✔
311
        if want != got {
37,825✔
312
                return fmt.Errorf("frame.Frame.parseHeader: CRC-8 checksum mismatch; expected 0x%02X, got 0x%02X", want, got)
×
313
        }
×
314

315
        return nil
37,825✔
316
}
317

318
// parseBitsPerSample parses the bits per sample of the header.
319
func (frame *Frame) parseBitsPerSample(br *bits.Reader) error {
37,825✔
320
        // 3 bits: BitsPerSample.
37,825✔
321
        x, err := br.Read(3)
37,825✔
322
        if err != nil {
37,825✔
323
                return unexpected(err)
×
324
        }
×
325

326
        // The 3 bits are used to specify the sample size as follows:
327
        //    000: unknown sample size; get from StreamInfo.
328
        //    001: 8 bits-per-sample.
329
        //    010: 12 bits-per-sample.
330
        //    011: reserved.
331
        //    100: 16 bits-per-sample.
332
        //    101: 20 bits-per-sample.
333
        //    110: 24 bits-per-sample.
334
        //    111: reserved.
335
        switch x {
37,825✔
336
        case 0x0:
×
337
                // 000: unknown bits-per-sample; get from StreamInfo.
338
        case 0x1:
106✔
339
                // 001: 8 bits-per-sample.
106✔
340
                frame.BitsPerSample = 8
106✔
341
        case 0x2:
54✔
342
                // 010: 12 bits-per-sample.
54✔
343
                frame.BitsPerSample = 12
54✔
344
        case 0x4:
35,107✔
345
                // 100: 16 bits-per-sample.
35,107✔
346
                frame.BitsPerSample = 16
35,107✔
347
        case 0x5:
244✔
348
                // 101: 20 bits-per-sample.
244✔
349
                frame.BitsPerSample = 20
244✔
350
        case 0x6:
2,314✔
351
                // 110: 24 bits-per-sample.
2,314✔
352
                frame.BitsPerSample = 24
2,314✔
353
        default:
×
354
                // 011: reserved.
×
355
                // 111: reserved.
×
356
                return fmt.Errorf("frame.Frame.parseHeader: reserved sample size bit pattern (%03b)", x)
×
357
        }
358
        return nil
37,825✔
359
}
360

361
// parseChannels parses the channels of the header.
362
func (frame *Frame) parseChannels(br *bits.Reader) error {
37,825✔
363
        // 4 bits: Channels.
37,825✔
364
        //
37,825✔
365
        // The 4 bits are used to specify the channels as follows:
37,825✔
366
        //    0000: (1 channel) mono.
37,825✔
367
        //    0001: (2 channels) left, right.
37,825✔
368
        //    0010: (3 channels) left, right, center.
37,825✔
369
        //    0011: (4 channels) left, right, left surround, right surround.
37,825✔
370
        //    0100: (5 channels) left, right, center, left surround, right surround.
37,825✔
371
        //    0101: (6 channels) left, right, center, LFE, left surround, right surround.
37,825✔
372
        //    0110: (7 channels) left, right, center, LFE, center surround, side left, side right.
37,825✔
373
        //    0111: (8 channels) left, right, center, LFE, left surround, right surround, side left, side right.
37,825✔
374
        //    1000: (2 channels) left, side; using inter-channel decorrelation.
37,825✔
375
        //    1001: (2 channels) side, right; using inter-channel decorrelation.
37,825✔
376
        //    1010: (2 channels) mid, side; using inter-channel decorrelation.
37,825✔
377
        //    1011: reserved.
37,825✔
378
        //    1100: reserved.
37,825✔
379
        //    1101: reserved.
37,825✔
380
        //    1111: reserved.
37,825✔
381
        x, err := br.Read(4)
37,825✔
382
        if err != nil {
37,825✔
383
                return unexpected(err)
×
384
        }
×
385
        if x >= 0xB {
37,825✔
386
                return fmt.Errorf("frame.Frame.parseHeader: reserved channels bit pattern (%04b)", x)
×
387
        }
×
388
        frame.Channels = Channels(x)
37,825✔
389
        return nil
37,825✔
390
}
391

392
// parseBlockSize parses the block size of the header.
393
func (frame *Frame) parseBlockSize(br *bits.Reader, blockSize uint64) error {
37,825✔
394
        // The 4 bits of n are used to specify the block size as follows:
37,825✔
395
        //    0000: reserved.
37,825✔
396
        //    0001: 192 samples.
37,825✔
397
        //    0010-0101: 576 * 2^(n-2) samples.
37,825✔
398
        //    0110: get 8 bit (block size)-1 from the end of the header.
37,825✔
399
        //    0111: get 16 bit (block size)-1 from the end of the header.
37,825✔
400
        //    1000-1111: 256 * 2^(n-8) samples.
37,825✔
401
        n := blockSize
37,825✔
402
        switch {
37,825✔
403
        case n == 0x0:
×
404
                // 0000: reserved.
×
405
                return errors.New("frame.Frame.parseHeader: reserved block size bit pattern (0000)")
×
406
        case n == 0x1:
2,272✔
407
                // 0001: 192 samples.
2,272✔
408
                frame.BlockSize = 192
2,272✔
409
        case n >= 0x2 && n <= 0x5:
745✔
410
                // 0010-0101: 576 * 2^(n-2) samples.
745✔
411
                frame.BlockSize = 576 * (1 << (n - 2))
745✔
412
        case n == 0x6:
23,497✔
413
                // 0110: get 8 bit (block size)-1 from the end of the header.
23,497✔
414
                x, err := br.Read(8)
23,497✔
415
                if err != nil {
23,497✔
416
                        return unexpected(err)
×
417
                }
×
418
                frame.BlockSize = uint16(x + 1)
23,497✔
419
        case n == 0x7:
2,635✔
420
                // 0111: get 16 bit (block size)-1 from the end of the header.
2,635✔
421
                x, err := br.Read(16)
2,635✔
422
                if err != nil {
2,635✔
423
                        return unexpected(err)
×
424
                }
×
425
                frame.BlockSize = uint16(x + 1)
2,635✔
426
        default:
8,676✔
427
                //    1000-1111: 256 * 2^(n-8) samples.
8,676✔
428
                frame.BlockSize = 256 * (1 << (n - 8))
8,676✔
429
        }
430
        return nil
37,825✔
431
}
432

433
// parseSampleRate parses the sample rate of the header.
434
func (frame *Frame) parseSampleRate(br *bits.Reader, sampleRate uint64) error {
37,825✔
435
        // The 4 bits are used to specify the sample rate as follows:
37,825✔
436
        //    0000: unknown sample rate; get from StreamInfo.
37,825✔
437
        //    0001: 88.2 kHz.
37,825✔
438
        //    0010: 176.4 kHz.
37,825✔
439
        //    0011: 192 kHz.
37,825✔
440
        //    0100: 8 kHz.
37,825✔
441
        //    0101: 16 kHz.
37,825✔
442
        //    0110: 22.05 kHz.
37,825✔
443
        //    0111: 24 kHz.
37,825✔
444
        //    1000: 32 kHz.
37,825✔
445
        //    1001: 44.1 kHz.
37,825✔
446
        //    1010: 48 kHz.
37,825✔
447
        //    1011: 96 kHz.
37,825✔
448
        //    1100: get 8 bit sample rate (in kHz) from the end of the header.
37,825✔
449
        //    1101: get 16 bit sample rate (in Hz) from the end of the header.
37,825✔
450
        //    1110: get 16 bit sample rate (in daHz) from the end of the header.
37,825✔
451
        //    1111: invalid.
37,825✔
452
        switch sampleRate {
37,825✔
453
        case 0x0:
×
454
                // 0000: unknown sample rate; get from StreamInfo.
455
        case 0x1:
104✔
456
                // 0001: 88.2 kHz.
104✔
457
                frame.SampleRate = 88200
104✔
458
        case 0x2:
×
459
                // 0010: 176.4 kHz.
×
460
                frame.SampleRate = 176400
×
461
                // TODO(u): Remove log message when the test cases have been extended.
×
462
                log.Printf("frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases.", frame.SampleRate)
×
463
        case 0x3:
915✔
464
                // 0011: 192 kHz.
915✔
465
                frame.SampleRate = 192000
915✔
466
        case 0x4:
1✔
467
                // 0100: 8 kHz.
1✔
468
                frame.SampleRate = 8000
1✔
469
        case 0x5:
×
470
                // 0101: 16 kHz.
×
471
                frame.SampleRate = 16000
×
472
        case 0x6:
36✔
473
                // 0110: 22.05 kHz.
36✔
474
                frame.SampleRate = 22050
36✔
475
        case 0x7:
×
476
                // 0111: 24 kHz.
×
477
                frame.SampleRate = 24000
×
478
                // TODO(u): Remove log message when the test cases have been extended.
×
479
                log.Printf("frame.Frame.parseHeader: The flac library test cases do not yet include any audio files with sample rate %d. If possible please consider contributing this audio sample to improve the reliability of the test cases.", frame.SampleRate)
×
480
        case 0x8:
79✔
481
                // 1000: 32 kHz.
79✔
482
                frame.SampleRate = 32000
79✔
483
        case 0x9:
33,075✔
484
                // 1001: 44.1 kHz.
33,075✔
485
                frame.SampleRate = 44100
33,075✔
486
        case 0xA:
1,380✔
487
                // 1010: 48 kHz.
1,380✔
488
                frame.SampleRate = 48000
1,380✔
489
        case 0xB:
791✔
490
                // 1011: 96 kHz.
791✔
491
                frame.SampleRate = 96000
791✔
492
        case 0xC:
319✔
493
                // 1100: get 8 bit sample rate (in kHz) from the end of the header.
319✔
494
                x, err := br.Read(8)
319✔
495
                if err != nil {
319✔
496
                        return unexpected(err)
×
497
                }
×
498
                frame.SampleRate = uint32(x * 1000)
319✔
499
        case 0xD:
109✔
500
                // 1101: get 16 bit sample rate (in Hz) from the end of the header.
109✔
501
                x, err := br.Read(16)
109✔
502
                if err != nil {
109✔
503
                        return unexpected(err)
×
504
                }
×
505
                frame.SampleRate = uint32(x)
109✔
506
        case 0xE:
1,016✔
507
                // 1110: get 16 bit sample rate (in daHz) from the end of the header.
1,016✔
508
                x, err := br.Read(16)
1,016✔
509
                if err != nil {
1,016✔
510
                        return unexpected(err)
×
511
                }
×
512
                frame.SampleRate = uint32(x * 10)
1,016✔
513
        default:
×
514
                // 1111: invalid.
×
515
                return errors.New("frame.Frame.parseHeader: invalid sample rate bit pattern (1111)")
×
516
        }
517
        return nil
37,825✔
518
}
519

520
// Channels specifies the number of channels (subframes) that exist in a frame,
521
// their order and possible inter-channel decorrelation.
522
type Channels uint8
523

524
// Channel assignments. The following abbreviations are used:
525
//
526
//        C:   center (directly in front)
527
//        R:   right (standard stereo)
528
//        Sr:  side right (directly to the right)
529
//        Rs:  right surround (back right)
530
//        Cs:  center surround (rear center)
531
//        Ls:  left surround (back left)
532
//        Sl:  side left (directly to the left)
533
//        L:   left (standard stereo)
534
//        Lfe: low-frequency effect (placed according to room acoustics)
535
//
536
// The first 6 channel constants follow the SMPTE/ITU-R channel order:
537
//
538
//        L R C Lfe Ls Rs
539
const (
540
        ChannelsMono           Channels = iota // 1 channel: mono.
541
        ChannelsLR                             // 2 channels: left, right.
542
        ChannelsLRC                            // 3 channels: left, right, center.
543
        ChannelsLRLsRs                         // 4 channels: left, right, left surround, right surround.
544
        ChannelsLRCLsRs                        // 5 channels: left, right, center, left surround, right surround.
545
        ChannelsLRCLfeLsRs                     // 6 channels: left, right, center, LFE, left surround, right surround.
546
        ChannelsLRCLfeCsSlSr                   // 7 channels: left, right, center, LFE, center surround, side left, side right.
547
        ChannelsLRCLfeLsRsSlSr                 // 8 channels: left, right, center, LFE, left surround, right surround, side left, side right.
548
        ChannelsLeftSide                       // 2 channels: left, side; using inter-channel decorrelation.
549
        ChannelsSideRight                      // 2 channels: side, right; using inter-channel decorrelation.
550
        ChannelsMidSide                        // 2 channels: mid, side; using inter-channel decorrelation.
551
)
552

553
// nChannels specifies the number of channels used by each channel assignment.
554
var nChannels = [...]int{
555
        ChannelsMono:           1,
556
        ChannelsLR:             2,
557
        ChannelsLRC:            3,
558
        ChannelsLRLsRs:         4,
559
        ChannelsLRCLsRs:        5,
560
        ChannelsLRCLfeLsRs:     6,
561
        ChannelsLRCLfeCsSlSr:   7,
562
        ChannelsLRCLfeLsRsSlSr: 8,
563
        ChannelsLeftSide:       2,
564
        ChannelsSideRight:      2,
565
        ChannelsMidSide:        2,
566
}
567

568
// Count returns the number of channels (subframes) used by the provided channel
569
// assignment.
570
func (channels Channels) Count() int {
37,825✔
571
        return nChannels[channels]
37,825✔
572
}
37,825✔
573

574
// Correlate reverts any inter-channel decorrelation between the samples of the
575
// subframes.
576
//
577
// An encoder decorrelates audio samples as follows:
578
//
579
//        mid = (left + right)/2
580
//        side = left - right
581
func (frame *Frame) Correlate() {
37,825✔
582
        switch frame.Channels {
37,825✔
583
        case ChannelsLeftSide:
3,592✔
584
                // 2 channels: left, side; using inter-channel decorrelation.
3,592✔
585
                left := frame.Subframes[0].Samples
3,592✔
586
                side := frame.Subframes[1].Samples
3,592✔
587
                for i := range side {
1,425,423✔
588
                        // right = left - side
1,421,831✔
589
                        side[i] = left[i] - side[i]
1,421,831✔
590
                }
1,421,831✔
591
        case ChannelsSideRight:
3,644✔
592
                // 2 channels: side, right; using inter-channel decorrelation.
3,644✔
593
                side := frame.Subframes[0].Samples
3,644✔
594
                right := frame.Subframes[1].Samples
3,644✔
595
                for i := range side {
2,701,467✔
596
                        // left = right + side
2,697,823✔
597
                        side[i] = right[i] + side[i]
2,697,823✔
598
                }
2,697,823✔
599
        case ChannelsMidSide:
13,948✔
600
                // 2 channels: mid, side; using inter-channel decorrelation.
13,948✔
601
                mid := frame.Subframes[0].Samples
13,948✔
602
                side := frame.Subframes[1].Samples
13,948✔
603
                for i := range side {
22,601,176✔
604
                        // left = (2*mid + side)/2
22,587,228✔
605
                        // right = (2*mid - side)/2
22,587,228✔
606
                        m := mid[i]
22,587,228✔
607
                        s := side[i]
22,587,228✔
608
                        m *= 2
22,587,228✔
609
                        // Notice that the integer division in mid = (left + right)/2 discards
22,587,228✔
610
                        // the least significant bit. It can be reconstructed however, since a
22,587,228✔
611
                        // sum A+B and a difference A-B has the same least significant bit.
22,587,228✔
612
                        //
22,587,228✔
613
                        // ref: Data Compression: The Complete Reference (ch. 7, Decorrelation)
22,587,228✔
614
                        m |= s & 1
22,587,228✔
615
                        mid[i] = (m + s) / 2
22,587,228✔
616
                        side[i] = (m - s) / 2
22,587,228✔
617
                }
22,587,228✔
618
        }
619
}
620

621
// Decorrelate performs inter-channel decorrelation between the samples of the
622
// subframes.
623
//
624
// An encoder decorrelates audio samples as follows:
625
//
626
//        mid = (left + right)/2
627
//        side = left - right
628
func (frame *Frame) Decorrelate() {
×
629
        switch frame.Channels {
×
630
        case ChannelsLeftSide:
×
631
                // 2 channels: left, side; using inter-channel decorrelation.
×
632
                left := frame.Subframes[0].Samples  // already left; no change after inter-channel decorrelation.
×
633
                right := frame.Subframes[1].Samples // set to side after inter-channel decorrelation.
×
634
                for i := range left {
×
635
                        l := left[i]
×
636
                        r := right[i]
×
637
                        // inter-channel decorrelation:
×
638
                        //        side = left - right
×
639
                        side := l - r
×
640
                        right[i] = side
×
641
                }
×
642
        case ChannelsSideRight:
×
643
                // 2 channels: side, right; using inter-channel decorrelation.
×
644
                left := frame.Subframes[0].Samples  // set to side after inter-channel decorrelation.
×
645
                right := frame.Subframes[1].Samples // already right; no change after inter-channel decorrelation.
×
646
                for i := range left {
×
647
                        l := left[i]
×
648
                        r := right[i]
×
649
                        // inter-channel decorrelation:
×
650
                        //        side = left - right
×
651
                        side := l - r
×
652
                        left[i] = side
×
653
                }
×
654
        case ChannelsMidSide:
×
655
                // 2 channels: mid, side; using inter-channel decorrelation.
×
656
                left := frame.Subframes[0].Samples  // set to mid after inter-channel decorrelation.
×
657
                right := frame.Subframes[1].Samples // set to side after inter-channel decorrelation.
×
658
                for i := range left {
×
659
                        // inter-channel decorrelation:
×
660
                        //        mid = (left + right)/2
×
661
                        //        side = left - right
×
662
                        l := left[i]
×
663
                        r := right[i]
×
664
                        mid := int32((int64(l) + int64(r)) >> 1) // NOTE: using `(left + right) >> 1`, not the same as `(left + right) / 2`.
×
665
                        side := l - r
×
666
                        left[i] = mid
×
667
                        right[i] = side
×
668
                }
×
669
        }
670
}
671

672
// SampleNumber returns the first sample number contained within the frame.
673
func (frame *Frame) SampleNumber() uint64 {
×
674
        if frame.HasFixedBlockSize {
×
675
                return frame.Num * uint64(frame.BlockSize)
×
676
        }
×
677
        return frame.Num
×
678
}
679

680
// unexpected returns io.ErrUnexpectedEOF if err is io.EOF, and returns err
681
// otherwise.
682
func unexpected(err error) error {
×
683
        if err == io.EOF {
×
684
                return io.ErrUnexpectedEOF
×
685
        }
×
686
        return err
×
687
}
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