diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b83cf6c..7f1c5de0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,26 @@ jobs: - name: Run tox run: tox + test-arm: + runs-on: ubuntu-22.04-arm + steps: + - uses: actions/checkout@v3 + with: + lfs: true + submodules: true + - name: Initialize lfs + run: git lfs pull + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + pip install -U tox tox-gh-actions poetry + - name: Run tox + run: tox + build: runs-on: ubuntu-20.04 steps: diff --git a/hvcc/generators/ir2c/static/HvSignalPhasor.c b/hvcc/generators/ir2c/static/HvSignalPhasor.c index b763b95a..26e13d9d 100644 --- a/hvcc/generators/ir2c/static/HvSignalPhasor.c +++ b/hvcc/generators/ir2c/static/HvSignalPhasor.c @@ -60,8 +60,8 @@ static void sPhasor_k_updatePhase(SignalPhasor *o, hv_uint32_t p) { static void sPhasor_k_updateFrequency(SignalPhasor *o, float f, double r) { #if HV_SIMD_AVX o->step.f2sc = (float) (f/r); - o->inc = _mm256_set1_ps((float) (8.0f*f/r)); - sPhasor_k_updatePhase(o, o->phase[0]); + o->inc = _mm256_set1_epi32((int)(f/r * 8388608.0f)); // 2^23 scaling + sPhasor_k_updatePhase(o, _mm256_castsi256_ps(o->phase)); // Adjust if needed #elif HV_SIMD_SSE o->step.s = (hv_int32_t) (f*(HV_PHASOR_2_32/r)); o->inc = _mm_set1_epi32(4*o->step.s); diff --git a/hvcc/generators/ir2c/static/HvSignalPhasor.h b/hvcc/generators/ir2c/static/HvSignalPhasor.h index 08c64649..1f219426 100644 --- a/hvcc/generators/ir2c/static/HvSignalPhasor.h +++ b/hvcc/generators/ir2c/static/HvSignalPhasor.h @@ -25,8 +25,8 @@ extern "C" { typedef struct SignalPhasor { #if HV_SIMD_AVX - __m256 phase; // current phase - __m256 inc; // phase increment + __m256i phase; // current phase + __m256i inc; // phase increment #elif HV_SIMD_SSE __m128i phase; __m128i inc; @@ -108,11 +108,14 @@ static inline void __hv_phasor_f(SignalPhasor *o, hv_bInf_t bIn, hv_bOutf_t bOut static inline void __hv_phasor_k_f(SignalPhasor *o, hv_bOutf_t bOut) { #if HV_SIMD_AVX - *bOut = _mm256_sub_ps(o->phase, _mm256_set1_ps(1.0f)); - o->phase = _mm256_or_ps(_mm256_andnot_ps( - _mm256_set1_ps(-INFINITY), - _mm256_add_ps(o->phase, o->inc)), - _mm256_set1_ps(1.0f)); + // Output current phase as float in [0,1) + *bOut = _mm256_sub_ps(_mm256_castsi256_ps( + _mm256_or_si256(_mm256_srli_epi32(o->phase, 9), + _mm256_set1_epi32(0x3F800000))), + _mm256_set1_ps(1.0f)); + + // Update phase as integer + o->phase = _mm256_add_epi32(o->phase, o->inc); #elif HV_SIMD_SSE *bOut = _mm_sub_ps(_mm_castsi128_ps( _mm_or_si128(_mm_srli_epi32(o->phase, 9), diff --git a/hvcc/generators/ir2c/static/HvUtils.h b/hvcc/generators/ir2c/static/HvUtils.h index 2186f547..003f365d 100644 --- a/hvcc/generators/ir2c/static/HvUtils.h +++ b/hvcc/generators/ir2c/static/HvUtils.h @@ -55,7 +55,7 @@ #if !(HV_SIMD_NONE || HV_SIMD_NEON || HV_SIMD_SSE || HV_SIMD_AVX) #define HV_SIMD_NEON __ARM_NEON__ #define HV_SIMD_SSE (__SSE__ && __SSE2__ && __SSE3__ && __SSSE3__ && __SSE4_1__) - #define HV_SIMD_AVX (__AVX__ && HV_SIMD_SSE) + #define HV_SIMD_AVX (__AVX2__ && HV_SIMD_SSE) #endif #ifndef HV_SIMD_FMA #define HV_SIMD_FMA __FMA__ diff --git a/tests/framework/base_signal.py b/tests/framework/base_signal.py index 70c767c3..543cec64 100644 --- a/tests/framework/base_signal.py +++ b/tests/framework/base_signal.py @@ -48,7 +48,7 @@ def compile_and_run( str(block_size or 480), str(num_iterations or 100)]) - return wav_path + return exe_path, wav_path def _compare_wave_output(self, out_dir, c_sources, golden_path, flag=None): # http://stackoverflow.com/questions/10580676/comparing-two-numpy-arrays-for-equality-element-wise diff --git a/tests/framework/base_test.py b/tests/framework/base_test.py index 207393fb..facbbf09 100644 --- a/tests/framework/base_test.py +++ b/tests/framework/base_test.py @@ -112,6 +112,9 @@ def _compile_and_run( source_files=source_files, out_path=exe_path)) + # run the clean command + subprocess.check_output(["make", "-C", os.path.dirname(makefile_path), "clean"]) + # run the compile command subprocess.check_output(["make", "-C", os.path.dirname(makefile_path), "-j"]) diff --git a/tests/framework/template/Makefile b/tests/framework/template/Makefile index afe46e77..2918c9d7 100644 --- a/tests/framework/template/Makefile +++ b/tests/framework/template/Makefile @@ -1,6 +1,6 @@ CC=clang CXX=clang++ -COMMONFLAGS=-Werror -Wno-unused-function -Wno-\#warnings {{" ".join(simd_flags)}} +COMMONFLAGS=-Werror -Wno-unused-function -gdwarf-4 -Wno-\#warnings {{" ".join(simd_flags)}} CFLAGS=-std=c11 $(COMMONFLAGS) CXXFLAGS=-std=c++11 -fno-exceptions -fno-rtti $(COMMONFLAGS) diff --git a/tests/src/test_control.c b/tests/src/test_control.c index 1872c379..32c4f86a 100644 --- a/tests/src/test_control.c +++ b/tests/src/test_control.c @@ -33,7 +33,7 @@ int main(int argc, const char *argv[]) { HeavyContextInterface *context = hv_heavy_new(48000.0); hv_setPrintHook(context, &printHook); - float *outBuffers = (float *) malloc(numOutputChannels * BLOCK_SIZE * sizeof(float)); + float *outBuffers = (float *) hv_malloc(numOutputChannels * BLOCK_SIZE * sizeof(float)); for (int i = 0; i < numIterations; ++i) { hv_processInline(context, NULL, outBuffers, BLOCK_SIZE); diff --git a/tests/src/test_midi.cpp b/tests/src/test_midi.cpp index 8f8269e1..dc8b0f14 100644 --- a/tests/src/test_midi.cpp +++ b/tests/src/test_midi.cpp @@ -79,7 +79,7 @@ int main(int argc, const char *argv[]) { MidiEvent* mev; - float *outBuffers = (float *) malloc(numOutputChannels * BLOCK_SIZE * sizeof(float)); + float *outBuffers = (float *) hv_malloc(numOutputChannels * BLOCK_SIZE * sizeof(float)); for (int i = 0; i < numIterations; ++i) { for (int event=0; event < midifile[0].size(); event++) { diff --git a/tests/src/test_signal.c b/tests/src/test_signal.c index bd28d6e4..c256a809 100644 --- a/tests/src/test_signal.c +++ b/tests/src/test_signal.c @@ -20,6 +20,15 @@ #include "tinywav.h" int main(int argc, const char *argv[]) { + #if HV_SIMD_AVX + printf("AVX!\n"); + #elif HV_SIMD_SSE + printf("SSE!\n"); + #elif HV_SIMD_NEON + printf("NEON!\n"); + #else // HV_SIMD_NONE + printf("NONE!\n"); + #endif if (argc < 5) return -1; const char *outputPath = argv[1]; const double sampleRate = atof(argv[2]); @@ -40,7 +49,7 @@ int main(int argc, const char *argv[]) { (int32_t) hv_getSampleRate(context), TW_FLOAT32, TW_INLINE, outputPath); - float *outBuffers = (float *) malloc( + float *outBuffers = (float *) hv_malloc( hv_getNumOutputChannels(context) * blockSize * sizeof(float)); for (int i = 0; i < numIterations; ++i) { diff --git a/tests/test_signal.py b/tests/test_signal.py index 75bd33be..555aec54 100644 --- a/tests/test_signal.py +++ b/tests/test_signal.py @@ -30,6 +30,9 @@ def test_line(self): def test_phasor_control(self): self._test_signal_patch("test-phasor-control.pd") + def test_phasor_signal(self): + self._test_signal_patch("test-phasor-signal.pd") + def main(): parser = argparse.ArgumentParser(