A few speed optimizations, still not great

This commit is contained in:
2024-06-14 03:58:36 +02:00
parent 32f252ddf3
commit 752db1536a
2 changed files with 143 additions and 77 deletions
+72 -21
View File
@@ -3,14 +3,13 @@ package flac
import "core:bytes"
import "core:io"
import "core:math"
/* Basic byte reader with support for reading bits.
Uses core:bytes reader under the hood with a few useful procedures for reading structs and other types.
*/
Reader :: struct {
using _: bytes.Reader,
bits_read_in_byte: u8,
bits_read: u8,
}
read_slice :: #force_inline proc(r: ^Reader, size: int) -> (res: []u8, err: io.Error) {
@@ -37,43 +36,95 @@ read_data :: #force_inline proc(r: ^Reader, $T: typeid) -> (res: T, err: io.Erro
return (^T)(&b[0])^, nil
}
read_bit :: #force_inline proc(r: ^Reader) -> (bit: byte, err: Error) {
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
}
byte := r.s[r.i]
// Get the bit that's after however many bits read starting from the MSB in the byte
bits := 8 - (r.bits_read_in_byte + 1)
b := (r.s[r.i:r.i+1][0] & auto_cast math.pow2_f32(bits)) >> bits
r.bits_read_in_byte += 1
bits := 8 - (r.bits_read + 1)
b := (r.s[r.i] >> bits) & 1
r.bits_read += 1
if r.bits_read_in_byte == 8 {
if r.bits_read == 8 {
r.i += 1
r.bits_read_in_byte = 0
r.bits_read = 0
}
return b, nil
}
read_bits :: proc(r: ^Reader, n: int) -> (bits: u64, err: Error) {
x: u64 = 0
//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
//}
for i in 0 ..< n {
x = 2 * x + auto_cast read_bit(r) or_return
}
// TODO: optimize this even more
read_bits :: proc(r: ^Reader, n: int) -> (bits: u64, err: Error) #no_bounds_check {
return x, nil
//if n % 8 == 0 {
//}
//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
}
read_byte :: proc(r: ^Reader) -> (b: byte, err: Error) {
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_in_byte != 0 {
b = u8(read_bits(r, 8) or_return)
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
@@ -82,7 +133,7 @@ read_byte :: proc(r: ^Reader) -> (b: byte, err: Error) {
}
align_to_byte :: proc(r: ^Reader) -> Error {
if r.bits_read_in_byte == 0 {
if r.bits_read == 0 {
return nil
}
if r.i >= i64(len(r.s)) {
@@ -90,7 +141,7 @@ align_to_byte :: proc(r: ^Reader) -> Error {
}
// Align by skipping the remaining bits in the byte
r.bits_read_in_byte = 0
r.bits_read = 0
r.i += 1
return nil