diff --git a/.github/workflows/win-msvc.yml b/.github/workflows/win-msvc.yml index 246c8ec..4e39390 100644 --- a/.github/workflows/win-msvc.yml +++ b/.github/workflows/win-msvc.yml @@ -18,7 +18,8 @@ jobs: fail-fast: false matrix: include: - - { icon: '🟪', arch: "x64", os: "windows-latest" } + - { icon: '🟪', arch: "win64", os: "windows-latest" } + - { icon: '🟫', arch: "win32", os: "windows-latest" } - { icon: '🟩', arch: "arm64", os: "windows-11-arm" } runs-on: ${{ matrix.os }} name: 🚧${{ matrix.icon }} msvc ${{ matrix.arch }} diff --git a/arm-wt-22k/lib_src/compute_tick_conv.c b/arm-wt-22k/lib_src/compute_tick_conv.c deleted file mode 100644 index 0a80d15..0000000 --- a/arm-wt-22k/lib_src/compute_tick_conv.c +++ /dev/null @@ -1,76 +0,0 @@ -#include // For uint64_t -#include // For USHRT_MAX -#ifdef _MSC_VER -#include // For _umul128 and _addcarry_u64 -#if defined(_M_ARM64) //!(defined(_M_AMD64) || defined(_M_X64)) -#pragma intrinsic(__umulh) - -uint64_t _umul128(uint64_t a, uint64_t b, uint64_t *high) { - *high = __umulh(a, b); - return a * b; -} - -uint8_t _addcarry_u64(uint64_t carry_in, uint64_t x, uint64_t y, uint64_t *sum) { - *sum = x + y + (carry_in !=0 ? 1 : 0); - return x > UINT32_MAX - y; -} -#endif -#endif - -#define MAX_TICK_CONV USHRT_MAX // Use USHRT_MAX for 16-bit unsigned max value - -// pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); - -uint16_t compute_tick_conv(uint32_t temp, uint32_t ppqn) -{ - // Guard against division by zero - if (ppqn == 0) { - return MAX_TICK_CONV; - } - - uint64_t temp64; - int overflow = 0; - -#ifdef _MSC_VER - // MSVC-specific overflow-safe multiplication - uint64_t high; - temp64 = _umul128(temp, 1024u, &high); - if (high != 0) { - overflow = 1; - } -#else - // GCC/Clang-specific overflow-safe multiplication - if (__builtin_mul_overflow(temp, 1024u, &temp64)) { - overflow = 1; - } -#endif - - if (!overflow) { - temp64 /= ppqn; - -#ifdef _MSC_VER - // MSVC-specific overflow-safe addition - uint8_t carry = _addcarry_u64(0, temp64, 500, &temp64); - if (carry) { - overflow = 1; - } -#else - // GCC/Clang-specific overflow-safe addition - if (__builtin_add_overflow(temp64, 500, &temp64)) { - overflow = 1; - } -#endif - } - - if (!overflow) { - temp64 /= 1000; - if (temp64 > MAX_TICK_CONV) { - overflow = 1; - } - } - - if (overflow) { - return MAX_TICK_CONV; - } - return (uint16_t) temp64; -} diff --git a/arm-wt-22k/lib_src/eas_smf.c b/arm-wt-22k/lib_src/eas_smf.c index 42a9271..d9a879d 100644 --- a/arm-wt-22k/lib_src/eas_smf.c +++ b/arm-wt-22k/lib_src/eas_smf.c @@ -29,6 +29,9 @@ *---------------------------------------------------------------------------- */ +#include // For uint64_t +#include // For USHRT_MAX + #define LOG_TAG "Sonivox" #include "log/log.h" @@ -47,8 +50,6 @@ #include "jet_data.h" #endif -#include "compute_tick_conv.c" - //3 dls: The timebase for this module is adequate to keep MIDI and //3 digital audio synchronized for only a few minutes. It should be //3 sufficient for most mobile applications. If better accuracy is @@ -882,22 +883,23 @@ static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData return result; temp = (temp << 8) | c; } - /* Replaced this horrible obfuscated code: + // note: temp is microseconds per quarter note. if SMF tempo is 120 quarters per minute, then: + // temp = 60'000'000 / 120 = 500'000 (SMF_DEFAULT_TIMEBASE) + // temp will be maximum 28 bits. See also SMF_ParseHeader() and SMF_UpdateTime() { - // pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); - uint64_t temp64; - if (__builtin_mul_overflow(temp, 1024u, &temp64) || - pSMFData->ppqn == 0 || - (temp64 /= pSMFData->ppqn, false) || - __builtin_add_overflow(temp64, 500, &temp64) || - (temp64 /= 1000, false) || - temp64 > 65535) { - pSMFData->tickConv = 65535; + uint64_t temp64 = temp * 1024; // will never overflow + if (pSMFData->ppqn > 0) { + // see https://en.wikipedia.org/wiki/MIDI_beat_clock#Pulses_per_quarter_note + temp64 /= pSMFData->ppqn; // ticks per quarter note, values typically between 24 and 960 + temp64 += 500; + temp64 /= 1000; + } + if (temp64 > USHRT_MAX) { + pSMFData->tickConv = 65535; // unlikely! } else { pSMFData->tickConv = (EAS_U16) temp64; } - }*/ - pSMFData->tickConv = compute_tick_conv(temp, pSMFData->ppqn); + } pSMFData->flags |= SMF_FLAGS_HAS_TEMPO; }