Use a template to read integers with endian awareness

This commit is contained in:
Chris Robinson
2021-01-06 17:10:03 -08:00
parent 04cd0bc576
commit 292de73c75
+84 -71
View File
@@ -49,6 +49,7 @@
#include "alspan.h" #include "alspan.h"
#include "core/filters/splitter.h" #include "core/filters/splitter.h"
#include "core/logging.h" #include "core/logging.h"
#include "endiantest.h"
#include "math_defs.h" #include "math_defs.h"
#include "opthelpers.h" #include "opthelpers.h"
#include "polyphase_resampler.h" #include "polyphase_resampler.h"
@@ -462,48 +463,59 @@ void MirrorLeftHrirs(const al::span<const HrtfStore::Elevation> elevs, HrirArray
} }
} }
ubyte GetLE_ALubyte(std::istream &data)
template<typename T, size_t num_bits=sizeof(T)*8>
inline std::enable_if_t<std::is_signed<T>::value,T>
readle(std::istream &data)
{ {
return static_cast<ubyte>(data.get()); static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8");
constexpr auto signbit = static_cast<T>(1 << (num_bits-1));
al::byte b[num_bits/8];
if(!data.read(reinterpret_cast<char*>(b), sizeof(b)))
return static_cast<T>(EOF);
T ret{};
if(IS_LITTLE_ENDIAN)
std::memcpy(&ret, b, sizeof(b));
else
{
for(size_t i{0};i < sizeof(b);++i)
ret |= al::to_integer<T>(b[i]) << (i*8);
}
return (ret^signbit) - signbit;
} }
short GetLE_ALshort(std::istream &data) template<typename T, size_t num_bits=sizeof(T)*8>
inline std::enable_if_t<!std::is_signed<T>::value,T>
readle(std::istream &data)
{ {
int ret = data.get(); static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8");
ret |= data.get() << 8;
return static_cast<short>((ret^32768) - 32768);
}
ushort GetLE_ALushort(std::istream &data) al::byte b[num_bits/8];
{ if(!data.read(reinterpret_cast<char*>(b), sizeof(b)))
int ret = data.get(); return static_cast<T>(EOF);
ret |= data.get() << 8; T ret{};
return static_cast<ushort>(ret); if(IS_LITTLE_ENDIAN)
} std::memcpy(&ret, b, sizeof(b));
else
int GetLE_ALint24(std::istream &data) {
{ for(size_t i{0};i < sizeof(b);++i)
int ret = data.get(); ret |= al::to_integer<T>(b[i]) << (i*8);
ret |= data.get() << 8; }
ret |= data.get() << 16;
return (ret^8388608) - 8388608;
}
uint GetLE_ALuint(std::istream &data)
{
uint ret{static_cast<uint>(data.get())};
ret |= static_cast<uint>(data.get()) << 8;
ret |= static_cast<uint>(data.get()) << 16;
ret |= static_cast<uint>(data.get()) << 24;
return ret; return ret;
} }
template<>
inline uint8_t readle<uint8_t,8>(std::istream &data)
{ return static_cast<uint8_t>(data.get()); }
std::unique_ptr<HrtfStore> LoadHrtf00(std::istream &data, const char *filename) std::unique_ptr<HrtfStore> LoadHrtf00(std::istream &data, const char *filename)
{ {
uint rate{GetLE_ALuint(data)}; uint rate{readle<uint32_t>(data)};
ushort irCount{GetLE_ALushort(data)}; ushort irCount{readle<uint16_t>(data)};
ushort irSize{GetLE_ALushort(data)}; ushort irSize{readle<uint16_t>(data)};
ubyte evCount{GetLE_ALubyte(data)}; ubyte evCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -524,7 +536,7 @@ std::unique_ptr<HrtfStore> LoadHrtf00(std::istream &data, const char *filename)
auto elevs = al::vector<HrtfStore::Elevation>(evCount); auto elevs = al::vector<HrtfStore::Elevation>(evCount);
for(auto &elev : elevs) for(auto &elev : elevs)
elev.irOffset = GetLE_ALushort(data); elev.irOffset = readle<uint16_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -569,10 +581,10 @@ std::unique_ptr<HrtfStore> LoadHrtf00(std::istream &data, const char *filename)
for(auto &hrir : coeffs) for(auto &hrir : coeffs)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
val[0] = GetLE_ALshort(data) / 32768.0f; val[0] = readle<int16_t>(data) / 32768.0f;
} }
for(auto &val : delays) for(auto &val : delays)
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -598,9 +610,9 @@ std::unique_ptr<HrtfStore> LoadHrtf00(std::istream &data, const char *filename)
std::unique_ptr<HrtfStore> LoadHrtf01(std::istream &data, const char *filename) std::unique_ptr<HrtfStore> LoadHrtf01(std::istream &data, const char *filename)
{ {
uint rate{GetLE_ALuint(data)}; uint rate{readle<uint32_t>(data)};
ushort irSize{GetLE_ALubyte(data)}; ushort irSize{readle<uint8_t>(data)};
ubyte evCount{GetLE_ALubyte(data)}; ubyte evCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -620,7 +632,8 @@ std::unique_ptr<HrtfStore> LoadHrtf01(std::istream &data, const char *filename)
} }
auto elevs = al::vector<HrtfStore::Elevation>(evCount); auto elevs = al::vector<HrtfStore::Elevation>(evCount);
for (auto &elev : elevs) elev.azCount = GetLE_ALubyte(data); for(auto &elev : elevs)
elev.azCount = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -646,10 +659,10 @@ std::unique_ptr<HrtfStore> LoadHrtf01(std::istream &data, const char *filename)
for(auto &hrir : coeffs) for(auto &hrir : coeffs)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
val[0] = GetLE_ALshort(data) / 32768.0f; val[0] = readle<int16_t>(data) / 32768.0f;
} }
for(auto &val : delays) for(auto &val : delays)
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -680,11 +693,11 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
constexpr ubyte ChanType_LeftOnly{0}; constexpr ubyte ChanType_LeftOnly{0};
constexpr ubyte ChanType_LeftRight{1}; constexpr ubyte ChanType_LeftRight{1};
uint rate{GetLE_ALuint(data)}; uint rate{readle<uint32_t>(data)};
ubyte sampleType{GetLE_ALubyte(data)}; ubyte sampleType{readle<uint8_t>(data)};
ubyte channelType{GetLE_ALubyte(data)}; ubyte channelType{readle<uint8_t>(data)};
ushort irSize{GetLE_ALubyte(data)}; ushort irSize{readle<uint8_t>(data)};
ubyte fdCount{GetLE_ALubyte(data)}; ubyte fdCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -718,8 +731,8 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
auto elevs = al::vector<HrtfStore::Elevation>{}; auto elevs = al::vector<HrtfStore::Elevation>{};
for(size_t f{0};f < fdCount;f++) for(size_t f{0};f < fdCount;f++)
{ {
const ushort distance{GetLE_ALushort(data)}; const ushort distance{readle<uint16_t>(data)};
const ubyte evCount{GetLE_ALubyte(data)}; const ubyte evCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -751,7 +764,7 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
const size_t ebase{elevs.size()}; const size_t ebase{elevs.size()};
elevs.resize(ebase + evCount); elevs.resize(ebase + evCount);
for(auto &elev : al::span<HrtfStore::Elevation>(elevs.data()+ebase, evCount)) for(auto &elev : al::span<HrtfStore::Elevation>(elevs.data()+ebase, evCount))
elev.azCount = GetLE_ALubyte(data); elev.azCount = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -788,7 +801,7 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
for(auto &hrir : coeffs) for(auto &hrir : coeffs)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
val[0] = GetLE_ALshort(data) / 32768.0f; val[0] = readle<int16_t>(data) / 32768.0f;
} }
} }
else if(sampleType == SampleType_S24) else if(sampleType == SampleType_S24)
@@ -796,11 +809,11 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
for(auto &hrir : coeffs) for(auto &hrir : coeffs)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
val[0] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[0] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
} }
} }
for(auto &val : delays) for(auto &val : delays)
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -827,8 +840,8 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
{ {
val[0] = GetLE_ALshort(data) / 32768.0f; val[0] = readle<int16_t>(data) / 32768.0f;
val[1] = GetLE_ALshort(data) / 32768.0f; val[1] = readle<int16_t>(data) / 32768.0f;
} }
} }
} }
@@ -838,15 +851,15 @@ std::unique_ptr<HrtfStore> LoadHrtf02(std::istream &data, const char *filename)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
{ {
val[0] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[0] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
val[1] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[1] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
} }
} }
} }
for(auto &val : delays) for(auto &val : delays)
{ {
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
val[1] = GetLE_ALubyte(data); val[1] = readle<uint8_t>(data);
} }
if(!data || data.eof()) if(!data || data.eof())
{ {
@@ -947,10 +960,10 @@ std::unique_ptr<HrtfStore> LoadHrtf03(std::istream &data, const char *filename)
constexpr ubyte ChanType_LeftOnly{0}; constexpr ubyte ChanType_LeftOnly{0};
constexpr ubyte ChanType_LeftRight{1}; constexpr ubyte ChanType_LeftRight{1};
uint rate{GetLE_ALuint(data)}; uint rate{readle<uint32_t>(data)};
ubyte channelType{GetLE_ALubyte(data)}; ubyte channelType{readle<uint8_t>(data)};
ushort irSize{GetLE_ALubyte(data)}; ushort irSize{readle<uint8_t>(data)};
ubyte fdCount{GetLE_ALubyte(data)}; ubyte fdCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -979,8 +992,8 @@ std::unique_ptr<HrtfStore> LoadHrtf03(std::istream &data, const char *filename)
auto elevs = al::vector<HrtfStore::Elevation>{}; auto elevs = al::vector<HrtfStore::Elevation>{};
for(size_t f{0};f < fdCount;f++) for(size_t f{0};f < fdCount;f++)
{ {
const ushort distance{GetLE_ALushort(data)}; const ushort distance{readle<uint16_t>(data)};
const ubyte evCount{GetLE_ALubyte(data)}; const ubyte evCount{readle<uint8_t>(data)};
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -1012,7 +1025,7 @@ std::unique_ptr<HrtfStore> LoadHrtf03(std::istream &data, const char *filename)
const size_t ebase{elevs.size()}; const size_t ebase{elevs.size()};
elevs.resize(ebase + evCount); elevs.resize(ebase + evCount);
for(auto &elev : al::span<HrtfStore::Elevation>(elevs.data()+ebase, evCount)) for(auto &elev : al::span<HrtfStore::Elevation>(elevs.data()+ebase, evCount))
elev.azCount = GetLE_ALubyte(data); elev.azCount = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -1047,10 +1060,10 @@ std::unique_ptr<HrtfStore> LoadHrtf03(std::istream &data, const char *filename)
for(auto &hrir : coeffs) for(auto &hrir : coeffs)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
val[0] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[0] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
} }
for(auto &val : delays) for(auto &val : delays)
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
if(!data || data.eof()) if(!data || data.eof())
{ {
ERR("Failed reading %s\n", filename); ERR("Failed reading %s\n", filename);
@@ -1075,14 +1088,14 @@ std::unique_ptr<HrtfStore> LoadHrtf03(std::istream &data, const char *filename)
{ {
for(auto &val : al::span<float2>{hrir.data(), irSize}) for(auto &val : al::span<float2>{hrir.data(), irSize})
{ {
val[0] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[0] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
val[1] = static_cast<float>(GetLE_ALint24(data)) / 8388608.0f; val[1] = static_cast<float>(readle<int,24>(data)) / 8388608.0f;
} }
} }
for(auto &val : delays) for(auto &val : delays)
{ {
val[0] = GetLE_ALubyte(data); val[0] = readle<uint8_t>(data);
val[1] = GetLE_ALubyte(data); val[1] = readle<uint8_t>(data);
} }
if(!data || data.eof()) if(!data || data.eof())
{ {