mirror of
https://github.com/IllusionMan1212/flac-odin.git
synced 2026-10-24 18:12:29 +00:00
Compare commits
5
Commits
1142d83adb
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a0741320d
|
||
|
|
44b4e52063
|
||
|
|
ba691f7470
|
||
|
|
c8b4c93276
|
||
|
|
81aa8d0f68
|
@@ -13,17 +13,12 @@ uncommon/11 -> We error with Invalid Signature
|
|||||||
|
|
||||||
faulty/01 -> This one works when it shouldn't (Wrong max blocksize)
|
faulty/01 -> This one works when it shouldn't (Wrong max blocksize)
|
||||||
faulty/02 -> This one works when it shouldn't (Wrong max framesize)
|
faulty/02 -> This one works when it shouldn't (Wrong max framesize)
|
||||||
faulty/04 -> This one works when it shouldn't. This one has a wrong number of channels (whatever that means)
|
|
||||||
Each frame has to be played by itself, otherwise plays sped up.
|
|
||||||
faulty/05 -> This one works when it shouldn't. (Wrong number of samples)
|
|
||||||
This should be fine to decode and play.
|
|
||||||
faulty/08 -> This one works when it shouldn't. (Blocksize 65536, exceeds the allowed max of 65535)
|
|
||||||
We should error here. We segfault currently.
|
|
||||||
faulty/09 -> This one works when it shouldn't. (Blocksize 1, below the allowed min of 16 (only the last frame is allowed to have less than 16))
|
|
||||||
We should error here. We play correctly currently.
|
|
||||||
faulty/11 -> We return an error now, but we should just warn and decode the audio fine.
|
|
||||||
|
|
||||||
Things:-
|
Things:-
|
||||||
|
[ ] Seeking to arbitrary samples
|
||||||
|
- bufio `Reader` doesn't implement `.Seek` but the underlying `io.Stream` which is just a file DOES implement
|
||||||
|
`.Seek` so I think bufio `Reader` should have Seeking capabilities too as long as the underlying Reader supports it.
|
||||||
|
I could hack something together to (dis)prove this.
|
||||||
[ ] Options
|
[ ] Options
|
||||||
- [x] Vorbis comment data
|
- [x] Vorbis comment data
|
||||||
- [ ] Cuesheet ?
|
- [ ] Cuesheet ?
|
||||||
@@ -33,6 +28,7 @@ Things:-
|
|||||||
[ ] Lots of checks (look at the TODOs in flac.odin)
|
[ ] Lots of checks (look at the TODOs in flac.odin)
|
||||||
[x] Memory optimizations
|
[x] Memory optimizations
|
||||||
[ ] Speed optimizations
|
[ ] Speed optimizations
|
||||||
|
- Does this matter? So far I haven't found a FLAC file that lags while playing or stalls the audio device even without `-o:speed`
|
||||||
[ ] Seeking
|
[ ] Seeking
|
||||||
[ ] Fuzzing to test the stability of the code
|
[ ] Fuzzing to test the stability of the code
|
||||||
[x] Check if the use-after-free bug happens on Windows, and if so, if the address sanitizer will show us the full stacktrace
|
[x] Check if the use-after-free bug happens on Windows, and if so, if the address sanitizer will show us the full stacktrace
|
||||||
|
|||||||
+25
-5
@@ -1,4 +1,4 @@
|
|||||||
package flac_linux_example
|
package flac_linux_alsa_example
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
@@ -33,15 +33,19 @@ main :: proc() {
|
|||||||
fmt.eprintln("Failed to alloc memory")
|
fmt.eprintln("Failed to alloc memory")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
allocator := virtual.arena_allocator(&arena)
|
//allocator := virtual.arena_allocator(&arena)
|
||||||
|
|
||||||
|
track: mem.Tracking_Allocator
|
||||||
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
|
defer mem.tracking_allocator_destroy(&track)
|
||||||
|
context.allocator = mem.tracking_allocator(&track)
|
||||||
|
|
||||||
start := time.now()
|
start := time.now()
|
||||||
flac_data, reader, err := flac.load_from_file(os.args[1], allocator)
|
flac_data, reader, err := flac.load_from_file(os.args[1], context.allocator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.println("Error while reading flac file:", err)
|
fmt.println("Error while reading flac file:", err)
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
}
|
}
|
||||||
defer flac.destroy(flac_data, reader, allocator)
|
|
||||||
|
|
||||||
fmt.println(flac_data)
|
fmt.println(flac_data)
|
||||||
|
|
||||||
@@ -57,7 +61,7 @@ main :: proc() {
|
|||||||
md5_ctx: md5.Context
|
md5_ctx: md5.Context
|
||||||
md5.init(&md5_ctx)
|
md5.init(&md5_ctx)
|
||||||
for {
|
for {
|
||||||
frame, err := flac.read_next_frame(reader, flac_data, allocator)
|
frame, err := flac.decode_next_frame(reader, flac_data, context.allocator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == .EOF {
|
if err == .EOF {
|
||||||
break
|
break
|
||||||
@@ -123,4 +127,20 @@ main :: proc() {
|
|||||||
|
|
||||||
elapsed := time.diff(start, end)
|
elapsed := time.diff(start, end)
|
||||||
fmt.println("Decoding took", elapsed)
|
fmt.println("Decoding took", elapsed)
|
||||||
|
|
||||||
|
flac.destroy(flac_data, reader, context.allocator)
|
||||||
|
|
||||||
|
for _, leak in track.allocation_map {
|
||||||
|
fmt.printfln("%v leaked %m", leak.location, leak.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
for bad_free in track.bad_free_array {
|
||||||
|
fmt.printfln("%v allocation %p was freed badly", bad_free.location, bad_free.memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.printfln("Peak Mem: %m", track.peak_memory_allocated)
|
||||||
|
fmt.printfln("Total Mem: %m", track.total_memory_allocated)
|
||||||
|
fmt.printfln("Current Mem: %m", track.current_memory_allocated)
|
||||||
|
fmt.printfln("Total Allocs: %v, Total Frees: %v:", track.total_allocation_count, track.total_free_count)
|
||||||
|
fmt.printfln("Total Mem Free'd: %m", track.total_memory_freed)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package flac
|
package flac
|
||||||
|
|
||||||
import "core:bytes"
|
|
||||||
import "core:bufio"
|
import "core:bufio"
|
||||||
import "core:crypto/legacy/md5"
|
import "core:crypto/legacy/md5"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:time"
|
|
||||||
|
|
||||||
Error :: union {
|
Error :: union {
|
||||||
io.Error,
|
io.Error,
|
||||||
@@ -69,8 +67,8 @@ PictureType :: enum u32 {
|
|||||||
|
|
||||||
Flac :: struct {
|
Flac :: struct {
|
||||||
metadata: FlacMetadata,
|
metadata: FlacMetadata,
|
||||||
// This holds the samples up to the currently decoded frame. If all frames have
|
// This holds the samples of the current frame.
|
||||||
// been decoded then this will hold all the decoded samples.
|
// TODO: Should this be deleted? every frame already holds its own samples data
|
||||||
samples: [dynamic]i32,
|
samples: [dynamic]i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,14 +92,15 @@ Picture :: struct {
|
|||||||
height: u32,
|
height: u32,
|
||||||
depth: u32,
|
depth: u32,
|
||||||
num_colors: u32,
|
num_colors: u32,
|
||||||
data: []byte,
|
data: []byte `fmt:"-"`,
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame :: struct {
|
Frame :: struct {
|
||||||
channels: u8,
|
channels: u8,
|
||||||
sample_rate: u32,
|
sample_rate: u32,
|
||||||
// A slice of `Flac`'s `samples` field.
|
// A slice view of `Flac`'s `samples` field.
|
||||||
// Contains the frame's decoded samples.
|
// Contains the frame's decoded samples.
|
||||||
|
// DO NOT FREE.
|
||||||
samples: []i32,
|
samples: []i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,12 +429,27 @@ correlate :: proc(subframes: [][]i32, channel_assignment: ChannelAssignment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Flac, err: Error) {
|
read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (out_flac: ^Flac, err: Error) {
|
||||||
|
context.allocator = allocator
|
||||||
|
|
||||||
|
/* Held in a local rather than in the named result: an Odin `defer` cannot
|
||||||
|
change a named result, so the unwind below is able to free this but not to
|
||||||
|
nil it out for the caller. Assigning it only on the successful return means
|
||||||
|
every error path hands back nil instead of a freed pointer.
|
||||||
|
*/
|
||||||
|
flac: ^Flac
|
||||||
|
|
||||||
header := read_data(r, FlacHeader) or_return
|
header := read_data(r, FlacHeader) or_return
|
||||||
if header.magic != FLAC_MAGIC {
|
if header.magic != FLAC_MAGIC {
|
||||||
return nil, .Invalid_Signature
|
return nil, .Invalid_Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.streaminfo.min_block_size < 16 || header.streaminfo.min_block_size > 65535) ||
|
||||||
|
(header.streaminfo.max_block_size < 16 || header.streaminfo.max_block_size > 65535) ||
|
||||||
|
(header.streaminfo.min_block_size > header.streaminfo.max_block_size) {
|
||||||
|
return nil, .Invalid_Block_Size
|
||||||
|
}
|
||||||
|
|
||||||
sample_rate := header.streaminfo.sr_chan_bps_ts >> 44
|
sample_rate := header.streaminfo.sr_chan_bps_ts >> 44
|
||||||
num_channel_minus_one := (header.streaminfo.sr_chan_bps_ts >> 41) & 7
|
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
|
bits_per_sample_minus_one := (header.streaminfo.sr_chan_bps_ts >> 36) & 0x1F
|
||||||
@@ -448,7 +462,7 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
}
|
}
|
||||||
|
|
||||||
if streaminfo_header.type != .STREAMINFO {
|
if streaminfo_header.type != .STREAMINFO {
|
||||||
return flac, .Missing_StreamInfo
|
return nil, .Missing_StreamInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
if flac == nil {
|
if flac == nil {
|
||||||
@@ -462,6 +476,30 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
flac.metadata.expected_md5 = header.streaminfo.md5
|
flac.metadata.expected_md5 = header.streaminfo.md5
|
||||||
|
|
||||||
pictures := make([dynamic]Picture, 0, 2, allocator)
|
pictures := make([dynamic]Picture, 0, 2, allocator)
|
||||||
|
|
||||||
|
/* Everything allocated from here on hangs off `flac`, and a caller that gets
|
||||||
|
an error back is handed a nil `flac` -- so it has nothing to pass to
|
||||||
|
`destroy` and cannot clean any of this up itself. Unwind it here instead.
|
||||||
|
Each block below therefore hands its allocations to `flac` or to `pictures`
|
||||||
|
as soon as they exist, before the next read that could fail.
|
||||||
|
*/
|
||||||
|
defer if err != nil {
|
||||||
|
for picture in pictures {
|
||||||
|
delete(picture.mimetype)
|
||||||
|
delete(picture.description)
|
||||||
|
delete(picture.data)
|
||||||
|
}
|
||||||
|
delete(pictures)
|
||||||
|
|
||||||
|
for comment in flac.metadata.vorbis_comments {
|
||||||
|
delete(comment)
|
||||||
|
}
|
||||||
|
delete(flac.metadata.vorbis_comments)
|
||||||
|
delete(flac.metadata.vendor_name)
|
||||||
|
|
||||||
|
free(flac)
|
||||||
|
}
|
||||||
|
|
||||||
last_block := streaminfo_header.last_block
|
last_block := streaminfo_header.last_block
|
||||||
for !last_block {
|
for !last_block {
|
||||||
md_block_hdr := read_data(r, u32be) or_return
|
md_block_hdr := read_data(r, u32be) or_return
|
||||||
@@ -501,26 +539,33 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
fmt.eprintfln("Expected size: %d, Got %d", metadata_block_header.length, actual_size)
|
fmt.eprintfln("Expected size: %d, Got %d", metadata_block_header.length, actual_size)
|
||||||
}
|
}
|
||||||
case .VORBIS_COMMENT:
|
case .VORBIS_COMMENT:
|
||||||
|
// A stream may carry more than one of these; the last one wins,
|
||||||
|
// so release the previous block rather than orphaning it.
|
||||||
|
for comment in flac.metadata.vorbis_comments {
|
||||||
|
delete(comment)
|
||||||
|
}
|
||||||
|
delete(flac.metadata.vorbis_comments)
|
||||||
|
delete(flac.metadata.vendor_name)
|
||||||
|
flac.metadata.vorbis_comments = nil
|
||||||
|
flac.metadata.vendor_name = ""
|
||||||
|
|
||||||
vendor_name_len := read_data(r, u32le) or_return
|
vendor_name_len := read_data(r, u32le) or_return
|
||||||
vendor_name_slice := make([]byte, vendor_name_len)
|
vendor_name_slice := make([]byte, vendor_name_len)
|
||||||
|
flac.metadata.vendor_name = string(vendor_name_slice)
|
||||||
read_slice(r, vendor_name_slice) or_return
|
read_slice(r, vendor_name_slice) or_return
|
||||||
vendor_name := string(vendor_name_slice)
|
|
||||||
user_comment_list_len := read_data(r, u32le) or_return
|
user_comment_list_len := read_data(r, u32le) or_return
|
||||||
|
|
||||||
actual_size := 4 + vendor_name_len + 4
|
actual_size := 4 + vendor_name_len + 4
|
||||||
|
|
||||||
comments := make([]string, user_comment_list_len)
|
comments := make([]string, user_comment_list_len)
|
||||||
|
flac.metadata.vorbis_comments = comments
|
||||||
for i in 0..<user_comment_list_len {
|
for i in 0..<user_comment_list_len {
|
||||||
comment_len := read_data(r, u32le) or_return
|
comment_len := read_data(r, u32le) or_return
|
||||||
comment_slice := make([]byte, comment_len)
|
comment_slice := make([]byte, comment_len)
|
||||||
|
comments[i] = string(comment_slice)
|
||||||
read_slice(r, comment_slice) or_return
|
read_slice(r, comment_slice) or_return
|
||||||
comment := string(comment_slice)
|
|
||||||
actual_size += 4 + comment_len
|
actual_size += 4 + comment_len
|
||||||
|
|
||||||
comments[i] = comment
|
|
||||||
}
|
}
|
||||||
flac.metadata.vorbis_comments = comments
|
|
||||||
flac.metadata.vendor_name = vendor_name
|
|
||||||
if metadata_block_header.length != u32(actual_size) {
|
if metadata_block_header.length != u32(actual_size) {
|
||||||
fmt.eprintln("Vorbis metadata header length mismatch!")
|
fmt.eprintln("Vorbis metadata header length mismatch!")
|
||||||
fmt.eprintfln("Expected size: %d, Got %d", metadata_block_header.length, actual_size)
|
fmt.eprintfln("Expected size: %d, Got %d", metadata_block_header.length, actual_size)
|
||||||
@@ -532,7 +577,7 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
cuesheet := read_data(r, CueSheet) or_return
|
cuesheet := read_data(r, CueSheet) or_return
|
||||||
if cuesheet.num_tracks < 1 {
|
if cuesheet.num_tracks < 1 {
|
||||||
// TODO: should this be a warning instead of an error that halts the decoding?
|
// TODO: should this be a warning instead of an error that halts the decoding?
|
||||||
return flac, .Missing_Lead_Out_Track
|
return nil, .Missing_Lead_Out_Track
|
||||||
}
|
}
|
||||||
//fmt.println(cuesheet)
|
//fmt.println(cuesheet)
|
||||||
for i in 0..<cuesheet.num_tracks {
|
for i in 0..<cuesheet.num_tracks {
|
||||||
@@ -546,15 +591,20 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
case .PICTURE:
|
case .PICTURE:
|
||||||
pic_type := PictureType(read_data(r, u32be) or_return)
|
pic_type := PictureType(read_data(r, u32be) or_return)
|
||||||
mime_len := read_data(r, u32be) or_return
|
mime_len := read_data(r, u32be) or_return
|
||||||
|
// These three are only reachable through `pictures` once the
|
||||||
|
// append below runs, so they need their own unwind until then.
|
||||||
mimetype_slice := make([]byte, mime_len)
|
mimetype_slice := make([]byte, mime_len)
|
||||||
|
defer if err != nil {delete(mimetype_slice)}
|
||||||
read_slice(r, mimetype_slice) or_return
|
read_slice(r, mimetype_slice) or_return
|
||||||
mimetype := string(mimetype_slice)
|
mimetype := string(mimetype_slice)
|
||||||
desc_len := read_data(r, u32be) or_return
|
desc_len := read_data(r, u32be) or_return
|
||||||
desc_slice := make([]byte, desc_len)
|
desc_slice := make([]byte, desc_len)
|
||||||
|
defer if err != nil {delete(desc_slice)}
|
||||||
read_slice(r, desc_slice) or_return
|
read_slice(r, desc_slice) or_return
|
||||||
desc := string(desc_slice)
|
desc := string(desc_slice)
|
||||||
metadata := read_data(r, PictureMetadata) or_return
|
metadata := read_data(r, PictureMetadata) or_return
|
||||||
data := make([]byte, metadata.data_len)
|
data := make([]byte, metadata.data_len)
|
||||||
|
defer if err != nil {delete(data)}
|
||||||
read_slice(r, data) or_return
|
read_slice(r, data) or_return
|
||||||
picture := Picture{
|
picture := Picture{
|
||||||
type = pic_type,
|
type = pic_type,
|
||||||
@@ -583,7 +633,7 @@ read_metadata :: proc(r: ^Reader, allocator := context.allocator) -> (flac: ^Fla
|
|||||||
return flac, nil
|
return flac, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator) -> (frame: Frame, err: Error) {
|
decode_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator) -> (frame: Frame, err: Error) {
|
||||||
//
|
//
|
||||||
// Frame Header
|
// Frame Header
|
||||||
//
|
//
|
||||||
@@ -652,6 +702,14 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
|
|||||||
return {}, .Invalid_Block_Size
|
return {}, .Invalid_Block_Size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Any frame but the last one MUST have a block size equal to or greater
|
||||||
|
// than the minimum block size and MUST have a block size equal to or
|
||||||
|
// less than the maximum block size. The last frame MUST have a block
|
||||||
|
// size equal to or less than the maximum block size; it does not have
|
||||||
|
// to comply to the minimum block size because the block size of that
|
||||||
|
// frame must be able to accommodate the length of the audio data the
|
||||||
|
// stream contains
|
||||||
|
//
|
||||||
//if actual_block_size < 15 && !last_frame {
|
//if actual_block_size < 15 && !last_frame {
|
||||||
// TODO: block sizes less than 16 are only valid for the last frame and MUST NOT be used for any other frame.
|
// TODO: block sizes less than 16 are only valid for the last frame and MUST NOT be used for any other frame.
|
||||||
//}
|
//}
|
||||||
@@ -780,7 +838,7 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
|
|||||||
|
|
||||||
correlate(subframes, channel_assignment)
|
correlate(subframes, channel_assignment)
|
||||||
|
|
||||||
start := len(flac.samples)
|
clear(&flac.samples)
|
||||||
|
|
||||||
// Write the samples interleaved.
|
// Write the samples interleaved.
|
||||||
for i in 0..<len(subframes[0]) {
|
for i in 0..<len(subframes[0]) {
|
||||||
@@ -794,7 +852,7 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
|
|||||||
delete(subframe)
|
delete(subframe)
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.samples = flac.samples[start:]
|
frame.samples = flac.samples[:]
|
||||||
frame.channels = frame_channels
|
frame.channels = frame_channels
|
||||||
frame.sample_rate = actual_sample_rate_in_Hz
|
frame.sample_rate = actual_sample_rate_in_Hz
|
||||||
|
|
||||||
@@ -856,33 +914,47 @@ md5sum :: proc(md5_ctx: ^md5.Context, flac: ^Flac) -> Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `load_from_file` initializes a buffered reader for the file and reads all the metadata blocks.
|
// `load_from_file` initializes a buffered reader for the file and reads all the metadata blocks.
|
||||||
// Calls to `read_next_frame()` MUST be made to decode the audio data.
|
// Calls to `decode_next_frame()` MUST be made to decode the audio data.
|
||||||
// This is the recommended way to read most FLAC files as it has a minimal memory overhead.
|
// This is the recommended way to read most FLAC files as it has a minimal memory overhead.
|
||||||
load_from_file :: proc(filename: string, allocator := context.allocator) -> (flac: ^Flac, r: ^Reader, err: Error) {
|
load_from_file :: proc(filename: string, allocator := context.allocator) -> (flac: ^Flac, r: ^Reader, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
file, open_err := os.open(filename)
|
file, open_err := os.open(filename)
|
||||||
if open_err != os.ERROR_NONE {
|
if open_err != nil {
|
||||||
fmt.eprintln(open_err)
|
fmt.eprintln(open_err)
|
||||||
return nil, {}, .Unable_To_Read_File
|
return nil, nil, .Unable_To_Read_File
|
||||||
}
|
}
|
||||||
|
|
||||||
br := new(bufio.Reader)
|
br := new(bufio.Reader)
|
||||||
bufio.reader_init(br, os.stream_from_handle(file))
|
bufio.reader_init(br, os.to_stream(file))
|
||||||
|
|
||||||
r = new(Reader)
|
reader := new(Reader)
|
||||||
r.r = bufio.reader_to_stream(br)
|
reader.r = bufio.reader_to_stream(br)
|
||||||
r.buf = 0
|
reader.buf = 0
|
||||||
r.x = 0
|
reader.x = 0
|
||||||
r.n = 0
|
reader.n = 0
|
||||||
|
|
||||||
flac = read_metadata(r) or_return
|
/* Without this an unreadable file in a scanned library burns an fd and the
|
||||||
|
reader's 4 KB buffer on every attempt -- the caller is handed nil for both
|
||||||
|
results and so has no handle to close the file with.
|
||||||
|
`reader` is a local for the same reason `read_metadata` keeps one: a defer
|
||||||
|
cannot nil out the named result, so `r` is only assigned on success.
|
||||||
|
*/
|
||||||
|
defer if err != nil {
|
||||||
|
bufio.reader_destroy(br)
|
||||||
|
free(br)
|
||||||
|
free(reader)
|
||||||
|
os.close(file)
|
||||||
|
}
|
||||||
|
|
||||||
return flac, r, nil
|
flac = read_metadata(reader) or_return
|
||||||
|
|
||||||
|
return flac, reader, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `destroy` cleans up and frees the memory allocated by all 3 loading functions.
|
/* `destroy` cleans up and frees the memory allocated by all 3 loading functions.
|
||||||
The returned reader from `load_from_file` MUST be passed to `destroy` in order to close the file handle.
|
The returned reader from `load_from_file` MUST be passed to `destroy` in order to close the file handle.
|
||||||
|
Both arguments may be nil, so it is safe to defer immediately after a load.
|
||||||
---
|
---
|
||||||
The allocator that was used when loading the flac file MUST be passed to `destroy` in order to properly free
|
The allocator that was used when loading the flac file MUST be passed to `destroy` in order to properly free
|
||||||
the memory, otherwise a bad free may occur and crash the program.
|
the memory, otherwise a bad free may occur and crash the program.
|
||||||
@@ -890,21 +962,25 @@ load_from_file :: proc(filename: string, allocator := context.allocator) -> (fla
|
|||||||
destroy :: proc(flac: ^Flac, r: ^Reader = nil, allocator := context.allocator) {
|
destroy :: proc(flac: ^Flac, r: ^Reader = nil, allocator := context.allocator) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
delete(flac.samples)
|
// Tolerates a nil `flac` so a caller can `defer destroy(...)` straight after
|
||||||
for picture in flac.metadata.pictures {
|
// a load without first checking whether the load succeeded.
|
||||||
delete(picture.mimetype)
|
if flac != nil {
|
||||||
delete(picture.data)
|
delete(flac.samples)
|
||||||
delete(picture.description)
|
for picture in flac.metadata.pictures {
|
||||||
}
|
delete(picture.mimetype)
|
||||||
delete(flac.metadata.pictures)
|
delete(picture.data)
|
||||||
|
delete(picture.description)
|
||||||
|
}
|
||||||
|
delete(flac.metadata.pictures)
|
||||||
|
|
||||||
for comment in flac.metadata.vorbis_comments {
|
for comment in flac.metadata.vorbis_comments {
|
||||||
delete(comment)
|
delete(comment)
|
||||||
}
|
}
|
||||||
delete(flac.metadata.vorbis_comments)
|
delete(flac.metadata.vorbis_comments)
|
||||||
delete(flac.metadata.vendor_name)
|
delete(flac.metadata.vendor_name)
|
||||||
|
|
||||||
free(flac)
|
free(flac)
|
||||||
|
}
|
||||||
|
|
||||||
if r != nil {
|
if r != nil {
|
||||||
br := cast(^bufio.Reader)r.data
|
br := cast(^bufio.Reader)r.data
|
||||||
|
|||||||
+5
-4
@@ -212,10 +212,10 @@ CueSheet :: struct #packed {
|
|||||||
media_catalog_num: [128]byte,
|
media_catalog_num: [128]byte,
|
||||||
num_lead_in_samples: u64be,
|
num_lead_in_samples: u64be,
|
||||||
using _: bit_field u8 {
|
using _: bit_field u8 {
|
||||||
reserved: u8 | 7,
|
reserved_1: u8 | 7,
|
||||||
compact_disc: bool | 1,
|
compact_disc: bool | 1,
|
||||||
},
|
},
|
||||||
reserved: [258]byte,
|
reserved_2: [258]byte,
|
||||||
num_tracks: u8,
|
num_tracks: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,11 +225,11 @@ CueSheetTrack :: struct #packed {
|
|||||||
track_num: u8,
|
track_num: u8,
|
||||||
ISRC: [12]byte,
|
ISRC: [12]byte,
|
||||||
using _: bit_field u8 {
|
using _: bit_field u8 {
|
||||||
reserved: u8 | 6,
|
reserved_1: u8 | 6,
|
||||||
pre_emphasis: bool | 1,
|
pre_emphasis: bool | 1,
|
||||||
track_type: TrackType | 1,
|
track_type: TrackType | 1,
|
||||||
},
|
},
|
||||||
reserved: [13]byte,
|
reserved_2: [13]byte,
|
||||||
num_track_index_points: u8,
|
num_track_index_points: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,6 +240,7 @@ CueSheetTrackIndex :: struct #packed {
|
|||||||
reserved: [3]byte,
|
reserved: [3]byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(optimization_mode="favor_size")
|
||||||
decode_extended_utf8 :: proc(r: ^Reader) -> (decoded_num: u64, err: Error) {
|
decode_extended_utf8 :: proc(r: ^Reader) -> (decoded_num: u64, err: Error) {
|
||||||
MASKX :: 0b0011_1111
|
MASKX :: 0b0011_1111
|
||||||
MASK2 :: 0b0001_1111
|
MASK2 :: 0b0001_1111
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,3 @@
|
|||||||
#+private
|
|
||||||
package flac
|
package flac
|
||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
@@ -6,6 +5,8 @@ import "core:io"
|
|||||||
/* Basic byte and bit reader.
|
/* Basic byte and bit reader.
|
||||||
Uses core:bytes reader under the hood with a few useful procedures for reading structs and other types.
|
Uses core:bytes reader under the hood with a few useful procedures for reading structs and other types.
|
||||||
*/
|
*/
|
||||||
|
// Public because load_from_file hands one back; everything else in this file
|
||||||
|
// stays package-private.
|
||||||
Reader :: struct {
|
Reader :: struct {
|
||||||
using r: io.Stream,
|
using r: io.Stream,
|
||||||
// Temporary read buffer.
|
// Temporary read buffer.
|
||||||
@@ -33,6 +34,7 @@ read_data :: #force_inline proc(r: ^Reader, $T: typeid) -> (res: T, err: io.Erro
|
|||||||
// Read reads and returns the next n bits, at most 64. It buffers bits up to the
|
// Read reads and returns the next n bits, at most 64. It buffers bits up to the
|
||||||
// next byte boundary.
|
// next byte boundary.
|
||||||
// Borrowed from https://github.com/mewkiz/flac
|
// Borrowed from https://github.com/mewkiz/flac
|
||||||
|
@(private)
|
||||||
read_bits :: proc(r: ^Reader, n: uint) -> (res: u64, err: io.Error) #no_bounds_check {
|
read_bits :: proc(r: ^Reader, n: uint) -> (res: u64, err: io.Error) #no_bounds_check {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
@@ -86,6 +88,7 @@ read_bits :: proc(r: ^Reader, n: uint) -> (res: u64, err: io.Error) #no_bounds_c
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
align_to_byte :: proc(r: ^Reader) {
|
align_to_byte :: proc(r: ^Reader) {
|
||||||
r.x = 0
|
r.x = 0
|
||||||
r.n = 0
|
r.n = 0
|
||||||
|
|||||||
+90
-66
@@ -3,6 +3,7 @@ package flac_test
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
import "core:crypto/legacy/md5"
|
||||||
import "shared:flac"
|
import "shared:flac"
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
@@ -12,7 +13,7 @@ test_blocksize_4096 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Read Blocksize 4096 metadata Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Read Blocksize 4096 metadata Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -27,7 +28,7 @@ test_blocksize_4608 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 4608 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 4608 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -42,7 +43,7 @@ test_blocksize_16 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 16 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 16 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -57,7 +58,7 @@ test_blocksize_192 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 192 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 192 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ test_blocksize_254 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 254 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 254 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ test_blocksize_512 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 512 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 512 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ test_blocksize_725 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 725 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 725 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -117,7 +118,7 @@ test_blocksize_1000 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 1000 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 1000 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ test_blocksize_1937 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 1937 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 1937 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -147,7 +148,7 @@ test_blocksize_2304 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Blocksize 2304 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Blocksize 2304 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,7 @@ test_partition_order_8 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Partition order 8 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Partition order 8 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -177,7 +178,7 @@ test_qlp_precision_15_bit :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("qlp precision 15 bit Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("qlp precision 15 bit Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -192,7 +193,7 @@ test_qlp_precision_2_bit :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("qlp precision 2 bit Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("qlp precision 2 bit Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -207,7 +208,7 @@ wasted_bits :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Wasted bits Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Wasted bits Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -222,7 +223,7 @@ only_verbatim_subframes :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Only verbatim subframes Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Only verbatim subframes Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -241,7 +242,7 @@ partition_order_8_containing_escaped_partitions :: proc(t: ^testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -256,7 +257,7 @@ all_fixed_orders :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("All fixed orders Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("All fixed orders Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -271,7 +272,7 @@ precision_search :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Precision search Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Precision search Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -286,7 +287,7 @@ samplerate_35467Hz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 35467Hz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 35467Hz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -301,7 +302,7 @@ samplerate_39kHz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 39kHz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 39kHz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -316,7 +317,7 @@ samplerate_22050Hz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 22050Hz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 22050Hz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -331,7 +332,7 @@ _12_bit_per_sample :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("12 bit per sample Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("12 bit per sample Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -346,7 +347,7 @@ _8_bit_per_sample :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("8 bit per sample Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("8 bit per sample Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -367,7 +368,7 @@ variable_blocksize_file_created_with_flake_revision_264 :: proc(t: ^testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -391,7 +392,7 @@ variable_blocksize_file_created_with_flake_revision_264_modified_to_create_small
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -412,7 +413,7 @@ variable_blocksize_file_created_with_CUETools_Flake_2_1_6 :: proc(t: ^testing.T)
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -433,7 +434,7 @@ old_format_variable_blocksize_file_created_with_Flake_0_11 :: proc(t: ^testing.T
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -448,7 +449,7 @@ high_resolution_audio_default_settings :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("High resolution audio, default settings Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("High resolution audio, default settings Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -463,7 +464,7 @@ high_resolution_audio_blocksize_16384 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 16384 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 16384 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -478,7 +479,7 @@ high_resolution_audio_blocksize_13456 :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 13456 Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("High resolution audio, blocksize 13456 Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -499,7 +500,7 @@ high_resolution_audio_using_only_32nd_order_predictors :: proc(t: ^testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -520,7 +521,7 @@ high_resolution_audio_partition_order_8_containing_escaped_partitions :: proc(t:
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -535,7 +536,7 @@ samplerate_192kHz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 192kHz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 192kHz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -554,7 +555,7 @@ samplerate_192kHz_using_only_32nd_order_predictors :: proc(t: ^testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -569,7 +570,7 @@ samplerate_134560Hz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 134560Hz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 134560Hz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -584,7 +585,7 @@ samplerate_384kHz :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Samplerate 384kHz Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Samplerate 384kHz Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -599,7 +600,7 @@ _20_bit_per_sample :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("20 bit per sample Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("20 bit per sample Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -614,7 +615,7 @@ _3_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("3 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("3 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -629,7 +630,7 @@ _4_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("4 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("4 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -644,7 +645,7 @@ _5_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("5 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("5 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -659,7 +660,7 @@ _6_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("6 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("6 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -674,7 +675,7 @@ _7_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("7 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("7 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -689,7 +690,7 @@ _8_channels :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("8 channels Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("8 channels Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -710,7 +711,7 @@ _8_channel_surround_192kHz_24_bit_using_only_32nd_order_predictors :: proc(t: ^t
|
|||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -725,7 +726,7 @@ no_total_number_of_samples :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("No total number of samples Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("No total number of samples Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -740,7 +741,7 @@ no_min_max_framesize :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("No min-max framesize Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("No min-max framesize Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -755,7 +756,7 @@ only_streaminfo :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Only STREAMINFO Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Only STREAMINFO Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -770,7 +771,7 @@ extreme_large_seektable :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Extremely large SEEKTABLE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Extremely large SEEKTABLE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -785,7 +786,7 @@ extreme_large_padding :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Extremely large PADDING Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Extremely large PADDING Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -800,7 +801,7 @@ extreme_large_picture :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Extremely large PICTURE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Extremely large PICTURE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -815,7 +816,7 @@ extreme_large_vorbiscomment :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Extremely large VORBISCOMMENT Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Extremely large VORBISCOMMENT Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -830,7 +831,7 @@ extreme_large_application :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Extremely large APPLICATION Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Extremely large APPLICATION Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -845,7 +846,7 @@ cuesheet_with_very_many_indexes :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("CUESHEET with very many indexes Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("CUESHEET with very many indexes Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -860,7 +861,7 @@ _1000x_repeating_vorbiscomment :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("1000x repeating VORBSICOMMENT Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("1000x repeating VORBSICOMMENT Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -875,7 +876,7 @@ file_48_53_combined :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("File 48-53 combined Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("File 48-53 combined Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -890,7 +891,7 @@ jpg_picture :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("JPG PICTURE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("JPG PICTURE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -905,7 +906,7 @@ png_picture :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("PNG PICTURE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("PNG PICTURE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -920,7 +921,7 @@ gif_picture :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("GIF PICTURE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("GIF PICTURE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -935,7 +936,7 @@ avif_picture :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("AVIF PICTURE Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("AVIF PICTURE Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -950,7 +951,7 @@ mono_audio :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Mono audio Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Mono audio Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -965,7 +966,7 @@ predictor_overflow_check_16_bit :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 16-bit Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 16-bit Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -980,7 +981,7 @@ predictor_overflow_check_20_bit :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 20-bit Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 20-bit Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -995,7 +996,7 @@ predictor_overflow_check_24_bit :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 24-bit Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Predictor overflow check, 24-bit Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1011,7 @@ rice_partitions_with_escape_code_zero :: proc(t: ^testing.T) {
|
|||||||
testing.expect(t, err == nil, fmt.tprint("Rice partitions with escape code zero Failed with error:", err))
|
testing.expect(t, err == nil, fmt.tprint("Rice partitions with escape code zero Failed with error:", err))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1018,6 +1019,29 @@ rice_partitions_with_escape_code_zero :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
uncommon_changing_samplerate :: proc(t: ^testing.T) {
|
||||||
|
data, r, err := flac.load_from_file("flac-test-files/uncommon/01 - changing samplerate.flac")
|
||||||
|
defer flac.destroy(data, r)
|
||||||
|
testing.expect(t, err == nil, fmt.tprint("Uncommon changing samplerate Failed with error:", err))
|
||||||
|
|
||||||
|
md5_ctx: md5.Context
|
||||||
|
md5.init(&md5_ctx)
|
||||||
|
|
||||||
|
for {
|
||||||
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
|
if f_err == .EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
flac.md5hash(&md5_ctx, data.metadata.bits_per_sample, frame.samples)
|
||||||
|
testing.expect(t, f_err == nil, fmt.tprintf("Decoding Uncommon changing samplerate frame Failed with error:", f_err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.metadata.expected_md5 != 0 {
|
||||||
|
testing.expect(t, flac.md5sum(&md5_ctx, data) == nil, fmt.tprintf("Incorrect MD5 hash. Expected %v. Got %v", data.metadata.expected_md5, data.metadata.calculated_md5))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
uncommon_32_bit_per_sample :: proc(t: ^testing.T) {
|
uncommon_32_bit_per_sample :: proc(t: ^testing.T) {
|
||||||
data, r, err := flac.load_from_file("flac-test-files/uncommon/05 - 32bps audio.flac")
|
data, r, err := flac.load_from_file("flac-test-files/uncommon/05 - 32bps audio.flac")
|
||||||
@@ -1025,7 +1049,7 @@ uncommon_32_bit_per_sample :: proc(t: ^testing.T) {
|
|||||||
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))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1064,7 @@ uncommon_samplerate_768kHz :: proc(t: ^testing.T) {
|
|||||||
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))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
frame, f_err := flac.read_next_frame(r, data)
|
frame, f_err := flac.decode_next_frame(r, data)
|
||||||
if f_err == .EOF {
|
if f_err == .EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user