diff --git a/src/streamfile.h b/src/streamfile.h index 6c552555..c85a25ba 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -231,41 +231,22 @@ static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64 static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); } static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); } -/* The recommended int-to-float type punning in C is through union, but pointer casting - * works too (though less portable due to aliasing rules?). For C++ memcpy seems - * recommended. Both work in GCC and VS2015+ (not sure about older, ifdef as needed). */ -static inline float read_f32be(off_t offset, STREAMFILE* sf) { - union { - uint32_t u32; - float f32; - } temp; - temp.u32 = read_u32be(offset, sf); - return temp.f32; +static inline float read_f32be(off_t offset, STREAMFILE* sf) { + uint8_t buf[4]; + + if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) + return -1; + return get_f32be(buf); } static inline float read_f32le(off_t offset, STREAMFILE* sf) { - union { - uint32_t u32; - float f32; - } temp; - temp.u32 = read_u32le(offset, sf); - return temp.f32; + uint8_t buf[4]; + + if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) + return -1; + return get_f32le(buf); } -#if 0 -static inline float read_f32be_p(off_t offset, STREAMFILE* sf) { - uint32_t sample_int = read_u32be(offset, sf); - float* sample_float = (float*)&sample_int; - return *sample_float; -} -static inline float read_f32be_m(off_t offset, STREAMFILE* sf) { - uint32_t sample_int = read_u32be(offset, sf); - float sample_float; - memcpy(&sample_float, &sample_int, sizeof(uint32_t)); - return sample_float; -} -#endif #if 0 - // on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring: // uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle; // only for the functions actually used in code, and inlined if possible (like big_endian param being a constant). diff --git a/src/util.h b/src/util.h index 7df0a9f7..e4560245 100644 --- a/src/util.h +++ b/src/util.h @@ -51,14 +51,52 @@ static inline uint64_t get_u64le(const uint8_t* p) { return (uint64_t)get_64bitL static inline int64_t get_s64be(const uint8_t* p) { return ( int64_t)get_64bitBE(p); } static inline uint64_t get_u64be(const uint8_t* p) { return (uint64_t)get_64bitBE(p); } +/* The recommended int-to-float type punning in C is through union, but pointer casting + * works too (though less portable due to aliasing rules?). For C++ memcpy seems + * recommended. Both work in GCC and VS2015+ (not sure about older, ifdef as needed). */ +static inline float get_f32be(const uint8_t* p) { + union { + uint32_t u32; + float f32; + } temp; + temp.u32 = get_u32be(p); + return temp.f32; +} +static inline float get_f32le(const uint8_t* p) { + union { + uint32_t u32; + float f32; + } temp; + temp.u32 = get_u32le(p); + return temp.f32; +} +static inline float get_d64le(const uint8_t* p) { + union { + uint64_t u64; + double d64; + } temp; + temp.u64 = get_u64le(p); + return temp.d64; +} +#if 0 +static inline float get_f32be_cast(const uint8_t* p) { + uint32_t sample_int = get_u32be(p); + float* sample_float = (float*)&sample_int; + return *sample_float; +} +static inline float get_f32be_mcpy(const uint8_t* p) { + uint32_t sample_int = get_u32be(p); + float sample_float; + memcpy(&sample_float, &sample_int, sizeof(uint32_t)); + return sample_float; +} +#endif + + void put_8bit(uint8_t* buf, int8_t i); - void put_16bitLE(uint8_t* buf, int16_t i); - void put_32bitLE(uint8_t* buf, int32_t i); - void put_16bitBE(uint8_t* buf, int16_t i); - void put_32bitBE(uint8_t* buf, int32_t i); /* alias of the above */ //TODO: improve