mirror of
https://github.com/IllusionMan1212/flac-odin.git
synced 2026-10-24 02:12:29 +00:00
Cleanup comments, move internal stuff to be private, slightly improve read_bits(), start work on user-friendly stuff and options
This commit is contained in:
+52
-74
@@ -4,11 +4,11 @@ package flac
|
||||
import "core:bytes"
|
||||
import "core:io"
|
||||
|
||||
/* Basic byte reader with support for reading bits.
|
||||
/* Basic byte and bit reader.
|
||||
Uses core:bytes reader under the hood with a few useful procedures for reading structs and other types.
|
||||
*/
|
||||
Reader :: struct {
|
||||
using _: bytes.Reader,
|
||||
using _: bytes.Reader,
|
||||
bits_read: u8,
|
||||
}
|
||||
|
||||
@@ -28,18 +28,11 @@ read_slice :: #force_inline proc(r: ^Reader, size: int) -> (res: []u8, err: io.E
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make sure this takes into account the bits in bits_read_in_byte
|
||||
// Although this is probably not needed since the only times we're not alinged to a byte is when finishing a subframe
|
||||
// All frames are supposed to end byte-aligned.
|
||||
read_data :: #force_inline proc(r: ^Reader, $T: typeid) -> (res: T, err: io.Error) {
|
||||
b := read_slice(r, size_of(T)) or_return
|
||||
return (^T)(&b[0])^, nil
|
||||
}
|
||||
|
||||
pow2 :: #force_inline proc(#any_int exp: uint) -> int {
|
||||
return 1 << exp
|
||||
}
|
||||
|
||||
read_bit :: proc(r: ^Reader) -> (bit: byte, err: Error) #no_bounds_check {
|
||||
if r.i >= i64(len(r.s)) {
|
||||
return 0, .EOF
|
||||
@@ -57,79 +50,64 @@ read_bit :: proc(r: ^Reader) -> (bit: byte, err: Error) #no_bounds_check {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
//read_bits :: proc(r: ^Reader, n: int) -> (bits: u64, err: Error) {
|
||||
// x: u64 = 0
|
||||
//
|
||||
// for i in 0 ..< n {
|
||||
// x = 2 * x + auto_cast read_bit(r) or_return
|
||||
// }
|
||||
//
|
||||
// return x, nil
|
||||
//}
|
||||
read_bits :: proc(r: ^Reader, n: uint) -> (bits: u64, err: Error) #no_bounds_check {
|
||||
res: u64
|
||||
|
||||
// TODO: optimize this even more
|
||||
read_bits :: proc(r: ^Reader, n: int) -> (bits: u64, err: Error) #no_bounds_check {
|
||||
// Fast path: if we can read all bits within the current byte.
|
||||
if r.bits_read + u8(n) <= 8 {
|
||||
res = (u64(r.s[r.i]) >> (8 - r.bits_read - u8(n))) & ((1 << n) - 1)
|
||||
r.bits_read += u8(n)
|
||||
if r.bits_read == 8 {
|
||||
r.bits_read = 0
|
||||
r.i += 1
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
//if n % 8 == 0 {
|
||||
// General case: reading across multiple bytes.
|
||||
rem_bits := n
|
||||
if r.bits_read > 0 {
|
||||
// Read the remaining bits in the current byte.
|
||||
bits_in_byte := 8 - r.bits_read
|
||||
res = u64(r.s[r.i]) & ((1 << bits_in_byte) - 1)
|
||||
rem_bits -= uint(bits_in_byte)
|
||||
r.bits_read = 0
|
||||
r.i += 1
|
||||
}
|
||||
|
||||
//}
|
||||
// Read full bytes.
|
||||
for rem_bits >= 8 {
|
||||
res = (res << 8) | u64(r.s[r.i])
|
||||
rem_bits -= 8
|
||||
r.i += 1
|
||||
}
|
||||
|
||||
// Read remaining bits in the final byte.
|
||||
if rem_bits > 0 {
|
||||
res = (res << rem_bits) | (u64(r.s[r.i]) >> (8 - rem_bits))
|
||||
r.bits_read += u8(rem_bits)
|
||||
}
|
||||
|
||||
//if r.bits_remaining < u8(n) {
|
||||
// // we need to read into the next byte too and possibly more bytes
|
||||
//} else if r.bits_remaining == u8(n) {
|
||||
// r.bits_remaining = 0
|
||||
// r.i += 1
|
||||
//} else {
|
||||
|
||||
//}
|
||||
|
||||
n := n
|
||||
for n > 0 {
|
||||
if r.i >= i64(len(r.s)) {
|
||||
return 0, .EOF
|
||||
}
|
||||
|
||||
to_read := min(n, 8-int(r.bits_read))
|
||||
mask := (1 << u8(to_read)) - 1
|
||||
shift := 8 - int(r.bits_read) - to_read
|
||||
|
||||
// Extract bits from the current byte
|
||||
bitsPart := u64(r.s[r.i] >> u8(shift)) & u64(mask)
|
||||
bits |= bitsPart << u64(n - to_read)
|
||||
|
||||
// Update counters
|
||||
r.bits_read += u8(to_read)
|
||||
n -= to_read
|
||||
|
||||
// Move to the next byte if all bits in the current byte have been read
|
||||
if r.bits_read == 8 {
|
||||
r.i += 1
|
||||
r.bits_read = 0
|
||||
}
|
||||
}
|
||||
|
||||
return bits, nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
read_byte :: proc(r: ^Reader) -> (b: byte, err: Error) #no_bounds_check {
|
||||
if r.i >= i64(len(r.s)) {
|
||||
return 0, .EOF
|
||||
}
|
||||
// Continue reading from the current byte if it has unread bits.
|
||||
// Needed for the subframes.
|
||||
if r.bits_read != 0 {
|
||||
cur_byte := r.s[r.i]
|
||||
next_byte := r.s[r.i + 1]
|
||||
rem_bits := 8 - r.bits_read
|
||||
rem_bits_mask: u8 = (1 << rem_bits) - 1
|
||||
b = ((cur_byte & rem_bits_mask) << r.bits_read) | (next_byte >> rem_bits)
|
||||
r.i += 1
|
||||
} else {
|
||||
b = r.s[r.i]
|
||||
r.i += 1
|
||||
}
|
||||
return b, nil
|
||||
if r.i >= i64(len(r.s)) {
|
||||
return 0, .EOF
|
||||
}
|
||||
// Continue reading from the current byte if it has unread bits.
|
||||
if r.bits_read != 0 {
|
||||
cur_byte := r.s[r.i]
|
||||
next_byte := r.s[r.i + 1]
|
||||
rem_bits := 8 - r.bits_read
|
||||
rem_bits_mask: u8 = (1 << rem_bits) - 1
|
||||
b = ((cur_byte & rem_bits_mask) << r.bits_read) | (next_byte >> rem_bits)
|
||||
r.i += 1
|
||||
} else {
|
||||
b = r.s[r.i]
|
||||
r.i += 1
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
align_to_byte :: proc(r: ^Reader) -> Error {
|
||||
|
||||
Reference in New Issue
Block a user