#pragma once #include #include namespace rack { namespace dsp { /** 24-bit integer, using int32_t for conversions. */ struct #ifdef __clang__ __attribute__((packed, aligned(1))) #else __attribute__((packed, aligned(1), gcc_struct)) #endif Int24 { int32_t i : 24; Int24() {} Int24(int32_t i) : i(i) {} operator int32_t() {return i;} }; static_assert(sizeof(Int24) == 3, "Int24 type must be 3 bytes"); /** Converts between normalized types. */ template To convert(From x) = delete; /** Trivial conversions */ template <> inline float convert(float x) {return x;} /** Integer to float */ template <> inline float convert(int8_t x) {return x / 128.f;} template <> inline float convert(int16_t x) {return x / 32768.f;} template <> inline float convert(Int24 x) {return x / 8388608.f;} template <> inline float convert(int32_t x) {return x / 2147483648.f;} template <> inline float convert(int64_t x) {return x / 9223372036854775808.f;} /** Float to integer */ template <> inline int8_t convert(float x) {return std::min(std::llround(x * 128.f), 127LL);} template <> inline int16_t convert(float x) {return std::min(std::llround(x * 32768.f), 32767LL);} template <> inline Int24 convert(float x) {return std::min(std::llround(x * 8388608.f), 8388607LL);} template <> inline int32_t convert(float x) {return std::min(std::llround(x * 2147483648.f), 2147483647LL);} template <> inline int64_t convert(float x) {return std::min(std::llround(x * 9223372036854775808.f), 9223372036854775807LL);} /** Buffer conversion */ template void convert(const From* in, To* out, size_t len) { for (size_t i = 0; i < len; i++) { out[i] = convert(in[i]); } } } // namespace dsp } // namespace rack