mirror of
https://github.com/IllusionMan1212/flac-odin.git
synced 2026-10-24 18:12:29 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1142d83adb
|
||
|
|
f444efc5af
|
@@ -6,6 +6,7 @@ Files:-
|
||||
Playback issues in the example program that may relate to the decoder:-
|
||||
23 - Crunchy loud noise mixed with the actual audio data
|
||||
|
||||
uncommon/02 -> 6 channel audio might be incorrect (not a decoder issue afaik)
|
||||
uncommon/04 -> We get a bits per sample mismatch
|
||||
uncommon/10 -> We error with Invalid Signature. I assume for these two I should look for the frame sync bits. But maybe my decoder should reject these. idk.
|
||||
uncommon/11 -> We error with Invalid Signature
|
||||
@@ -34,8 +35,10 @@ Things:-
|
||||
[ ] Speed optimizations
|
||||
[ ] Seeking
|
||||
[ ] Fuzzing to test the stability of the code
|
||||
[ ] 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
|
||||
instead of skipping some procs.
|
||||
This was caused by `read_data()` and the tee reader writing into the buffer and us using some memory that was freed while the buffer
|
||||
resized. Solution is to use buffer data BEFORE calling `read_data()`
|
||||
|
||||
[ ] Encoder (low priority for now)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package flac_example
|
||||
package flac_linux_example
|
||||
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
@@ -51,13 +51,13 @@ main :: proc() {
|
||||
os.exit(1)
|
||||
}
|
||||
|
||||
sample_rate := flac_data.metadata.sample_rate
|
||||
// TODO: channel mapping is incorrect for anything with more than 2 channels.
|
||||
channels := flac_data.metadata.channels
|
||||
|
||||
md5_ctx: md5.Context
|
||||
md5.init(&md5_ctx)
|
||||
for {
|
||||
frame, err := flac.read_next_frame(reader, flac_data)
|
||||
frame, err := flac.read_next_frame(reader, flac_data, allocator)
|
||||
if err != nil {
|
||||
if err == .EOF {
|
||||
break
|
||||
@@ -67,20 +67,24 @@ main :: proc() {
|
||||
}
|
||||
}
|
||||
|
||||
//if frame.sample_rate != sample_rate || frame.channels != channels {
|
||||
// sample_rate = frame.sample_rate
|
||||
// channels = frame.channels
|
||||
// alsa_err = alsa.pcm_set_params(handle, .S16_LE, .RW_INTERLEAVED, u32(channels), sample_rate, 1, 0)
|
||||
// if alsa_err < 0 {
|
||||
// fmt.eprintln("Playback open error:", alsa.strerror(alsa_err))
|
||||
// os.exit(1)
|
||||
// }
|
||||
//}
|
||||
if frame.channels != channels {
|
||||
// Finish playing the previous frame before changing the hw params.
|
||||
alsa.pcm_drain(handle)
|
||||
|
||||
channels = frame.channels
|
||||
alsa_err = alsa.pcm_set_params(handle, .S16_LE, .RW_INTERLEAVED, u32(channels), flac_data.metadata.sample_rate, 1, 500000)
|
||||
if alsa_err < 0 {
|
||||
fmt.eprintln("Playback open error:", alsa.strerror(alsa_err))
|
||||
os.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: resampling
|
||||
|
||||
// 8 bps audio
|
||||
//converted_samples := make([]u8, len(samples))
|
||||
//converted_samples := make([]u8, len(frame.samples))
|
||||
//defer delete(converted_samples)
|
||||
//for sample, i in samples {
|
||||
//for sample, i in frame.samples {
|
||||
// converted_samples[i] = u8(sample & 0xFF)
|
||||
//}
|
||||
|
||||
@@ -102,13 +106,6 @@ main :: proc() {
|
||||
|
||||
flac.md5hash(&md5_ctx, flac_data.metadata.bits_per_sample, frame.samples)
|
||||
}
|
||||
end := time.now()
|
||||
|
||||
err = flac.md5sum(&md5_ctx, flac_data)
|
||||
if err == .MD5_Mismatch {
|
||||
fmt.println("Decoded audio data is not correct.")
|
||||
os.exit(1)
|
||||
}
|
||||
|
||||
alsa_err = alsa.pcm_drain(handle)
|
||||
if alsa_err < 0 {
|
||||
@@ -116,6 +113,14 @@ main :: proc() {
|
||||
}
|
||||
alsa.pcm_close(handle)
|
||||
|
||||
end := time.now()
|
||||
|
||||
err = flac.md5sum(&md5_ctx, flac_data)
|
||||
if err == .MD5_Mismatch {
|
||||
fmt.printfln("Decoded audio data is not correct. Expected MD5: %v, Got: %v", flac_data.metadata.expected_md5, flac_data.metadata.calculated_md5)
|
||||
os.exit(1)
|
||||
}
|
||||
|
||||
elapsed := time.diff(start, end)
|
||||
fmt.println("Decoding took", elapsed)
|
||||
}
|
||||
@@ -591,10 +591,6 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
|
||||
tee_r: io.Tee_Reader
|
||||
|
||||
crc_buffer: Buffer
|
||||
// NOTE: using the default heap allocator here causes a use-after-free bug on files subset/05, subset/06, and subset/25
|
||||
// No idea what the cause of the bug is.
|
||||
//
|
||||
// Resolved without understanding the root issue. See below code for a note on this.
|
||||
buffer_init_allocator(&crc_buffer, 0, 128)
|
||||
defer buffer_destroy(&crc_buffer)
|
||||
|
||||
@@ -806,13 +802,6 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
|
||||
// Frame Footer
|
||||
//
|
||||
crc16_bytes := buffer_to_bytes(&crc_buffer)
|
||||
// NOTE: The order of these two calls is important. If we're using the default heap allocator
|
||||
// for crc_buffer and we call read_data before calculate_crc16 then we run into a memory bug.
|
||||
// I'm still not sure the root cause of the bug but it disappears when they're in this order.
|
||||
//
|
||||
// In the below cases the bug doesn't happen and the order doesn't matter.
|
||||
// When using the temp allocator or an arena allocator.
|
||||
// When using the reader from the arguments instead of the tee reader.
|
||||
calculated_frame_crc := calculate_crc16(crc16_bytes)
|
||||
frame_crc := u16(read_data(r, u16be) or_return)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import "core:crypto/legacy/md5"
|
||||
FLAC_MAGIC :: 'f' << 24 | 'L' << 16 | 'a' << 8 | 'C'
|
||||
|
||||
//odinfmt: disable
|
||||
@(rodata)
|
||||
crc8_lookup := [256]u8 {
|
||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
@@ -41,6 +42,7 @@ crc8_lookup := [256]u8 {
|
||||
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3,
|
||||
}
|
||||
|
||||
@(rodata)
|
||||
crc16_lookup := [256]u16 {
|
||||
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
|
||||
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
|
||||
|
||||
Reference in New Issue
Block a user