aRts audio server
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.

gslwaveosc.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* GSL - Generic Sound Layer
  2. * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
  3. *
  4. * This library is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Library General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. */
  19. #include "gslwaveosc.h"
  20. #include "gslfilter.h"
  21. #include "gslsignal.h"
  22. #include "gslengine.h" /* for gsl_engine_sample_freq() */
  23. #include <string.h>
  24. #define FRAC_SHIFT (16)
  25. #define FRAC_MASK ((1 << FRAC_SHIFT) - 1)
  26. #define SIGNAL_LEVEL_INVAL (-2.0) /* trigger level-changed checks */
  27. /* --- prototype --- */
  28. static void wave_osc_transform_filter (GslWaveOscData *wosc,
  29. gfloat play_freq);
  30. /* --- generated function variants --- */
  31. #define WOSC_MIX_VARIANT_INVAL (0xffffffff)
  32. #define WOSC_MIX_WITH_SYNC (1)
  33. #define WOSC_MIX_WITH_FREQ (2)
  34. #define WOSC_MIX_WITH_MOD (4)
  35. #define WOSC_MIX_WITH_EXP_FM (8)
  36. #define WOSC_MIX_VARIANT_NAME wosc_process_sfme
  37. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
  38. #include "gslwaveosc-aux.c"
  39. #define WOSC_MIX_VARIANT_NAME wosc_process_sfm_
  40. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0 )
  41. #include "gslwaveosc-aux.c"
  42. #if 0
  43. #define WOSC_MIX_VARIANT_NAME wosc_process_sf_e
  44. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM)
  45. #include "gslwaveosc-aux.c"
  46. #endif
  47. #define WOSC_MIX_VARIANT_NAME wosc_process_sf__
  48. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | 0 )
  49. #include "gslwaveosc-aux.c"
  50. #define WOSC_MIX_VARIANT_NAME wosc_process_s_me
  51. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
  52. #include "gslwaveosc-aux.c"
  53. #define WOSC_MIX_VARIANT_NAME wosc_process_s_m_
  54. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | 0 )
  55. #include "gslwaveosc-aux.c"
  56. #if 0
  57. #define WOSC_MIX_VARIANT_NAME wosc_process_s__e
  58. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | 0 | WOSC_MIX_WITH_EXP_FM)
  59. #include "gslwaveosc-aux.c"
  60. #endif
  61. #define WOSC_MIX_VARIANT_NAME wosc_process_s___
  62. #define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | 0 | 0 )
  63. #include "gslwaveosc-aux.c"
  64. #define WOSC_MIX_VARIANT_NAME wosc_process__fme
  65. #define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
  66. #include "gslwaveosc-aux.c"
  67. #define WOSC_MIX_VARIANT_NAME wosc_process__fm_
  68. #define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0 )
  69. #include "gslwaveosc-aux.c"
  70. #if 0
  71. #define WOSC_MIX_VARIANT_NAME wosc_process__f_e
  72. #define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM)
  73. #include "gslwaveosc-aux.c"
  74. #endif
  75. #define WOSC_MIX_VARIANT_NAME wosc_process__f__
  76. #define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | 0 | 0 )
  77. #include "gslwaveosc-aux.c"
  78. #define WOSC_MIX_VARIANT_NAME wosc_process___me
  79. #define WOSC_MIX_VARIANT (0 | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
  80. #include "gslwaveosc-aux.c"
  81. #define WOSC_MIX_VARIANT_NAME wosc_process___m_
  82. #define WOSC_MIX_VARIANT (0 | 0 | WOSC_MIX_WITH_MOD | 0 )
  83. #include "gslwaveosc-aux.c"
  84. #if 0
  85. #define WOSC_MIX_VARIANT_NAME wosc_process____e
  86. #define WOSC_MIX_VARIANT (0 | 0 | 0 | WOSC_MIX_WITH_EXP_FM)
  87. #include "gslwaveosc-aux.c"
  88. #endif
  89. #define WOSC_MIX_VARIANT_NAME wosc_process_____
  90. #define WOSC_MIX_VARIANT (0 | 0 | 0 | 0 )
  91. #include "gslwaveosc-aux.c"
  92. /* --- functions --- */
  93. gboolean
  94. gsl_wave_osc_process (GslWaveOscData *wosc,
  95. guint n_values,
  96. const gfloat *freq_in,
  97. const gfloat *mod_in,
  98. const gfloat *sync_in,
  99. gfloat *mono_out)
  100. {
  101. guint mode = 0;
  102. g_return_val_if_fail (wosc != NULL, FALSE);
  103. g_return_val_if_fail (n_values > 0, FALSE);
  104. g_return_val_if_fail (mono_out != NULL, FALSE);
  105. if_reject (!wosc->config.wchunk_from_freq)
  106. return FALSE;
  107. /* mode changes:
  108. * freq_in: if (freq_in) last_freq=inval else set_filter()
  109. * sync_in: last_sync=0
  110. * mod_in: if (mod_in) last_mod=0 else if (freq_in) last_freq=inval else transform_filter()
  111. * exp_mod: n/a
  112. */
  113. if (sync_in)
  114. mode |= WOSC_MIX_WITH_SYNC;
  115. if (freq_in)
  116. mode |= WOSC_MIX_WITH_FREQ;
  117. if (mod_in)
  118. mode |= WOSC_MIX_WITH_MOD;
  119. if (wosc->config.exponential_fm)
  120. mode |= WOSC_MIX_WITH_EXP_FM;
  121. if_reject (mode != wosc->last_mode)
  122. {
  123. guint mask = wosc->last_mode ^ mode;
  124. if (mask & WOSC_MIX_WITH_SYNC)
  125. wosc->last_sync_level = 0;
  126. if (mask & WOSC_MIX_WITH_FREQ)
  127. {
  128. if (freq_in)
  129. wosc->last_freq_level = SIGNAL_LEVEL_INVAL;
  130. else
  131. gsl_wave_osc_set_filter (wosc, wosc->config.cfreq, FALSE);
  132. }
  133. if (mask & WOSC_MIX_WITH_MOD)
  134. {
  135. if (mod_in)
  136. wosc->last_mod_level = 0;
  137. else if (freq_in)
  138. wosc->last_freq_level = SIGNAL_LEVEL_INVAL;
  139. else /* !mod_in && !freq_in */
  140. wave_osc_transform_filter (wosc, wosc->config.cfreq);
  141. }
  142. wosc->last_mode = mode;
  143. }
  144. switch (mode)
  145. {
  146. case 0 | 0 | 0 | 0:
  147. case 0 | 0 | 0 | WOSC_MIX_WITH_EXP_FM:
  148. wosc_process_____ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  149. break;
  150. case 0 | 0 | WOSC_MIX_WITH_MOD | 0:
  151. wosc_process___m_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  152. break;
  153. case 0 | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
  154. wosc_process___me (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  155. break;
  156. case 0 | WOSC_MIX_WITH_FREQ | 0 | 0:
  157. case 0 | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM:
  158. wosc_process__f__ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  159. break;
  160. case 0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0:
  161. wosc_process__fm_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  162. break;
  163. case 0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
  164. wosc_process__fme (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  165. break;
  166. case WOSC_MIX_WITH_SYNC | 0 | 0 | 0:
  167. case WOSC_MIX_WITH_SYNC | 0 | 0 | WOSC_MIX_WITH_EXP_FM:
  168. wosc_process_s___ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  169. break;
  170. case WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | 0:
  171. wosc_process_s_m_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  172. break;
  173. case WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
  174. wosc_process_s_me (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  175. break;
  176. case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | 0:
  177. case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM:
  178. wosc_process_sf__ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  179. break;
  180. case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0:
  181. wosc_process_sfm_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  182. break;
  183. case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
  184. wosc_process_sfme (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
  185. break;
  186. default:
  187. g_assert_not_reached ();
  188. }
  189. if (wosc->y[0] != 0.0 &&
  190. !(fabs (wosc->y[0]) > GSL_SIGNAL_EPSILON && fabs (wosc->y[0]) < GSL_SIGNAL_KAPPA))
  191. {
  192. guint i;
  193. /*g_printerr ("clearing filter state at:\n");*/
  194. for (i = 0; i < GSL_WAVE_OSC_FILTER_ORDER; i++)
  195. {
  196. /*g_printerr ("%u) %+.38f\n", i, wosc->y[i]);*/
  197. if (GSL_DOUBLE_IS_INF (wosc->y[0]) || fabs (wosc->y[0]) > GSL_SIGNAL_KAPPA)
  198. wosc->y[i] = GSL_DOUBLE_SIGN (wosc->y[0]) ? -1.0 : 1.0;
  199. else
  200. wosc->y[i] = 0.0;
  201. }
  202. }
  203. g_assert (!GSL_DOUBLE_IS_NANINF (wosc->y[0]));
  204. wosc->done = (wosc->block.is_silent && /* FIXME, let filter state run out? */
  205. ((wosc->block.play_dir < 0 && wosc->block.offset < 0) ||
  206. (wosc->block.play_dir > 0 && wosc->block.offset > wosc->wchunk->wave_length)));
  207. return TRUE;
  208. }
  209. void
  210. gsl_wave_osc_set_filter (GslWaveOscData *wosc,
  211. gfloat play_freq,
  212. gboolean clear_state)
  213. {
  214. gfloat zero_padding = 2;
  215. gfloat step;
  216. guint i, istep;
  217. g_return_if_fail (play_freq > 0);
  218. if_reject (!wosc->config.wchunk_from_freq)
  219. return;
  220. wosc->step_factor = zero_padding * wosc->wchunk->mix_freq;
  221. wosc->step_factor /= wosc->wchunk->osc_freq * wosc->mix_freq;
  222. step = wosc->step_factor * play_freq;
  223. istep = step * (FRAC_MASK + 1.) + 0.5;
  224. if (istep != wosc->istep)
  225. {
  226. gfloat nyquist_fact = GSL_PI * 2.0 / wosc->mix_freq, cutoff_freq = 18000, stop_freq = 24000;
  227. gfloat empiric_filter_stability_limit = 6.;
  228. gfloat filt_fact = CLAMP (1. / step,
  229. 1. / (empiric_filter_stability_limit * zero_padding),
  230. 1. / zero_padding /* spectrum half */);
  231. gfloat freq_c = cutoff_freq * nyquist_fact * filt_fact;
  232. gfloat freq_r = stop_freq * nyquist_fact * filt_fact;
  233. /* FIXME: this should store filter roots and poles, so modulation does lp->lp transform */
  234. wosc->istep = istep;
  235. gsl_filter_tscheb2_lp (GSL_WAVE_OSC_FILTER_ORDER, freq_c, freq_r / freq_c, 0.18, wosc->a, wosc->b);
  236. for (i = 0; i < GSL_WAVE_OSC_FILTER_ORDER + 1; i++)
  237. wosc->a[i] *= zero_padding; /* scale to compensate for zero-padding */
  238. for (i = 0; i < (GSL_WAVE_OSC_FILTER_ORDER + 1) / 2; i++) /* reverse bs */
  239. {
  240. gfloat t = wosc->b[GSL_WAVE_OSC_FILTER_ORDER - i];
  241. wosc->b[GSL_WAVE_OSC_FILTER_ORDER - i] = wosc->b[i];
  242. wosc->b[i] = t;
  243. }
  244. /*g_printerr ("filter: fc=%f fr=%f st=%f is=%u\n", freq_c/GSL_PI*2, freq_r/GSL_PI*2, step, wosc->istep);*/
  245. }
  246. if (clear_state)
  247. {
  248. /* clear filter state */
  249. memset (wosc->y, 0, sizeof (wosc->y));
  250. wosc->j = 0;
  251. wosc->cur_pos = 0; /* might want to initialize with istep? */
  252. }
  253. }
  254. static void
  255. wave_osc_transform_filter (GslWaveOscData *wosc,
  256. gfloat play_freq)
  257. {
  258. gfloat step;
  259. guint istep;
  260. step = wosc->step_factor * play_freq;
  261. istep = step * (FRAC_MASK + 1.) + 0.5;
  262. if (istep != wosc->istep)
  263. {
  264. wosc->istep = istep;
  265. /* transform filter poles and roots, normalize filter, update a[] and b[] */
  266. }
  267. }
  268. void
  269. gsl_wave_osc_retrigger (GslWaveOscData *wosc,
  270. gfloat base_freq)
  271. {
  272. g_return_if_fail (wosc != NULL);
  273. if_reject (!wosc->config.wchunk_from_freq)
  274. return;
  275. if (wosc->wchunk)
  276. gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
  277. wosc->wchunk = wosc->config.wchunk_from_freq (wosc->config.wchunk_data, base_freq);
  278. wosc->block.play_dir = wosc->config.play_dir;
  279. wosc->block.offset = wosc->config.start_offset;
  280. gsl_wave_chunk_use_block (wosc->wchunk, &wosc->block);
  281. wosc->x = wosc->block.start + wosc->config.channel;
  282. /*g_printerr ("wave lookup: want=%f got=%f length=%lu\n",
  283. base_freq, wosc->wchunk->osc_freq, wosc->wchunk->wave_length);*/
  284. wosc->last_freq_level = GSL_SIGNAL_FROM_FREQ (base_freq);
  285. wosc->last_mod_level = 0;
  286. gsl_wave_osc_set_filter (wosc, base_freq, TRUE);
  287. }
  288. void
  289. gsl_wave_osc_config (GslWaveOscData *wosc,
  290. GslWaveOscConfig *config)
  291. {
  292. g_return_if_fail (wosc != NULL);
  293. g_return_if_fail (config != NULL);
  294. if (wosc->config.wchunk_data != config->wchunk_data ||
  295. wosc->config.wchunk_from_freq != config->wchunk_from_freq ||
  296. wosc->config.channel != config->channel)
  297. {
  298. if (wosc->wchunk)
  299. gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
  300. wosc->wchunk = NULL;
  301. wosc->config = *config;
  302. gsl_wave_osc_retrigger (wosc, wosc->config.cfreq);
  303. }
  304. else
  305. {
  306. wosc->config.play_dir = config->play_dir;
  307. wosc->config.fm_strength = config->fm_strength;
  308. if (wosc->config.cfreq != config->cfreq ||
  309. wosc->config.start_offset != config->start_offset)
  310. {
  311. wosc->config.start_offset = config->start_offset;
  312. wosc->config.cfreq = config->cfreq;
  313. gsl_wave_osc_retrigger (wosc, wosc->config.cfreq);
  314. }
  315. }
  316. }
  317. void
  318. gsl_wave_osc_init (GslWaveOscData *wosc)
  319. {
  320. g_return_if_fail (wosc != NULL);
  321. g_assert (GSL_WAVE_OSC_FILTER_ORDER <= gsl_get_config ()->wave_chunk_padding);
  322. memset (wosc, 0, sizeof (GslWaveOscData));
  323. wosc->mix_freq = gsl_engine_sample_freq ();
  324. }
  325. void
  326. gsl_wave_osc_shutdown (GslWaveOscData *wosc)
  327. {
  328. g_return_if_fail (wosc != NULL);
  329. if (wosc->wchunk)
  330. gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
  331. memset (wosc, 0xaa, sizeof (GslWaveOscData));
  332. }