Repository: mewkiz/flac Branch: master Commit: f26319f6afb6 Files: 52 Total size: 332.0 KB Directory structure: gitextract_oegtlq8n/ ├── .github/ │ └── workflows/ │ └── go.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── analysis_fixed.go ├── enc_benchmark_test.go ├── enc_test.go ├── encode.go ├── encode_frame.go ├── encode_meta.go ├── encode_subframe.go ├── example_test.go ├── flac.go ├── flac_test.go ├── frame/ │ ├── frame.go │ ├── frame_test.go │ └── subframe.go ├── go.mod ├── go.sum ├── internal/ │ ├── bits/ │ │ ├── reader.go │ │ ├── reader_test.go │ │ ├── twocomp.go │ │ ├── twocomp_test.go │ │ ├── unary.go │ │ ├── unary_test.go │ │ ├── zigzag.go │ │ └── zigzag_test.go │ ├── bufseekio/ │ │ ├── readseeker.go │ │ └── readseeker_test.go │ ├── hashutil/ │ │ ├── crc16/ │ │ │ ├── crc16.go │ │ │ └── crc16_test.go │ │ ├── crc8/ │ │ │ ├── crc8.go │ │ │ └── crc8_test.go │ │ └── hashutil.go │ ├── ioutilx/ │ │ ├── byte.go │ │ └── zero.go │ └── utf8/ │ ├── decode.go │ └── encode.go ├── meta/ │ ├── application.go │ ├── cuesheet.go │ ├── meta.go │ ├── meta_test.go │ ├── padding.go │ ├── picture.go │ ├── reader.go │ ├── seektable.go │ ├── streaminfo.go │ ├── testdata/ │ │ └── README.md │ └── vorbiscomment.go └── testdata/ ├── README.md └── convert_to_verbatim.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/go.yml ================================================ # This workflow will build a golang project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go name: Go on: push: branches: [ "master" ] pull_request: branches: [ "master" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: go-version: ['stable'] name: Build with Go ${{ matrix.go-version }} steps: - uses: actions/checkout@v3 with: submodules: recursive - name: Set up Go uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} - name: Install goveralls if: ${{ matrix.go-version == 'stable' && github.ref == 'refs/heads/master' }} run: go install github.com/mattn/goveralls@latest - name: Build run: go build -v ./... - name: Test run: go test -v -covermode atomic -coverprofile=covprofile ./... - name: Gofmt # Run gofmt, print the output and exit with status code 1 if it isn't empty. run: | OUTPUT=$(gofmt -d ./) echo "$OUTPUT" test -z "$OUTPUT" - name: Send coverage if: ${{ matrix.go-version == 'stable' && github.ref == 'refs/heads/master' }} env: COVERALLS_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} run: goveralls -coverprofile=covprofile -service=github ================================================ FILE: .gitignore ================================================ *.flac *.wav _resources_ ================================================ FILE: .gitmodules ================================================ [submodule "flac-test-files"] path = testdata/flac-test-files url = https://github.com/ietf-wg-cellar/flac-test-files ================================================ FILE: LICENSE ================================================ This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ================================================ FILE: README.md ================================================ # flac [![Go build status](https://github.com/mewkiz/flac/actions/workflows/go.yml/badge.svg?branch=master)](https://github.com/mewkiz/flac/actions/workflows/go.yml) [![Coverage Status](https://coveralls.io/repos/github/mewkiz/flac/badge.svg?branch=master)](https://coveralls.io/github/mewkiz/flac?branch=master) [![GoDoc](https://pkg.go.dev/badge/github.com/mewkiz/flac)](https://pkg.go.dev/github.com/mewkiz/flac) This package provides access to [FLAC][1] (Free Lossless Audio Codec) streams. [1]: http://flac.sourceforge.net/format.html ## Documentation Documentation provided by GoDoc. - [flac]: provides access to FLAC (Free Lossless Audio Codec) streams. - [frame][flac/frame]: implements access to FLAC audio frames. - [meta][flac/meta]: implements access to FLAC metadata blocks. [flac]: http://pkg.go.dev/github.com/mewkiz/flac [flac/frame]: http://pkg.go.dev/github.com/mewkiz/flac/frame [flac/meta]: http://pkg.go.dev/github.com/mewkiz/flac/meta ## Changes * Version 1.0.14 (TBA) - Make parsing more robust against corrupt/malicious FLAC files (see [#77](https://github.com/mewkiz/flac/pull/77)). Thanks to [Alex Svetkin](https://github.com/whisk). * Version 1.0.13 (2025-07-11) - Add support for Fixed prediction encoding of FLAC subframes (see [#76](https://github.com/mewkiz/flac/pull/76)). Thanks to [Michael Braha](https://github.com/braheezy). * Version 1.0.12 (2024-08-11) - Improve performance of `flac.NewSeek()` by using a buffered reader (see [#72](https://github.com/mewkiz/flac/pull/72)). - Fix off-by-one error in `Seek` end of stream check (see [#73](https://github.com/mewkiz/flac/pull/73)). * Version 1.0.11 (2024-08-04) - Move example tools to dedicated [mewkiz/flac-tools](https://github.com/mewkiz/flac-tools) repository to reduce external dependencies (see [#62](https://github.com/mewkiz/flac/pull/62)). - Fix seek to frame start (see [#71](https://github.com/mewkiz/flac/pull/71)). Thanks to [Mark Kremer](https://github.com/MarkKremer). - Simplify internal handling of `io.Closer` element in `flac.Stream` and `flac.Encoder` types (see [#70](https://github.com/mewkiz/flac/pull/70)). Thanks to [Mario Salgado](https://github.com/zalgonoise). * Version 1.0.10 (2023-11-11) - Add support for LPC audio sample encoding (see [#66](https://github.com/mewkiz/flac/pull/66)). Thanks to [Mark Kremer](https://github.com/MarkKremer) for bug fixes and [Mattias Wadman](https://github.com/wader) for the invaluable [fq](https://github.com/wader/fq) tool used to investigate FLAC encoding issues. - Replace Travis CI with GitHub actions for CI build status, test status and code coverage [#64](https://github.com/mewkiz/flac/pull/64)). Thanks to [Mark Kremer](https://github.com/MarkKremer). * Version 1.0.9 (2023-10-24) - Fix integer overflow during unfolding of rice residual (see [#61](https://github.com/mewkiz/flac/pull/61)). Thanks to [Mark Kremer](https://github.com/MarkKremer). - Fix decoding of escaped partition audio samples (see [#60](https://github.com/mewkiz/flac/issues/60)). Thanks to [Mark Kremer](https://github.com/MarkKremer). - Handle frame hashing of audio samples with bits-per-sample not evenly divisible by 8 (see [9d50c9e](https://github.com/mewkiz/flac/commit/9d50c9ee99ba322f487ed60442dc16f22b2affb8)). * Version 1.0.8 (2023-04-09) - Fix race condition when reading meta data (see [#56](https://github.com/mewkiz/flac/pull/56)). Thanks to [Zach Orosz](https://github.com/zachorosz). - Fix encoding of 8-bps WAV audio samples (see [#52](https://github.com/mewkiz/flac/pull/52)). Thanks to [Martijn van Beurden](https://github.com/ktmf01). - Fix `StreamInfo` block type error message (see [#49](https://github.com/mewkiz/flac/pull/49)). * Version 1.0.7 (2021-01-28) - Add seek API (see [#44](https://github.com/mewkiz/flac/pull/44) and [#46](https://github.com/mewkiz/flac/pull/46)). Thanks to [Craig Swank](https://github.com/cswank). * Version 1.0.6 (2019-12-20) - Add experimental Encoder API to encode audio samples and metadata blocks (see [#32](https://github.com/mewkiz/flac/pull/32)). - Use go.mod. - Skip ID3v2 data prepended to flac files when parsing (see [36cc17e](https://github.com/mewkiz/flac/commit/36cc17efed51a9bae283d6a3a7a10997492945e7)). - Remove dependency on encodebytes. Thanks to [Mikey Dickerson](https://github.com/mdickers47). - Add 16kHz test case. Thanks to [Chewxy](https://github.com/chewxy). - Fix lint issues (see [#25](https://github.com/mewkiz/flac/issues/25)). * Version 1.0.5 (2016-05-06) - Simplify import paths. Drop use of gopkg.in, and rely on vendoring instead (see [azul3d/engine#1](https://github.com/azul3d/engine/issues/1)). - Add FLAC decoding benchmark (see [d675e0a](https://github.com/mewkiz/flac/blob/d675e0aaccf2e43055f56b9b3feeddfdeed402e2/frame/frame_test.go#L60)). * Version 1.0.4 (2016-02-11) - Add API examples to documentation (see [#11](https://github.com/mewkiz/flac/issues/11)). - Extend test cases (see [aadf80a](https://github.com/mewkiz/flac/commit/aadf80aa28c463a94b8d5c49757e5a0948613ce2)). * Version 1.0.3 (2016-02-02) - Implement decoding of FLAC files with wasted bits-per-sample (see [#12](https://github.com/mewkiz/flac/issues/12)). - Stress test the library using [go-fuzz](https://github.com/dvyukov/go-fuzz) (see [#10](https://github.com/mewkiz/flac/pull/10)). Thanks to [Patrick Mézard](https://github.com/pmezard). * Version 1.0.2 (2015-06-05) - Fix decoding of blocking strategy (see [#9](https://github.com/mewkiz/flac/pull/9)). Thanks to [Sergey Didyk](https://github.com/sdidyk). * Version 1.0.1 (2015-02-25) - Fix two subframe decoding bugs (see [#7](https://github.com/mewkiz/flac/pull/7)). Thanks to [Jonathan MacMillan](https://github.com/perotinus). - Add frame decoding test cases. * Version 1.0.0 (2014-09-30) - Initial release. - Implement decoding of FLAC files. ================================================ FILE: analysis_fixed.go ================================================ package flac import ( "github.com/mewkiz/flac/frame" iobits "github.com/mewkiz/flac/internal/bits" ) // analyzeFixed selects the best fixed predictor (order 0-4) for the given // subframe and fills the fields required by the existing writer so that a // compressed SUBFRAME_FIXED is emitted instead of a verbatim subframe. // // The algorithm is a very small subset of libFLAC's encoder analysis: // 1. For each order 0..4 compute residuals using the fixed coefficients // defined in frame.FixedCoeffs. // 2. For those residuals, choose the Rice parameter k (0..14) that minimizes // the encoded bit-length assuming partition order 0. // 3. Pick the order with the overall fewest bits. // // Note: ignoring partition orders >0 and Rice2 for now. func analyzeFixed(sf *frame.Subframe, bps uint) { bestBits := int(^uint(0) >> 1) // max int bestOrder := 0 bestK := uint(0) // Try predictor orders 0 through 4. for order := 0; order <= 4 && order < len(sf.Samples); order++ { residuals := computeFixedResiduals(sf.Samples, order) k := chooseRice(residuals) bits := costFixed(order, bps, residuals, k) if bits < bestBits { bestBits = bits bestOrder = order bestK = k } } // Populate subframe fields so the existing encode* routines can do their // job. Warm-up samples are already present in sf.Samples. sf.Pred = frame.PredFixed sf.Order = bestOrder sf.ResidualCodingMethod = frame.ResidualCodingMethodRice1 sf.RiceSubframe = &frame.RiceSubframe{ PartOrder: 0, Partitions: []frame.RicePartition{{Param: bestK}}, } // Note: We do NOT mutate sf.Samples. The encoder expects original samples // because it recomputes residuals internally. The metadata we filled in is // enough for encodeFixedSamples to reproduce the exact same residuals. } // computeFixedResiduals returns the residual signal for a given fixed predictor // order. The returned slice has length len(samples)-order. func computeFixedResiduals(samples []int32, order int) []int32 { n := len(samples) res := make([]int32, 0, n-order) switch order { case 0: // x_0[n] = 0 for i := 0; i < n; i++ { res = append(res, samples[i]) } case 1: // x_1[n] = x[n-1] for i := 1; i < n; i++ { predicted := samples[i-1] res = append(res, samples[i]-predicted) } case 2: // x_2[n] = 2*x[n-1] - x[n-2] for i := 2; i < n; i++ { predicted := 2*samples[i-1] - samples[i-2] res = append(res, samples[i]-predicted) } case 3: // x_3[n] = 3*x[n-1] - 3*x[n-2] + x[n-3] for i := 3; i < n; i++ { predicted := 3*samples[i-1] - 3*samples[i-2] + samples[i-3] res = append(res, samples[i]-predicted) } case 4: // x_4[n] = 4*x[n-1] - 6*x[n-2] + 4*x[n-3] - x[n-4] for i := 4; i < n; i++ { predicted := 4*samples[i-1] - 6*samples[i-2] + 4*samples[i-3] - samples[i-4] res = append(res, samples[i]-predicted) } } return res } // chooseRice returns the Rice parameter k (0..14) that minimizes the encoded // length of residuals when using Rice coding with paramSize=4 (Rice1). func chooseRice(residuals []int32) uint { bestK := uint(0) bestBits := int(^uint(0) >> 1) for k := uint(0); k < 15; k++ { // 15 is escape code, so evaluate 0..14 bits := 0 for _, r := range residuals { folded := iobits.EncodeZigZag(r) quo := folded >> k bits += int(quo) + 1 + int(k) // unary + stop bit + k LSBs } if bits < bestBits { bestBits = bits bestK = k } } return bestK } // costFixed returns the number of bits needed to code the subframe with the // given parameters. 6 bits for the subframe header are included so orders with // more warm-up samples are fairly compared. func costFixed(order int, bps uint, residuals []int32, k uint) int { warmUpBits := order * int(bps) // residual bits for chosen k residBits := 0 for _, r := range residuals { folded := iobits.EncodeZigZag(r) quo := folded >> k residBits += int(quo) + 1 + int(k) } // Subframe header is 6 bits + 1 wasted flag bit (always 0 here) return 6 + warmUpBits + residBits } // analyzeSubframe decides on the best prediction method (constant, verbatim, or // fixed) for a subframe that is currently marked PredVerbatim. It will update // the Subframe fields to use the chosen method. The heuristic is simple: it // picks the encoding that yields the fewest estimated bits when assuming a // single Rice partition. func analyzeSubframe(sf *frame.Subframe, bps uint) { // Only analyze when the caller has not chosen a prediction method yet. if sf.Pred != frame.PredVerbatim { return } samples := sf.Samples n := len(samples) if n == 0 { return } // Guard against degenerate inputs. If there are fewer than two samples we // simply keep verbatim encoding. if n < 2 { return } // --- Constant predictor cost. allEqual := true for i := 1; i < n; i++ { if samples[i] != samples[0] { allEqual = false break } } constBits := int(^uint(0) >> 1) // max int if allEqual { // 6-bit header + one sample. constBits = 6 + int(bps) } // --- Verbatim predictor cost. verbatimBits := 6 + n*int(bps) // 6-bit header + raw samples // --- Fixed predictor: reuse existing helper to find best order/k. analyzeFixed(sf, bps) // fills Order, RiceSubframe, etc. // Cost of that choice fixedResiduals := computeFixedResiduals(samples, sf.Order) fixedBits := costFixed(sf.Order, bps, fixedResiduals, sf.RiceSubframe.Partitions[0].Param) // Choose the smallest. switch { case constBits < verbatimBits && constBits < fixedBits: // Use constant encoding. sf.Pred = frame.PredConstant // No other metadata needed. case fixedBits < verbatimBits: // Keep fixed settings filled in by analyzeFixed. sf.Pred = frame.PredFixed default: // Stick with verbatim – restore defaults that analyzeFixed may have // overwritten. sf.Pred = frame.PredVerbatim sf.Order = 0 sf.RiceSubframe = nil } } ================================================ FILE: enc_benchmark_test.go ================================================ package flac import ( "bytes" "math" "testing" "github.com/mewkiz/flac/frame" "github.com/mewkiz/flac/meta" ) // BenchmarkEncodeSyntheticAudio measures the performance of encoding synthetic // audio data. It creates a simple sine wave pattern to avoid dependency on // external files. func BenchmarkEncodeSyntheticAudio(b *testing.B) { // Create synthetic audio data (1 second of 44.1kHz stereo audio) const ( sampleRate = 44100 nchannels = 2 bitsPerSample = 16 nsamples = sampleRate ) // Create StreamInfo info := &meta.StreamInfo{ BlockSizeMin: 4096, BlockSizeMax: 4096, FrameSizeMin: 0, FrameSizeMax: 0, SampleRate: sampleRate, NChannels: nchannels, BitsPerSample: bitsPerSample, NSamples: nsamples, } // Generate synthetic audio data (sine wave) samples := make([]int32, nsamples*nchannels) freq := 440.0 // A4 note for i := 0; i < nsamples; i++ { // Generate a sine wave sample := int32(math.Sin(2*math.Pi*freq*float64(i)/float64(sampleRate)) * 32767) // Fill both channels with the same data samples[i*2] = sample samples[i*2+1] = sample } // Reset the timer before the actual benchmark b.ResetTimer() // Run the benchmark for range b.N { // Create a buffer to write the encoded data buf := &bytes.Buffer{} // Create encoder enc, err := NewEncoder(buf, info) if err != nil { b.Fatal(err) } // Process samples in blocks for offset := 0; offset < nsamples; offset += 4096 { blockSize := 4096 if offset+blockSize > nsamples { blockSize = nsamples - offset } // Create frame f := &frame.Frame{ Header: frame.Header{ HasFixedBlockSize: true, BlockSize: uint16(blockSize), SampleRate: sampleRate, Channels: frame.ChannelsLR, BitsPerSample: bitsPerSample, }, } // Create subframes f.Subframes = make([]*frame.Subframe, nchannels) for channel := 0; channel < nchannels; channel++ { // Extract samples for this channel channelSamples := make([]int32, blockSize) for i := 0; i < blockSize; i++ { channelSamples[i] = samples[(offset+i)*nchannels+channel] } // Create verbatim subframe since we're just testing encoding speed f.Subframes[channel] = &frame.Subframe{ SubHeader: frame.SubHeader{ Pred: frame.PredVerbatim, }, Samples: channelSamples, NSamples: blockSize, } } // Encode frame if err := enc.WriteFrame(f); err != nil { b.Fatal(err) } } // Close encoder if err := enc.Close(); err != nil { b.Fatal(err) } } } ================================================ FILE: enc_test.go ================================================ package flac_test import ( "bytes" "errors" "io" "io/ioutil" "os" "slices" "testing" "github.com/mewkiz/flac" "github.com/mewkiz/flac/meta" ) var paths = []string{ // metadata test cases. "meta/testdata/input-SCPAP.flac", "meta/testdata/input-SCVA.flac", "meta/testdata/input-SCVPAP.flac", "meta/testdata/input-VA.flac", "meta/testdata/input-SCVAUP.flac", // empty metadata block (of type 0x7e) "meta/testdata/input-SVAUP.flac", // empty metadata block (of type 0x7e) "meta/testdata/silence.flac", // flac test cases. "testdata/19875.flac", // prediction method 3 (FIR) "testdata/44127.flac", // prediction method 3 (FIR) "testdata/59996.flac", "testdata/80574.flac", // prediction method 3 (FIR) "testdata/172960.flac", "testdata/189983.flac", "testdata/191885.flac", "testdata/212768.flac", "testdata/220014.flac", // prediction method 2 (Fixed) "testdata/243749.flac", // prediction method 2 (Fixed) "testdata/256529.flac", "testdata/257344.flac", // prediction method 3 (FIR) "testdata/8297-275156-0011.flac", // prediction method 3 (FIR) "testdata/love.flac", // wasted bits // test cases for prediction analysis. // // Run `testdata/convert_to_verbatim.sh` to generate these test files. "testdata/19875_verbatim.flac", // verbatim "testdata/44127_verbatim.flac", // verbatim "testdata/59996_verbatim.flac", // verbatim "testdata/80574_verbatim.flac", // verbatim "testdata/172960_verbatim.flac", // verbatim "testdata/189983_verbatim.flac", // verbatim "testdata/191885_verbatim.flac", // verbatim "testdata/212768_verbatim.flac", // verbatim "testdata/220014_verbatim.flac", // verbatim "testdata/243749_verbatim.flac", // verbatim "testdata/256529_verbatim.flac", // verbatim "testdata/257344_verbatim.flac", // verbatim // IETF test cases. "testdata/flac-test-files/subset/01 - blocksize 4096.flac", "testdata/flac-test-files/subset/02 - blocksize 4608.flac", "testdata/flac-test-files/subset/03 - blocksize 16.flac", "testdata/flac-test-files/subset/04 - blocksize 192.flac", "testdata/flac-test-files/subset/05 - blocksize 254.flac", "testdata/flac-test-files/subset/06 - blocksize 512.flac", "testdata/flac-test-files/subset/07 - blocksize 725.flac", "testdata/flac-test-files/subset/08 - blocksize 1000.flac", "testdata/flac-test-files/subset/09 - blocksize 1937.flac", "testdata/flac-test-files/subset/10 - blocksize 2304.flac", "testdata/flac-test-files/subset/11 - partition order 8.flac", "testdata/flac-test-files/subset/12 - qlp precision 15 bit.flac", "testdata/flac-test-files/subset/13 - qlp precision 2 bit.flac", "testdata/flac-test-files/subset/14 - wasted bits.flac", "testdata/flac-test-files/subset/15 - only verbatim subframes.flac", "testdata/flac-test-files/subset/16 - partition order 8 containing escaped partitions.flac", "testdata/flac-test-files/subset/17 - all fixed orders.flac", "testdata/flac-test-files/subset/18 - precision search.flac", "testdata/flac-test-files/subset/19 - samplerate 35467Hz.flac", "testdata/flac-test-files/subset/20 - samplerate 39kHz.flac", "testdata/flac-test-files/subset/21 - samplerate 22050Hz.flac", "testdata/flac-test-files/subset/22 - 12 bit per sample.flac", "testdata/flac-test-files/subset/23 - 8 bit per sample.flac", "testdata/flac-test-files/subset/24 - variable blocksize file created with flake revision 264.flac", "testdata/flac-test-files/subset/25 - variable blocksize file created with flake revision 264, modified to create smaller blocks.flac", // NOTE: the only diff is that "26 - ...flac" uses `block_size: 0b111 // (end of header (16 bit))` to encode the block size at the end of the // header, whereas mewkiz/flac encodes it directly `block_size: 4096 // (0b1100)`. Notably, the computed md5 hash of the decoded audio samples // is identical (MD5: 3b2939b39ae7369b80451c77865e60c1). Thus, ignore the // test case. //"testdata/flac-test-files/subset/26 - variable blocksize file created with CUETools.Flake 2.1.6.flac", // NOTE: the only diff is that "27 - ...flac" uses `block_size: 0b111 // (end of header (16 bit))` to encode the block size at the end of the // header, whereas mewkiz/flac encodes it directly `block_size: 4608 // (0b101)`. Notably, the computed md5 hash of the decoded audio samples // is identical (MD5: 9fb66177d2f735d4b1f501a5af1320a3). Thus, ignore the // test case. //"testdata/flac-test-files/subset/27 - old format variable blocksize file created with Flake 0.11.flac", "testdata/flac-test-files/subset/28 - high resolution audio, default settings.flac", "testdata/flac-test-files/subset/29 - high resolution audio, blocksize 16384.flac", "testdata/flac-test-files/subset/30 - high resolution audio, blocksize 13456.flac", "testdata/flac-test-files/subset/31 - high resolution audio, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/32 - high resolution audio, partition order 8 containing escaped partitions.flac", "testdata/flac-test-files/subset/33 - samplerate 192kHz.flac", // NOTE: the only diff is that "34 - ...flac" uses `0b1100 (end of header // (8 bit*1000))` to encode the sample rate at the end of the header, // whereas mewkiz/flac encodes it directly `192000 (0b11)`. Notably, the // computed md5 hash of the decoded audio samples is identical // (MD5: 942f56e503437dfd4c269c331774b2e3). Thus, ignore the test case. //"testdata/flac-test-files/subset/34 - samplerate 192kHz, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/35 - samplerate 134560Hz.flac", "testdata/flac-test-files/subset/36 - samplerate 384kHz.flac", "testdata/flac-test-files/subset/37 - 20 bit per sample.flac", "testdata/flac-test-files/subset/38 - 3 channels (3.0).flac", "testdata/flac-test-files/subset/39 - 4 channels (4.0).flac", "testdata/flac-test-files/subset/40 - 5 channels (5.0).flac", "testdata/flac-test-files/subset/41 - 6 channels (5.1).flac", "testdata/flac-test-files/subset/42 - 7 channels (6.1).flac", "testdata/flac-test-files/subset/43 - 8 channels (7.1).flac", // NOTE: the only diff is that "44 - ...flac" uses `0b1100 (end of header // (8 bit*1000))` to encode the sample rate at the end of the header, // whereas mewkiz/flac encodes it directly `192000 (0b11)`. Notably, the // computed md5 hash of the decoded audio samples is identical // (MD5: cdf531d4d4b95233986bc499518a89db). Thus, ignore the test case. //"testdata/flac-test-files/subset/44 - 8-channel surround, 192kHz, 24 bit, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/45 - no total number of samples set.flac", "testdata/flac-test-files/subset/46 - no min-max framesize set.flac", "testdata/flac-test-files/subset/47 - only STREAMINFO.flac", "testdata/flac-test-files/subset/48 - Extremely large SEEKTABLE.flac", "testdata/flac-test-files/subset/49 - Extremely large PADDING.flac", "testdata/flac-test-files/subset/50 - Extremely large PICTURE.flac", "testdata/flac-test-files/subset/51 - Extremely large VORBISCOMMENT.flac", "testdata/flac-test-files/subset/52 - Extremely large APPLICATION.flac", "testdata/flac-test-files/subset/53 - CUESHEET with very many indexes.flac", "testdata/flac-test-files/subset/54 - 1000x repeating VORBISCOMMENT.flac", "testdata/flac-test-files/subset/55 - file 48-53 combined.flac", "testdata/flac-test-files/subset/56 - JPG PICTURE.flac", "testdata/flac-test-files/subset/57 - PNG PICTURE.flac", "testdata/flac-test-files/subset/58 - GIF PICTURE.flac", "testdata/flac-test-files/subset/59 - AVIF PICTURE.flac", "testdata/flac-test-files/subset/60 - mono audio.flac", "testdata/flac-test-files/subset/61 - predictor overflow check, 16-bit.flac", "testdata/flac-test-files/subset/62 - predictor overflow check, 20-bit.flac", "testdata/flac-test-files/subset/63 - predictor overflow check, 24-bit.flac", "testdata/flac-test-files/subset/64 - rice partitions with escape code zero.flac", } func TestEncodeRoundTrip(t *testing.T) { for _, path := range paths { t.Run(path, func(t *testing.T) { if !exists(path) { t.Skipf("path %q does not exist", path) } // Decode source file. stream, err := flac.ParseFile(path) if err != nil { t.Fatalf("%q: unable to parse FLAC file; %v", path, err) } defer stream.Close() // Open encoder for FLAC stream. out := new(bytes.Buffer) enc, err := flac.NewEncoder(out, stream.Info, stream.Blocks...) if err != nil { t.Fatalf("%q: unable to create encoder for FLAC stream; %v", path, err) } enc.EnablePredictionAnalysis(false) // disable prediction analysis to support round-trip decode/encode test. // Encode audio samples. for { frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } t.Fatalf("%q: unable to parse audio frame of FLAC stream; %v", path, err) } if err := enc.WriteFrame(frame); err != nil { t.Fatalf("%q: unable to encode audio frame of FLAC stream; %v", path, err) } } // Close encoder and flush pending writes. if err := enc.Close(); err != nil { t.Fatalf("%q: unable to close encoder for FLAC stream; %v", path, err) } // Compare source and destination FLAC streams. want, err := ioutil.ReadFile(path) if err != nil { t.Fatalf("%q: unable to read file; %v", path, err) } got := out.Bytes() if !bytes.Equal(got, want) { t.Fatalf("%q: content mismatch; expected % X, got % X", path, want, got) } }) } } func TestEncodeComment(t *testing.T) { // Decode FLAC file. const path = "meta/testdata/input-VA.flac" src, err := flac.ParseFile(path) if err != nil { t.Fatalf("unable to parse input FLAC file; %v", err) } defer src.Close() // Add custom vorbis comment. const want = "FLAC encoding test case" for _, block := range src.Blocks { if comment, ok := block.Body.(*meta.VorbisComment); ok { comment.Vendor = want } } // Open encoder for FLAC stream. out := new(bytes.Buffer) enc, err := flac.NewEncoder(out, src.Info, src.Blocks...) if err != nil { t.Fatalf("%q: unable to create encoder for FLAC stream; %v", path, err) } // Encode audio samples. for { frame, err := src.ParseNext() if err != nil { if err == io.EOF { break } t.Fatalf("%q: unable to parse audio frame of FLAC stream; %v", path, err) } if err := enc.WriteFrame(frame); err != nil { t.Fatalf("%q: unable to encode audio frame of FLAC stream; %v", path, err) } } // Close encoder and flush pending writes. if err := enc.Close(); err != nil { t.Fatalf("%q: unable to close encoder for FLAC stream; %v", path, err) } // Parse encoded FLAC file. stream, err := flac.Parse(out) if err != nil { t.Fatalf("unable to parse output FLAC file; %v", err) } defer stream.Close() // Add custom vorbis comment. for _, block := range stream.Blocks { if comment, ok := block.Body.(*meta.VorbisComment); ok { got := comment.Vendor if got != want { t.Errorf("Vorbis comment mismatch; expected %q, got %q", want, got) continue } } } } func TestEncodeAnalysisFixed(t *testing.T) { for _, path := range paths { t.Run(path, func(t *testing.T) { if !exists(path) { t.Skipf("path %q does not exist", path) } // Decode source file. stream, err := flac.ParseFile(path) if err != nil { t.Fatalf("%q: unable to parse FLAC file; %v", path, err) } defer stream.Close() // Open encoder for FLAC stream. out := new(bytes.Buffer) enc, err := flac.NewEncoder(out, stream.Info, stream.Blocks...) if err != nil { t.Fatalf("%q: unable to create encoder for FLAC stream; %v", path, err) } enc.EnablePredictionAnalysis(true) // enable prediction encoding // Encode audio samples. for { frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } t.Fatalf("%q: unable to parse audio frame of FLAC stream; %v", path, err) } if err := enc.WriteFrame(frame); err != nil { t.Fatalf("%q: unable to encode audio frame of FLAC stream; %v", path, err) } } // Close encoder and flush pending writes. if err := enc.Close(); err != nil { t.Fatalf("%q: unable to close encoder for FLAC stream; %v", path, err) } // Compare source and destination FLAC streams. wantStream, err := flac.ParseFile(path) if err != nil { t.Fatalf("%q: unable to parse FLAC file; %v", path, err) } wantSamples, err := getSamples(wantStream) if err != nil { t.Fatalf("%q: unable to get audio samples of FLAC file; %v", path, err) } if err := wantStream.Close(); err != nil { t.Fatalf("%q: unable to close FLAC stream; %v", path, err) } fi, err := os.Stat(path) if err != nil { t.Fatalf("%q: unable to stat FLAC file; %v", path, err) } wantSize := fi.Size() gotBytes := out.Bytes() gotSize := int64(len(gotBytes)) gotStream, err := flac.Parse(bytes.NewReader(gotBytes)) if err != nil { t.Fatalf("%q: unable to parse encoded FLAC file; %v", path, err) } gotSamples, err := getSamples(gotStream) if err != nil { t.Fatalf("%q: unable to get audio samples of encoded FLAC file; %v", path, err) } if err := gotStream.Close(); err != nil { t.Fatalf("%q: unable to close encoded FLAC stream; %v", path, err) } if !slices.Equal(wantSamples, gotSamples) { t.Fatalf("%q: content mismatch; expected %#v, got %#v", path, wantSamples, gotSamples) } percent := 100 * float64(gotSize) / float64(wantSize) if wantSize != gotSize { t.Logf("%q: input size: %d, output size: %d. ratio: %.02f%%", path, wantSize, gotSize, percent) } }) } } // getSamples returns all audio samples in stream. func getSamples(stream *flac.Stream) ([]int32, error) { var out []int32 for { frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } return nil, errors.New("unable to parse audio frame of FLAC stream") } for _, subframe := range frame.Subframes { out = append(out, subframe.Samples...) } } return out, nil } // exists reports whether the given file or directory exists. func exists(path string) bool { _, err := os.Stat(path) return err == nil } ================================================ FILE: encode.go ================================================ package flac import ( "crypto/md5" "hash" "io" "github.com/icza/bitio" "github.com/mewkiz/flac/meta" "github.com/mewkiz/pkg/errutil" ) // An Encoder represents a FLAC encoder. type Encoder struct { // FLAC stream of encoder. *Stream // Underlying io.Writer or io.WriteCloser to the output stream. w io.Writer // Minimum and maximum block size (in samples) of frames written by encoder. blockSizeMin, blockSizeMax uint16 // Minimum and maximum frame size (in bytes) of frames written by encoder. frameSizeMin, frameSizeMax uint32 // MD5 running hash of unencoded audio samples. md5sum hash.Hash // Total number of samples (per channel) written by encoder. nsamples uint64 // Current frame number if block size is fixed, and the first sample number // of the current frame otherwise. curNum uint64 // AnalysisEnabled indicates whether analysis is enabled for the encoder. AnalysisEnabled bool } // NewEncoder returns a new FLAC encoder for the given metadata StreamInfo block // and optional metadata blocks. // // By default prediction analysis is enabled. For more information, see // Encoder.EnablePredictionAnalysis. func NewEncoder(w io.Writer, info *meta.StreamInfo, blocks ...*meta.Block) (*Encoder, error) { // Store FLAC signature. enc := &Encoder{ Stream: &Stream{ Info: info, Blocks: blocks, }, w: w, md5sum: md5.New(), AnalysisEnabled: true, // enable prediction analysis by default. } bw := bitio.NewWriter(w) if _, err := bw.Write(flacSignature); err != nil { return nil, errutil.Err(err) } // Encode metadata blocks. // TODO: consider using bufio.NewWriter. if err := encodeStreamInfo(bw, info, len(blocks) == 0); err != nil { return nil, errutil.Err(err) } for i, block := range blocks { if err := encodeBlock(bw, block, i == len(blocks)-1); err != nil { return nil, errutil.Err(err) } } // Flush pending writes of metadata blocks. if _, err := bw.Align(); err != nil { return nil, errutil.Err(err) } // Return encoder to be used for encoding audio samples. return enc, nil } // Close closes the underlying io.Writer of the encoder and flushes any pending // writes. If the io.Writer implements io.Seeker, the encoder will update the // StreamInfo metadata block with the MD5 checksum of the unencoded audio // samples, the number of samples, and the minimum and maximum frame size and // block size. func (enc *Encoder) Close() error { // TODO: check if bit writer should be flushed before seeking on enc.w. // Update StreamInfo metadata block. if ws, ok := enc.w.(io.WriteSeeker); ok { if _, err := ws.Seek(int64(len(flacSignature)), io.SeekStart); err != nil { return errutil.Err(err) } // Update minimum and maximum block size (in samples) of FLAC stream. enc.Info.BlockSizeMin = enc.blockSizeMin enc.Info.BlockSizeMax = enc.blockSizeMax // Update minimum and maximum frame size (in bytes) of FLAC stream. enc.Info.FrameSizeMin = enc.frameSizeMin enc.Info.FrameSizeMax = enc.frameSizeMax // Update total number of samples (per channel) of FLAC stream. enc.Info.NSamples = enc.nsamples // Update MD5 checksum of the unencoded audio samples. sum := enc.md5sum.Sum(nil) for i := range sum { enc.Info.MD5sum[i] = sum[i] } bw := bitio.NewWriter(ws) // Write updated StreamInfo metadata block to output stream. if err := encodeStreamInfo(bw, enc.Info, len(enc.Blocks) == 0); err != nil { return errutil.Err(err) } if _, err := bw.Align(); err != nil { return errutil.Err(err) } } if closer, ok := enc.w.(io.Closer); ok { return closer.Close() } return nil } // EnablePredictionAnalysis specifies whether to enable analysis for the // encoder. When analysis is enabled, subframes that are currently marked as // PredVerbatim will be analyzed to use the best prediction method // (constant, fixed or verbatim) based on size. func (enc *Encoder) EnablePredictionAnalysis(enable bool) { enc.AnalysisEnabled = enable } ================================================ FILE: encode_frame.go ================================================ package flac import ( "encoding/binary" "io" "math" "github.com/icza/bitio" "github.com/mewkiz/flac/frame" "github.com/mewkiz/flac/internal/hashutil/crc16" "github.com/mewkiz/flac/internal/hashutil/crc8" "github.com/mewkiz/flac/internal/utf8" "github.com/mewkiz/pkg/errutil" ) // --- [ Frame ] --------------------------------------------------------------- // WriteFrame encodes the given audio frame to the output stream. The Num field // of the frame header is automatically calculated by the encoder. func (enc *Encoder) WriteFrame(f *frame.Frame) error { // Sanity checks. nchannels := int(enc.Info.NChannels) if nchannels != len(f.Subframes) { return errutil.Newf("subframe and channel count mismatch; expected %d, got %d", nchannels, len(f.Subframes)) } nsamplesPerChannel := f.Subframes[0].NSamples for i, subframe := range f.Subframes { if nsamplesPerChannel != len(subframe.Samples) { return errutil.Newf("invalid number of samples in channel %d; expected %d, got %d", i, nsamplesPerChannel, len(subframe.Samples)) } } if nchannels != f.Channels.Count() { return errutil.Newf("channel count mismatch; expected %d, got %d", nchannels, f.Channels.Count()) } // Create a new CRC-16 hash writer which adds the data from all write // operations to a running hash. h := crc16.NewIBM() hw := io.MultiWriter(h, enc.w) // Encode frame header. f.Num = enc.curNum if f.HasFixedBlockSize { enc.curNum++ } else { enc.curNum += uint64(nsamplesPerChannel) } enc.nsamples += uint64(nsamplesPerChannel) blockSize := uint16(nsamplesPerChannel) if enc.blockSizeMin == 0 || blockSize < enc.blockSizeMin { enc.blockSizeMin = blockSize } if enc.blockSizeMax == 0 || blockSize > enc.blockSizeMax { enc.blockSizeMax = blockSize } // TODO: track number of bytes written to hw, to update values of // frameSizeMin and frameSizeMax. // Add unencoded audio samples to running MD5 hash. f.Hash(enc.md5sum) if err := enc.encodeFrameHeader(hw, f.Header); err != nil { return errutil.Err(err) } // Inter-channel decorrelation of subframe samples. f.Decorrelate() defer f.Correlate() // NOTE: revert decorrelation of audio samples after encoding is done (to make encode non-destructive). // Encode subframes. bw := bitio.NewWriter(hw) for channel, subframe := range f.Subframes { // The side channel requires an extra bit per sample when using // inter-channel decorrelation. bps := uint(f.BitsPerSample) switch f.Channels { case frame.ChannelsSideRight: // channel 0 is the side channel. if channel == 0 { bps++ } case frame.ChannelsLeftSide, frame.ChannelsMidSide: // channel 1 is the side channel. if channel == 1 { bps++ } } // optional prediction analysis // // (leave subframe as-is if AnalysisEnabled is false) if enc.AnalysisEnabled { switch subframe.Pred { case frame.PredVerbatim: analyzeSubframe(subframe, bps) } } if err := encodeSubframe(bw, f.Header, subframe, bps); err != nil { return errutil.Err(err) } } // Zero-padding to byte alignment. // Flush pending writes to subframe. if _, err := bw.Align(); err != nil { return errutil.Err(err) } // CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with 0) of // everything before the crc, back to and including the frame header sync // code. crc := h.Sum16() if err := binary.Write(enc.w, binary.BigEndian, crc); err != nil { return errutil.Err(err) } return nil } // --- [ Frame header ] -------------------------------------------------------- // encodeFrameHeader encodes the given frame header, writing to w. func (enc *Encoder) encodeFrameHeader(w io.Writer, hdr frame.Header) error { // Create a new CRC-8 hash writer which adds the data from all write // operations to a running hash. h := crc8.NewATM() hw := io.MultiWriter(h, w) bw := bitio.NewWriter(hw) // Closing the *bitio.Writer will not close the underlying writer defer bw.Close() // Sync code: 11111111111110 if err := bw.WriteBits(0x3FFE, 14); err != nil { return errutil.Err(err) } // Reserved: 0 if err := bw.WriteBits(0x0, 1); err != nil { return errutil.Err(err) } // Blocking strategy: // 0 : fixed-blocksize stream; frame header encodes the frame number // 1 : variable-blocksize stream; frame header encodes the sample number if err := bw.WriteBool(!hdr.HasFixedBlockSize); err != nil { return errutil.Err(err) } // Encode block size. nblockSizeSuffixBits, err := encodeFrameHeaderBlockSize(bw, hdr.BlockSize) if err != nil { return errutil.Err(err) } // Encode sample rate. sampleRateSuffixBits, nsampleRateSuffixBits, err := encodeFrameHeaderSampleRate(bw, hdr.SampleRate) if err != nil { return errutil.Err(err) } // Encode channels assignment. if err := encodeFrameHeaderChannels(bw, hdr.Channels); err != nil { return errutil.Err(err) } // Encode bits-per-sample. if err := encodeFrameHeaderBitsPerSample(bw, hdr.BitsPerSample); err != nil { return errutil.Err(err) } // Reserved: 0 if err := bw.WriteBits(0x0, 1); err != nil { return errutil.Err(err) } // if (variable blocksize) // <8-56>:"UTF-8" coded sample number (decoded number is 36 bits) // else // <8-48>:"UTF-8" coded frame number (decoded number is 31 bits) if err := utf8.Encode(bw, hdr.Num); err != nil { return errutil.Err(err) } // Write block size after the frame header (used for uncommon block sizes). if nblockSizeSuffixBits > 0 { // 0110 : get 8 bit (blocksize-1) from end of header // 0111 : get 16 bit (blocksize-1) from end of header if err := bw.WriteBits(uint64(hdr.BlockSize-1), nblockSizeSuffixBits); err != nil { return errutil.Err(err) } } // Write sample rate after the frame header (used for uncommon sample rates). if nsampleRateSuffixBits > 0 { if err := bw.WriteBits(sampleRateSuffixBits, nsampleRateSuffixBits); err != nil { return errutil.Err(err) } } // Flush pending writes to frame header. if _, err := bw.Align(); err != nil { return errutil.Err(err) } // CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) of // everything before the crc, including the sync code. crc := h.Sum8() if err := binary.Write(w, binary.BigEndian, crc); err != nil { return errutil.Err(err) } return nil } // ~~~ [ Block size ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeFrameHeaderBlockSize encodes the block size of the frame header, // writing to bw. It returns the number of bits used to store block size after // the frame header. func encodeFrameHeaderBlockSize(bw *bitio.Writer, blockSize uint16) (nblockSizeSuffixBits byte, err error) { // Block size in inter-channel samples: // 0000 : reserved // 0001 : 192 samples // 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608 // 0110 : get 8 bit (blocksize-1) from end of header // 0111 : get 16 bit (blocksize-1) from end of header // 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768 var bits uint64 switch blockSize { case 192: // 0001 bits = 0x1 case 576, 1152, 2304, 4608: // 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608 bits = 0x2 + uint64(math.Log2(float64(blockSize/576))) case 256, 512, 1024, 2048, 4096, 8192, 16384, 32768: // 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768 bits = 0x8 + uint64(math.Log2(float64(blockSize/256))) default: if blockSize <= 256 { // 0110 : get 8 bit (blocksize-1) from end of header bits = 0x6 nblockSizeSuffixBits = 8 } else { // 0111 : get 16 bit (blocksize-1) from end of header bits = 0x7 nblockSizeSuffixBits = 16 } } if err := bw.WriteBits(bits, 4); err != nil { return 0, errutil.Err(err) } return nblockSizeSuffixBits, nil } // ~~~ [ Sample rate ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeFrameHeaderSampleRate encodes the sample rate of the frame header, // writing to bw. It returns the bits and the number of bits used to store // sample rate after the frame header. func encodeFrameHeaderSampleRate(bw *bitio.Writer, sampleRate uint32) (sampleRateSuffixBits uint64, nsampleRateSuffixBits byte, err error) { // Sample rate: // 0000 : get from STREAMINFO metadata block // 0001 : 88.2kHz // 0010 : 176.4kHz // 0011 : 192kHz // 0100 : 8kHz // 0101 : 16kHz // 0110 : 22.05kHz // 0111 : 24kHz // 1000 : 32kHz // 1001 : 44.1kHz // 1010 : 48kHz // 1011 : 96kHz // 1100 : get 8 bit sample rate (in kHz) from end of header // 1101 : get 16 bit sample rate (in Hz) from end of header // 1110 : get 16 bit sample rate (in tens of Hz) from end of header // 1111 : invalid, to prevent sync-fooling string of 1s var bits uint64 switch sampleRate { case 0: // 0000 : get from STREAMINFO metadata block bits = 0 case 88200: // 0001 : 88.2kHz bits = 0x1 case 176400: // 0010 : 176.4kHz bits = 0x2 case 192000: // 0011 : 192kHz bits = 0x3 case 8000: // 0100 : 8kHz bits = 0x4 case 16000: // 0101 : 16kHz bits = 0x5 case 22050: // 0110 : 22.05kHz bits = 0x6 case 24000: // 0111 : 24kHz bits = 0x7 case 32000: // 1000 : 32kHz bits = 0x8 case 44100: // 1001 : 44.1kHz bits = 0x9 case 48000: // 1010 : 48kHz bits = 0xA case 96000: // 1011 : 96kHz bits = 0xB default: switch { case sampleRate <= 255000 && sampleRate%1000 == 0: // 1100 : get 8 bit sample rate (in kHz) from end of header bits = 0xC sampleRateSuffixBits = uint64(sampleRate / 1000) nsampleRateSuffixBits = 8 case sampleRate <= 65535: // 1101 : get 16 bit sample rate (in Hz) from end of header bits = 0xD sampleRateSuffixBits = uint64(sampleRate) nsampleRateSuffixBits = 16 case sampleRate <= 655350 && sampleRate%10 == 0: // 1110 : get 16 bit sample rate (in tens of Hz) from end of header bits = 0xE sampleRateSuffixBits = uint64(sampleRate / 10) nsampleRateSuffixBits = 16 default: return 0, 0, errutil.Newf("unable to encode sample rate %v", sampleRate) } } if err := bw.WriteBits(bits, 4); err != nil { return 0, 0, errutil.Err(err) } return sampleRateSuffixBits, nsampleRateSuffixBits, nil } // ~~~ [ Channels assignment ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeFrameHeaderChannels encodes the channels assignment of the frame // header, writing to bw. func encodeFrameHeaderChannels(bw *bitio.Writer, channels frame.Channels) error { // Channel assignment. // 0000-0111 : (number of independent channels)-1. Where defined, the channel order follows SMPTE/ITU-R recommendations. The assignments are as follows: // 1 channel: mono // 2 channels: left, right // 3 channels: left, right, center // 4 channels: front left, front right, back left, back right // 5 channels: front left, front right, front center, back/surround left, back/surround right // 6 channels: front left, front right, front center, LFE, back/surround left, back/surround right // 7 channels: front left, front right, front center, LFE, back center, side left, side right // 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right // 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel // 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel // 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel // 1011-1111 : reserved var bits uint64 switch channels { case frame.ChannelsMono, frame.ChannelsLR, frame.ChannelsLRC, frame.ChannelsLRLsRs, frame.ChannelsLRCLsRs, frame.ChannelsLRCLfeLsRs, frame.ChannelsLRCLfeCsSlSr, frame.ChannelsLRCLfeLsRsSlSr: // 1 channel: mono. // 2 channels: left, right. // 3 channels: left, right, center. // 4 channels: left, right, left surround, right surround. // 5 channels: left, right, center, left surround, right surround. // 6 channels: left, right, center, LFE, left surround, right surround. // 7 channels: left, right, center, LFE, center surround, side left, side right. // 8 channels: left, right, center, LFE, left surround, right surround, side left, side right. bits = uint64(channels.Count() - 1) case frame.ChannelsLeftSide: // 2 channels: left, side; using inter-channel decorrelation. // 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel bits = 0x8 case frame.ChannelsSideRight: // 2 channels: side, right; using inter-channel decorrelation. // 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel bits = 0x9 case frame.ChannelsMidSide: // 2 channels: mid, side; using inter-channel decorrelation. // 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel bits = 0xA default: return errutil.Newf("support for channel assignment %v not yet implemented", channels) } if err := bw.WriteBits(bits, 4); err != nil { return errutil.Err(err) } return nil } // ~~~ [ Bits-per-sample ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeFrameHeaderBitsPerSample encodes the bits-per-sample of the frame // header, writing to bw. func encodeFrameHeaderBitsPerSample(bw *bitio.Writer, bps uint8) error { // Sample size in bits: // 000 : get from STREAMINFO metadata block // 001 : 8 bits per sample // 010 : 12 bits per sample // 011 : reserved // 100 : 16 bits per sample // 101 : 20 bits per sample // 110 : 24 bits per sample // 111 : reserved var bits uint64 switch bps { case 0: // 000 : get from STREAMINFO metadata block bits = 0x0 case 8: // 001 : 8 bits per sample bits = 0x1 case 12: // 010 : 12 bits per sample bits = 0x2 case 16: // 100 : 16 bits per sample bits = 0x4 case 20: // 101 : 20 bits per sample bits = 0x5 case 24: // 110 : 24 bits per sample bits = 0x6 default: return errutil.Newf("support for sample size %v not yet implemented", bps) } if err := bw.WriteBits(bits, 3); err != nil { return errutil.Err(err) } return nil } ================================================ FILE: encode_meta.go ================================================ package flac import ( "encoding/binary" "fmt" "io" "github.com/icza/bitio" "github.com/mewkiz/flac/internal/ioutilx" "github.com/mewkiz/flac/meta" "github.com/mewkiz/pkg/errutil" ) // --- [ Metadata block ] ------------------------------------------------------ // encodeBlock encodes the metadata block, writing to bw. func encodeBlock(bw *bitio.Writer, block *meta.Block, last bool) error { if block.Type == meta.TypePadding { return encodePadding(bw, block.Length, last) } if block.Length == 0 { return encodeEmptyBlock(bw, block.Type, last) } switch body := block.Body.(type) { case *meta.StreamInfo: return encodeStreamInfo(bw, body, last) case *meta.Application: return encodeApplication(bw, body, last) case *meta.SeekTable: return encodeSeekTable(bw, body, last) case *meta.VorbisComment: return encodeVorbisComment(bw, body, last) case *meta.CueSheet: return encodeCueSheet(bw, body, last) case *meta.Picture: return encodePicture(bw, body, last) default: panic(fmt.Errorf("support for metadata block body type %T not yet implemented", body)) } } // --- [ Metadata block header ] ----------------------------------------------- // encodeEmptyBlock encodes the metadata block header of an empty metadata // block with the specified type, writing to bw. func encodeEmptyBlock(bw *bitio.Writer, typ meta.Type, last bool) error { // Store metadata block header. hdr := &meta.Header{ IsLast: last, Type: typ, Length: 0, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } return nil } // --- [ Metadata block header ] ----------------------------------------------- // encodeBlockHeader encodes the metadata block header, writing to bw. func encodeBlockHeader(bw *bitio.Writer, hdr *meta.Header) error { // 1 bit: IsLast. if err := bw.WriteBool(hdr.IsLast); err != nil { return errutil.Err(err) } // 7 bits: Type. if err := bw.WriteBits(uint64(hdr.Type), 7); err != nil { return errutil.Err(err) } // 24 bits: Length. if err := bw.WriteBits(uint64(hdr.Length), 24); err != nil { return errutil.Err(err) } return nil } // --- [ StreamInfo ] ---------------------------------------------------------- // encodeStreamInfo encodes the StreamInfo metadata block, writing to bw. func encodeStreamInfo(bw *bitio.Writer, info *meta.StreamInfo, last bool) error { // Store metadata block header. const nbits = 16 + 16 + 24 + 24 + 20 + 3 + 5 + 36 + 8*16 hdr := &meta.Header{ IsLast: last, Type: meta.TypeStreamInfo, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. // 16 bits: BlockSizeMin. if err := bw.WriteBits(uint64(info.BlockSizeMin), 16); err != nil { return errutil.Err(err) } // 16 bits: BlockSizeMax. if err := bw.WriteBits(uint64(info.BlockSizeMax), 16); err != nil { return errutil.Err(err) } // 24 bits: FrameSizeMin. if err := bw.WriteBits(uint64(info.FrameSizeMin), 24); err != nil { return errutil.Err(err) } // 24 bits: FrameSizeMax. if err := bw.WriteBits(uint64(info.FrameSizeMax), 24); err != nil { return errutil.Err(err) } // 20 bits: SampleRate. if err := bw.WriteBits(uint64(info.SampleRate), 20); err != nil { return errutil.Err(err) } // 3 bits: NChannels; stored as (number of channels) - 1. if err := bw.WriteBits(uint64(info.NChannels-1), 3); err != nil { return errutil.Err(err) } // 5 bits: BitsPerSample; stored as (bits-per-sample) - 1. if err := bw.WriteBits(uint64(info.BitsPerSample-1), 5); err != nil { return errutil.Err(err) } // 36 bits: NSamples. if err := bw.WriteBits(info.NSamples, 36); err != nil { return errutil.Err(err) } // 16 bytes: MD5sum. if _, err := bw.Write(info.MD5sum[:]); err != nil { return errutil.Err(err) } return nil } // --- [ Padding ] ---------------------------------------------------------- // encodePadding encodes the Padding metadata block, writing to bw. func encodePadding(bw *bitio.Writer, length int64, last bool) error { // Store metadata block header. hdr := &meta.Header{ IsLast: last, Type: meta.TypePadding, Length: length, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. if _, err := io.CopyN(bw, ioutilx.Zero, length); err != nil { return errutil.Err(err) } return nil } // --- [ Application ] --------------------------------------------------------- // encodeApplication encodes the Application metadata block, writing to bw. func encodeApplication(bw *bitio.Writer, app *meta.Application, last bool) error { // Store metadata block header. nbits := int64(32 + 8*len(app.Data)) hdr := &meta.Header{ IsLast: last, Type: meta.TypeApplication, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. // 32 bits: ID. if err := bw.WriteBits(uint64(app.ID), 32); err != nil { return errutil.Err(err) } // TODO: check if the Application block may contain only an ID. if _, err := bw.Write(app.Data); err != nil { return errutil.Err(err) } return nil } // --- [ SeekTable ] ----------------------------------------------------------- // encodeSeekTable encodes the SeekTable metadata block, writing to bw. func encodeSeekTable(bw *bitio.Writer, table *meta.SeekTable, last bool) error { // Store metadata block header. nbits := int64((64 + 64 + 16) * len(table.Points)) hdr := &meta.Header{ IsLast: last, Type: meta.TypeSeekTable, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. for _, point := range table.Points { if err := binary.Write(bw, binary.BigEndian, point); err != nil { return errutil.Err(err) } } return nil } // --- [ VorbisComment ] ------------------------------------------------------- // encodeVorbisComment encodes the VorbisComment metadata block, writing to bw. func encodeVorbisComment(bw *bitio.Writer, comment *meta.VorbisComment, last bool) error { // Store metadata block header. nbits := int64(32 + 8*len(comment.Vendor) + 32) for _, tag := range comment.Tags { nbits += int64(32 + 8*(len(tag[0])+1+len(tag[1]))) } hdr := &meta.Header{ IsLast: last, Type: meta.TypeVorbisComment, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. // 32 bits: vendor length. // TODO: verify that little-endian encoding is used; otherwise, switch to // using bw.WriteBits. if err := binary.Write(bw, binary.LittleEndian, uint32(len(comment.Vendor))); err != nil { return errutil.Err(err) } // (vendor length) bits: Vendor. if _, err := bw.Write([]byte(comment.Vendor)); err != nil { return errutil.Err(err) } // Store tags. // 32 bits: number of tags. if err := binary.Write(bw, binary.LittleEndian, uint32(len(comment.Tags))); err != nil { return errutil.Err(err) } for _, tag := range comment.Tags { // Store tag, which has the following format: // NAME=VALUE buf := []byte(fmt.Sprintf("%s=%s", tag[0], tag[1])) // 32 bits: vector length if err := binary.Write(bw, binary.LittleEndian, uint32(len(buf))); err != nil { return errutil.Err(err) } // (vector length): vector. if _, err := bw.Write(buf); err != nil { return errutil.Err(err) } } return nil } // --- [ CueSheet ] ------------------------------------------------------------ // encodeCueSheet encodes the CueSheet metadata block, writing to bw. func encodeCueSheet(bw *bitio.Writer, cs *meta.CueSheet, last bool) error { // Store metadata block header. nbits := int64(8*128 + 64 + 1 + 7 + 8*258 + 8) for _, track := range cs.Tracks { nbits += 64 + 8 + 8*12 + 1 + 1 + 6 + 8*13 + 8 for range track.Indicies { nbits += 64 + 8 + 8*3 } } hdr := &meta.Header{ IsLast: last, Type: meta.TypeCueSheet, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. // Store cue sheet. // 128 bytes: MCN. var mcn [128]byte copy(mcn[:], cs.MCN) if _, err := bw.Write(mcn[:]); err != nil { return errutil.Err(err) } // 64 bits: NLeadInSamples. if err := bw.WriteBits(cs.NLeadInSamples, 64); err != nil { return errutil.Err(err) } // 1 bit: IsCompactDisc. if err := bw.WriteBool(cs.IsCompactDisc); err != nil { return errutil.Err(err) } // 7 bits and 258 bytes: reserved. if err := bw.WriteBits(0, 7); err != nil { return errutil.Err(err) } if _, err := io.CopyN(bw, ioutilx.Zero, 258); err != nil { return errutil.Err(err) } // Store cue sheet tracks. // 8 bits: (number of tracks) if err := bw.WriteBits(uint64(len(cs.Tracks)), 8); err != nil { return errutil.Err(err) } for _, track := range cs.Tracks { // 64 bits: Offset. if err := bw.WriteBits(track.Offset, 64); err != nil { return errutil.Err(err) } // 8 bits: Num. if err := bw.WriteBits(uint64(track.Num), 8); err != nil { return errutil.Err(err) } // 12 bytes: ISRC. var isrc [12]byte copy(isrc[:], track.ISRC) if _, err := bw.Write(isrc[:]); err != nil { return errutil.Err(err) } // 1 bit: IsAudio. if err := bw.WriteBool(!track.IsAudio); err != nil { return errutil.Err(err) } // 1 bit: HasPreEmphasis. // mask = 01000000 if err := bw.WriteBool(track.HasPreEmphasis); err != nil { return errutil.Err(err) } // 6 bits and 13 bytes: reserved. // mask = 00111111 if err := bw.WriteBits(0, 6); err != nil { return errutil.Err(err) } if _, err := io.CopyN(bw, ioutilx.Zero, 13); err != nil { return errutil.Err(err) } // Store indicies. // 8 bits: (number of indicies) if err := bw.WriteBits(uint64(len(track.Indicies)), 8); err != nil { return errutil.Err(err) } for _, index := range track.Indicies { // 64 bits: Offset. if err := bw.WriteBits(index.Offset, 64); err != nil { return errutil.Err(err) } // 8 bits: Num. if err := bw.WriteBits(uint64(index.Num), 8); err != nil { return errutil.Err(err) } // 3 bytes: reserved. if _, err := io.CopyN(bw, ioutilx.Zero, 3); err != nil { return errutil.Err(err) } } } return nil } // --- [ Picture ] ------------------------------------------------------------- // encodePicture encodes the Picture metadata block, writing to bw. func encodePicture(bw *bitio.Writer, pic *meta.Picture, last bool) error { // Store metadata block header. nbits := int64(32 + 32 + 8*len(pic.MIME) + 32 + 8*len(pic.Desc) + 32 + 32 + 32 + 32 + 32 + 8*len(pic.Data)) hdr := &meta.Header{ IsLast: last, Type: meta.TypePicture, Length: nbits / 8, } if err := encodeBlockHeader(bw, hdr); err != nil { return errutil.Err(err) } // Store metadata block body. // 32 bits: Type. if err := bw.WriteBits(uint64(pic.Type), 32); err != nil { return errutil.Err(err) } // 32 bits: (MIME type length). if err := bw.WriteBits(uint64(len(pic.MIME)), 32); err != nil { return errutil.Err(err) } // (MIME type length) bytes: MIME. if _, err := bw.Write([]byte(pic.MIME)); err != nil { return errutil.Err(err) } // 32 bits: (description length). if err := bw.WriteBits(uint64(len(pic.Desc)), 32); err != nil { return errutil.Err(err) } // (description length) bytes: Desc. if _, err := bw.Write([]byte(pic.Desc)); err != nil { return errutil.Err(err) } // 32 bits: Width. if err := bw.WriteBits(uint64(pic.Width), 32); err != nil { return errutil.Err(err) } // 32 bits: Height. if err := bw.WriteBits(uint64(pic.Height), 32); err != nil { return errutil.Err(err) } // 32 bits: Depth. if err := bw.WriteBits(uint64(pic.Depth), 32); err != nil { return errutil.Err(err) } // 32 bits: NPalColors. if err := bw.WriteBits(uint64(pic.NPalColors), 32); err != nil { return errutil.Err(err) } // 32 bits: (data length). if err := bw.WriteBits(uint64(len(pic.Data)), 32); err != nil { return errutil.Err(err) } // (data length) bytes: Data. if _, err := bw.Write(pic.Data); err != nil { return errutil.Err(err) } return nil } ================================================ FILE: encode_subframe.go ================================================ package flac import ( "fmt" "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, bps uint) error { // Encode subframe header. if err := encodeSubframeHeader(bw, subframe.SubHeader); err != nil { return errutil.Err(err) } // Adjust bps of subframe for wasted bits-per-sample. bps -= subframe.Wasted // Right shift to account for wasted bits-per-sample. if subframe.Wasted > 0 { for i, sample := range subframe.Samples { subframe.Samples[i] = sample >> subframe.Wasted } // NOTE: use defer to restore original samples after encode. defer func() { for i, sample := range subframe.Samples { subframe.Samples[i] = sample << subframe.Wasted } }() } // Encode audio samples. switch subframe.Pred { case frame.PredConstant: if err := encodeConstantSamples(bw, hdr, subframe, bps); err != nil { return errutil.Err(err) } case frame.PredVerbatim: if err := encodeVerbatimSamples(bw, hdr, subframe, bps); err != nil { return errutil.Err(err) } case frame.PredFixed: if err := encodeFixedSamples(bw, hdr, subframe, bps); err != nil { return errutil.Err(err) } case frame.PredFIR: if err := encodeFIRSamples(bw, hdr, subframe, bps); 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, subHdr 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 subHdr.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(subHdr.Order) case frame.PredFIR: // 1xxxxx : SUBFRAME_LPC, xxxxx=order-1 bits = 0x20 | uint64(subHdr.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 := subHdr.Wasted > 0 if err := bw.WriteBool(hasWastedBits); err != nil { return errutil.Err(err) } if hasWastedBits { if err := iobits.WriteUnary(bw, uint64(subHdr.Wasted-1)); err != nil { return errutil.Err(err) } } return nil } // --- [ Constant samples ] ---------------------------------------------------- // encodeConstantSamples stores the given constant sample, writing to bw. func encodeConstantSamples(bw *bitio.Writer, hdr frame.Header, subframe *frame.Subframe, bps uint) error { samples := subframe.Samples 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), uint8(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, subframe *frame.Subframe, bps uint) error { // Unencoded subblock; n = frame's bits-per-sample, i = frame's blocksize. samples := subframe.Samples 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), uint8(bps)); err != nil { return errutil.Err(err) } } return nil } // --- [ Fixed samples ] ------------------------------------------------------- // encodeFixedSamples stores the given samples using linear prediction coding // with a fixed set of predefined polynomial coefficients, writing to bw. func encodeFixedSamples(bw *bitio.Writer, hdr frame.Header, subframe *frame.Subframe, bps uint) error { // Encode unencoded warm-up samples. samples := subframe.Samples for i := 0; i < subframe.Order; i++ { sample := samples[i] if err := bw.WriteBits(uint64(sample), uint8(bps)); err != nil { return errutil.Err(err) } } // Compute residuals (signal errors of the prediction) between audio // samples and LPC predicted audio samples. const shift = 0 residuals, err := getLPCResiduals(subframe, frame.FixedCoeffs[subframe.Order], shift) if err != nil { return errutil.Err(err) } // Encode subframe residuals. if err := encodeResiduals(bw, subframe, residuals); err != nil { return errutil.Err(err) } return nil } // --- [ FIR samples ] ------------------------------------------------------- // encodeFIRSamples stores the given samples using linear prediction coding // with a custom set of predefined polynomial coefficients, writing to bw. func encodeFIRSamples(bw *bitio.Writer, hdr frame.Header, subframe *frame.Subframe, bps uint) error { // Encode unencoded warm-up samples. samples := subframe.Samples for i := 0; i < subframe.Order; i++ { sample := samples[i] if err := bw.WriteBits(uint64(sample), uint8(bps)); err != nil { return errutil.Err(err) } } // 4 bits: (coefficients' precision in bits) - 1. if err := bw.WriteBits(uint64(subframe.CoeffPrec-1), 4); err != nil { return errutil.Err(err) } // 5 bits: predictor coefficient shift needed in bits. if err := bw.WriteBits(uint64(subframe.CoeffShift), 5); err != nil { return errutil.Err(err) } // Encode coefficients. for _, coeff := range subframe.Coeffs { // (prec) bits: Predictor coefficient. if err := bw.WriteBits(uint64(coeff), uint8(subframe.CoeffPrec)); err != nil { return errutil.Err(err) } } // Compute residuals (signal errors of the prediction) between audio // samples and LPC predicted audio samples. residuals, err := getLPCResiduals(subframe, subframe.Coeffs, subframe.CoeffShift) if err != nil { return errutil.Err(err) } // Encode subframe residuals. if err := encodeResiduals(bw, subframe, residuals); err != nil { return errutil.Err(err) } return nil } // encodeResiduals encodes the residuals (prediction method error signals) of the // subframe. // // ref: https://www.xiph.org/flac/format.html#residual func encodeResiduals(bw *bitio.Writer, subframe *frame.Subframe, residuals []int32) error { // 2 bits: Residual coding method. if err := bw.WriteBits(uint64(subframe.ResidualCodingMethod), 2); err != nil { return errutil.Err(err) } // The 2 bits are used to specify the residual coding method as follows: // 00: Rice coding with a 4-bit Rice parameter. // 01: Rice coding with a 5-bit Rice parameter. // 10: reserved. // 11: reserved. switch subframe.ResidualCodingMethod { case frame.ResidualCodingMethodRice1: return encodeRicePart(bw, subframe, 4, residuals) case frame.ResidualCodingMethodRice2: return encodeRicePart(bw, subframe, 5, residuals) default: return fmt.Errorf("encodeResiduals: reserved residual coding method bit pattern (%02b)", uint8(subframe.ResidualCodingMethod)) } } // encodeRicePart encodes a Rice partition of residuals from the subframe, using // a Rice parameter of the specified size in bits. // // ref: https://www.xiph.org/flac/format.html#partitioned_rice // ref: https://www.xiph.org/flac/format.html#partitioned_rice2 func encodeRicePart(bw *bitio.Writer, subframe *frame.Subframe, paramSize uint, residuals []int32) error { // 4 bits: Partition order. riceSubframe := subframe.RiceSubframe if err := bw.WriteBits(uint64(riceSubframe.PartOrder), 4); err != nil { return errutil.Err(err) } // Parse Rice partitions; in total 2^partOrder partitions. // // ref: https://www.xiph.org/flac/format.html#rice_partition // ref: https://www.xiph.org/flac/format.html#rice2_partition partOrder := riceSubframe.PartOrder nparts := 1 << partOrder curResidualIndex := 0 for i := range riceSubframe.Partitions { partition := &riceSubframe.Partitions[i] // (4 or 5) bits: Rice parameter. param := partition.Param if err := bw.WriteBits(uint64(param), uint8(paramSize)); err != nil { return errutil.Err(err) } // Determine the number of Rice encoded samples in the partition. var nsamples int if partOrder == 0 { nsamples = subframe.NSamples - subframe.Order } else if i != 0 { nsamples = subframe.NSamples / nparts } else { nsamples = subframe.NSamples/nparts - subframe.Order } if paramSize == 4 && param == 0xF || paramSize == 5 && param == 0x1F { // 1111 or 11111: Escape code, meaning the partition is in unencoded // binary form using n bits per sample; n follows as a 5-bit number. if err := bw.WriteBits(uint64(partition.EscapedBitsPerSample), 5); err != nil { return errutil.Err(err) } for j := 0; j < nsamples; j++ { // ref: https://datatracker.ietf.org/doc/draft-ietf-cellar-flac/ // // From section 9.2.7.1. Escaped partition: // // The residual samples themselves are stored signed two's // complement. For example, when a partition is escaped and each // residual sample is stored with 3 bits, the number -1 is // represented as 0b111. residual := residuals[curResidualIndex] curResidualIndex++ if err := bw.WriteBits(uint64(residual), uint8(partition.EscapedBitsPerSample)); err != nil { return errutil.Err(err) } } continue } // Encode the Rice residuals of the partition. for j := 0; j < nsamples; j++ { residual := residuals[curResidualIndex] curResidualIndex++ if err := encodeRiceResidual(bw, param, residual); err != nil { return errutil.Err(err) } } } return nil } // encodeRiceResidual encodes a Rice residual (error signal). func encodeRiceResidual(bw *bitio.Writer, k uint, residual int32) error { // ZigZag encode. folded := iobits.EncodeZigZag(residual) // unfold into low- and high. lowMask := ^uint32(0) >> (32 - k) // lower k bits. highMask := ^uint32(0) << k // upper bits. high := (folded & highMask) >> k low := folded & lowMask // Write unary encoded most significant bits. if err := iobits.WriteUnary(bw, uint64(high)); err != nil { return errutil.Err(err) } // Write binary encoded least significant bits. if err := bw.WriteBits(uint64(low), uint8(k)); err != nil { return errutil.Err(err) } return nil } // getLPCResiduals returns the residuals (signal errors of the prediction) // between the given audio samples and the LPC predicted audio samples, using // the coefficients of a given polynomial, and a couple (order of polynomial; // i.e. len(coeffs)) of unencoded warm-up samples. func getLPCResiduals(subframe *frame.Subframe, coeffs []int32, shift int32) ([]int32, error) { if len(coeffs) != subframe.Order { return nil, fmt.Errorf("getLPCResiduals: prediction order (%d) differs from number of coefficients (%d)", subframe.Order, len(coeffs)) } if shift < 0 { return nil, fmt.Errorf("getLPCResiduals: invalid negative shift") } if subframe.NSamples != len(subframe.Samples) { return nil, fmt.Errorf("getLPCResiduals: subframe sample count mismatch; expected %d, got %d", subframe.NSamples, len(subframe.Samples)) } var residuals []int32 for i := subframe.Order; i < subframe.NSamples; i++ { var sample int64 for j, c := range coeffs { sample += int64(c) * int64(subframe.Samples[i-j-1]) } residual := subframe.Samples[i] - int32(sample>>uint(shift)) residuals = append(residuals, residual) } return residuals, nil } ================================================ FILE: example_test.go ================================================ package flac_test import ( "bytes" "crypto/md5" "fmt" "io" "log" "github.com/mewkiz/flac" ) func ExampleParseFile() { // Parse metadata of love.flac stream, err := flac.ParseFile("testdata/love.flac") if err != nil { log.Fatal(err) } defer stream.Close() fmt.Printf("unencoded audio md5sum: %032x\n", stream.Info.MD5sum[:]) for i, block := range stream.Blocks { fmt.Printf("block %d: %v\n", i, block.Type) } // Output: // unencoded audio md5sum: bdf6f7d31f77cb696a02b2192d192a89 // block 0: seek table // block 1: vorbis comment // block 2: padding } func ExampleOpen() { // Open love.flac for audio streaming without parsing metadata. stream, err := flac.Open("testdata/love.flac") if err != nil { log.Fatal(err) } defer stream.Close() // Parse audio samples and verify the MD5 signature of the decoded audio // samples. md5sum := md5.New() for { // Parse one frame of audio samples at the time, each frame containing one // subframe per audio channel. frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } log.Fatal(err) } frame.Hash(md5sum) // Print first three samples from each channel of the first five frames. if frame.Num < 5 { fmt.Printf("frame %d\n", frame.Num) for i, subframe := range frame.Subframes { fmt.Printf(" subframe %d\n", i) for j, sample := range subframe.Samples { if j >= 3 { break } fmt.Printf(" sample %d: %v\n", j, sample) } } } } fmt.Println() got, want := md5sum.Sum(nil), stream.Info.MD5sum[:] fmt.Println("decoded audio md5sum valid:", bytes.Equal(got, want)) // Output: // frame 0 // subframe 0 // sample 0: 126 // sample 1: 126 // sample 2: 126 // subframe 1 // sample 0: 126 // sample 1: 126 // sample 2: 126 // frame 1 // subframe 0 // sample 0: 126 // sample 1: 126 // sample 2: 126 // subframe 1 // sample 0: 126 // sample 1: 126 // sample 2: 126 // frame 2 // subframe 0 // sample 0: 121 // sample 1: 130 // sample 2: 137 // subframe 1 // sample 0: 121 // sample 1: 130 // sample 2: 137 // frame 3 // subframe 0 // sample 0: -9501 // sample 1: -6912 // sample 2: -3916 // subframe 1 // sample 0: -9501 // sample 1: -6912 // sample 2: -3916 // frame 4 // subframe 0 // sample 0: 513 // sample 1: 206 // sample 2: 152 // subframe 1 // sample 0: 513 // sample 1: 206 // sample 2: 152 // // decoded audio md5sum valid: true } ================================================ FILE: flac.go ================================================ // TODO(u): Evaluate storing the samples (and residuals) during frame audio // decoding in a buffer allocated for the stream. This buffer would be allocated // using BlockSize and NChannels from the StreamInfo block, and it could be // reused in between calls to Next and ParseNext. This should reduce GC // pressure. // TODO: Remove note about encoder API. // Package flac provides access to FLAC (Free Lossless Audio Codec) streams. // // A brief introduction of the FLAC stream format [1] follows. Each FLAC stream // starts with a 32-bit signature ("fLaC"), followed by one or more metadata // blocks, and then one or more audio frames. The first metadata block // (StreamInfo) describes the basic properties of the audio stream and it is the // only mandatory metadata block. Subsequent metadata blocks may appear in an // arbitrary order. // // Please refer to the documentation of the meta [2] and the frame [3] packages // for a brief introduction of their respective formats. // // [1]: https://www.xiph.org/flac/format.html#stream // [2]: https://godoc.org/github.com/mewkiz/flac/meta // [3]: https://godoc.org/github.com/mewkiz/flac/frame // // Note: the Encoder API is experimental until the 1.1.x release. As such, it's // API is expected to change. package flac import ( "bufio" "bytes" "errors" "fmt" "io" "os" "github.com/mewkiz/flac/frame" "github.com/mewkiz/flac/internal/bufseekio" "github.com/mewkiz/flac/meta" ) // A Stream contains the metadata blocks and provides access to the audio frames // of a FLAC stream. // // ref: https://www.xiph.org/flac/format.html#stream type Stream struct { // The StreamInfo metadata block describes the basic properties of the FLAC // audio stream. Info *meta.StreamInfo // Zero or more metadata blocks. Blocks []*meta.Block // seekTable contains one or more pre-calculated audio frame seek points of // the stream; nil if uninitialized. seekTable *meta.SeekTable // seekTableSize determines how many seek points the seekTable should have if // the flac file does not include one in the metadata. seekTableSize int // dataStart is the offset of the first frame header since SeekPoint.Offset // is relative to this position. dataStart int64 // Underlying io.Reader, or io.ReadCloser. r io.Reader } // New creates a new Stream for accessing the audio samples of r. It reads and // parses the FLAC signature and the StreamInfo metadata block, but skips all // other metadata blocks. // // Call Stream.Next to parse the frame header of the next audio frame, and call // Stream.ParseNext to parse the entire next frame including audio samples. func New(r io.Reader) (stream *Stream, err error) { // Verify FLAC signature and parse the StreamInfo metadata block. br := bufio.NewReader(r) stream = &Stream{r: br} block, err := stream.parseStreamInfo() if err != nil { return nil, err } // Skip the remaining metadata blocks. for !block.IsLast { block, err = meta.New(br) if err != nil && err != meta.ErrReservedType { return stream, err } if err = block.Skip(); err != nil { return stream, err } } return stream, nil } // NewSeek returns a Stream that has seeking enabled. The incoming io.ReadSeeker // will not be buffered, which might result in performance issues. Using an // in-memory buffer like *bytes.Reader should work well. func NewSeek(rs io.ReadSeeker) (stream *Stream, err error) { br := bufseekio.NewReadSeeker(rs) stream = &Stream{r: br, seekTableSize: defaultSeekTableSize} // Verify FLAC signature and parse the StreamInfo metadata block. block, err := stream.parseStreamInfo() if err != nil { return stream, err } for !block.IsLast { block, err = meta.Parse(stream.r) if err != nil { if err != meta.ErrReservedType { return stream, err } if err = block.Skip(); err != nil { return stream, err } } if block.Header.Type == meta.TypeSeekTable { stream.seekTable = block.Body.(*meta.SeekTable) } } // Record file offset of the first frame header. stream.dataStart, err = br.Seek(0, io.SeekCurrent) return stream, err } var ( // flacSignature marks the beginning of a FLAC stream. flacSignature = []byte("fLaC") // id3Signature marks the beginning of an ID3 stream, used to skip over ID3 // data. id3Signature = []byte("ID3") // ErrNoSeeker reports that flac.NewSeek was called with an io.Reader not // implementing io.Seeker, and thus does not allow for seeking. ErrNoSeeker = errors.New("stream.Seek: reader does not implement io.Seeker") // ErrNoSeektable reports that no seektable has been generated. Therefore, // it is not possible to seek in the stream. ErrNoSeektable = errors.New("stream.searchFromStart: no seektable exists") ) const ( defaultSeekTableSize = 100 ) // parseStreamInfo verifies the signature which marks the beginning of a FLAC // stream, and parses the StreamInfo metadata block. It returns a boolean value // which specifies if the StreamInfo block was the last metadata block of the // FLAC stream. func (stream *Stream) parseStreamInfo() (block *meta.Block, err error) { // Verify FLAC signature. r := stream.r var buf [4]byte if _, err = io.ReadFull(r, buf[:]); err != nil { return block, err } // Skip prepended ID3v2 data. if bytes.Equal(buf[:3], id3Signature) { if err := stream.skipID3v2(); err != nil { return block, err } // Second attempt at verifying signature. if _, err = io.ReadFull(r, buf[:]); err != nil { return block, err } } if !bytes.Equal(buf[:], flacSignature) { return block, fmt.Errorf("flac.parseStreamInfo: invalid FLAC signature; expected %q, got %q", flacSignature, buf) } // Parse StreamInfo metadata block. block, err = meta.Parse(r) if err != nil { return block, err } si, ok := block.Body.(*meta.StreamInfo) if !ok { return block, fmt.Errorf("flac.parseStreamInfo: incorrect type of first metadata block; expected *meta.StreamInfo, got %T", block.Body) } stream.Info = si return block, nil } // skipID3v2 skips ID3v2 data prepended to flac files. func (stream *Stream) skipID3v2() error { r := bufio.NewReader(stream.r) // Discard unnecessary data from the ID3v2 header. if _, err := r.Discard(2); err != nil { return err } // Read the size from the ID3v2 header. var sizeBuf [4]byte if _, err := r.Read(sizeBuf[:]); err != nil { return err } // The size is encoded as a synchsafe integer. size := int(sizeBuf[0])<<21 | int(sizeBuf[1])<<14 | int(sizeBuf[2])<<7 | int(sizeBuf[3]) _, err := r.Discard(size) return err } // Parse creates a new Stream for accessing the metadata blocks and audio // samples of r. It reads and parses the FLAC signature and all metadata blocks. // // Call Stream.Next to parse the frame header of the next audio frame, and call // Stream.ParseNext to parse the entire next frame including audio samples. func Parse(r io.Reader) (stream *Stream, err error) { // Verify FLAC signature and parse the StreamInfo metadata block. br := bufio.NewReader(r) stream = &Stream{r: br} block, err := stream.parseStreamInfo() if err != nil { return nil, err } // Parse the remaining metadata blocks. for !block.IsLast { block, err = meta.Parse(br) if err != nil { if err != meta.ErrReservedType { return stream, err } // Skip the body of unknown (reserved) metadata blocks, as stated by // the specification. // // ref: https://www.xiph.org/flac/format.html#format_overview if err = block.Skip(); err != nil { return stream, err } } stream.Blocks = append(stream.Blocks, block) } return stream, nil } // Open creates a new Stream for accessing the audio samples of path. It reads // and parses the FLAC signature and the StreamInfo metadata block, but skips // all other metadata blocks. // // Call Stream.Next to parse the frame header of the next audio frame, and call // Stream.ParseNext to parse the entire next frame including audio samples. // // Note: The Close method of the stream must be called when finished using it. func Open(path string) (stream *Stream, err error) { f, err := os.Open(path) if err != nil { return nil, err } stream, err = New(f) if err != nil { return nil, err } return stream, err } // ParseFile creates a new Stream for accessing the metadata blocks and audio // samples of path. It reads and parses the FLAC signature and all metadata // blocks. // // Call Stream.Next to parse the frame header of the next audio frame, and call // Stream.ParseNext to parse the entire next frame including audio samples. // // Note: The Close method of the stream must be called when finished using it. func ParseFile(path string) (stream *Stream, err error) { f, err := os.Open(path) if err != nil { return nil, err } stream, err = Parse(f) if err != nil { return nil, err } return stream, err } // Close closes the stream gracefully if the underlying io.Reader also implements the io.Closer interface. func (stream *Stream) Close() error { if closer, ok := stream.r.(io.Closer); ok { return closer.Close() } return nil } // Next parses the frame header of the next audio frame. It returns io.EOF to // signal a graceful end of FLAC stream. // // Call Frame.Parse to parse the audio samples of its subframes. func (stream *Stream) Next() (f *frame.Frame, err error) { return frame.New(stream.r) } // ParseNext parses the entire next frame including audio samples. It returns // io.EOF to signal a graceful end of FLAC stream. func (stream *Stream) ParseNext() (f *frame.Frame, err error) { return frame.Parse(stream.r) } // Seek seeks to the frame containing the given absolute sample number. The // return value specifies the first sample number of the frame containing // sampleNum. func (stream *Stream) Seek(sampleNum uint64) (uint64, error) { if stream.seekTable == nil && stream.seekTableSize > 0 { if err := stream.makeSeekTable(); err != nil { return 0, err } } rs := stream.r.(io.ReadSeeker) isBiggerThanStream := stream.Info.NSamples != 0 && sampleNum >= stream.Info.NSamples if isBiggerThanStream || sampleNum < 0 { return 0, fmt.Errorf("unable to seek to sample number %d", sampleNum) } point, err := stream.searchFromStart(sampleNum) if err != nil { return 0, err } if _, err := rs.Seek(stream.dataStart+int64(point.Offset), io.SeekStart); err != nil { return 0, err } for { // Record seek offset to start of frame. offset, err := rs.Seek(0, io.SeekCurrent) if err != nil { return 0, err } frame, err := stream.ParseNext() if err != nil { return 0, err } if frame.SampleNumber()+uint64(frame.BlockSize) > sampleNum { // Restore seek offset to the start of the frame containing the // specified sample number. _, err := rs.Seek(offset, io.SeekStart) return frame.SampleNumber(), err } } } // TODO(_): Utilize binary search in searchFromStart. // searchFromStart searches for the given sample number from the start of the // seek table and returns the last seek point containing the sample number. If // no seek point contains the sample number, the last seek point preceding the // sample number is returned. If the sample number is lower than the first seek // point, the first seek point is returned. func (stream *Stream) searchFromStart(sampleNum uint64) (meta.SeekPoint, error) { if len(stream.seekTable.Points) == 0 { return meta.SeekPoint{}, ErrNoSeektable } prev := stream.seekTable.Points[0] for _, p := range stream.seekTable.Points { if p.SampleNum+uint64(p.NSamples) >= sampleNum { return prev, nil } prev = p } return prev, nil } // makeSeekTable creates a seek table with seek points to each frame of the FLAC // stream. func (stream *Stream) makeSeekTable() (err error) { rs, ok := stream.r.(io.ReadSeeker) if !ok { return ErrNoSeeker } pos, err := rs.Seek(0, io.SeekCurrent) if err != nil { return err } _, err = rs.Seek(stream.dataStart, io.SeekStart) if err != nil { return err } var i int var sampleNum uint64 var points []meta.SeekPoint for { // Record seek offset to start of frame. off, err := rs.Seek(0, io.SeekCurrent) if err != nil { return err } f, err := stream.ParseNext() if err != nil { if err == io.EOF { break } return err } points = append(points, meta.SeekPoint{ SampleNum: sampleNum, Offset: uint64(off - stream.dataStart), NSamples: f.BlockSize, }) sampleNum += uint64(f.BlockSize) i++ } stream.seekTable = &meta.SeekTable{Points: points} _, err = rs.Seek(pos, io.SeekStart) return err } ================================================ FILE: flac_test.go ================================================ package flac_test import ( "fmt" "io" "os" "testing" "github.com/mewkiz/flac" ) func TestSkipID3v2(t *testing.T) { if _, err := flac.ParseFile("testdata/id3.flac"); err != nil { t.Fatal(err) } } func TestSeek(t *testing.T) { f, err := os.Open("testdata/172960.flac") if err != nil { t.Fatal(err) } defer f.Close() //Seek Table: // {SampleNum:0 Offset:8283 NSamples:4096} // {SampleNum:4096 Offset:17777 NSamples:4096} // {SampleNum:8192 Offset:27141 NSamples:4096} // {SampleNum:12288 Offset:36665 NSamples:4096} // {SampleNum:16384 Offset:46179 NSamples:4096} // {SampleNum:20480 Offset:55341 NSamples:4096} // {SampleNum:24576 Offset:64690 NSamples:4096} // {SampleNum:28672 Offset:74269 NSamples:4096} // {SampleNum:32768 Offset:81984 NSamples:4096} // {SampleNum:36864 Offset:86656 NSamples:4096} // {SampleNum:40960 Offset:89596 NSamples:2723} testPos := []struct { seek uint64 expected uint64 err string }{ {seek: 0, expected: 0}, {seek: 9000, expected: 8192}, {seek: 0, expected: 0}, {seek: 8000, expected: 4096}, {seek: 0, expected: 0}, {seek: 50000, expected: 0, err: "unable to seek to sample number 50000"}, {seek: 100, expected: 0}, {seek: 8192, expected: 8192}, {seek: 8191, expected: 4096}, //{seek: 40960 + 2723 - 1, expected: 40960}, // last sample // TODO: re-enable when it works. See https://github.com/mewkiz/flac/pull/73 {seek: 40960 + 2723, expected: 0, err: "unable to seek to sample number 43683"}, // one after last sample } stream, err := flac.NewSeek(f) if err != nil { t.Fatal(err) } for i, pos := range testPos { t.Run(fmt.Sprintf("%02d", i), func(t *testing.T) { p, err := stream.Seek(pos.seek) if err != nil { if err.Error() != pos.err { t.Fatal(err) } } if p != pos.expected { t.Fatalf("pos %d does not equal %d", p, pos.expected) } _, err = stream.ParseNext() if err != nil && err != io.EOF { t.Fatal(err) } }) } } func TestDecode(t *testing.T) { paths := []string{ "meta/testdata/input-SCPAP.flac", "meta/testdata/input-SCVA.flac", "meta/testdata/input-SCVPAP.flac", "meta/testdata/input-VA.flac", "meta/testdata/silence.flac", "testdata/19875.flac", "testdata/44127.flac", "testdata/59996.flac", "testdata/80574.flac", "testdata/172960.flac", "testdata/189983.flac", "testdata/191885.flac", "testdata/212768.flac", "testdata/220014.flac", "testdata/243749.flac", "testdata/256529.flac", "testdata/257344.flac", "testdata/8297-275156-0011.flac", "testdata/love.flac", // IETF test cases. // // ref: https://github.com/ietf-wg-cellar/flac-test-files/tree/main/subset "testdata/flac-test-files/subset/01 - blocksize 4096.flac", "testdata/flac-test-files/subset/02 - blocksize 4608.flac", "testdata/flac-test-files/subset/03 - blocksize 16.flac", "testdata/flac-test-files/subset/04 - blocksize 192.flac", "testdata/flac-test-files/subset/05 - blocksize 254.flac", "testdata/flac-test-files/subset/06 - blocksize 512.flac", "testdata/flac-test-files/subset/07 - blocksize 725.flac", "testdata/flac-test-files/subset/08 - blocksize 1000.flac", "testdata/flac-test-files/subset/09 - blocksize 1937.flac", "testdata/flac-test-files/subset/10 - blocksize 2304.flac", "testdata/flac-test-files/subset/11 - partition order 8.flac", "testdata/flac-test-files/subset/12 - qlp precision 15 bit.flac", "testdata/flac-test-files/subset/13 - qlp precision 2 bit.flac", "testdata/flac-test-files/subset/14 - wasted bits.flac", "testdata/flac-test-files/subset/15 - only verbatim subframes.flac", "testdata/flac-test-files/subset/16 - partition order 8 containing escaped partitions.flac", "testdata/flac-test-files/subset/17 - all fixed orders.flac", "testdata/flac-test-files/subset/18 - precision search.flac", "testdata/flac-test-files/subset/19 - samplerate 35467Hz.flac", "testdata/flac-test-files/subset/20 - samplerate 39kHz.flac", "testdata/flac-test-files/subset/21 - samplerate 22050Hz.flac", "testdata/flac-test-files/subset/22 - 12 bit per sample.flac", "testdata/flac-test-files/subset/23 - 8 bit per sample.flac", "testdata/flac-test-files/subset/24 - variable blocksize file created with flake revision 264.flac", "testdata/flac-test-files/subset/25 - variable blocksize file created with flake revision 264, modified to create smaller blocks.flac", "testdata/flac-test-files/subset/26 - variable blocksize file created with CUETools.Flake 2.1.6.flac", "testdata/flac-test-files/subset/27 - old format variable blocksize file created with Flake 0.11.flac", "testdata/flac-test-files/subset/28 - high resolution audio, default settings.flac", "testdata/flac-test-files/subset/29 - high resolution audio, blocksize 16384.flac", "testdata/flac-test-files/subset/30 - high resolution audio, blocksize 13456.flac", "testdata/flac-test-files/subset/31 - high resolution audio, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/32 - high resolution audio, partition order 8 containing escaped partitions.flac", "testdata/flac-test-files/subset/33 - samplerate 192kHz.flac", "testdata/flac-test-files/subset/34 - samplerate 192kHz, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/35 - samplerate 134560Hz.flac", "testdata/flac-test-files/subset/36 - samplerate 384kHz.flac", "testdata/flac-test-files/subset/37 - 20 bit per sample.flac", "testdata/flac-test-files/subset/38 - 3 channels (3.0).flac", "testdata/flac-test-files/subset/39 - 4 channels (4.0).flac", "testdata/flac-test-files/subset/40 - 5 channels (5.0).flac", "testdata/flac-test-files/subset/41 - 6 channels (5.1).flac", "testdata/flac-test-files/subset/42 - 7 channels (6.1).flac", "testdata/flac-test-files/subset/43 - 8 channels (7.1).flac", "testdata/flac-test-files/subset/44 - 8-channel surround, 192kHz, 24 bit, using only 32nd order predictors.flac", "testdata/flac-test-files/subset/45 - no total number of samples set.flac", "testdata/flac-test-files/subset/46 - no min-max framesize set.flac", "testdata/flac-test-files/subset/47 - only STREAMINFO.flac", "testdata/flac-test-files/subset/48 - Extremely large SEEKTABLE.flac", "testdata/flac-test-files/subset/49 - Extremely large PADDING.flac", "testdata/flac-test-files/subset/50 - Extremely large PICTURE.flac", "testdata/flac-test-files/subset/51 - Extremely large VORBISCOMMENT.flac", "testdata/flac-test-files/subset/52 - Extremely large APPLICATION.flac", "testdata/flac-test-files/subset/53 - CUESHEET with very many indexes.flac", "testdata/flac-test-files/subset/54 - 1000x repeating VORBISCOMMENT.flac", "testdata/flac-test-files/subset/55 - file 48-53 combined.flac", "testdata/flac-test-files/subset/56 - JPG PICTURE.flac", "testdata/flac-test-files/subset/57 - PNG PICTURE.flac", "testdata/flac-test-files/subset/58 - GIF PICTURE.flac", "testdata/flac-test-files/subset/59 - AVIF PICTURE.flac", "testdata/flac-test-files/subset/60 - mono audio.flac", "testdata/flac-test-files/subset/61 - predictor overflow check, 16-bit.flac", "testdata/flac-test-files/subset/62 - predictor overflow check, 20-bit.flac", "testdata/flac-test-files/subset/63 - predictor overflow check, 24-bit.flac", "testdata/flac-test-files/subset/64 - rice partitions with escape code zero.flac", } funcs := map[string]func(io.Reader) (*flac.Stream, error){ "new": flac.New, "newSeek": func(r io.Reader) (*flac.Stream, error) { return flac.NewSeek(r.(io.ReadSeeker)) }, "parse": flac.Parse, } for _, path := range paths { for k, f := range funcs { t.Run(fmt.Sprintf("%s/%s", k, path), func(t *testing.T) { file, err := os.Open(path) if err != nil { t.Fatal(err) } stream, err := f(file) if err != nil { t.Fatal(err) } _, err = stream.ParseNext() if err != nil { t.Fatal(err) } file.Close() }) } } } ================================================ FILE: frame/frame.go ================================================ // Package frame implements access to FLAC audio frames. // // A brief introduction of the FLAC audio format [1] follows. FLAC encoders // divide the audio stream into blocks through a process called blocking [2]. A // block contains the unencoded audio samples from all channels during a short // period of time. Each audio block is divided into subblocks, one per channel. // // There is often a correlation between the left and right channel of stereo // audio. Using inter-channel decorrelation [3] it is possible to store only one // of the channels and the difference between the channels, or store the average // of the channels and their difference. An encoder decorrelates audio samples // as follows: // // mid = (left + right)/2 // average of the channels // side = left - right // difference between the channels // // The blocks are encoded using a variety of prediction methods [4][5] and // stored in frames. Blocks and subblocks contains unencoded audio samples while // frames and subframes contain encoded audio samples. A FLAC stream contains // one or more audio frames. // // [1]: https://www.xiph.org/flac/format.html#architecture // [2]: https://www.xiph.org/flac/format.html#blocking // [3]: https://www.xiph.org/flac/format.html#interchannel // [4]: https://www.xiph.org/flac/format.html#prediction // [5]: https://godoc.org/github.com/mewkiz/flac/frame#Pred package frame import ( "encoding/binary" "errors" "fmt" "hash" "io" "log" "github.com/mewkiz/flac/internal/bits" "github.com/mewkiz/flac/internal/hashutil" "github.com/mewkiz/flac/internal/hashutil/crc16" "github.com/mewkiz/flac/internal/hashutil/crc8" "github.com/mewkiz/flac/internal/utf8" ) // A Frame contains the header and subframes of an audio frame. It holds the // encoded samples from a block (a part) of the audio stream. Each subframe // holding the samples from one of its channel. // // ref: https://www.xiph.org/flac/format.html#frame type Frame struct { // Audio frame header. Header // One subframe per channel, containing encoded audio samples. Subframes []*Subframe // CRC-16 hash sum, calculated by read operations on hr. crc hashutil.Hash16 // A bit reader, wrapping read operations to hr. br *bits.Reader // A CRC-16 hash reader, wrapping read operations to r. hr io.Reader // Underlying io.Reader. r io.Reader } // New creates a new Frame for accessing the audio samples of r. It reads and // parses an audio frame header. It returns io.EOF to signal a graceful end of // FLAC stream. // // Call Frame.Parse to parse the audio samples of its subframes. func New(r io.Reader) (frame *Frame, err error) { // Create a new CRC-16 hash reader which adds the data from all read // operations to a running hash. crc := crc16.NewIBM() hr := io.TeeReader(r, crc) // Parse frame header. frame = &Frame{crc: crc, hr: hr, r: r} err = frame.parseHeader() return frame, err } // Parse reads and parses the header, and the audio samples from each subframe // of a frame. If the samples are inter-channel decorrelated between the // subframes, it correlates them. It returns io.EOF to signal a graceful end of // FLAC stream. // // ref: https://www.xiph.org/flac/format.html#interchannel func Parse(r io.Reader) (frame *Frame, err error) { // Parse frame header. frame, err = New(r) if err != nil { return frame, err } // Parse subframes. err = frame.Parse() return frame, err } // Parse reads and parses the audio samples from each subframe of the frame. If // the samples are inter-channel decorrelated between the subframes, it // correlates them. // // ref: https://www.xiph.org/flac/format.html#interchannel func (frame *Frame) Parse() error { // Parse subframes. frame.Subframes = make([]*Subframe, frame.Channels.Count()) var err error for channel := range frame.Subframes { // The side channel requires an extra bit per sample when using // inter-channel decorrelation. bps := uint(frame.BitsPerSample) switch frame.Channels { case ChannelsSideRight: // channel 0 is the side channel. if channel == 0 { bps++ } case ChannelsLeftSide, ChannelsMidSide: // channel 1 is the side channel. if channel == 1 { bps++ } } // Parse subframe. frame.Subframes[channel], err = frame.parseSubframe(frame.br, bps) if err != nil { return err } } // Inter-channel correlation of subframe samples. frame.Correlate() // 2 bytes: CRC-16 checksum. var want uint16 if err = binary.Read(frame.r, binary.BigEndian, &want); err != nil { return unexpected(err) } got := frame.crc.Sum16() if got != want { return fmt.Errorf("frame.Frame.Parse: CRC-16 checksum mismatch; expected 0x%04X, got 0x%04X", want, got) } return nil } // Hash adds the decoded audio samples of the frame to a running MD5 hash. It // can be used in conjunction with StreamInfo.MD5sum to verify the integrity of // the decoded audio samples. // // Note: The audio samples of the frame must be decoded before calling Hash. func (frame *Frame) Hash(md5sum hash.Hash) { // Write decoded samples to a running MD5 hash. bps := frame.BitsPerSample var buf [3]byte if len(frame.Subframes) == 0 { return } // Use the length of the first subframe's samples as they should all be the same length nsamples := len(frame.Subframes[0].Samples) for i := 0; i < nsamples; i++ { for _, subframe := range frame.Subframes { sample := subframe.Samples[i] switch { case 1 <= bps && bps <= 8: buf[0] = uint8(sample) md5sum.Write(buf[:1]) case 9 <= bps && bps <= 16: buf[0] = uint8(sample) buf[1] = uint8(sample >> 8) md5sum.Write(buf[:2]) case 17 <= bps && bps <= 24: buf[0] = uint8(sample) buf[1] = uint8(sample >> 8) buf[2] = uint8(sample >> 16) md5sum.Write(buf[:]) default: log.Printf("frame.Frame.Hash: support for %d-bit sample size not yet implemented", bps) } } } } // A Header contains the basic properties of an audio frame, such as its sample // rate and channel count. To facilitate random access decoding each frame // header starts with a sync-code. This allows the decoder to synchronize and // locate the start of a frame header. // // ref: https://www.xiph.org/flac/format.html#frame_header type Header struct { // Specifies if the block size is fixed or variable. HasFixedBlockSize bool // Block size in inter-channel samples, i.e. the number of audio samples in // each subframe. BlockSize uint16 // Sample rate in Hz; a 0 value implies unknown, get sample rate from // StreamInfo. SampleRate uint32 // Specifies the number of channels (subframes) that exist in the frame, // their order and possible inter-channel decorrelation. Channels Channels // Sample size in bits-per-sample; a 0 value implies unknown, get sample size // from StreamInfo. BitsPerSample uint8 // Specifies the frame number if the block size is fixed, and the first // sample number in the frame otherwise. When using fixed block size, the // first sample number in the frame can be derived by multiplying the frame // number with the block size (in samples). Num uint64 } // Errors returned by Frame.parseHeader. var ( ErrInvalidSync = errors.New("frame.Frame.parseHeader: invalid sync-code") ) // parseHeader reads and parses the header of an audio frame. func (frame *Frame) parseHeader() error { // Create a new CRC-8 hash reader which adds the data from all read // operations to a running hash. h := crc8.NewATM() hr := io.TeeReader(frame.hr, h) // Create bit reader. br := bits.NewReader(hr) frame.br = br // 14 bits: sync-code (11111111111110) x, err := br.Read(14) if err != nil { // This is the only place an audio frame may return io.EOF, which signals // a graceful end of a FLAC stream. return err } if x != 0x3FFE { return ErrInvalidSync } // 1 bit: reserved. x, err = br.Read(1) if err != nil { return unexpected(err) } if x != 0 { return errors.New("frame.Frame.parseHeader: non-zero reserved value") } // 1 bit: HasFixedBlockSize. x, err = br.Read(1) if err != nil { return unexpected(err) } if x == 0 { frame.HasFixedBlockSize = true } // 4 bits: BlockSize. The block size parsing is simplified by deferring it to // the end of the header. blockSize, err := br.Read(4) if err != nil { return unexpected(err) } // 4 bits: SampleRate. The sample rate parsing is simplified by deferring it // to the end of the header. sampleRate, err := br.Read(4) if err != nil { return unexpected(err) } // Parse channels. if err := frame.parseChannels(br); err != nil { return err } // Parse bits per sample. if err := frame.parseBitsPerSample(br); err != nil { return err } // 1 bit: reserved. x, err = br.Read(1) if err != nil { return unexpected(err) } if x != 0 { return errors.New("frame.Frame.parseHeader: non-zero reserved value") } // if (fixed block size) // 1-6 bytes: UTF-8 encoded frame number. // else // 1-7 bytes: UTF-8 encoded sample number. frame.Num, err = utf8.Decode(hr) if err != nil { return unexpected(err) } // Parse block size. if err := frame.parseBlockSize(br, blockSize); err != nil { return err } // Parse sample rate. if err := frame.parseSampleRate(br, sampleRate); err != nil { return err } // 1 byte: CRC-8 checksum. var want uint8 if err = binary.Read(frame.hr, binary.BigEndian, &want); err != nil { return unexpected(err) } got := h.Sum8() if want != got { return fmt.Errorf("frame.Frame.parseHeader: CRC-8 checksum mismatch; expected 0x%02X, got 0x%02X", want, got) } return nil } // parseBitsPerSample parses the bits per sample of the header. func (frame *Frame) parseBitsPerSample(br *bits.Reader) error { // 3 bits: BitsPerSample. x, err := br.Read(3) if err != nil { return unexpected(err) } // The 3 bits are used to specify the sample size as follows: // 000: unknown sample size; get from StreamInfo. // 001: 8 bits-per-sample. // 010: 12 bits-per-sample. // 011: reserved. // 100: 16 bits-per-sample. // 101: 20 bits-per-sample. // 110: 24 bits-per-sample. // 111: reserved. switch x { case 0x0: // 000: unknown bits-per-sample; get from StreamInfo. case 0x1: // 001: 8 bits-per-sample. frame.BitsPerSample = 8 case 0x2: // 010: 12 bits-per-sample. frame.BitsPerSample = 12 case 0x4: // 100: 16 bits-per-sample. frame.BitsPerSample = 16 case 0x5: // 101: 20 bits-per-sample. frame.BitsPerSample = 20 case 0x6: // 110: 24 bits-per-sample. frame.BitsPerSample = 24 default: // 011: reserved. // 111: reserved. return fmt.Errorf("frame.Frame.parseHeader: reserved sample size bit pattern (%03b)", x) } return nil } // parseChannels parses the channels of the header. func (frame *Frame) parseChannels(br *bits.Reader) error { // 4 bits: Channels. // // The 4 bits are used to specify the channels as follows: // 0000: (1 channel) mono. // 0001: (2 channels) left, right. // 0010: (3 channels) left, right, center. // 0011: (4 channels) left, right, left surround, right surround. // 0100: (5 channels) left, right, center, left surround, right surround. // 0101: (6 channels) left, right, center, LFE, left surround, right surround. // 0110: (7 channels) left, right, center, LFE, center surround, side left, side right. // 0111: (8 channels) left, right, center, LFE, left surround, right surround, side left, side right. // 1000: (2 channels) left, side; using inter-channel decorrelation. // 1001: (2 channels) side, right; using inter-channel decorrelation. // 1010: (2 channels) mid, side; using inter-channel decorrelation. // 1011: reserved. // 1100: reserved. // 1101: reserved. // 1111: reserved. x, err := br.Read(4) if err != nil { return unexpected(err) } if x >= 0xB { return fmt.Errorf("frame.Frame.parseHeader: reserved channels bit pattern (%04b)", x) } frame.Channels = Channels(x) return nil } // parseBlockSize parses the block size of the header. func (frame *Frame) parseBlockSize(br *bits.Reader, blockSize uint64) error { // The 4 bits of n are used to specify the block size as follows: // 0000: reserved. // 0001: 192 samples. // 0010-0101: 576 * 2^(n-2) samples. // 0110: get 8 bit (block size)-1 from the end of the header. // 0111: get 16 bit (block size)-1 from the end of the header. // 1000-1111: 256 * 2^(n-8) samples. n := blockSize switch { case n == 0x0: // 0000: reserved. return errors.New("frame.Frame.parseHeader: reserved block size bit pattern (0000)") case n == 0x1: // 0001: 192 samples. frame.BlockSize = 192 case n >= 0x2 && n <= 0x5: // 0010-0101: 576 * 2^(n-2) samples. frame.BlockSize = 576 * (1 << (n - 2)) case n == 0x6: // 0110: get 8 bit (block size)-1 from the end of the header. x, err := br.Read(8) if err != nil { return unexpected(err) } frame.BlockSize = uint16(x + 1) case n == 0x7: // 0111: get 16 bit (block size)-1 from the end of the header. x, err := br.Read(16) if err != nil { return unexpected(err) } frame.BlockSize = uint16(x + 1) default: // 1000-1111: 256 * 2^(n-8) samples. frame.BlockSize = 256 * (1 << (n - 8)) } return nil } // parseSampleRate parses the sample rate of the header. func (frame *Frame) parseSampleRate(br *bits.Reader, sampleRate uint64) error { // The 4 bits are used to specify the sample rate as follows: // 0000: unknown sample rate; get from StreamInfo. // 0001: 88.2 kHz. // 0010: 176.4 kHz. // 0011: 192 kHz. // 0100: 8 kHz. // 0101: 16 kHz. // 0110: 22.05 kHz. // 0111: 24 kHz. // 1000: 32 kHz. // 1001: 44.1 kHz. // 1010: 48 kHz. // 1011: 96 kHz. // 1100: get 8 bit sample rate (in kHz) from the end of the header. // 1101: get 16 bit sample rate (in Hz) from the end of the header. // 1110: get 16 bit sample rate (in daHz) from the end of the header. // 1111: invalid. switch sampleRate { case 0x0: // 0000: unknown sample rate; get from StreamInfo. case 0x1: // 0001: 88.2 kHz. frame.SampleRate = 88200 case 0x2: // 0010: 176.4 kHz. frame.SampleRate = 176400 // TODO(u): Remove log message when the test cases have been extended. 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) case 0x3: // 0011: 192 kHz. frame.SampleRate = 192000 case 0x4: // 0100: 8 kHz. frame.SampleRate = 8000 case 0x5: // 0101: 16 kHz. frame.SampleRate = 16000 case 0x6: // 0110: 22.05 kHz. frame.SampleRate = 22050 case 0x7: // 0111: 24 kHz. frame.SampleRate = 24000 // TODO(u): Remove log message when the test cases have been extended. 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) case 0x8: // 1000: 32 kHz. frame.SampleRate = 32000 case 0x9: // 1001: 44.1 kHz. frame.SampleRate = 44100 case 0xA: // 1010: 48 kHz. frame.SampleRate = 48000 case 0xB: // 1011: 96 kHz. frame.SampleRate = 96000 case 0xC: // 1100: get 8 bit sample rate (in kHz) from the end of the header. x, err := br.Read(8) if err != nil { return unexpected(err) } frame.SampleRate = uint32(x * 1000) case 0xD: // 1101: get 16 bit sample rate (in Hz) from the end of the header. x, err := br.Read(16) if err != nil { return unexpected(err) } frame.SampleRate = uint32(x) case 0xE: // 1110: get 16 bit sample rate (in daHz) from the end of the header. x, err := br.Read(16) if err != nil { return unexpected(err) } frame.SampleRate = uint32(x * 10) default: // 1111: invalid. return errors.New("frame.Frame.parseHeader: invalid sample rate bit pattern (1111)") } return nil } // Channels specifies the number of channels (subframes) that exist in a frame, // their order and possible inter-channel decorrelation. type Channels uint8 // Channel assignments. The following abbreviations are used: // // C: center (directly in front) // R: right (standard stereo) // Sr: side right (directly to the right) // Rs: right surround (back right) // Cs: center surround (rear center) // Ls: left surround (back left) // Sl: side left (directly to the left) // L: left (standard stereo) // Lfe: low-frequency effect (placed according to room acoustics) // // The first 6 channel constants follow the SMPTE/ITU-R channel order: // // L R C Lfe Ls Rs const ( ChannelsMono Channels = iota // 1 channel: mono. ChannelsLR // 2 channels: left, right. ChannelsLRC // 3 channels: left, right, center. ChannelsLRLsRs // 4 channels: left, right, left surround, right surround. ChannelsLRCLsRs // 5 channels: left, right, center, left surround, right surround. ChannelsLRCLfeLsRs // 6 channels: left, right, center, LFE, left surround, right surround. ChannelsLRCLfeCsSlSr // 7 channels: left, right, center, LFE, center surround, side left, side right. ChannelsLRCLfeLsRsSlSr // 8 channels: left, right, center, LFE, left surround, right surround, side left, side right. ChannelsLeftSide // 2 channels: left, side; using inter-channel decorrelation. ChannelsSideRight // 2 channels: side, right; using inter-channel decorrelation. ChannelsMidSide // 2 channels: mid, side; using inter-channel decorrelation. ) // nChannels specifies the number of channels used by each channel assignment. var nChannels = [...]int{ ChannelsMono: 1, ChannelsLR: 2, ChannelsLRC: 3, ChannelsLRLsRs: 4, ChannelsLRCLsRs: 5, ChannelsLRCLfeLsRs: 6, ChannelsLRCLfeCsSlSr: 7, ChannelsLRCLfeLsRsSlSr: 8, ChannelsLeftSide: 2, ChannelsSideRight: 2, ChannelsMidSide: 2, } // Count returns the number of channels (subframes) used by the provided channel // assignment. func (channels Channels) Count() int { return nChannels[channels] } // Correlate reverts any inter-channel decorrelation between the samples of the // subframes. // // An encoder decorrelates audio samples as follows: // // mid = (left + right)/2 // side = left - right func (frame *Frame) Correlate() { switch frame.Channels { case ChannelsLeftSide: // 2 channels: left, side; using inter-channel decorrelation. left := frame.Subframes[0].Samples side := frame.Subframes[1].Samples for i := range side { // right = left - side side[i] = left[i] - side[i] } case ChannelsSideRight: // 2 channels: side, right; using inter-channel decorrelation. side := frame.Subframes[0].Samples right := frame.Subframes[1].Samples for i := range side { // left = right + side side[i] = right[i] + side[i] } case ChannelsMidSide: // 2 channels: mid, side; using inter-channel decorrelation. mid := frame.Subframes[0].Samples side := frame.Subframes[1].Samples for i := range side { // left = (2*mid + side)/2 // right = (2*mid - side)/2 m := mid[i] s := side[i] m *= 2 // Notice that the integer division in mid = (left + right)/2 discards // the least significant bit. It can be reconstructed however, since a // sum A+B and a difference A-B has the same least significant bit. // // ref: Data Compression: The Complete Reference (ch. 7, Decorrelation) m |= s & 1 mid[i] = (m + s) / 2 side[i] = (m - s) / 2 } } } // Decorrelate performs inter-channel decorrelation between the samples of the // subframes. // // An encoder decorrelates audio samples as follows: // // mid = (left + right)/2 // side = left - right func (frame *Frame) Decorrelate() { switch frame.Channels { case ChannelsLeftSide: // 2 channels: left, side; using inter-channel decorrelation. left := frame.Subframes[0].Samples // already left; no change after inter-channel decorrelation. right := frame.Subframes[1].Samples // set to side after inter-channel decorrelation. for i := range left { l := left[i] r := right[i] // inter-channel decorrelation: // side = left - right side := l - r right[i] = side } case ChannelsSideRight: // 2 channels: side, right; using inter-channel decorrelation. left := frame.Subframes[0].Samples // set to side after inter-channel decorrelation. right := frame.Subframes[1].Samples // already right; no change after inter-channel decorrelation. for i := range left { l := left[i] r := right[i] // inter-channel decorrelation: // side = left - right side := l - r left[i] = side } case ChannelsMidSide: // 2 channels: mid, side; using inter-channel decorrelation. left := frame.Subframes[0].Samples // set to mid after inter-channel decorrelation. right := frame.Subframes[1].Samples // set to side after inter-channel decorrelation. for i := range left { // inter-channel decorrelation: // mid = (left + right)/2 // side = left - right l := left[i] r := right[i] mid := int32((int64(l) + int64(r)) >> 1) // NOTE: using `(left + right) >> 1`, not the same as `(left + right) / 2`. side := l - r left[i] = mid right[i] = side } } } // SampleNumber returns the first sample number contained within the frame. func (frame *Frame) SampleNumber() uint64 { if frame.HasFixedBlockSize { return frame.Num * uint64(frame.BlockSize) } return frame.Num } // unexpected returns io.ErrUnexpectedEOF if err is io.EOF, and returns err // otherwise. func unexpected(err error) error { if err == io.EOF { return io.ErrUnexpectedEOF } return err } ================================================ FILE: frame/frame_test.go ================================================ package frame_test import ( "bytes" "crypto/md5" "io" "testing" "github.com/mewkiz/flac" ) var golden = []struct { path string }{ {path: "../testdata/love.flac"}, {path: "../testdata/19875.flac"}, {path: "../testdata/44127.flac"}, {path: "../testdata/59996.flac"}, {path: "../testdata/80574.flac"}, {path: "../testdata/172960.flac"}, {path: "../testdata/189983.flac"}, {path: "../testdata/191885.flac"}, {path: "../testdata/212768.flac"}, {path: "../testdata/220014.flac"}, {path: "../testdata/243749.flac"}, {path: "../testdata/256529.flac"}, {path: "../testdata/257344.flac"}, // IETF test cases. {path: "../testdata/flac-test-files/subset/01 - blocksize 4096.flac"}, {path: "../testdata/flac-test-files/subset/02 - blocksize 4608.flac"}, {path: "../testdata/flac-test-files/subset/03 - blocksize 16.flac"}, {path: "../testdata/flac-test-files/subset/04 - blocksize 192.flac"}, {path: "../testdata/flac-test-files/subset/05 - blocksize 254.flac"}, {path: "../testdata/flac-test-files/subset/06 - blocksize 512.flac"}, {path: "../testdata/flac-test-files/subset/07 - blocksize 725.flac"}, {path: "../testdata/flac-test-files/subset/08 - blocksize 1000.flac"}, {path: "../testdata/flac-test-files/subset/09 - blocksize 1937.flac"}, {path: "../testdata/flac-test-files/subset/10 - blocksize 2304.flac"}, {path: "../testdata/flac-test-files/subset/11 - partition order 8.flac"}, {path: "../testdata/flac-test-files/subset/12 - qlp precision 15 bit.flac"}, {path: "../testdata/flac-test-files/subset/13 - qlp precision 2 bit.flac"}, {path: "../testdata/flac-test-files/subset/14 - wasted bits.flac"}, {path: "../testdata/flac-test-files/subset/15 - only verbatim subframes.flac"}, {path: "../testdata/flac-test-files/subset/16 - partition order 8 containing escaped partitions.flac"}, {path: "../testdata/flac-test-files/subset/17 - all fixed orders.flac"}, {path: "../testdata/flac-test-files/subset/18 - precision search.flac"}, {path: "../testdata/flac-test-files/subset/19 - samplerate 35467Hz.flac"}, {path: "../testdata/flac-test-files/subset/20 - samplerate 39kHz.flac"}, {path: "../testdata/flac-test-files/subset/21 - samplerate 22050Hz.flac"}, {path: "../testdata/flac-test-files/subset/22 - 12 bit per sample.flac"}, {path: "../testdata/flac-test-files/subset/23 - 8 bit per sample.flac"}, {path: "../testdata/flac-test-files/subset/24 - variable blocksize file created with flake revision 264.flac"}, {path: "../testdata/flac-test-files/subset/25 - variable blocksize file created with flake revision 264, modified to create smaller blocks.flac"}, {path: "../testdata/flac-test-files/subset/26 - variable blocksize file created with CUETools.Flake 2.1.6.flac"}, {path: "../testdata/flac-test-files/subset/27 - old format variable blocksize file created with Flake 0.11.flac"}, {path: "../testdata/flac-test-files/subset/28 - high resolution audio, default settings.flac"}, {path: "../testdata/flac-test-files/subset/29 - high resolution audio, blocksize 16384.flac"}, {path: "../testdata/flac-test-files/subset/30 - high resolution audio, blocksize 13456.flac"}, {path: "../testdata/flac-test-files/subset/31 - high resolution audio, using only 32nd order predictors.flac"}, {path: "../testdata/flac-test-files/subset/32 - high resolution audio, partition order 8 containing escaped partitions.flac"}, {path: "../testdata/flac-test-files/subset/33 - samplerate 192kHz.flac"}, {path: "../testdata/flac-test-files/subset/34 - samplerate 192kHz, using only 32nd order predictors.flac"}, {path: "../testdata/flac-test-files/subset/35 - samplerate 134560Hz.flac"}, {path: "../testdata/flac-test-files/subset/36 - samplerate 384kHz.flac"}, {path: "../testdata/flac-test-files/subset/37 - 20 bit per sample.flac"}, {path: "../testdata/flac-test-files/subset/38 - 3 channels (3.0).flac"}, {path: "../testdata/flac-test-files/subset/39 - 4 channels (4.0).flac"}, {path: "../testdata/flac-test-files/subset/40 - 5 channels (5.0).flac"}, {path: "../testdata/flac-test-files/subset/41 - 6 channels (5.1).flac"}, {path: "../testdata/flac-test-files/subset/42 - 7 channels (6.1).flac"}, {path: "../testdata/flac-test-files/subset/43 - 8 channels (7.1).flac"}, {path: "../testdata/flac-test-files/subset/44 - 8-channel surround, 192kHz, 24 bit, using only 32nd order predictors.flac"}, {path: "../testdata/flac-test-files/subset/45 - no total number of samples set.flac"}, {path: "../testdata/flac-test-files/subset/46 - no min-max framesize set.flac"}, {path: "../testdata/flac-test-files/subset/47 - only STREAMINFO.flac"}, {path: "../testdata/flac-test-files/subset/48 - Extremely large SEEKTABLE.flac"}, {path: "../testdata/flac-test-files/subset/49 - Extremely large PADDING.flac"}, {path: "../testdata/flac-test-files/subset/50 - Extremely large PICTURE.flac"}, {path: "../testdata/flac-test-files/subset/51 - Extremely large VORBISCOMMENT.flac"}, {path: "../testdata/flac-test-files/subset/52 - Extremely large APPLICATION.flac"}, {path: "../testdata/flac-test-files/subset/53 - CUESHEET with very many indexes.flac"}, {path: "../testdata/flac-test-files/subset/54 - 1000x repeating VORBISCOMMENT.flac"}, {path: "../testdata/flac-test-files/subset/55 - file 48-53 combined.flac"}, {path: "../testdata/flac-test-files/subset/56 - JPG PICTURE.flac"}, {path: "../testdata/flac-test-files/subset/57 - PNG PICTURE.flac"}, {path: "../testdata/flac-test-files/subset/58 - GIF PICTURE.flac"}, {path: "../testdata/flac-test-files/subset/59 - AVIF PICTURE.flac"}, {path: "../testdata/flac-test-files/subset/60 - mono audio.flac"}, {path: "../testdata/flac-test-files/subset/61 - predictor overflow check, 16-bit.flac"}, {path: "../testdata/flac-test-files/subset/62 - predictor overflow check, 20-bit.flac"}, // TODO: fix decoding of "subset/63 - ...flac": MD5 checksum mismatch for decoded audio samples; expected e4e4a6b3a672a849a3e2157c11ad23c6, got a0343afaaaa6229266d78ccf3175eb8d {path: "../testdata/flac-test-files/subset/63 - predictor overflow check, 24-bit.flac"}, {path: "../testdata/flac-test-files/subset/64 - rice partitions with escape code zero.flac"}, } func TestFrameHash(t *testing.T) { var zeroHash [md5.Size]byte for _, g := range golden { t.Run(g.path, func(t *testing.T) { stream, err := flac.Open(g.path) if err != nil { t.Fatal(err) } defer stream.Close() // Skip frame hash test if no MD5 hash was set in StreamInfo. want := stream.Info.MD5sum[:] if bytes.Equal(want, zeroHash[:]) { t.Skipf("path=%q, skipping frame hash test as no MD5 hash was set in StreamInfo", g.path) return } md5sum := md5.New() for frameNum := 0; ; frameNum++ { frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } t.Errorf("path=%q, frameNum=%d: error while parsing frame; %v", g.path, frameNum, err) continue } frame.Hash(md5sum) } got := md5sum.Sum(nil) // Verify the decoded audio samples by comparing the MD5 checksum that is // stored in StreamInfo with the computed one. if !bytes.Equal(got, want) { t.Errorf("path=%q: MD5 checksum mismatch for decoded audio samples; expected %32x, got %32x", g.path, want, got) } }) } } func BenchmarkFrameParse(b *testing.B) { // The file 151185.flac is a 119.5 MB public domain FLAC file used to // benchmark the flac library. Because of its size, it has not been included // in the repository, but is available for download at // // http://freesound.org/people/jarfil/sounds/151185/ for i := 0; i < b.N; i++ { stream, err := flac.Open("../testdata/benchmark/151185.flac") if err != nil { b.Fatal(err) } for { _, err := stream.ParseNext() if err != nil { if err == io.EOF { break } stream.Close() b.Fatal(err) } } stream.Close() } } func BenchmarkFrameHash(b *testing.B) { // The file 151185.flac is a 119.5 MB public domain FLAC file used to // benchmark the flac library. Because of its size, it has not been included // in the repository, but is available for download at // // http://freesound.org/people/jarfil/sounds/151185/ for i := 0; i < b.N; i++ { stream, err := flac.Open("../testdata/benchmark/151185.flac") if err != nil { b.Fatal(err) } md5sum := md5.New() for { frame, err := stream.ParseNext() if err != nil { if err == io.EOF { break } stream.Close() b.Fatal(err) } frame.Hash(md5sum) } stream.Close() want := stream.Info.MD5sum[:] got := md5sum.Sum(nil) // Verify the decoded audio samples by comparing the MD5 checksum that is // stored in StreamInfo with the computed one. if !bytes.Equal(got, want) { b.Fatalf("MD5 checksum mismatch for decoded audio samples; expected %32x, got %32x", want, got) } } } ================================================ FILE: frame/subframe.go ================================================ package frame import ( "errors" "fmt" "github.com/mewkiz/flac/internal/bits" ) // A Subframe contains the encoded audio samples from one channel of an audio // block (a part of the audio stream). // // ref: https://www.xiph.org/flac/format.html#subframe type Subframe struct { // Subframe header. SubHeader // Unencoded audio samples. Samples is initially nil, and gets populated by a // call to Frame.Parse. // // Samples is used by decodeFixed and decodeFIR to temporarily store // residuals. Before returning they call decodeLPC which decodes the audio // samples. Samples []int32 // Number of audio samples in the subframe. NSamples int } // parseSubframe reads and parses the header, and the audio samples of a // subframe. func (frame *Frame) parseSubframe(br *bits.Reader, bps uint) (subframe *Subframe, err error) { // Parse subframe header. subframe = new(Subframe) if err = subframe.parseHeader(br); err != nil { return subframe, err } // Adjust bps of subframe for wasted bits-per-sample. bps -= subframe.Wasted // Decode subframe audio samples. subframe.NSamples = int(frame.BlockSize) subframe.Samples = make([]int32, 0, subframe.NSamples) switch subframe.Pred { case PredConstant: err = subframe.decodeConstant(br, bps) case PredVerbatim: err = subframe.decodeVerbatim(br, bps) case PredFixed: err = subframe.decodeFixed(br, bps) case PredFIR: err = subframe.decodeFIR(br, bps) } // Left shift to account for wasted bits-per-sample. for i, sample := range subframe.Samples { subframe.Samples[i] = sample << subframe.Wasted } return subframe, err } // A SubHeader specifies the prediction method and order of a subframe. // // ref: https://www.xiph.org/flac/format.html#subframe_header type SubHeader struct { // Specifies the prediction method used to encode the audio sample of the // subframe. Pred Pred // Prediction order used by fixed and FIR linear prediction decoding. Order int // Wasted bits-per-sample. Wasted uint // Residual coding method used by fixed and FIR linear prediction decoding. ResidualCodingMethod ResidualCodingMethod // Coefficients' precision in bits used by FIR linear prediction decoding. CoeffPrec uint // Predictor coefficient shift needed in bits used by FIR linear prediction // decoding. CoeffShift int32 // Predictor coefficients used by FIR linear prediction decoding. Coeffs []int32 // Rice-coding subframe fields used by residual coding methods rice1 and // rice2; nil if unused. RiceSubframe *RiceSubframe } // RiceSubframe holds rice-coding subframe fields used by residual coding // methods rice1 and rice2. type RiceSubframe struct { // Partition order used by fixed and FIR linear prediction decoding // (for residual coding methods, rice1 and rice2). PartOrder int // TODO: remove PartOrder and infer from int(math.Log2(float64(len(Partitions))))? // Rice partitions. Partitions []RicePartition } // RicePartition is a partition containing a subset of the residuals of a // subframe. type RicePartition struct { // Rice parameter. Param uint // Residual sample size in bits-per-sample used by escaped partitions. EscapedBitsPerSample uint } // parseHeader reads and parses the header of a subframe. func (subframe *Subframe) parseHeader(br *bits.Reader) error { // 1 bit: zero-padding. x, err := br.Read(1) if err != nil { return unexpected(err) } if x != 0 { return errors.New("frame.Subframe.parseHeader: non-zero padding") } // 6 bits: Pred. x, err = br.Read(6) if err != nil { return unexpected(err) } // The 6 bits are used to specify the prediction method and order as follows: // 000000: Constant prediction method. // 000001: Verbatim prediction method. // 00001x: reserved. // 0001xx: reserved. // 001xxx: // if (xxx <= 4) // Fixed prediction method; xxx=order // else // reserved. // 01xxxx: reserved. // 1xxxxx: FIR prediction method; xxxxx=order-1 switch { case x < 1: // 000000: Constant prediction method. subframe.Pred = PredConstant case x < 2: // 000001: Verbatim prediction method. subframe.Pred = PredVerbatim case x < 8: // 00001x: reserved. // 0001xx: reserved. return fmt.Errorf("frame.Subframe.parseHeader: reserved prediction method bit pattern (%06b)", x) case x < 16: // 001xxx: // if (xxx <= 4) // Fixed prediction method; xxx=order // else // reserved. order := int(x & 0x07) if order > 4 { return fmt.Errorf("frame.Subframe.parseHeader: reserved prediction method bit pattern (%06b)", x) } subframe.Pred = PredFixed subframe.Order = order case x < 32: // 01xxxx: reserved. return fmt.Errorf("frame.Subframe.parseHeader: reserved prediction method bit pattern (%06b)", x) default: // 1xxxxx: FIR prediction method; xxxxx=order-1 subframe.Pred = PredFIR subframe.Order = int(x&0x1F) + 1 } // 1 bit: hasWastedBits. x, err = br.Read(1) if err != nil { return unexpected(err) } if x != 0 { // k wasted bits-per-sample in source subblock, k-1 follows, unary coded; // e.g. k=3 => 001 follows, k=7 => 0000001 follows. x, err = br.ReadUnary() if err != nil { return unexpected(err) } subframe.Wasted = uint(x) + 1 } return nil } // Pred specifies the prediction method used to encode the audio samples of a // subframe. type Pred uint8 // Prediction methods. const ( // PredConstant specifies that the subframe contains a constant sound. The // audio samples are encoded using run-length encoding. Since every audio // sample has the same constant value, a single unencoded audio sample is // stored in practice. It is replicated a number of times, as specified by // BlockSize in the frame header. PredConstant Pred = iota // PredVerbatim specifies that the subframe contains unencoded audio samples. // Random sound is often stored verbatim, since no prediction method can // compress it sufficiently. PredVerbatim // PredFixed specifies that the subframe contains linear prediction coded // audio samples. The coefficients of the prediction polynomial are selected // from a fixed set, and can represent 0th through fourth-order polynomials. // The prediction order (0 through 4) is stored within the subframe along // with the same number of unencoded warm-up samples, which are used to kick // start the prediction polynomial. The remainder of the subframe stores // encoded residuals (signal errors) which specify the difference between the // predicted and the original audio samples. PredFixed // PredFIR specifies that the subframe contains linear prediction coded audio // samples. The coefficients of the prediction polynomial are stored in the // subframe, and can represent 0th through 32nd-order polynomials. The // prediction order (0 through 32) is stored within the subframe along with // the same number of unencoded warm-up samples, which are used to kick start // the prediction polynomial. The remainder of the subframe stores encoded // residuals (signal errors) which specify the difference between the // predicted and the original audio samples. PredFIR ) // signExtend interprets x as a signed n-bit integer value and sign extends it // to 32 bits. func signExtend(x uint64, n uint) int32 { // x is signed if its most significant bit is set. if x&(1<<(n-1)) != 0 { // Sign extend x. return int32(x | ^uint64(0)<> uint(shift)) } return nil } ================================================ FILE: go.mod ================================================ module github.com/mewkiz/flac go 1.23.2 toolchain go1.24.5 require ( github.com/icza/bitio v1.1.0 github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d ) require github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 // indirect ================================================ FILE: go.sum ================================================ github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0= github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d h1:IL2tii4jXLdhCeQN69HNzYYW1kl0meSG0wt5+sLwszU= github.com/mewkiz/pkg v0.0.0-20250417130911-3f050ff8c56d/go.mod h1:SIpumAnUWSy0q9RzKD3pyH3g1t5vdawUAPcW5tQrUtI= github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 h1:h8O1byDZ1uk6RUXMhj1QJU3VXFKXHDZxr4TXRPGeBa8= github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985/go.mod h1:uiPmbdUbdt1NkGApKl7htQjZ8S7XaGUAVulJUJ9v6q4= ================================================ FILE: internal/bits/reader.go ================================================ // Package bits provides bit access operations and binary decoding algorithms. package bits import ( "fmt" "io" ) // A Reader handles bit reading operations. It buffers bits up to the next byte // boundary. type Reader struct { // Underlying reader. r io.Reader // Temporary read buffer. buf [8]uint8 // Between 0 and 7 buffered bits since previous read operations. x uint8 // The number of buffered bits in x. n uint } // NewReader returns a new Reader that reads bits from r. func NewReader(r io.Reader) *Reader { return &Reader{r: r} } // Read reads and returns the next n bits, at most 64. It buffers bits up to the // next byte boundary. func (br *Reader) Read(n uint) (x uint64, err error) { if n == 0 { return 0, nil } if n > 64 { return 0, fmt.Errorf("bit.Reader.Read: invalid number of bits; n (%d) exceeds 64", n) } // Read buffered bits. if br.n > 0 { switch { case br.n == n: br.n = 0 return uint64(br.x), nil case br.n > n: br.n -= n mask := ^uint8(0) << br.n x = uint64(br.x&mask) >> br.n br.x &^= mask return x, nil } n -= br.n x = uint64(br.x) br.n = 0 } // Fill the temporary buffer. bytes := n / 8 bits := n % 8 if bits > 0 { bytes++ } _, err = io.ReadFull(br.r, br.buf[:bytes]) if err != nil { return 0, err } // Read bits from the temporary buffer. for _, b := range br.buf[:bytes-1] { x <<= 8 x |= uint64(b) } b := br.buf[bytes-1] if bits > 0 { x <<= bits br.n = 8 - bits mask := ^uint8(0) << br.n x |= uint64(b&mask) >> br.n br.x = b & ^mask } else { x <<= 8 x |= uint64(b) } return x, nil } ================================================ FILE: internal/bits/reader_test.go ================================================ // © 2013 the Bits Authors under the MIT license. See AUTHORS for the list of authors. // // Some benchmark functions in this file were adapted from github.com/bamiaux/iobit // which came with the following copyright notice: // Copyright 2013 Benoît Amiaux. All rights reserved. package bits import ( "bytes" "io" "math/rand" "testing" ) func TestRead(t *testing.T) { tests := []struct { data []byte ns []uint vals []uint64 }{ // 11111111 {[]byte{0xFF}, []uint{1, 1, 1, 1, 1, 1, 1, 1}, []uint64{1, 1, 1, 1, 1, 1, 1, 1}}, {[]byte{0xFF}, []uint{2, 2, 2, 2}, []uint64{0x3, 0x3, 0x3, 0x3}}, {[]byte{0xFF}, []uint{3, 3, 2}, []uint64{0x7, 0x7, 0x3}}, {[]byte{0xFF}, []uint{4, 4}, []uint64{0xF, 0xF}}, {[]byte{0xFF}, []uint{5, 3}, []uint64{0x1F, 0x7}}, {[]byte{0xFF}, []uint{6, 2}, []uint64{0x3F, 0x3}}, {[]byte{0xFF}, []uint{7, 1}, []uint64{0x7F, 0x1}}, {[]byte{0xFF}, []uint{8}, []uint64{0xFF}}, // 10101010 {[]byte{0xAA}, []uint{1, 1, 1, 1, 1, 1, 1, 1}, []uint64{1, 0, 1, 0, 1, 0, 1, 0}}, {[]byte{0xAA}, []uint{2, 2, 2, 2}, []uint64{0x2, 0x2, 0x2, 0x2}}, {[]byte{0xAA}, []uint{3, 3, 2}, []uint64{0x5, 0x2, 0x2}}, {[]byte{0xAA}, []uint{4, 4}, []uint64{0xA, 0xA}}, {[]byte{0xAA}, []uint{5, 3}, []uint64{0x15, 0x2}}, {[]byte{0xAA}, []uint{6, 2}, []uint64{0x2A, 0x2}}, {[]byte{0xAA}, []uint{7, 1}, []uint64{0x55, 0x0}}, {[]byte{0xAA}, []uint{8}, []uint64{0xAA}}, {[]byte{0xAA}, []uint{0}, []uint64{0}}, // orig: 101010101010101010101010101010101010101010101010101010101010101010101010 // 6 bits: 101010 (0x2A) // 64 bits: 1010101010101010101010101010101010101010101010101010101010101010 (0xAAAAAAAAAAAAAAAA) // 2 bit: 10 (0x2) {[]byte{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, []uint{6, 64, 2}, []uint64{0x2A, 0xAAAAAAAAAAAAAAAA, 0x2}}, // 01 1011011 011011 0 {[]byte{0x6D, 0xB6}, []uint{2, 7, 6, 1}, []uint64{0x1, 0x5B, 0x1B, 0x0}}, { []byte{0x21, 0x0F, 0xC7, 0xBB, 0x81, 0x86, 0x39, 0xAC, 0x48, 0xA4, 0xC6, 0xAF, 0xA2, 0xF1, 0x58, 0x1A, 0x8B, 0x95, 0x25, 0xE2, 0x0F, 0xDA, 0x68, 0x92, 0x7F, 0x2B, 0x2F, 0xF8, 0x36, 0xF7, 0x35, 0x78, 0xDB, 0x0F, 0xA5, 0x4C, 0x29, 0xF7, 0xFD, 0x92, 0x8D, 0x92, 0xCA, 0x43, 0xF1, 0x93, 0xDE, 0xE4, 0x7F, 0x59, 0x15, 0x49, 0xF5, 0x97, 0xA8, 0x11, 0xC8, 0xFA, 0x67, 0xAB, 0x03, 0x1E, 0xBD, 0x9C, 0x6A, 0xA4, 0xE9, 0x82, 0x9F, 0x22, 0x4B, 0xE8, 0xEA, 0xF6, 0x67, 0x26, 0xC9, 0x07, 0x7C, 0xB4, 0x1F, 0x79, 0x01, 0x9D, 0x89, 0x2B, 0xE9, 0x93, 0x03, 0xB2, 0xBE, 0x58, 0x82, 0xF3, 0x24, 0x07, 0x58, 0xA3, 0x8D, 0x7E}, []uint{2, 40, 28, 62, 8, 59, 51, 54, 63, 49, 11, 42, 64, 7, 41, 2, 4, 58, 24, 55, 63, 13}, []uint64{0x00, 0x843F1EEE06, 0x18E6B12, 0xA4C6AFA2F1581A8, 0xB9, 0x292F107ED34493F, 0x4ACBFE0DBDCD5, 0x38DB0FA54C29F7, 0x7EC946C96521F8C9, 0x1DEE47F591549, 0x7AC, 0x2F502391F4C, 0xF56063D7B38D549D, 0x18, 0x53E4497D1D, 0x01, 0x07, 0x2CCE4D920EF9683, 0xEF2033, 0x5892BE99303B2B, 0x72C41799203AC51C, 0xD7E}, }, { []byte{0x0D, 0xAF, 0x62, 0xD6, 0x5D, 0xCE, 0x5B, 0xA5, 0x24, 0xF7, 0x35, 0x8E, 0xFB, 0xB5, 0xB8, 0x32, 0x20, 0xCF, 0x58, 0x63, 0x6C, 0xBC, 0x40, 0xCF, 0xAC, 0x9A, 0xEB, 0x3C, 0xC8, 0x47, 0xBC, 0xDC, 0xF1, 0x0F, 0x71, 0x7A, 0xA2, 0x62, 0x77, 0xFF, 0x0A, 0x3A, 0x0E, 0xC7, 0x3E, 0x10, 0xFF, 0x40, 0x8E, 0xCE, 0x87, 0x28, 0xF8, 0x4A, 0xE1, 0xAF, 0x7B, 0xBF, 0x86, 0xE9, 0x94, 0x6F, 0xB0, 0x8F, 0xB6, 0x58, 0x97, 0x5A, 0xB5, 0x52, 0x9D, 0x70, 0x40, 0x74, 0xAF, 0x4A, 0xC8, 0xC0, 0xF5, 0xA4, 0x6F, 0x09, 0x6E, 0xE8, 0x47, 0x7A, 0x77, 0x54, 0x30, 0x03, 0x8F, 0xC0, 0x0E, 0xAC, 0x03, 0xAF, 0x4D, 0xDC, 0xD3, 0x25}, []uint{62, 44, 50, 50, 7, 53, 11, 9, 57, 37, 35, 54, 30, 45, 5, 8, 59, 9, 13, 48, 62, 46, 6}, []uint64{0x36BD8B5977396E9, 0x493DCD63BEE, 0x35B83220CF586, 0xDB2F1033EB26, 0x5D, 0xCF3211EF373C4, 0x1EE, 0x5E, 0x151313BFF851D07, 0xC73E10FF4, 0x47674394, 0x1F095C35EF77F0, 0x374CA37D, 0x108FB658975A, 0x16, 0xAA, 0x29D704074AF4AC8, 0x181, 0x1D69, 0x1BC25BBA11DE, 0x2775430038FC00EA, 0x300EBD37734C, 0x25}, }, { []byte{0x08, 0x0F, 0x1D, 0xFD, 0xC9, 0xC4, 0xAD, 0x25, 0x6F, 0x47, 0x56, 0x20, 0x46, 0xFC, 0x40, 0x54, 0xF5, 0x9B, 0x5B, 0xE5, 0x46, 0x5E, 0x75, 0xE6, 0xE0, 0xAA, 0x60, 0xC8, 0xEB, 0x2E, 0xE5, 0xD4, 0xCD, 0x26, 0x50, 0xA8, 0x1C, 0xCE, 0xE3, 0x55, 0x07, 0xA1, 0x1A, 0x37, 0x90, 0x71, 0xC7, 0x51, 0xF7, 0x1F, 0xDF, 0x0D, 0xFE, 0xB3, 0xFB, 0xC8, 0xF0, 0x08, 0x25, 0xE6, 0x4C, 0x27, 0x62, 0xFA, 0xC9, 0xFE, 0x63, 0xE2, 0x42, 0x03, 0x7A, 0x8B, 0xC4, 0x03, 0x69, 0x6E, 0x07, 0x33, 0x42, 0x37, 0x10, 0x4C, 0x5E, 0xC5, 0x64, 0x2C, 0xA3, 0xC1, 0xC2, 0x55, 0x0A, 0x87, 0x16, 0xA9, 0x28, 0xE7, 0xCD, 0xBA, 0xEA, 0xC9}, []uint{64, 38, 1, 25, 10, 6, 13, 38, 27, 13, 48, 53, 3, 30, 60, 39, 32, 34, 5, 1, 56, 26, 47, 21, 43, 32, 35}, []uint64{0x80F1DFDC9C4AD25, 0x1BD1D58811, 0x01, 0xFC4054, 0x3D6, 0x1B, 0xB7C, 0x2A32F3AF37, 0x2A9832, 0x759, 0x772EA6693285, 0x81CCEE35507A1, 0x00, 0x346F20E3, 0x8EA3EE3FBE1BFD6, 0x3FBC8F0082, 0x5E64C276, 0xBEB27F98, 0x1F, 0x00, 0x242037A8BC4036, 0x25B81CC, 0x6846E2098BD8, 0x1590B2, 0x478384AA150, 0xE2D5251C, 0x7CDBAEAC9}, }, { []byte{0x49, 0x2C, 0x95, 0x56, 0xD7, 0x40, 0x88, 0xA9, 0x13, 0x2E, 0x4A, 0x5C, 0x13, 0xCC, 0x15, 0x9A, 0xA6, 0xEB, 0x4A, 0x0E, 0x9B, 0x96, 0x3C, 0xAD, 0xD1, 0x6E, 0x9C, 0x2D, 0xBA, 0xFD, 0xCE, 0x26, 0xC7, 0x18, 0xBC, 0xDC, 0x0F, 0xA7, 0xD4, 0xAD, 0x15, 0x5E, 0xEB, 0xCC, 0xB9, 0x46, 0x71, 0xE3, 0xDD, 0xFB, 0x4B, 0x99, 0x7D, 0x5B, 0x3F, 0xE4, 0xA4, 0x8B, 0x59, 0x8E, 0x7D, 0x89, 0xDF, 0xFF, 0x84, 0x0D, 0xAE, 0xCA, 0xA8, 0x9B, 0x8E, 0xF2, 0x31, 0xF6, 0xF2, 0x7E, 0x13, 0xDA, 0xEB, 0xE2, 0xED, 0xCD, 0xED, 0x9F, 0x38, 0xC6, 0x9E, 0x7F, 0x7A, 0xA1, 0x83, 0x4E, 0xDA, 0x01, 0xE3, 0x35, 0x41, 0x20, 0x10, 0xA6}, []uint{18, 61, 54, 29, 43, 60, 15, 25, 42, 47, 8, 6, 7, 2, 37, 8, 13, 24, 49, 16, 22, 19, 36, 17, 43, 27, 9, 5, 36, 22}, []uint64{0x124B2, 0xAAB6BA044548997, 0x94B827982B354, 0x1BAD283A, 0x372C795BA2D, 0xD385B75FB9C4D8E, 0x18BC, 0x1B81F4F, 0x2A568AAF75E, 0x32E519C78F77, 0xED, 0x0B, 0x4C, 0x02, 0x1F56CFF929, 0x22, 0x1ACC, 0x73EC4E, 0x1FFF840DAECAA, 0x89B8, 0x3BC8C7, 0x6DE4F, 0xC27B5D7C5, 0x1B737, 0x5B3E718D3CF, 0x77AA183, 0x9D, 0x16, 0x8078CD504, 0x2010A6}, }, { []byte{0x7B, 0x22, 0xD1, 0x15, 0x7D, 0x2A, 0x8F, 0x5E, 0x35, 0x8E, 0xFD, 0x26, 0x3D, 0x98, 0xF0, 0x10, 0x18, 0xD7, 0x1E, 0xDC, 0x1D, 0x54, 0x3A, 0x4D, 0xF3, 0xED, 0xDB, 0x19, 0x46, 0xF8, 0x5B, 0xF3, 0xE5, 0x2C, 0x4B, 0xB6, 0x80, 0x08, 0x4D, 0x27, 0x71, 0x58, 0xAA, 0x81, 0x28, 0x1C, 0x8A, 0xB5, 0x47, 0x6A, 0x84, 0x1B, 0xF2, 0x23, 0xC1, 0xC0, 0x6E, 0x51, 0xF9, 0xB5, 0x19, 0x80, 0xCD, 0xF8, 0x06, 0x6B, 0x31, 0xF6, 0x23, 0x84, 0x1C, 0xB6, 0xBF, 0xEA, 0x59, 0x9B, 0xD8, 0x4F, 0x84, 0x04, 0xDB, 0x4B, 0x71, 0xE4, 0xAE, 0xF2, 0xD6, 0xE9, 0x2A, 0x16, 0x42, 0x9E, 0x0C, 0xFC, 0xA6, 0x84, 0x79, 0xC8, 0x2A, 0x23}, []uint{52, 58, 42, 30, 54, 55, 26, 15, 18, 43, 47, 34, 58, 3, 15, 17, 48, 8, 50, 49, 37, 18, 23}, []uint64{0x7B22D1157D2A8, 0x3D78D63BF498F66, 0xF01018D71E, 0x3707550E, 0x24DF3EDDB1946F, 0x42DF9F29625DB4, 0x109A4, 0x7715, 0x22AA0, 0x25039156A8E, 0x6A841BF223C1, 0x301B947E6, 0x351980CDF8066B3, 0x00, 0x7D88, 0x1C20E, 0x5B5FF52CCDEC, 0x27, 0x30809B696E3C9, 0xBBCB5BA4A859, 0x14F067E53, 0x108F3, 0x482A23}, }, { []byte{0x0B, 0xBD, 0x5B, 0x49, 0x1C, 0x14, 0x1C, 0xE6, 0x96, 0x97, 0x97, 0x3C, 0x76, 0x70, 0xF4, 0x3E, 0xBA, 0x37, 0x88, 0xB2, 0x46, 0xBF, 0x22, 0xE9, 0xA2, 0x84, 0x7A, 0x3D, 0xF2, 0x12, 0xC9, 0xB5, 0x28, 0x15, 0x0A, 0x31, 0x4E, 0xFC, 0x13, 0x09, 0x02, 0x41, 0x3F, 0xCC, 0x8E, 0x0B, 0x06, 0xD1, 0xA3, 0x80, 0x6E, 0x48, 0x12, 0x00, 0xA7, 0xD2, 0x77, 0xCD, 0x9D, 0xB5, 0x91, 0x13, 0x0A, 0x45, 0xBB, 0xE3, 0xFA, 0x0F, 0xC7, 0x8F, 0x4F, 0x4C, 0x3C, 0xB3, 0xC1, 0xD7, 0xC8, 0x92, 0xB1, 0x32, 0x0B, 0x07, 0x21, 0x27, 0x60, 0x0A, 0xF5, 0x44, 0xDB, 0x90, 0x8C, 0x62, 0xBB, 0x20, 0xB1, 0x84, 0x3B, 0xDB, 0xAF, 0xDB}, []uint{5, 4, 44, 10, 7, 54, 2, 22, 24, 49, 32, 52, 63, 57, 25, 5, 61, 22, 9, 25, 51, 12, 14, 1, 23, 57, 16, 40, 14}, []uint64{0x01, 0x07, 0x7AB69238283, 0x273, 0x25, 0x297973C7670F43, 0x03, 0x2BA378, 0x8B246B, 0x1E45D34508F47, 0xBE425936, 0xA502A14629DF8, 0x130902413FCC8E0B, 0xDA34700DC9024, 0x29F49, 0x1B, 0x1CD9DB591130A45B, 0x2F8FE8, 0x7E, 0x78F4F4, 0x61E59E0EBE449, 0x589, 0x2416, 0x00, 0xE424E, 0x1802BD5136E4231, 0x8AEC, 0x82C610EF6E, 0x2FDB}, }, { []byte{0x48, 0xB3, 0x01, 0xCE, 0x08, 0x20, 0xE4, 0xBD, 0x27, 0x21, 0x0A, 0x77, 0x34, 0x5A, 0x50, 0x74, 0xD5, 0x56, 0xCB, 0xE2, 0xCB, 0x7A, 0x63, 0x5F, 0xE3, 0x04, 0x52, 0x87, 0xA8, 0x16, 0x3D, 0x78, 0xE5, 0xC3, 0x82, 0x84, 0x80, 0xC9, 0x67, 0xD4, 0x34, 0xB4, 0xAF, 0xEF, 0x9F, 0x91, 0x5E, 0x1B, 0x8D, 0xF5, 0x43, 0x24, 0xB4, 0xDA, 0xD0, 0xBA, 0xC0, 0xEE, 0xF1, 0x94, 0xA1, 0xE8, 0xAC, 0xDB, 0x84, 0xB8, 0xDC, 0x99, 0x62, 0x4B, 0x19, 0xD1, 0xF8, 0xC5, 0x48, 0x7E, 0xEB, 0x9F, 0x82, 0xFF, 0xE9, 0xA4, 0x88, 0x86, 0x5C, 0x28, 0x60, 0x0F, 0xA3, 0xA7, 0x0B, 0x97, 0xFE, 0x4C, 0x99, 0x17, 0x08, 0xB5, 0x58, 0x94}, []uint{34, 25, 22, 55, 18, 20, 35, 30, 1, 12, 30, 64, 32, 33, 51, 3, 32, 32, 15, 10, 25, 26, 26, 20, 62, 63, 24}, []uint64{0x122CC0738, 0x410725, 0x3A4E42, 0xA77345A5074D5, 0x15B2F, 0x8B2DE, 0x4C6BFC608, 0x2943D40B, 0x00, 0x3D7, 0x23970E0A, 0x1203259F50D2D2BF, 0xBE7E4578, 0xDC6FAA19, 0x12D36B42EB03B, 0x05, 0xE32943D1, 0x59B70971, 0x5C99, 0x189, 0x58CE8F, 0x318A90F, 0x375CFC1, 0x7FF4D, 0x9110CB850C01F47, 0x270B97FE4C991708, 0xB55894}, }, { []byte{0x48, 0x34, 0xA6, 0xF7, 0xD5, 0x71, 0x21, 0x1F, 0x5D, 0x73, 0xC4, 0xCF, 0x93, 0x0B, 0x9C, 0x62, 0xD3, 0xD2, 0x0F, 0x53, 0x68, 0xFC, 0x22, 0x1B, 0x99, 0x91, 0x60, 0x87, 0x45, 0x9C, 0x56, 0x41, 0x66, 0x1C, 0x32, 0x52, 0xB0, 0xAA, 0xA1, 0x65, 0xED, 0x1D, 0x0F, 0x3E, 0x40, 0x5B, 0x80, 0xD1, 0xE8, 0x6B, 0x4C, 0x1A, 0x7E, 0xAD, 0xC2, 0x77, 0x36, 0xA5, 0x02, 0x01, 0x21, 0x98, 0x92, 0x1C, 0x7A, 0xCB, 0x68, 0x3B, 0x03, 0xFC, 0xC9, 0x67, 0xF7, 0x77, 0x65, 0xE7, 0xFA, 0x5E, 0xF9, 0xE5, 0x92, 0x2A, 0x97, 0x7C, 0xAC, 0x82, 0xF5, 0xEE, 0xAD, 0x81, 0xF4, 0xB9, 0xF0, 0xF7, 0xA7, 0x9C, 0x91, 0xC6, 0x51, 0x4D}, []uint{61, 55, 35, 55, 14, 6, 37, 60, 46, 25, 52, 62, 27, 23, 3, 27, 39, 19, 31, 2, 6, 52, 7, 48, 8}, []uint64{0x90694DEFAAE2423, 0x75D73C4CF930B9, 0x63169E907, 0x54DA3F0886E664, 0x1608, 0x1D, 0x2CE2B20B3, 0xE1929585550B2F, 0x1A3A1E7C80B7, 0x347A1, 0xAD3069FAB709D, 0x336A502012198921, 0x63D65B4, 0xEC0FF, 0x01, 0x4967F77, 0x3B2F3FD2F7, 0x67964, 0x4552EF95, 0x02, 0x10, 0x5EBDD5B03E973, 0x70, 0xF7A79C91C651, 0x4D}, }, { []byte{0x04, 0x2A, 0xDC, 0xC2, 0x25, 0xBF, 0x31, 0x81, 0x18, 0xE5, 0x6F, 0xAD, 0xE0, 0x60, 0x2C, 0xAC, 0x62, 0xF2, 0xD5, 0x59, 0xB9, 0x26, 0xAE, 0x4D, 0x67, 0x86, 0x7B, 0x23, 0xA2, 0xCB, 0xAC, 0x63, 0x06, 0xB2, 0xE3, 0x2F, 0x73, 0x59, 0x64, 0x79, 0xAC, 0x74, 0x15, 0xF2, 0x51, 0x14, 0xFB, 0x45, 0x06, 0xBB, 0xF0, 0x29, 0x5A, 0xD2, 0x90, 0x6F, 0x24, 0xB9, 0x8F, 0x06, 0x54, 0xAE, 0x56, 0x33, 0x3D, 0x79, 0x92, 0x42, 0x50, 0xCF, 0x16, 0x53, 0xCB, 0xC6, 0x57, 0x45, 0x17, 0xEA, 0x69, 0x40, 0xAC, 0xCB, 0x97, 0x74, 0xA0, 0x8A, 0x79, 0x40, 0xA1, 0x2E, 0x63, 0xCA, 0x61, 0xCD, 0x98, 0x2B, 0xCF, 0x55, 0x3A, 0xCB}, []uint{4, 14, 31, 4, 42, 46, 62, 30, 58, 51, 6, 1, 39, 61, 52, 24, 48, 57, 6, 50, 44, 1, 54, 15}, []uint64{0x00, 0x10AB, 0x39844B7E, 0x06, 0xC08C72B7D6, 0x3C0C05958C5E, 0x16AACDC935726B3C, 0xCF64745, 0x25D63183597197B, 0x4D6591E6B1D05, 0x1F, 0x00, 0x25114FB450, 0xD77E052B5A520DE, 0x49731E0CA95CA, 0xC667AF, 0x32484A19E2CA, 0xF2F195D145FA9A, 0x14, 0x2B32E5DD2822, 0x9E50284B98F, 0x00, 0x14C39B30579EAA, 0x3ACB}, }, { []byte{0x8A, 0xCC, 0x20, 0x56, 0x0B, 0x1B, 0x64, 0xA3, 0x37, 0x3A, 0x54, 0xD7, 0x6E, 0x2B, 0x16, 0x8E, 0x92, 0xE5, 0xC1, 0xCA, 0x2B, 0xE8, 0x00, 0x8A, 0x64, 0xBF, 0x5C, 0x3F, 0x3F, 0xF6, 0x3C, 0x11, 0x80, 0x34, 0x84, 0x3E, 0xE4, 0x04, 0x51, 0x7C, 0x54, 0xA0, 0x07, 0x59, 0xD3, 0x2E, 0x19, 0x3E, 0x1E, 0xAE, 0x16, 0x47, 0x2F, 0xF5, 0xF1, 0x19, 0xB6, 0xA1, 0x36, 0x2D, 0xFC, 0x1B, 0x86, 0x13, 0xE0, 0xF4, 0xF9, 0x68, 0x57, 0x9D, 0x1F, 0xDE, 0xE5, 0x12, 0xD1, 0x94, 0x47, 0xD8, 0xE5, 0x2A, 0xAF, 0xCE, 0xE0, 0xB7, 0x98, 0xB2, 0xE1, 0xEE, 0xA5, 0x7A, 0x89, 0xB4, 0x06, 0x8B, 0x59, 0xD6, 0xBF, 0x69, 0x56, 0x4B}, []uint{13, 1, 5, 35, 47, 53, 53, 18, 10, 42, 12, 6, 6, 62, 43, 42, 38, 55, 35, 21, 27, 57, 25, 13, 32, 33, 6, 10}, []uint64{0x1159, 0x01, 0x01, 0x1582C6D9, 0x1466E74A9AED, 0x18AC5A3A4B9707, 0x515F40045325F, 0x2B87E, 0x1FF, 0x2C782300690, 0x87D, 0x32, 0x00, 0x228BE2A5003ACE99, 0x3864F87AB85, 0x2472FF5F119, 0x2DA84D8B7F, 0x370C27C1E9F2D, 0x579D1FDE, 0x1CA25A, 0x19447D8, 0x1CA555F9DC16F31, 0xCB87BA, 0x12BD, 0x44DA0345, 0x159D6BF69, 0x15, 0x24B}, }, { []byte{0x47, 0xC2, 0x96, 0xCD, 0x76, 0xCD, 0x5C, 0x93, 0xA4, 0x08, 0xD0, 0x96, 0x39, 0x5C, 0xE1, 0x02, 0x05, 0xBF, 0xD5, 0x7B, 0xF8, 0xD6, 0xCD, 0x5D, 0x30, 0x6E, 0xD2, 0x31, 0x28, 0xEB, 0x5C, 0x3C, 0x4A, 0x95, 0xF1, 0x3F, 0xB6, 0xA8, 0xAD, 0xB8, 0x53, 0xC8, 0xED, 0x3D, 0x9D, 0xB4, 0xC2, 0x2F, 0xE5, 0x79, 0x94, 0x3F, 0x15, 0x38, 0xBE, 0xEB, 0x51, 0x9B, 0xB9, 0x6F, 0x6F, 0xF1, 0x4F, 0xA6, 0x7F, 0xB4, 0xD0, 0x1B, 0xF7, 0x8A, 0xF7, 0xCC, 0xD8, 0x36, 0x17, 0xD4, 0x9A, 0xAE, 0xFF, 0x04, 0x07, 0xAA, 0x86, 0xC6, 0x12, 0x31, 0x77, 0x8A, 0x5B, 0x15, 0x0B, 0xEB, 0x1C, 0xA4, 0xF8, 0xA2, 0x12, 0xD8, 0x81, 0xA2}, []uint{16, 21, 34, 33, 40, 35, 26, 3, 34, 6, 45, 11, 45, 44, 6, 14, 7, 32, 11, 16, 35, 16, 48, 43, 63, 14, 13, 34, 35, 13, 7}, []uint64{0x47C2, 0x12D9AE, 0x366AE49D2, 0x8D09639, 0x5CE10205BF, 0x6ABDFC6B6, 0x1ABA60D, 0x06, 0x348C4A3AD, 0x1C, 0x78952BE27F6, 0x6A8, 0x15B70A791DA7, 0xB3B69845FCA, 0x3C, 0x3287, 0x71, 0x538BEEB5, 0xCD, 0xDCB7, 0x5BFC53E99, 0xFED3, 0x406FDE2BDF33, 0x306C2FA9355, 0x6FF0407AA86C6123, 0x5DE, 0x52D, 0x22A17D639, 0x24F8A212D, 0x1103, 0x22}, }, { []byte{0xAD, 0x57, 0x64, 0x74, 0x59, 0x9A, 0x31, 0x7D, 0x46, 0x3A, 0xD3, 0x15, 0xEA, 0xE7, 0x3A, 0xBC, 0xBF, 0xE7, 0x6A, 0x36, 0xF2, 0x99, 0x7A, 0x5F, 0x09, 0xB2, 0x3E, 0xE5, 0xD6, 0x7D, 0x84, 0x7A, 0x62, 0xB3, 0xD8, 0xC3, 0x84, 0x42, 0x40, 0x59, 0xBE, 0x8A, 0x59, 0xC7, 0x35, 0xD7, 0xC9, 0xB2, 0x6F, 0xDD, 0x67, 0x04, 0x3B, 0x20, 0xDC, 0x27, 0x63, 0x82, 0x34, 0x3D, 0xBC, 0xE6, 0x29, 0x45, 0x15, 0x94, 0xC9, 0x0C, 0xFA, 0xCF, 0x0F, 0x35, 0x58, 0x06, 0x12, 0x51, 0x18, 0xE7, 0x42, 0x11, 0x39, 0xB3, 0xB4, 0xDD, 0xFE, 0x3F, 0xD7, 0x54, 0xB0, 0xF3, 0x56, 0x61, 0x7D, 0xC4, 0x09, 0xA2, 0x1E, 0x36, 0xFA, 0xFA}, []uint{23, 21, 29, 16, 60, 23, 38, 41, 14, 27, 15, 61, 34, 40, 47, 21, 23, 51, 2, 30, 50, 53, 38, 4, 29, 10}, []uint64{0x56ABB2, 0x74599, 0x1462FA8C, 0x75A6, 0x2BD5CE75797FCED, 0x236F29, 0x25E97C26C8, 0x1F72EB3EC23, 0x34C5, 0x33D8C38, 0x2212, 0x59BE8A59C735D7, 0x326C9BF75, 0x9C10EC8370, 0x4EC704687B79, 0x198A51, 0x22B299, 0x10CFACF0F3558, 0x00, 0x6125118, 0x39D0844E6CED3, 0xEFF1FEBAA5879, 0x2ACC2FB881, 0x03, 0x8878DBE, 0x2FA}, }, { []byte{0xCD, 0x03, 0x06, 0x80, 0x27, 0x9D, 0x7E, 0x06, 0x6D, 0x29, 0x42, 0xAE, 0x44, 0x8D, 0xA3, 0xC9, 0x85, 0x03, 0xF1, 0x4D, 0x48, 0xB6, 0xC7, 0xDF, 0xBF, 0x87, 0x7E, 0x58, 0xB1, 0x92, 0x87, 0x05, 0x06, 0xE1, 0x6E, 0x0D, 0x15, 0x51, 0x99, 0xC5, 0x6C, 0x71, 0xCF, 0xFB, 0x8F, 0xE2, 0xD3, 0xA2, 0x31, 0x90, 0x4F, 0x38, 0x9C, 0x3A, 0xD7, 0x50, 0xD0, 0x75, 0x70, 0x33, 0x8B, 0x62, 0x44, 0x23, 0x9E, 0x6A, 0x8C, 0xE7, 0xB2, 0xCA, 0x84, 0x3C, 0x9F, 0x57, 0x70, 0x51, 0xA5, 0xBE, 0xD4, 0x4A, 0x3A, 0x61, 0xE8, 0x4E, 0x75, 0x25, 0xCD, 0x4E, 0x72, 0x5C, 0x69, 0xB3, 0x5B, 0x74, 0xF2, 0x4B, 0x76, 0x9C, 0x8B, 0xF0}, []uint{47, 52, 30, 11, 13, 23, 37, 17, 13, 18, 26, 3, 64, 5, 37, 21, 37, 46, 28, 8, 23, 48, 1, 9, 30, 42, 15, 23, 26, 16, 12, 19}, []uint64{0x6681834013CE, 0xBF033694A1572, 0x91B4793, 0x50, 0x7E2, 0x4D48B6, 0x18FBF7F0EF, 0x1962C, 0xC94, 0xE0A0, 0x370B706, 0x04, 0x55466715B1C73FEE, 0x07, 0x1E2D3A2319, 0x9E71, 0x70EB5D434, 0x7570338B624, 0x4239E6A, 0x8C, 0x73D965, 0x421E4FABB828, 0x01, 0x14B, 0x1F6A251D, 0xC3D09CEA4B, 0x4D4E, 0x392E34, 0x366B6E9, 0xE496, 0xED3, 0x48BF0}, }, { []byte{0x69, 0x4F, 0x3D, 0x68, 0x86, 0x48, 0x1B, 0x9E, 0x94, 0xFF, 0xDE, 0x36, 0xDD, 0xD1, 0xBF, 0x69, 0x48, 0x8D, 0xCF, 0x2C, 0x2A, 0xA0, 0xA2, 0xFF, 0xC9, 0xD9, 0x6A, 0x99, 0x3D, 0x6D, 0xFA, 0x39, 0x79, 0xAC, 0x87, 0xC1, 0xAF, 0xCE, 0x2A, 0xCF, 0x09, 0x84, 0xFD, 0xC1, 0xE6, 0xC4, 0x27, 0x2E, 0x4A, 0x4C, 0x64, 0x0F, 0xBC, 0x81, 0xFA, 0xED, 0xED, 0x23, 0x29, 0x02, 0x6F, 0xF5, 0x81, 0xC5, 0x18, 0x33, 0x08, 0xC8, 0x7F, 0xE0, 0xD0, 0x90, 0xC0, 0x12, 0x77, 0xEE, 0xEB, 0x6A, 0x6C, 0x11, 0x08, 0xA0, 0xBB, 0xF2, 0x94, 0x80, 0xA1, 0x98, 0xBB, 0x44, 0xDC, 0xE4, 0x07, 0x99, 0x1D, 0x54, 0x18, 0x58, 0x14, 0x39}, []uint{20, 47, 3, 29, 11, 38, 53, 36, 6, 20, 14, 8, 55, 6, 32, 23, 49, 28, 16, 50, 20, 55, 41, 3, 31, 13, 33, 39, 21}, []uint64{0x694F3, 0x6B443240DCF4, 0x05, 0x7FEF1B6, 0x774, 0x1BF69488DC, 0x1E58554145FF93, 0xB2D5327AD, 0x2F, 0xD1CBC, 0x3590, 0xF8, 0x1AFCE2ACF0984F, 0x37, 0x79B109C, 0x5C9498, 0x1903EF207EBB7, 0xB48CA40, 0x9BFD, 0x181C5183308C8, 0x7FE0D, 0x4860093BF775B, 0xA6C1108A0B, 0x05, 0x7CA52028, 0xCC5, 0x1B44DCE40, 0x3CC8EAA0C2, 0x181439}, }, { []byte{0xAA, 0xE8, 0x77, 0xB9, 0x9B, 0xB1, 0xDF, 0xCD, 0x24, 0x21, 0xCA, 0xFC, 0x15, 0x32, 0xFC, 0x71, 0x41, 0x53, 0x20, 0x3C, 0x9A, 0x26, 0x5E, 0x35, 0x58, 0x6E, 0x97, 0xC3, 0xEE, 0x5A, 0x8F, 0x6C, 0x26, 0x9C, 0xD9, 0xB0, 0x54, 0xCE, 0x57, 0x3D, 0xDC, 0x41, 0x56, 0xE6, 0xBE, 0x7A, 0x20, 0xEF, 0x04, 0xF6, 0x14, 0x4F, 0x21, 0x78, 0x5A, 0x55, 0x66, 0xA1, 0x3D, 0xF8, 0x7D, 0x5C, 0x10, 0x3C, 0x3F, 0x28, 0x4C, 0x05, 0x62, 0x3F, 0xDA, 0xBF, 0x11, 0xA7, 0x02, 0x8E, 0xC8, 0x4F, 0xC2, 0x4A, 0x86, 0xE4, 0xFD, 0xD4, 0xAC, 0x37, 0x10, 0xD7, 0x60, 0x05, 0x97, 0xE0, 0x08, 0xD8, 0xB6, 0xAA, 0x08, 0xC9, 0xD5, 0x1F}, []uint{9, 23, 6, 21, 31, 58, 51, 34, 50, 22, 35, 63, 13, 37, 12, 29, 63, 64, 16, 46, 9, 28, 47, 33}, []uint64{0x155, 0x6877B9, 0x26, 0x1D8EFE, 0x3490872B, 0x3C1532FC7141532, 0x1E4D132F1AAC, 0xDD2F87DC, 0x2D47B6134E6CD, 0x20A99C, 0x573DDC415, 0x3735F3D1077827B0, 0x144F, 0x42F0B4AAC, 0xD42, 0xF7E1F57, 0x20787E50980AC47, 0xFB57E234E051D909, 0xF849, 0x143727EEA561, 0x171, 0xD76005, 0x4BF0046C5B55, 0x8C9D51F}, }, { []byte{0x7E, 0x3B, 0x8C, 0x41, 0x5D, 0x41, 0x24, 0xF4, 0x14, 0x8C, 0x75, 0xCB, 0x0D, 0x8E, 0x08, 0xEA, 0xD9, 0xE5, 0x84, 0x3E, 0x54, 0xA0, 0xD9, 0x22, 0xF5, 0xB8, 0x0D, 0xED, 0x3A, 0x7F, 0x93, 0x06, 0xF8, 0xC8, 0x4A, 0x60, 0x15, 0x65, 0x06, 0x43, 0xFF, 0x3A, 0x50, 0xFE, 0xCE, 0xE0, 0x15, 0x1F, 0x03, 0x7F, 0x2B, 0xB1, 0x04, 0x07, 0x9C, 0xCD, 0x9B, 0xEA, 0xCE, 0xC7, 0xAB, 0x96, 0xD5, 0x42, 0x88, 0x93, 0xBB, 0xD0, 0x2B, 0x74, 0x06, 0x68, 0x3E, 0xE2, 0x80, 0xDA, 0x78, 0x10, 0x94, 0x47, 0x3C, 0x7B, 0xA1, 0x8F, 0x27, 0x55, 0xD7, 0x37, 0xA9, 0x5F, 0xDD, 0x1D, 0xE1, 0xF4, 0x03, 0xA8, 0x99, 0xC2, 0xD0, 0x86}, []uint{34, 59, 46, 49, 28, 60, 53, 47, 38, 45, 23, 33, 8, 1, 8, 12, 11, 50, 16, 25, 30, 33, 2, 3, 33, 35, 18}, []uint64{0x1F8EE3105, 0x3A8249E82918EB9, 0x186C704756CF, 0x5843E54A0D92, 0x2F5B80D, 0xED3A7F9306F8C84, 0x14C02ACA0C87FE, 0x3A50FECEE015, 0x7C0DFCAEC, 0x8203CE66CDF, 0x2B3B1E, 0x15CB6AA14, 0x44, 0x01, 0x3B, 0xBD0, 0x15B, 0x280CD07DC501B, 0x4F02, 0x2511CF, 0x7BA18F2, 0xEABAE6F5, 0x00, 0x05, 0xFEE8EF0F, 0x500EA2670, 0x2D086}, }, { []byte{0xDD, 0xE8, 0x87, 0xA5, 0xCA, 0xBB, 0xC8, 0x9F, 0x2F, 0xAF, 0x66, 0xE8, 0xB9, 0x48, 0x0D, 0x31, 0xB5, 0x8E, 0xAA, 0x48, 0x6A, 0x74, 0xCB, 0xC5, 0x9E, 0x1C, 0x1D, 0xE5, 0x1D, 0x89, 0x0A, 0x4B, 0x10, 0x12, 0xAA, 0xFB, 0x08, 0x6B, 0x10, 0x62, 0x55, 0x94, 0xA1, 0x38, 0xB0, 0x4D, 0x3F, 0xB1, 0xA8, 0xFC, 0xA2, 0x0E, 0x6C, 0x6B, 0x65, 0x73, 0x2D, 0x61, 0x47, 0x24, 0xB9, 0xBB, 0xA0, 0x4A, 0xF8, 0x05, 0xF4, 0x74, 0x1B, 0x06, 0x99, 0x93, 0x63, 0x4A, 0xF7, 0x9D, 0x43, 0x23, 0x00, 0x30, 0x39, 0x5A, 0x65, 0x8A, 0xA4, 0x13, 0xF1, 0x6A, 0x29, 0xB7, 0x16, 0x24, 0xDD, 0xDB, 0xF7, 0x75, 0x05, 0x94, 0x48, 0x76}, []uint{32, 10, 14, 19, 40, 24, 28, 60, 31, 59, 43, 11, 27, 19, 22, 33, 46, 51, 41, 10, 29, 31, 34, 9, 25, 28, 24}, []uint64{0xDDE887A5, 0x32A, 0x3BC8, 0x4F97D, 0x7B3745CA40, 0x698DAC, 0x7552435, 0x3A65E2CF0E0EF28, 0x7624292C, 0x202555F610D620C, 0x25594A138B0, 0x269, 0x7EC6A3F, 0x1441C, 0x3635B2, 0x1732D6147, 0x92E6EE812BE, 0xBE8E8360D33, 0x4D8D2BDE75, 0x32, 0x6006072, 0x5A658AA4, 0x4FC5A8A6, 0x1B8, 0x1624DDD, 0xBF77505, 0x944876}, }, { []byte{0x80, 0x94, 0x8F, 0xFF, 0xAB, 0xB3, 0x58, 0x12, 0x91, 0x7D, 0xEB, 0xBA, 0x4F, 0xF2, 0x01, 0x6B, 0xCD, 0xFF, 0x44, 0xB7, 0xD7, 0xC7, 0x19, 0xAE, 0x12, 0x9A, 0x65, 0x48, 0x18, 0xD7, 0x10, 0x30, 0x2D, 0x72, 0x76, 0xC1, 0x97, 0x4E, 0xC2, 0x91, 0x40, 0x30, 0x92, 0x47, 0x5E, 0xCB, 0xC2, 0x85, 0xBA, 0xF4, 0xEF, 0x47, 0x3D, 0x70, 0x2D, 0x64, 0xD8, 0x63, 0xAD, 0xB2, 0x96, 0xC4, 0xF1, 0x1A, 0x57, 0xB2, 0xAB, 0xF4, 0x6E, 0x1E, 0x4E, 0x4E, 0x93, 0x32, 0xF1, 0x6C, 0x76, 0x1F, 0xA1, 0xAE, 0xD6, 0x5A, 0x27, 0x1D, 0x37, 0xA9, 0x2B, 0x32, 0x4A, 0xF6, 0x29, 0x47, 0xC0, 0x29, 0x69, 0xCE, 0xA9, 0x64, 0x93, 0xBC}, []uint{37, 49, 14, 17, 29, 33, 20, 9, 52, 30, 60, 24, 18, 22, 41, 3, 11, 30, 23, 14, 38, 14, 20, 27, 6, 15, 25, 63, 42, 4, 10}, []uint64{0x101291FFF5, 0xECD604A45F7A, 0x3BA4, 0x1FE40, 0x5AF37FD, 0x25BEBE38, 0xCD709, 0x9A, 0x654818D710302, 0x35C9DB06, 0x5D3B0A4500C2491, 0xD7B2F0, 0x285BA, 0x3D3BD1, 0x19EB816B26C, 0x01, 0x475, 0x2D94B627, 0x44695E, 0x32AB, 0x3D1B879393, 0x2933, 0x2F16C, 0x3B0FD0D, 0x1D, 0x565A, 0x4E3A6F, 0x292B324AF62947C0, 0xA5A73AA592, 0x04, 0x3BC}, }, { []byte{0x00, 0xFA, 0x33, 0x12, 0xCB, 0xA1, 0x5D, 0xC3, 0x6C, 0x6A, 0x85, 0xBF, 0xA2, 0x49, 0x3C, 0x04, 0x16, 0xD2, 0xF2, 0x2E, 0xCA, 0x84, 0x20, 0x29, 0x9D, 0x54, 0x0C, 0xE2, 0x4A, 0x7D, 0x26, 0x36, 0x54, 0xC2, 0x7B, 0x72, 0x3D, 0x4A, 0xA6, 0x6E, 0xAD, 0xDE, 0xF7, 0x94, 0x78, 0xF5, 0xB5, 0x7D, 0x24, 0xB2, 0x9C, 0xC4, 0x5E, 0xA5, 0xE2, 0xF6, 0x2D, 0x5C, 0x7D, 0x8D, 0x32, 0x47, 0x4A, 0xC6, 0x51, 0xBA, 0x66, 0x80, 0xA4, 0xF9, 0x22, 0xF0, 0x3E, 0x51, 0x09, 0xAD, 0x1E, 0x26, 0x1E, 0xC5, 0x0C, 0x2A, 0xFA, 0x7A, 0xDC, 0x8A, 0x6F, 0xF2, 0x3C, 0x0A, 0xD4, 0xAB, 0x25, 0x1F, 0xFD, 0x1A, 0xC1, 0x9E, 0x35, 0x8D}, []uint{11, 43, 6, 27, 24, 36, 9, 63, 39, 53, 11, 56, 17, 59, 57, 52, 42, 11, 45, 15, 54, 17, 21, 13, 18, 1}, []uint64{0x07, 0x68CC4B2E857, 0x1C, 0x1B63542, 0xDFD124, 0x9E020B697, 0x122, 0x765421014CEAA067, 0x929F498D9, 0xA613DB91EA553, 0x1BA, 0xB77BDE51E3D6D5, 0x1E925, 0x4A73117A978BD8B, 0xAE3EC69923A563, 0x28DD3340527C9, 0x5E07CA2135, 0x51E, 0x4C3D8A1855F, 0x27AD, 0x3229BFC8F02B52, 0x15928, 0x1FFD1A, 0x1833, 0x31AC6, 0x01}, }, { []byte{0x78, 0xF4, 0x61, 0xC2, 0x47, 0x09, 0x4B, 0x98, 0xDD, 0x2A, 0xF5, 0x9F, 0x24, 0x99, 0x71, 0x4A, 0x3E, 0x0E, 0xB0, 0xEF, 0xB0, 0xAA, 0x6C, 0x61, 0xB2, 0xF6, 0x46, 0x0F, 0xB5, 0x94, 0x3E, 0x64, 0x4A, 0x5B, 0x55, 0xF4, 0x16, 0xF0, 0x65, 0xB4, 0x74, 0xD9, 0x3F, 0x07, 0x29, 0x7E, 0x12, 0xBF, 0xF6, 0xC1, 0x39, 0x0B, 0x1E, 0x33, 0xC0, 0x65, 0xEC, 0x68, 0xA2, 0x1E, 0xBE, 0xD1, 0x5A, 0x66, 0xC2, 0xCD, 0xA6, 0xF2, 0x46, 0x39, 0x03, 0x84, 0xE1, 0xF9, 0x72, 0x46, 0xF5, 0x3E, 0xA3, 0x3B, 0x49, 0x47, 0x0D, 0xB2, 0xBA, 0x43, 0x5A, 0x6B, 0x52, 0xF2, 0x01, 0x99, 0x3F, 0xBB, 0x0F, 0xA3, 0x55, 0x95, 0xB3, 0x5E}, []uint{22, 44, 17, 40, 32, 4, 31, 20, 14, 57, 50, 57, 3, 10, 24, 59, 58, 18, 40, 51, 19, 25, 33, 55, 17}, []uint64{0x1E3D18, 0x7091C252E63, 0xE957, 0xACF924CB8A, 0x51F07587, 0x07, 0x6C2A9B18, 0x6CBD9, 0x60F, 0x16B287CC894B6AB, 0x3A0B7832DA3A6, 0x193F07297E12BFF, 0x03, 0x182, 0x72163C, 0x33C065EC68A21EB, 0x3B45699B0B369BC, 0x24639, 0x384E1F972, 0x237A9F519DA4A, 0x1C36C, 0x15D21AD, 0x6B52F201, 0x4C9FDD87D1AACA, 0x1B35E}, }, { []byte{0x5D, 0x8E, 0x1E, 0xCA, 0x9E, 0xB2, 0x62, 0x1F, 0xC3, 0x5C, 0xD0, 0x64, 0xC8, 0x63, 0xD9, 0x53, 0x2F, 0x2E, 0x5E, 0x6D, 0x03, 0xC6, 0xB1, 0xFE, 0x3A, 0xAE, 0x99, 0x3C, 0x47, 0x91, 0x34, 0x15, 0x1C, 0x95, 0xE4, 0xD1, 0xD0, 0xC0, 0xE7, 0xFD, 0x66, 0x35, 0x33, 0xC3, 0x03, 0xAA, 0x77, 0xCC, 0x1C, 0x77, 0x92, 0xB9, 0xA2, 0xD7, 0xE4, 0xEA, 0xD1, 0x4A, 0x74, 0xF4, 0x05, 0x4C, 0xCB, 0xBF, 0xEB, 0x98, 0x20, 0x8F, 0x77, 0x4D, 0xAA, 0x13, 0xD6, 0xB1, 0xCF, 0x80, 0x9D, 0x6B, 0xDB, 0x02, 0xA9, 0xA3, 0xD2, 0x0F, 0xCA, 0x4D, 0xDC, 0xC5, 0x58, 0x10, 0x3D, 0x96, 0x82, 0xF1, 0x00, 0x32, 0x6B, 0x25, 0xFC, 0x0E}, []uint{39, 44, 24, 38, 3, 27, 12, 58, 22, 28, 54, 20, 35, 30, 27, 46, 41, 35, 44, 19, 1, 20, 41, 8, 36, 48}, []uint64{0x2EC70F654F, 0x59310FE1AE6, 0x832643, 0x7B2A65E5C, 0x05, 0x73681E3, 0x58F, 0x3C755D32788F226, 0x20A8E4, 0xAF268E8, 0x181CFFACC6A678, 0x60754, 0x77CC1C779, 0xAE68B5F, 0x49D5A29, 0x13A7A02A665D, 0x1FEB98208F7, 0x3A6D509EB, 0x58E7C04EB5E, 0x6C0AA, 0x00, 0xD1E90, 0xFCA4DDCC55, 0x81, 0x3D9682F1, 0x326B25FC0E}, }, { []byte{0xB4, 0x6D, 0x53, 0x49, 0xB7, 0x06, 0x34, 0x33, 0x99, 0x26, 0xC8, 0x16, 0x3E, 0x5F, 0x8E, 0x87, 0x26, 0xDE, 0x13, 0xBD, 0xBA, 0xEA, 0x1A, 0x03, 0xCD, 0x2E, 0xAC, 0x7D, 0x79, 0xFA, 0x25, 0x4F, 0xAF, 0x5B, 0xC4, 0xE4, 0x6A, 0x50, 0x33, 0x83, 0xCC, 0xF5, 0x49, 0x3E, 0xCF, 0xAC, 0xAA, 0x94, 0x89, 0x33, 0xB6, 0xC4, 0x77, 0xBF, 0xAF, 0xE6, 0xFA, 0x07, 0x07, 0x5B, 0x8E, 0x6B, 0x8B, 0xFE, 0x1C, 0xE3, 0x20, 0xF3, 0x17, 0x54, 0x3F, 0x38, 0x99, 0xD4, 0xAB, 0x85, 0xE7, 0x7D, 0x47, 0xE3, 0x41, 0x98, 0xE9, 0x5B, 0xF4, 0x38, 0x18, 0xEE, 0x13, 0x64, 0x2E, 0xC3, 0x5F, 0x22, 0x42, 0x41, 0xCB, 0x62, 0x59, 0xBE}, []uint{56, 11, 10, 52, 2, 11, 13, 21, 25, 24, 13, 2, 52, 27, 43, 10, 16, 41, 13, 46, 60, 57, 4, 62, 43, 13, 40, 28, 5}, []uint64{0xB46D5349B70634, 0x19C, 0x324, 0xD902C7CBF1D0E, 0x01, 0x1B7, 0x109D, 0x1DBAEA, 0x34079A, 0x5D58FA, 0x1E7E, 0x02, 0x254FAF5BC4E46, 0x52819C1, 0x733D524FB3E, 0x2CA, 0xA948, 0x12676D88EF7, 0x1EBF, 0x26FA07075B8E, 0x6B8BFE1CE320F31, 0xEA87E7133A9570, 0x0B, 0x33BEA3F1A0CC74AD, 0x7D0E063B84D, 0x1217, 0x61AF912120, 0xE5B12CD, 0x1E}, }, { []byte{0x23, 0xFE, 0xE6, 0xE3, 0x2F, 0x43, 0xE0, 0x65, 0xBD, 0xCA, 0xD1, 0xD8, 0x44, 0x1A, 0x37, 0x2C, 0xF8, 0xB3, 0x17, 0x83, 0x0E, 0x12, 0xDB, 0x23, 0x90, 0x83, 0x9C, 0xBF, 0x7D, 0x16, 0x5E, 0x28, 0xCA, 0x6E, 0x86, 0xE0, 0x09, 0x61, 0x71, 0xE5, 0x00, 0x4D, 0xCE, 0xE1, 0x8A, 0xA8, 0xBD, 0xB1, 0xD5, 0xC4, 0xF2, 0xEF, 0x0B, 0xEE, 0x07, 0x6A, 0x12, 0x2F, 0xB1, 0x2B, 0x5D, 0x0B, 0xC4, 0xD3, 0xE0, 0x9A, 0xC6, 0xDC, 0x25, 0x75, 0x87, 0xC8, 0xB2, 0x7B, 0xAE, 0x6A, 0xC8, 0x3C, 0xF9, 0x2A, 0xC6, 0xD7, 0xBD, 0x6D, 0x88, 0x91, 0x82, 0xAB, 0x01, 0xA0, 0x3C, 0x3E, 0xE2, 0x5B, 0x22, 0xB9, 0xF4, 0x40, 0x13, 0x27}, []uint{46, 17, 6, 2, 47, 18, 58, 46, 1, 3, 45, 56, 64, 21, 53, 35, 1, 38, 57, 31, 7, 49, 8, 60, 31}, []uint64{0x8FFB9B8CBD0, 0x1F032, 0x37, 0x02, 0x72B47611068D, 0x32CF8, 0x2CC5E0C384B6C8E, 0x10839CBF7D16, 0x00, 0x05, 0x1C5194DD0DC0, 0x12C2E3CA009B9D, 0xC315517B63AB89E5, 0x1BC2FB, 0x103B50917D895A, 0x742F134F8, 0x00, 0x1358DB84AE, 0x161F22C9EEB9AB2, 0x79F2558, 0x6D, 0xF7ADB1123055, 0x60, 0x340787DC4B64573, 0x74401327}, }, { []byte{0xD7, 0x29, 0xE8, 0xD8, 0x9D, 0x5F, 0x04, 0x11, 0x02, 0x6B, 0xDE, 0x9E, 0x4F, 0x4B, 0xF9, 0x97, 0x75, 0x01, 0xB6, 0x49, 0xE5, 0x48, 0xFF, 0x34, 0x2A, 0xE6, 0xCF, 0x5D, 0x85, 0x6D, 0xF8, 0x35, 0x8C, 0xEA, 0x04, 0xB3, 0x10, 0x5B, 0x07, 0x80, 0x3B, 0xD5, 0x69, 0x4E, 0xD2, 0xA5, 0x9F, 0x6A, 0x38, 0x77, 0x58, 0x5C, 0x79, 0xEB, 0x03, 0x30, 0x5C, 0x5D, 0x7D, 0x47, 0xD1, 0xD3, 0xAE, 0xC2, 0xE8, 0xB5, 0x69, 0x35, 0x58, 0xD5, 0xC2, 0x91, 0x80, 0x4E, 0x1B, 0x87, 0x92, 0xB2, 0x60, 0x69, 0x02, 0x6F, 0x47, 0x1B, 0x89, 0x14, 0x7E, 0x4F, 0xE4, 0xF9, 0xF0, 0x4D, 0xBD, 0x76, 0x72, 0x36, 0xF3, 0xD8, 0xB8, 0x4D}, []uint{43, 23, 21, 42, 26, 28, 54, 30, 49, 8, 33, 11, 25, 35, 39, 38, 21, 37, 62, 7, 60, 57, 36, 15}, []uint64{0x6B94F46C4EA, 0x7C1044, 0x135EF, 0x13C9E97F32E, 0x3A80DB2, 0x4F2A47F, 0x26855CD9EBB0AD, 0x2FC1AC67, 0xA04B3105B078, 0x03, 0x17AAD29DA, 0x2A5, 0x13ED470, 0x77585C79E, 0x581982E2EB, 0x3A8FA3A75D, 0x10BA2D, 0xB49AAC6AE, 0x523009C370F2564, 0x60, 0x69026F471B89147, 0x1C9FC9F3E09B7AE, 0xCE46DE7B1, 0x384D}, }, { []byte{0x76, 0x2E, 0x87, 0xCE, 0x9D, 0x1C, 0xF7, 0x87, 0xD8, 0x0E, 0xD4, 0x6B, 0x3D, 0x01, 0x84, 0x6C, 0xDE, 0xF7, 0x72, 0xC4, 0xCC, 0xAE, 0xC4, 0xF4, 0x35, 0xBD, 0xDC, 0xA5, 0x69, 0x4F, 0xFF, 0x98, 0x7D, 0x30, 0xBE, 0x40, 0xE7, 0x39, 0xF6, 0xFD, 0x52, 0x19, 0xD9, 0x51, 0xB4, 0x04, 0x22, 0x5C, 0x93, 0x07, 0x7D, 0xB9, 0xF0, 0x5D, 0x53, 0x67, 0x6E, 0xAA, 0xCF, 0x28, 0x16, 0x14, 0x2C, 0x28, 0x5A, 0xB9, 0x20, 0xD3, 0x8C, 0x42, 0xFC, 0x6D, 0xE5, 0x68, 0x47, 0x84, 0xBF, 0x4D, 0x9C, 0x55, 0x62, 0x56, 0x10, 0xAE, 0xFC, 0x1E, 0x91, 0x8B, 0x52, 0x52, 0x49, 0x25, 0x3C, 0x6F, 0xC0, 0x59, 0x59, 0x2D, 0x80, 0x43}, []uint{42, 51, 40, 8, 22, 55, 9, 12, 60, 53, 35, 48, 31, 50, 34, 7, 7, 53, 55, 41, 35, 32, 2, 18}, []uint64{0x1D8BA1F3A74, 0x39EF0FB01DA8D, 0x67A0308D9B, 0xDE, 0x3B9626, 0x32BB13D0D6F772, 0x12B, 0x4A7, 0xFFCC3E985F20739, 0x19F6FD5219D951, 0x5A02112E4, 0x983BEDCF82EA, 0x4D9DBAAB, 0xF2816142C285, 0x2AE4834E3, 0x08, 0x2F, 0x18DBCAD08F097E, 0x4D9C55625610AE, 0x1F83D2316A4, 0x5249253C6, 0xFC059592, 0x03, 0x18043}, }, { []byte{0x33, 0xC2, 0xC3, 0xBC, 0x9D, 0x2A, 0x36, 0xB4, 0x92, 0x36, 0x02, 0x93, 0x54, 0xB9, 0x86, 0x32, 0xC1, 0x0C, 0x75, 0xC4, 0x3B, 0xE4, 0x0A, 0x3F, 0xDF, 0x4E, 0xF6, 0x05, 0x4F, 0x30, 0x19, 0xA6, 0xE9, 0xE6, 0x55, 0xAF, 0xE8, 0xC4, 0x3F, 0xFF, 0xE3, 0x40, 0xC1, 0xA2, 0xE1, 0x05, 0xD7, 0x77, 0x82, 0xD5, 0xF9, 0xA6, 0x0F, 0x54, 0xED, 0x96, 0xA0, 0x68, 0xEC, 0xAE, 0x57, 0xE3, 0x6A, 0xD2, 0xCE, 0x18, 0x9A, 0xC2, 0x5E, 0x10, 0x3C, 0x21, 0x5C, 0x38, 0xA9, 0xC4, 0x82, 0x76, 0xF9, 0xA9, 0x9B, 0x33, 0x43, 0x40, 0x61, 0xDD, 0x0D, 0x83, 0x9E, 0xDE, 0x08, 0x4C, 0x13, 0x33, 0x82, 0x6A, 0xF4, 0xAB, 0x61, 0x1C}, []uint{28, 60, 58, 5, 41, 56, 29, 27, 38, 2, 28, 51, 3, 63, 33, 57, 36, 61, 22, 1, 62, 26, 13}, []uint64{0x33C2C3B, 0xC9D2A36B4923602, 0x24D52E618CB0431, 0x1A, 0x1C43BE40A3F, 0xDF4EF6054F3019, 0x14DD3CCA, 0x5AFE8C4, 0xFFFF8D030, 0x01, 0xA2E105D, 0x3BBC16AFCD307, 0x05, 0x29DB2D40D1D95CAF, 0x18DAB4B38, 0xC4D612F081E10A, 0xE1C54E241, 0x76F9A99B3343406, 0x77436, 0x00, 0x73DBC1098266704, 0x357A55B, 0x11C}, }, { []byte{0xCB, 0x0A, 0x64, 0xC1, 0xEF, 0xEC, 0x67, 0x09, 0xE1, 0x9A, 0x2A, 0xC2, 0xC5, 0xD9, 0xC7, 0x3D, 0x2A, 0x49, 0x3E, 0xF4, 0x30, 0xC9, 0x47, 0x2E, 0xEC, 0xAA, 0x46, 0xDA, 0x31, 0x62, 0x27, 0x4F, 0xAD, 0x4C, 0x50, 0xCD, 0x83, 0x51, 0x37, 0x09, 0x8B, 0xC7, 0x6D, 0x62, 0xFE, 0xC3, 0xE9, 0x91, 0xE5, 0xE8, 0x4D, 0x11, 0x1B, 0xDE, 0x03, 0x23, 0xAA, 0x1E, 0x65, 0xAD, 0x06, 0x23, 0x28, 0xD2, 0xDF, 0x59, 0x47, 0x52, 0xF2, 0x3F, 0xC7, 0x68, 0x50, 0x20, 0xF3, 0x2A, 0xC0, 0xFB, 0xBB, 0xC0, 0xAD, 0x26, 0xA6, 0x75, 0x19, 0x1B, 0xD8, 0x1F, 0xF9, 0xFD, 0x33, 0x10, 0x2C, 0x15, 0x80, 0xDC, 0xA7, 0xF6, 0xF4, 0x50}, []uint{21, 51, 60, 7, 33, 20, 14, 36, 57, 10, 51, 3, 17, 50, 55, 3, 14, 7, 35, 45, 12, 43, 50, 51, 28, 27}, []uint64{0x19614C, 0x4C1EFEC6709E1, 0x9A2AC2C5D9C73D2, 0x52, 0x93EF430C, 0x9472E, 0x3B2A, 0x91B68C588, 0x13A7D6A62866C1A, 0x226, 0x7098BC76D62FE, 0x06, 0x3E99, 0x797A134446F7, 0x40647543CCB5A0, 0x06, 0x8CA, 0x1A, 0x2DF594752, 0x1E47F8ED0A04, 0x1E6, 0x2AC0FBBBC0A, 0x349A99D4646F6, 0x3FF3FA662058, 0x2B01B94, 0x7F6F450}, }, { []byte{0x56, 0x6B, 0xDA, 0x9E, 0xD9, 0x04, 0x9A, 0xE7, 0x5E, 0x85, 0x25, 0x0B, 0x1D, 0xEF, 0xB8, 0x65, 0x6F, 0xFF, 0xE5, 0x6F, 0x02, 0xA8, 0xE2, 0x9B, 0x18, 0xC2, 0x11, 0x8A, 0x7E, 0xB5, 0xDF, 0x72, 0x44, 0x0C, 0xC7, 0x85, 0x43, 0xC5, 0x75, 0x3A, 0x2B, 0x1F, 0xA5, 0x75, 0x66, 0x42, 0x15, 0x03, 0xB3, 0x2F, 0x90, 0xCB, 0x2B, 0x56, 0x8E, 0x2E, 0xB1, 0x98, 0xD0, 0x5D, 0x53, 0x8D, 0x7C, 0xF8, 0x0E, 0x07, 0x98, 0x60, 0x4E, 0x8D, 0x69, 0xF9, 0x2E, 0xD7, 0x9A, 0xE2, 0x4D, 0x37, 0x49, 0xB9, 0x59, 0x5D, 0x2D, 0xC2, 0x7E, 0x50, 0x7B, 0x97, 0x4F, 0x06, 0x2B, 0xBC, 0xCB, 0x10, 0x3E, 0x0E, 0xD3, 0xF8, 0x7E, 0x78}, []uint{38, 55, 32, 34, 58, 58, 53, 8, 29, 19, 37, 46, 7, 55, 39, 44, 24, 5, 5, 22, 19, 11, 49, 40, 13}, []uint64{0x159AF6A7B6, 0x20935CEBD0A4A1, 0x63BDF70C, 0x2B7FFF2B7, 0x20551C536318423, 0x53F5AEFB922066, 0x78543C5753A2B, 0x1F, 0x14AEACC8, 0x21503, 0x1665F21965, 0x1AB471758CC6, 0x41, 0x3AA71AF9F01C0F, 0x18604E8D69, 0xF92ED79AE24, 0xD3749B, 0x12, 0x16, 0x15D2DC, 0x13F28, 0x1EE, 0xBA78315DE658, 0x81F0769FC3, 0x1E78}, }, { []byte{0x52, 0xEE, 0x85, 0xDF, 0x00, 0xC1, 0xE3, 0x65, 0x76, 0x46, 0x99, 0x52, 0xDC, 0xA5, 0x26, 0x5C, 0x31, 0x62, 0xEB, 0xC2, 0xCD, 0xC7, 0x27, 0x12, 0xE4, 0xFC, 0xC5, 0x56, 0xB5, 0xDB, 0x87, 0x39, 0x94, 0xFB, 0x3D, 0x31, 0x24, 0xB7, 0x16, 0x4D, 0x6E, 0x51, 0x8E, 0x47, 0x8E, 0xFF, 0xC0, 0x58, 0x09, 0xC3, 0xE7, 0xCC, 0x5C, 0xA8, 0x82, 0x0F, 0xE2, 0x4D, 0xD2, 0x6D, 0xBF, 0x9B, 0x3D, 0x28, 0xD6, 0x65, 0x6D, 0x0A, 0x05, 0x1B, 0xFA, 0x66, 0x9C, 0xF6, 0x15, 0xCE, 0x50, 0xE1, 0x21, 0x90, 0x9B, 0xA0, 0xDE, 0xDB, 0x76, 0x7C, 0xB6, 0x2D, 0x30, 0xEB, 0xCD, 0x74, 0xE5, 0x19, 0x18, 0xC0, 0x7D, 0x43, 0xA3, 0x61}, []uint{33, 22, 19, 36, 45, 49, 18, 64, 5, 22, 40, 5, 2, 47, 9, 13, 9, 54, 55, 11, 32, 15, 22, 55, 41, 37, 24, 7, 9}, []uint64{0xA5DD0BBE, 0x60F1, 0x595D9, 0x1A654B729, 0x932E18B175E, 0x2CDC72712E4F, 0x33155, 0xAD76E1CE653ECF4C, 0x09, 0x96E2C, 0x9ADCA31C8F, 0x03, 0x02, 0x7FE02C04E1F3, 0x1CC, 0xB95, 0x20, 0x20FE24DD26DBF9, 0x59E946B32B6850, 0x146, 0xFE99A73D, 0x42B9, 0x328709, 0x6426E837B6DD9, 0x1E5B169875E, 0xD74E51918, 0xC07D43, 0x51, 0x161}, }, { []byte{0xB0, 0x67, 0x0E, 0x66, 0x77, 0x4D, 0x4E, 0xDB, 0xEB, 0xDC, 0x05, 0x3B, 0xAA, 0xBB, 0xE8, 0x71, 0x59, 0xD4, 0x71, 0x53, 0xBE, 0xF4, 0x78, 0x2A, 0xB8, 0x9F, 0x09, 0xBB, 0x18, 0x2D, 0x89, 0xD7, 0xDF, 0x15, 0xB9, 0xD6, 0x6D, 0x90, 0x3F, 0x2B, 0xBF, 0xF7, 0xC7, 0x41, 0x1D, 0xCA, 0xAB, 0x52, 0x41, 0x21, 0x6F, 0xB1, 0xF1, 0x2F, 0xCD, 0xC8, 0x85, 0xC3, 0xD7, 0x80, 0x82, 0xFB, 0x86, 0x14, 0x3E, 0x34, 0x95, 0x3E, 0x82, 0xE2, 0x14, 0x51, 0x93, 0xFE, 0xEE, 0x0A, 0xF2, 0xFE, 0xDE, 0x97, 0xB7, 0xEF, 0x1F, 0x95, 0x5D, 0x8F, 0xE8, 0x59, 0xC9, 0x5E, 0x9B, 0x9D, 0x35, 0x0C, 0x84, 0x54, 0x7D, 0x7D, 0x30, 0x42}, []uint{1, 13, 4, 42, 5, 62, 28, 12, 37, 22, 51, 1, 36, 54, 18, 39, 13, 57, 64, 24, 56, 44, 24, 63, 30}, []uint64{0x01, 0xC19, 0x0C, 0xE66774D4ED, 0x17, 0x35EE029DD55DF438, 0xACEA38A, 0x9DF, 0xF4782AB89, 0x3C26EC, 0x305B13AFBE2B7, 0x00, 0x759B640FC, 0x2BBFF7C7411DCA, 0x2AD49, 0x242DF63E2, 0xBF3, 0xE442E1EBC0417D, 0xC30A1F1A4A9F4171, 0xA28C9, 0xFF7705797F6F4B, 0xDBF78FCAAEC, 0x7F42CE, 0x257A6E74D4321151, 0x3D7D3042}, }, { []byte{0xD8, 0x92, 0xDB, 0xF2, 0x33, 0xA4, 0x8B, 0x06, 0xD6, 0xC5, 0xBE, 0x2D, 0x6B, 0x2B, 0x82, 0x33, 0x75, 0xA7, 0xD4, 0x36, 0x2F, 0x46, 0x81, 0xE1, 0xC7, 0xBB, 0xDC, 0xF9, 0x1C, 0x93, 0xF8, 0xEB, 0xFA, 0x14, 0xF3, 0xD2, 0xCB, 0xD7, 0x70, 0x24, 0xAA, 0x92, 0xE5, 0xB3, 0x14, 0x5F, 0x18, 0x14, 0xEC, 0xC3, 0x5B, 0xF0, 0x33, 0xE7, 0xF6, 0xA7, 0x2D, 0x0F, 0xF7, 0x0A, 0x84, 0xD1, 0x87, 0xEF, 0xDD, 0xCD, 0xDC, 0xA8, 0xA1, 0xEF, 0x18, 0x6F, 0xDB, 0x05, 0x79, 0xD6, 0xF9, 0x33, 0x89, 0x9A, 0x57, 0xB7, 0xAC, 0xFE, 0x1C, 0x49, 0xA5, 0x6B, 0x5D, 0x15, 0x19, 0x1F, 0x74, 0x35, 0x87, 0xB3, 0xDD, 0xF6, 0x91, 0x59}, []uint{59, 22, 40, 1, 33, 56, 30, 30, 20, 23, 23, 64, 4, 27, 7, 23, 11, 33, 13, 43, 20, 8, 21, 55, 56, 64, 14}, []uint64{0x6C496DF919D2458, 0xDAD8B, 0x7C5AD65704, 0x00, 0x19BAD3EA1, 0xB17A340F0E3DDE, 0x39F23927, 0x3C75FD0A, 0x79E96, 0x2F5DC0, 0x495525, 0xCB6628BE3029D986, 0x0B, 0x3F033E7, 0x7B, 0x29CB43, 0x7EE, 0x2A13461F, 0x17EE, 0x73772A287BC, 0x61BF6, 0xC1, 0xBCEB7, 0x64CE26695EDEB3, 0xF8712695AD7454, 0x647DD0D61ECF77DA, 0x1159}, }, { []byte{0xEE, 0xDC, 0x02, 0xB6, 0x64, 0xD5, 0x98, 0xBA, 0x54, 0x05, 0x83, 0x4E, 0xB1, 0xC6, 0x5E, 0x02, 0x6F, 0x12, 0x3A, 0xC4, 0xD4, 0x99, 0xF8, 0xF4, 0x4E, 0xC5, 0x5F, 0x69, 0xB9, 0xEE, 0xFF, 0xB0, 0x5A, 0x10, 0x69, 0xEF, 0x95, 0x82, 0xA6, 0x51, 0xAC, 0x06, 0x46, 0x6A, 0x69, 0x80, 0x07, 0x5A, 0xDB, 0x0B, 0x58, 0x49, 0xD3, 0x9B, 0xD6, 0x66, 0xFC, 0x14, 0x05, 0x58, 0x46, 0x98, 0x16, 0xC0, 0x3E, 0x50, 0xDB, 0xD7, 0x68, 0xC1, 0xFE, 0x16, 0xA8, 0xE6, 0x80, 0x21, 0xBA, 0xC1, 0x89, 0xB7, 0xD3, 0xCF, 0xDF, 0x3E, 0x5E, 0xB0, 0x76, 0x25, 0xB0, 0xB8, 0x65, 0xA1, 0x57, 0x35, 0x2B, 0x79, 0x35, 0x23, 0x70, 0x7A}, []uint{19, 14, 28, 59, 53, 55, 20, 4, 1, 40, 36, 2, 42, 20, 60, 61, 59, 46, 62, 23, 50, 4, 42}, []uint64{0x776E0, 0x56C, 0xC9AB317, 0x25405834EB1C65E, 0x4DE247589A93, 0x1F8F44EC55F69B, 0x9EEFF, 0x0B, 0x00, 0xB420D3DF2, 0xB054CA358, 0x00, 0xC8CD4D3000, 0xEB5B6, 0x16B093A737ACCDF, 0x105015611A605B00, 0x7CA1B7AED183FC2, 0x354734010DD6, 0x3136FA79FBE7CBD, 0x307625, 0x2C2E196855CD4, 0x0A, 0x3793523707A}, }, { []byte{0x26, 0x44, 0x9D, 0xFF, 0x6D, 0x96, 0x22, 0x0A, 0xD1, 0xF2, 0xE7, 0x81, 0xD8, 0xEC, 0x90, 0xFD, 0x74, 0x52, 0x63, 0x4A, 0x3C, 0x34, 0xDB, 0x1A, 0xA8, 0xDF, 0xA5, 0x62, 0x34, 0x57, 0x32, 0x2C, 0x53, 0xEC, 0xDF, 0x03, 0xFC, 0xE0, 0x86, 0x03, 0x24, 0xCD, 0x44, 0x36, 0xDF, 0xE2, 0x2F, 0x55, 0x25, 0xD6, 0x27, 0xF3, 0x2E, 0xDB, 0x38, 0x31, 0x5D, 0xAC, 0x2C, 0x28, 0x05, 0x33, 0xA2, 0xFB, 0x0D, 0x7C, 0x02, 0x1B, 0x8A, 0xD4, 0xDF, 0xFC, 0x02, 0x69, 0xC4, 0x2C, 0x65, 0x6F, 0x8C, 0xA4, 0x2F, 0x19, 0x04, 0xBE, 0xC5, 0x0F, 0x8C, 0xF0, 0xB1, 0x8A, 0x2E, 0x58, 0x96, 0xC3, 0x87, 0x1F, 0x89, 0x4F, 0xA9, 0x44}, []uint{37, 50, 48, 42, 39, 50, 30, 29, 11, 10, 17, 20, 29, 52, 50, 17, 27, 47, 16, 16, 25, 61, 28, 8, 29, 12}, []uint64{0x4C893BFED, 0x2CB110568F973, 0xC0EC76487EBA, 0xA4C6947869, 0x5B1AA8DFA5, 0x188D15CC8B14F, 0x2CDF03FC, 0x1C10C064, 0x4CD, 0x110, 0x1B6FF, 0x117AA, 0x125D627F, 0x32EDB38315DAC, 0xB0A014CE8BEC, 0x6BE0, 0x86E2B5, 0x1BFF804D3885, 0x8CAD, 0xF194, 0x10BC641, 0x5F6287C67858C51, 0x72C4B61, 0xC3, 0x11F894FA, 0x944}, }, { []byte{0x93, 0xC5, 0x74, 0xE2, 0x73, 0x08, 0xB2, 0xDD, 0xB8, 0xD7, 0xD5, 0xC3, 0x88, 0x2F, 0x98, 0xA2, 0xB8, 0x42, 0x98, 0xE2, 0xFD, 0xC6, 0x7F, 0x6C, 0x47, 0xE6, 0xC5, 0x9D, 0x30, 0x31, 0x40, 0x3C, 0x63, 0xE7, 0xD1, 0x20, 0x1E, 0x85, 0xF9, 0x40, 0x98, 0xE8, 0x9F, 0x31, 0xDF, 0x9E, 0x14, 0xEE, 0xB5, 0x62, 0x56, 0x7F, 0x88, 0x3F, 0xE1, 0xD1, 0xEB, 0xAC, 0x09, 0xCD, 0x71, 0xF8, 0x23, 0x07, 0xDA, 0x37, 0x32, 0x37, 0xDE, 0x65, 0x21, 0x72, 0x9B, 0x89, 0x9B, 0xEC, 0x35, 0xBC, 0x6B, 0xB8, 0x20, 0x00, 0xF6, 0xA9, 0x06, 0xDC, 0xAC, 0xE8, 0xC3, 0x52, 0x89, 0x20, 0x74, 0xC9, 0xB3, 0xCC, 0x72, 0x45, 0x0E, 0x76}, []uint{49, 42, 47, 16, 27, 33, 16, 39, 45, 23, 47, 52, 64, 20, 17, 63, 30, 50, 23, 54, 31, 12}, []uint64{0x1278AE9C4E611, 0x196EDC6BEAE, 0xE20BE628AE1, 0xA63, 0x45FB8CF, 0x1DB11F9B1, 0x674C, 0x628078C7C, 0x1F44807A17E5, 0x131D1, 0x1F31DF9E14EE, 0xB562567F883FE, 0x1D1EBAC09CD71F82, 0x307DA, 0x6E64, 0x37DE6521729B899B, 0x3B0D6F1A, 0x3B82000F6A906, 0x6E5674, 0x186A51240E9936, 0x3CC72450, 0xE76}, }, { []byte{0xCA, 0x4E, 0x83, 0x60, 0x1A, 0xEF, 0xAC, 0x61, 0x4C, 0x22, 0x4A, 0xE3, 0xFC, 0xEF, 0x32, 0x2A, 0xDB, 0x52, 0x73, 0xC3, 0xEB, 0xA6, 0xF0, 0xAE, 0x35, 0x1D, 0x0C, 0xDE, 0x1D, 0x38, 0x41, 0x75, 0x4B, 0xF3, 0x62, 0x98, 0x73, 0x07, 0xB9, 0x58, 0x83, 0x38, 0x29, 0xE3, 0xCD, 0x38, 0xBA, 0xF0, 0x59, 0xDC, 0x74, 0xE4, 0xE4, 0x17, 0x6C, 0x83, 0xBF, 0x52, 0xDB, 0xEA, 0xF5, 0xFA, 0xBF, 0x1D, 0xBA, 0x13, 0xED, 0xDA, 0x93, 0x6E, 0xCB, 0x89, 0x1E, 0x83, 0x72, 0xC5, 0x28, 0x3A, 0x5F, 0x8D, 0xAF, 0xDB, 0xDD, 0x6E, 0xA9, 0xD2, 0x76, 0x4B, 0x7F, 0x4A, 0xD8, 0x0E, 0xBF, 0xE0, 0xC6, 0x5F, 0xA0, 0x77, 0x7A, 0x2B}, []uint{57, 31, 47, 37, 29, 27, 49, 3, 52, 31, 34, 41, 35, 37, 47, 59, 31, 46, 10, 7, 14, 54, 22}, []uint64{0x1949D06C035DF58, 0x614C224A, 0x71FE7799156D, 0x15273C3EBA, 0xDE15C6A, 0x1D0CDE1, 0x1A7082EA97E6C, 0x02, 0x987307B958833, 0x414F1E69, 0x3175E0B3B, 0x11D393905DB, 0x1077EA5B7, 0x1ABD7EAFC7, 0x37427DBB526D, 0x6CB891E8372C528, 0x1D2FC6D7, 0x3B7BADD53A4E, 0x325, 0x5F, 0x34AD, 0x203AFF83197E81, 0x377A2B}, }, { []byte{0x2C, 0x77, 0x59, 0x98, 0x44, 0xE0, 0xD5, 0x78, 0x5F, 0xFE, 0xD1, 0x44, 0xAD, 0xCC, 0x78, 0x46, 0x69, 0x3B, 0xD5, 0xC2, 0x03, 0xE1, 0x24, 0x54, 0x8C, 0xAB, 0x06, 0x61, 0x78, 0x78, 0x89, 0x42, 0x8B, 0x1C, 0x9E, 0xA1, 0x13, 0xC8, 0x09, 0xAB, 0x7E, 0xD6, 0xC6, 0xB2, 0xAF, 0x4D, 0x1D, 0xB4, 0x85, 0xB5, 0x5D, 0x39, 0x23, 0x8E, 0x67, 0x8D, 0x48, 0xA1, 0x1B, 0x42, 0xDD, 0xBD, 0xCB, 0x53, 0xA8, 0x20, 0x50, 0xF7, 0x44, 0xE7, 0xBC, 0x7A, 0x85, 0x09, 0x71, 0x04, 0xCF, 0x81, 0xCA, 0xB4, 0x10, 0xF2, 0xBF, 0xC7, 0x7C, 0x05, 0xC3, 0x62, 0x19, 0x79, 0x04, 0x7F, 0xF8, 0x54, 0x85, 0x0E, 0x35, 0xE4, 0x64, 0x4C}, []uint{35, 33, 39, 14, 2, 40, 63, 64, 53, 56, 47, 42, 51, 12, 9, 43, 58, 55, 32, 52}, []uint64{0x163BACCC2, 0x4E0D5785, 0x7FF68A256E, 0x18F0, 0x02, 0x3349DEAE10, 0xF84915232AC1985, 0xE1E2250A2C727A84, 0x9E404D5BF6B63, 0x5957A68EDA42DA, 0x574E48E399E3, 0x148A11B42DD, 0x5EE5A9D410287, 0xBA2, 0xE7, 0x5E3D4284B88, 0x99F03956821E57, 0x7C77C05C362197, 0x9047FF85, 0x4850E35E4644C}, }, { []byte{0x2F, 0x1E, 0xB8, 0x50, 0xC1, 0xF6, 0xD4, 0xD4, 0x33, 0xD8, 0x40, 0xC9, 0x5E, 0xB5, 0x29, 0x9E, 0x60, 0x65, 0xB4, 0xD2, 0x68, 0x4D, 0x3F, 0x7E, 0x0D, 0xCB, 0xE6, 0x9E, 0x0D, 0x2A, 0x4C, 0xF5, 0xD4, 0x0D, 0x20, 0x36, 0x17, 0xCB, 0xCD, 0x2A, 0xA4, 0xBE, 0x08, 0x48, 0x7C, 0xFE, 0x77, 0x28, 0xDA, 0xC0, 0xFF, 0xAC, 0x48, 0xF5, 0xCD, 0x34, 0xCD, 0x1D, 0x6E, 0x13, 0x19, 0xDD, 0x0D, 0xF1, 0x78, 0x41, 0x59, 0x87, 0xDB, 0x13, 0x44, 0xC1, 0xE0, 0xB7, 0x9C, 0x18, 0xF9, 0x4E, 0x09, 0x53, 0x99, 0x95, 0x9D, 0x7C, 0x0E, 0xDB, 0xF5, 0x7D, 0x55, 0x20, 0x19, 0x6A, 0x39, 0x30, 0xC8, 0x6E, 0xE7, 0x0E, 0xCA, 0x02}, []uint{15, 11, 7, 40, 53, 47, 60, 55, 29, 8, 29, 25, 53, 33, 45, 9, 30, 17, 30, 11, 7, 37, 35, 43, 25, 19, 8, 19}, []uint64{0x178F, 0x2E1, 0x21, 0x83EDA9A867, 0x16103257AD4A67, 0x4C0CB69A4D09, 0xA7EFC1B97CD3C1A, 0x2A4CF5D40D2036, 0x2F979A5, 0x54, 0x12F82121, 0x1E7F3B9, 0x8DAC0FFAC48F5, 0x19A699A3A, 0x1B84C677437C, 0xBC, 0x82B30FB, 0xC4D1, 0xC1E0B79, 0x60C, 0x3E, 0xA704A9CCC, 0x5675F03B6, 0x7EAFAAA4032, 0x1A8E4C3, 0x10DDC, 0xE1, 0x6CA02}, }, { []byte{0x52, 0x18, 0x09, 0x9C, 0xE3, 0xF6, 0x3F, 0xA5, 0xED, 0xF7, 0x0E, 0xB9, 0x49, 0x47, 0x88, 0x47, 0x62, 0x11, 0x91, 0x9A, 0xDD, 0x33, 0x2C, 0xF9, 0x77, 0x0C, 0xFE, 0x5D, 0xBC, 0x11, 0x25, 0x0C, 0x57, 0x41, 0x2E, 0x26, 0x6A, 0x84, 0xF4, 0x6B, 0x74, 0x45, 0x74, 0x06, 0x1F, 0xAF, 0x0E, 0x4D, 0x5A, 0xBF, 0x4E, 0x02, 0x6E, 0xF5, 0x7B, 0xA4, 0xCD, 0x5F, 0xFC, 0x9B, 0xA3, 0x7D, 0x8D, 0x35, 0x11, 0xEE, 0x63, 0x6B, 0xE1, 0xC8, 0x51, 0xDB, 0x79, 0x94, 0x42, 0x4D, 0xEA, 0xAE, 0xBD, 0xC0, 0x24, 0x0C, 0x28, 0x3B, 0xCB, 0x2D, 0x67, 0x10, 0x38, 0x99, 0x8F, 0xFA, 0x9D, 0x76, 0xC5, 0xD9, 0x85, 0x0E, 0xDA, 0x45}, []uint{33, 3, 51, 28, 16, 63, 3, 16, 33, 58, 33, 12, 64, 41, 13, 11, 52, 27, 8, 15, 1, 20, 30, 61, 34, 39, 35}, []uint64{0xA4301339, 0x06, 0x1FB1FD2F6FB87, 0x5CA4A3C, 0x423B, 0x846466B74CCB3E5, 0x06, 0xE19F, 0x1976F0449, 0x10C57412E266A84, 0x1E8D6E88A, 0xE80, 0xC3F5E1C9AB57E9C0, 0x9BBD5EE933, 0xAFF, 0x726, 0xE8DF634D447B9, 0x46D7C39, 0x0A, 0x1DB7, 0x01, 0x32884, 0x26F5575E, 0x1C0240C283BCB2D6, 0x1C40E2663, 0x7F53AED8BB, 0x1850EDA45}, }, { []byte{0xD6, 0x66, 0x64, 0xE0, 0x81, 0x98, 0x56, 0xB5, 0xF4, 0xA8, 0x1E, 0x12, 0x6F, 0xB0, 0x17, 0xE7, 0x91, 0xF9, 0x6C, 0x82, 0x9F, 0x22, 0xE2, 0x15, 0x5A, 0xCE, 0x73, 0x71, 0x29, 0x69, 0x8F, 0x94, 0xC7, 0xB3, 0x4F, 0x1B, 0x16, 0x28, 0xE7, 0xD6, 0x7E, 0x5F, 0xDE, 0xB6, 0x93, 0xA8, 0xDB, 0x9B, 0x44, 0x19, 0xDC, 0xE7, 0x57, 0x69, 0x4F, 0xA9, 0x33, 0x4C, 0x16, 0x5A, 0x91, 0xE4, 0x69, 0x33, 0x34, 0x93, 0x92, 0xE0, 0x00, 0xA2, 0xF2, 0xFB, 0xA9, 0xE0, 0xB5, 0xE0, 0xC0, 0x9D, 0x39, 0x52, 0xD6, 0xA4, 0x45, 0xB3, 0x9E, 0x96, 0x51, 0x44, 0xAD, 0xF0, 0x70, 0x51, 0x7D, 0xA7, 0x9F, 0xBB, 0x20, 0x41, 0x0C, 0x94}, []uint{49, 14, 13, 57, 39, 20, 12, 63, 47, 53, 9, 52, 41, 9, 24, 60, 44, 16, 50, 21, 42, 36, 29}, []uint64{0x1ACCCC9C10330, 0x2B5A, 0x1F4A, 0x103C24DF602FCF2, 0x1F96C829F2, 0x2E215, 0x5AC, 0x739B894B4C7CA63D, 0x4D3C6C58A39F, 0xB3F2FEF5B49D4, 0xDB, 0x9B4419DCE7576, 0x129F5266982, 0x196, 0xA4791A, 0x4CCD24E4B80028B, 0xCBEEA782D78, 0x3027, 0x13952D6A445B3, 0x13D2CA, 0xA256F83828, 0xBED3CFDD9, 0x410C94}, }, { []byte{0xA1, 0xA6, 0x11, 0xEE, 0xBB, 0x60, 0x43, 0x9A, 0x10, 0xDA, 0x7D, 0xBB, 0x9D, 0xFC, 0x67, 0x7E, 0xE5, 0x57, 0x36, 0x8C, 0xB4, 0x20, 0x6D, 0x5A, 0xD1, 0x61, 0x1F, 0x1B, 0x1F, 0x23, 0x72, 0x26, 0xB1, 0xFF, 0x12, 0x26, 0xBB, 0x6D, 0x2B, 0x7A, 0x7E, 0x15, 0x5A, 0x2F, 0x0E, 0x17, 0xEF, 0x71, 0xCB, 0x1C, 0x18, 0xD0, 0xFE, 0x00, 0x9F, 0xC6, 0x0C, 0xB7, 0x45, 0xED, 0xF7, 0xB9, 0x93, 0xAF, 0xA5, 0x02, 0xB6, 0xFA, 0x8D, 0x7C, 0xF6, 0x2C, 0x36, 0x9A, 0x81, 0xB8, 0xCE, 0x89, 0x63, 0xAD, 0x26, 0x5C, 0x3B, 0x1B, 0xF7, 0xB8, 0xAE, 0xAF, 0x5C, 0x07, 0x47, 0x3C, 0x79, 0x14, 0x0F, 0x18, 0x35, 0xAA, 0x30, 0xCE}, []uint{30, 56, 32, 18, 22, 48, 9, 2, 41, 20, 9, 18, 51, 20, 28, 52, 47, 37, 24, 24, 20, 8, 19, 25, 9, 29, 24, 37, 2, 6, 33}, []uint64{0x2869847B, 0xAED810E684369F, 0x6EE77F19, 0x37EE5, 0x15CDA3, 0x2D081B56B458, 0x8F, 0x02, 0x6C7C8DC89A, 0xC7FC4, 0x113, 0x176DA, 0x2B7A7E155A2F0, 0xE17EF, 0x71CB1C1, 0x8D0FE009FC60C, 0x5BA2F6FBDCC9, 0x1AFA502B6F, 0xA8D7CF, 0x62C369, 0xA81B8, 0xCE, 0x44B1D, 0xD265C3, 0x163, 0xFDEE2BA, 0xBD701D, 0x39E3C8A07, 0x02, 0x0C, 0x35AA30CE}, }, { []byte{0x44, 0x4D, 0xAD, 0xF6, 0xC5, 0x49, 0x84, 0x42, 0x7C, 0x1C, 0x52, 0xAB, 0x5E, 0xB4, 0xB1, 0x05, 0x2A, 0x91, 0xE7, 0xAD, 0x2C, 0x17, 0x8F, 0xCE, 0xB5, 0x0A, 0x3A, 0xAA, 0x05, 0x57, 0x36, 0xFD, 0x18, 0xA4, 0x2F, 0x32, 0x14, 0xAE, 0x60, 0x5D, 0xEE, 0x36, 0xBD, 0x7B, 0x1F, 0x6A, 0xB5, 0x10, 0x26, 0x0A, 0x19, 0xD1, 0x25, 0x53, 0xEA, 0x97, 0xF3, 0x9C, 0xE6, 0x71, 0x1E, 0xA6, 0x33, 0x98, 0x6C, 0x3E, 0xB4, 0xBD, 0x1D, 0x5B, 0xDF, 0xAB, 0xEF, 0x5D, 0xDE, 0x17, 0xB0, 0x62, 0x7D, 0x71, 0x8A, 0x36, 0xF5, 0x5B, 0xD2, 0x92, 0x54, 0xB7, 0xD0, 0x1B, 0xAD, 0x75, 0x69, 0xA0, 0x5A, 0x77, 0xFD, 0xF2, 0x81, 0xF5}, []uint{29, 23, 54, 22, 44, 39, 56, 7, 49, 58, 48, 51, 17, 63, 28, 7, 55, 32, 62, 56}, []uint64{0x889B5BE, 0x6C5498, 0x1109F0714AAD7A, 0x34B105, 0x2A91E7AD2C1, 0x3C7E75A851, 0xD5502AB9B7E8C5, 0x10, 0x17990A57302EF, 0x1C6D7AF63ED56A2, 0x4C1433A24AA, 0x3EA97F39CE671, 0x3D4C, 0x33986C3EB4BD1D5B, 0xDFABEF5, 0x6E, 0x785EC189F5C628, 0xDBD56F4A, 0x1254B7D01BAD7569, 0xA05A77FDF281F5}, }, { []byte{0x0C, 0x0A, 0x46, 0x32, 0x3A, 0x2A, 0x4C, 0xD8, 0x81, 0x7D, 0x88, 0x36, 0xA9, 0x0D, 0xD2, 0xF7, 0x1C, 0x9C, 0xB9, 0xE8, 0x6B, 0x6D, 0x1D, 0xA5, 0x89, 0x16, 0x95, 0x20, 0x42, 0x46, 0x59, 0xD0, 0x4B, 0xEF, 0x6A, 0x1A, 0xD6, 0x92, 0xFF, 0x34, 0x44, 0x7D, 0x2D, 0x61, 0xC6, 0xE1, 0xAD, 0x75, 0x64, 0xDD, 0x00, 0xDA, 0x0F, 0x3E, 0xAB, 0x4D, 0x1B, 0x79, 0x55, 0x02, 0xC8, 0xF6, 0x8C, 0xF0, 0x4F, 0xAD, 0x64, 0x37, 0x08, 0xDC, 0x05, 0x4C, 0xE0, 0x3F, 0xE6, 0x0E, 0x6A, 0xC9, 0x5B, 0x82, 0x8B, 0x54, 0x2B, 0x28, 0x0F, 0xE5, 0x41, 0x4A, 0x53, 0x53, 0x81, 0x9C, 0x22, 0x75, 0xD4, 0x2A, 0x9F, 0x03, 0x14, 0x2D}, []uint{7, 25, 64, 47, 3, 22, 11, 18, 56, 12, 64, 63, 8, 35, 40, 12, 31, 18, 64, 51, 58, 22, 64, 5}, []uint64{0x06, 0xA4632, 0x3A2A4CD8817D8836, 0x5486E97B8E4E, 0x02, 0x39E86B, 0x368, 0x3B4B1, 0x22D2A40848CB3A, 0x97, 0xDED435AD25FE6888, 0x7D2D61C6E1AD7564, 0xDD, 0x6D079F5, 0x5A68DBCAA8, 0x164, 0x3DA33C13, 0x3AD64, 0x3708DC054CE03FE6, 0x73564ADC145A, 0x2856501FCA8294A, 0x1A9C0C, 0xE113AEA154F818A1, 0x0D}, }, { []byte{0xB0, 0x2B, 0x72, 0xA2, 0xB5, 0xBA, 0x1F, 0xA0, 0x87, 0xEF, 0xEE, 0xE5, 0x01, 0x7F, 0x46, 0x66, 0x05, 0x7E, 0xBD, 0x0B, 0x06, 0x43, 0x3D, 0xA2, 0xCC, 0x6B, 0xA1, 0xB5, 0xBF, 0x91, 0xA7, 0x6C, 0x44, 0xC7, 0xB7, 0x7A, 0xBE, 0x20, 0xE9, 0xB1, 0xA7, 0xF9, 0x58, 0x2E, 0x92, 0x5F, 0xA2, 0xD5, 0x10, 0x98, 0xF9, 0x58, 0x1F, 0x91, 0x84, 0xCE, 0xEC, 0x53, 0x42, 0xE5, 0xBA, 0xD8, 0xC9, 0x3C, 0x5B, 0x4F, 0x7A, 0x8D, 0xC4, 0xFE, 0x6E, 0x56, 0x0A, 0x1A, 0x08, 0x2B, 0xD5, 0xFF, 0x8F, 0x28, 0xAB, 0x6A, 0xB3, 0x6C, 0x8A, 0x0F, 0x2B, 0xA5, 0x73, 0xED, 0xC7, 0x2C, 0xB9, 0xB7, 0xFD, 0x9C, 0xCA, 0xE7, 0x4E, 0xBA}, []uint{51, 62, 30, 50, 54, 45, 5, 36, 27, 34, 30, 27, 60, 20, 44, 43, 45, 5, 5, 12, 9, 25, 18, 50, 13}, []uint64{0x5815B9515ADD0, 0x3F410FDFDDCA02FE, 0x233302BF, 0x17A160C867B45, 0x2635D0DADFC8D3, 0x16C44C7B77AB, 0x1C, 0x41D3634FF, 0x1582E92, 0x17E8B5442, 0x18F9581F, 0x48C2677, 0x629A172DD6C649E, 0x2DA7B, 0xD46E27F372B, 0x286820AF57, 0x1FC79455B559, 0x16, 0x19, 0x141, 0x1CA, 0x1D2B9F6, 0x38E59, 0x1CDBFECE6573A, 0xEBA}, }, { []byte{0x8E, 0xEB, 0xED, 0x77, 0xFC, 0xB9, 0x57, 0xAA, 0xC6, 0xF4, 0xEA, 0xF7, 0x59, 0xA3, 0x3F, 0xC7, 0x98, 0xF2, 0x6A, 0xA1, 0x0C, 0x08, 0xE5, 0x54, 0x8A, 0x69, 0x24, 0xE8, 0xCD, 0xD2, 0x27, 0x74, 0xC6, 0x96, 0x64, 0x1D, 0x00, 0x76, 0x21, 0xA1, 0x4F, 0xE8, 0xCF, 0x42, 0xFD, 0x51, 0x86, 0xD8, 0xBD, 0xA9, 0x28, 0x00, 0x42, 0xE9, 0x4B, 0xCB, 0xF5, 0xCF, 0x20, 0xFA, 0x96, 0x2F, 0x39, 0x86, 0x1B, 0x22, 0x73, 0x15, 0x65, 0x78, 0xFE, 0xB9, 0x12, 0xCD, 0x70, 0x2C, 0x8D, 0xE6, 0x4B, 0x08, 0x3C, 0xBB, 0x62, 0x96, 0xF9, 0xC3, 0x18, 0x29, 0xB6, 0x01, 0xEF, 0x76, 0xB6, 0x10, 0x8D, 0x00, 0x09, 0xC8, 0xBD, 0xC9}, []uint{23, 25, 14, 24, 54, 57, 17, 10, 55, 55, 48, 6, 52, 23, 29, 46, 62, 52, 16, 9, 28, 44, 19, 20, 12}, []uint64{0x4775F6, 0x177FCB9, 0x15EA, 0xB1BD3A, 0x2F759A33FC798F, 0x4D5421811CAA91, 0x9A49, 0xE8, 0x66E913BA634B32, 0x7401D886853FA, 0x33D0BF5461B6, 0x0B, 0xDA9280042E94B, 0x65FAE7, 0x120FA962, 0x3CE6186C89CC, 0x156578FEB912CD70, 0x2C8DE64B083CB, 0xB629, 0xDF, 0x3863053, 0x6C03DEED6C2, 0x8D00, 0x9C8B, 0xDC9}, }, { []byte{0xCF, 0x4B, 0x63, 0xE2, 0x82, 0xA4, 0xA3, 0x18, 0x6B, 0x5B, 0x1E, 0xAA, 0x55, 0x8D, 0xBD, 0x1D, 0xE3, 0xA5, 0xAE, 0x26, 0x41, 0xBA, 0x07, 0xC5, 0x85, 0xA2, 0xB0, 0xCC, 0xA9, 0x90, 0x6B, 0xA4, 0x07, 0xBF, 0xE3, 0x01, 0x1F, 0x0D, 0x73, 0xBD, 0xC4, 0xAB, 0x03, 0xC0, 0xD7, 0xEC, 0x47, 0xCE, 0x21, 0x9C, 0x43, 0x3B, 0x88, 0xD4, 0xA3, 0xDE, 0x49, 0x70, 0x48, 0x47, 0x84, 0x97, 0xD8, 0x03, 0x34, 0x74, 0x26, 0x4B, 0x0E, 0x52, 0x32, 0x18, 0xDF, 0x36, 0xD2, 0x34, 0xA1, 0x9C, 0x04, 0x97, 0x83, 0x10, 0xC2, 0x32, 0xF8, 0x5A, 0xD2, 0xCB, 0xD8, 0x3B, 0x35, 0x58, 0x86, 0x00, 0x89, 0xDE, 0xF5, 0x7C, 0x1A, 0xFA}, []uint{23, 40, 60, 52, 61, 12, 53, 39, 40, 17, 40, 58, 31, 13, 58, 39, 47, 4, 38, 16, 43, 12, 4}, []uint64{0x67A5B1, 0xF14152518C, 0x35AD8F552AC6DE8, 0xEF1D2D71320DD, 0x7C585A2B0CCA99, 0x6B, 0x1480F7FC6023E1, 0x573BDC4AB0, 0x3C0D7EC47C, 0x1C433, 0x8867711A94, 0x1EF24B82423C24B, 0x7600CD1D, 0x132, 0x161CA46431BE6DA, 0x234A19C049, 0x3C18861197C2, 0x0D, 0x1A597B0766, 0xAB10, 0x60089DEF57C, 0x1AF, 0x0A}, }, { []byte{0xC5, 0x28, 0x7C, 0xA6, 0x66, 0xF1, 0xAE, 0xF5, 0xC2, 0x0E, 0xCA, 0x71, 0xCB, 0x22, 0xE0, 0xB5, 0xA6, 0x6E, 0xC9, 0x23, 0xBE, 0xD6, 0x6A, 0x16, 0x8E, 0xC1, 0x00, 0x9B, 0xD7, 0x59, 0xA7, 0x8E, 0x68, 0x41, 0x13, 0x55, 0xAD, 0x6A, 0xC9, 0x49, 0xE1, 0x6A, 0x17, 0xBE, 0x8B, 0xA3, 0xFC, 0x81, 0x3B, 0xFB, 0x88, 0xCB, 0x1C, 0x66, 0x3F, 0x66, 0x28, 0x84, 0xB4, 0xBF, 0xFD, 0xAC, 0x65, 0x7F, 0x80, 0x67, 0x98, 0x32, 0xBF, 0x6E, 0xDC, 0xBD, 0xCD, 0x18, 0x7C, 0xBB, 0x54, 0xF9, 0xBA, 0x66, 0x79, 0x6A, 0x39, 0xC1, 0x55, 0x0E, 0x2C, 0x2B, 0x08, 0x10, 0x7F, 0x0A, 0x8A, 0xFA, 0xE3, 0x24, 0x31, 0x99, 0xFE, 0xAA}, []uint{29, 64, 55, 11, 37, 3, 50, 2, 21, 56, 17, 35, 48, 42, 61, 26, 3, 16, 19, 11, 9, 64, 50, 11, 29, 14, 17}, []uint64{0x18A50F94, 0xCCDE35DEB841D94E, 0x1CB22E0B5A66EC, 0x491, 0x1BED66A168, 0x07, 0x1820137AEB34F, 0x00, 0xE6841, 0x1355AD6AC949E1, 0xD42F, 0x3E8BA3FC8, 0x13BFB88CB1C6, 0x18FD98A212D, 0x5FFED632BFC033C, 0x30657ED, 0x06, 0xDCBD, 0x668C3, 0x72E, 0x1AA, 0x7CDD333CB51CE0AA, 0x21C58561020FE, 0xA8, 0x15F5C648, 0x18CC, 0x1FEAA}, }, { []byte{0x69, 0x50, 0x9D, 0x23, 0xBD, 0xE7, 0x5B, 0x7F, 0x45, 0x9A, 0xD4, 0xD8, 0x62, 0x06, 0xCD, 0x3E, 0x7F, 0x32, 0xB5, 0x41, 0x25, 0x12, 0xD2, 0x13, 0xC9, 0x91, 0x44, 0x49, 0x86, 0x50, 0x8E, 0xCF, 0x38, 0x1E, 0x85, 0x65, 0xCB, 0x68, 0x6A, 0xFF, 0x1E, 0x03, 0x28, 0x0A, 0xB0, 0x93, 0xB6, 0xD5, 0x50, 0x15, 0x04, 0xB1, 0x6C, 0x71, 0xF1, 0xE7, 0xFE, 0xC9, 0x10, 0x89, 0xD6, 0xCE, 0x3F, 0x4F, 0xFF, 0x2F, 0xE8, 0xE7, 0xD1, 0x88, 0x19, 0x74, 0xEF, 0xC4, 0xD8, 0xAA, 0x49, 0x77, 0x09, 0xE9, 0x73, 0x5C, 0x75, 0xCB, 0x2F, 0x97, 0xB2, 0xF7, 0x8A, 0x71, 0x1C, 0xC5, 0x9D, 0x72, 0x16, 0x66, 0x18, 0x39, 0x3F, 0xBF}, []uint{47, 4, 10, 61, 39, 3, 60, 41, 7, 5, 46, 14, 54, 21, 57, 14, 48, 57, 4, 56, 60, 34, 33, 25}, []uint64{0x34A84E91DEF3, 0x0A, 0x36F, 0x1D166B5361881B34, 0x7CFE656A82, 0x02, 0x512D213C9914449, 0x10CA11D9E70, 0x1E, 0x10, 0x2B2E5B4357F8, 0x3C06, 0x14055849DB6AA8, 0x1504B, 0x2D8E3E3CFFD922, 0x44E, 0xB671FA7FF97F, 0x8E7D1881974EFC, 0x04, 0xD8AA497709E973, 0x5C75CB2F97B2F78, 0x29C473167, 0xB90B330C, 0x393FBF}, }, { []byte{0x66, 0x39, 0x3F, 0x83, 0xCF, 0x72, 0x88, 0x33, 0xFB, 0xC8, 0x2F, 0x5D, 0x9E, 0x20, 0xD3, 0xF3, 0x8B, 0x9D, 0xC9, 0xE8, 0xEC, 0xC1, 0x77, 0xD0, 0x76, 0xFF, 0x95, 0x84, 0x0E, 0x97, 0x97, 0x1F, 0x62, 0x6B, 0x24, 0x42, 0x72, 0x39, 0x75, 0x5B, 0x1C, 0x65, 0xA4, 0x91, 0x43, 0xDF, 0xCA, 0x1D, 0x4F, 0x15, 0x64, 0x1E, 0xA5, 0xFC, 0xBF, 0x4B, 0x2D, 0x5D, 0xD9, 0x3F, 0xC8, 0xD9, 0x09, 0x15, 0x81, 0x71, 0xF7, 0x2D, 0x0C, 0xAD, 0xE1, 0x6F, 0x76, 0x92, 0x48, 0x1F, 0xF7, 0x63, 0xC5, 0x4E, 0x9B, 0x0E, 0xB7, 0x1F, 0xE3, 0x9C, 0x71, 0x1D, 0x85, 0xB6, 0x23, 0x48, 0x3D, 0x5B, 0x27, 0x54, 0xD0, 0xE6, 0xFF, 0x66}, []uint{63, 43, 6, 51, 18, 20, 8, 45, 60, 24, 54, 8, 60, 4, 35, 38, 42, 26, 28, 18, 25, 15, 28, 8, 16, 57}, []uint64{0x331C9FC1E7B94419, 0x7EF20BD7678, 0x20, 0x69F9C5CEE4F47, 0x1982E, 0xFA0ED, 0xFF, 0x56103A5E5C7, 0xD89AC9109C8E5D5, 0x6C7196, 0x249143DFCA1D4F, 0x15, 0x641EA5FCBF4B2D5, 0x0D, 0x6C9FE46C8, 0x122B02E3EE, 0x168656F0B7B, 0x2D24903, 0xFEEC78A, 0x274D8, 0xEB71FE, 0x1CE3, 0x88EC2DB, 0x11, 0xA41E, 0x15B2754D0E6FF66}, }, { []byte{0x8F, 0x63, 0xBD, 0x4A, 0x79, 0xCC, 0x5B, 0x8B, 0x94, 0xD1, 0x09, 0xEC, 0xEA, 0x03, 0x58, 0xA1, 0xED, 0x5C, 0x72, 0x41, 0xBE, 0x2E, 0x84, 0x52, 0x1F, 0xE0, 0x20, 0x0F, 0x6E, 0x34, 0x3C, 0xEF, 0xC2, 0xD4, 0x1B, 0x4C, 0x52, 0x99, 0x33, 0x4F, 0x53, 0xB0, 0xD7, 0x54, 0x4B, 0x59, 0x2E, 0xEB, 0x04, 0x59, 0xAE, 0xFF, 0x4E, 0x47, 0xE1, 0x06, 0x8F, 0xB2, 0xF2, 0xB2, 0xB4, 0x73, 0x3B, 0xDA, 0x65, 0xBF, 0x04, 0x74, 0xAB, 0xE0, 0x8C, 0x51, 0x04, 0x7A, 0x68, 0x7D, 0xFE, 0xF1, 0xF1, 0xC6, 0x87, 0xD9, 0x20, 0xEE, 0x9C, 0xD7, 0x05, 0xB7, 0x7F, 0xB2, 0x9E, 0xC7, 0xB7, 0x1E, 0x28, 0x85, 0xE0, 0x86, 0xA8, 0x3C}, []uint{7, 18, 6, 31, 48, 10, 41, 63, 35, 22, 27, 13, 22, 64, 30, 9, 14, 53, 18, 47, 8, 62, 30, 18, 41, 56, 7}, []uint64{0x47, 0x2C77A, 0x25, 0x1E7316E2, 0xE534427B3A80, 0x358, 0x143DAB8E483, 0x3E2E84521FE0200F, 0x371A1E77E, 0x5A836, 0x4C52993, 0x69E, 0x29D86B, 0xAA25AC9775822CD7, 0x1FE9C8FC, 0x41, 0x28FB, 0x5E56568E677B4, 0x32DF8, 0x11D2AF823144, 0x11, 0x3A687DFEF1F1C687, 0x36483BA7, 0xD705, 0x16EFF653D8F, 0x6E3C510BC10D50, 0x3C}, }, { []byte{0x68, 0xBC, 0xC2, 0x6E, 0x0B, 0xE7, 0x1E, 0x5A, 0x9E, 0xE4, 0x64, 0xB1, 0xF7, 0x37, 0xA7, 0xF8, 0x1B, 0x6E, 0xD3, 0x99, 0x2A, 0xE4, 0x42, 0x43, 0xA7, 0x5E, 0xD0, 0x02, 0x1D, 0x64, 0x72, 0x99, 0x26, 0xF5, 0x76, 0xD1, 0xD5, 0x0D, 0x11, 0x30, 0x71, 0x58, 0x4F, 0xD3, 0xAB, 0x73, 0xBB, 0xD0, 0x1C, 0xE9, 0xCA, 0x37, 0x41, 0xA1, 0xF6, 0x76, 0x13, 0xD6, 0x7A, 0xF2, 0xA0, 0x76, 0x66, 0xC3, 0x3B, 0x3A, 0x9C, 0xE8, 0x28, 0x50, 0x9A, 0x76, 0x2C, 0xFC, 0x48, 0x2A, 0x23, 0xD9, 0xF4, 0x39, 0x9F, 0xC1, 0x85, 0x49, 0xFE, 0xFD, 0x2C, 0x14, 0x73, 0x3D, 0x08, 0xE9, 0x15, 0x9E, 0xC1, 0x86, 0xA5, 0x27, 0xAB, 0x9D}, []uint{7, 27, 15, 37, 13, 26, 25, 4, 56, 38, 25, 11, 13, 38, 26, 32, 51, 7, 53, 13, 46, 53, 41, 50, 41, 52}, []uint64{0x34, 0x2F309B8, 0x17CE, 0x796A7B919, 0x58F, 0x2E6F4FF, 0x6DBB4, 0x0E, 0x64AB91090E9D7B, 0x10021D6472, 0x1324DEA, 0x76D, 0x3AA, 0x6889838AC, 0x9FA756, 0xE777A039, 0x69CA3741A1F67, 0x30, 0x13D67AF2A07666, 0x1867, 0x19D4E7414284, 0x1A762CFC482A23, 0x1B3E8733F83, 0x2A4FF7E960A3, 0x133D08E9159, 0xEC186A527AB9D}, }, { []byte{0xDE, 0xFA, 0x7D, 0x18, 0x91, 0x5F, 0xD5, 0x6A, 0x70, 0x0D, 0xEA, 0x2C, 0x70, 0x3E, 0xC2, 0x17, 0x65, 0x69, 0xB9, 0x94, 0x4D, 0xEF, 0x61, 0x47, 0xFB, 0x07, 0x57, 0x14, 0x60, 0xEE, 0x6F, 0x2C, 0x50, 0x2C, 0xDC, 0x56, 0xAC, 0x5A, 0x1E, 0xA6, 0x3D, 0xAE, 0xEB, 0xEB, 0x52, 0xA0, 0x8F, 0xEB, 0x2C, 0x01, 0x55, 0x6B, 0x7D, 0x29, 0x15, 0x06, 0xB9, 0x12, 0x9E, 0x88, 0x15, 0x06, 0xE5, 0x81, 0x77, 0x61, 0x3E, 0x6A, 0x0E, 0xE4, 0xA9, 0xE2, 0x73, 0x78, 0x7A, 0x04, 0x3A, 0x8E, 0xB2, 0x68, 0x3E, 0x97, 0xFE, 0x8B, 0xA7, 0x54, 0x7C, 0x44, 0xCD, 0x50, 0x75, 0x8D, 0x1E, 0x3C, 0xF8, 0x0F, 0x09, 0x7A, 0x30, 0x38}, []uint{18, 55, 46, 36, 6, 40, 36, 28, 62, 26, 58, 8, 62, 57, 61, 31, 4, 14, 55, 59, 6, 5, 27}, []uint64{0x37BE9, 0x7A3122BFAAD4E0, 0x6F516381F61, 0xBB2B4DCC, 0x28, 0x9BDEC28FF6, 0xEAE28C1D, 0xCDE58A0, 0x166E2B562D0F531E, 0x35DD7D6, 0x295047F59600AAB, 0x5B, 0x3A522A0D72253D10, 0x541B9605DD84F9, 0x15077254F139BC3D, 0x10EA3AC, 0x09, 0x283E, 0x4BFF45D3AA3E22, 0x33541D63478F3E0, 0x0F, 0x01, 0x17A3038}, }, { []byte{0x1F, 0x14, 0x9C, 0x3B, 0x12, 0xAB, 0xA7, 0x1E, 0x56, 0x9C, 0x0F, 0x6B, 0xD7, 0x06, 0x53, 0x96, 0xD3, 0x93, 0x66, 0x48, 0x51, 0x47, 0x3B, 0x8B, 0x73, 0x6D, 0x56, 0x25, 0xE1, 0x37, 0x33, 0x5E, 0x50, 0x51, 0xD5, 0xA2, 0xDF, 0x36, 0x71, 0x08, 0xA4, 0x45, 0xA2, 0xD8, 0x7A, 0xE4, 0x71, 0x2C, 0x8F, 0x2F, 0x58, 0x1C, 0x92, 0x53, 0x36, 0x72, 0xD1, 0x3E, 0xED, 0xDB, 0xBE, 0x81, 0x6E, 0xA5, 0x3C, 0x88, 0xE6, 0x86, 0xA2, 0xFD, 0x2C, 0xEC, 0xE2, 0x87, 0x3C, 0x4E, 0xA8, 0xB9, 0x30, 0xB6, 0xD2, 0x44, 0xFD, 0x7C, 0xDD, 0x9D, 0x68, 0x7E, 0xE3, 0xC0, 0xE1, 0x55, 0xB5, 0x46, 0xEE, 0x6E, 0x3A, 0xEC, 0xC0, 0xEE}, []uint{27, 22, 22, 27, 60, 40, 63, 9, 2, 14, 31, 30, 40, 57, 18, 25, 52, 61, 35, 27, 25, 51, 9, 40, 13}, []uint64{0xF8A4E1, 0x362557, 0x138F2B, 0x2703DAF, 0x5C194E5B4E4D992, 0x1451CEE2DC, 0x6DAAC4BC26E66BCA, 0x14, 0x01, 0x3568, 0x5BE6CE21, 0x5222D16, 0xC3D7238964, 0xF2F581C9253367, 0xB44F, 0x176EDDF, 0x40B7529E44734, 0x6A2FD2CECE2873C, 0x27545C985, 0x5B4913F, 0xBE6ECE, 0x5A1FB8F038556, 0x1AA, 0x377371D766, 0xEE}, }, { []byte{0xC6, 0x50, 0x5B, 0xDC, 0x8F, 0x17, 0x18, 0xFC, 0x74, 0xB0, 0xA2, 0x6B, 0x88, 0x04, 0x43, 0x34, 0x39, 0xEE, 0x82, 0x49, 0x11, 0xCE, 0x55, 0x79, 0xC0, 0xBE, 0xC5, 0x9A, 0x68, 0xA7, 0xC3, 0xF3, 0x10, 0x6D, 0xCC, 0x36, 0x5A, 0xCE, 0x18, 0x02, 0xE0, 0x3F, 0x72, 0xCF, 0x15, 0xBF, 0xE6, 0x8E, 0x53, 0xA8, 0xE8, 0xC7, 0x8A, 0xF2, 0x36, 0x8F, 0x23, 0xB4, 0xF1, 0x2A, 0xF2, 0xBB, 0x12, 0x3E, 0x89, 0xDA, 0x20, 0x08, 0x70, 0x08, 0xC3, 0xD7, 0x29, 0x87, 0x29, 0xA9, 0x3C, 0x63, 0x28, 0x7B, 0x85, 0xE4, 0x58, 0x91, 0x9A, 0x28, 0xCD, 0x52, 0x3D, 0x8F, 0x57, 0xC6, 0xE6, 0xD2, 0xC7, 0x4E, 0x8C, 0x8C, 0x94, 0x0B}, []uint{30, 9, 43, 58, 57, 60, 39, 34, 10, 51, 14, 9, 33, 26, 38, 8, 24, 11, 40, 60, 41, 44, 40, 14, 7}, []uint64{0x319416F7, 0x47, 0x45C63F1D2C2, 0x226B8804433439E, 0x1D0492239CAAF38, 0x17D8B34D14F87E6, 0x106DCC365A, 0x338600B80, 0x3F7, 0x1678ADFF34729, 0x351D, 0x31, 0x1C5791B47, 0x24769E2, 0x15795D891F, 0x44, 0xED1004, 0x1C0, 0x230F5CA61C, 0xA6A4F18CA1EE179, 0x2C48CD1466, 0xA91EC7ABE37, 0x36963A7464, 0x1928, 0x0B}, }, { []byte{0x92, 0x34, 0xDC, 0xA7, 0x57, 0x47, 0x83, 0xFB, 0x4C, 0x08, 0x2D, 0x84, 0xED, 0x7A, 0xD1, 0x7A, 0x8F, 0xDF, 0x10, 0xAE, 0xD4, 0x58, 0xEB, 0xF7, 0x69, 0xE8, 0x94, 0x41, 0x97, 0xAC, 0x78, 0x04, 0x9C, 0x5E, 0xB3, 0xB9, 0x0C, 0xE3, 0x48, 0xC5, 0x45, 0x1A, 0xBB, 0x8D, 0x21, 0xA0, 0x4B, 0x77, 0xE1, 0x01, 0x06, 0x6D, 0x89, 0x37, 0xD8, 0xB9, 0xCF, 0xD3, 0x94, 0xD0, 0xFD, 0xF8, 0xE2, 0xC5, 0x33, 0x3E, 0xAF, 0x7F, 0x9B, 0xF1, 0xDE, 0x2D, 0xF7, 0x10, 0x3A, 0xBA, 0xD9, 0x17, 0xF8, 0x79, 0x7A, 0xF4, 0xAC, 0x44, 0x60, 0x5E, 0x2E, 0xA5, 0x87, 0xC9, 0x9C, 0x7D, 0x0A, 0x42, 0xAC, 0xBF, 0x90, 0x0A, 0x83, 0xB9}, []uint{41, 57, 52, 49, 23, 39, 53, 1, 6, 37, 2, 19, 13, 10, 52, 17, 38, 20, 20, 45, 36, 56, 22, 20, 49, 5, 18}, []uint64{0x12469B94EAE, 0x11E0FED3020B613, 0xB5EB45EA3F7C4, 0x576A2C75FBB4, 0x7A2510, 0x32F58F0093, 0x117ACEE4338D23, 0x00, 0x0A, 0x1146AEE348, 0x01, 0x5025B, 0x17E1, 0x04, 0x19B624DF62E73, 0x1E9CA, 0x1A1FBF1C58, 0xA667D, 0x5EFF3, 0xFC778B7DC40, 0xEAEB645FE, 0x1E5EBD2B111817, 0x22EA58, 0x7C99C, 0xFA1485597F20, 0x02, 0x283B9}, }, { []byte{0x14, 0x51, 0xA2, 0xCB, 0xC5, 0x75, 0xFD, 0x6D, 0xAA, 0x55, 0x35, 0x8A, 0x0C, 0x63, 0xD7, 0xD0, 0x6A, 0x88, 0x56, 0x78, 0xDE, 0x38, 0xA8, 0xAA, 0xB0, 0x3A, 0x8A, 0xD4, 0xCC, 0x91, 0x9A, 0x6D, 0xA2, 0xC9, 0xA5, 0x3A, 0xAB, 0x4C, 0xC4, 0xFC, 0x3C, 0xB2, 0x44, 0xBB, 0x3C, 0xFB, 0xF8, 0x62, 0x82, 0x90, 0xF8, 0x5E, 0x6A, 0x3C, 0x6A, 0x14, 0x61, 0x7E, 0xA8, 0x0C, 0x3B, 0x7F, 0x00, 0xF8, 0x18, 0x14, 0xBD, 0x13, 0xA3, 0xC6, 0xE6, 0xF1, 0xB0, 0x9F, 0x91, 0xF7, 0x16, 0xC9, 0xDB, 0x9D, 0xC8, 0xB8, 0x96, 0xA0, 0x22, 0x95, 0xF3, 0x39, 0x8C, 0xE8, 0x6D, 0xDC, 0xE2, 0x75, 0xAD, 0xC3, 0xC9, 0x2E, 0x2A, 0xDC}, []uint{9, 52, 26, 1, 3, 3, 39, 45, 14, 59, 41, 42, 38, 61, 61, 57, 29, 56, 58, 6, 11, 32, 33, 17, 7}, []uint64{0x28, 0xA345978AEBFAD, 0x2D52A9A, 0x01, 0x04, 0x02, 0x418C7AFA0D, 0xA2159E378E2, 0x28AA, 0x581D456A6648CD3, 0xDA2C9A53AA, 0x2D3313F0F2C, 0x244BB3CFBF, 0x10C50521F0BCD478, 0x1A85185FAA030EDF, 0x1807C0C0A5E89D1, 0x1C6E6F1B, 0x9F91F716C9DB9, 0x3722E25A808A57C, 0x33, 0x4C6, 0x7436EE71, 0x75ADC3C9, 0x5C55, 0x5C}, }, { []byte{0x71, 0x4F, 0x73, 0x51, 0xAA, 0x39, 0xC9, 0x4F, 0xF7, 0x6E, 0x45, 0x35, 0x07, 0x37, 0x78, 0x28, 0x44, 0x01, 0x14, 0xE7, 0xCA, 0x39, 0x71, 0x8B, 0x93, 0x42, 0x99, 0x23, 0x8B, 0x38, 0x34, 0x2F, 0xD9, 0x59, 0xF7, 0xFA, 0x8F, 0x96, 0x99, 0x23, 0x4D, 0x5D, 0x6D, 0xF2, 0xDD, 0xEB, 0x60, 0xF6, 0x7F, 0x01, 0xBA, 0x5D, 0xAD, 0x7E, 0xD2, 0x2C, 0x34, 0x11, 0x1E, 0xD7, 0x77, 0xAE, 0x59, 0x52, 0x8B, 0xAC, 0x48, 0x9F, 0xF3, 0x26, 0xCF, 0x56, 0xE2, 0x16, 0x56, 0x15, 0xB1, 0xDE, 0xDC, 0x0E, 0x00, 0x35, 0x4A, 0x59, 0x72, 0x56, 0x44, 0xD7, 0x22, 0x77, 0x2E, 0x78, 0x26, 0x3E, 0x0E, 0xF2, 0xB7, 0x37, 0x5B, 0x86}, []uint{49, 54, 59, 50, 64, 64, 51, 12, 33, 26, 54, 4, 29, 33, 32, 61, 44, 41, 18, 22}, []uint64{0xE29EE6A35473, 0x24A7FBB7229A83, 0x4DDE0A11004539F, 0xA39718B93429, 0x9238B38342FD959F, 0x7FA8F9699234D5D6, 0x6F96EF5B07B3F, 0x80D, 0x1A5DAD7ED, 0x8B0D04, 0x11ED777AE59528, 0x0B, 0x158913FE, 0xC9B3D5B8, 0x8595856C, 0xEF6E07001AA52CB, 0x92B226B913B, 0x12E78263E0E, 0x3CADC, 0x375B86}, }, { []byte{0x50, 0xFB, 0x8B, 0x19, 0xF8, 0xE7, 0x6D, 0xEF, 0xCC, 0x78, 0x91, 0x98, 0x77, 0xAD, 0x00, 0xA7, 0x6F, 0x35, 0x25, 0xA8, 0x8F, 0xC2, 0x2E, 0x07, 0x1C, 0x95, 0x09, 0x10, 0xED, 0xCC, 0x86, 0x3C, 0xF1, 0x04, 0x2C, 0xC6, 0xC6, 0xE7, 0x89, 0xC1, 0x7F, 0x34, 0x16, 0xBE, 0x45, 0x47, 0xD8, 0xE7, 0x84, 0x74, 0x30, 0x91, 0x36, 0xDD, 0x88, 0x00, 0xB9, 0x73, 0x22, 0xA9, 0xF1, 0x72, 0x5F, 0x6B, 0x61, 0x1F, 0x09, 0xFA, 0xB8, 0x8F, 0xE1, 0x24, 0xBB, 0xDF, 0xB9, 0x43, 0xD8, 0x46, 0x3E, 0x4C, 0xD9, 0x77, 0x56, 0xD5, 0x4F, 0x98, 0x7D, 0x61, 0xD6, 0xFA, 0x27, 0xB6, 0xA1, 0x95, 0x8A, 0xB2, 0x40, 0x6E, 0x1F, 0xC2}, []uint{9, 19, 15, 27, 49, 35, 15, 38, 48, 39, 29, 49, 62, 51, 3, 17, 38, 37, 35, 13, 6, 33, 54, 8, 14, 35, 22}, []uint64{0xA1, 0x7B8B1, 0x4FC7, 0x1DB7BF3, 0x3C48CC3BD680, 0x29DBCD496, 0x511F, 0x2117038E4A, 0x848876E6431E, 0x3C410B31B1, 0x173C4E0B, 0x1F3416BE4547D, 0x239E11D0C244DB76, 0x100172E64553E, 0x01, 0xE4BE, 0x35B08F84FD, 0xB88FE124B, 0x5EFDCA1EC, 0x463, 0x39, 0x66CBBAB6, 0x2A9F30FAC3ADF4, 0x4F, 0x1B50, 0x6562AC901, 0x2E1FC2}, }, { []byte{0xCB, 0x0B, 0xBC, 0xEA, 0x8E, 0x98, 0xFC, 0x67, 0x6A, 0x13, 0x54, 0x10, 0x90, 0xE9, 0xAF, 0x4D, 0xA5, 0x28, 0xAD, 0x14, 0xD3, 0x62, 0x21, 0x81, 0x4F, 0x15, 0x40, 0x65, 0x32, 0x37, 0x39, 0x8C, 0x71, 0x38, 0xBE, 0xF8, 0x37, 0x6B, 0x96, 0x5A, 0x2C, 0x19, 0x6F, 0xF3, 0xCF, 0xF9, 0x08, 0xC3, 0x4B, 0xAB, 0x9C, 0xB3, 0xA2, 0xE7, 0x62, 0x61, 0xBC, 0x59, 0x83, 0x95, 0x5B, 0x22, 0x0B, 0x1B, 0x7D, 0x7B, 0xDE, 0xF7, 0x96, 0xC0, 0x30, 0x29, 0xEF, 0x4E, 0x46, 0xE8, 0x8D, 0x24, 0xFC, 0x0B, 0x5E, 0xC1, 0x40, 0x6E, 0xA6, 0x81, 0xB1, 0x66, 0x15, 0x78, 0xED, 0xF6, 0x3A, 0x6D, 0x3B, 0xC6, 0x29, 0x3B, 0x29, 0xAD}, []uint{34, 62, 46, 7, 8, 55, 14, 33, 30, 14, 16, 63, 29, 31, 39, 52, 60, 2, 21, 4, 60, 45, 9, 51, 15}, []uint64{0x32C2EF3AA, 0xE98FC676A135410, 0x243A6BD3694A, 0x15, 0xA2, 0x4D36221814F154, 0x194, 0x191B9CC63, 0x22717DF0, 0x1BB5, 0xCB2D, 0xB065BFCF3FE4230, 0x1A5D5CE5, 0x4E8B9D89, 0x4378B3072A, 0xB6441636FAF7B, 0xDEF2D806053DE9C, 0x02, 0x6E88D, 0x02, 0x4FC0B5EC1406EA6, 0x10362CC2AF1D, 0x17D, 0x474DA778C5276, 0x29AD}, }, { []byte{0x65, 0x00, 0xA4, 0x4F, 0x09, 0x6B, 0x77, 0xDC, 0xB3, 0x75, 0xDA, 0x0C, 0xEF, 0x14, 0x65, 0x7B, 0x1B, 0xDF, 0x21, 0x1E, 0xBA, 0x98, 0xC0, 0xD0, 0x34, 0xB3, 0x75, 0x8F, 0x90, 0x17, 0xF0, 0x73, 0x99, 0x7D, 0x1A, 0x89, 0xDF, 0x48, 0xEE, 0xF4, 0x7C, 0x23, 0x93, 0x2B, 0xFF, 0xFE, 0x5A, 0x3C, 0x4F, 0x9D, 0x4C, 0x22, 0x2E, 0xD0, 0x31, 0x23, 0xD6, 0x00, 0xA2, 0x63, 0xD8, 0x78, 0xAD, 0x90, 0xB3, 0xF2, 0x8B, 0x38, 0x45, 0xB3, 0x1A, 0xB7, 0x5B, 0xD3, 0x5A, 0x93, 0x43, 0x65, 0x33, 0xB2, 0xB4, 0x74, 0x2C, 0x87, 0x63, 0x15, 0xCF, 0x9F, 0x20, 0x6D, 0xCF, 0xE7, 0x49, 0xFD, 0x32, 0x85, 0x0D, 0x4C, 0x56, 0x23}, []uint{33, 45, 36, 59, 14, 38, 44, 46, 39, 5, 16, 58, 26, 45, 28, 1, 48, 46, 26, 54, 57, 19, 17}, []uint64{0xCA01489E, 0x25ADDF72CDD, 0x76833BC51, 0x4AF637BE423D753, 0x606, 0x206966EB1F, 0x202FE0E732F, 0x28D44EFA4777, 0x51F08E4CAF, 0x1F, 0xFF2D, 0x789F3A98445DA0, 0x1891EB0, 0xA263D878AD, 0x90B3F28, 0x01, 0x6708B66356EB, 0x1E9AD49A1B29, 0x276568E, 0x21643B18AE7CF9, 0x6DCFE749FD328, 0x286A6, 0x5623}, }, { []byte{0x31, 0xB1, 0x41, 0xCC, 0x16, 0x3C, 0xA8, 0x45, 0x95, 0x99, 0x28, 0x22, 0xBC, 0xDB, 0x79, 0xB1, 0x73, 0x27, 0xF2, 0x83, 0xFF, 0x6D, 0x48, 0x0D, 0xAF, 0x90, 0x08, 0xF8, 0x9C, 0xD3, 0x54, 0x39, 0x63, 0x63, 0x75, 0xD7, 0xA0, 0x88, 0x47, 0x1A, 0x8A, 0x0F, 0x3D, 0x0E, 0x92, 0x7B, 0x6E, 0x5D, 0x01, 0x4F, 0x0E, 0x59, 0x79, 0xF0, 0x4B, 0xDC, 0x53, 0x58, 0x2A, 0x6E, 0x98, 0xC9, 0x62, 0xAD, 0x24, 0x08, 0xB7, 0x37, 0xAB, 0x65, 0x9A, 0x2A, 0x59, 0x3E, 0xE4, 0x29, 0x9C, 0x10, 0xC3, 0x45, 0xD7, 0x6A, 0x1C, 0x4D, 0xC3, 0x85, 0xFF, 0x94, 0x8E, 0x56, 0x3B, 0x21, 0x7A, 0x3D, 0x6C, 0x7D, 0xE3, 0x97, 0x37, 0x6C}, []uint{37, 10, 30, 25, 3, 25, 7, 11, 15, 8, 19, 20, 25, 37, 45, 63, 33, 52, 55, 12, 63, 24, 1, 31, 53, 25, 54, 17}, []uint64{0x636283982, 0x31E, 0x1508B2B3, 0x4A08AF, 0x01, 0x16DE6C5, 0x66, 0x27F, 0x141F, 0xFB, 0x35203, 0x6BE40, 0x47C4E6, 0x1354396363, 0xEBAF41108E3, 0x28A0F3D0E927B6E5, 0x1A029E1CB, 0x2F3E097B8A6B0, 0x2A6E98C962AD24, 0x8B, 0x39BD5B2CD152C9F7, 0x214CE0, 0x01, 0x61A2EBB, 0xA1C4DC385FF94, 0x11CAC76, 0x10BD1EB63EF1CB, 0x1376C}, }, { []byte{0x8B, 0x89, 0x8A, 0x74, 0xAA, 0x17, 0xFF, 0xDA, 0x92, 0xDF, 0xB8, 0xC9, 0xFE, 0xB4, 0xB6, 0x84, 0x9C, 0x55, 0x64, 0x82, 0x41, 0x81, 0xFE, 0x23, 0xF1, 0xAC, 0x76, 0x5D, 0x55, 0xC8, 0x13, 0x6C, 0x5A, 0x0E, 0xAA, 0x71, 0x12, 0xFA, 0xED, 0x0C, 0x56, 0x2F, 0xD9, 0x70, 0x38, 0x7F, 0x8D, 0x06, 0x00, 0x3C, 0xD8, 0xB7, 0xE4, 0x99, 0x69, 0xD4, 0xFC, 0xA0, 0x35, 0x5D, 0x9F, 0xD2, 0x59, 0x32, 0x93, 0x60, 0x4A, 0x57, 0xCD, 0x93, 0x94, 0x74, 0x6F, 0x99, 0x5C, 0x49, 0x58, 0x62, 0xE5, 0xF3, 0x59, 0x9B, 0x33, 0xFE, 0x9D, 0x86, 0x2D, 0xA3, 0x0A, 0xB8, 0xB8, 0x7E, 0xFB, 0x51, 0xD0, 0x16, 0xF6, 0xF3, 0x22, 0x22}, []uint{31, 27, 6, 12, 61, 3, 47, 47, 8, 8, 15, 29, 29, 32, 27, 22, 42, 51, 14, 52, 6, 25, 6, 22, 51, 62, 60, 5}, []uint64{0x45C4C53A, 0x2A85FFF, 0x1A, 0x92D, 0x1F7193FD696D0938, 0x05, 0x2B24120C0FF1, 0xFC6B1D97557, 0x20, 0x4D, 0x58B4, 0x3AA9C44, 0x17D76862, 0xB17ECB81, 0x61FE341, 0x2003CD, 0x22DF9265A75, 0x1F9406ABB3FA4, 0x2C99, 0x49B0252BE6C9C, 0x28, 0x1D1BE65, 0x1C, 0x125618, 0x5CBE6B33667FD, 0xEC316D1855C5C3F, 0x7DA8E80B7B79911, 0x02}, }, { []byte{0xC8, 0x02, 0x2F, 0x55, 0xFC, 0x45, 0xDF, 0xA9, 0x4D, 0x04, 0xDC, 0x73, 0xDF, 0x5C, 0x82, 0x14, 0x9E, 0x65, 0xC8, 0xFF, 0x12, 0x5E, 0x15, 0x8F, 0xCA, 0x0A, 0xC9, 0xB9, 0x59, 0x99, 0x64, 0x7A, 0x6A, 0xE6, 0x49, 0x9C, 0x74, 0x72, 0xCD, 0xB3, 0x6F, 0xCF, 0x99, 0x02, 0xB1, 0x2C, 0xB4, 0x78, 0xF4, 0x43, 0x1C, 0xB9, 0xB0, 0xE6, 0xC6, 0x94, 0xF3, 0x01, 0x66, 0x13, 0x5E, 0x2A, 0xF9, 0xD0, 0x33, 0xFC, 0x77, 0xC4, 0xFA, 0x0F, 0x7B, 0xFD, 0x1C, 0xC2, 0x77, 0xED, 0x37, 0xAA, 0x97, 0x3D, 0x1E, 0x86, 0x96, 0x9C, 0x67, 0x12, 0xC2, 0x8B, 0xA7, 0xCB, 0xC1, 0x35, 0xCE, 0x80, 0xF2, 0x4F, 0xCB, 0xB8, 0x9F, 0xE4}, []uint{28, 39, 42, 11, 32, 11, 2, 11, 58, 55, 37, 23, 17, 57, 41, 8, 22, 21, 23, 3, 1, 49, 45, 27, 46, 48, 9, 34}, []uint64{0xC8022F5, 0x2FE22EFD4A, 0x1A09B8E7BEB, 0x482, 0x149E65C8, 0x7F8, 0x02, 0x25E, 0x563F282B26E566, 0x32C8F4D5CC9338, 0x1D1CB36CDB, 0x79F320, 0xAC4B, 0x5A3C7A218E5CD8, 0xE6C694F301, 0x66, 0x4D78A, 0x17CE81, 0x4FF1DF, 0x00, 0x01, 0x7D07BDFE8E61, 0x77ED37AA973, 0x68F434B, 0x138CE2585174, 0xF97826B9D01E, 0x93, 0x3CBB89FE4}, }, { []byte{0x69, 0x18, 0xCA, 0x1F, 0x76, 0xD9, 0x00, 0xA8, 0xC4, 0x7C, 0x90, 0xB8, 0xC9, 0x4B, 0xF2, 0xE1, 0xEF, 0xFA, 0x7C, 0x5A, 0x6E, 0xB2, 0xDA, 0x4A, 0x86, 0x2E, 0x93, 0x5A, 0xB0, 0x61, 0x15, 0x72, 0xDD, 0x20, 0xEA, 0xBF, 0xA5, 0x4D, 0x9C, 0x7C, 0x9E, 0xD0, 0xA4, 0x0D, 0x1D, 0x85, 0xF1, 0x03, 0xBA, 0xA0, 0xF7, 0x37, 0x96, 0x0E, 0x05, 0x4C, 0xCD, 0x96, 0x9E, 0x7F, 0xF2, 0xE9, 0xE5, 0xA2, 0x7F, 0xED, 0x32, 0x13, 0x24, 0x1F, 0x60, 0x93, 0x0F, 0x25, 0x4D, 0x96, 0x9B, 0x4C, 0x19, 0xE1, 0xA8, 0x20, 0x41, 0x27, 0xE5, 0x1C, 0x92, 0x30, 0x93, 0x15, 0x0D, 0xD8, 0xCB, 0xAC, 0x25, 0xE1, 0x60, 0xE2, 0x4D, 0x1E}, []uint{36, 31, 43, 61, 45, 54, 48, 21, 50, 49, 44, 30, 7, 12, 26, 30, 62, 63, 60, 28}, []uint64{0x6918CA1F7, 0x36C80546, 0x11F242E3252, 0x1F970F7FD3E2D375, 0x12DA4A862E93, 0x16AC18455CB748, 0x3AAFE953671F, 0x4F685, 0x81A3B0BE2077, 0xA83DCDE58381, 0x533365A79FF, 0x32E9E5A2, 0x3F, 0xF69, 0x2426483, 0x3B049879, 0xA9B2D369833C350, 0x204127E51C923093, 0x150DD8CBAC25E16, 0xE24D1E}, }, { []byte{0x06, 0x15, 0x43, 0xBF, 0x63, 0x7B, 0xFD, 0x1D, 0xED, 0xB3, 0x50, 0x4E, 0x2F, 0x27, 0x4D, 0x97, 0xD2, 0x0D, 0x47, 0x39, 0xD1, 0x16, 0x90, 0x26, 0xEC, 0xC6, 0x5D, 0x6C, 0xA5, 0x99, 0x92, 0x02, 0xD7, 0x1D, 0x35, 0x00, 0x4A, 0xE0, 0xFF, 0xE5, 0xEC, 0x16, 0x13, 0x59, 0xB3, 0x05, 0xE9, 0x4D, 0xD5, 0x7D, 0x24, 0x81, 0x14, 0x2C, 0xF4, 0xF7, 0xBD, 0xD0, 0x19, 0xFB, 0x51, 0xE9, 0x9E, 0x54, 0x17, 0x84, 0x9E, 0x39, 0x23, 0x1E, 0xFC, 0x9B, 0xC1, 0xF2, 0x75, 0xA1, 0xC6, 0xFC, 0x3D, 0xEA, 0xB4, 0xA0, 0x64, 0xA0, 0xE0, 0x43, 0xD6, 0x66, 0xF7, 0x77, 0x0B, 0xF0, 0x1E, 0x66, 0x6B, 0x7B, 0xAD, 0xCA, 0xDB, 0xEC}, []uint{39, 11, 11, 10, 48, 32, 20, 46, 26, 16, 25, 24, 37, 16, 47, 63, 18, 9, 51, 38, 56, 63, 61, 32, 1}, []uint64{0x30AA1DFB1, 0x5EF, 0x7A3, 0x2F6, 0xD9A8271793A6, 0xCBE906A3, 0x9CE88, 0x2D204DD98CBA, 0x3652CCC, 0x9016, 0x171D350, 0x4AE0F, 0x1FCBD82C26, 0xB366, 0x5E94DD57D24, 0x408A167A7BDEE80C, 0x3F6A3, 0x1A6, 0x3CA82F093C724, 0x18F7E4DE0F, 0x93AD0E37E1EF55, 0x52819283810F599B, 0x1BBB85F80F3335BD, 0xD6E56DF6, 0x00}, }, { []byte{0xA3, 0x34, 0x99, 0x5A, 0xA7, 0x43, 0xDE, 0x9D, 0x0D, 0xB0, 0x07, 0x3A, 0x06, 0x10, 0x48, 0x4F, 0x9D, 0x6E, 0xA1, 0x12, 0xBE, 0x3E, 0xBE, 0x16, 0x5C, 0x0D, 0xC9, 0x30, 0x78, 0x71, 0x44, 0x0F, 0xC1, 0xB5, 0x54, 0x00, 0xEE, 0xEB, 0x28, 0x81, 0x2C, 0xF9, 0x16, 0xEA, 0xA6, 0x31, 0x28, 0xC0, 0x08, 0xDD, 0x33, 0x89, 0x6B, 0x58, 0x2F, 0x6A, 0x73, 0xA6, 0xED, 0xDD, 0xFA, 0x6D, 0xAE, 0x45, 0xA4, 0xE1, 0x2B, 0xD3, 0xDA, 0xF1, 0x1F, 0x4A, 0x89, 0x03, 0xD4, 0x9A, 0xF1, 0x0C, 0x9B, 0x01, 0xF3, 0x67, 0x87, 0x64, 0x93, 0x21, 0x2C, 0xC7, 0x84, 0x3D, 0xBE, 0x07, 0x6B, 0x2B, 0xD2, 0x87, 0x5B, 0xAB, 0x1E, 0x2A}, []uint{17, 5, 3, 47, 17, 35, 37, 43, 52, 22, 45, 63, 37, 55, 37, 16, 12, 32, 12, 13, 2, 49, 3, 55, 5, 37, 15, 33, 1}, []uint64{0x14669, 0x06, 0x02, 0x5AA743DE9D0D, 0x1600E, 0x3A0610484, 0x1F3ADD4225, 0x3E3EBE165C0, 0xDC9307871440F, 0x306D55, 0x777594409, 0x33E45BAA98C4A300, 0x46E99C4B5, 0x560BDA9CE9BB77, 0xFD36D722D, 0x2709, 0x5E9, 0xED788FA5, 0x448, 0x3D4, 0x02, 0xD78864D80F9B, 0x01, 0x70EC92642598F0, 0x10, 0x1EDF03B595, 0x74A1, 0x1ADD58F15, 0x00}, }, { []byte{0xC2, 0x1C, 0x29, 0x23, 0xD2, 0x85, 0x5C, 0x44, 0xDD, 0x85, 0xEB, 0xB0, 0x7D, 0x6B, 0x97, 0x2B, 0x4A, 0x92, 0x13, 0xDF, 0x85, 0x7B, 0x3F, 0xF1, 0x81, 0xFD, 0x59, 0xC5, 0x6B, 0x34, 0xE8, 0x98, 0xFB, 0x49, 0x38, 0x07, 0x6B, 0xE7, 0x0C, 0x2B, 0x48, 0x23, 0x87, 0x36, 0x1E, 0x2A, 0x00, 0x39, 0x0E, 0x01, 0x9C, 0x34, 0x67, 0x8D, 0x62, 0x2F, 0xD3, 0x59, 0x80, 0x20, 0x14, 0xB1, 0xDF, 0xE0, 0xA9, 0xF3, 0x05, 0x8D, 0xFB, 0x1F, 0xD2, 0xE5, 0x43, 0xEA, 0xEB, 0xE0, 0xF3, 0x78, 0x15, 0x16, 0x34, 0x1A, 0xD7, 0x05, 0xB3, 0x66, 0xC1, 0xB1, 0x7A, 0x98, 0xFB, 0x9C, 0x88, 0x1F, 0xD4, 0xD4, 0xEF, 0x03, 0x43, 0xFA}, []uint{54, 24, 30, 28, 48, 31, 42, 39, 14, 8, 55, 63, 17, 57, 64, 10, 62, 60, 10, 41, 31, 12}, []uint64{0x30870A48F4A157, 0x113761, 0x1EBB07D6, 0xB972B4A, 0x9213DF857B3F, 0x78C0FEAC, 0x38AD669D131, 0x7B4938076B, 0x39C3, 0x0A, 0x690470E6C3C540, 0x390E019C34678D6, 0x45FA, 0xD66008052C77F8, 0x2A7CC1637EC7F4B9, 0x143, 0x3ABAF83CDE05458D, 0x6B5C16CD9B06C5, 0x3A9, 0x11F739103FA, 0x4D4EF034, 0x3FA}, }, { []byte{0x2E, 0xB7, 0x5F, 0x66, 0x0C, 0xEE, 0x9F, 0x22, 0x62, 0xEE, 0x89, 0x47, 0x18, 0x75, 0xC2, 0x9C, 0x4B, 0xC0, 0x5A, 0xB1, 0x11, 0x1F, 0x57, 0xA4, 0x68, 0xF4, 0xA9, 0xF4, 0x0A, 0x52, 0x86, 0xA5, 0x4B, 0x56, 0xBF, 0xC0, 0x2F, 0x16, 0x31, 0x62, 0xA2, 0x78, 0xD1, 0x9D, 0xE9, 0x0F, 0x2D, 0x40, 0xC5, 0xA7, 0x3C, 0x6C, 0x53, 0x8A, 0xBF, 0xD2, 0x16, 0x78, 0xDB, 0x22, 0xD3, 0x19, 0x69, 0x17, 0x9D, 0x81, 0x43, 0x98, 0x3A, 0x82, 0x93, 0x84, 0xFF, 0x4B, 0xA0, 0x26, 0xB0, 0x5C, 0xC3, 0x72, 0xA5, 0x7C, 0xDE, 0xC8, 0xD5, 0x2E, 0x6F, 0x80, 0x75, 0x14, 0xA5, 0xAB, 0x96, 0xEE, 0x60, 0x94, 0x0D, 0x42, 0xB9, 0x62}, []uint{49, 25, 55, 41, 56, 18, 46, 16, 29, 17, 38, 39, 23, 18, 12, 34, 45, 9, 4, 48, 28, 59, 9, 14, 15, 34, 19}, []uint64{0x5D6EBECC19DD, 0x7C898B, 0x5D128E30EB8538, 0x12F016AC444, 0x7D5E91A3D2A7D0, 0xA528, 0x1A952D5AFF00, 0xBC58, 0x18B1513C, 0xD19D, 0x3A43CB5031, 0x34E78D8A71, 0x2BFD21, 0x19E36, 0xC8B, 0x131969179, 0x1B0287307505, 0x4E, 0x01, 0x3FD2E809AC17, 0x30DCA95, 0x79BD91AA5CDF00E, 0x145, 0xA5A, 0x5CB7, 0x1CC1281A8, 0x2B962}, }, { []byte{0x11, 0x9E, 0xE6, 0x8D, 0x03, 0x9F, 0x19, 0x2F, 0x7C, 0x53, 0xA3, 0xA6, 0x8F, 0x6C, 0xA2, 0xF4, 0x0E, 0xE2, 0x21, 0x84, 0x09, 0xDB, 0x3C, 0xDF, 0x61, 0xEC, 0xCE, 0x30, 0xF0, 0x0B, 0x4E, 0x47, 0x97, 0x26, 0xE2, 0xE8, 0x13, 0x7A, 0x9D, 0x77, 0x17, 0x28, 0xB2, 0x5F, 0x77, 0x64, 0x25, 0x93, 0x01, 0xEB, 0x8B, 0xD9, 0x8F, 0x54, 0x49, 0x2C, 0x0B, 0x6F, 0x85, 0x9E, 0x06, 0x34, 0x26, 0x0C, 0xF1, 0x44, 0xC9, 0x5D, 0x04, 0x46, 0x92, 0x69, 0xA1, 0x16, 0xA9, 0x0D, 0x32, 0x3A, 0x88, 0x11, 0x33, 0x3B, 0xCD, 0x3F, 0x78, 0x4F, 0x0A, 0x5D, 0x55, 0x69, 0x35, 0x22, 0x2C, 0x90, 0xFD, 0xC2, 0x49, 0xF5, 0x44, 0x7D}, []uint{50, 55, 18, 59, 59, 49, 28, 6, 23, 35, 63, 16, 40, 13, 12, 43, 56, 7, 34, 44, 3, 18, 11, 52, 6}, []uint64{0x467B9A340E7C, 0x325EF8A7474D1E, 0x36517, 0x503B888610276CF, 0x1BEC3D99C61E016, 0x1391E5C9B8BA0, 0x4DEA75D, 0x31, 0x394592, 0x7DDD90964, 0x603D717B31EA8925, 0x816D, 0xF0B3C0C684, 0x1833, 0xC51, 0x192BA088D24, 0xD3422D521A6475, 0x08, 0x44CCEF34, 0xFDE13C29755, 0x02, 0x349A9, 0x8B, 0x243F70927D511, 0x3D}, }, { []byte{0x6D, 0x2D, 0x02, 0x1B, 0x65, 0xC7, 0x93, 0x72, 0xA1, 0xC8, 0x00, 0xE7, 0xD6, 0xB5, 0x89, 0x88, 0x9B, 0x48, 0x4E, 0x8A, 0x7F, 0x41, 0x10, 0x12, 0x6B, 0xF5, 0x3C, 0x74, 0x9F, 0x86, 0x6F, 0x9E, 0x74, 0x0C, 0x6C, 0x80, 0x6D, 0x65, 0xBB, 0xAC, 0x9A, 0xAF, 0x74, 0x6E, 0x28, 0x07, 0x2D, 0xCD, 0x12, 0x07, 0xEE, 0x47, 0x97, 0xC0, 0xF8, 0x85, 0xBC, 0x6C, 0x00, 0xE6, 0x03, 0x07, 0x19, 0xB2, 0xE0, 0xC0, 0x76, 0x24, 0xB8, 0xD0, 0x98, 0x5B, 0xD3, 0xBE, 0x06, 0x6C, 0x9C, 0xF2, 0x64, 0xC2, 0xAC, 0x9D, 0xE2, 0x58, 0x76, 0xF0, 0x2F, 0x1D, 0xA8, 0x92, 0xDA, 0xB8, 0x54, 0xEE, 0xC9, 0xB2, 0x6F, 0xE2, 0xC2, 0x3A}, []uint{49, 35, 28, 50, 45, 11, 8, 11, 41, 57, 52, 4, 57, 7, 55, 27, 27, 30, 12, 10, 64, 32, 58, 10, 20}, []uint64{0xDA5A0436CB8F, 0x1372A1C80, 0xE7D6B5, 0x226226D213A29, 0x1FA0880935FA, 0x4F1, 0xD2, 0x3F0, 0x19BE79D031B, 0x4036B2DDD64D57, 0xBA37140396E68, 0x09, 0x7EE4797C0F885, 0x5E, 0x1B003980C1C66C, 0x5C180EC, 0x24B8D09, 0x216F4EF8, 0x19B, 0x9C, 0xF264C2AC9DE25876, 0xF02F1DA8, 0x24B6AE153BB26C9, 0x2FE, 0x2C23A}, }, { []byte{0xF6, 0x50, 0x44, 0x6B, 0xE9, 0x59, 0x96, 0x1E, 0x48, 0x15, 0x9A, 0x63, 0x62, 0xDC, 0x04, 0x5E, 0x86, 0xE3, 0xCA, 0x7A, 0x47, 0x38, 0x1C, 0xB8, 0xD0, 0x0F, 0x4D, 0x0B, 0x7C, 0x4D, 0xB8, 0xE7, 0xAB, 0xD2, 0x11, 0x03, 0x13, 0x90, 0xD1, 0x08, 0x50, 0xD0, 0xC9, 0xAE, 0xBD, 0x67, 0xB2, 0x3B, 0xDE, 0xED, 0x7B, 0x79, 0x0F, 0x23, 0xE2, 0x89, 0x33, 0x7E, 0xE9, 0x07, 0xE1, 0x24, 0xDC, 0xAB, 0x49, 0xDE, 0x26, 0xFC, 0xA1, 0xE3, 0x9B, 0x6C, 0x16, 0x5E, 0x60, 0xEA, 0xFF, 0x67, 0x56, 0x9B, 0xF3, 0x88, 0xCC, 0x57, 0x56, 0xCB, 0x76, 0x25, 0xDA, 0xB5, 0x9C, 0xE8, 0x3D, 0xB7, 0x79, 0xED, 0xF5, 0xB4, 0x99, 0xB4}, []uint{44, 12, 8, 57, 32, 29, 32, 28, 18, 40, 8, 58, 60, 59, 64, 50, 46, 4, 46, 59, 46}, []uint64{0xF650446BE95, 0x996, 0x1E, 0x902B34C6C5B808, 0xBD0DC794, 0x1E91CE07, 0x2E3403D3, 0x42DF136, 0x38E7A, 0xBD21103139, 0x0D, 0x421434326BAF59, 0xEC8EF7BB5EDE43C, 0x47C51266FDD20FC, 0x249B95693BC4DF94, 0xF1CDB60B2F30, 0x1D5FECEAD37E, 0x07, 0x4662BAB65BB, 0x976AD673A0F6DD, 0x39EDF5B499B4}, }, { []byte{0xB0, 0x15, 0x5C, 0x01, 0xE3, 0x0E, 0x1A, 0xB6, 0x97, 0x04, 0x07, 0x63, 0xBB, 0x29, 0x2D, 0xB7, 0x80, 0xD3, 0x50, 0x42, 0x6B, 0xA3, 0xCA, 0x7C, 0x71, 0x40, 0xF2, 0xB6, 0x51, 0x89, 0x52, 0x84, 0xF1, 0x93, 0xAB, 0xAF, 0xC9, 0x9D, 0x1C, 0x3D, 0x43, 0xEC, 0xB8, 0x6F, 0xA1, 0xCE, 0xAB, 0x94, 0xF2, 0xF0, 0xF3, 0x14, 0xE9, 0x41, 0x02, 0x9B, 0xA6, 0x42, 0x83, 0xB7, 0xF6, 0x58, 0x60, 0x60, 0xDD, 0xD1, 0xC3, 0xCF, 0xCA, 0x4C, 0x74, 0xDC, 0x6D, 0xEF, 0x7F, 0x8C, 0x9F, 0xE9, 0xE4, 0x1F, 0xDF, 0xCD, 0x59, 0xAC, 0x70, 0x43, 0xE0, 0xF9, 0x5E, 0xB6, 0x8D, 0x10, 0x5F, 0xE0, 0x4B, 0x85, 0xD8, 0xCF, 0x59, 0xE3}, []uint{55, 6, 54, 27, 46, 46, 43, 11, 7, 18, 16, 23, 23, 60, 12, 9, 54, 61, 39, 31, 54, 34, 40, 31}, []uint64{0x580AAE00F1870D, 0x16, 0x34B8203B1DD949, 0x36DE034, 0x350426BA3CA7, 0x31C503CAD946, 0x12A509E3275, 0x3AF, 0x64, 0x33A38, 0x7A87, 0x6CB86F, 0x50E755, 0xCA7978798A74A08, 0x14D, 0x1A6, 0x10A0EDFD961818, 0x6EE8E1E7E5263A6, 0x71B7BDFE32, 0x3FD3C83F, 0x2FE6ACD63821F0, 0x1F2BD6D1A, 0x20BFC0970B, 0x58CF59E3}, }, { []byte{0x7F, 0x0D, 0xFB, 0x8B, 0x93, 0x2C, 0x51, 0xC3, 0xAE, 0x2F, 0xBE, 0xD2, 0xAD, 0xFE, 0x95, 0x3F, 0xEB, 0x41, 0xF1, 0x59, 0xDD, 0xBA, 0x1F, 0x31, 0xC1, 0x5C, 0x82, 0x78, 0x93, 0x3A, 0x53, 0x99, 0x29, 0x1F, 0x3E, 0x5B, 0xB5, 0x69, 0x25, 0x22, 0x34, 0xF3, 0x7C, 0x3A, 0xA8, 0xB6, 0xE4, 0xE3, 0x5E, 0xD5, 0x9D, 0xFB, 0x69, 0x49, 0xD0, 0x9F, 0x01, 0x4C, 0x03, 0x88, 0xD2, 0x82, 0x6E, 0xC7, 0x85, 0x35, 0x4D, 0xE7, 0x19, 0xA6, 0xF8, 0x1D, 0x3D, 0xDD, 0xC7, 0xE1, 0x89, 0x83, 0x69, 0xD9, 0xA3, 0x30, 0x25, 0x42, 0x95, 0x6E, 0x02, 0xFE, 0xC9, 0xDC, 0x6E, 0xD8, 0x58, 0xBB, 0xB6, 0x61, 0x48, 0xB9, 0x6D, 0xF8}, []uint{57, 11, 41, 47, 48, 3, 18, 37, 2, 23, 46, 10, 41, 43, 30, 51, 30, 22, 54, 24, 59, 11, 30, 21, 6, 34, 1}, []uint64{0xFE1BF7172658A3, 0x43A, 0x1C5F7DA55BF, 0x6953FEB41F15, 0x9DDBA1F31C15, 0x06, 0x104F1, 0x4CE94E64A, 0x01, 0xF9F2D, 0x36AD24A4469E, 0x1BE, 0x3AA8B6E4E3, 0x2F6ACEFDB4A, 0x13A13E02, 0x4C0388D2826EC, 0x1E14D537, 0x2719A6, 0x3E074F7771F862, 0x60DA76, 0x346604A852ADC05, 0x7EC, 0x2771BB61, 0xC5DDB, 0x0C, 0xA45CB6FC, 0x00}, }, { []byte{0xA8, 0x79, 0x2E, 0x69, 0x7C, 0xA9, 0x38, 0x1C, 0xBB, 0x72, 0x13, 0x55, 0xA9, 0x2B, 0xC6, 0xCD, 0xB9, 0x05, 0xAA, 0x90, 0xE3, 0x86, 0x2A, 0xB2, 0xD4, 0x18, 0x0C, 0xC0, 0x79, 0x2E, 0xFB, 0x29, 0x9B, 0x65, 0xA7, 0xB5, 0x06, 0x46, 0xD4, 0x1C, 0x7C, 0x4D, 0xDA, 0x29, 0x68, 0x83, 0xA6, 0x66, 0xFE, 0xA8, 0x96, 0x52, 0xAF, 0x88, 0x38, 0x25, 0x15, 0x51, 0xE0, 0x46, 0x29, 0x70, 0x7D, 0x74, 0xC9, 0xA2, 0xDD, 0x9C, 0xEA, 0x0D, 0x42, 0xFA, 0x50, 0x6A, 0x52, 0x77, 0x24, 0xC8, 0x37, 0x40, 0x45, 0x01, 0xEC, 0x9C, 0xDE, 0x91, 0x94, 0x23, 0xBD, 0x0A, 0xFA, 0x68, 0x39, 0xF3, 0x4F, 0xAD, 0x4E, 0xF4, 0xEB, 0x35}, []uint{16, 23, 38, 47, 6, 47, 2, 15, 21, 1, 13, 37, 17, 45, 6, 40, 31, 56, 59, 25, 27, 12, 14, 60, 64, 35, 10, 33}, []uint64{0xA879, 0x1734BE, 0x152703976E, 0x21355A92BC6C, 0x36, 0x720B5521C70C, 0x01, 0x2ACB, 0xA0C06, 0x00, 0x180F, 0x4BBECA66D, 0x12D3D, 0x150646D41C7C, 0x13, 0x768A5A20E9, 0x4CDFD512, 0xCA55F10704A2AA, 0x1E04629707D74C9, 0x145BB39, 0x6A0D42F, 0xA50, 0x1A94, 0x9DC9320DD011407, 0xB2737A46508EF42B, 0x74D073E69, 0x3D6, 0x14EF4EB35}, }, { []byte{0x79, 0xD5, 0x86, 0x52, 0x20, 0xE8, 0xC2, 0x30, 0x48, 0xBC, 0x55, 0xC3, 0x16, 0x7C, 0xAA, 0xED, 0x94, 0xB2, 0xEC, 0x72, 0xB6, 0x37, 0x2D, 0xDC, 0xC5, 0x32, 0xD7, 0x37, 0xEC, 0x9F, 0xBF, 0x05, 0x83, 0x87, 0x82, 0x02, 0xE9, 0xDF, 0x9A, 0x27, 0x20, 0x18, 0xC4, 0x63, 0x9B, 0x2B, 0x74, 0xFB, 0xC9, 0xBD, 0xE2, 0xF0, 0xD6, 0xB7, 0x88, 0x28, 0x2B, 0x8F, 0xD1, 0xE5, 0xE0, 0xFC, 0x54, 0x53, 0xC6, 0x3C, 0xD5, 0xC6, 0xCC, 0x18, 0x12, 0xDC, 0xAB, 0x57, 0x56, 0x3A, 0xCC, 0x3A, 0x42, 0x65, 0x30, 0x02, 0xB5, 0x17, 0x69, 0x18, 0x86, 0xB0, 0xC0, 0xE8, 0x65, 0x96, 0xBB, 0x24, 0x42, 0xCA, 0x60, 0x74, 0x3E, 0x4E}, []uint{49, 12, 22, 14, 60, 8, 49, 19, 64, 29, 5, 37, 17, 56, 40, 3, 4, 19, 29, 45, 6, 51, 14, 10, 53, 48, 37}, []uint64{0xF3AB0CA441D1, 0x846, 0x245E2, 0x2B86, 0x2CF955DB2965D8E, 0x56, 0x18DCB77314CB5, 0x66FD9, 0x3F7E0B070F0405D3, 0x17E689C8, 0x00, 0x18C4639B2B, 0xE9F7, 0x937BC5E1AD6F10, 0x50571FA3CB, 0x06, 0x00, 0x7E2A2, 0x13C63CD5, 0x18D983025B95, 0x1A, 0x5D58EB30E9099, 0x1300, 0xAD, 0x8BB48C4358607, 0x432CB5D92216, 0xA60743E4E}, }, { []byte{0x1D, 0x25, 0xA6, 0x20, 0x3A, 0x6C, 0x00, 0xE9, 0xD1, 0x02, 0xD0, 0xA1, 0xB6, 0xEF, 0xA5, 0x89, 0x34, 0xCC, 0x79, 0x82, 0x7E, 0x3A, 0x46, 0x57, 0xF5, 0x83, 0x6E, 0xAE, 0xF2, 0x43, 0x25, 0xA5, 0xD5, 0xF0, 0x9B, 0x8E, 0xDD, 0x0F, 0xCC, 0x8E, 0x0C, 0xD7, 0xB1, 0xC3, 0x56, 0x9F, 0xA0, 0x2A, 0x9D, 0x0C, 0x37, 0xD1, 0xBD, 0x13, 0x67, 0x31, 0xD4, 0x84, 0xD3, 0xE9, 0xCE, 0xB2, 0x34, 0xDB, 0xFC, 0x31, 0x75, 0xCD, 0x70, 0x08, 0x4C, 0x71, 0x75, 0xDD, 0x8F, 0x3F, 0xD5, 0xFA, 0xC3, 0x24, 0xE8, 0xC0, 0x10, 0x9B, 0x7C, 0xF9, 0xCA, 0xE9, 0x54, 0x21, 0xD8, 0xE3, 0x8D, 0x31, 0xA3, 0x39, 0xA5, 0xC4, 0xF3, 0xFC}, []uint{32, 13, 52, 46, 22, 7, 13, 37, 50, 64, 63, 60, 52, 42, 57, 35, 35, 54, 35, 31}, []uint64{0x1D25A620, 0x74D, 0x801D3A205A143, 0x1B77D2C49A66, 0xF304F, 0x63, 0x148C, 0x15FD60DBAB, 0x2F24325A5D5F0, 0x9B8EDD0FCC8E0CD7, 0x58E1AB4FD0154E86, 0x1BE8DE89B398EA4, 0x269F4E7591A6D, 0x3F862EB9AE0, 0x2131C5D7763CFF, 0x2BF58649D, 0xC0109B7C, 0x3E72BA55087638, 0x71A634673, 0x25C4F3FC}, }, { []byte{0x68, 0x5A, 0x69, 0x38, 0xFD, 0x40, 0x54, 0xB3, 0x83, 0x36, 0x19, 0x7E, 0x49, 0x98, 0x71, 0xA3, 0x2A, 0x61, 0xF7, 0xE7, 0x8A, 0x7E, 0x6B, 0x1A, 0xB8, 0x98, 0x47, 0x80, 0x1A, 0x45, 0x10, 0xDC, 0xD7, 0x19, 0x89, 0xBF, 0xF0, 0x6A, 0x58, 0xFF, 0x62, 0xE4, 0xEC, 0x13, 0x4C, 0x50, 0x88, 0xFA, 0xFC, 0xA6, 0x12, 0xA6, 0xB3, 0xA4, 0xDB, 0x1E, 0x4C, 0xA4, 0x6D, 0x6B, 0xA2, 0xE1, 0xB7, 0x38, 0x47, 0x98, 0x64, 0xF9, 0xBD, 0xC2, 0x52, 0xB9, 0x85, 0x5A, 0xAA, 0x08, 0x67, 0xC9, 0xA6, 0x10, 0x6C, 0x9F, 0xB1, 0x85, 0xAB, 0x93, 0x8E, 0x27, 0x9E, 0x5A, 0xD8, 0x4B, 0xAB, 0x1D, 0x07, 0x24, 0x5A, 0x92, 0xE8, 0xFE}, []uint{53, 49, 47, 35, 53, 37, 62, 62, 2, 44, 23, 43, 10, 31, 49, 39, 56, 4, 58, 43}, []uint64{0xD0B4D271FA80A, 0x12CE0CD865F92, 0x330E34654C3E, 0x7E78A7E6B, 0x3571308F00348, 0x1443735C66, 0x9BFF06A58FF62E4, 0x3B04D314223EBF29, 0x02, 0x12A6B3A4DB1, 0x726523, 0x35AE8B86DCE, 0x47, 0x4C327CDE, 0x1C252B9855AAA, 0x433E4D308, 0x364FD8C2D5C9C7, 0x01, 0xF3CB5B097563A0, 0x7245A92E8FE}, }, { []byte{0x81, 0xB5, 0xA2, 0x65, 0x98, 0x2C, 0x6B, 0x6B, 0xC7, 0x8F, 0x17, 0x8A, 0xE9, 0x66, 0xF9, 0x70, 0x5D, 0xCE, 0x2F, 0x35, 0xC3, 0xB7, 0xEC, 0xB8, 0x3F, 0xA1, 0xB8, 0x6F, 0x08, 0x31, 0xAB, 0x93, 0x9E, 0x7C, 0xFB, 0x43, 0x1C, 0xA4, 0xB6, 0xD1, 0x89, 0xD3, 0x4F, 0xD4, 0x2A, 0x89, 0x72, 0x13, 0x50, 0xB9, 0x02, 0xC7, 0x6A, 0x98, 0xE0, 0x3F, 0x75, 0x33, 0x61, 0x36, 0x8F, 0x7B, 0xC7, 0x8F, 0x7F, 0x78, 0x21, 0xC1, 0xD1, 0x73, 0x7D, 0xCE, 0x8C, 0xD6, 0xB3, 0x20, 0x9C, 0xAF, 0x5A, 0x57, 0x8B, 0xE5, 0xC6, 0xA4, 0xCA, 0x76, 0x1E, 0x50, 0x20, 0x43, 0x87, 0xE4, 0xCE, 0x0F, 0x89, 0x21, 0x64, 0x65, 0x9B, 0xD3}, []uint{1, 15, 30, 2, 9, 48, 40, 45, 20, 27, 29, 1, 13, 35, 47, 59, 24, 38, 50, 39, 37, 8, 54, 46, 14, 58, 11}, []uint64{0x01, 0x1B5, 0x2899660B, 0x00, 0xD6, 0xD78F1E2F15D2, 0xCDF2E0BB9C, 0xBCD70EDFB2E, 0xFE86, 0x70DE106, 0x6AE4E79, 0x01, 0x1CFB, 0x218E525B6, 0x46274D3F50AA, 0x12E426A172058ED, 0x531C07, 0x3BA99B09B4, 0x1EF78F1EFEF04, 0x1C1D1737DC, 0x1D19AD6641, 0x39, 0x17AD2BC5F2E352, 0x194EC3CA0408, 0x1C3F, 0x99C1F1242C8CB3, 0x3D3}, }, { []byte{0x71, 0xF3, 0xAA, 0x6E, 0x84, 0xDF, 0xE6, 0x77, 0xA6, 0xC2, 0xAE, 0x13, 0x8C, 0x9E, 0xDF, 0xFA, 0x68, 0x97, 0x18, 0x10, 0x2D, 0x29, 0xE9, 0x8A, 0xBF, 0xA3, 0xB6, 0x34, 0x93, 0xA0, 0x81, 0xE6, 0xBB, 0xB2, 0x2B, 0xCC, 0x6C, 0x2E, 0xD2, 0xD0, 0x97, 0xB8, 0x7B, 0x41, 0x3D, 0x11, 0xFB, 0xFC, 0xE0, 0xE3, 0x5B, 0x75, 0xE4, 0x6A, 0x28, 0x88, 0x0A, 0x2D, 0x41, 0x6B, 0x00, 0xE3, 0xB8, 0xA1, 0x98, 0x45, 0x63, 0xD1, 0x89, 0xF1, 0xDD, 0xE5, 0xAB, 0xB8, 0x07, 0xA1, 0x7A, 0xDF, 0xA6, 0xF4, 0x89, 0x6D, 0x41, 0x90, 0xA2, 0x3B, 0x79, 0x07, 0xA6, 0xFE, 0xB5, 0x19, 0x32, 0x0D, 0x7E, 0x8F, 0x37, 0x49, 0xB1, 0x1F}, []uint{18, 39, 32, 4, 63, 43, 56, 45, 45, 5, 15, 29, 6, 33, 52, 33, 44, 44, 21, 32, 57, 45, 23, 16}, []uint64{0x1C7CE, 0x54DD09BFCC, 0xEF4D855C, 0x02, 0x38C9EDFFA6897181, 0x1694F4C55F, 0xD1DB1A49D040F3, 0xBBB22BCC6C2, 0x1DA5A12F70F6, 0x10, 0x27A2, 0x7EFF383, 0x23, 0xB6EBC8D4, 0x5110145A82D60, 0x38EE2866, 0x1158F4627C7, 0x7796AEE01E8, 0xBD6FD, 0x37A44B6A, 0x190A23B7907A6F, 0x1D6A32641AFD, 0xF3749, 0xB11F}, }, { []byte{0xAC, 0x14, 0xB0, 0x1B, 0x9B, 0xF6, 0x27, 0xD0, 0xB0, 0xB4, 0x78, 0xD8, 0x72, 0x2F, 0x7B, 0x35, 0x27, 0x93, 0xD7, 0x03, 0xBE, 0x3D, 0x08, 0x38, 0xA4, 0x4F, 0x77, 0xC6, 0x93, 0x8C, 0xDF, 0x54, 0x7B, 0x25, 0x14, 0xDB, 0xF4, 0x3A, 0x1B, 0xB0, 0x20, 0x0C, 0x7A, 0x40, 0x15, 0xE4, 0xCE, 0x72, 0x9E, 0x50, 0x05, 0x85, 0xFE, 0x5A, 0xDA, 0x51, 0xC1, 0x10, 0x35, 0xB6, 0x93, 0x7D, 0xE1, 0x29, 0x8A, 0xA1, 0x64, 0xCB, 0xD7, 0x43, 0x53, 0x6F, 0x1A, 0x31, 0x83, 0x1E, 0x90, 0xFF, 0x5D, 0x99, 0xF8, 0xF1, 0xB4, 0xBD, 0x91, 0xEF, 0xF3, 0xB7, 0x70, 0x71, 0x1D, 0x09, 0x4B, 0x8A, 0x94, 0x47, 0x86, 0xDF, 0xB9, 0x73}, []uint{63, 40, 4, 14, 10, 41, 30, 19, 11, 22, 20, 18, 17, 26, 63, 12, 39, 8, 12, 7, 23, 64, 2, 57, 48, 5, 26, 18, 31, 29, 21}, []uint64{0x560A580DCDFB13E8, 0x585A3C6C39, 0x01, 0x1EF6, 0x1A9, 0x793D703BE3, 0x3420E291, 0x1EEF8, 0x693, 0x2337D5, 0x1EC94, 0x14DBF, 0x8743, 0x1D81006, 0x1E900579339CA794, 0x16, 0xBFCB5B4A3, 0x82, 0x206, 0x5B, 0x349BEF, 0x94C550B265EBA1A, 0x02, 0xDBC68C60C7A43F, 0xD7667E3C6D2F, 0x0C, 0x23DFE76, 0x3B838, 0x474252E2, 0x14A23C36, 0x1FB973}, }, { []byte{0xE4, 0x50, 0xCC, 0x46, 0xE5, 0x6C, 0xB4, 0x5E, 0x7D, 0x27, 0x6A, 0x12, 0x75, 0x27, 0x71, 0xB2, 0x5F, 0xCD, 0x62, 0x8E, 0x39, 0x4C, 0x93, 0xAB, 0x74, 0x84, 0x7D, 0x73, 0x72, 0x69, 0x2B, 0x3E, 0x09, 0x98, 0x75, 0xCE, 0xEA, 0xCE, 0x41, 0x90, 0x1B, 0x5E, 0x43, 0x77, 0x9F, 0x03, 0x45, 0xD5, 0x5C, 0xE2, 0xED, 0x27, 0xF9, 0x3C, 0x74, 0x7B, 0x43, 0x46, 0x74, 0x48, 0xBA, 0x17, 0x38, 0xD5, 0x20, 0xE5, 0xA0, 0xF4, 0xF6, 0xF2, 0xDD, 0x35, 0x11, 0xDC, 0x2C, 0x05, 0x24, 0xF9, 0x32, 0x87, 0xF2, 0x46, 0x5C, 0x38, 0x5F, 0x30, 0xD5, 0xE5, 0xCA, 0x7B, 0xB2, 0x84, 0x2B, 0x52, 0x79, 0x1E, 0xA2, 0xA7, 0xF2, 0xE5}, []uint{36, 51, 25, 30, 33, 48, 1, 40, 47, 24, 52, 35, 50, 19, 46, 35, 49, 42, 43, 25, 3, 46, 20}, []uint64{0xE450CC46E, 0x2B65A2F3E93B5, 0x127527, 0x1C6C97F3, 0xB1471CA6, 0x49D5BA423EB9, 0x01, 0x72692B3E09, 0x4C3AE7756720, 0xC80DAF, 0x21BBCF81A2EAA, 0x738BB49FE, 0x13C747B434674, 0x245D0, 0x2E71AA41CB41, 0x74F6F2DD3, 0xA23B8580A49F, 0x9943F9232E, 0xE17CC35797, 0x53DD94, 0x01, 0x2B52791EA2A, 0x7F2E5}, }, { []byte{0x62, 0x1F, 0x77, 0x6B, 0x70, 0x29, 0x95, 0x1E, 0xE8, 0xF4, 0xFB, 0x70, 0x7C, 0x70, 0xB6, 0x51, 0xF6, 0xD5, 0xD8, 0x16, 0x6D, 0xB0, 0x7D, 0x7F, 0xE3, 0x3A, 0x1C, 0x01, 0x3C, 0x72, 0xD5, 0x19, 0x42, 0x22, 0xE9, 0xCB, 0x6E, 0xF5, 0x4F, 0x63, 0xAA, 0x74, 0xDA, 0x86, 0x06, 0xB0, 0x0E, 0x2B, 0xF1, 0xD8, 0x12, 0x3D, 0x78, 0xCD, 0x60, 0x4F, 0xE4, 0x24, 0x18, 0xE9, 0xB2, 0x8A, 0xAC, 0xB4, 0x95, 0x53, 0x1D, 0x31, 0xDF, 0x2C, 0x24, 0x59, 0x32, 0x26, 0xFC, 0xDE, 0x18, 0x5A, 0x10, 0x25, 0x66, 0xDF, 0x5D, 0xFB, 0x4F, 0xC6, 0x40, 0xBC, 0x81, 0x51, 0xB1, 0xC5, 0xC7, 0xED, 0x68, 0xEF, 0xEF, 0x03, 0xD1, 0x3B}, []uint{43, 47, 64, 7, 19, 26, 16, 29, 30, 10, 17, 28, 35, 31, 49, 46, 25, 43, 18, 14, 24, 58, 17, 2, 22, 22, 18, 40}, []uint64{0x310FBBB5B81, 0x26547BA3D3ED, 0xC1F1C2D947DB5760, 0x2C, 0x6DB07, 0x35FF8CE, 0x8700, 0x9E396A8, 0x328445D3, 0x25B, 0xEF54, 0xF63AA74, 0x6D4303580, 0x38AFC760, 0x91EBC66B027F, 0x84831D36515, 0xB2D255, 0x263A63BE584, 0x22C99, 0x4DF, 0x9BC30B, 0x10812B36FAEFDA7, 0x1C640, 0x02, 0x3C8151, 0x2C7171, 0x3ED68, 0xEFEF03D13B}, }, { []byte{0xCD, 0x82, 0x19, 0x41, 0x84, 0x11, 0x69, 0x22, 0x42, 0x4E, 0xA2, 0x7B, 0xF6, 0x52, 0xC1, 0x02, 0x54, 0x2D, 0xFB, 0x27, 0x0E, 0x8C, 0x34, 0x0A, 0xCE, 0x0E, 0x4F, 0x05, 0x94, 0x9D, 0xF2, 0x5A, 0xCB, 0x48, 0x05, 0xA3, 0x38, 0x41, 0xDE, 0x45, 0x83, 0x4F, 0x0B, 0xBF, 0x11, 0x7A, 0x01, 0x5A, 0x30, 0x93, 0x0F, 0x18, 0x86, 0x95, 0x95, 0x7E, 0x3C, 0x73, 0xB4, 0x45, 0x5F, 0xE0, 0x3B, 0xA1, 0xCA, 0x5B, 0x6E, 0x12, 0xCE, 0xF7, 0xC1, 0x48, 0x89, 0xFA, 0x79, 0x8B, 0xD2, 0x7D, 0xCC, 0x75, 0x5C, 0xF4, 0x8D, 0x72, 0x54, 0xD5, 0xED, 0x47, 0x8E, 0x6E, 0x0E, 0x18, 0x0F, 0x1B, 0xB6, 0xA3, 0x62, 0x32, 0xB2, 0xB3}, []uint{43, 57, 38, 50, 12, 62, 63, 24, 14, 12, 14, 42, 6, 17, 10, 51, 53, 7, 58, 1, 4, 20, 14, 29, 35, 30, 5, 29}, []uint64{0x66C10CA0C20, 0x116922424EA27BF, 0x194B040950, 0x2DFB270E8C340, 0xACE, 0x393C165277C96B2, 0x6900B467083BC8B0, 0x69E177, 0x388B, 0xD00, 0x2B46, 0x49878C434A, 0x32, 0x15F8F, 0x73, 0x5A22AFF01DD0E, 0xA5B6E12CEF7C1, 0x24, 0x113F4F317A4FB98, 0x01, 0x0D, 0x573D2, 0xD72, 0xA9ABDA8, 0x78E6E0E18, 0x3C6EDA8, 0x1B, 0x232B2B3}, }, { []byte{0x34, 0xFA, 0x8F, 0x98, 0x59, 0x1E, 0xE3, 0x3E, 0x39, 0xCE, 0x5F, 0x3C, 0xBB, 0xEF, 0xBB, 0xE9, 0xE2, 0xA0, 0x31, 0x73, 0x67, 0x50, 0x0C, 0xF0, 0x94, 0xCC, 0x5F, 0x23, 0xF9, 0x86, 0x9D, 0xF8, 0xBD, 0xF7, 0xB9, 0x91, 0xB7, 0x06, 0xF5, 0xE0, 0x50, 0x6C, 0x2C, 0xF9, 0xE6, 0xE8, 0x2B, 0xDC, 0xBA, 0xBC, 0x02, 0x90, 0xBF, 0xF7, 0x63, 0x91, 0xF3, 0x4D, 0xAF, 0x53, 0x8D, 0xAC, 0xAE, 0xC3, 0x44, 0x24, 0xE6, 0x90, 0xCC, 0xB0, 0x16, 0x12, 0x6E, 0x35, 0x0B, 0x77, 0x2C, 0xF1, 0xF5, 0xE3, 0xA1, 0x82, 0x58, 0x2C, 0x0E, 0x64, 0xCC, 0x98, 0x39, 0x5D, 0x92, 0x91, 0xBE, 0x50, 0xC7, 0x27, 0x0C, 0x12, 0xF4, 0x0E}, []uint{23, 44, 62, 40, 13, 51, 6, 42, 31, 59, 29, 37, 37, 23, 23, 41, 64, 42, 44, 8, 63, 18}, []uint64{0x1A7D47, 0xCC2C8F719F1, 0x339CBE7977DF77D3, 0xC54062E6CE, 0x1403, 0x1E12998BE47F3, 0x03, 0x13BF17BEF73, 0x11B706F5, 0x702836167CF3741, 0xBDCBABC, 0x5217FEEC, 0xE47CD36BD, 0x271B59, 0x2EC344, 0x49CD219960, 0x2C24DC6A16EE59E3, 0x3AF1D0C12C1, 0x60732664C1C, 0xAE, 0x64A46F9431C9C304, 0x2F40E}, }, { []byte{0xA8, 0xC6, 0x63, 0x71, 0x15, 0xAF, 0x2F, 0x1D, 0x44, 0x45, 0xC8, 0xCC, 0x64, 0xED, 0x7E, 0xB7, 0xC5, 0x8A, 0xC1, 0x2A, 0xF9, 0xA0, 0x9E, 0x6B, 0xD2, 0x1E, 0xC7, 0x83, 0x6C, 0x44, 0x73, 0x04, 0x5F, 0xD8, 0x31, 0x89, 0xCF, 0xA2, 0x2C, 0xDE, 0xCF, 0x5F, 0xF3, 0xE6, 0xCF, 0x88, 0x7A, 0xE9, 0x3F, 0xD2, 0x23, 0x25, 0x9D, 0x4F, 0xF4, 0xC3, 0x39, 0xB9, 0x60, 0xCA, 0x31, 0xD2, 0xFC, 0xF3, 0xC1, 0x29, 0xC8, 0x5C, 0x05, 0x95, 0xA1, 0xB7, 0x72, 0xC9, 0x8B, 0x85, 0xFD, 0x18, 0xCB, 0x05, 0x9B, 0x11, 0xD8, 0xEA, 0xF6, 0x4E, 0xB2, 0xDA, 0x35, 0xEC, 0xDD, 0x75, 0x3E, 0xCC, 0xCE, 0x5F, 0x3A, 0xFB, 0xC3, 0x01}, []uint{2, 38, 8, 59, 17, 7, 23, 38, 34, 52, 45, 60, 36, 45, 22, 55, 6, 9, 26, 11, 37, 37, 19, 56, 27, 31}, []uint64{0x02, 0x28C6637115, 0xAF, 0x178EA222E466327, 0xD7EB, 0x3E, 0x162B04, 0x2AF9A09E6B, 0x3487B1E0D, 0xB111CC117F60C, 0xC4E7D1166F6, 0x7AFF9F367C43D74, 0x9FE91192C, 0x1D4FF4C339B9, 0x18328C, 0x3A5F9E7825390B, 0x20, 0x59, 0x1686DDC, 0x593, 0x2E17F4632, 0x182CD88EC7, 0x2BD93, 0xACB68D7B375D4F, 0x5999CBE, 0x3AFBC301}, }, { []byte{0x2B, 0x17, 0x50, 0xEA, 0x8B, 0xD1, 0x09, 0x00, 0x9C, 0x2E, 0x3C, 0x07, 0x3B, 0x0D, 0xFC, 0x07, 0xAA, 0xD1, 0x55, 0x1E, 0x37, 0x40, 0xE0, 0xBB, 0xC5, 0x38, 0x40, 0x64, 0xF5, 0x3C, 0x0B, 0x0B, 0x37, 0x76, 0x43, 0xDA, 0x7F, 0x01, 0x63, 0x03, 0xA3, 0xF9, 0xD8, 0x06, 0x93, 0x4C, 0xF0, 0x01, 0xE6, 0x86, 0xAA, 0x94, 0x35, 0xD5, 0xB3, 0xA2, 0x1D, 0xB6, 0x2A, 0x40, 0x83, 0xFE, 0x63, 0x2E, 0x40, 0x81, 0x42, 0x11, 0xC4, 0x61, 0x9A, 0xAF, 0x08, 0x0D, 0x36, 0x20, 0x32, 0x67, 0xEA, 0x49, 0xF4, 0x26, 0xA5, 0x8D, 0xF4, 0xFD, 0xAC, 0x15, 0xB2, 0x5B, 0x97, 0x49, 0xC2, 0xDE, 0x1D, 0x79, 0x43, 0xD8, 0x20, 0x63}, []uint{58, 27, 18, 25, 4, 25, 47, 9, 22, 36, 4, 53, 13, 53, 15, 15, 2, 54, 34, 62, 62, 37, 41, 34, 50}, []uint64{0xAC5D43AA2F4424, 0x1385C7, 0x2039D, 0x10DFC07, 0x0A, 0x15A2AA3, 0x63740E0BBC53, 0x108, 0x327A9, 0xE05859BBB, 0x02, 0x3DA7F016303A3, 0x1F3B, 0x1A4D33C0079A, 0xD55, 0x1435, 0x03, 0x15B3A21DB62A40, 0x20FF98CB9, 0x814211C4619AAF, 0x2034D880C99FA92, 0xFA1352C6F, 0x14FDAC15B25, 0x2E5D270B7, 0x21D7943D82063}, }, { []byte{0x93, 0x6A, 0xA0, 0xA2, 0xA9, 0x33, 0x42, 0x9C, 0x74, 0x54, 0x5E, 0x06, 0x0E, 0xE2, 0x05, 0x9E, 0x8F, 0xCC, 0x56, 0xBC, 0x59, 0xBD, 0xAF, 0x76, 0x71, 0x9C, 0x06, 0x88, 0x42, 0x5A, 0xBC, 0x12, 0x29, 0x1C, 0x48, 0x11, 0x96, 0xA0, 0x78, 0x15, 0x6D, 0xDE, 0x8F, 0xF4, 0xBC, 0x9D, 0xB1, 0x4B, 0xEB, 0xDC, 0x9F, 0x6B, 0x70, 0xE3, 0x77, 0x32, 0x42, 0xAE, 0x35, 0x82, 0x8A, 0xD9, 0x1E, 0x26, 0x33, 0xA2, 0x51, 0xD9, 0x2B, 0xAE, 0x07, 0xBF, 0x8B, 0x14, 0x8D, 0x53, 0xC5, 0xFF, 0xE4, 0x27, 0x9F, 0x10, 0xC3, 0x2B, 0x4B, 0x90, 0x9F, 0xB2, 0x99, 0x38, 0xA7, 0xB4, 0xD2, 0xA4, 0x4B, 0xF3, 0x5D, 0x52, 0x94, 0xD2}, []uint{29, 7, 49, 40, 43, 23, 4, 17, 13, 29, 59, 63, 8, 25, 2, 28, 49, 27, 50, 14, 6, 5, 22, 20, 3, 35, 32, 19, 12, 48, 19}, []uint64{0x126D5414, 0x2A, 0x12668538E8A8B, 0xC0C1DC40B3, 0x68FCC56BC59, 0x5ED7BB, 0x03, 0x119C0, 0xD10, 0x1096AF04, 0x4523890232D40F0, 0x156DDE8FF4BC9DB1, 0x4B, 0x1D7B93E, 0x03, 0x5B871BB, 0x13242AE35828A, 0x6C8F131, 0x2744A3B2575C0, 0x3DFC, 0x16, 0x05, 0x8D53C, 0x5FFE4, 0x01, 0x1E7C430CA, 0xD2E427EC, 0x53271, 0x4F6, 0x9A54897E6BAA, 0x294D2}, }, { []byte{0x41, 0x7C, 0x00, 0xB7, 0x0A, 0x88, 0x91, 0x50, 0x11, 0x1E, 0x2D, 0xDC, 0xA6, 0xF0, 0x3D, 0xDE, 0xC4, 0x37, 0xD7, 0x61, 0x65, 0x8D, 0x2B, 0x3A, 0x94, 0xAB, 0x46, 0xC3, 0x9D, 0xD1, 0x8B, 0x38, 0x7B, 0x5F, 0x17, 0xB5, 0xFF, 0x73, 0xE1, 0xAB, 0x17, 0x34, 0x4B, 0x0F, 0x5B, 0xB7, 0x84, 0x94, 0x06, 0xB1, 0x01, 0x15, 0x57, 0x4C, 0x77, 0xBF, 0xF8, 0x31, 0x6C, 0x2D, 0xDB, 0x80, 0x94, 0x7F, 0x70, 0xF5, 0x9F, 0xB9, 0xAF, 0xEB, 0x79, 0x15, 0xD5, 0xCF, 0x69, 0x55, 0x39, 0x69, 0xF0, 0x2E, 0xEB, 0x7F, 0x98, 0x8F, 0x9D, 0x51, 0x8B, 0x5F, 0xC0, 0xD1, 0x3F, 0xAB, 0xA7, 0x6B, 0x27, 0xED, 0x5C, 0x81, 0x42, 0x87}, []uint{43, 57, 36, 34, 17, 2, 53, 49, 40, 39, 30, 24, 9, 35, 21, 28, 19, 53, 4, 53, 57, 53, 12, 22, 10}, []uint64{0x20BE005B854, 0x89150111E2DDCA, 0x6F03DDEC4, 0xDF5D8596, 0x6959, 0x03, 0xA52AD1B0E7746, 0x59C3DAF8BDAF, 0xFB9F0D58B9, 0x512C3D6EDE, 0x49406B1, 0x11557, 0x98, 0x77BFF8316, 0x185BB7, 0x128FEE, 0xF59F, 0x1735FD6F22BAB9, 0x0E, 0x1A554E5A7C0BBA, 0x1BFCC47CEA8C5AF, 0x1C0D13FABA76B2, 0x7ED, 0x172050, 0x287}, }, { []byte{0x62, 0x94, 0x17, 0x81, 0xEB, 0x57, 0xC8, 0x95, 0x9F, 0x6D, 0x5E, 0xB5, 0xB7, 0x75, 0xE0, 0x67, 0xB5, 0x74, 0xBB, 0x0D, 0xCE, 0xA3, 0x1A, 0x2A, 0xC7, 0x51, 0x0E, 0x1B, 0x08, 0x9E, 0xA2, 0xFC, 0x01, 0x20, 0xBF, 0xA3, 0x6B, 0xAC, 0x4B, 0x5B, 0x25, 0x35, 0xE1, 0x2A, 0x6F, 0xD2, 0x27, 0x6C, 0x29, 0x3C, 0x8A, 0x7E, 0x1C, 0x0D, 0xCD, 0x6A, 0x0B, 0x51, 0x7F, 0x12, 0x4D, 0xE8, 0xAC, 0x16, 0x18, 0x83, 0x16, 0xFD, 0xFE, 0x01, 0xA1, 0xC7, 0xF9, 0x6A, 0xBB, 0x48, 0x76, 0x98, 0xF0, 0x09, 0xE3, 0x9A, 0x2F, 0x83, 0xDF, 0x55, 0x4D, 0x41, 0xDC, 0x6F, 0x39, 0xA4, 0xEA, 0x6D, 0x3E, 0x4D, 0xD3, 0xE7, 0x8F, 0xFB}, []uint{20, 19, 52, 17, 9, 10, 40, 5, 57, 24, 46, 25, 24, 11, 18, 13, 24, 39, 8, 27, 34, 11, 53, 48, 36, 44, 36, 50}, []uint64{0x62941, 0x3C0F5, 0xABE44ACFB6AF5, 0x15B77, 0xBC, 0x33, 0xDABA5D86E7, 0x0A, 0x634558EA21C361, 0x13D45F, 0x200905FD1B5D, 0xC4B5B2, 0x535E12, 0x537, 0x3A44E, 0x1B0A, 0x4F229F, 0x4381B9AD41, 0x6A, 0x17F124D, 0x3A2B05862, 0x62, 0x1BF7F806871FE5, 0xAAED21DA63C0, 0x278E68BE0, 0xF7D55350771, 0xBCE693A9B, 0x13E4DD3E78FFB}, }, { []byte{0x6B, 0x8C, 0x0C, 0x85, 0x7A, 0x48, 0x0C, 0xBA, 0x1D, 0x28, 0x30, 0xB4, 0x23, 0xA2, 0x16, 0x85, 0x62, 0x13, 0x29, 0x59, 0x81, 0x4E, 0x23, 0xDC, 0xA7, 0xD7, 0x85, 0x14, 0x4B, 0xD8, 0x8E, 0xA7, 0xD7, 0xC2, 0x3A, 0xD2, 0x86, 0x60, 0xA0, 0xBE, 0x6A, 0x22, 0xCD, 0xF1, 0x07, 0x75, 0xD2, 0x48, 0x9A, 0xEA, 0x56, 0x3D, 0x16, 0x70, 0xEF, 0x9F, 0xF5, 0xC2, 0x94, 0x86, 0x4C, 0x21, 0x29, 0x85, 0x9A, 0x84, 0x52, 0xF4, 0x41, 0xAC, 0xC5, 0x17, 0xD9, 0x72, 0xBE, 0xBA, 0x88, 0x38, 0xC2, 0xD2, 0x7D, 0xB3, 0xC1, 0x7A, 0x93, 0x61, 0x35, 0xEF, 0x34, 0xB3, 0x92, 0xA0, 0x7A, 0x34, 0x7B, 0x4D, 0x93, 0xDE, 0x1C, 0x46}, []uint{61, 42, 37, 33, 39, 19, 40, 14, 62, 26, 60, 57, 36, 52, 19, 64, 51, 33, 55}, []uint64{0xD718190AF490197, 0x10E94185A11, 0x1A21685621, 0x652B3029, 0x623DCA7D78, 0x28A25, 0xEC4753EBE1, 0x75A, 0x14330505F351166F, 0x220EEBA, 0x49135D4AC7A2CE1, 0x1BE7FD70A521930, 0x84A6166A1, 0x14BD106B3145F, 0x32E57, 0xD75107185A4FB678, 0x17A936135EF34, 0x1672540F4, 0x347B4D93DE1C46}, }, { []byte{0xC8, 0x0A, 0xF4, 0xE9, 0x19, 0x51, 0xA6, 0xEA, 0x2C, 0x73, 0xB2, 0x54, 0xCE, 0x8B, 0x7D, 0x94, 0xDC, 0xB5, 0x38, 0x27, 0x6E, 0xD0, 0x3A, 0x1E, 0xA2, 0x09, 0x63, 0x7B, 0x9E, 0x2B, 0x7F, 0x8C, 0x9E, 0x49, 0x42, 0x8A, 0x15, 0xDF, 0xF7, 0xF9, 0xDF, 0xCA, 0xE3, 0xB5, 0x3D, 0x4F, 0xE0, 0x67, 0x7C, 0xC5, 0x77, 0x59, 0x1C, 0x51, 0x28, 0xD0, 0x0A, 0xE7, 0x4A, 0x14, 0xE5, 0x49, 0xF9, 0xA1, 0x49, 0x08, 0x3B, 0xE7, 0x3D, 0xC2, 0xB9, 0x95, 0x06, 0x8A, 0xA3, 0x7F, 0x63, 0x9E, 0x7F, 0x87, 0x67, 0xFC, 0x63, 0x54, 0x98, 0x00, 0x15, 0x3D, 0x4F, 0x99, 0xCD, 0x0F, 0x4A, 0xCC, 0x0D, 0x03, 0x16, 0x69, 0xB6, 0x67}, []uint{33, 50, 24, 24, 5, 53, 5, 61, 26, 56, 35, 50, 2, 22, 59, 54, 8, 7, 48, 13, 14, 27, 42, 37, 42, 3}, []uint64{0x19015E9D2, 0xCA8D3751639D, 0x92A674, 0x5BECA6, 0x1C, 0x16A704EDDA0743, 0x1A, 0x1104B1BDCF15BFC6, 0x13C9285, 0x142BBFEFF3BF95, 0x63B53D4FE, 0x19DF315DD647, 0x00, 0x144A34, 0x15CE9429CA93F3, 0x10A4841DF39EE1, 0x5C, 0x65, 0x41A2A8DFD8E7, 0x13FC, 0xECF, 0x7C63549, 0x200054F53E6, 0xE687A5660, 0x1A062CD36CC, 0x07}, }, { []byte{0x83, 0x89, 0x65, 0xAD, 0xCF, 0xD1, 0xA9, 0x1F, 0xB5, 0x29, 0x97, 0x34, 0xA0, 0x5C, 0x67, 0xEC, 0x10, 0x7C, 0xB5, 0xB9, 0xB1, 0x3F, 0x70, 0xCD, 0x54, 0x37, 0xCF, 0x1A, 0x0A, 0xF8, 0x7C, 0x68, 0xF1, 0x7A, 0x4E, 0x69, 0x53, 0xAA, 0xBA, 0x8E, 0x42, 0xC8, 0x49, 0x28, 0xB4, 0xED, 0x55, 0x08, 0x88, 0x0D, 0xAF, 0xF1, 0x34, 0x2B, 0x4A, 0x14, 0x2F, 0x00, 0x2E, 0xB7, 0x9B, 0xEE, 0x86, 0x62, 0x25, 0x12, 0x39, 0xF6, 0x12, 0xD6, 0x9F, 0x95, 0x52, 0x68, 0x2F, 0x9B, 0x2E, 0xBC, 0x32, 0xC4, 0xC6, 0x98, 0x99, 0xB6, 0xB9, 0x93, 0x61, 0xA2, 0x07, 0x20, 0x70, 0x1D, 0x1C, 0x9F, 0xC3, 0xCF, 0x72, 0xFA, 0x4A, 0x1B}, []uint{47, 7, 1, 29, 41, 12, 14, 2, 46, 54, 62, 59, 12, 45, 62, 1, 6, 6, 50, 14, 23, 27, 45, 11, 51, 36, 20, 17}, []uint64{0x41C4B2D6E7E8, 0x6A, 0x00, 0x11FB5299, 0xE6940B8CFD, 0x820, 0x3E5A, 0x03, 0x1CD89FB866AA, 0x6F9E3415F0F8D, 0x78BD2734A9D55D4, 0x390B2124A2D3B55, 0x422, 0x406D7F89A15, 0x294285E005D6F37D, 0x01, 0x28, 0x19, 0x22251239F612D, 0x1A7E, 0x2AA4D0, 0x2F9B2EB, 0x1865898D3133, 0x36B, 0x4C9B0D1039038, 0xE8E4FE1E, 0x7B97D, 0x4A1B}, }, { []byte{0x9D, 0xCF, 0xB2, 0x8C, 0xE0, 0xE6, 0xD3, 0xD4, 0xC0, 0x77, 0x4C, 0x43, 0xDB, 0xEE, 0x32, 0xD6, 0x67, 0x9F, 0xED, 0xAA, 0xB6, 0x0C, 0x1D, 0x65, 0x61, 0x02, 0xA1, 0xB0, 0x08, 0xB9, 0x06, 0xCF, 0xA1, 0xD4, 0xE0, 0x54, 0x75, 0x30, 0x59, 0xDA, 0xFE, 0x16, 0x9F, 0x36, 0x88, 0xD4, 0x70, 0x3D, 0xE4, 0x2E, 0x78, 0x17, 0x5F, 0x18, 0x5A, 0x7F, 0x35, 0x31, 0x63, 0xD0, 0xF9, 0xCF, 0x34, 0xD6, 0xDF, 0x7E, 0xB9, 0x07, 0x24, 0x37, 0x2B, 0x5C, 0xFC, 0xD0, 0x3B, 0x32, 0xD4, 0xA7, 0x96, 0x28, 0xD1, 0x23, 0xDA, 0x6C, 0xEA, 0x4C, 0x29, 0x31, 0xB2, 0x20, 0x3C, 0x23, 0xE2, 0xEB, 0x22, 0x78, 0x79, 0xD1, 0xBC, 0xEB}, []uint{49, 29, 9, 37, 23, 47, 33, 37, 49, 15, 60, 35, 21, 35, 36, 5, 9, 45, 31, 23, 18, 64, 13, 58, 19}, []uint64{0x13B9F6519C1CD, 0x14F5301D, 0x1A6, 0x43DBEE32D, 0x333CFF, 0x36AAD8307595, 0x108150D80, 0x8B906CFA1, 0x1A9C0A8EA60B3, 0x5AFE, 0x169F3688D4703DE, 0x2173C0BAF, 0x1185A7, 0x79A98B1E8, 0x7CE79A6B6, 0x1F, 0xFD, 0xE41C90DCAD7, 0x1F9A0766, 0x2D4A79, 0x18A34, 0x48F69B3A930A4C6C, 0x1101, 0x3847C5D644F0F3A, 0x1BCEB}, }, { []byte{0x91, 0x0B, 0x7C, 0xD2, 0x4C, 0xB9, 0x12, 0xA4, 0x56, 0x7E, 0xE5, 0x29, 0xEC, 0x0D, 0xEE, 0xD9, 0xCD, 0x10, 0x96, 0x04, 0xDE, 0xAE, 0x9A, 0x8E, 0xFA, 0x41, 0x7C, 0x47, 0x22, 0x53, 0xD3, 0xBF, 0x1E, 0x78, 0x75, 0xBA, 0x7A, 0x88, 0x06, 0x39, 0xC3, 0x8C, 0x59, 0x79, 0x6B, 0x4F, 0x52, 0x30, 0x08, 0xF6, 0x7E, 0x0A, 0xB9, 0x74, 0xB8, 0x25, 0x9C, 0x20, 0x53, 0x7E, 0x4C, 0xAC, 0xE4, 0x58, 0x38, 0xCC, 0xAA, 0x55, 0xCA, 0xE9, 0x1F, 0x2A, 0xD8, 0x15, 0xB8, 0x53, 0x7D, 0xD3, 0x16, 0x47, 0x96, 0xC2, 0x98, 0x56, 0x35, 0xDB, 0x83, 0x5E, 0xD7, 0xCF, 0xB6, 0x03, 0x6A, 0xBF, 0x7A, 0x6C, 0x7A, 0x54, 0x99, 0x0C}, []uint{34, 58, 36, 43, 41, 55, 14, 6, 6, 12, 62, 43, 34, 27, 12, 29, 46, 25, 51, 13, 36, 42, 35, 40}, []uint64{0x2442DF349, 0xCB912A4567EE52, 0x9EC0DEED9, 0x66884B026F5, 0xE9A8EFA417, 0x6239129E9DF8F3, 0x30EB, 0x1D, 0x0F, 0x510, 0x31CE1C62CBCB5A7, 0x548C023D9F8, 0xAB974B82, 0x2CE1029, 0xBF2, 0xCACE458, 0xE332A9572BA, 0x8F956C, 0x56E14DF74C59, 0x3CB, 0x614C2B1AE, 0x3706BDAF9F6, 0x6036ABF7A, 0x6C7A54990C}, }, { []byte{0xAE, 0x2E, 0x61, 0xAB, 0x47, 0x76, 0x8C, 0x9E, 0x28, 0x13, 0x95, 0x06, 0x9A, 0x10, 0x8A, 0x5B, 0xFD, 0xB2, 0x2F, 0xC5, 0x44, 0x29, 0xB3, 0xBF, 0x5B, 0x39, 0xD5, 0x5A, 0xD2, 0xED, 0x48, 0xA6, 0x09, 0x11, 0x37, 0x9A, 0x18, 0x04, 0xA2, 0xC5, 0x07, 0x94, 0xAF, 0x3F, 0x3C, 0x59, 0x3E, 0x8E, 0xE6, 0x9C, 0x25, 0x03, 0xFC, 0xFA, 0xB3, 0x95, 0xB8, 0xAD, 0x53, 0x12, 0x2F, 0xB9, 0x91, 0x9C, 0xD0, 0x93, 0x52, 0xF8, 0x03, 0x68, 0xD2, 0x72, 0xD4, 0x63, 0x2B, 0xAA, 0xFF, 0x92, 0x8E, 0xFB, 0x82, 0xC4, 0x41, 0xEC, 0x40, 0x0C, 0x9D, 0xFB, 0x40, 0x25, 0x0B, 0x2F, 0xB1, 0x34, 0x05, 0xD7, 0xB4, 0x73, 0xAE, 0x05}, []uint{20, 26, 55, 35, 26, 47, 15, 22, 5, 30, 16, 29, 32, 21, 47, 57, 49, 56, 32, 13, 23, 8, 54, 20, 31, 31}, []uint64{0xAE2E6, 0x6AD1DD, 0x5193C50272A0D3, 0x2108A5BFD, 0x2C8BF15, 0x853677EB673, 0x555A, 0x34BB52, 0x05, 0xC12226F, 0x3430, 0x128B141, 0xE52BCFCF, 0x2C9F4, 0x3B9A70940FF3, 0x1D59CADC56A9891, 0xFB9919CD0935, 0x2F80368D272D46, 0x32BAAFF9, 0x51D, 0x7B82C4, 0x41, 0x3B1003277ED009, 0x42CBE, 0x62680BAF, 0x3473AE05}, }, { []byte{0xC3, 0x42, 0xF8, 0x38, 0x04, 0x5F, 0x4F, 0x7A, 0x7A, 0x2F, 0x32, 0xEC, 0xE5, 0x0F, 0xDD, 0x4C, 0x16, 0x10, 0x31, 0x0A, 0xF0, 0xAE, 0x6D, 0xE1, 0xEB, 0xE3, 0x4E, 0x11, 0x30, 0x6C, 0xC1, 0xA8, 0xA6, 0xB5, 0x33, 0xD3, 0x58, 0x03, 0xBF, 0x16, 0x09, 0x37, 0x4D, 0xE7, 0xE9, 0x82, 0xCC, 0xBC, 0xFA, 0x12, 0x4D, 0xAC, 0xF6, 0x53, 0x22, 0xBD, 0xF7, 0xFD, 0x22, 0x77, 0xEC, 0x5B, 0xD1, 0xC4, 0xA2, 0x97, 0xC9, 0x04, 0x1C, 0x62, 0x7B, 0xD4, 0x03, 0x82, 0x21, 0x22, 0x2B, 0x20, 0xC6, 0x0D, 0xF8, 0xAA, 0x03, 0xC0, 0x30, 0x21, 0x31, 0xF0, 0xEE, 0x9B, 0x17, 0x60, 0x24, 0x94, 0x71, 0x5F, 0x04, 0xC5, 0x21, 0x97}, []uint{62, 59, 50, 16, 6, 35, 61, 35, 43, 22, 8, 55, 5, 33, 27, 32, 33, 23, 21, 40, 38, 23, 2, 27, 43, 1}, []uint64{0x30D0BE0E0117D3DE, 0x4F45E65D9CA1FBA, 0x260B081885785, 0x736F, 0x03, 0x6BE34E113, 0xD983514D6A67A6, 0x5803BF160, 0x49BA6F3F4C1, 0x19979F, 0x42, 0x24DACF65322BDF, 0x0F, 0x1F489DFB1, 0x37A3894, 0x52F92083, 0x1189EF500, 0x704424, 0x8AC83, 0x1837E2A80F, 0x302131F0, 0x774D8B, 0x02, 0x6024947, 0xAF826290CB, 0x01}, }, { []byte{0xDB, 0xB6, 0x8B, 0x84, 0x54, 0x5F, 0x96, 0xF5, 0xA7, 0x0A, 0x0C, 0x86, 0x2B, 0x97, 0x6C, 0x1D, 0x06, 0xF1, 0x2B, 0x6B, 0x3C, 0xD6, 0xE2, 0x4E, 0x00, 0x50, 0xFF, 0x99, 0x4E, 0x19, 0x48, 0xC0, 0x51, 0xAE, 0x3F, 0x8A, 0x89, 0xB5, 0x4E, 0x1D, 0x4B, 0xA7, 0x4E, 0xC6, 0xF9, 0x51, 0x4C, 0xAC, 0xFA, 0x68, 0x40, 0xB1, 0xD6, 0xA5, 0x40, 0xF3, 0xCD, 0xDC, 0xCB, 0x3B, 0x5E, 0xBD, 0x4D, 0x42, 0xA1, 0xDE, 0x60, 0x5F, 0xFF, 0x04, 0xB8, 0xC4, 0xC6, 0xCC, 0x6D, 0xAE, 0xE0, 0xD4, 0x5C, 0x19, 0x12, 0x0C, 0xE1, 0x5D, 0xEA, 0x52, 0x81, 0x48, 0x36, 0x7E, 0xB4, 0x3E, 0x2F, 0x55, 0xE8, 0xF1, 0x5C, 0xCC, 0xE9, 0x69}, []uint{40, 14, 56, 38, 64, 31, 42, 45, 46, 13, 7, 51, 4, 7, 54, 61, 37, 57, 15, 30, 56, 32}, []uint64{0xDBB68B8454, 0x17E5, 0xBD69C283218AE5, 0x36C1D06F12, 0xB6B3CD6E24E0050F, 0x7CCA70CA, 0x1180A35C7F1, 0xA26D538752E, 0x274EC6F9514C, 0x159F, 0x26, 0x42058EB52A079, 0x0E, 0x37, 0x1CCB3B5EBD4D42, 0x143BCC0BFFE09718, 0x131B31B6BB, 0x106A2E0C890670A, 0x77A9, 0x12814836, 0x7EB43E2F55E8F1, 0x5CCCE969}, }, { []byte{0xC1, 0xD6, 0x8F, 0x43, 0xE4, 0xDA, 0x73, 0x69, 0xFF, 0xD2, 0xBD, 0x90, 0x9C, 0xA7, 0x7F, 0x80, 0x19, 0x74, 0xED, 0xAA, 0xFC, 0x25, 0x6C, 0xB8, 0x2B, 0xD9, 0xE1, 0x2F, 0xC1, 0xD8, 0xCF, 0x8C, 0x5F, 0xA9, 0xA7, 0x4A, 0x4B, 0xFD, 0x69, 0x5D, 0x81, 0x47, 0x74, 0x01, 0x04, 0xC0, 0xE2, 0x44, 0xC0, 0x6A, 0x9D, 0x55, 0x36, 0x67, 0x97, 0x1D, 0xA5, 0x77, 0xF1, 0x66, 0xA7, 0xFF, 0x9A, 0xE7, 0xE7, 0x2C, 0x11, 0xBA, 0xD1, 0x35, 0xAB, 0xFE, 0x6E, 0x1B, 0x4E, 0x71, 0x8E, 0xE1, 0x76, 0x9A, 0x37, 0xC9, 0xB9, 0x0D, 0xE7, 0x48, 0xE3, 0xF5, 0x1B, 0xD0, 0x37, 0xAD, 0xB5, 0x6A, 0x5D, 0x1D, 0x68, 0xA6, 0x25, 0xA5}, []uint{43, 24, 64, 30, 32, 57, 56, 61, 50, 3, 45, 46, 3, 60, 22, 42, 5, 60, 20, 24, 10, 43}, []uint64{0x60EB47A1F26, 0xD39B4F, 0xFE95EC84E53BFC00, 0x32E9DB55, 0xF84AD970, 0xAF6784BF07633E, 0x317EA69D292FF5, 0x14AEC0A3BA008260, 0x1C48980D53AAA, 0x03, 0xCCF2E3B4AEF, 0x38B353FFCD73, 0x07, 0x9CB046EB44D6AFF, 0x26E1B4, 0x39C63B85DA6, 0x11, 0xBE4DC86F3A471FA, 0x8DE81, 0xBD6DAB, 0x14B, 0x51D68A625A5}, }, { []byte{0xD2, 0x0F, 0x71, 0xCA, 0xCA, 0xC7, 0x54, 0x23, 0xD0, 0x56, 0x71, 0xA4, 0x96, 0x84, 0x3D, 0xA6, 0x34, 0x6E, 0x5E, 0x7F, 0x4E, 0x49, 0x22, 0xE0, 0x9E, 0xC8, 0x94, 0x2E, 0xAF, 0x34, 0x2F, 0xF6, 0xD3, 0xA7, 0x90, 0x9E, 0xEC, 0x25, 0x15, 0xC5, 0xFB, 0xE4, 0xBD, 0x08, 0x3D, 0x5A, 0x70, 0x77, 0x17, 0x20, 0x2F, 0x1B, 0x1B, 0xAB, 0xA5, 0xC9, 0x83, 0x6D, 0x44, 0x21, 0xD6, 0x0A, 0x01, 0xBD, 0x5D, 0x9F, 0xFD, 0xE4, 0xDF, 0xE4, 0xFD, 0x83, 0xA2, 0x7C, 0xAF, 0x23, 0x7B, 0xB1, 0x6B, 0xAA, 0x71, 0x50, 0x11, 0xBB, 0x48, 0x66, 0xE8, 0x6C, 0xF4, 0x42, 0x28, 0x36, 0x78, 0xEE, 0x64, 0xA5, 0xEA, 0xFC, 0x2E, 0x5A}, []uint{32, 19, 41, 28, 7, 20, 33, 64, 3, 54, 63, 16, 12, 12, 63, 9, 64, 3, 29, 29, 18, 6, 28, 3, 2, 39, 41, 40, 22}, []uint64{0xD20F71CA, 0x6563A, 0x1423D05671A, 0x496843D, 0x53, 0x1A372, 0x1E7F4E492, 0x2E09EC8942EAF342, 0x07, 0x3EDA74F213DD84, 0x515C5FBE4BD083D5, 0xA707, 0x717, 0x202, 0x78D8DD5D2E4C1B6A, 0x42, 0x1D60A01BD5D9FFDE, 0x02, 0xDFE4FD8, 0x744F95E, 0x11BDD, 0x22, 0xD754E2A, 0x00, 0x00, 0x237690CDD0, 0x1B3D108A0D9, 0xE3B99297AB, 0x3C2E5A}, }, { []byte{0x97, 0xD2, 0x7B, 0x0E, 0xF3, 0x1D, 0x05, 0xA6, 0x82, 0x27, 0xD8, 0xE0, 0x4C, 0x2C, 0xFE, 0x8E, 0x5B, 0x92, 0x67, 0xA1, 0xDA, 0x2F, 0xC8, 0x6A, 0x3F, 0x83, 0x20, 0x33, 0xB2, 0xF7, 0xE6, 0x6E, 0xE2, 0x93, 0x98, 0xA2, 0x32, 0x15, 0xD1, 0x21, 0x41, 0xBC, 0x2B, 0xDE, 0xFE, 0x55, 0xFB, 0x6C, 0x34, 0x28, 0xC4, 0x41, 0xA1, 0xFE, 0x33, 0x0C, 0xD3, 0xF5, 0x4A, 0x90, 0xF7, 0x58, 0x04, 0x0C, 0xB6, 0xEE, 0x44, 0xCC, 0x80, 0x3F, 0x00, 0x8F, 0xA8, 0x85, 0xE8, 0x9C, 0x9D, 0xF5, 0x5A, 0xEA, 0xA0, 0x6B, 0x3B, 0x59, 0xD1, 0x89, 0x81, 0x5A, 0xE0, 0x10, 0xD5, 0xD3, 0x7B, 0x1A, 0x4E, 0xAF, 0x3D, 0xE9, 0x3E, 0x59}, []uint{22, 40, 15, 18, 48, 34, 7, 54, 40, 57, 21, 10, 60, 13, 5, 38, 25, 14, 28, 20, 11, 53, 9, 36, 23, 46, 17, 4, 32}, []uint64{0x25F49E, 0xC3BCC74169, 0x5044, 0x3EC70, 0x26167F472DC9, 0xCF43B45F, 0x48, 0x1A8FE0C80CECBD, 0xF99BB8A4E6, 0x51190AE890A0DE, 0x2BDEF, 0x395, 0x7EDB0D0A3110687, 0x1F19, 0x10, 0x334FD52A43, 0x1BAC020, 0x196D, 0xDC89990, 0x7E01, 0xFA, 0x110BD1393BEAB5, 0x1AA, 0x81ACED674, 0x31302B, 0x170086AE9BD8, 0x1A4EA, 0x0F, 0x3DE93E59}, }, { []byte{0xAB, 0x5F, 0xA3, 0x18, 0x91, 0x10, 0x4D, 0x85, 0x95, 0xC6, 0x23, 0xBA, 0x0D, 0xBD, 0xC4, 0x2A, 0x12, 0x30, 0xE1, 0xD3, 0xFE, 0xA2, 0x0B, 0xB9, 0xD9, 0x3D, 0x61, 0x91, 0x97, 0x8B, 0x53, 0x2A, 0xC1, 0x80, 0x3C, 0x46, 0x46, 0x44, 0x57, 0x8A, 0x23, 0x66, 0xF2, 0x51, 0xCC, 0xF8, 0xFB, 0xEF, 0x0A, 0x0B, 0x72, 0xF0, 0xA8, 0x36, 0xE7, 0x26, 0x04, 0x83, 0x15, 0x36, 0x04, 0x73, 0x38, 0x48, 0x41, 0x61, 0x0B, 0x09, 0x46, 0xBC, 0x29, 0xA8, 0x02, 0xB6, 0x80, 0xDB, 0xCF, 0x22, 0x54, 0x5B, 0x5A, 0x2E, 0x34, 0x24, 0x06, 0xB9, 0x66, 0x4C, 0xD1, 0xB7, 0x1A, 0xFF, 0x92, 0x06, 0x49, 0xD1, 0x26, 0xE6, 0x23, 0xAD}, []uint{61, 43, 8, 31, 38, 4, 45, 5, 51, 58, 5, 2, 51, 22, 38, 44, 26, 20, 52, 51, 49, 39, 50, 7}, []uint64{0x156BF463122209B0, 0x595C623BA0D, 0xBD, 0x62150918, 0x1C3A7FD441, 0x07, 0xE764F586465, 0x1C, 0x2D4CAB0600F11, 0x24644578A2366F2, 0x0A, 0x00, 0x733E3EFBC282D, 0x32F0A8, 0xDB9C98120, 0xC54D811CCE1, 0x841610, 0xB0946, 0xBC29A802B680D, 0x5E7912A2DAD17, 0x342406B9664C, 0x68DB8D7FC9, 0xC93A24DCC47, 0x2D}, }, { []byte{0xAA, 0x55}, []uint{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, []uint64{1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1}, }, { []byte{0xAA, 0x55}, []uint{7, 8, 1}, []uint64{0x55, 0x2A, 0x1}, }, { []byte{0xAA, 0x55}, []uint{3, 3, 3, 3, 3, 1}, []uint64{0x5, 0x2, 0x4, 0x5, 0x2, 0x1}, }, { []byte{0xAA, 0x55}, []uint{16}, []uint64{0xAA55}, }, { []byte{0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}, []uint{32, 32}, []uint64{0xAA55AA55, 0xAA55AA55}, }, { []byte{0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}, []uint{33, 31}, []uint64{0x154AB54AB, 0x2A55AA55}, }, } for i, test := range tests { r := NewReader(bytes.NewReader(test.data)) if len(test.ns) != len(test.vals) { panic("Number of reads does not match number of results") } for j, n := range test.ns { m, err := r.Read(n) if err != nil { panic("Unexpected error: " + err.Error()) } if m != test.vals[j] { t.Errorf("i=%d; %v with reads %v: read %d gave %x, expected %x", i, test.data, test.ns, j, m, test.vals[j]) } } } } func TestReadEOF(t *testing.T) { tests := []struct { data []byte n uint err error }{ {[]byte{0xFF}, 8, nil}, {[]byte{0xFF}, 2, nil}, {[]byte{0xFF}, 9, io.ErrUnexpectedEOF}, {[]byte{}, 1, io.EOF}, {[]byte{0xFF, 0xFF}, 16, nil}, {[]byte{0xFF, 0xFF}, 17, io.ErrUnexpectedEOF}, } for i, test := range tests { r := NewReader(bytes.NewReader(test.data)) if _, err := r.Read(test.n); err != test.err { t.Errorf("i=%d; Reading %d from %v, expected err=%s, got err=%s", i, test.n, test.data, test.err, err) } } } func BenchmarkReadAlign1(b *testing.B) { benchmarkReads(b, 64, 1) } func BenchmarkReadAlign32(b *testing.B) { benchmarkReads(b, 64, 32) } func BenchmarkReadAlign64(b *testing.B) { benchmarkReads(b, 64, 64) } func benchmarkReads(b *testing.B, chunk, align int) { size := 1 << 12 buf, bits, _, last := prepareBenchmark(size, chunk, align) b.SetBytes(int64(len(buf))) b.ResetTimer() for i := 0; i < b.N; i++ { r := NewReader(bytes.NewReader(buf)) for j := 0; j < last; j++ { if _, err := r.Read(bits[j]); err != nil { b.Error(err) continue } } } } func prepareBenchmark(size, chunk, align int) ([]byte, []uint, []uint64, int) { buf := make([]byte, size) bits := make([]uint, size) values := make([]uint64, size) idx := 0 last := 0 for i := 0; i < size; i++ { val := getNumBits(idx, size*8, chunk, align) idx += val if val != 0 { last = i + 1 } bits[i] = uint(val) values[i] = uint64(rand.Uint32())<<32 + uint64(rand.Uint32()) } return buf, bits, values, last } func getNumBits(read, max, chunk, align int) int { bits := 1 if align != chunk { bits += rand.Intn(chunk / align) } bits *= align if read+bits > max { bits = max - read } if bits > chunk { panic("too many bits") } return bits } ================================================ FILE: internal/bits/twocomp.go ================================================ package bits // IntN returns the signed two's complement of x with the specified integer bit // width. // // Examples of unsigned (n-bit width) x values on the left and decoded values on // the right: // // 0b011 -> 3 // 0b010 -> 2 // 0b001 -> 1 // 0b000 -> 0 // 0b111 -> -1 // 0b110 -> -2 // 0b101 -> -3 // 0b100 -> -4 func IntN(x uint64, n uint) int64 { signBitMask := uint64(1 << (n - 1)) if x&signBitMask == 0 { // positive. return int64(x) } // negative. v := int64(x ^ signBitMask) // clear sign bit. v -= int64(signBitMask) return v } ================================================ FILE: internal/bits/twocomp_test.go ================================================ package bits import "testing" func TestIntN(t *testing.T) { golden := []struct { x uint64 n uint want int64 }{ {x: 0b011, n: 3, want: 3}, {x: 0b010, n: 3, want: 2}, {x: 0b001, n: 3, want: 1}, {x: 0b000, n: 3, want: 0}, {x: 0b111, n: 3, want: -1}, {x: 0b110, n: 3, want: -2}, {x: 0b101, n: 3, want: -3}, {x: 0b100, n: 3, want: -4}, } for _, g := range golden { got := IntN(g.x, g.n) if g.want != got { t.Errorf("result mismatch of IntN(x=0b%03b, n=%d); expected %d, got %d", g.x, g.n, g.want, got) continue } } } ================================================ FILE: internal/bits/unary.go ================================================ package bits import ( "github.com/icza/bitio" ) // ReadUnary decodes and returns an unary coded integer, whose value is // represented by the number of leading zeros before a one. // // Examples of unary coded binary on the left and decoded decimal on the right: // // 1 => 0 // 01 => 1 // 001 => 2 // 0001 => 3 // 00001 => 4 // 000001 => 5 // 0000001 => 6 func (br *Reader) ReadUnary() (x uint64, err error) { for { bit, err := br.Read(1) if err != nil { return 0, err } if bit == 1 { break } x++ } return x, nil } // WriteUnary encodes x as an unary coded integer, whose value is represented by // the number of leading zeros before a one. // // Examples of unary coded binary on the left and decoded decimal on the right: // // 0 => 1 // 1 => 01 // 2 => 001 // 3 => 0001 // 4 => 00001 // 5 => 000001 // 6 => 0000001 func WriteUnary(bw *bitio.Writer, x uint64) error { for ; x > 8; x -= 8 { if err := bw.WriteByte(0x0); err != nil { return err } } bits := uint64(1) n := byte(x + 1) if err := bw.WriteBits(bits, n); err != nil { return err } return nil } ================================================ FILE: internal/bits/unary_test.go ================================================ package bits_test import ( "bytes" "testing" "github.com/icza/bitio" "github.com/mewkiz/flac/internal/bits" ) func TestUnary(t *testing.T) { buf := &bytes.Buffer{} bw := bitio.NewWriter(buf) for want := uint64(0); want < 1000; want++ { // Write unary if err := bits.WriteUnary(bw, want); err != nil { t.Fatalf("unable to write unary; %v", err) } // Flush buffer if err := bw.Close(); err != nil { t.Fatalf("unable to close (flush) the bit buffer; %v", err) } // Read written unary r := bits.NewReader(buf) got, err := r.ReadUnary() if err != nil { t.Fatalf("unable to read unary; %v", err) } if want != got { t.Fatalf("mismatch between written and read unary value; expected: %d, got: %d", want, got) } } } ================================================ FILE: internal/bits/zigzag.go ================================================ package bits // DecodeZigZag decodes a ZigZag encoded integer and returns it. // // Examples of ZigZag encoded values on the left and decoded values on the // right: // // 0 => 0 // 1 => -1 // 2 => 1 // 3 => -2 // 4 => 2 // 5 => -3 // 6 => 3 // // ref: https://developers.google.com/protocol-buffers/docs/encoding func DecodeZigZag(x uint32) int32 { return int32(x>>1) ^ -int32(x&1) } // EncodeZigZag encodes a given integer to ZigZag-encoding. // // Examples of integer input on the left and corresponding ZigZag encoded values // on the right: // // 0 => 0 // -1 => 1 // 1 => 2 // -2 => 3 // 2 => 4 // -3 => 5 // 3 => 6 // // ref: https://developers.google.com/protocol-buffers/docs/encoding func EncodeZigZag(x int32) uint32 { if x < 0 { x = -x return uint32(x)<<1 - 1 } return uint32(x) << 1 } ================================================ FILE: internal/bits/zigzag_test.go ================================================ package bits import ( "testing" ) func TestDecodeZigZag(t *testing.T) { golden := []struct { x uint32 want int32 }{ {x: 0, want: 0}, {x: 1, want: -1}, {x: 2, want: 1}, {x: 3, want: -2}, {x: 4, want: 2}, {x: 5, want: -3}, {x: 6, want: 3}, } for _, g := range golden { got := DecodeZigZag(g.x) if g.want != got { t.Errorf("result mismatch of DecodeZigZag(x=%d); expected %d, got %d", g.x, g.want, got) continue } } } func TestEncodeZigZag(t *testing.T) { golden := []struct { x int32 want uint32 }{ {x: 0, want: 0}, {x: -1, want: 1}, {x: 1, want: 2}, {x: -2, want: 3}, {x: 2, want: 4}, {x: -3, want: 5}, {x: 3, want: 6}, } for _, g := range golden { got := EncodeZigZag(g.x) if g.want != got { t.Errorf("result mismatch of EncodeZigZag(x=%d); expected %d, got %d", g.x, g.want, got) continue } } } ================================================ FILE: internal/bufseekio/readseeker.go ================================================ package bufseekio import ( "errors" "io" ) const ( defaultBufSize = 4096 ) // ReadSeeker implements buffering for an io.ReadSeeker object. // ReadSeeker is based on bufio.Reader with Seek functionality added // and unneeded functionality removed. type ReadSeeker struct { buf []byte pos int64 // absolute start position of buf rd io.ReadSeeker // read-seeker provided by the client r, w int // buf read and write positions within buf err error } const minReadBufferSize = 16 // NewReadSeekerSize returns a new ReadSeeker whose buffer has at least the specified // size. If the argument io.ReadSeeker is already a ReadSeeker with large enough // size, it returns the underlying ReadSeeker. func NewReadSeekerSize(rd io.ReadSeeker, size int) *ReadSeeker { // Is it already a Reader? b, ok := rd.(*ReadSeeker) if ok && len(b.buf) >= size { return b } if size < minReadBufferSize { size = minReadBufferSize } r := new(ReadSeeker) r.reset(make([]byte, size), rd) return r } // NewReadSeeker returns a new ReadSeeker whose buffer has the default size. func NewReadSeeker(rd io.ReadSeeker) *ReadSeeker { return NewReadSeekerSize(rd, defaultBufSize) } var errNegativeRead = errors.New("bufseekio: reader returned negative count from Read") func (b *ReadSeeker) reset(buf []byte, r io.ReadSeeker) { *b = ReadSeeker{ buf: buf, rd: r, } } func (b *ReadSeeker) readErr() error { err := b.err b.err = nil return err } // Read reads data into p. // It returns the number of bytes read into p. // The bytes are taken from at most one Read on the underlying Reader, // hence n may be less than len(p). // To read exactly len(p) bytes, use io.ReadFull(b, p). // If the underlying Reader can return a non-zero count with io.EOF, // then this Read method can do so as well; see the [io.Reader] docs. func (b *ReadSeeker) Read(p []byte) (n int, err error) { n = len(p) if n == 0 { if b.buffered() > 0 { return 0, nil } return 0, b.readErr() } if b.r == b.w { if b.err != nil { return 0, b.readErr() } if len(p) >= len(b.buf) { // Large read, empty buffer. // Read directly into p to avoid copy. n, b.err = b.rd.Read(p) if n < 0 { panic(errNegativeRead) } b.pos += int64(n) return n, b.readErr() } // One read. b.pos += int64(b.r) b.r = 0 b.w = 0 n, b.err = b.rd.Read(b.buf) if n < 0 { panic(errNegativeRead) } if n == 0 { return 0, b.readErr() } b.w += n } // copy as much as we can // Note: if the slice panics here, it is probably because // the underlying reader returned a bad count. See issue 49795. n = copy(p, b.buf[b.r:b.w]) b.r += n return n, nil } // buffered returns the number of bytes that can be read from the current buffer. func (b *ReadSeeker) buffered() int { return b.w - b.r } func (b *ReadSeeker) Seek(offset int64, whence int) (int64, error) { // The stream.Seek() implementation makes heavy use of seeking with offset 0 // to obtain the current position; let's optimize for it. if offset == 0 && whence == io.SeekCurrent { return b.position(), nil } // When seeking from the end, the absolute position isn't known by ReadSeeker // so the current buffer cannot be used. Seeking cannot be avoided. if whence == io.SeekEnd { return b.seek(offset, whence) } // Calculate the absolute offset. abs := offset if whence == io.SeekCurrent { abs += b.position() } // Check if the offset is within buf. if abs >= b.pos && abs < b.pos+int64(b.w) { b.r = int(abs - b.pos) return abs, nil } return b.seek(abs, io.SeekStart) } func (b *ReadSeeker) seek(offset int64, whence int) (int64, error) { b.r = 0 b.w = 0 var err error b.pos, err = b.rd.Seek(offset, whence) return b.pos, err } // position returns the absolute read offset. func (b *ReadSeeker) position() int64 { return b.pos + int64(b.r) } ================================================ FILE: internal/bufseekio/readseeker_test.go ================================================ package bufseekio import ( "bytes" "errors" "io" "reflect" "testing" ) func TestNewReadSeekerSize(t *testing.T) { buf := bytes.NewReader(make([]byte, 100)) // Test custom buffer size. if rs := NewReadSeekerSize(buf, 20); len(rs.buf) != 20 { t.Fatalf("want %d got %d", 20, len(rs.buf)) } // Test too small buffer size. if rs := NewReadSeekerSize(buf, 1); len(rs.buf) != minReadBufferSize { t.Fatalf("want %d got %d", minReadBufferSize, len(rs.buf)) } // Test reuse existing ReadSeeker. rs := NewReadSeekerSize(buf, 20) if rs2 := NewReadSeekerSize(rs, 5); rs != rs2 { t.Fatal("expected ReadSeeker to be reused but got a different ReadSeeker") } } func TestNewReadSeeker(t *testing.T) { buf := bytes.NewReader(make([]byte, 100)) if rs := NewReadSeeker(buf); len(rs.buf) != defaultBufSize { t.Fatalf("want %d got %d", defaultBufSize, len(rs.buf)) } } func TestReadSeeker_Read(t *testing.T) { data := make([]byte, 100) for i := range data { data[i] = byte(i) } rs := NewReadSeekerSize(bytes.NewReader(data), 20) if len(rs.buf) != 20 { t.Fatal("the buffer size was changed and the validity of this test has become unknown") } // Test small read. got := make([]byte, 5) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{0, 1, 2, 3, 4}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{0, 1, 2, 3, 4}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 5 { t.Fatalf("want %d got %d, err=%v", 5, p, err) } // Test big read with initially filled buffer. got = make([]byte, 25) if n, err := rs.Read(got); err != nil || n != 15 || !reflect.DeepEqual(got, []byte{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 15, n, []byte{5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 20 { t.Fatalf("want %d got %d, err=%v", 20, p, err) } // Test big read with initially empty buffer. if n, err := rs.Read(got); err != nil || n != 25 || !reflect.DeepEqual(got, []byte{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}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 25, n, []byte{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}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 45 { t.Fatalf("want %d got %d, err=%v", 45, p, err) } // Test EOF. if p, err := rs.Seek(98, io.SeekStart); err != nil || p != 98 { t.Fatalf("want %d got %d, err=%v", 98, p, err) } got = make([]byte, 5) if n, err := rs.Read(got); err != nil || n != 2 || !reflect.DeepEqual(got, []byte{98, 99, 0, 0, 0}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 2, n, []byte{98, 99, 0, 0, 0}, got, err) } if n, err := rs.Read(got); err != io.EOF || n != 0 { t.Fatalf("want n read %d got %d, err=%v", 0, n, err) } // Test source that returns bytes and an error at the same time. rs = NewReadSeekerSize(&readAndError{bytes: []byte{2, 3, 5}}, 20) if len(rs.buf) != 20 { t.Fatal("the buffer size was changed and the validity of this test has become unknown") } got = make([]byte, 5) if n, err := rs.Read(got); err != nil || n != 3 || !reflect.DeepEqual(got, []byte{2, 3, 5, 0, 0}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 3, n, []byte{2, 3, 5, 0, 0}, got, err) } if n, err := rs.Read(got); err != expectedErr || n != 0 { t.Fatalf("want n read %d got %d, want error %v, got %v", 0, n, expectedErr, err) } // Test read nothing with an empty buffer and a queued error. rs = NewReadSeekerSize(&readAndError{bytes: []byte{2, 3, 5}}, 20) if len(rs.buf) != 20 { t.Fatal("the buffer size was changed and the validity of this test has become unknown") } got = make([]byte, 3) if n, err := rs.Read(got); err != nil || n != 3 || !reflect.DeepEqual(got, []byte{2, 3, 5}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 3, n, []byte{2, 3, 5}, got, err) } if n, err := rs.Read(nil); err != expectedErr || n != 0 { t.Fatalf("want n read %d got %d, want error %v, got %v", 0, n, expectedErr, err) } if n, err := rs.Read(nil); err != nil || n != 0 { t.Fatalf("want n read %d got %d, err=%v", 0, n, err) } // Test read nothing with a non-empty buffer and a queued error. rs = NewReadSeekerSize(&readAndError{bytes: []byte{2, 3, 5}}, 20) if len(rs.buf) != 20 { t.Fatal("the buffer size was changed and the validity of this test has become unknown") } got = make([]byte, 1) if n, err := rs.Read(got); err != nil || n != 1 || !reflect.DeepEqual(got, []byte{2}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 1, n, []byte{}, got, err) } if n, err := rs.Read(nil); err != nil || n != 0 { t.Fatalf("want n read %d got %d, err=%v", 0, n, err) } } var expectedErr = errors.New("expected error") type readAndError struct { bytes []byte } func (r *readAndError) Read(p []byte) (n int, err error) { for i, b := range r.bytes { p[i] = b } return len(r.bytes), expectedErr } func (r *readAndError) Seek(offset int64, whence int) (int64, error) { panic("not implemented") } func TestReadSeeker_Seek(t *testing.T) { data := make([]byte, 100) for i := range data { data[i] = byte(i) } r := &seekRecorder{rs: bytes.NewReader(data)} rs := NewReadSeekerSize(r, 20) if len(rs.buf) != 20 { t.Fatal("the buffer size was changed and the validity of this test has become unknown") } got := make([]byte, 5) // Test with io.SeekStart if p, err := rs.Seek(10, io.SeekStart); err != nil || p != 10 { t.Fatalf("want %d got %d, err=%v", 10, p, err) } r.assertSeeked(t, []seekRecord{{10, io.SeekStart}}) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{10, 11, 12, 13, 14}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{10, 11, 12, 13, 14}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 15 { t.Fatalf("want %d got %d, err=%v", 15, p, err) } r.assertSeeked(t, nil) // Test with io.SeekCurrent and positive offset within buffer. if p, err := rs.Seek(5, io.SeekCurrent); err != nil || p != 20 { t.Fatalf("want %d got %d, err=%v", 20, p, err) } r.assertSeeked(t, nil) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{20, 21, 22, 23, 24}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{20, 21, 22, 23, 24}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 25 { t.Fatalf("want %d got %d, err=%v", 25, p, err) } // Test with io.SeekCurrent and negative offset within buffer. if p, err := rs.Seek(-10, io.SeekCurrent); err != nil || p != 15 { t.Fatalf("want %d got %d, err=%v", 15, p, err) } r.assertSeeked(t, nil) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{15, 16, 17, 18, 19}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{15, 16, 17, 18, 19}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 20 { t.Fatalf("want %d got %d, err=%v", 20, p, err) } // Test with io.SeekCurrent and positive offset outside buffer. if p, err := rs.Seek(30, io.SeekCurrent); err != nil || p != 50 { t.Fatalf("want %d got %d, err=%v", 50, p, err) } r.assertSeeked(t, []seekRecord{{50, io.SeekStart}}) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{50, 51, 52, 53, 54}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{50, 51, 52, 53, 54}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 55 { t.Fatalf("want %d got %d, err=%v", 55, p, err) } // Test seek with io.SeekEnd within buffer. if p, err := rs.Seek(-45, io.SeekEnd); err != nil || p != 55 { t.Fatalf("want %d got %d, err=%v", 55, p, err) } r.assertSeeked(t, []seekRecord{{-45, io.SeekEnd}}) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{55, 56, 57, 58, 59}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{55, 56, 57, 58, 59}, got, err) } if p, err := rs.Seek(0, io.SeekCurrent); err != nil || p != 60 { t.Fatalf("want %d got %d, err=%v", 60, p, err) } // Test seek with error. if _, err := rs.Seek(-100, io.SeekStart); err == nil || err.Error() != "bytes.Reader.Seek: negative position" { t.Fatalf("want error 'bytes.Reader.Seek: negative position' got %v", err) } r.assertSeeked(t, []seekRecord{{-100, io.SeekStart}}) // Test seek after error. if p, err := rs.Seek(10, io.SeekStart); err != nil || p != 10 { t.Fatalf("want %d got %d, err=%v", 10, p, err) } r.assertSeeked(t, []seekRecord{{10, io.SeekStart}}) if n, err := rs.Read(got); err != nil || n != 5 || !reflect.DeepEqual(got, []byte{10, 11, 12, 13, 14}) { t.Fatalf("want n read %d got %d, want buffer %v got %v, err=%v", 5, n, []byte{10, 11, 12, 13, 14}, got, err) } } type seekRecord struct { offset int64 whence int } type seekRecorder struct { rs io.ReadSeeker seeks []seekRecord } func (r *seekRecorder) Read(p []byte) (n int, err error) { return r.rs.Read(p) } func (r *seekRecorder) Seek(offset int64, whence int) (int64, error) { r.seeks = append(r.seeks, seekRecord{offset: offset, whence: whence}) return r.rs.Seek(offset, whence) } func (r *seekRecorder) assertSeeked(t *testing.T, expected []seekRecord) { t.Helper() if !reflect.DeepEqual(expected, r.seeks) { t.Fatalf("seek mismatch; expected %#v, got %#v", expected, r.seeks) } r.reset() } func (r *seekRecorder) reset() { r.seeks = nil } ================================================ FILE: internal/hashutil/crc16/crc16.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package crc16 implements the 16-bit cyclic redundancy check, or CRC-16, // checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check and // http://www.ross.net/crc/download/crc_v3.txt for information. package crc16 import "github.com/mewkiz/flac/internal/hashutil" // Size of a CRC-16 checksum in bytes. const Size = 2 // Predefined polynomials. const ( IBM = 0x8005 // x^16 + x^15 + x^2 + x^0 ) // Table is a 256-word table representing the polynomial for efficient // processing. type Table [256]uint16 // IBMTable is the table for the IBM polynomial. var IBMTable = makeTable(IBM) // MakeTable returns the Table constructed from the specified polynomial. func MakeTable(poly uint16) (table *Table) { switch poly { case IBM: return IBMTable } return makeTable(poly) } // makeTable returns the Table constructed from the specified polynomial. func makeTable(poly uint16) (table *Table) { table = new(Table) for i := range table { crc := uint16(i << 8) for j := 0; j < 8; j++ { if crc&0x8000 != 0 { crc = crc<<1 ^ poly } else { crc <<= 1 } } table[i] = crc } return table } // digest represents the partial evaluation of a checksum. type digest struct { crc uint16 table *Table } // New creates a new hashutil.Hash16 computing the CRC-16 checksum using the // polynomial represented by the Table. func New(table *Table) hashutil.Hash16 { return &digest{0, table} } // NewIBM creates a new hashutil.Hash16 computing the CRC-16 checksum using the // IBM polynomial. func NewIBM() hashutil.Hash16 { return New(IBMTable) } func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return 1 } func (d *digest) Reset() { d.crc = 0 } // Update returns the result of adding the bytes in p to the crc. func Update(crc uint16, table *Table, p []byte) uint16 { for _, v := range p { crc = crc<<8 ^ table[crc>>8^uint16(v)] } return crc } func (d *digest) Write(p []byte) (n int, err error) { d.crc = Update(d.crc, d.table, p) return len(p), nil } // Sum16 returns the 16-bit checksum of the hash. func (d *digest) Sum16() uint16 { return d.crc } func (d *digest) Sum(in []byte) []byte { s := d.Sum16() return append(in, byte(s>>8), byte(s)) } // Checksum returns the CRC-16 checksum of data, using the polynomial // represented by the Table. func Checksum(data []byte, table *Table) uint16 { return Update(0, table, data) } // ChecksumIBM returns the CRC-16 checksum of data using the IBM polynomial. func ChecksumIBM(data []byte) uint16 { return Update(0, IBMTable, data) } ================================================ FILE: internal/hashutil/crc16/crc16_test.go ================================================ package crc16 import ( "io" "testing" ) type test struct { want uint16 in string } var golden = []test{ {0x0000, ""}, {0x8145, "a"}, {0xC749, "ab"}, {0xCADB, "abc"}, {0x58E7, "abcd"}, {0x678D, "abcde"}, {0x0D05, "abcdef"}, {0x047C, "abcdefg"}, {0x7D68, "abcdefgh"}, {0x6878, "abcdefghi"}, {0xF80F, "abcdefghij"}, {0x0F8E, "Discard medicine more than two years old."}, {0xE149, "He who has a shady past knows that nice guys finish last."}, {0x02B7, "I wouldn't marry him with a ten foot pole."}, {0x7F6A, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, {0x28BD, "The days of the digital watch are numbered. -Tom Stoppard"}, {0x7C55, "Nepal premier won't resign."}, {0xC92B, "For every action there is an equal and opposite government program."}, {0x3E41, "His money is twice tainted: 'taint yours and 'taint mine."}, {0xDA56, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, {0x7F66, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, {0x2A00, "size: a.out: bad magic"}, {0x25B2, "The major problem is with sendmail. -Mark Horton"}, {0xBD71, "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, {0x8596, "If the enemy is within range, then so are you."}, {0x74A2, "It's well we cannot hear the screams/That we create in others' dreams."}, {0x0D73, "You remind me of a TV show, but that's all right: I watch it anyway."}, {0xEE65, "C is as portable as Stonehedge!!"}, {0xA94E, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, {0x0B98, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, {0xF560, "How can you write a big system without C++? -Paul Glick"}, {0x60AE, "The quick brown fox jumps over the lazy dog"}, } func TestCrc16IBM(t *testing.T) { for _, g := range golden { h := NewIBM() if _, err := io.WriteString(h, g.in); err != nil { t.Error(err) continue } got := h.Sum16() if got != g.want { t.Errorf("IBM(%q); expected 0x%04X, got 0x%04X.", g.in, g.want, got) } } } func BenchmarkNewIBM(b *testing.B) { for i := 0; i < b.N; i++ { NewIBM() } } func BenchmarkCrc16_1K(b *testing.B) { benchmarkCrc16(b, 1024) } func BenchmarkCrc16_2K(b *testing.B) { benchmarkCrc16(b, 2*1024) } func BenchmarkCrc16_4K(b *testing.B) { benchmarkCrc16(b, 4*1024) } func BenchmarkCrc16_8K(b *testing.B) { benchmarkCrc16(b, 8*1024) } func BenchmarkCrc16_16K(b *testing.B) { benchmarkCrc16(b, 16*1024) } func benchmarkCrc16(b *testing.B, count int64) { b.SetBytes(count) data := make([]byte, count) for i := range data { data[i] = byte(i) } h := NewIBM() in := make([]byte, 0, h.Size()) b.ResetTimer() for i := 0; i < b.N; i++ { h.Reset() if _, err := h.Write(data); err != nil { b.Error(err) continue } h.Sum(in) } } ================================================ FILE: internal/hashutil/crc8/crc8.go ================================================ // Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package crc8 implements the 8-bit cyclic redundancy check, or CRC-8, // checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check and // http://www.ross.net/crc/download/crc_v3.txt for information. package crc8 import "github.com/mewkiz/flac/internal/hashutil" // Size of a CRC-8 checksum in bytes. const Size = 1 // Predefined polynomials. const ( ATM = 0x07 // x^8 + x^2 + x + 1 ) // Table is a 256-word table representing the polynomial for efficient // processing. type Table [256]uint8 // ATMTable is the table for the ATM polynomial. var ATMTable = makeTable(ATM) // MakeTable returns the Table constructed from the specified polynomial. func MakeTable(poly uint8) (table *Table) { switch poly { case ATM: return ATMTable } return makeTable(poly) } // makeTable returns the Table constructed from the specified polynomial. func makeTable(poly uint8) (table *Table) { table = new(Table) for i := range table { crc := uint8(i) for j := 0; j < 8; j++ { if crc&0x80 != 0 { crc = crc<<1 ^ poly } else { crc <<= 1 } } table[i] = crc } return table } // digest represents the partial evaluation of a checksum. type digest struct { crc uint8 table *Table } // New creates a new hashutil.Hash8 computing the CRC-8 checksum using the // polynomial represented by the Table. func New(table *Table) hashutil.Hash8 { return &digest{0, table} } // NewATM creates a new hashutil.Hash8 computing the CRC-8 checksum using the // ATM polynomial. func NewATM() hashutil.Hash8 { return New(ATMTable) } func (d *digest) Size() int { return Size } func (d *digest) BlockSize() int { return 1 } func (d *digest) Reset() { d.crc = 0 } // Update returns the result of adding the bytes in p to the crc. func Update(crc uint8, table *Table, p []byte) uint8 { for _, v := range p { crc = table[crc^v] } return crc } func (d *digest) Write(p []byte) (n int, err error) { d.crc = Update(d.crc, d.table, p) return len(p), nil } // Sum8 returns the 8-bit checksum of the hash. func (d *digest) Sum8() uint8 { return d.crc } func (d *digest) Sum(in []byte) []byte { return append(in, d.crc) } // Checksum returns the CRC-8 checksum of data, using the polynomial represented // by the Table. func Checksum(data []byte, table *Table) uint8 { return Update(0, table, data) } // ChecksumATM returns the CRC-8 checksum of data using the ATM polynomial. func ChecksumATM(data []byte) uint8 { return Update(0, ATMTable, data) } ================================================ FILE: internal/hashutil/crc8/crc8_test.go ================================================ package crc8 import ( "io" "testing" ) type test struct { want uint8 in string } var golden = []test{ {0x00, ""}, {0x20, "a"}, {0xC9, "ab"}, {0x5F, "abc"}, {0xA1, "abcd"}, {0x52, "abcde"}, {0x8C, "abcdef"}, {0x9F, "abcdefg"}, {0xCB, "abcdefgh"}, {0x67, "abcdefghi"}, {0x23, "abcdefghij"}, {0x56, "Discard medicine more than two years old."}, {0x6B, "He who has a shady past knows that nice guys finish last."}, {0x70, "I wouldn't marry him with a ten foot pole."}, {0x8F, "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, {0x48, "The days of the digital watch are numbered. -Tom Stoppard"}, {0x5E, "Nepal premier won't resign."}, {0x3C, "For every action there is an equal and opposite government program."}, {0xA8, "His money is twice tainted: 'taint yours and 'taint mine."}, {0x46, "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, {0xC7, "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, {0x31, "size: a.out: bad magic"}, {0xB6, "The major problem is with sendmail. -Mark Horton"}, {0x7D, "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, {0xDC, "If the enemy is within range, then so are you."}, {0x13, "It's well we cannot hear the screams/That we create in others' dreams."}, {0x96, "You remind me of a TV show, but that's all right: I watch it anyway."}, {0x96, "C is as portable as Stonehedge!!"}, {0x3C, "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, {0xEE, "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, {0x33, "How can you write a big system without C++? -Paul Glick"}, {0xC1, "The quick brown fox jumps over the lazy dog"}, } func TestCrc8ATM(t *testing.T) { for _, g := range golden { h := NewATM() if _, err := io.WriteString(h, g.in); err != nil { t.Error(err) continue } got := h.Sum8() if got != g.want { t.Errorf("ATM(%q); expected 0x%02X, got 0x%02X.", g.in, g.want, got) } } } func BenchmarkNewATM(b *testing.B) { for i := 0; i < b.N; i++ { NewATM() } } func BenchmarkCrc8_1K(b *testing.B) { benchmarkCrc8(b, 1024) } func BenchmarkCrc8_2K(b *testing.B) { benchmarkCrc8(b, 2*1024) } func BenchmarkCrc8_4K(b *testing.B) { benchmarkCrc8(b, 4*1024) } func BenchmarkCrc8_8K(b *testing.B) { benchmarkCrc8(b, 8*1024) } func BenchmarkCrc8_16K(b *testing.B) { benchmarkCrc8(b, 16*1024) } func benchmarkCrc8(b *testing.B, count int64) { b.SetBytes(count) data := make([]byte, count) for i := range data { data[i] = byte(i) } h := NewATM() in := make([]byte, 0, h.Size()) b.ResetTimer() for i := 0; i < b.N; i++ { h.Reset() if _, err := h.Write(data); err != nil { b.Error(err) continue } h.Sum(in) } } ================================================ FILE: internal/hashutil/hashutil.go ================================================ // Package hashutil provides utility interfaces for hash functions. package hashutil import "hash" // Hash8 is the common interface implemented by all 8-bit hash functions. type Hash8 interface { hash.Hash // Sum8 returns the 8-bit checksum of the hash. Sum8() uint8 } // Hash16 is the common interface implemented by all 16-bit hash functions. type Hash16 interface { hash.Hash // Sum16 returns the 16-bit checksum of the hash. Sum16() uint16 } ================================================ FILE: internal/ioutilx/byte.go ================================================ // Package ioutilx implements extended input/output utility functions. package ioutilx import ( "io" ) // ReadByte reads and returns the next byte from r. func ReadByte(r io.Reader) (byte, error) { var buf [1]byte if _, err := io.ReadFull(r, buf[:]); err != nil { return 0, err } return buf[0], nil } // WriteByte writes the given byte to w. func WriteByte(w io.Writer, b byte) error { buf := [1]byte{b} if _, err := w.Write(buf[:]); err != nil { return err } return nil } ================================================ FILE: internal/ioutilx/zero.go ================================================ package ioutilx // Zero is an io.Reader which always reads zero bytes. var Zero zero // zero is an io.Reader which always reads zero bytes. type zero struct { } // Read reads len(b) zero bytes into b. It returns the number of bytes read and // a nil error value. func (zero) Read(b []byte) (n int, err error) { for i := range b { b[i] = 0 } return len(b), nil } ================================================ FILE: internal/utf8/decode.go ================================================ // Package utf8 implements encoding and decoding of UTF-8 coded numbers. package utf8 import ( "errors" "fmt" "io" "github.com/mewkiz/flac/internal/ioutilx" ) const ( tx = 0x80 // 1000 0000 t2 = 0xC0 // 1100 0000 t3 = 0xE0 // 1110 0000 t4 = 0xF0 // 1111 0000 t5 = 0xF8 // 1111 1000 t6 = 0xFC // 1111 1100 t7 = 0xFE // 1111 1110 t8 = 0xFF // 1111 1111 maskx = 0x3F // 0011 1111 mask2 = 0x1F // 0001 1111 mask3 = 0x0F // 0000 1111 mask4 = 0x07 // 0000 0111 mask5 = 0x03 // 0000 0011 mask6 = 0x01 // 0000 0001 rune1Max = 1<<7 - 1 rune2Max = 1<<11 - 1 rune3Max = 1<<16 - 1 rune4Max = 1<<21 - 1 rune5Max = 1<<26 - 1 rune6Max = 1<<31 - 1 rune7Max = 1<<36 - 1 ) // Decode decodes a "UTF-8" coded number and returns it. // // ref: http://permalink.gmane.org/gmane.comp.audio.compression.flac.devel/3033 // // Algorithm description: // - read one byte B0 from the stream // - if B0 = 0xxxxxxx then the read value is B0 -> end // - if B0 = 10xxxxxx, the encoding is invalid // - if B0 = 11xxxxxx, set L to the number of leading binary 1s minus 1: // B0 = 110xxxxx -> L = 1 // B0 = 1110xxxx -> L = 2 // B0 = 11110xxx -> L = 3 // B0 = 111110xx -> L = 4 // B0 = 1111110x -> L = 5 // B0 = 11111110 -> L = 6 // - assign the bits following the encoding (the x bits in the examples) to // a variable R with a magnitude of at least 36 bits // - loop from 1 to L // - left shift R 6 bits // - read B from the stream // - if B does not match 10xxxxxx, the encoding is invalid // - set R = R or // - the read value is R func Decode(r io.Reader) (x uint64, err error) { c0, err := ioutilx.ReadByte(r) if err != nil { return 0, err } // 1-byte, 7-bit sequence? if c0 < tx { // if c0 == 0xxxxxxx // total: 7 bits (7) return uint64(c0), nil } // unexpected continuation byte? if c0 < t2 { // if c0 == 10xxxxxx return 0, errors.New("frame.decodeUTF8Int: unexpected continuation byte") } // get number of continuation bytes and store bits from c0. var l int switch { case c0 < t3: // if c0 == 110xxxxx // total: 11 bits (5 + 6) l = 1 x = uint64(c0 & mask2) case c0 < t4: // if c0 == 1110xxxx // total: 16 bits (4 + 6 + 6) l = 2 x = uint64(c0 & mask3) case c0 < t5: // if c0 == 11110xxx // total: 21 bits (3 + 6 + 6 + 6) l = 3 x = uint64(c0 & mask4) case c0 < t6: // if c0 == 111110xx // total: 26 bits (2 + 6 + 6 + 6 + 6) l = 4 x = uint64(c0 & mask5) case c0 < t7: // if c0 == 1111110x // total: 31 bits (1 + 6 + 6 + 6 + 6 + 6) l = 5 x = uint64(c0 & mask6) case c0 < t8: // if c0 == 11111110 // total: 36 bits (0 + 6 + 6 + 6 + 6 + 6 + 6) l = 6 x = 0 } // store bits from continuation bytes. for i := 0; i < l; i++ { x <<= 6 c, err := ioutilx.ReadByte(r) if err != nil { if err == io.EOF { return 0, io.ErrUnexpectedEOF } return 0, err } if c < tx || t2 <= c { // if c != 10xxxxxx return 0, errors.New("frame.decodeUTF8Int: expected continuation byte") } x |= uint64(c & maskx) } // check if number representation is larger than necessary. switch l { case 1: if x <= rune1Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } case 2: if x <= rune2Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } case 3: if x <= rune3Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } case 4: if x <= rune4Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } case 5: if x <= rune5Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } case 6: if x <= rune6Max { return 0, fmt.Errorf("frame.decodeUTF8Int: larger number representation than necessary; x (%d) stored in %d bytes, could be stored in %d bytes", x, l+1, l) } } return x, nil } ================================================ FILE: internal/utf8/encode.go ================================================ package utf8 import ( "io" "github.com/mewkiz/flac/internal/ioutilx" "github.com/mewkiz/pkg/errutil" ) // Encode encodes x as a "UTF-8" coded number. func Encode(w io.Writer, x uint64) error { // 1-byte, 7-bit sequence? if x <= rune1Max { if err := ioutilx.WriteByte(w, byte(x)); err != nil { return errutil.Err(err) } return nil } // get number of continuation bytes and store bits of c0. var ( // number of continuation bytes., l int // bits of c0. bits uint64 ) switch { case x <= rune2Max: // if c0 == 110xxxxx // total: 11 bits (5 + 6) l = 1 bits = t2 | (x>>6)&mask2 case x <= rune3Max: // if c0 == 1110xxxx // total: 16 bits (4 + 6 + 6) l = 2 bits = t3 | (x>>(6*2))&mask3 case x <= rune4Max: // if c0 == 11110xxx // total: 21 bits (3 + 6 + 6 + 6) l = 3 bits = t4 | (x>>(6*3))&mask4 case x <= rune5Max: // if c0 == 111110xx // total: 26 bits (2 + 6 + 6 + 6 + 6) l = 4 bits = t5 | (x>>(6*4))&mask5 case x <= rune6Max: // if c0 == 1111110x // total: 31 bits (1 + 6 + 6 + 6 + 6 + 6) l = 5 bits = t6 | (x>>(6*5))&mask6 case x <= rune7Max: // if c0 == 11111110 // total: 36 bits (0 + 6 + 6 + 6 + 6 + 6 + 6) l = 6 bits = 0 } // Store bits of c0. if err := ioutilx.WriteByte(w, byte(bits)); err != nil { return errutil.Err(err) } // Store continuation bytes. for i := l - 1; i >= 0; i-- { bits := tx | (x>>uint(6*i))&maskx if err := ioutilx.WriteByte(w, byte(bits)); err != nil { return errutil.Err(err) } } return nil } ================================================ FILE: meta/application.go ================================================ package meta import ( "encoding/binary" "io/ioutil" ) // Application contains third party application specific data. // // ref: https://www.xiph.org/flac/format.html#metadata_block_application type Application struct { // Registered application ID. // // ref: https://www.xiph.org/flac/id.html ID uint32 // Application data. Data []byte } // parseApplication reads and parses the body of an Application metadata block. func (block *Block) parseApplication() error { // 32 bits: ID. app := new(Application) block.Body = app err := binary.Read(block.lr, binary.BigEndian, &app.ID) if err != nil { return unexpected(err) } // Check if the Application block only contains an ID. if block.Length == 4 { return nil } // (block length)-4 bytes: Data. app.Data, err = ioutil.ReadAll(block.lr) return unexpected(err) } ================================================ FILE: meta/cuesheet.go ================================================ package meta import ( "encoding/binary" "errors" "fmt" "io" "io/ioutil" "strings" ) // A CueSheet describes how tracks are laid out within a FLAC stream. // // ref: https://www.xiph.org/flac/format.html#metadata_block_cuesheet type CueSheet struct { // Media catalog number. MCN string // Number of lead-in samples. This field only has meaning for CD-DA cue // sheets; for other uses it should be 0. Refer to the spec for additional // information. NLeadInSamples uint64 // Specifies if the cue sheet corresponds to a Compact Disc. IsCompactDisc bool // One or more tracks. The last track of a cue sheet is always the lead-out // track. Tracks []CueSheetTrack } // parseCueSheet reads and parses the body of a CueSheet metadata block. func (block *Block) parseCueSheet() error { // Parse cue sheet. // 128 bytes: MCN. szMCN, err := readString(block.lr, 128) if err != nil { return unexpected(err) } cs := &CueSheet{ MCN: stringFromSZ(szMCN), } block.Body = cs // 64 bits: NLeadInSamples. if err = binary.Read(block.lr, binary.BigEndian, &cs.NLeadInSamples); err != nil { return unexpected(err) } // 1 bit: IsCompactDisc. var x uint8 if err := binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } // mask = 10000000 if x&0x80 != 0 { cs.IsCompactDisc = true } // 7 bits and 258 bytes: reserved. // mask = 01111111 if x&0x7F != 0 { return ErrInvalidPadding } lr := io.LimitReader(block.lr, 258) zr := zeros{r: lr} if _, err := io.Copy(ioutil.Discard, zr); err != nil { return err } // Parse cue sheet tracks. // 8 bits: (number of tracks) if err := binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } if x < 1 { return errors.New("meta.Block.parseCueSheet: at least one track required") } if cs.IsCompactDisc && x > 100 { return fmt.Errorf("meta.Block.parseCueSheet: number of CD-DA tracks (%d) exceeds 100", x) } cs.Tracks = make([]CueSheetTrack, x) // Each track number within a cue sheet must be unique; use uniq to keep // track. uniq := make(map[uint8]struct{}) for i := range cs.Tracks { if err := block.parseTrack(cs, i, uniq); err != nil { return err } } return nil } // parseTrack parses the i:th cue sheet track, and ensures that its track number // is unique. func (block *Block) parseTrack(cs *CueSheet, i int, uniq map[uint8]struct{}) error { track := &cs.Tracks[i] // 64 bits: Offset. if err := binary.Read(block.lr, binary.BigEndian, &track.Offset); err != nil { return unexpected(err) } if cs.IsCompactDisc && track.Offset%588 != 0 { return fmt.Errorf("meta.Block.parseCueSheet: CD-DA track offset (%d) must be evenly divisible by 588", track.Offset) } // 8 bits: Num. if err := binary.Read(block.lr, binary.BigEndian, &track.Num); err != nil { return unexpected(err) } if _, ok := uniq[track.Num]; ok { return fmt.Errorf("meta.Block.parseCueSheet: duplicated track number %d", track.Num) } uniq[track.Num] = struct{}{} if track.Num == 0 { return errors.New("meta.Block.parseCueSheet: invalid track number (0)") } isLeadOut := i == len(cs.Tracks)-1 if cs.IsCompactDisc { if !isLeadOut { if track.Num >= 100 { return fmt.Errorf("meta.Block.parseCueSheet: CD-DA track number (%d) exceeds 99", track.Num) } } else { if track.Num != 170 { return fmt.Errorf("meta.Block.parseCueSheet: invalid lead-out CD-DA track number; expected 170, got %d", track.Num) } } } else { if isLeadOut && track.Num != 255 { return fmt.Errorf("meta.Block.parseCueSheet: invalid lead-out track number; expected 255, got %d", track.Num) } } // 12 bytes: ISRC. szISRC, err := readString(block.lr, 12) if err != nil { return unexpected(err) } track.ISRC = stringFromSZ(szISRC) // 1 bit: IsAudio. var x uint8 if err = binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } // mask = 10000000 if x&0x80 == 0 { track.IsAudio = true } // 1 bit: HasPreEmphasis. // mask = 01000000 if x&0x40 != 0 { track.HasPreEmphasis = true } // 6 bits and 13 bytes: reserved. // mask = 00111111 if x&0x3F != 0 { return ErrInvalidPadding } lr := io.LimitReader(block.lr, 13) zr := zeros{r: lr} _, err = io.Copy(ioutil.Discard, zr) if err != nil { return err } // Parse indicies. // 8 bits: (number of indicies) if err = binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } if x < 1 { if !isLeadOut { return errors.New("meta.Block.parseCueSheet: at least one track index required") } // Lead-out track has no track indices to parse; return early. return nil } track.Indicies = make([]CueSheetTrackIndex, x) for i := range track.Indicies { index := &track.Indicies[i] // 64 bits: Offset. if err = binary.Read(block.lr, binary.BigEndian, &index.Offset); err != nil { return unexpected(err) } // 8 bits: Num. if err = binary.Read(block.lr, binary.BigEndian, &index.Num); err != nil { return unexpected(err) } // 3 bytes: reserved. lr = io.LimitReader(block.lr, 3) zr = zeros{r: lr} _, err = io.Copy(ioutil.Discard, zr) if err != nil { return err } } return nil } // stringFromSZ returns a copy of the given string terminated at the first // occurrence of a NULL character. func stringFromSZ(szStr string) string { pos := strings.IndexByte(szStr, '\x00') if pos == -1 { return szStr } return string(szStr[:pos]) } // CueSheetTrack contains the start offset of a track and other track specific // metadata. type CueSheetTrack struct { // Track offset in samples, relative to the beginning of the FLAC audio // stream. Offset uint64 // Track number; never 0, always unique. Num uint8 // International Standard Recording Code; empty string if not present. // // ref: http://isrc.ifpi.org/ ISRC string // Specifies if the track contains audio or data. IsAudio bool // Specifies if the track has been recorded with pre-emphasis HasPreEmphasis bool // Every track has one or more track index points, except for the lead-out // track which has zero. Each index point specifies a position within the // track. Indicies []CueSheetTrackIndex } // A CueSheetTrackIndex specifies a position within a track. type CueSheetTrackIndex struct { // Index point offset in samples, relative to the track offset. Offset uint64 // Index point number; subsequently incrementing by 1 and always unique // within a track. Num uint8 } ================================================ FILE: meta/meta.go ================================================ // Package meta implements access to FLAC metadata blocks. // // A brief introduction of the FLAC metadata format [1] follows. FLAC metadata // is stored in blocks; each block contains a header followed by a body. The // block header describes the type of the block body, its length in bytes, and // specifies if the block was the last metadata block in a FLAC stream. The // contents of the block body depends on the type specified in the block header. // // At the time of this writing, the FLAC metadata format defines seven different // metadata block types, namely: // - StreamInfo [2] // - Padding [3] // - Application [4] // - SeekTable [5] // - VorbisComment [6] // - CueSheet [7] // - Picture [8] // // Please refer to their respective documentation for further information. // // [1]: https://www.xiph.org/flac/format.html#format_overview // [2]: https://godoc.org/github.com/mewkiz/flac/meta#StreamInfo // [3]: https://www.xiph.org/flac/format.html#metadata_block_padding // [4]: https://godoc.org/github.com/mewkiz/flac/meta#Application // [5]: https://godoc.org/github.com/mewkiz/flac/meta#SeekTable // [6]: https://godoc.org/github.com/mewkiz/flac/meta#VorbisComment // [7]: https://godoc.org/github.com/mewkiz/flac/meta#CueSheet // [8]: https://godoc.org/github.com/mewkiz/flac/meta#Picture package meta import ( "errors" "io" "io/ioutil" "github.com/mewkiz/flac/internal/bits" ) // A Block contains the header and body of a metadata block. // // ref: https://www.xiph.org/flac/format.html#metadata_block type Block struct { // Metadata block header. Header // Metadata block body of type *StreamInfo, *Application, ... etc. Body is // initially nil, and gets populated by a call to Block.Parse. Body interface{} // Underlying io.Reader; limited by the length of the block body. lr io.Reader } // New creates a new Block for accessing the metadata of r. It reads and parses // a metadata block header. // // Call Block.Parse to parse the metadata block body, and call Block.Skip to // ignore it. func New(r io.Reader) (block *Block, err error) { block = new(Block) if err = block.parseHeader(r); err != nil { return block, err } block.lr = io.LimitReader(r, block.Length) return block, nil } // Parse reads and parses the header and body of a metadata block. Use New for // additional granularity. func Parse(r io.Reader) (block *Block, err error) { block, err = New(r) if err != nil { return block, err } if err = block.Parse(); err != nil { return block, err } return block, nil } // Errors returned by Parse. var ( ErrReservedType = errors.New("meta.Block.Parse: reserved block type") ErrInvalidType = errors.New("meta.Block.Parse: invalid block type") ErrDeclaredBlockTooBig = errors.New("declared block size is too big to allocate") ) // Parse reads and parses the metadata block body. func (block *Block) Parse() error { switch block.Type { case TypeStreamInfo: return block.parseStreamInfo() case TypePadding: return block.verifyPadding() case TypeApplication: return block.parseApplication() case TypeSeekTable: return block.parseSeekTable() case TypeVorbisComment: return block.parseVorbisComment() case TypeCueSheet: return block.parseCueSheet() case TypePicture: return block.parsePicture() } if block.Type >= 7 && block.Type <= 126 { return ErrReservedType } return ErrInvalidType } // Skip ignores the contents of the metadata block body. func (block *Block) Skip() error { if sr, ok := block.lr.(io.Seeker); ok { _, err := sr.Seek(0, io.SeekEnd) return err } _, err := io.Copy(ioutil.Discard, block.lr) return err } // A Header contains information about the type and length of a metadata block. // // ref: https://www.xiph.org/flac/format.html#metadata_block_header type Header struct { // Metadata block body type. Type Type // Length of body data in bytes. Length int64 // IsLast specifies if the block is the last metadata block. IsLast bool } // parseHeader reads and parses the header of a metadata block. func (block *Block) parseHeader(r io.Reader) error { // 1 bit: IsLast. br := bits.NewReader(r) x, err := br.Read(1) if err != nil { // This is the only place a metadata block may return io.EOF, which // signals a graceful end of a FLAC stream (from a metadata point of // view). // // Note that valid FLAC streams always contain at least one audio frame // after the last metadata block. Therefore an io.EOF error at this // location is always invalid. This logic is to be handled by the flac // package however. return err } if x != 0 { block.IsLast = true } // 7 bits: Type. x, err = br.Read(7) if err != nil { return unexpected(err) } block.Type = Type(x) // 24 bits: Length. x, err = br.Read(24) if err != nil { return unexpected(err) } block.Length = int64(x) return nil } // Type represents the type of a metadata block body. type Type uint8 // Metadata block body types. const ( TypeStreamInfo Type = 0 TypePadding Type = 1 TypeApplication Type = 2 TypeSeekTable Type = 3 TypeVorbisComment Type = 4 TypeCueSheet Type = 5 TypePicture Type = 6 ) func (t Type) String() string { switch t { case TypeStreamInfo: return "stream info" case TypePadding: return "padding" case TypeApplication: return "application" case TypeSeekTable: return "seek table" case TypeVorbisComment: return "vorbis comment" case TypeCueSheet: return "cue sheet" case TypePicture: return "picture" default: return "" } } // unexpected returns io.ErrUnexpectedEOF if err is io.EOF, and returns err // otherwise. func unexpected(err error) error { if err == io.EOF { return io.ErrUnexpectedEOF } return err } ================================================ FILE: meta/meta_test.go ================================================ package meta_test import ( "bytes" "errors" "io/ioutil" "reflect" "testing" "github.com/mewkiz/flac" "github.com/mewkiz/flac/meta" ) var golden = []struct { path string info *meta.StreamInfo blocks []*meta.Block }{ { path: "../testdata/59996.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1000, BlockSizeMax: 0x1000, FrameSizeMin: 0x44c5, FrameSizeMax: 0x4588, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x18, NSamples: 0x2000, MD5sum: [16]uint8{0x95, 0xba, 0xe5, 0xe2, 0xc7, 0x45, 0xbb, 0x3c, 0xa9, 0x5c, 0xa3, 0xb1, 0x35, 0xc9, 0x43, 0xf4}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x4, Length: 202, IsLast: true}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.2.1 20070917", Tags: [][2]string{{"Description", "Waving a bamboo staff"}, {"YEAR", "2008"}, {"ARTIST", "qubodup aka Iwan Gabovitch | qubodup@gmail.com"}, {"COMMENTS", "I release this file into the public domain"}}}, }, }, }, { path: "../testdata/172960.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1000, BlockSizeMax: 0x1000, FrameSizeMin: 0xb7c, FrameSizeMax: 0x256b, SampleRate: 0x17700, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0xaaa3, MD5sum: [16]uint8{0x76, 0x3d, 0xa8, 0xa5, 0xb7, 0x58, 0xe6, 0x2, 0x61, 0xb4, 0xd4, 0xc2, 0x88, 0x4d, 0x8e, 0xe}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x4, Length: 180, IsLast: true}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.2.1 20070917", Tags: [][2]string{{"GENRE", "Sound Clip"}, {"ARTIST", "Iwan 'qubodup' Gabovitch"}, {"Artist Homepage", "http://qubodup.net"}, {"Artist Email", "qubodup@gmail.com"}, {"DATE", "2012"}}}, }, }, }, { path: "../testdata/189983.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0x94d, FrameSizeMax: 0x264a, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x50f4, MD5sum: [16]uint8{0x63, 0x28, 0xed, 0x6d, 0xd3, 0xe, 0x55, 0xfb, 0xa5, 0x73, 0x69, 0x2b, 0xb7, 0x35, 0x73, 0xb7}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x4, Length: 40, IsLast: true}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.2.1 20070917", Tags: nil}, }, }, }, { path: "testdata/input-SCPAP.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x3, Length: 180, IsLast: false}, Body: &meta.SeekTable{Points: []meta.SeekPoint{{SampleNum: 0x0, Offset: 0x0, NSamples: 0x1200}, {SampleNum: 0x1200, Offset: 0xe, NSamples: 0x4f8}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}}}, }, { Header: meta.Header{Type: 0x5, Length: 540, IsLast: false}, Body: &meta.CueSheet{MCN: "1234567890123", NLeadInSamples: 0x15888, IsCompactDisc: true, Tracks: []meta.CueSheetTrack{{Offset: 0x0, Num: 0x1, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}, {Offset: 0x24c, Num: 0x2}}}, {Offset: 0xb7c, Num: 0x2, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}}}, {Offset: 0x16f8, Num: 0xaa, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex(nil)}}}, }, { Header: meta.Header{Type: 0x1, Length: 4, IsLast: false}, Body: nil, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: false}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, { Header: meta.Header{Type: 0x1, Length: 3201, IsLast: true}, Body: nil, }, }, }, { path: "testdata/input-SCVA.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x3, Length: 180, IsLast: false}, Body: &meta.SeekTable{Points: []meta.SeekPoint{{SampleNum: 0x0, Offset: 0x0, NSamples: 0x1200}, {SampleNum: 0x1200, Offset: 0xe, NSamples: 0x4f8}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}}}, }, { Header: meta.Header{Type: 0x5, Length: 540, IsLast: false}, Body: &meta.CueSheet{MCN: "1234567890123", NLeadInSamples: 0x15888, IsCompactDisc: true, Tracks: []meta.CueSheetTrack{{Offset: 0x0, Num: 0x1, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}, {Offset: 0x24c, Num: 0x2}}}, {Offset: 0xb7c, Num: 0x2, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}}}, {Offset: 0x16f8, Num: 0xaa, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex(nil)}}}, }, { Header: meta.Header{Type: 0x4, Length: 203, IsLast: false}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.1.3 20060805", Tags: [][2]string{{"REPLAYGAIN_TRACK_PEAK", "0.99996948"}, {"REPLAYGAIN_TRACK_GAIN", "-7.89 dB"}, {"REPLAYGAIN_ALBUM_PEAK", "0.99996948"}, {"REPLAYGAIN_ALBUM_GAIN", "-7.89 dB"}, {"artist", "1"}, {"title", "2"}}}, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: true}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, }, }, { path: "testdata/input-SCVAUP.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x3, Length: 180, IsLast: false}, Body: &meta.SeekTable{Points: []meta.SeekPoint{{SampleNum: 0x0, Offset: 0x0, NSamples: 0x1200}, {SampleNum: 0x1200, Offset: 0xe, NSamples: 0x4f8}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}}}, }, { Header: meta.Header{Type: 0x5, Length: 540, IsLast: false}, Body: &meta.CueSheet{MCN: "1234567890123", NLeadInSamples: 0x15888, IsCompactDisc: true, Tracks: []meta.CueSheetTrack{{Offset: 0x0, Num: 0x1, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}, {Offset: 0x24c, Num: 0x2}}}, {Offset: 0xb7c, Num: 0x2, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}}}, {Offset: 0x16f8, Num: 0xaa, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex(nil)}}}, }, { Header: meta.Header{Type: 0x4, Length: 203, IsLast: false}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.1.3 20060805", Tags: [][2]string{{"REPLAYGAIN_TRACK_PEAK", "0.99996948"}, {"REPLAYGAIN_TRACK_GAIN", "-7.89 dB"}, {"REPLAYGAIN_ALBUM_PEAK", "0.99996948"}, {"REPLAYGAIN_ALBUM_GAIN", "-7.89 dB"}, {"artist", "1"}, {"title", "2"}}}, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: false}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, { Header: meta.Header{Type: 0x7e, Length: 0, IsLast: false}, Body: nil, }, { Header: meta.Header{Type: 0x1, Length: 3201, IsLast: true}, Body: nil, }, }, }, { path: "testdata/input-SCVPAP.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x3, Length: 180, IsLast: false}, Body: &meta.SeekTable{Points: []meta.SeekPoint{{SampleNum: 0x0, Offset: 0x0, NSamples: 0x1200}, {SampleNum: 0x1200, Offset: 0xe, NSamples: 0x4f8}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}}}, }, { Header: meta.Header{Type: 0x5, Length: 540, IsLast: false}, Body: &meta.CueSheet{MCN: "1234567890123", NLeadInSamples: 0x15888, IsCompactDisc: true, Tracks: []meta.CueSheetTrack{{Offset: 0x0, Num: 0x1, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}, {Offset: 0x24c, Num: 0x2}}}, {Offset: 0xb7c, Num: 0x2, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex{{Offset: 0x0, Num: 0x1}}}, {Offset: 0x16f8, Num: 0xaa, ISRC: "", IsAudio: true, HasPreEmphasis: false, Indicies: []meta.CueSheetTrackIndex(nil)}}}, }, { Header: meta.Header{Type: 0x4, Length: 203, IsLast: false}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.1.3 20060805", Tags: [][2]string{{"REPLAYGAIN_TRACK_PEAK", "0.99996948"}, {"REPLAYGAIN_TRACK_GAIN", "-7.89 dB"}, {"REPLAYGAIN_ALBUM_PEAK", "0.99996948"}, {"REPLAYGAIN_ALBUM_GAIN", "-7.89 dB"}, {"artist", "1"}, {"title", "2"}}}, }, { Header: meta.Header{Type: 0x1, Length: 4, IsLast: false}, Body: nil, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: false}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, { Header: meta.Header{Type: 0x1, Length: 3201, IsLast: true}, Body: nil, }, }, }, { path: "testdata/input-SVAUP.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x3, Length: 180, IsLast: false}, Body: &meta.SeekTable{Points: []meta.SeekPoint{{SampleNum: 0x0, Offset: 0x0, NSamples: 0x1200}, {SampleNum: 0x1200, Offset: 0xe, NSamples: 0x4f8}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}, {SampleNum: 0xffffffffffffffff, Offset: 0x0, NSamples: 0x0}}}, }, { Header: meta.Header{Type: 0x4, Length: 203, IsLast: false}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.1.3 20060805", Tags: [][2]string{{"REPLAYGAIN_TRACK_PEAK", "0.99996948"}, {"REPLAYGAIN_TRACK_GAIN", "-7.89 dB"}, {"REPLAYGAIN_ALBUM_PEAK", "0.99996948"}, {"REPLAYGAIN_ALBUM_GAIN", "-7.89 dB"}, {"artist", "1"}, {"title", "2"}}}, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: false}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, { Header: meta.Header{Type: 0x7e, Length: 0, IsLast: false}, Body: nil, }, { Header: meta.Header{Type: 0x1, Length: 3201, IsLast: true}, Body: nil, }, }, }, { path: "testdata/input-VA.flac", info: &meta.StreamInfo{BlockSizeMin: 0x1200, BlockSizeMax: 0x1200, FrameSizeMin: 0xe, FrameSizeMax: 0x10, SampleRate: 0xac44, NChannels: 0x2, BitsPerSample: 0x10, NSamples: 0x16f8, MD5sum: [16]uint8{0x74, 0xff, 0xd4, 0x73, 0x7e, 0xb5, 0x48, 0x8d, 0x51, 0x2b, 0xe4, 0xaf, 0x58, 0x94, 0x33, 0x62}}, blocks: []*meta.Block{ { Header: meta.Header{Type: 0x4, Length: 203, IsLast: false}, Body: &meta.VorbisComment{Vendor: "reference libFLAC 1.1.3 20060805", Tags: [][2]string{{"REPLAYGAIN_TRACK_PEAK", "0.99996948"}, {"REPLAYGAIN_TRACK_GAIN", "-7.89 dB"}, {"REPLAYGAIN_ALBUM_PEAK", "0.99996948"}, {"REPLAYGAIN_ALBUM_GAIN", "-7.89 dB"}, {"artist", "1"}, {"title", "2"}}}, }, { Header: meta.Header{Type: 0x2, Length: 4, IsLast: true}, Body: &meta.Application{ID: 0x66616b65, Data: nil}, }, }, }, } func TestParseBlocks(t *testing.T) { for _, g := range golden { stream, err := flac.ParseFile(g.path) if err != nil { t.Fatal(err) } defer stream.Close() blocks := stream.Blocks if len(blocks) != len(g.blocks) { t.Errorf("path=%q: invalid number of metadata blocks; expected %d, got %d", g.path, len(g.blocks), len(blocks)) continue } got := stream.Info want := g.info if !reflect.DeepEqual(got, want) { t.Errorf("path=%q: metadata StreamInfo block bodies differ; expected %#v, got %#v", g.path, want, got) } for blockNum, got := range blocks { want := g.blocks[blockNum] if !reflect.DeepEqual(got.Header, want.Header) { t.Errorf("path=%q, blockNum=%d: metadata block headers differ; expected %#v, got %#v", g.path, blockNum, want.Header, got.Header) } if !reflect.DeepEqual(got.Body, want.Body) { t.Errorf("path=%q, blockNum=%d: metadata block bodies differ; expected %#v, got %#v", g.path, blockNum, want.Body, got.Body) } } } } func TestParsePicture(t *testing.T) { stream, err := flac.ParseFile("testdata/silence.flac") if err != nil { t.Fatal(err) } defer stream.Close() want, err := ioutil.ReadFile("testdata/silence.jpg") if err != nil { t.Fatal(err) } for _, block := range stream.Blocks { if block.Type == meta.TypePicture { pic := block.Body.(*meta.Picture) got := pic.Data if !bytes.Equal(got, want) { t.Errorf("picture data differ; expected %v, got %v", want, got) } break } } } // TODO: better error verification than string-based comparisons. func TestMissingValue(t *testing.T) { _, err := flac.ParseFile("testdata/missing-value.flac") if err.Error() != `meta.Block.parseVorbisComment: unable to locate '=' in vector "title 2"` { t.Fatal(err) } } var MaliciousTooManyTags = []byte{ // "fLaC" 0x66, 0x4C, 0x61, 0x43, // StreamInfo header: type=0, len=34 (0x22) 0x00, 0x00, 0x00, 0x22, // StreamInfo body (34 bytes): // BlockSizeMin=16, BlockSizeMax=16 0x00, 0x10, 0x00, 0x10, // FrameSizeMin=0, FrameSizeMax=0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 64-bit packed: sampleRate=1, channels=1, bitsPerSample=4, nSamples=0 0x00, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, // MD5 (16 zeros) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VorbisComment header: isLast=1,type=4,len=9 0x84, 0x00, 0x00, 0x09, // vendor length = 1 (little endian) 0x01, 0x00, 0x00, 0x00, // vendor string: "x" 0x78, // tags list length = 4278190080 (little endian) 0x00, 0x00, 0x00, 0xff, } func TestVorbisCommentTooManyTags(t *testing.T) { _, err := flac.Parse(bytes.NewReader(MaliciousTooManyTags)) if !errors.Is(err, meta.ErrDeclaredBlockTooBig) { t.Errorf("expected to detect malicious number of tags; actual error=%q", err) } } // TestVorbisCommentTooManyTagsOOM is designed to parse corrupt or malicious data that may lead to out-of-memory problems. // It is skipped by default as it may cause instability during test runs. func TestVorbisCommentTooManyTagsOOM(t *testing.T) { t.Skip() for i := 0; i < 255; i++ { // Parse full metadata stream s, err := flac.Parse(bytes.NewReader(MaliciousTooManyTags)) if err != nil { continue } for { if _, err := s.ParseNext(); err != nil { break } } } } ================================================ FILE: meta/padding.go ================================================ package meta import ( "errors" "io" "io/ioutil" ) // verifyPadding verifies the body of a Padding metadata block. It should only // contain zero-padding. // // ref: https://www.xiph.org/flac/format.html#metadata_block_padding func (block *Block) verifyPadding() error { zr := zeros{r: block.lr} _, err := io.Copy(ioutil.Discard, zr) return err } // Errors returned by zeros.Read. var ( ErrInvalidPadding = errors.New("invalid padding") ) // zeros implements an io.Reader, with a Read method which returns an error if // any byte read isn't zero. type zeros struct { r io.Reader } // Read returns an error if any byte read isn't zero. func (zr zeros) Read(p []byte) (n int, err error) { n, err = zr.r.Read(p) for i := 0; i < n; i++ { if p[i] != 0 { return n, ErrInvalidPadding } } return n, err } ================================================ FILE: meta/picture.go ================================================ package meta import ( "encoding/binary" "fmt" "io" ) const maxPictureDataSize = 128 << 20 // 128 MB // Picture contains the image data of an embedded picture. // // ref: https://www.xiph.org/flac/format.html#metadata_block_picture type Picture struct { // Picture type according to the ID3v2 APIC frame: // // 0: Other // 1: 32x32 pixels 'file icon' (PNG only) // 2: Other file icon // 3: Cover (front) // 4: Cover (back) // 5: Leaflet page // 6: Media (e.g. label side of CD) // 7: Lead artist/lead performer/soloist // 8: Artist/performer // 9: Conductor // 10: Band/Orchestra // 11: Composer // 12: Lyricist/text writer // 13: Recording Location // 14: During recording // 15: During performance // 16: Movie/video screen capture // 17: A bright coloured fish // 18: Illustration // 19: Band/artist logotype // 20: Publisher/Studio logotype // // ref: http://id3.org/id3v2.4.0-frames Type uint32 // MIME type string. The MIME type "-->" specifies that the picture data is // to be interpreted as an URL instead of image data. MIME string // Description of the picture. Desc string // Image dimensions. Width, Height uint32 // Color depth in bits-per-pixel. Depth uint32 // Number of colors in palette; 0 for non-indexed images. NPalColors uint32 // Image data. Data []byte } // parsePicture reads and parses the body of a Picture metadata block. func (block *Block) parsePicture() error { // 32 bits: Type. pic := new(Picture) block.Body = pic err := binary.Read(block.lr, binary.BigEndian, &pic.Type) if err != nil { return unexpected(err) } // 32 bits: (MIME type length). var x uint32 if err = binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } // (MIME type length) bytes: MIME. mime, err := readString(block.lr, int(x)) if err != nil { return unexpected(err) } pic.MIME = mime // 32 bits: (description length). if err = binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } // (description length) bytes: Desc. desc, err := readString(block.lr, int(x)) if err != nil { return unexpected(err) } pic.Desc = desc // 32 bits: Width. if err = binary.Read(block.lr, binary.BigEndian, &pic.Width); err != nil { return unexpected(err) } // 32 bits: Height. if err = binary.Read(block.lr, binary.BigEndian, &pic.Height); err != nil { return unexpected(err) } // 32 bits: Depth. if err = binary.Read(block.lr, binary.BigEndian, &pic.Depth); err != nil { return unexpected(err) } // 32 bits: NPalColors. if err = binary.Read(block.lr, binary.BigEndian, &pic.NPalColors); err != nil { return unexpected(err) } // 32 bits: (data length). if err = binary.Read(block.lr, binary.BigEndian, &x); err != nil { return unexpected(err) } if x == 0 { return nil } if x > maxPictureDataSize { return fmt.Errorf("meta.parsePicture: %w, picture data size=%d", ErrDeclaredBlockTooBig, x) } // (data length) bytes: Data. pic.Data = make([]byte, x) _, err = io.ReadFull(block.lr, pic.Data) return unexpected(err) } ================================================ FILE: meta/reader.go ================================================ package meta import "io" // readString reads and returns exactly n bytes from the provided io.Reader. // // The error is io.EOF only if no bytes were read. If an io.EOF happens after // reading some but not all the bytes, ReadFull returns io.ErrUnexpectedEOF. On // return, n == len(buf) if and only if err == nil. func readString(r io.Reader, n int) (string, error) { // readBuf is the local buffer used by readBytes. var backingArray [4096]byte // hopefully allocated on stack. readBuf := backingArray[:] if n > len(readBuf) { // The local buffer is initially 4096 bytes and will grow automatically if // so required. readBuf = make([]byte, n) } _, err := io.ReadFull(r, readBuf[:n]) if err != nil { return "", err } return string(readBuf[:n]), nil } ================================================ FILE: meta/seektable.go ================================================ package meta import ( "encoding/binary" "errors" "fmt" ) const maxSeekPoints = 1000000 // SeekTable contains one or more pre-calculated audio frame seek points. // // ref: https://www.xiph.org/flac/format.html#metadata_block_seektable type SeekTable struct { // One or more seek points. Points []SeekPoint } // parseSeekTable reads and parses the body of a SeekTable metadata block. func (block *Block) parseSeekTable() error { // The number of seek points is derived from the header length, divided by // the size of a SeekPoint; which is 18 bytes. n := block.Length / 18 if n < 1 { return errors.New("meta.Block.parseSeekTable: at least one seek point is required") } if n > maxSeekPoints { return fmt.Errorf("meta.parseSeekTable: %w, number of seekpoints: %d", ErrDeclaredBlockTooBig, n) } table := &SeekTable{Points: make([]SeekPoint, n)} block.Body = table var prev uint64 for i := range table.Points { point := &table.Points[i] err := binary.Read(block.lr, binary.BigEndian, point) if err != nil { return unexpected(err) } // Seek points within a table must be sorted in ascending order by sample // number. Each seek point must have a unique sample number, except for // placeholder points. sampleNum := point.SampleNum if i != 0 && sampleNum != PlaceholderPoint { switch { case sampleNum < prev: return fmt.Errorf("meta.Block.parseSeekTable: invalid seek point order; sample number (%d) < prev (%d)", sampleNum, prev) case sampleNum == prev: return fmt.Errorf("meta.Block.parseSeekTable: duplicate seek point with sample number (%d)", sampleNum) } } } return nil } // A SeekPoint specifies the byte offset and initial sample number of a given // target frame. // // ref: https://www.xiph.org/flac/format.html#seekpoint type SeekPoint struct { // Sample number of the first sample in the target frame, or // 0xFFFFFFFFFFFFFFFF for a placeholder point. SampleNum uint64 // Offset in bytes from the first byte of the first frame header to the first // byte of the target frame's header. Offset uint64 // Number of samples in the target frame. NSamples uint16 } // PlaceholderPoint represent the sample number used to specify placeholder seek // points. const PlaceholderPoint = 0xFFFFFFFFFFFFFFFF ================================================ FILE: meta/streaminfo.go ================================================ package meta import ( "crypto/md5" "errors" "fmt" "io" "github.com/mewkiz/flac/internal/bits" ) // 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 a 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) } ================================================ FILE: meta/testdata/README.md ================================================ # Testcase Licences ## BSD License The following testcase sounds have been copied from the [reference implementation] library, which is released under a [BSD license]. * input-SCPAP.flac * input-SCVA.flac * input-SCVAUP.flac * input-SCVPAP.flac * input-SVAUP.flac * input-VA.flac * `missing-value.flac`, created using the following command. ```shell sed 's/title=/title /' input-SCVA.flac > missing-value.flac ``` [reference implementation]: https://git.xiph.org/?p=flac.git [BSD license]: https://git.xiph.org/?p=flac.git;a=blob_plain;f=COPYING.Xiph ## Public domain The following testcase images and sounds have been released into the [public domain]. * [silence.jpg](http://www.pdpics.com/photo/2546-silence-word-magnified/) * `silence.flac`, created using the following commands. ```shell ffmpeg -f lavfi -i "aevalsrc=0|0:d=3" silence.wav flac silence.wav metaflac --import-picture=silence.jpg silence.flac ``` [public domain]: https://creativecommons.org/publicdomain/zero/1.0/ ================================================ FILE: meta/vorbiscomment.go ================================================ package meta import ( "encoding/binary" "fmt" "strings" ) const maxTags = 50000 // VorbisComment contains a list of name-value pairs. // // ref: https://www.xiph.org/flac/format.html#metadata_block_vorbis_comment type VorbisComment struct { // Vendor name. Vendor string // A list of tags, each represented by a name-value pair. Tags [][2]string } // parseVorbisComment reads and parses the body of a VorbisComment metadata // block. func (block *Block) parseVorbisComment() (err error) { // 32 bits: vendor length. var x uint32 if err = binary.Read(block.lr, binary.LittleEndian, &x); err != nil { return unexpected(err) } // (vendor length) bits: Vendor. vendor, err := readString(block.lr, int(x)) if err != nil { return unexpected(err) } comment := new(VorbisComment) block.Body = comment comment.Vendor = vendor // Parse tags. // 32 bits: number of tags. if err = binary.Read(block.lr, binary.LittleEndian, &x); err != nil { return unexpected(err) } if x > maxTags { return fmt.Errorf("meta.Block.parseVorbisComment: %w, number of tags=%d", ErrDeclaredBlockTooBig, x) } if x < 1 { return nil } comment.Tags = make([][2]string, x) for i := range comment.Tags { // 32 bits: vector length if err = binary.Read(block.lr, binary.LittleEndian, &x); err != nil { return unexpected(err) } // (vector length): vector. vector, err := readString(block.lr, int(x)) if err != nil { return unexpected(err) } // Parse tag, which has the following format: // NAME=VALUE pos := strings.Index(vector, "=") if pos == -1 { return fmt.Errorf("meta.Block.parseVorbisComment: unable to locate '=' in vector %q", vector) } comment.Tags[i][0] = vector[:pos] comment.Tags[i][1] = vector[pos+1:] } return nil } ================================================ FILE: testdata/README.md ================================================ ## Git Submodule To fetch the FLAC test files of the `testdata/flac-test-files` directory, run the following command: ```bash git submodule update --init --recursive ``` ## Public domain The following testcase sounds have been released into the [public domain]. * [19875.flac](http://freesound.org/people/yawfle/sounds/19875/) * [44127.flac](http://freesound.org/people/dland/sounds/44127/) * [59996.flac](http://freesound.org/people/qubodup/sounds/59996/) * [80574.flac](http://freesound.org/people/EsbenSloth/sounds/80574/) * [172960.flac](http://freesound.org/people/qubodup/sounds/172960/) * [189983.flac](http://freesound.org/people/raygrote/sounds/189983/) * [191885.flac](http://freesound.org/people/Hedmarking/sounds/191885/) * [212768.flac](http://freesound.org/people/qubodup/sounds/212768/) * [220014.flac](http://freesound.org/people/djani00/sounds/220014/) * [243749.flac](http://freesound.org/people/unfa/sounds/243749/) * [256529.flac](http://freesound.org/people/tymorafarr/sounds/256529/) * [257344.flac](http://freesound.org/people/arseniiv/sounds/257344/) *Note:* run `convert_to_verbatim.sh` to convert the above FLAC test files to verbatim encoding (used by the prediction analysis test case). [public domain]: https://creativecommons.org/publicdomain/zero/1.0/ The following flac files are CC BY 4.0: * [8297-275156-0011.flac](http://www.openslr.org/12/) - a single file from the LibriSpeech ASR corpus, by Vassil Panyotov and DanielPovey. ================================================ FILE: testdata/convert_to_verbatim.sh ================================================ #!/bin/bash flac -l 0 --disable-fixed-subframes -V -0 -f -o 19875_verbatim.flac 19875.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 44127_verbatim.flac 44127.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 59996_verbatim.flac 59996.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 80574_verbatim.flac 80574.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 172960_verbatim.flac 172960.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 189983_verbatim.flac 189983.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 191885_verbatim.flac 191885.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 212768_verbatim.flac 212768.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 220014_verbatim.flac 220014.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 243749_verbatim.flac 243749.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 256529_verbatim.flac 256529.flac flac -l 0 --disable-fixed-subframes -V -0 -f -o 257344_verbatim.flac 257344.flac