From ae6ad428ab6c6fae483f7d8008cc27ad24afb020 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sat, 15 Jun 2024 03:39:53 +0200 Subject: [PATCH] WIP: better API --- README.md | 9 ++ TODO.md | 15 +-- example/main.odin | 2 +- flac.odin | 159 ++++++++++++++----------- internal.odin | 14 +++ tests/flac_test.odin | 277 +++++++++++++++++++++++++++++++------------ 6 files changed, 317 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index 28c8e93..2b140df 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,15 @@ FLAC decoder library written in Odin (WIP) +### References +Reference material that was used in the development of this library. + +- **Official FLAC documentation**: https://xiph.org/flac/format.html +- **IETF draft specification**: https://datatracker.ietf.org/doc/draft-ietf-cellar-flac/ +- **UTF-8 RFC3629**: https://datatracker.ietf.org/doc/html/rfc3629 +- **IETF specification's rfc backmatter**: https://github.com/ietf-wg-cellar/flac-specification/blob/master/rfc_backmatter.md +- **mewkiz's excellent library**: https://github.com/mewkiz/flac + ## LICENSE No license has been decided on yet. A suitable license will be chosen once the project is near "completion". diff --git a/TODO.md b/TODO.md index cfd8258..7d4e130 100644 --- a/TODO.md +++ b/TODO.md @@ -20,21 +20,16 @@ faulty/09 -> This one works when it shouldn't. (Blocksize 1, below the allowed m Things:- [ ] Options + - [ ] Vorbis comment data + - [ ] Cuesheet ? + - [ ] Seektable ? + - [x] Picture data [ ] File streaming API? io.Stream?? [ ] Lots of checks (look at the TODOs in flac.odin) [ ] Memory optimizations [ ] Speed optimizations [ ] Seeking -[x] RICE2 -[x] Add check for mismatched bits per sample -[x] Unencoded BPS is zero -[x] CONSTANT subframe -[x] Stereo Decorrelation -[x] MD5 checksums - - [x] VERBATIM subframe - - [x] CONSTANT subframe - - [x] FIXED subframe - - [x] LPC subframe +[ ] Fuzzing to test the stability of the code [ ] Encoder (low priority for now) diff --git a/example/main.odin b/example/main.odin index 9497607..c79eafe 100644 --- a/example/main.odin +++ b/example/main.odin @@ -23,7 +23,7 @@ main :: proc() { allocator := virtual.arena_allocator(&arena) start := time.now() - err := flac.load_from_file(os.args[1], allocator = allocator) + flac_data, err := flac.load_from_file(os.args[1], allocator = allocator) if err != nil { fmt.eprintln(err) os.exit(1) diff --git a/flac.odin b/flac.odin index fa25f85..6811936 100644 --- a/flac.odin +++ b/flac.odin @@ -52,7 +52,7 @@ Option :: enum { Options :: bit_set[Option] -PictureType :: enum u32be { +PictureType :: enum u32 { OTHER, FILE_ICON_32x32_PNG, OTHER_FILE_ICON, @@ -77,24 +77,30 @@ PictureType :: enum u32be { } Flac :: struct { - // TODO: Sample slice or array, other stuff - metadata: Flac_Metadata, + // TODO: Other stuff + metadata: FlacMetadata, samples: []i32, } -Flac_Metadata :: struct { - // TODO: Picture info and data and other stuff - total_samples: u32, +FlacMetadata :: struct { + total_samples: u64, bits_per_sample: u8, channels: u8, sample_rate: u32, + expected_md5: [16]byte, + calculated_md5: [16]byte, + pictures: []Picture, } -#assert(size_of(FlacHeader) == 0x2A) -FlacHeader :: struct #packed { - magic: u32be, - streaminfo_header: u32be, - streaminfo: StreamInfoBlock, +Picture :: struct { + type: PictureType, + mimetype: string, + description: string, + width: u32, + height: u32, + depth: u32, + num_colors: u32, + data: []byte, } decode_subframe :: proc(r: ^Reader, bps: u8, block_size: u16) -> (samples: []i32, err: Error) #no_bounds_check { @@ -168,6 +174,7 @@ decode_subframe :: proc(r: ^Reader, bps: u8, block_size: u16) -> (samples: []i32 } coefficients := make([]i32, predictor_order) + defer delete(coefficients) for i in 0.. ( err: Error, ) #no_bounds_check { @@ -462,8 +467,7 @@ decode_frame :: proc( actual_sample_rate_in_Hz: u32 switch sample_rate { case .USE_STREAMINFO: - // TODO: ditto for global streaminfo - actual_sample_rate_in_Hz = streaminfo_sample_rate + actual_sample_rate_in_Hz = flac.metadata.sample_rate case ._88_2kHz: actual_sample_rate_in_Hz = 88200 case ._176_4kHz: @@ -522,9 +526,7 @@ decode_frame :: proc( bps: u8 switch sample_size { case .USE_STREAMINFO: - // TODO: maybe we'll store the streaminfo data in a global flac struct and then retrieve from there - // instead of passing a parameter - bps = streaminfo_bps + bps = flac.metadata.bits_per_sample case ._8BPS: bps = 8 case ._12BPS: @@ -539,11 +541,11 @@ decode_frame :: proc( bps = 32 } - if bps != streaminfo_bps { + if bps != flac.metadata.bits_per_sample { return .Bits_Per_Second_Mismatch } - frame_channels := channels + frame_channels := flac.metadata.channels switch channel_assignment { case .MONO: frame_channels = 1 @@ -566,7 +568,7 @@ decode_frame :: proc( frame_channels = 2 } - if frame_channels != channels { + if frame_channels != flac.metadata.channels { // TODO: warning or error? // we have a faulty file that says it has 5 channels but subframes all say they got 1 // we also have an two uncommon files with increasing and decreasing number of channels @@ -576,6 +578,7 @@ decode_frame :: proc( // TODO: remember to clean this up subframes := make([][]i32, frame_channels) + defer delete(subframes) for i in 0.. (err: Error) { +load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (flac: ^Flac, err: Error) { r: Reader bytes.reader_init(&r, data) @@ -676,26 +687,14 @@ load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context header := read_data(&r, FlacHeader) or_return if header.magic != FLAC_MAGIC { - return .Invalid_Signature + return nil, .Invalid_Signature } - //fmt.println(header) - sample_rate := header.streaminfo.sr_chan_bps_ts >> 44 num_channel_minus_one := (header.streaminfo.sr_chan_bps_ts >> 41) & 7 bits_per_sample_minus_one := (header.streaminfo.sr_chan_bps_ts >> 36) & 0x1F total_samples := header.streaminfo.sr_chan_bps_ts & 0xFFFFFFFFF - //fmt.println("sample rate:", sample_rate) - //fmt.println("channels:", num_channel_minus_one + 1) - //fmt.println("bits per sample:", bits_per_sample_minus_one + 1) - //fmt.println("total samples:", total_samples) - - /*bit_field u32be { - last_block: bool | 1, - type: BlockType | 7, - length: u32be | 24, - }*/ streaminfo_header := MetadataBlockHeader { last_block = bool(header.streaminfo_header >> 31), type = BlockType((header.streaminfo_header >> 24) & 0x7F), @@ -703,9 +702,20 @@ load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context } if streaminfo_header.type != .STREAMINFO { - return .Missing_StreamInfo + return flac, .Missing_StreamInfo } + if flac == nil { + flac = new(Flac) + } + + flac.metadata.channels = u8(num_channel_minus_one + 1) + flac.metadata.sample_rate = u32(sample_rate) + flac.metadata.bits_per_sample = u8(bits_per_sample_minus_one + 1) + flac.metadata.total_samples = u64(total_samples) + flac.metadata.expected_md5 = header.streaminfo.md5 + + pictures := make([dynamic]Picture, 0, 2, allocator) last_block := streaminfo_header.last_block for !last_block { md_block_hdr := read_data(&r, u32be) or_return @@ -714,7 +724,6 @@ load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context type = BlockType((md_block_hdr >> 24) & 0x7F), length = u32(md_block_hdr & 0xFFFFFF), } - //fmt.println("Metadata block", metadata_block_header) last_block = cast(bool)(metadata_block_header.last_block) @@ -757,7 +766,7 @@ load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context // I think so, the comment isn't crucial to the decoding process. //fmt.println("Metadata header length mismatch!") //fmt.printfln("Expected size: %d, Got %d", metadata_block_header.length, actual_size) - return .Metadata_Block_Length_Mismatch + return flac, .Metadata_Block_Length_Mismatch } // TODO: framing bit?? //fmt.println(vendor_name) @@ -767,7 +776,7 @@ load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context cuesheet := read_data(&r, CueSheet) or_return if cuesheet.num_tracks < 1 { // TODO: should this be a warning instead of an error that halts the decoding? - return .Missing_Lead_Out_Track + return flac, .Missing_Lead_Out_Track } //fmt.println(cuesheet) for i in 0.. (err: Error) { +load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (flac: ^Flac, err: Error) { context.allocator = allocator data, ok := os.read_entire_file(filename) @@ -844,6 +851,20 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont if ok { return load_from_bytes(data) } else { - return .Unable_To_Read_File + return nil, .Unable_To_Read_File } } + +destroy :: proc(flac: ^Flac) { + // TODO: clean up the allocations + delete(flac.samples) + // TODO: I think this data gets deleted when the data from os.read_entire_file is deleted. + // Double check that and if it's true then make sure to copy this data. + // Copying small strings is fine but copying the image pixel data might be slow. + //for picture in flac.metadata.pictures { + // picture.mimetype + // picture.data + // picture.description + //} + delete(flac.metadata.pictures) +} diff --git a/internal.odin b/internal.odin index 4be0018..470478c 100644 --- a/internal.odin +++ b/internal.odin @@ -154,12 +154,26 @@ ResidualCodingMethod :: enum { RICE2, } +/* +bit_field u32be { + last_block: bool | 1, + type: BlockType | 7, + length: u32be | 24, +} +*/ MetadataBlockHeader :: struct { type: BlockType, last_block: bool, length: u32, } +#assert(size_of(FlacHeader) == 0x2A) +FlacHeader :: struct #packed { + magic: u32be, + streaminfo_header: u32be, + streaminfo: StreamInfoBlock, +} + #assert(size_of(Seekpoint) == 18) Seekpoint :: struct #packed { sample_num: u64be, diff --git a/tests/flac_test.odin b/tests/flac_test.odin index 36da236..314b602 100644 --- a/tests/flac_test.odin +++ b/tests/flac_test.odin @@ -8,529 +8,648 @@ import "shared:flac" @(test) test_blocksize_4096 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/01 - blocksize 4096.flac") + data, err := flac.load_from_file("flac-test-files/subset/01 - blocksize 4096.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 4096 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_4608 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/02 - blocksize 4608.flac") + data, err := flac.load_from_file("flac-test-files/subset/02 - blocksize 4608.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 4608 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_16 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/03 - blocksize 16.flac") + data, err := flac.load_from_file("flac-test-files/subset/03 - blocksize 16.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 16 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_192 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/04 - blocksize 192.flac") + data, err := flac.load_from_file("flac-test-files/subset/04 - blocksize 192.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 192 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_254 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/05 - blocksize 254.flac") + data, err := flac.load_from_file("flac-test-files/subset/05 - blocksize 254.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 254 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_512 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/06 - blocksize 512.flac") + data, err := flac.load_from_file("flac-test-files/subset/06 - blocksize 512.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 512 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_725 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/07 - blocksize 725.flac") + data, err := flac.load_from_file("flac-test-files/subset/07 - blocksize 725.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 725 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_1000 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/08 - blocksize 1000.flac") + data, err := flac.load_from_file("flac-test-files/subset/08 - blocksize 1000.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 1000 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_1937 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/09 - blocksize 1937.flac") + data, err := flac.load_from_file("flac-test-files/subset/09 - blocksize 1937.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 1937 Failed with error:", err)) + flac.destroy(data) } @(test) test_blocksize_2304 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/10 - blocksize 2304.flac") + data, err := flac.load_from_file("flac-test-files/subset/10 - blocksize 2304.flac") testing.expect(t, err == nil, fmt.tprint("Blocksize 2304 Failed with error:", err)) + flac.destroy(data) } @(test) test_partition_order_8 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/11 - partition order 8.flac") + data, err := flac.load_from_file("flac-test-files/subset/11 - partition order 8.flac") testing.expect(t, err == nil, fmt.tprint("Partition order 8 Failed with error:", err)) + flac.destroy(data) } @(test) test_qlp_precision_15_bit :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/12 - qlp precision 15 bit.flac") + data, err := flac.load_from_file("flac-test-files/subset/12 - qlp precision 15 bit.flac") testing.expect(t, err == nil, fmt.tprint("qlp precision 15 bit Failed with error:", err)) + flac.destroy(data) } @(test) test_qlp_precision_2_bit :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/13 - qlp precision 2 bit.flac") + data, err := flac.load_from_file("flac-test-files/subset/13 - qlp precision 2 bit.flac") testing.expect(t, err == nil, fmt.tprint("qlp precision 2 bit Failed with error:", err)) + flac.destroy(data) } @(test) wasted_bits :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/14 - wasted bits.flac") + data, err := flac.load_from_file("flac-test-files/subset/14 - wasted bits.flac") testing.expect(t, err == nil, fmt.tprint("Wasted bits Failed with error:", err)) + flac.destroy(data) } @(test) only_verbatim_subframes :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/15 - only verbatim subframes.flac") + data, err := flac.load_from_file("flac-test-files/subset/15 - only verbatim subframes.flac") testing.expect(t, err == nil, fmt.tprint("Only verbatim subframes Failed with error:", err)) + flac.destroy(data) } @(test) partition_order_8_containing_escaped_partitions :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/16 - partition order 8 containing escaped partitions.flac") + data, err := flac.load_from_file("flac-test-files/subset/16 - partition order 8 containing escaped partitions.flac") - testing.expect(t, err == nil, fmt.tprint("Partition order 8 containing escaped partitions Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("Partition order 8 containing escaped partitions Failed with error:", err), + ) + flac.destroy(data) } @(test) all_fixed_orders :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/17 - all fixed orders.flac") + data, err := flac.load_from_file("flac-test-files/subset/17 - all fixed orders.flac") testing.expect(t, err == nil, fmt.tprint("All fixed orders Failed with error:", err)) + flac.destroy(data) } @(test) precision_search :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/18 - precision search.flac") + data, err := flac.load_from_file("flac-test-files/subset/18 - precision search.flac") testing.expect(t, err == nil, fmt.tprint("Precision search Failed with error:", err)) + flac.destroy(data) } @(test) samplerate_35467Hz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/19 - samplerate 35467Hz.flac") + data, err := flac.load_from_file("flac-test-files/subset/19 - samplerate 35467Hz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 35467Hz Failed with error:", err)) + flac.destroy(data) } @(test) samplerate_39kHz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/20 - samplerate 39kHz.flac") + data, err := flac.load_from_file("flac-test-files/subset/20 - samplerate 39kHz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 39kHz Failed with error:", err)) + flac.destroy(data) } @(test) samplerate_22050Hz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/21 - samplerate 22050Hz.flac") + data, err := flac.load_from_file("flac-test-files/subset/21 - samplerate 22050Hz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 22050Hz Failed with error:", err)) + flac.destroy(data) } @(test) _12_bit_per_sample :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/22 - 12 bit per sample.flac") + data, err := flac.load_from_file("flac-test-files/subset/22 - 12 bit per sample.flac") testing.expect(t, err == nil, fmt.tprint("12 bit per sample Failed with error:", err)) + flac.destroy(data) } @(test) _8_bit_per_sample :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/23 - 8 bit per sample.flac") + data, err := flac.load_from_file("flac-test-files/subset/23 - 8 bit per sample.flac") testing.expect(t, err == nil, fmt.tprint("8 bit per sample Failed with error:", err)) + flac.destroy(data) } @(test) variable_blocksize_file_created_with_flake_revision_264 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/24 - variable blocksize file created with flake revision 264.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/24 - variable blocksize file created with flake revision 264.flac", + ) - testing.expect(t, err == nil, fmt.tprint("Variable blocksize file created with flake revision 264 Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("Variable blocksize file created with flake revision 264 Failed with error:", err), + ) + flac.destroy(data) } @(test) variable_blocksize_file_created_with_flake_revision_264_modified_to_create_smaller_blocks :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/25 - variable blocksize file created with flake revision 264, modified to create smaller blocks.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/25 - variable blocksize file created with flake revision 264, modified to create smaller blocks.flac", + ) - testing.expect(t, err == nil, fmt.tprint("Variable blocksize file created with flake revision 264 modified to create smaller blocks Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint( + "Variable blocksize file created with flake revision 264 modified to create smaller blocks Failed with error:", + err, + ), + ) + flac.destroy(data) } @(test) variable_blocksize_file_created_with_CUETools_Flake_2_1_6 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/26 - variable blocksize file created with CUETools.Flake 2.1.6.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/26 - variable blocksize file created with CUETools.Flake 2.1.6.flac", + ) - testing.expect(t, err == nil, fmt.tprint("Variable blocksize file created with CUETools.Flake 2.1.6 Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("Variable blocksize file created with CUETools.Flake 2.1.6 Failed with error:", err), + ) + flac.destroy(data) } @(test) old_format_variable_blocksize_file_created_with_Flake_0_11 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/27 - old format variable blocksize file created with Flake 0.11.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/27 - old format variable blocksize file created with Flake 0.11.flac", + ) - testing.expect(t, err == nil, fmt.tprint("Old format variable blocksize file created with Flake 0.11 Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("Old format variable blocksize file created with Flake 0.11 Failed with error:", err), + ) + flac.destroy(data) } @(test) high_resolution_audio_default_settings :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/28 - high resolution audio, default settings.flac") + data, err := flac.load_from_file("flac-test-files/subset/28 - high resolution audio, default settings.flac") testing.expect(t, err == nil, fmt.tprint("High resolution audio, default settings Failed with error:", err)) + flac.destroy(data) } @(test) high_resolution_audio_blocksize_16384 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/29 - high resolution audio, blocksize 16384.flac") + data, err := flac.load_from_file("flac-test-files/subset/29 - high resolution audio, blocksize 16384.flac") testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 16384 Failed with error:", err)) + flac.destroy(data) } @(test) high_resolution_audio_blocksize_13456 :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/30 - high resolution audio, blocksize 13456.flac") + data, err := flac.load_from_file("flac-test-files/subset/30 - high resolution audio, blocksize 13456.flac") testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 13456 Failed with error:", err)) + flac.destroy(data) } @(test) high_resolution_audio_using_only_32nd_order_predictors :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/31 - high resolution audio, using only 32nd order predictors.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/31 - high resolution audio, using only 32nd order predictors.flac", + ) - testing.expect(t, err == nil, fmt.tprint("High resolution audio, using only 32nd order predictors Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("High resolution audio, using only 32nd order predictors Failed with error:", err), + ) + flac.destroy(data) } @(test) high_resolution_audio_partition_order_8_containing_escaped_partitions :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/32 - high resolution audio, partition order 8 containing escaped partitions.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/32 - high resolution audio, partition order 8 containing escaped partitions.flac", + ) - testing.expect(t, err == nil, fmt.tprint("High resolution audio, partition order 8 containing escaped partitions Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("High resolution audio, partition order 8 containing escaped partitions Failed with error:", err), + ) + flac.destroy(data) } @(test) samplerate_192kHz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/33 - samplerate 192kHz.flac") + data, err := flac.load_from_file("flac-test-files/subset/33 - samplerate 192kHz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 192kHz Failed with error:", err)) + flac.destroy(data) } @(test) samplerate_192kHz_using_only_32nd_order_predictors :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/34 - samplerate 192kHz, using only 32nd order predictors.flac") + data, err := flac.load_from_file("flac-test-files/subset/34 - samplerate 192kHz, using only 32nd order predictors.flac") - testing.expect(t, err == nil, fmt.tprint("Samplerate 192kHz, using only 32nd order predictors Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("Samplerate 192kHz, using only 32nd order predictors Failed with error:", err), + ) + flac.destroy(data) } @(test) samplerate_134560Hz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/35 - samplerate 134560Hz.flac") + data, err := flac.load_from_file("flac-test-files/subset/35 - samplerate 134560Hz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 134560Hz Failed with error:", err)) + flac.destroy(data) } @(test) samplerate_384kHz :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/36 - samplerate 384kHz.flac") + data, err := flac.load_from_file("flac-test-files/subset/36 - samplerate 384kHz.flac") testing.expect(t, err == nil, fmt.tprint("Samplerate 384kHz Failed with error:", err)) + flac.destroy(data) } @(test) _20_bit_per_sample :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/37 - 20 bit per sample.flac") + data, err := flac.load_from_file("flac-test-files/subset/37 - 20 bit per sample.flac") testing.expect(t, err == nil, fmt.tprint("20 bit per sample Failed with error:", err)) + flac.destroy(data) } @(test) _3_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/38 - 3 channels (3.0).flac") + data, err := flac.load_from_file("flac-test-files/subset/38 - 3 channels (3.0).flac") testing.expect(t, err == nil, fmt.tprint("3 channels Failed with error:", err)) + flac.destroy(data) } @(test) _4_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/39 - 4 channels (4.0).flac") + data, err := flac.load_from_file("flac-test-files/subset/39 - 4 channels (4.0).flac") testing.expect(t, err == nil, fmt.tprint("4 channels Failed with error:", err)) + flac.destroy(data) } @(test) _5_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/40 - 5 channels (5.0).flac") + data, err := flac.load_from_file("flac-test-files/subset/40 - 5 channels (5.0).flac") testing.expect(t, err == nil, fmt.tprint("5 channels Failed with error:", err)) + flac.destroy(data) } @(test) _6_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/41 - 6 channels (5.1).flac") + data, err := flac.load_from_file("flac-test-files/subset/41 - 6 channels (5.1).flac") testing.expect(t, err == nil, fmt.tprint("6 channels Failed with error:", err)) + flac.destroy(data) } @(test) _7_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/42 - 7 channels (6.1).flac") + data, err := flac.load_from_file("flac-test-files/subset/42 - 7 channels (6.1).flac") testing.expect(t, err == nil, fmt.tprint("7 channels Failed with error:", err)) + flac.destroy(data) } @(test) _8_channels :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/43 - 8 channels (7.1).flac") + data, err := flac.load_from_file("flac-test-files/subset/43 - 8 channels (7.1).flac") testing.expect(t, err == nil, fmt.tprint("8 channels Failed with error:", err)) + flac.destroy(data) } @(test) _8_channel_surround_192kHz_24_bit_using_only_32nd_order_predictors :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/44 - 8-channel surround, 192kHz, 24 bit, using only 32nd order predictors.flac") + data, err := flac.load_from_file( + "flac-test-files/subset/44 - 8-channel surround, 192kHz, 24 bit, using only 32nd order predictors.flac", + ) - testing.expect(t, err == nil, fmt.tprint("8-channel surround 192kHz 24 bit using only 32nd order predictors Failed with error:", err)) + testing.expect( + t, + err == nil, + fmt.tprint("8-channel surround 192kHz 24 bit using only 32nd order predictors Failed with error:", err), + ) + flac.destroy(data) } @(test) no_total_number_of_samples :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/45 - no total number of samples set.flac") + data, err := flac.load_from_file("flac-test-files/subset/45 - no total number of samples set.flac") testing.expect(t, err == nil, fmt.tprint("No total number of samples Failed with error:", err)) + flac.destroy(data) } @(test) no_min_max_framesize :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/46 - no min-max framesize set.flac") + data, err := flac.load_from_file("flac-test-files/subset/46 - no min-max framesize set.flac") testing.expect(t, err == nil, fmt.tprint("No min-max framesize Failed with error:", err)) + flac.destroy(data) } @(test) only_streaminfo :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/47 - only STREAMINFO.flac") + data, err := flac.load_from_file("flac-test-files/subset/47 - only STREAMINFO.flac") testing.expect(t, err == nil, fmt.tprint("Only STREAMINFO Failed with error:", err)) + flac.destroy(data) } @(test) extreme_large_seektable :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/48 - Extremely large SEEKTABLE.flac") + data, err := flac.load_from_file("flac-test-files/subset/48 - Extremely large SEEKTABLE.flac") testing.expect(t, err == nil, fmt.tprint("Extremely large SEEKTABLE Failed with error:", err)) + flac.destroy(data) } @(test) extreme_large_padding :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/49 - Extremely large PADDING.flac") + data, err := flac.load_from_file("flac-test-files/subset/49 - Extremely large PADDING.flac") testing.expect(t, err == nil, fmt.tprint("Extremely large PADDING Failed with error:", err)) + flac.destroy(data) } @(test) extreme_large_picture :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/50 - Extremely large PICTURE.flac") + data, err := flac.load_from_file("flac-test-files/subset/50 - Extremely large PICTURE.flac") testing.expect(t, err == nil, fmt.tprint("Extremely large PICTURE Failed with error:", err)) + flac.destroy(data) } @(test) extreme_large_vorbiscomment :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/51 - Extremely large VORBISCOMMENT.flac") + data, err := flac.load_from_file("flac-test-files/subset/51 - Extremely large VORBISCOMMENT.flac") testing.expect(t, err == nil, fmt.tprint("Extremely large VORBISCOMMENT Failed with error:", err)) + flac.destroy(data) } @(test) extreme_large_application :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/52 - Extremely large APPLICATION.flac") + data, err := flac.load_from_file("flac-test-files/subset/52 - Extremely large APPLICATION.flac") testing.expect(t, err == nil, fmt.tprint("Extremely large APPLICATION Failed with error:", err)) + flac.destroy(data) } @(test) cuesheet_with_very_many_indexes :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/53 - CUESHEET with very many indexes.flac") + data, err := flac.load_from_file("flac-test-files/subset/53 - CUESHEET with very many indexes.flac") testing.expect(t, err == nil, fmt.tprint("CUESHEET with very many indexes Failed with error:", err)) + flac.destroy(data) } @(test) _1000x_repeating_vorbiscomment :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/54 - 1000x repeating VORBISCOMMENT.flac") + data, err := flac.load_from_file("flac-test-files/subset/54 - 1000x repeating VORBISCOMMENT.flac") testing.expect(t, err == nil, fmt.tprint("1000x repeating VORBSICOMMENT Failed with error:", err)) + flac.destroy(data) } @(test) file_48_53_combined :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/55 - file 48-53 combined.flac") + data, err := flac.load_from_file("flac-test-files/subset/55 - file 48-53 combined.flac") testing.expect(t, err == nil, fmt.tprint("File 48-53 combined Failed with error:", err)) + flac.destroy(data) } @(test) jpg_picture :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/56 - JPG PICTURE.flac") + data, err := flac.load_from_file("flac-test-files/subset/56 - JPG PICTURE.flac") testing.expect(t, err == nil, fmt.tprint("JPG PICTURE Failed with error:", err)) + flac.destroy(data) } @(test) png_picture :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/57 - PNG PICTURE.flac") + data, err := flac.load_from_file("flac-test-files/subset/57 - PNG PICTURE.flac") testing.expect(t, err == nil, fmt.tprint("PNG PICTURE Failed with error:", err)) + flac.destroy(data) } @(test) gif_picture :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/58 - GIF PICTURE.flac") + data, err := flac.load_from_file("flac-test-files/subset/58 - GIF PICTURE.flac") testing.expect(t, err == nil, fmt.tprint("GIF PICTURE Failed with error:", err)) + flac.destroy(data) } @(test) avif_picture :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/59 - AVIF PICTURE.flac") + data, err := flac.load_from_file("flac-test-files/subset/59 - AVIF PICTURE.flac") testing.expect(t, err == nil, fmt.tprint("AVIF PICTURE Failed with error:", err)) + flac.destroy(data) } @(test) mono_audio :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/60 - mono audio.flac") + data, err := flac.load_from_file("flac-test-files/subset/60 - mono audio.flac") testing.expect(t, err == nil, fmt.tprint("Mono audio Failed with error:", err)) + flac.destroy(data) } @(test) predictor_overflow_check_16_bit :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/61 - predictor overflow check, 16-bit.flac") + data, err := flac.load_from_file("flac-test-files/subset/61 - predictor overflow check, 16-bit.flac") testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 16-bit Failed with error:", err)) + flac.destroy(data) } @(test) predictor_overflow_check_20_bit :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/62 - predictor overflow check, 20-bit.flac") + data, err := flac.load_from_file("flac-test-files/subset/62 - predictor overflow check, 20-bit.flac") testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 20-bit Failed with error:", err)) + flac.destroy(data) } @(test) predictor_overflow_check_24_bit :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/63 - predictor overflow check, 24-bit.flac") + data, err := flac.load_from_file("flac-test-files/subset/63 - predictor overflow check, 24-bit.flac") testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 24-bit Failed with error:", err)) + flac.destroy(data) } @(test) rice_partitions_with_escape_code_zero :: proc(t: ^testing.T) { os.stdout = -1 - err := flac.load_from_file("flac-test-files/subset/64 - rice partitions with escape code zero.flac") + data, err := flac.load_from_file("flac-test-files/subset/64 - rice partitions with escape code zero.flac") testing.expect(t, err == nil, fmt.tprint("Rice partitions with escape code zero Failed with error:", err)) + flac.destroy(data) } @(test) uncommon_32_bit_per_sample :: proc(t: ^testing.T) { - os.stdout = -1 - err := flac.load_from_file("flac-test-files/uncommon/05 - 32bps audio.flac") + os.stdout = -1 + data, err := flac.load_from_file("flac-test-files/uncommon/05 - 32bps audio.flac") - testing.expect(t, err == nil, fmt.tprint("Uncommon 32bps audio Failed with error:", err)) + testing.expect(t, err == nil, fmt.tprint("Uncommon 32bps audio Failed with error:", err)) + flac.destroy(data) } @(test) uncommon_samplerate_768kHz :: proc(t: ^testing.T) { - os.stdout = -1 - err := flac.load_from_file("flac-test-files/uncommon/06 - samplerate 768kHz.flac") + os.stdout = -1 + data, err := flac.load_from_file("flac-test-files/uncommon/06 - samplerate 768kHz.flac") - testing.expect(t, err == nil, fmt.tprint("Uncommon samplerate 768kHz Failed with error:", err)) + testing.expect(t, err == nil, fmt.tprint("Uncommon samplerate 768kHz Failed with error:", err)) + flac.destroy(data) } // TODO: