Mercurial > hg > beaglert
comparison projects/heavy/hello-world/SignalPhasor.h @ 160:5bcf04234f80 heavy-updated
- added -std=c99 to Makefile for user-supplied C files (required for heavy files)
- changed heavy core render.cpp file to use latest API and removed all redundant functions (e.g. foleyDesigner/touchkey stuff)
- use build_pd.sh to compile and run pd files (-h for usage instructions)
author | chnrx <chris.heinrichs@gmail.com> |
---|---|
date | Thu, 05 Nov 2015 18:58:26 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
159:1e7db6610600 | 160:5bcf04234f80 |
---|---|
1 /** | |
2 * Copyright (c) 2014, 2015, Enzien Audio Ltd. | |
3 * | |
4 * Permission to use, copy, modify, and/or distribute this software for any | |
5 * purpose with or without fee is hereby granted, provided that the above | |
6 * copyright notice and this permission notice appear in all copies. | |
7 * | |
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
14 * PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #ifndef _HEAVY_SIGNAL_PHASOR_H_ | |
18 #define _HEAVY_SIGNAL_PHASOR_H_ | |
19 | |
20 #include "HvBase.h" | |
21 | |
22 typedef struct SignalPhasor { | |
23 #if HV_SIMD_AVX | |
24 __m256 phase; // current phase | |
25 __m256 inc; // phase increment | |
26 #elif HV_SIMD_SSE | |
27 __m128i phase; | |
28 __m128i inc; | |
29 #elif HV_SIMD_NEON | |
30 uint32x4_t phase; | |
31 int32x4_t inc; | |
32 #else // HV_SIMD_NONE | |
33 hv_uint32_t phase; | |
34 hv_int32_t inc; | |
35 #endif | |
36 union { | |
37 float f2sc; // float to step conversion (used for __phasor~f) | |
38 hv_int32_t s; // step value (used for __phasor_k~f) | |
39 } step; | |
40 } SignalPhasor; | |
41 | |
42 hv_size_t sPhasor_init(SignalPhasor *o, double samplerate); | |
43 | |
44 hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate); | |
45 | |
46 void sPhasor_k_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m); | |
47 | |
48 void sPhasor_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m); | |
49 | |
50 static inline void __hv_phasor_f(SignalPhasor *o, hv_bInf_t bIn, hv_bOutf_t bOut) { | |
51 #if HV_SIMD_AVX | |
52 __m256 p = _mm256_mul_ps(bIn, _mm256_set1_ps(o->step.f2sc)); // a b c d e f g h | |
53 | |
54 __m256 z = _mm256_setzero_ps(); | |
55 | |
56 // http://stackoverflow.com/questions/11906814/how-to-rotate-an-sse-avx-vector | |
57 __m256 a = _mm256_permute_ps(p, _MM_SHUFFLE(2,1,0,3)); // d a b c h e f g | |
58 __m256 b = _mm256_permute2f128_ps(a, a, 0x01); // h e f g d a b c | |
59 __m256 c = _mm256_blend_ps(a, b, 0x10); // d a b c d e f g | |
60 __m256 d = _mm256_blend_ps(c, z, 0x01); // 0 a b c d e f g | |
61 __m256 e = _mm256_add_ps(p, d); // a (a+b) (b+c) (c+d) (d+e) (e+f) (f+g) (g+h) | |
62 | |
63 __m256 f = _mm256_permute_ps(e, _MM_SHUFFLE(1,0,3,2)); // (b+c) (c+d) a (a+b) (f+g) (g+h) (d+e) (e+f) | |
64 __m256 g = _mm256_permute2f128_ps(f, f, 0x01); // (f+g) (g+h) (d+e) (e+f) (b+c) (c+d) a (a+b) | |
65 __m256 h = _mm256_blend_ps(f, g, 0x33); // (b+c) (c+d) a (a+b) (b+c) (c+d) (d+e) (e+f) | |
66 __m256 i = _mm256_blend_ps(h, z, 0x03); // 0 0 a (a+b) (b+c) (c+d) (d+e) (e+f) | |
67 __m256 j = _mm256_add_ps(e, i); // a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) (c+d+e+f) (d+e+f+g) (e+f+g+h) | |
68 | |
69 __m256 k = _mm256_permute2f128_ps(j, z, 0x02); // 0 0 0 0 a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) | |
70 __m256 m = _mm256_add_ps(j, k); // a (a+b) (a+b+c) (a+b+c+d) (a+b+c+d+e) (a+b+c+d+e+f) (a+b+c+d+e+f+g) (a+b+c+d+e+f+g+h) | |
71 | |
72 __m256 n = _mm256_or_ps(_mm256_andnot_ps( | |
73 _mm256_set1_ps(-INFINITY), | |
74 _mm256_add_ps(o->phase, m)), | |
75 _mm256_set1_ps(1.0f)); | |
76 | |
77 *bOut = _mm256_sub_ps(n, _mm256_set1_ps(1.0f)); | |
78 | |
79 __m256 x = _mm256_permute_ps(n, _MM_SHUFFLE(3,3,3,3)); | |
80 o->phase = _mm256_permute2f128_ps(x, x, 0x11); | |
81 #elif HV_SIMD_SSE | |
82 __m128i p = _mm_cvtps_epi32(_mm_mul_ps(bIn, _mm_set1_ps(o->step.f2sc))); // convert frequency to step | |
83 p = _mm_add_epi32(p, _mm_slli_si128(p, 4)); // add incremental steps to phase (prefix sum) | |
84 p = _mm_add_epi32(p, _mm_slli_si128(p, 8)); // http://stackoverflow.com/questions/10587598/simd-prefix-sum-on-intel-cpu?rq=1 | |
85 p = _mm_add_epi32(o->phase, p); | |
86 *bOut = _mm_sub_ps(_mm_castsi128_ps( | |
87 _mm_or_si128(_mm_srli_epi32(p, 9), | |
88 (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})), | |
89 _mm_set1_ps(1.0f)); | |
90 o->phase = _mm_shuffle_epi32(p, _MM_SHUFFLE(3,3,3,3)); | |
91 #elif HV_SIMD_NEON | |
92 int32x4_t p = vcvtq_s32_f32(vmulq_n_f32(bIn, o->step.f2sc)); | |
93 p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 3)); // http://stackoverflow.com/questions/11259596/arm-neon-intrinsics-rotation | |
94 p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 2)); | |
95 uint32x4_t pp = vaddq_u32(o->phase, vreinterpretq_u32_s32(p)); | |
96 *bOut = vsubq_f32(vreinterpretq_f32_u32(vorrq_u32(vshrq_n_u32(pp, 9), vdupq_n_u32(0x3F800000))), vdupq_n_f32(1.0f)); | |
97 o->phase = vdupq_n_u32(pp[3]); | |
98 #else // HV_SIMD_NONE | |
99 const hv_uint32_t p = (o->phase >> 9) | 0x3F800000; | |
100 *bOut = *((float *) (&p)) - 1.0f; | |
101 o->phase += ((int) (bIn * o->step.f2sc)); | |
102 #endif | |
103 } | |
104 | |
105 static inline void __hv_phasor_k_f(SignalPhasor *o, hv_bOutf_t bOut) { | |
106 #if HV_SIMD_AVX | |
107 *bOut = _mm256_sub_ps(o->phase, _mm256_set1_ps(1.0f)); | |
108 o->phase = _mm256_or_ps(_mm256_andnot_ps( | |
109 _mm256_set1_ps(-INFINITY), | |
110 _mm256_add_ps(o->phase, o->inc)), | |
111 _mm256_set1_ps(1.0f)); | |
112 #elif HV_SIMD_SSE | |
113 *bOut = _mm_sub_ps(_mm_castsi128_ps( | |
114 _mm_or_si128(_mm_srli_epi32(o->phase, 9), | |
115 (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})), | |
116 _mm_set1_ps(1.0f)); | |
117 o->phase = _mm_add_epi32(o->phase, o->inc); | |
118 #elif HV_SIMD_NEON | |
119 *bOut = vsubq_f32(vreinterpretq_f32_u32( | |
120 vorrq_u32(vshrq_n_u32(o->phase, 9), | |
121 vdupq_n_u32(0x3F800000))), | |
122 vdupq_n_f32(1.0f)); | |
123 o->phase = vaddq_u32(o->phase, vreinterpretq_u32_s32(o->inc)); | |
124 #else // HV_SIMD_NONE | |
125 const hv_uint32_t p = (o->phase >> 9) | 0x3F800000; | |
126 *bOut = *((float *) (&p)) - 1.0f; | |
127 o->phase += o->inc; | |
128 #endif | |
129 } | |
130 | |
131 #endif // _HEAVY_SIGNAL_PHASOR_H_ |