MicroDexed is a compatible 6-operator-FM-synth based on the Teensy(-3.6/-4.0) Microcontroller. https://www.parasitstudio.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
9.1KB

  1. /*
  2. * Copyright 2012 Google Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <math.h>
  17. #include <cstdlib>
  18. #ifdef HAVE_NEON
  19. #include <cpu-features.h>
  20. #endif
  21. #include "synth.h"
  22. #include "sin.h"
  23. #include "fm_op_kernel.h"
  24. #include "config.h"
  25. #ifdef HAVE_NEON
  26. static bool hasNeon() {
  27. return true;
  28. return (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
  29. }
  30. extern "C"
  31. void neon_fm_kernel(const int *in, const int *busin, int *out, int count,
  32. int32_t phase0, int32_t freq, int32_t gain1, int32_t dgain);
  33. const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0};
  34. #else
  35. static bool hasNeon() {
  36. return false;
  37. }
  38. #endif
  39. void FmOpKernel::compute(int32_t *output, const int32_t *input,
  40. int32_t phase0, int32_t freq,
  41. int32_t gain1, int32_t gain2, bool add) {
  42. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  43. int32_t gain = gain1;
  44. int32_t phase = phase0;
  45. if (hasNeon()) {
  46. #ifdef HAVE_NEON
  47. neon_fm_kernel(input, add ? output : zeros, output, _N_,
  48. phase0, freq, gain, dgain);
  49. #endif
  50. } else {
  51. if (add) {
  52. for (int i = 0; i < _N_; i++) {
  53. gain += dgain;
  54. int32_t y = Sin::lookup(phase + input[i]);
  55. int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24;
  56. output[i] += y1;
  57. phase += freq;
  58. }
  59. } else {
  60. for (int i = 0; i < _N_; i++) {
  61. gain += dgain;
  62. int32_t y = Sin::lookup(phase + input[i]);
  63. int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24;
  64. output[i] = y1;
  65. phase += freq;
  66. }
  67. }
  68. }
  69. }
  70. void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
  71. int32_t gain1, int32_t gain2, bool add) {
  72. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  73. int32_t gain = gain1;
  74. int32_t phase = phase0;
  75. if (hasNeon()) {
  76. #ifdef HAVE_NEON
  77. neon_fm_kernel(zeros, add ? output : zeros, output, _N_,
  78. phase0, freq, gain, dgain);
  79. #endif
  80. } else {
  81. if (add) {
  82. for (int i = 0; i < _N_; i++) {
  83. gain += dgain;
  84. int32_t y = Sin::lookup(phase);
  85. int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24;
  86. output[i] += y1;
  87. phase += freq;
  88. }
  89. } else {
  90. for (int i = 0; i < _N_; i++) {
  91. gain += dgain;
  92. int32_t y = Sin::lookup(phase);
  93. int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24;
  94. output[i] = y1;
  95. phase += freq;
  96. }
  97. }
  98. }
  99. }
  100. #define noDOUBLE_ACCURACY
  101. #define HIGH_ACCURACY
  102. void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq,
  103. int32_t gain1, int32_t gain2,
  104. int32_t *fb_buf, int fb_shift, bool add) {
  105. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  106. int32_t gain = gain1;
  107. int32_t phase = phase0;
  108. int32_t y0 = fb_buf[0];
  109. int32_t y = fb_buf[1];
  110. if (add) {
  111. for (int i = 0; i < _N_; i++) {
  112. gain += dgain;
  113. int32_t scaled_fb = (y0 + y) >> (fb_shift + 1);
  114. y0 = y;
  115. y = Sin::lookup(phase + scaled_fb);
  116. y = ((int64_t)y * (int64_t)gain) >> 24;
  117. output[i] += y;
  118. phase += freq;
  119. }
  120. } else {
  121. for (int i = 0; i < _N_; i++) {
  122. gain += dgain;
  123. int32_t scaled_fb = (y0 + y) >> (fb_shift + 1);
  124. y0 = y;
  125. y = Sin::lookup(phase + scaled_fb);
  126. y = ((int64_t)y * (int64_t)gain) >> 24;
  127. output[i] = y;
  128. phase += freq;
  129. }
  130. }
  131. fb_buf[0] = y0;
  132. fb_buf[1] = y;
  133. }
  134. ////////////////////////////////////////////////////////////////////////////////////
  135. ////////////////////////////////////////////////////////////////////////////////////
  136. ////////////////////////////////////////////////////////////////////////////////////
  137. ////////////////////////////////////////////////////////////////////////////////////
  138. // Experimental sine wave generators below
  139. #if 0
  140. // Results: accuracy 64.3 mean, 170 worst case
  141. // high accuracy: 5.0 mean, 49 worst case
  142. void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
  143. int32_t gain1, int32_t gain2, bool add) {
  144. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  145. int32_t gain = gain1;
  146. int32_t phase = phase0;
  147. #ifdef HIGH_ACCURACY
  148. int32_t u = Sin::compute10(phase << 6);
  149. u = ((int64_t)u * gain) >> 30;
  150. int32_t v = Sin::compute10((phase << 6) + (1 << 28)); // quarter cycle
  151. v = ((int64_t)v * gain) >> 30;
  152. int32_t s = Sin::compute10(freq << 6);
  153. int32_t c = Sin::compute10((freq << 6) + (1 << 28));
  154. #else
  155. int32_t u = Sin::compute(phase);
  156. u = ((int64_t)u * gain) >> 24;
  157. int32_t v = Sin::compute(phase + (1 << 22)); // quarter cycle
  158. v = ((int64_t)v * gain) >> 24;
  159. int32_t s = Sin::compute(freq) << 6;
  160. int32_t c = Sin::compute(freq + (1 << 22)) << 6;
  161. #endif
  162. for (int i = 0; i < _N_; i++) {
  163. output[i] = u;
  164. int32_t t = ((int64_t)v * (int64_t)c - (int64_t)u * (int64_t)s) >> 30;
  165. u = ((int64_t)u * (int64_t)c + (int64_t)v * (int64_t)s) >> 30;
  166. v = t;
  167. }
  168. }
  169. #endif
  170. #if 0
  171. // Results: accuracy 392.3 mean, 15190 worst case (near freq = 0.5)
  172. // for freq < 0.25, 275.2 mean, 716 worst
  173. // high accuracy: 57.4 mean, 7559 worst
  174. // freq < 0.25: 17.9 mean, 78 worst
  175. void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
  176. int32_t gain1, int32_t gain2, bool add) {
  177. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  178. int32_t gain = gain1;
  179. int32_t phase = phase0;
  180. #ifdef HIGH_ACCURACY
  181. int32_t u = floor(gain * sin(phase * (M_PI / (1 << 23))) + 0.5);
  182. int32_t v = floor(gain * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5);
  183. int32_t a = floor((1 << 25) * sin(freq * (M_PI / (1 << 24))) + 0.5);
  184. #else
  185. int32_t u = Sin::compute(phase);
  186. u = ((int64_t)u * gain) >> 24;
  187. int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1));
  188. v = ((int64_t)v * gain) >> 24;
  189. int32_t a = Sin::compute(freq >> 1) << 1;
  190. #endif
  191. for (int i = 0; i < _N_; i++) {
  192. output[i] = u;
  193. v -= ((int64_t)a * (int64_t)u) >> 24;
  194. u += ((int64_t)a * (int64_t)v) >> 24;
  195. }
  196. }
  197. #endif
  198. #if 0
  199. // Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5)
  200. // with FRAC_NUM accuracy initialization: mean 1.55, worst 58 (near freq = 0)
  201. // with high accuracy: mean 4.2, worst 292 (near freq = 0.5)
  202. void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
  203. int32_t gain1, int32_t gain2, bool add) {
  204. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  205. int32_t gain = gain1;
  206. int32_t phase = phase0;
  207. #ifdef DOUBLE_ACCURACY
  208. int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5);
  209. FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24)));
  210. int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) *
  211. (M_PI / (1 << 23))) + 0.5);
  212. int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5);
  213. #else
  214. #ifdef HIGH_ACCURACY
  215. int32_t u = Sin::compute10(phase << 6);
  216. int32_t v = Sin::compute10((phase << 6) + (1 << 28) - (freq << 5));
  217. int32_t a = Sin::compute10(freq << 5);
  218. v = ((int64_t)v * (int64_t)a) >> 29;
  219. int32_t aa = ((int64_t)a * (int64_t)a) >> 29;
  220. #else
  221. int32_t u = Sin::compute(phase) << 6;
  222. int32_t v = Sin::compute(phase + (1 << 22) - (freq >> 1));
  223. int32_t a = Sin::compute(freq >> 1);
  224. v = ((int64_t)v * (int64_t)a) >> 17;
  225. int32_t aa = ((int64_t)a * (int64_t)a) >> 17;
  226. #endif
  227. #endif
  228. if (aa < 0) aa = (1 << 31) - 1;
  229. for (int i = 0; i < _N_; i++) {
  230. gain += dgain;
  231. output[i] = ((int64_t)u * (int64_t)gain) >> 30;
  232. v -= ((int64_t)aa * (int64_t)u) >> 29;
  233. u += v;
  234. }
  235. }
  236. #endif
  237. #if 0
  238. // Results:: accuracy 112.3 mean, 4262 worst (near freq = 0.5)
  239. // high accuracy 2.9 mean, 143 worst
  240. void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
  241. int32_t gain1, int32_t gain2, bool add) {
  242. int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N;
  243. int32_t gain = gain1;
  244. int32_t phase = phase0;
  245. #ifdef HIGH_ACCURACY
  246. int32_t u = Sin::compute10(phase << 6);
  247. int32_t lastu = Sin::compute10((phase - freq) << 6);
  248. int32_t a = Sin::compute10((freq << 6) + (1 << 28)) << 1;
  249. #else
  250. int32_t u = Sin::compute(phase) << 6;
  251. int32_t lastu = Sin::compute(phase - freq) << 6;
  252. int32_t a = Sin::compute(freq + (1 << 22)) << 7;
  253. #endif
  254. if (a < 0 && freq < 256) a = (1 << 31) - 1;
  255. if (a > 0 && freq > 0x7fff00) a = -(1 << 31);
  256. for (int i = 0; i < _N_; i++) {
  257. gain += dgain;
  258. output[i] = ((int64_t)u * (int64_t)gain) >> 30;
  259. //output[i] = u;
  260. int32_t newu = (((int64_t)u * (int64_t)a) >> 30) - lastu;
  261. lastu = u;
  262. u = newu;
  263. }
  264. }
  265. #endif