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.

13287 lines
457KB

  1. /* tie CLM module into Scheme, Ruby, or Forth */
  2. /* if the optimizer stops working inexplicably, look for any symbols used before this that
  3. * might shadow a generator name; one such case was (make-hook 'env...) in snd-env.c
  4. *
  5. * (env env) is accepted by the optimizer in error
  6. */
  7. #include "mus-config.h"
  8. #if USE_SND
  9. #include "snd.h"
  10. #endif
  11. #include <stddef.h>
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include <errno.h>
  15. #include <stdlib.h>
  16. #include <limits.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #ifndef _MSC_VER
  20. #include <unistd.h>
  21. #else
  22. #include <io.h>
  23. #pragma warning(disable: 4244)
  24. #endif
  25. #include "_sndlib.h"
  26. #include "xen.h"
  27. #include "clm.h"
  28. #include "sndlib2xen.h"
  29. #include "vct.h"
  30. #include "clm2xen.h"
  31. #include "clm-strings.h"
  32. #ifndef TWO_PI
  33. #define TWO_PI (2.0 * M_PI)
  34. #endif
  35. #ifndef PROC_FALSE
  36. #if HAVE_RUBY
  37. #define PROC_FALSE "false"
  38. #define PROC_TRUE "true"
  39. #else
  40. #define PROC_FALSE "#f"
  41. #define PROC_TRUE "#t"
  42. #endif
  43. #endif
  44. /* -------------------------------------------------------------------------------- */
  45. #if HAVE_SCHEME
  46. static bool mus_simple_out_any_to_file(mus_long_t samp, mus_float_t val, int chan, mus_any *IO)
  47. {
  48. rdout *gen = (rdout *)IO;
  49. if ((chan < gen->chans) &&
  50. (samp <= gen->data_end) &&
  51. (samp >= gen->data_start))
  52. {
  53. gen->obufs[chan][samp - gen->data_start] += val;
  54. if (samp > gen->out_end)
  55. gen->out_end = samp;
  56. return(true);
  57. }
  58. return(false);
  59. }
  60. #endif
  61. /* -------------------------------------------------------------------------------- */
  62. struct mus_xen {
  63. mus_any *gen;
  64. int nvcts;
  65. #if HAVE_SCHEME
  66. bool free_data;
  67. #endif
  68. Xen *vcts; /* one for each accessible mus_float_t array (wrapped up here in a vct) */
  69. struct mus_xen *next;
  70. };
  71. enum {MUS_DATA_WRAPPER, MUS_INPUT_FUNCTION, MUS_ANALYZE_FUNCTION, MUS_EDIT_FUNCTION, MUS_SYNTHESIZE_FUNCTION, MUS_SAVED_FUNCTION,
  72. MUS_SELF_WRAPPER, MUS_INPUT_DATA, MUS_MAX_VCTS}; /* order matters, stuff before self_wrapper is GC marked */
  73. static mus_xen *mx_free_lists[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  74. static mus_xen *mx_alloc(int vcts)
  75. {
  76. mus_xen *p;
  77. if (mx_free_lists[vcts])
  78. {
  79. p = mx_free_lists[vcts];
  80. mx_free_lists[vcts] = p->next;
  81. return(p);
  82. }
  83. p = (mus_xen *)malloc(sizeof(mus_xen));
  84. p->nvcts = vcts;
  85. if (vcts > 0)
  86. p->vcts = (Xen *)malloc(vcts * sizeof(Xen));
  87. else p->vcts = NULL;
  88. #if HAVE_SCHEME
  89. p->free_data = false;
  90. #endif
  91. return(p);
  92. }
  93. static void mx_free(mus_xen *p)
  94. {
  95. #if HAVE_SCHEME
  96. if (p->free_data)
  97. {
  98. s7_xf_attach(s7, (void *)(p->vcts[MUS_INPUT_DATA]));
  99. p->free_data = false;
  100. }
  101. #endif
  102. p->next = mx_free_lists[p->nvcts];
  103. mx_free_lists[p->nvcts] = p;
  104. }
  105. mus_any *mus_xen_gen(mus_xen *x) {return(x->gen);}
  106. #define mus_xen_to_mus_any(Gn) (((mus_xen *)Gn)->gen)
  107. #if (!HAVE_SCHEME)
  108. #define XEN_NULL 0
  109. #define Xen_real_to_C_double_if_bound(Xen_Arg, C_Val, Caller, ArgNum) \
  110. if (Xen_is_bound(Xen_Arg)) {if (Xen_is_number(Xen_Arg)) C_Val = Xen_real_to_C_double(Xen_Arg); else Xen_check_type(false, Xen_Arg, ArgNum, Caller, "a number");}
  111. #define Xen_to_C_double_or_error(Xen_Arg, C_Val, Caller, ArgNum) \
  112. do {C_Val = 0.0; if (Xen_is_number(Xen_Arg)) C_Val = Xen_real_to_C_double(Xen_Arg); else Xen_check_type(false, Xen_Arg, ArgNum, Caller, "a number");} while (0)
  113. #define Xen_real_to_C_double_with_caller(Xen_Arg, Caller) Xen_real_to_C_double(Xen_Arg)
  114. #define Xen_to_C_integer_or_error(Xen_Arg, C_Val, Caller, ArgNum) \
  115. do {if (Xen_is_integer(Xen_Arg)) C_Val = Xen_integer_to_C_int(Xen_Arg); else {C_Val = 0.0; Xen_check_type(false, Xen_Arg, ArgNum, Caller, "an integer");}} while (0)
  116. #if (HAVE_FORTH) || (HAVE_RUBY)
  117. #define Xen_object_ref_checked(Obj, Type) (Xen_c_object_is_type(Obj, Type) ? Xen_object_ref(Obj) : NULL)
  118. #else
  119. #define Xen_object_ref_checked(Obj, Type) NULL
  120. #endif
  121. #else
  122. #define Xen_real_to_C_double_if_bound(Xen_Arg, C_Val, Caller, ArgNum) if (Xen_is_bound(Xen_Arg)) C_Val = (double)s7_number_to_real_with_caller(s7, Xen_Arg, Caller)
  123. #define Xen_to_C_double_or_error(Xen_Arg, C_Val, Caller, ArgNum) C_Val = (double)s7_number_to_real_with_caller(s7, Xen_Arg, Caller)
  124. #define Xen_real_to_C_double_with_caller(Xen_Arg, Caller) s7_number_to_real_with_caller(s7, Xen_Arg, Caller)
  125. #define Xen_to_C_integer_or_error(Xen_Arg, C_Val, Caller, ArgNum) \
  126. do {if (s7_is_integer(Xen_Arg)) C_Val = s7_integer(Xen_Arg); else {C_Val = 0.0; Xen_check_type(false, Xen_Arg, ArgNum, Caller, "an integer");}} while (0)
  127. #define Xen_object_ref_checked(Obj, Type) s7_object_value_checked(Obj, Type)
  128. #define XEN_NULL NULL
  129. #endif
  130. static int local_error_type = MUS_NO_ERROR;
  131. static char *local_error_msg = NULL;
  132. static void local_mus_error(int type, char *msg)
  133. {
  134. local_error_type = type;
  135. if (local_error_msg) free(local_error_msg);
  136. local_error_msg = mus_strdup(msg);
  137. }
  138. static Xen clm_mus_error(int type, const char *msg, const char *caller)
  139. {
  140. /* mus_error returns an int, which is a bother in this context */
  141. mus_error(type, "%s: %s", caller, msg);
  142. return(Xen_false);
  143. }
  144. #define CLM_ERROR Xen_make_error_type("mus-error")
  145. static void clm_error(const char *caller, const char *msg, Xen val)
  146. {
  147. Xen_error(CLM_ERROR,
  148. Xen_list_4(C_string_to_Xen_string("~A: ~A ~A"),
  149. C_string_to_Xen_string(caller),
  150. C_string_to_Xen_string(msg),
  151. val));
  152. }
  153. /* ---------------- optional-key ---------------- */
  154. int mus_optkey_unscramble(const char *caller, int nkeys, Xen *keys, Xen *args, int *orig)
  155. {
  156. /* implement the &optional-key notion in CLM */
  157. /* "keys" holds the keywords the calling function accepts,
  158. * upon return, if a key was given in the arglist or its position had a value, the corresponding value is in its keys location
  159. * "nkeys is the size of "keys"
  160. * "args" contains the original arguments passed to the function in order
  161. * it should be of size nkeys * 2, and any trailing (unspecified) args should be Xen_undefined
  162. * "orig" should be of size nkeys, and will contain upon return the 1-based location of the original keyword value argument
  163. * (it is intended for error reports)
  164. */
  165. int arg_ctr = 0, key_start = 0, rtn_ctr = 0, nargs, nargs_end;
  166. bool keying = false, key_found = false;
  167. nargs = nkeys * 2;
  168. nargs_end = nargs - 1;
  169. while ((arg_ctr < nargs) &&
  170. (Xen_is_bound(args[arg_ctr])))
  171. {
  172. Xen key;
  173. key = args[arg_ctr];
  174. if (!(Xen_is_keyword(key)))
  175. {
  176. if (keying)
  177. clm_error(caller, "unmatched value within keyword section?", key);
  178. /* type checking on the actual values has to be the caller's problem */
  179. if (arg_ctr >= nkeys) /* we aren't handling a keyword arg, so the underlying args should only take nkeys args */
  180. clm_error(caller, "extra trailing args?", key);
  181. keys[arg_ctr] = key;
  182. orig[arg_ctr] = arg_ctr + 1;
  183. arg_ctr++;
  184. key_start = arg_ctr;
  185. rtn_ctr++;
  186. }
  187. else
  188. {
  189. int i;
  190. Xen val;
  191. val = args[arg_ctr + 1];
  192. if ((arg_ctr == nargs_end) ||
  193. (!(Xen_is_bound(val))))
  194. clm_error(caller, "keyword without value?", key);
  195. if (Xen_is_keyword(val))
  196. clm_error(caller, "two keywords in a row?", key);
  197. keying = true;
  198. key_found = false;
  199. for (i = key_start; i < nkeys; i++)
  200. {
  201. if (Xen_keyword_is_eq(keys[i], key))
  202. {
  203. keys[i] = val;
  204. arg_ctr += 2;
  205. orig[i] = arg_ctr;
  206. rtn_ctr++;
  207. key_found = true;
  208. break;
  209. }
  210. }
  211. if (!key_found)
  212. {
  213. /* either there's a redundant keyword pair or a keyword that 'caller' doesn't recognize */
  214. clm_error(caller, "redundant or invalid key found", key);
  215. /* normally (all local cases) the error returns */
  216. arg_ctr += 2;
  217. }
  218. }
  219. }
  220. return(rtn_ctr);
  221. }
  222. static mus_float_t optkey_float_error(Xen key, int n, const char *caller)
  223. {
  224. Xen_check_type(false, key, n, caller, "a number");
  225. return(0.0);
  226. }
  227. #define Xen_optkey_to_float(Original_key, Key, Caller, N, Def) \
  228. ((Xen_keyword_is_eq(Original_key, Key)) ? Def : ((Xen_is_number(Key)) ? Xen_real_to_C_double(Key) : optkey_float_error(Key, N, Caller)))
  229. mus_float_t mus_optkey_to_float(Xen key, const char *caller, int n, mus_float_t def)
  230. {
  231. if (Xen_is_number(key))
  232. return(Xen_real_to_C_double(key));
  233. if (!(Xen_is_keyword(key)))
  234. Xen_check_type(false, key, n, caller, "a number");
  235. return(def);
  236. }
  237. static int optkey_int_error(Xen key, int n, const char *caller)
  238. {
  239. Xen_check_type(false, key, n, caller, "an integer");
  240. return(0);
  241. }
  242. #define Xen_optkey_to_int(Original_key, Key, Caller, N, Def) \
  243. ((Xen_keyword_is_eq(Original_key, Key)) ? Def : ((Xen_is_integer(Key)) ? Xen_integer_to_C_int(Key) : optkey_int_error(Key, N, Caller)))
  244. int mus_optkey_to_int(Xen key, const char *caller, int n, int def)
  245. {
  246. if (Xen_is_integer(key))
  247. return(Xen_integer_to_C_int(key));
  248. if (!(Xen_is_keyword(key)))
  249. Xen_check_type(false, key, n, caller, "an integer");
  250. return(def);
  251. }
  252. bool mus_optkey_to_bool(Xen key, const char *caller, int n, bool def)
  253. {
  254. if (Xen_is_boolean(key))
  255. return(Xen_boolean_to_C_bool(key));
  256. if (!(Xen_is_keyword(key)))
  257. Xen_check_type(false, key, n, caller, "#f or #t");
  258. return(def);
  259. }
  260. static mus_long_t optkey_llong_error(Xen key, int n, const char *caller)
  261. {
  262. Xen_check_type(false, key, n, caller, "an integer");
  263. return(0);
  264. }
  265. #define Xen_optkey_to_mus_long_t(Original_key, Key, Caller, N, Def) \
  266. ((Xen_keyword_is_eq(Original_key, Key)) ? Def : ((Xen_is_integer(Key)) ? Xen_llong_to_C_llong(Key) : optkey_llong_error(Key, N, Caller)))
  267. mus_long_t mus_optkey_to_mus_long_t(Xen key, const char *caller, int n, mus_long_t def)
  268. {
  269. if (Xen_is_integer(key))
  270. return(Xen_llong_to_C_llong(key));
  271. if (!(Xen_is_keyword(key)))
  272. Xen_check_type(false, key, n, caller, "a sample number or size");
  273. return(def);
  274. }
  275. const char *mus_optkey_to_string(Xen key, const char *caller, int n, char *def)
  276. {
  277. if (Xen_is_string(key))
  278. return(Xen_string_to_C_string(key));
  279. if ((!(Xen_is_keyword(key))) && (!(Xen_is_false(key))))
  280. Xen_check_type(false, key, n, caller, "a string");
  281. return(def);
  282. }
  283. static vct *mus_optkey_to_vct(Xen key, const char *caller, int n, vct *def)
  284. {
  285. if (mus_is_vct(key))
  286. return(Xen_to_vct(key));
  287. if ((!(Xen_is_keyword(key))) && (!(Xen_is_false(key))))
  288. Xen_check_type(false, key, n, caller, "a " S_vct);
  289. return(def);
  290. }
  291. static bool local_arity_ok(Xen proc, int args) /* from snd-xen.c minus (inconvenient) gc protection */
  292. {
  293. #if HAVE_SCHEME
  294. return(s7_is_aritable(s7, proc, args));
  295. #else
  296. Xen arity;
  297. int rargs;
  298. arity = Xen_arity(proc);
  299. rargs = Xen_integer_to_C_int(arity);
  300. #if HAVE_RUBY
  301. return(xen_rb_arity_ok(rargs, args));
  302. #endif
  303. #if HAVE_FORTH
  304. return(rargs == args);
  305. #endif
  306. #endif
  307. return(true);
  308. }
  309. Xen mus_optkey_to_procedure(Xen key, const char *caller, int n, Xen def, int required_args, const char *err)
  310. {
  311. /* in this case, it's faster to look for the keyword first */
  312. if ((!(Xen_is_keyword(key))) &&
  313. (!(Xen_is_false(key))))
  314. {
  315. Xen_check_type(Xen_is_procedure(key), key, n, caller, "a procedure");
  316. if (!(local_arity_ok(key, required_args)))
  317. Xen_bad_arity_error(caller, n, key, err);
  318. return(key);
  319. }
  320. return(def);
  321. }
  322. /* ---------------- clm keywords ---------------- */
  323. static Xen kw_frequency, kw_initial_phase, kw_wave, kw_amplitude,
  324. kw_r, kw_ratio, kw_size, kw_a0, kw_a1, kw_a2, kw_b1, kw_b2, kw_max_size,
  325. kw_input, kw_srate, kw_file, kw_channel, kw_start,
  326. kw_initial_contents, kw_initial_element, kw_scaler, kw_feedforward, kw_feedback,
  327. kw_radius, kw_partials, kw_a, kw_n,
  328. kw_order, kw_x_coeffs, kw_y_coeffs, kw_envelope, kw_base, kw_duration, kw_offset, kw_end,
  329. kw_direction, kw_degree, kw_distance, kw_reverb, kw_output, kw_fft_size,
  330. kw_expansion, kw_length, kw_hop, kw_ramp, kw_jitter,
  331. kw_type, kw_channels, kw_filter, kw_revout, kw_width,
  332. kw_edit, kw_synthesize, kw_analyze, kw_interp, kw_overlap, kw_pitch,
  333. kw_distribution, kw_coeffs, kw_kind;
  334. static void init_keywords(void)
  335. {
  336. /* in Ruby there's rb_intern of the symbol -- is it safe? */
  337. kw_frequency = Xen_make_keyword("frequency");
  338. kw_initial_phase = Xen_make_keyword("initial-phase");
  339. kw_wave = Xen_make_keyword("wave");
  340. kw_amplitude = Xen_make_keyword("amplitude");
  341. kw_r = Xen_make_keyword("r");
  342. kw_ratio = Xen_make_keyword("ratio");
  343. kw_size = Xen_make_keyword("size");
  344. kw_a0 = Xen_make_keyword("a0");
  345. kw_a1 = Xen_make_keyword("a1");
  346. kw_a2 = Xen_make_keyword("a2");
  347. kw_b1 = Xen_make_keyword("b1");
  348. kw_b2 = Xen_make_keyword("b2");
  349. kw_max_size = Xen_make_keyword("max-size");
  350. kw_input = Xen_make_keyword("input");
  351. kw_srate = Xen_make_keyword("srate");
  352. kw_file = Xen_make_keyword("file");
  353. kw_channel = Xen_make_keyword("channel");
  354. kw_start = Xen_make_keyword("start"); /* make-readin */
  355. kw_initial_contents = Xen_make_keyword("initial-contents");
  356. kw_initial_element = Xen_make_keyword("initial-element");
  357. kw_scaler = Xen_make_keyword("scaler");
  358. kw_feedforward = Xen_make_keyword("feedforward");
  359. kw_feedback = Xen_make_keyword("feedback");
  360. kw_radius = Xen_make_keyword("radius");
  361. kw_partials = Xen_make_keyword("partials");
  362. kw_a = Xen_make_keyword("a");
  363. kw_n = Xen_make_keyword("n");
  364. kw_order = Xen_make_keyword("order");
  365. kw_x_coeffs = Xen_make_keyword("xcoeffs");
  366. kw_y_coeffs = Xen_make_keyword("ycoeffs");
  367. kw_envelope = Xen_make_keyword("envelope");
  368. kw_base = Xen_make_keyword("base");
  369. kw_duration = Xen_make_keyword("duration");
  370. kw_offset = Xen_make_keyword("offset");
  371. kw_end = Xen_make_keyword("end");
  372. kw_direction = Xen_make_keyword("direction");
  373. kw_degree = Xen_make_keyword("degree");
  374. kw_distance = Xen_make_keyword("distance");
  375. kw_reverb = Xen_make_keyword("reverb");
  376. kw_output = Xen_make_keyword("output");
  377. kw_fft_size = Xen_make_keyword("fft-size");
  378. kw_expansion = Xen_make_keyword("expansion");
  379. kw_length = Xen_make_keyword("length");
  380. kw_hop = Xen_make_keyword("hop");
  381. kw_ramp = Xen_make_keyword("ramp");
  382. kw_jitter = Xen_make_keyword("jitter");
  383. kw_type = Xen_make_keyword("type");
  384. kw_channels = Xen_make_keyword("channels");
  385. kw_filter = Xen_make_keyword("filter");
  386. kw_revout = Xen_make_keyword("revout");
  387. kw_width = Xen_make_keyword("width");
  388. kw_edit = Xen_make_keyword("edit");
  389. kw_synthesize = Xen_make_keyword("synthesize");
  390. kw_analyze = Xen_make_keyword("analyze");
  391. kw_interp = Xen_make_keyword("interp");
  392. kw_overlap = Xen_make_keyword("overlap");
  393. kw_pitch = Xen_make_keyword("pitch");
  394. kw_distribution = Xen_make_keyword("distribution");
  395. kw_coeffs = Xen_make_keyword("coeffs");
  396. kw_kind = Xen_make_keyword("kind");
  397. }
  398. /* ---------------- *clm-table-size* ---------------- */
  399. static mus_long_t clm_table_size = MUS_CLM_DEFAULT_TABLE_SIZE;
  400. #if HAVE_SCHEME
  401. static s7_pointer clm_table_size_symbol;
  402. #endif
  403. mus_long_t clm_default_table_size_c(void) {return(clm_table_size);}
  404. static Xen g_clm_table_size(void) {return(C_llong_to_Xen_llong(clm_table_size));}
  405. static Xen g_set_clm_table_size(Xen val)
  406. {
  407. mus_long_t size;
  408. #define H_clm_table_size "(" S_clm_table_size "): the default table size for most generators (512)"
  409. Xen_check_type(Xen_is_llong(val), val, 1, S_set S_clm_table_size, "an integer");
  410. size = Xen_llong_to_C_llong(val);
  411. if ((size <= 0) ||
  412. (size > mus_max_table_size()))
  413. Xen_out_of_range_error(S_set S_clm_table_size, 1, val, "invalid size (see mus-max-table-size)");
  414. clm_table_size = size;
  415. #if HAVE_SCHEME
  416. s7_symbol_set_value(s7, clm_table_size_symbol, s7_make_integer(s7, clm_table_size));
  417. #endif
  418. return(C_llong_to_Xen_llong(clm_table_size));
  419. }
  420. /* ---------------- *clm-default-frequency* ---------------- */
  421. static mus_float_t clm_default_frequency = MUS_CLM_DEFAULT_FREQUENCY;
  422. #if HAVE_SCHEME
  423. static s7_pointer clm_default_frequency_symbol;
  424. #endif
  425. mus_float_t clm_default_frequency_c(void) {return(clm_default_frequency);}
  426. static Xen g_clm_default_frequency(void) {return(C_double_to_Xen_real(clm_default_frequency));}
  427. static Xen g_set_clm_default_frequency(Xen val)
  428. {
  429. #define H_clm_default_frequency "(" S_clm_default_frequency "): the default frequency for most generators (0.0)"
  430. Xen_check_type(Xen_is_double(val), val, 1, S_set S_clm_default_frequency, "a number");
  431. clm_default_frequency = Xen_real_to_C_double(val);
  432. #if HAVE_SCHEME
  433. s7_symbol_set_value(s7, clm_default_frequency_symbol, s7_make_real(s7, clm_default_frequency));
  434. #endif
  435. return(val);
  436. }
  437. /* ---------------- AM and simple stuff ---------------- */
  438. static const char *fft_window_xen_names[MUS_NUM_FFT_WINDOWS] =
  439. {S_rectangular_window, S_hann_window, S_welch_window, S_parzen_window, S_bartlett_window,
  440. S_hamming_window, S_blackman2_window, S_blackman3_window, S_blackman4_window,
  441. S_exponential_window, S_riemann_window, S_kaiser_window, S_cauchy_window,
  442. S_poisson_window, S_gaussian_window, S_tukey_window, S_dolph_chebyshev_window,
  443. S_hann_poisson_window, S_connes_window, S_samaraki_window, S_ultraspherical_window,
  444. S_bartlett_hann_window, S_bohman_window, S_flat_top_window,
  445. S_blackman5_window, S_blackman6_window, S_blackman7_window, S_blackman8_window, S_blackman9_window, S_blackman10_window,
  446. S_rv2_window, S_rv3_window, S_rv4_window, S_mlt_sine_window, S_papoulis_window, S_dpss_window, S_sinc_window
  447. };
  448. const char *mus_fft_window_xen_name(mus_fft_window_t i) {return(fft_window_xen_names[(int)i]);}
  449. static Xen g_mus_file_buffer_size(void)
  450. {
  451. #define H_mus_file_buffer_size "(" S_mus_file_buffer_size "): current CLM IO buffer size (default is 8192)"
  452. return(C_llong_to_Xen_llong(mus_file_buffer_size()));
  453. }
  454. #if HAVE_SCHEME
  455. static s7_pointer mus_file_buffer_size_symbol;
  456. #endif
  457. static Xen g_mus_set_file_buffer_size(Xen val)
  458. {
  459. mus_long_t len;
  460. Xen_check_type(Xen_is_llong(val), val, 1, S_set S_mus_file_buffer_size, "an integer");
  461. len = Xen_llong_to_C_llong(val);
  462. if (len <= 0)
  463. Xen_out_of_range_error(S_set S_mus_file_buffer_size, 1, val, "must be > 0");
  464. mus_set_file_buffer_size(len);
  465. #if HAVE_SCHEME
  466. s7_symbol_set_value(s7, mus_file_buffer_size_symbol, s7_make_integer(s7, len));
  467. #endif
  468. return(val);
  469. }
  470. static Xen g_radians_to_hz(Xen val)
  471. {
  472. #define H_radians_to_hz "(" S_radians_to_hz " rads): convert radians per sample to frequency in Hz: rads * srate / (2 * pi)"
  473. mus_float_t x;
  474. Xen_to_C_double_or_error(val, x, S_radians_to_hz, 1);
  475. return(C_double_to_Xen_real(mus_radians_to_hz(x)));
  476. }
  477. static Xen g_hz_to_radians(Xen val)
  478. {
  479. #define H_hz_to_radians "(" S_hz_to_radians " hz): convert frequency in Hz to radians per sample: hz * 2 * pi / srate"
  480. mus_float_t x;
  481. Xen_to_C_double_or_error(val, x, S_hz_to_radians, 1);
  482. return(C_double_to_Xen_real(mus_hz_to_radians(x)));
  483. }
  484. static Xen g_radians_to_degrees(Xen val)
  485. {
  486. #define H_radians_to_degrees "(" S_radians_to_degrees " rads): convert radians to degrees: rads * 360 / (2 * pi)"
  487. mus_float_t x;
  488. Xen_to_C_double_or_error(val, x, S_radians_to_degrees, 1);
  489. return(C_double_to_Xen_real(mus_radians_to_degrees(x)));
  490. }
  491. static Xen g_degrees_to_radians(Xen val)
  492. {
  493. #define H_degrees_to_radians "(" S_degrees_to_radians " deg): convert degrees to radians: deg * 2 * pi / 360"
  494. mus_float_t x;
  495. Xen_to_C_double_or_error(val, x, S_degrees_to_radians, 1);
  496. return(C_double_to_Xen_real(mus_degrees_to_radians(x)));
  497. }
  498. static Xen g_db_to_linear(Xen val)
  499. {
  500. #define H_db_to_linear "(" S_db_to_linear " db): convert decibel value db to linear value: pow(10, db / 20)"
  501. mus_float_t x;
  502. Xen_to_C_double_or_error(val, x, S_db_to_linear, 1);
  503. return(C_double_to_Xen_real(mus_db_to_linear(x)));
  504. }
  505. static Xen g_linear_to_db(Xen val)
  506. {
  507. #define H_linear_to_db "(" S_linear_to_db " lin): convert linear value to decibels: 20 * log10(lin)"
  508. mus_float_t x;
  509. Xen_to_C_double_or_error(val, x, S_linear_to_db, 1);
  510. return(C_double_to_Xen_real(mus_linear_to_db(x)));
  511. }
  512. static Xen g_even_weight(Xen val)
  513. {
  514. #define H_even_weight "(" S_even_weight " x): return the even weight of x"
  515. mus_float_t x;
  516. Xen_to_C_double_or_error(val, x, S_even_weight, 1);
  517. return(C_double_to_Xen_real(mus_even_weight(x)));
  518. }
  519. static Xen g_odd_weight(Xen val)
  520. {
  521. #define H_odd_weight "(" S_odd_weight " x): return the odd weight of x"
  522. mus_float_t x;
  523. Xen_to_C_double_or_error(val, x, S_odd_weight, 1);
  524. return(C_double_to_Xen_real(mus_odd_weight(x)));
  525. }
  526. static Xen g_even_multiple(Xen val1, Xen val2)
  527. {
  528. #define H_even_multiple "(" S_even_multiple " x y): return the even multiple of x and y"
  529. mus_float_t x, y;
  530. Xen_to_C_double_or_error(val1, x, S_even_multiple, 1);
  531. Xen_to_C_double_or_error(val2, y, S_even_multiple, 2);
  532. return(C_double_to_Xen_real(mus_even_multiple(x, y)));
  533. }
  534. static Xen g_odd_multiple(Xen val1, Xen val2)
  535. {
  536. #define H_odd_multiple "(" S_odd_multiple " x y): return the odd multiple of x and y"
  537. mus_float_t x, y;
  538. Xen_to_C_double_or_error(val1, x, S_odd_multiple, 1);
  539. Xen_to_C_double_or_error(val2, y, S_odd_multiple, 2);
  540. return(C_double_to_Xen_real(mus_odd_multiple(x, y)));
  541. }
  542. static Xen g_seconds_to_samples(Xen val)
  543. {
  544. #define H_seconds_to_samples "(" S_seconds_to_samples " secs): use " S_mus_srate " to convert seconds to samples"
  545. mus_float_t x;
  546. Xen_to_C_double_or_error(val, x, S_seconds_to_samples, 1);
  547. return(C_llong_to_Xen_llong(mus_seconds_to_samples(x)));
  548. }
  549. static Xen g_samples_to_seconds(Xen val)
  550. {
  551. #define H_samples_to_seconds "(" S_samples_to_seconds " samps): use " S_mus_srate " to convert samples to seconds"
  552. Xen_check_type(Xen_is_llong(val), val, 1, S_samples_to_seconds, "a number");
  553. return(C_double_to_Xen_real(mus_samples_to_seconds(Xen_llong_to_C_llong(val))));
  554. }
  555. #if HAVE_SCHEME
  556. static s7_pointer clm_srate_symbol;
  557. #endif
  558. static Xen g_mus_srate(void)
  559. {
  560. #define H_mus_srate "(" S_mus_srate "): current sampling rate"
  561. return(C_double_to_Xen_real(mus_srate()));
  562. }
  563. static Xen g_mus_set_srate(Xen val)
  564. {
  565. mus_float_t sr;
  566. Xen_check_type(Xen_is_number(val), val, 1, S_set S_mus_srate, "a number");
  567. sr = Xen_real_to_C_double(val);
  568. if (sr != mus_srate())
  569. {
  570. if (sr <= 0.0)
  571. Xen_out_of_range_error(S_set S_mus_srate, 1, val, "must be > 0.0");
  572. mus_set_srate(sr);
  573. #if HAVE_SCHEME
  574. s7_symbol_set_value(s7, clm_srate_symbol, s7_make_real(s7, sr));
  575. #endif
  576. }
  577. return(val);
  578. }
  579. #if HAVE_SCHEME
  580. static s7_pointer mus_float_equal_fudge_factor_symbol;
  581. #endif
  582. static Xen g_mus_float_equal_fudge_factor(void)
  583. {
  584. #define H_mus_float_equal_fudge_factor "(" S_mus_float_equal_fudge_factor "): floating point equality fudge factor"
  585. return(C_double_to_Xen_real(mus_float_equal_fudge_factor()));
  586. }
  587. static Xen g_mus_set_float_equal_fudge_factor(Xen val)
  588. {
  589. mus_float_t factor;
  590. Xen_check_type(Xen_is_number(val), val, 1, S_set S_mus_float_equal_fudge_factor, "a number");
  591. factor = Xen_real_to_C_double(val);
  592. if (factor != mus_float_equal_fudge_factor())
  593. {
  594. mus_set_float_equal_fudge_factor(factor);
  595. #if HAVE_SCHEME
  596. s7_symbol_set_value(s7, mus_float_equal_fudge_factor_symbol, s7_make_real(s7, factor));
  597. #endif
  598. }
  599. return(val);
  600. }
  601. #if HAVE_SCHEME
  602. static s7_pointer mus_array_print_length_symbol;
  603. #endif
  604. static Xen g_mus_array_print_length(void)
  605. {
  606. #define H_mus_array_print_length "(" S_mus_array_print_length "): current clm array print length (default is 8). This \
  607. affects error reporting and generator descriptions. Array (" S_vct ") elements beyond this length are represented by '...'"
  608. return(C_int_to_Xen_integer(mus_array_print_length()));
  609. }
  610. static Xen g_mus_set_array_print_length(Xen val)
  611. {
  612. int len;
  613. Xen_check_type(Xen_is_integer(val), val, 1, S_set S_mus_array_print_length, "an integer");
  614. len = Xen_integer_to_C_int(val);
  615. if (len != mus_array_print_length())
  616. {
  617. if (len < 0)
  618. Xen_out_of_range_error(S_set S_mus_array_print_length, 1, val, "must be >= 0");
  619. mus_set_array_print_length(len);
  620. #if HAVE_SCHEME
  621. s7_symbol_set_value(s7, mus_array_print_length_symbol, s7_make_integer(s7, len));
  622. #endif
  623. }
  624. return(val);
  625. }
  626. static Xen g_ring_modulate(Xen val1, Xen val2)
  627. {
  628. #define H_ring_modulate "(" S_ring_modulate " s1 s2): s1 * s2 (sample by sample multiply)"
  629. Xen_check_type(Xen_is_number(val1), val1, 1, S_ring_modulate, "a number");
  630. Xen_check_type(Xen_is_number(val2), val2, 2, S_ring_modulate, "a number");
  631. return(C_double_to_Xen_real(mus_ring_modulate(Xen_real_to_C_double(val1), Xen_real_to_C_double(val2))));
  632. }
  633. static Xen g_amplitude_modulate(Xen val1, Xen val2, Xen val3)
  634. {
  635. #define H_amplitude_modulate "(" S_amplitude_modulate " carrier in1 in2): in1 * (carrier + in2)"
  636. Xen_check_type(Xen_is_number(val1), val1, 1, S_amplitude_modulate, "a number");
  637. Xen_check_type(Xen_is_number(val2), val2, 2, S_amplitude_modulate, "a number");
  638. Xen_check_type(Xen_is_number(val3), val3, 3, S_amplitude_modulate, "a number");
  639. return(C_double_to_Xen_real(mus_amplitude_modulate(Xen_real_to_C_double(val1), Xen_real_to_C_double(val2), Xen_real_to_C_double(val3))));
  640. }
  641. static Xen g_contrast_enhancement(Xen val1, Xen val2)
  642. {
  643. mus_float_t index = 1.0; /* this is the default in clm.html and mus.lisp */
  644. #define H_contrast_enhancement "(" S_contrast_enhancement " sig (index 1.0)): sin(sig * pi / 2 + index * sin(sig * 2 * pi))"
  645. Xen_check_type(Xen_is_number(val1), val1, 1, S_contrast_enhancement, "a number");
  646. if (Xen_is_bound(val2))
  647. {
  648. Xen_check_type(Xen_is_number(val2), val2, 2, S_contrast_enhancement, "a number");
  649. index = Xen_real_to_C_double(val2);
  650. }
  651. return(C_double_to_Xen_real(mus_contrast_enhancement(Xen_real_to_C_double(val1), index)));
  652. }
  653. static Xen g_dot_product(Xen val1, Xen val2, Xen size)
  654. {
  655. #define H_dot_product "(" S_dot_product " v1 v2 (size)): sum of v1[i] * v2[i] (also named scalar product)"
  656. vct *v1, *v2;
  657. mus_long_t len;
  658. Xen_check_type(mus_is_vct(val1), val1, 1, S_dot_product, "a " S_vct);
  659. Xen_check_type(mus_is_vct(val2), val2, 2, S_dot_product, "a " S_vct);
  660. Xen_check_type(Xen_is_llong_or_unbound(size), size, 3, S_dot_product, "an integer");
  661. v1 = Xen_to_vct(val1);
  662. v2 = Xen_to_vct(val2);
  663. if (Xen_is_llong(size))
  664. {
  665. len = Xen_llong_to_C_llong(size);
  666. if (len == 0) return(C_double_to_Xen_real(0.0));
  667. if (len < 0)
  668. Xen_out_of_range_error(S_dot_product, 3, size, "size < 0?");
  669. if (len > mus_vct_length(v1)) len = mus_vct_length(v1);
  670. }
  671. else len = mus_vct_length(v1);
  672. if (len > mus_vct_length(v2)) len = mus_vct_length(v2);
  673. return(C_double_to_Xen_real(mus_dot_product(mus_vct_data(v1), mus_vct_data(v2), len)));
  674. }
  675. #if HAVE_COMPLEX_TRIG && HAVE_COMPLEX_NUMBERS && (!HAVE_RUBY)
  676. #if defined(__sun) && defined(__SVR4)
  677. #undef _Complex_I
  678. #define _Complex_I 1.0fi
  679. #endif
  680. #define S_edot_product "edot-product"
  681. static Xen g_edot_product(Xen val1, Xen val2)
  682. {
  683. #define H_edot_product "(" S_edot_product " freq data): sum of (e^freq*i) * data[i]"
  684. mus_long_t i, len;
  685. vct *v = NULL;
  686. complex double freq;
  687. complex double *vals;
  688. Xen result;
  689. Xen_check_type(Xen_is_complex(val1), val1, 1, S_edot_product, "complex");
  690. Xen_check_type((mus_is_vct(val2)) || (Xen_is_vector(val2)), val2, 2, S_edot_product, "a " S_vct);
  691. freq = Xen_complex_to_C_complex(val1);
  692. if (mus_is_vct(val2))
  693. {
  694. v = Xen_to_vct(val2);
  695. len = mus_vct_length(v);
  696. }
  697. else
  698. {
  699. len = Xen_vector_length(val2);
  700. }
  701. vals = (complex double *)calloc(len, sizeof(complex double));
  702. if (mus_is_vct(val2))
  703. {
  704. mus_float_t *vdata;
  705. vdata = mus_vct_data(v);
  706. for (i = 0; i < len; i++)
  707. vals[i] = vdata[i];
  708. }
  709. else
  710. {
  711. for (i = 0; i < len; i++)
  712. vals[i] = Xen_complex_to_C_complex(Xen_vector_ref(val2, i));
  713. }
  714. result = C_complex_to_Xen_complex(mus_edot_product(freq, vals, len));
  715. free(vals);
  716. return(result);
  717. }
  718. #endif
  719. typedef enum {G_RECTANGULAR_POLAR, G_POLAR_RECTANGULAR, G_RECTANGULAR_MAGNITUDES} xclm_window_t;
  720. static Xen g_fft_window_1(xclm_window_t choice, Xen val1, Xen val2, Xen ulen, const char *caller)
  721. {
  722. vct *v1, *v2;
  723. mus_long_t len;
  724. Xen_check_type(mus_is_vct(val1), val1, 1, caller, "a " S_vct);
  725. Xen_check_type(mus_is_vct(val2), val2, 2, caller, "a " S_vct);
  726. Xen_check_type(Xen_is_llong_or_unbound(ulen), ulen, 3, caller, "an integer");
  727. v1 = Xen_to_vct(val1);
  728. v2 = Xen_to_vct(val2);
  729. if (Xen_is_llong(ulen))
  730. {
  731. len = Xen_llong_to_C_llong(ulen);
  732. if (len == 0) return(Xen_false);
  733. if (len < 0)
  734. Xen_out_of_range_error(caller, 3, ulen, "size < 0?");
  735. if (len > mus_vct_length(v1)) len = mus_vct_length(v1);
  736. }
  737. else len = mus_vct_length(v1);
  738. if (len > mus_vct_length(v2)) len = mus_vct_length(v2);
  739. switch (choice)
  740. {
  741. case G_RECTANGULAR_POLAR: mus_rectangular_to_polar(mus_vct_data(v1), mus_vct_data(v2), len); break;
  742. case G_RECTANGULAR_MAGNITUDES: mus_rectangular_to_magnitudes(mus_vct_data(v1), mus_vct_data(v2), len); break;
  743. case G_POLAR_RECTANGULAR: mus_polar_to_rectangular(mus_vct_data(v1), mus_vct_data(v2), len); break;
  744. }
  745. return(val1);
  746. }
  747. static Xen g_rectangular_to_polar(Xen val1, Xen val2)
  748. {
  749. #define H_rectangular_to_polar "(" S_rectangular_to_polar " rl im): convert real/imaginary \
  750. data in " S_vct "s rl and im from rectangular form (fft output) to polar form (a spectrum)"
  751. return(g_fft_window_1(G_RECTANGULAR_POLAR, val1, val2, Xen_undefined, S_rectangular_to_polar));
  752. }
  753. static Xen g_rectangular_to_magnitudes(Xen val1, Xen val2)
  754. {
  755. #define H_rectangular_to_magnitudes "(" S_rectangular_to_magnitudes " rl im): convert real/imaginary \
  756. data in " S_vct "s rl and im from rectangular form (fft output) to polar form, but ignore the phases"
  757. return(g_fft_window_1(G_RECTANGULAR_MAGNITUDES, val1, val2, Xen_undefined, S_rectangular_to_magnitudes));
  758. }
  759. static Xen g_polar_to_rectangular(Xen val1, Xen val2)
  760. {
  761. #define H_polar_to_rectangular "(" S_polar_to_rectangular " rl im): convert real/imaginary \
  762. data in " S_vct "s rl and im from polar (spectrum) to rectangular (fft)"
  763. return(g_fft_window_1(G_POLAR_RECTANGULAR, val1, val2, Xen_undefined, S_polar_to_rectangular));
  764. }
  765. #if HAVE_SCHEME
  766. #if (!WITH_GMP)
  767. #define PF2_TO_PF(CName, Cfnc) \
  768. static s7_pointer CName ## _pf_a(s7_scheme *sc, s7_pointer **p) \
  769. { \
  770. s7_pf_t f; \
  771. s7_pointer x, y; \
  772. f = (s7_pf_t)(**p); (*p)++; \
  773. x = f(sc, p); \
  774. f = (s7_pf_t)(**p); (*p)++; \
  775. y = f(sc, p); \
  776. return(Cfnc); \
  777. } \
  778. static s7_pf_t CName ## _pf(s7_scheme *sc, s7_pointer expr) \
  779. { \
  780. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_null(sc, s7_cdddr(expr))) && \
  781. (s7_arg_to_pf(sc, s7_cadr(expr))) && \
  782. (s7_arg_to_pf(sc, s7_caddr(expr)))) \
  783. return(CName ## _pf_a); \
  784. return(NULL); \
  785. }
  786. PF2_TO_PF(rectangular_to_polar, g_rectangular_to_polar(x, y))
  787. PF2_TO_PF(polar_to_rectangular, g_polar_to_rectangular(x, y))
  788. PF2_TO_PF(rectangular_to_magnitudes, g_rectangular_to_magnitudes(x, y))
  789. #endif
  790. #endif
  791. static Xen g_mus_fft(Xen url, Xen uim, Xen len, Xen usign)
  792. {
  793. #define H_mus_fft "(" S_mus_fft " rl im (len) (dir 1)): return the fft of " S_vct "s rl and im which contain \
  794. the real and imaginary parts of the data; len should be a power of 2, dir = 1 for fft, -1 for inverse-fft"
  795. int sign;
  796. mus_long_t n;
  797. vct *v1, *v2;
  798. Xen_check_type((mus_is_vct(url)), url, 1, S_mus_fft, "a " S_vct);
  799. Xen_check_type((mus_is_vct(uim)), uim, 2, S_mus_fft, "a " S_vct);
  800. v1 = Xen_to_vct(url);
  801. v2 = Xen_to_vct(uim);
  802. if (Xen_is_integer(usign))
  803. sign = Xen_integer_to_C_int(usign);
  804. else sign = 1;
  805. if (Xen_is_llong(len))
  806. {
  807. n = Xen_llong_to_C_llong(len);
  808. if (n <= 0)
  809. Xen_out_of_range_error(S_mus_fft, 3, len, "size <= 0?");
  810. if (n > mus_max_malloc())
  811. Xen_out_of_range_error(S_mus_fft, 3, len, "size too large (see mus-max-malloc)");
  812. if (n > mus_vct_length(v1))
  813. n = mus_vct_length(v1);
  814. }
  815. else n = mus_vct_length(v1);
  816. if (n > mus_vct_length(v2))
  817. n = mus_vct_length(v2);
  818. if (!(is_power_of_2(n)))
  819. {
  820. mus_float_t nf;
  821. int np;
  822. nf = (log(n) / log(2.0));
  823. np = (int)nf;
  824. n = (mus_long_t)pow(2.0, np);
  825. }
  826. if (n > 0)
  827. mus_fft(mus_vct_data(v1), mus_vct_data(v2), n, sign);
  828. /*
  829. * in fftw, there's the extra complex array allocation, so for n = 2^29
  830. * (and doubles for vcts as well as fftw), we need 24.6 Gbytes, and the FFT
  831. * takes 144 secs on a 2.4 GHz machine. (Similarly, 2^28 needs 12.6 Gb
  832. * and takes 61 secs).
  833. */
  834. return(url);
  835. }
  836. static Xen g_make_fft_window(Xen type, Xen size, Xen ubeta, Xen ualpha)
  837. {
  838. #if HAVE_SCHEME
  839. #define make_window_example "(" S_make_fft_window " " S_hamming_window " 256)"
  840. #endif
  841. #if HAVE_RUBY
  842. #define make_window_example "make_fft_window(Hamming_window, 256)"
  843. #endif
  844. #if HAVE_FORTH
  845. #define make_window_example "hamming-window 256 make-fft-window"
  846. #endif
  847. #define H_make_fft_window "(" S_make_fft_window " type size (beta 0.0) (alpha 0.0)): -> fft data window (a " S_vct "). \
  848. type is one of the sndlib fft window identifiers such as " S_kaiser_window ", beta \
  849. is the window family parameter, if any:\n " make_window_example
  850. mus_float_t beta = 0.0, alpha = 0.0;
  851. mus_long_t n;
  852. int fft_window;
  853. mus_float_t *data;
  854. Xen_check_type(Xen_is_integer(type), type, 1, S_make_fft_window, "an integer (window type)");
  855. Xen_check_type(Xen_is_llong(size), size, 2, S_make_fft_window, "an integer");
  856. if (Xen_is_number(ubeta)) beta = Xen_real_to_C_double(ubeta);
  857. if (Xen_is_number(ualpha)) alpha = Xen_real_to_C_double(ualpha);
  858. n = Xen_llong_to_C_llong(size);
  859. if (n <= 0)
  860. Xen_out_of_range_error(S_make_fft_window, 2, size, "size <= 0?");
  861. if (n > mus_max_malloc())
  862. Xen_out_of_range_error(S_make_fft_window, 2, size, "size too large (see mus-max-malloc)");
  863. fft_window = Xen_integer_to_C_int(type);
  864. if (!(mus_is_fft_window(fft_window)))
  865. Xen_out_of_range_error(S_make_fft_window, 1, type, "unknown fft window");
  866. data = (mus_float_t *)malloc(n * sizeof(mus_float_t));
  867. mus_make_fft_window_with_window((mus_fft_window_t)fft_window, n, beta, alpha, data);
  868. return(xen_make_vct(n, data));
  869. }
  870. static Xen g_spectrum(Xen url, Xen uim, Xen uwin, Xen utype)
  871. {
  872. #define H_mus_spectrum "(" S_spectrum " rl im window (type 1)): \
  873. real and imaginary data in " S_vct "s rl and im, returns (in rl) the spectrum thereof; \
  874. window is the fft data window (a " S_vct " as returned by " S_make_fft_window "), \
  875. and type determines how the spectral data is scaled:\n\
  876. 0 = data in dB,\n\
  877. 1 (default) = linear and normalized\n\
  878. 2 = linear and un-normalized."
  879. int type;
  880. mus_long_t n;
  881. vct *v1, *v2, *v3 = NULL;
  882. Xen_check_type((mus_is_vct(url)), url, 1, S_spectrum, "a " S_vct);
  883. Xen_check_type((mus_is_vct(uim)), uim, 2, S_spectrum, "a " S_vct);
  884. if (!Xen_is_false(uwin)) Xen_check_type((mus_is_vct(uwin)), uwin, 3, S_spectrum, "a " S_vct " or " PROC_FALSE);
  885. v1 = Xen_to_vct(url);
  886. v2 = Xen_to_vct(uim);
  887. if (!Xen_is_false(uwin)) v3 = Xen_to_vct(uwin);
  888. n = mus_vct_length(v1);
  889. if (n > mus_vct_length(v2))
  890. n = mus_vct_length(v2);
  891. if ((v3) && (n > mus_vct_length(v3)))
  892. n = mus_vct_length(v3);
  893. if (!(is_power_of_2(n)))
  894. {
  895. mus_float_t nf;
  896. int np;
  897. nf = (log(n) / log(2.0));
  898. np = (int)nf;
  899. n = (int)pow(2.0, np);
  900. }
  901. if (Xen_is_integer(utype))
  902. type = Xen_integer_to_C_int(utype);
  903. else type = 1; /* linear normalized */
  904. if ((type < 0) || (type > 2))
  905. Xen_out_of_range_error(S_spectrum, 4, utype, "type must be 0..2");
  906. if (n > 0)
  907. mus_spectrum(mus_vct_data(v1), mus_vct_data(v2), (v3) ? (mus_vct_data(v3)) : NULL, n, (mus_spectrum_t)type);
  908. return(url);
  909. }
  910. static Xen g_autocorrelate(Xen reals)
  911. {
  912. #define H_autocorrelate "(" S_autocorrelate " data): in place autocorrelation of data (a " S_vct ")"
  913. /* assumes length is power of 2 */
  914. vct *v1 = NULL;
  915. Xen_check_type(mus_is_vct(reals), reals, 1, S_autocorrelate, "a " S_vct);
  916. v1 = Xen_to_vct(reals);
  917. if (mus_vct_length(v1) > 0)
  918. mus_autocorrelate(mus_vct_data(v1), mus_vct_length(v1));
  919. return(reals);
  920. }
  921. static Xen g_correlate(Xen data1, Xen data2)
  922. {
  923. #define H_correlate "(" S_correlate " data1 data2): in place cross-correlation of data1 and data2 (both " S_vct "s)"
  924. mus_long_t size;
  925. vct *v1 = NULL, *v2 = NULL;
  926. Xen_check_type(mus_is_vct(data1), data1, 1, S_correlate, "a " S_vct);
  927. Xen_check_type(mus_is_vct(data2), data2, 2, S_correlate, "a " S_vct);
  928. v1 = Xen_to_vct(data1);
  929. v2 = Xen_to_vct(data2);
  930. if (mus_vct_length(v1) < mus_vct_length(v2))
  931. size = mus_vct_length(v1);
  932. else size = mus_vct_length(v2);
  933. if (size > 0)
  934. mus_correlate(mus_vct_data(v1), mus_vct_data(v2), size);
  935. return(data1);
  936. }
  937. static Xen g_convolution(Xen url1, Xen url2, Xen un)
  938. {
  939. #define H_mus_convolution "(" S_convolution " v1 v2 (len)): convolution \
  940. of " S_vct "s v1 with v2, using fft of size len (a power of 2), result in v1"
  941. mus_long_t n;
  942. vct *v1, *v2;
  943. Xen_check_type((mus_is_vct(url1)), url1, 1, S_convolution, "a " S_vct);
  944. Xen_check_type((mus_is_vct(url2)), url2, 2, S_convolution, "a " S_vct);
  945. v1 = Xen_to_vct(url1);
  946. v2 = Xen_to_vct(url2);
  947. if (Xen_is_integer(un))
  948. {
  949. n = Xen_llong_to_C_llong(un);
  950. if (n <= 0)
  951. Xen_out_of_range_error(S_convolution, 3, un, "size <= 0?");
  952. if (n > mus_max_malloc())
  953. Xen_out_of_range_error(S_convolution, 3, un, "size too large (see mus-max-malloc)");
  954. if (n > mus_vct_length(v1))
  955. n = mus_vct_length(v1);
  956. }
  957. else n = mus_vct_length(v1);
  958. if (n > mus_vct_length(v2))
  959. n = mus_vct_length(v2);
  960. if (!(is_power_of_2(n)))
  961. {
  962. mus_float_t nf;
  963. int np;
  964. nf = (log(n) / log(2.0));
  965. np = (int)nf;
  966. n = (int)pow(2.0, np);
  967. }
  968. if (n > 0)
  969. mus_convolution(mus_vct_data(v1), mus_vct_data(v2), n);
  970. return(url1);
  971. }
  972. static Xen g_polynomial(Xen arr, Xen x)
  973. {
  974. #define H_polynomial "(" S_polynomial " coeffs x): evaluate a polynomial at x. coeffs are in order \
  975. of degree, so coeff[0] is the constant term."
  976. #if (!HAVE_SCHEME)
  977. Xen_check_type(Xen_is_number(x), x, 2, S_polynomial, "a number");
  978. #endif
  979. if (mus_is_vct(arr))
  980. {
  981. vct *v;
  982. v = Xen_to_vct(arr);
  983. return(C_double_to_Xen_real(mus_polynomial(mus_vct_data(v), Xen_real_to_C_double_with_caller(x, S_polynomial), mus_vct_length(v))));
  984. }
  985. Xen_check_type(Xen_is_vector(arr), arr, 1, S_polynomial, "a vector or " S_vct);
  986. {
  987. mus_float_t sum, cx;
  988. int i, ncoeffs;
  989. ncoeffs = Xen_vector_length(arr);
  990. if (ncoeffs <= 0) return(C_double_to_Xen_real(0.0));
  991. if (ncoeffs == 1) return(Xen_vector_ref(arr, 0)); /* just a constant term */
  992. cx = Xen_real_to_C_double_with_caller(x, S_polynomial);
  993. sum = Xen_real_to_C_double_with_caller(Xen_vector_ref(arr, ncoeffs - 1), S_polynomial);
  994. for (i = ncoeffs - 2; i >= 0; i--)
  995. sum = (sum * cx) + Xen_real_to_C_double_with_caller(Xen_vector_ref(arr, i), S_polynomial);
  996. return(C_double_to_Xen_real(sum));
  997. }
  998. }
  999. static Xen g_array_interp(Xen obj, Xen phase, Xen size) /* opt size */
  1000. {
  1001. #define H_array_interp "(" S_array_interp " v phase (size)): v[phase] \
  1002. taking into account wrap-around (size is size of data), with linear interpolation if phase is not an integer."
  1003. mus_long_t len;
  1004. vct *v;
  1005. Xen_check_type(mus_is_vct(obj), obj, 1, S_array_interp, "a " S_vct);
  1006. #if (!HAVE_SCHEME)
  1007. Xen_check_type(Xen_is_number(phase), phase, 2, S_array_interp, "a number");
  1008. #endif
  1009. Xen_check_type(Xen_is_llong_or_unbound(size), size, 3, S_array_interp, "an integer");
  1010. v = Xen_to_vct(obj);
  1011. if (Xen_is_bound(size))
  1012. {
  1013. len = Xen_llong_to_C_llong(size);
  1014. if (len <= 0)
  1015. Xen_out_of_range_error(S_array_interp, 3, size, "size <= 0?");
  1016. if (len > mus_vct_length(v))
  1017. len = mus_vct_length(v);
  1018. }
  1019. else len = mus_vct_length(v);
  1020. if (len == 0)
  1021. return(C_double_to_Xen_real(0.0));
  1022. return(C_double_to_Xen_real(mus_array_interp(mus_vct_data(v), Xen_real_to_C_double_with_caller(phase, S_array_interp), len)));
  1023. }
  1024. static Xen g_mus_interpolate(Xen type, Xen x, Xen obj, Xen size, Xen yn1)
  1025. {
  1026. #define H_mus_interpolate "(" S_mus_interpolate " type x v (size) (yn1 0.0)): interpolate in \
  1027. data ('v' is a " S_vct ") using interpolation 'type', such as " S_mus_interp_linear "."
  1028. mus_long_t len;
  1029. int itype;
  1030. vct *v;
  1031. mus_float_t y = 0.0;
  1032. Xen_check_type(Xen_is_integer(type), type, 1, S_mus_interpolate, "an integer (interp type such as " S_mus_interp_all_pass ")");
  1033. Xen_check_type(Xen_is_number(x), x, 2, S_mus_interpolate, "a number");
  1034. Xen_check_type(mus_is_vct(obj), obj, 3, S_mus_interpolate, "a " S_vct);
  1035. Xen_check_type(Xen_is_llong_or_unbound(size), size, 4, S_mus_interpolate, "an integer");
  1036. Xen_check_type(Xen_is_number_or_unbound(yn1), yn1, 5, S_mus_interpolate, "a number");
  1037. itype = Xen_integer_to_C_int(type);
  1038. if (!(mus_is_interp_type(itype)))
  1039. Xen_out_of_range_error(S_mus_interpolate, 1, type, "unknown interp type");
  1040. v = Xen_to_vct(obj);
  1041. if (Xen_is_bound(size))
  1042. {
  1043. len = Xen_llong_to_C_llong(size);
  1044. if (len <= 0)
  1045. Xen_out_of_range_error(S_mus_interpolate, 4, size, "size <= 0?");
  1046. if (len > mus_vct_length(v))
  1047. len = mus_vct_length(v);
  1048. }
  1049. else len = mus_vct_length(v);
  1050. if (len == 0)
  1051. return(C_double_to_Xen_real(0.0));
  1052. if (Xen_is_number(yn1))
  1053. y = Xen_real_to_C_double(yn1);
  1054. return(C_double_to_Xen_real(mus_interpolate((mus_interp_t)itype, Xen_real_to_C_double(x), mus_vct_data(v), len, y)));
  1055. }
  1056. /* ---------------- mus-xen struct ---------------- */
  1057. static Xen_object_type_t mus_xen_tag;
  1058. bool mus_is_xen(Xen obj) {return(Xen_c_object_is_type(obj, mus_xen_tag));}
  1059. #define Xen_to_C_generator(Xen_Arg, X_Val, C_Val, Checker, Caller, Descr) \
  1060. Xen_check_type((X_Val = (mus_xen *)Xen_object_ref_checked(Xen_Arg, mus_xen_tag)) && (Checker(C_Val = (mus_any *)mus_xen_to_mus_any(X_Val))), Xen_Arg, 1, Caller, Descr)
  1061. #define Xen_to_C_any_generator(Xen_Arg, X_Val, C_Val, Caller, Descr) \
  1062. Xen_check_type((X_Val = (mus_xen *)Xen_object_ref_checked(Xen_Arg, mus_xen_tag)) && (C_Val = (mus_any *)mus_xen_to_mus_any(X_Val)), Xen_Arg, 1, Caller, Descr)
  1063. static Xen g_is_mus_generator(Xen obj)
  1064. {
  1065. #define H_is_mus_generator "(" S_is_mus_generator " obj): " PROC_TRUE " if 'obj' is a CLM generator."
  1066. return(C_bool_to_Xen_boolean(mus_is_xen(obj)));
  1067. }
  1068. #if HAVE_SCHEME
  1069. static Xen_object_mark_t mark_mus_xen(void *obj)
  1070. #else
  1071. static Xen_object_mark_t mark_mus_xen(Xen obj)
  1072. #endif
  1073. {
  1074. mus_xen *ms;
  1075. #if HAVE_RUBY || HAVE_SCHEME
  1076. /* rb_gc_mark and scheme_mark_object pass us the actual value, not the Xen wrapper */
  1077. ms = (mus_xen *)obj;
  1078. #endif
  1079. #if HAVE_FORTH
  1080. ms = Xen_to_mus_xen(obj);
  1081. #endif
  1082. if (ms->vcts)
  1083. {
  1084. int i, lim;
  1085. lim = MUS_SELF_WRAPPER;
  1086. if (ms->nvcts < lim) lim = ms->nvcts;
  1087. #if HAVE_SCHEME
  1088. if (ms->free_data) /* set if rf functions are using these two vct slots */
  1089. {
  1090. for (i = 0; i < lim; i++)
  1091. if ((i != MUS_INPUT_FUNCTION) &&
  1092. (i != MUS_INPUT_DATA) &&
  1093. (Xen_is_bound(ms->vcts[i])))
  1094. xen_gc_mark(ms->vcts[i]);
  1095. return;
  1096. }
  1097. #endif
  1098. for (i = 0; i < lim; i++)
  1099. if (Xen_is_bound(ms->vcts[i]))
  1100. xen_gc_mark(ms->vcts[i]);
  1101. }
  1102. #if HAVE_RUBY
  1103. return(NULL);
  1104. #endif
  1105. #if (!HAVE_EXTENSION_LANGUAGE)
  1106. return(0);
  1107. #endif
  1108. }
  1109. static void mus_xen_free(mus_xen *ms)
  1110. {
  1111. mus_free(ms->gen);
  1112. ms->gen = NULL;
  1113. mx_free(ms);
  1114. }
  1115. Xen_wrap_free(mus_xen, free_mus_xen, mus_xen_free)
  1116. #if HAVE_SCHEME
  1117. static char *print_mus_xen(s7_scheme *sc, void *obj)
  1118. {
  1119. return(mus_describe(((mus_xen *)obj)->gen));
  1120. }
  1121. static bool s7_equalp_mus_xen(void *val1, void *val2)
  1122. {
  1123. return(mus_equalp(((mus_xen *)val1)->gen, ((mus_xen *)val2)->gen));
  1124. }
  1125. #endif
  1126. enum {G_FILTER_STATE, G_FILTER_XCOEFFS, G_FILTER_YCOEFFS};
  1127. /* G_FILTER_STATE must = MUS_DATA_WRAPPER = 0 */
  1128. enum {G_LOCSIG_DATA, G_LOCSIG_REVDATA, G_LOCSIG_OUT, G_LOCSIG_REVOUT};
  1129. static Xen mus_xen_copy(mus_xen *ms)
  1130. {
  1131. /* return an object -> copied mus_xen -> copied mus_any gen */
  1132. mus_xen *np;
  1133. np = mx_alloc(ms->nvcts);
  1134. np->gen = mus_copy(ms->gen);
  1135. if (ms->nvcts > 0)
  1136. {
  1137. if (ms->nvcts == 1)
  1138. {
  1139. if ((mus_is_env(np->gen)) || /* do the most common case first */
  1140. (mus_is_formant_bank(np->gen)))
  1141. np->vcts[MUS_DATA_WRAPPER] = ms->vcts[MUS_DATA_WRAPPER];
  1142. else
  1143. {
  1144. if ((mus_is_comb_bank(np->gen)) ||
  1145. (mus_is_all_pass_bank(np->gen)) ||
  1146. (mus_is_filtered_comb_bank(np->gen)))
  1147. {
  1148. /* set up objects for new gens so that they will eventually be GC'd */
  1149. Xen v;
  1150. int i, len;
  1151. len = Xen_vector_length(ms->vcts[MUS_DATA_WRAPPER]);
  1152. v = Xen_make_vector(len, Xen_false);
  1153. np->vcts[MUS_DATA_WRAPPER] = v;
  1154. for (i = 0; i < len; i++)
  1155. Xen_vector_set(v, i, mus_xen_to_object(mus_any_to_mus_xen(mus_bank_generator(np->gen, i))));
  1156. }
  1157. else np->vcts[MUS_DATA_WRAPPER] = xen_make_vct_wrapper(mus_length(np->gen), mus_data(np->gen));
  1158. }
  1159. }
  1160. else
  1161. {
  1162. if (ms->nvcts == 2)
  1163. {
  1164. if (mus_is_pulsed_env(np->gen))
  1165. {
  1166. /* mus_free taken care of by copied pulsed_env gen */
  1167. np->vcts[0] = Xen_false;
  1168. np->vcts[1] = Xen_false;
  1169. }
  1170. else
  1171. {
  1172. if (mus_is_filtered_comb(np->gen))
  1173. {
  1174. np->vcts[0] = xen_make_vct_wrapper(mus_length(np->gen), mus_data(np->gen));
  1175. np->vcts[1] = Xen_false; /* filt gen but it's not wrapped */
  1176. }
  1177. else
  1178. {
  1179. np->vcts[0] = ms->vcts[0];
  1180. np->vcts[1] = ms->vcts[1];
  1181. }
  1182. }
  1183. }
  1184. else
  1185. {
  1186. if (ms->nvcts == 3)
  1187. {
  1188. if (mus_is_oscil_bank(np->gen))
  1189. {
  1190. np->vcts[0] = ms->vcts[0];
  1191. np->vcts[1] = xen_make_vct_wrapper(mus_length(np->gen), mus_data(np->gen));
  1192. np->vcts[2] = ms->vcts[2];
  1193. }
  1194. else
  1195. {
  1196. np->vcts[G_FILTER_STATE] = xen_make_vct_wrapper(mus_length(np->gen), mus_data(np->gen));
  1197. np->vcts[G_FILTER_XCOEFFS] = ms->vcts[G_FILTER_XCOEFFS];
  1198. np->vcts[G_FILTER_YCOEFFS] = ms->vcts[G_FILTER_YCOEFFS];
  1199. }
  1200. }
  1201. else
  1202. {
  1203. int i;
  1204. for (i = 0; i < ms->nvcts; i++)
  1205. np->vcts[i] = ms->vcts[i];
  1206. if (mus_is_granulate(np->gen))
  1207. np->vcts[MUS_DATA_WRAPPER] = xen_make_vct_wrapper(mus_granulate_grain_max_length(np->gen), mus_data(np->gen));
  1208. if ((mus_is_convolve(np->gen)) ||
  1209. (mus_is_src(np->gen)) ||
  1210. (mus_is_granulate(np->gen)) ||
  1211. (mus_is_phase_vocoder(np->gen)))
  1212. {
  1213. Xen c_obj;
  1214. c_obj = mus_xen_to_object(np);
  1215. np->vcts[MUS_SELF_WRAPPER] = c_obj;
  1216. mus_generator_copy_feeders(np->gen, ms->gen);
  1217. return(c_obj);
  1218. }
  1219. }
  1220. }
  1221. }
  1222. }
  1223. return(mus_xen_to_object(np));
  1224. }
  1225. #if HAVE_RUBY
  1226. static Xen mus_xen_to_s(Xen obj)
  1227. {
  1228. char *str;
  1229. Xen result;
  1230. str = mus_describe(Xen_to_mus_any(obj));
  1231. result = C_string_to_Xen_string(str);
  1232. if (str) free(str);
  1233. return(result);
  1234. }
  1235. #endif
  1236. #if HAVE_FORTH
  1237. static Xen print_mus_xen(Xen obj)
  1238. {
  1239. char *str;
  1240. Xen result;
  1241. str = mus_describe(Xen_to_mus_any(obj));
  1242. result = fth_make_string_format("#<%s>", str);
  1243. if (str) free(str);
  1244. return(result);
  1245. }
  1246. #endif
  1247. #if (!HAVE_SCHEME)
  1248. static Xen equalp_mus_xen(Xen obj1, Xen obj2)
  1249. {
  1250. if ((!(mus_is_xen(obj1))) || (!(mus_is_xen(obj2)))) return(Xen_false);
  1251. return(C_bool_to_Xen_boolean(mus_equalp(Xen_to_mus_any(obj1), Xen_to_mus_any(obj2))));
  1252. }
  1253. #endif
  1254. #if HAVE_RUBY || HAVE_FORTH
  1255. static Xen mus_xen_apply(Xen gen, Xen arg1, Xen arg2)
  1256. {
  1257. #if HAVE_FORTH
  1258. Xen_check_type(mus_is_xen(gen), gen, 1, S_mus_apply, "a generator");
  1259. #endif
  1260. return(C_double_to_Xen_real(mus_run(Xen_to_mus_any(gen),
  1261. (Xen_is_number(arg1)) ? Xen_real_to_C_double(arg1) : 0.0,
  1262. (Xen_is_number(arg2)) ? Xen_real_to_C_double(arg2) : 0.0)));
  1263. }
  1264. #endif
  1265. #if HAVE_SCHEME
  1266. /* these are for mus_xen_tag, so need not handle float-vectors */
  1267. static Xen mus_xen_apply(s7_scheme *sc, Xen gen, Xen args)
  1268. {
  1269. if (s7_is_pair(args))
  1270. {
  1271. mus_float_t arg1, arg2;
  1272. arg1 = s7_number_to_real_with_caller(sc, s7_car(args), "mus-apply");
  1273. args = s7_cdr(args);
  1274. if (s7_is_pair(args))
  1275. arg2 = s7_number_to_real_with_caller(sc, s7_car(args), "mus-apply");
  1276. else arg2 = 0.0;
  1277. return(s7_make_real(s7, mus_run(Xen_to_mus_any(gen), arg1, arg2)));
  1278. }
  1279. return(s7_make_real(s7, mus_run(Xen_to_mus_any(gen), 0.0, 0.0)));
  1280. }
  1281. static Xen s7_mus_length(s7_scheme *sc, Xen obj)
  1282. {
  1283. return(g_mus_length(obj));
  1284. }
  1285. static Xen g_mus_copy(Xen gen);
  1286. static Xen s7_mus_copy(s7_scheme *sc, Xen args)
  1287. {
  1288. return(g_mus_copy(s7_car(args)));
  1289. }
  1290. #endif
  1291. Xen mus_xen_to_object(mus_xen *gn) /* global for user-defined gens */
  1292. {
  1293. return(Xen_make_object(mus_xen_tag, gn, mark_mus_xen, free_mus_xen));
  1294. }
  1295. Xen mus_xen_to_object_with_vct(mus_xen *gn, Xen v) /* global for user-defined gens */
  1296. {
  1297. gn->vcts[MUS_DATA_WRAPPER] = v;
  1298. return(Xen_make_object(mus_xen_tag, gn, mark_mus_xen, free_mus_xen));
  1299. }
  1300. mus_any *mus_optkey_to_mus_any(Xen key, const char *caller, int n, mus_any *def)
  1301. {
  1302. /* from Michael Scholz's sndins.c */
  1303. if (!(Xen_is_keyword(key)))
  1304. {
  1305. Xen_check_type(mus_is_xen(key), key, n, caller, "a clm generator or keyword");
  1306. return(Xen_to_mus_any(key));
  1307. }
  1308. return(def);
  1309. }
  1310. static Xen mus_optkey_to_input_procedure(Xen key, const char *caller, int n, Xen def, int required_args, const char *err)
  1311. {
  1312. if (Xen_is_procedure(key))
  1313. {
  1314. if (!(local_arity_ok(key, required_args)))
  1315. Xen_bad_arity_error(caller, n, key, err);
  1316. return(key);
  1317. }
  1318. if (mus_is_xen(key))
  1319. {
  1320. if (!(mus_is_input(Xen_to_mus_any(key))))
  1321. Xen_wrong_type_arg_error(caller, n, key, "an input generator");
  1322. return(key);
  1323. }
  1324. if ((!(Xen_is_keyword(key))) &&
  1325. (!(Xen_is_false(key))))
  1326. Xen_check_type(false, key, n, caller, "a procedure or input generator");
  1327. return(def);
  1328. }
  1329. /* ---------------- wrappers ---------------- */
  1330. mus_xen *mus_any_to_mus_xen(mus_any *ge)
  1331. {
  1332. mus_xen *gn;
  1333. gn = mx_alloc(0);
  1334. gn->gen = ge;
  1335. return(gn);
  1336. }
  1337. mus_xen *mus_any_to_mus_xen_with_vct(mus_any *ge, Xen v)
  1338. {
  1339. mus_xen *gn;
  1340. gn = mx_alloc(1);
  1341. gn->gen = ge;
  1342. gn->vcts[MUS_DATA_WRAPPER] = v;
  1343. return(gn);
  1344. }
  1345. mus_xen *mus_any_to_mus_xen_with_two_vcts(mus_any *ge, Xen v1, Xen v2)
  1346. {
  1347. mus_xen *gn;
  1348. gn = mx_alloc(2);
  1349. gn->gen = ge;
  1350. gn->vcts[MUS_DATA_WRAPPER] = v1;
  1351. gn->vcts[MUS_INPUT_FUNCTION] = v2;
  1352. return(gn);
  1353. }
  1354. /* ---------------- generic functions ---------------- */
  1355. static Xen g_mus_reset(Xen gen)
  1356. {
  1357. #define H_mus_reset "(" S_mus_reset " gen): clear out gen, setting it to its default starting state"
  1358. mus_xen *ms;
  1359. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1360. if (ms)
  1361. {
  1362. mus_reset(ms->gen);
  1363. return(gen);
  1364. }
  1365. #if HAVE_SCHEME
  1366. if (s7_is_float_vector(gen))
  1367. {
  1368. s7_int len;
  1369. len = s7_vector_length(gen);
  1370. if (len > 0)
  1371. memset((void *)s7_float_vector_elements(gen), 0, len * sizeof(s7_double));
  1372. return(gen);
  1373. }
  1374. {
  1375. s7_pointer func;
  1376. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-reset"));
  1377. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1378. }
  1379. #endif
  1380. Xen_check_type(false, gen, 1, S_mus_reset, "a generator");
  1381. return(gen);
  1382. }
  1383. #if HAVE_SCHEME
  1384. static s7_pointer mus_copy_symbol, copy_function;
  1385. #endif
  1386. static Xen g_mus_copy(Xen gen)
  1387. {
  1388. #define H_mus_copy "(" S_mus_copy " gen): return a copy of gen"
  1389. mus_xen *ms;
  1390. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1391. if (ms)
  1392. return(mus_xen_copy(ms));
  1393. #if HAVE_SCHEME
  1394. {
  1395. s7_pointer func;
  1396. func = s7_method(s7, gen, mus_copy_symbol);
  1397. if (func == copy_function)
  1398. return(s7_copy(s7, s7_list(s7, 1, gen)));
  1399. if (func != Xen_undefined)
  1400. return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1401. }
  1402. #endif
  1403. Xen_check_type(false, gen, 1, S_mus_copy, "a generator");
  1404. return(gen);
  1405. }
  1406. static Xen g_mus_run(Xen gen, Xen arg1, Xen arg2)
  1407. {
  1408. #define H_mus_run "(" S_mus_run " gen (arg1 0.0) (arg2 0.0)): apply gen to arg1 and arg2"
  1409. mus_xen *ms;
  1410. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1411. if (ms)
  1412. {
  1413. mus_float_t a1 = 0.0, a2 = 0.0;
  1414. Xen_real_to_C_double_if_bound(arg1, a1, S_mus_run, 2);
  1415. Xen_real_to_C_double_if_bound(arg2, a2, S_mus_run, 3);
  1416. return(C_double_to_Xen_real(mus_run(ms->gen, a1, a2)));
  1417. }
  1418. #if HAVE_SCHEME
  1419. {
  1420. s7_pointer func;
  1421. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-run"));
  1422. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 3, gen, arg1, arg2)));
  1423. }
  1424. #endif
  1425. Xen_check_type(false, gen, 1, S_mus_run, "a generator");
  1426. return(C_double_to_Xen_real(0.0));
  1427. }
  1428. static Xen g_mus_apply(Xen arglist)
  1429. {
  1430. #define H_mus_apply "(" S_mus_apply " gen args...): apply gen to args"
  1431. mus_xen *ms;
  1432. Xen gen;
  1433. int arglist_len;
  1434. arglist_len = Xen_list_length(arglist);
  1435. if ((arglist_len > 3) || (arglist_len == 0))
  1436. return(C_double_to_Xen_real(0.0));
  1437. gen = Xen_car(arglist);
  1438. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1439. if (ms)
  1440. {
  1441. mus_any *g;
  1442. g = ms->gen;
  1443. if (arglist_len == 1)
  1444. return(C_double_to_Xen_real(mus_apply(g, 0.0, 0.0)));
  1445. if (arglist_len == 2)
  1446. return(C_double_to_Xen_real(mus_apply(g, Xen_real_to_C_double(Xen_cadr(arglist)), 0.0)));
  1447. return(C_double_to_Xen_real(mus_apply(g,
  1448. Xen_real_to_C_double_with_caller(Xen_cadr(arglist), "mus-apply"),
  1449. Xen_real_to_C_double_with_caller(Xen_caddr(arglist), "mus-apply"))));
  1450. }
  1451. #if HAVE_SCHEME
  1452. {
  1453. s7_pointer func;
  1454. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-apply"));
  1455. if (func != Xen_undefined) return(s7_apply_function(s7, func, arglist));
  1456. }
  1457. #endif
  1458. Xen_check_type(false, Xen_car(arglist), 1, S_mus_apply, "a generator");
  1459. return(C_double_to_Xen_real(0.0));
  1460. }
  1461. static Xen g_mus_describe(Xen gen)
  1462. {
  1463. #define H_mus_describe "(" S_mus_describe " gen): return a string describing the state of CLM generator generator"
  1464. mus_xen *ms;
  1465. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1466. if (ms)
  1467. {
  1468. Xen result;
  1469. char *str;
  1470. str = mus_describe(ms->gen);
  1471. result = C_string_to_Xen_string(str);
  1472. if (str) free(str);
  1473. return(result);
  1474. }
  1475. #if HAVE_SCHEME
  1476. {
  1477. s7_pointer func;
  1478. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-describe"));
  1479. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1480. }
  1481. #endif
  1482. Xen_check_type(false, gen, 1, S_mus_describe, "a generator");
  1483. return(gen);
  1484. }
  1485. #if HAVE_SCHEME
  1486. #define mus_double_generic(Caller, CLM_case, Symbol) \
  1487. mus_xen *gn; \
  1488. s7_pointer func; \
  1489. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1490. if (gn) return(C_double_to_Xen_real(CLM_case(gn->gen))); \
  1491. func = s7_method(s7, gen, Symbol); \
  1492. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen))); \
  1493. Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1494. return(gen);
  1495. #define mus_set_double_generic(Caller, CLM_case) \
  1496. mus_xen *gn; \
  1497. s7_pointer func; \
  1498. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1499. Xen_check_type(Xen_is_double(val), val, 2, S_set Caller, "a float"); \
  1500. if (gn) {CLM_case(gn->gen, Xen_real_to_C_double(val)); return(val);} \
  1501. func = s7_method(s7, gen, s7_make_symbol(s7, Caller)); \
  1502. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func))) \
  1503. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 2, gen, val))); \
  1504. Xen_check_type(false, gen, 1, S_set Caller, "a generator"); \
  1505. return(val);
  1506. #define mus_long_long_generic(Caller, CLM_case) \
  1507. mus_xen *gn; \
  1508. s7_pointer func; \
  1509. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1510. if (gn) return(C_llong_to_Xen_llong(CLM_case(gn->gen))); \
  1511. func = s7_method(s7, gen, s7_make_symbol(s7, Caller)); \
  1512. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen))); \
  1513. Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1514. return(gen);
  1515. #define mus_set_long_long_generic(Caller, CLM_case) \
  1516. mus_xen *gn; \
  1517. s7_pointer func; \
  1518. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1519. Xen_check_type(Xen_is_integer(val), val, 2, Caller, "an integer"); \
  1520. if (gn) {CLM_case(gn->gen, Xen_llong_to_C_llong(val)); return(val);} \
  1521. func = s7_method(s7, gen, s7_make_symbol(s7, Caller)); \
  1522. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func))) \
  1523. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 2, gen, val))); \
  1524. Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1525. return(val);
  1526. #define mus_int_generic(Caller, CLM_case) \
  1527. mus_xen *gn; \
  1528. s7_pointer func; \
  1529. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1530. if (gn) return(C_int_to_Xen_integer(CLM_case(gn->gen))); \
  1531. func = s7_method(s7, gen, s7_make_symbol(s7, Caller)); \
  1532. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen))); \
  1533. Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1534. return(gen);
  1535. #else
  1536. #define mus_double_generic(Caller, CLM_case, Symbol) \
  1537. mus_xen *gn; \
  1538. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1539. if (!gn) Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1540. return(C_double_to_Xen_real(CLM_case(gn->gen)));
  1541. #define mus_set_double_generic(Caller, CLM_case) \
  1542. mus_xen *gn; \
  1543. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1544. if (!gn) Xen_check_type(false, gen, 1, S_set Caller, "a generator"); \
  1545. Xen_check_type(Xen_is_double(val), val, 2, S_set Caller, "a float"); \
  1546. CLM_case(gn->gen, Xen_real_to_C_double(val)); \
  1547. return(val);
  1548. #define mus_long_long_generic(Caller, CLM_case) \
  1549. mus_xen *gn; \
  1550. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1551. if (!gn) Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1552. return(C_llong_to_Xen_llong(CLM_case(gn->gen)));
  1553. #define mus_set_long_long_generic(Caller, CLM_case) \
  1554. mus_xen *gn; \
  1555. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1556. if (!gn) Xen_check_type(false, gen, 1, S_set Caller, "a generator"); \
  1557. Xen_check_type(Xen_is_integer(val), val, 2, S_set Caller, "an integer"); \
  1558. CLM_case(gn->gen, Xen_llong_to_C_llong(val)); \
  1559. return(val);
  1560. #define mus_int_generic(Caller, CLM_case) \
  1561. mus_xen *gn; \
  1562. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag); \
  1563. if (!gn) Xen_check_type(false, gen, 1, Caller, "a generator"); \
  1564. return(C_int_to_Xen_integer(CLM_case(gn->gen)));
  1565. #endif
  1566. #if HAVE_SCHEME
  1567. static Xen sym_frequency, sym_phase, sym_scaler, sym_increment, sym_width, sym_offset, sym_feedforward, sym_feedback;
  1568. #endif
  1569. static Xen g_mus_frequency(Xen gen)
  1570. {
  1571. #define H_mus_frequency "(" S_mus_frequency " gen): gen's frequency (Hz)"
  1572. mus_double_generic(S_mus_frequency, mus_frequency, sym_frequency);
  1573. }
  1574. static Xen g_mus_set_frequency(Xen gen, Xen val)
  1575. {
  1576. mus_set_double_generic(S_mus_frequency, mus_set_frequency);
  1577. }
  1578. static Xen g_mus_phase(Xen gen)
  1579. {
  1580. #define H_mus_phase "(" S_mus_phase " gen): gen's current phase (radians)"
  1581. mus_double_generic(S_mus_phase, mus_phase, sym_phase);
  1582. }
  1583. static Xen g_mus_set_phase(Xen gen, Xen val)
  1584. {
  1585. mus_set_double_generic(S_mus_phase, mus_set_phase);
  1586. }
  1587. static Xen g_mus_scaler(Xen gen)
  1588. {
  1589. #define H_mus_scaler "(" S_mus_scaler " gen): gen's scaler, if any. This is often an amplitude adjustment of some sort."
  1590. mus_double_generic(S_mus_scaler, mus_scaler, sym_scaler);
  1591. }
  1592. static Xen g_mus_set_scaler(Xen gen, Xen val)
  1593. {
  1594. mus_set_double_generic(S_mus_scaler, mus_set_scaler);
  1595. }
  1596. static Xen g_mus_feedforward(Xen gen)
  1597. {
  1598. #define H_mus_feedforward "(" S_mus_feedforward " gen): gen's feedforward field"
  1599. mus_double_generic(S_mus_feedforward, mus_scaler, sym_feedforward);
  1600. }
  1601. static Xen g_mus_set_feedforward(Xen gen, Xen val)
  1602. {
  1603. mus_set_double_generic(S_mus_feedforward, mus_set_scaler);
  1604. }
  1605. static Xen g_mus_feedback(Xen gen)
  1606. {
  1607. #define H_mus_feedback "(" S_mus_feedback " gen): gen's " S_mus_feedback " field"
  1608. mus_double_generic(S_mus_feedback, mus_increment, sym_feedback);
  1609. }
  1610. static Xen g_mus_set_feedback(Xen gen, Xen val)
  1611. {
  1612. mus_set_double_generic(S_mus_feedback, mus_set_increment);
  1613. }
  1614. static Xen g_mus_width(Xen gen)
  1615. {
  1616. #define H_mus_width "(" S_mus_width " gen): gen's width, if any. This is usually a table size."
  1617. mus_double_generic(S_mus_width, mus_width, sym_width);
  1618. }
  1619. static Xen g_mus_set_width(Xen gen, Xen val)
  1620. {
  1621. mus_set_double_generic(S_mus_width, mus_set_width);
  1622. }
  1623. static Xen g_mus_offset(Xen gen)
  1624. {
  1625. #define H_mus_offset "(" S_mus_offset " gen): gen's offset, if any"
  1626. mus_double_generic(S_mus_offset, mus_offset, sym_offset);
  1627. }
  1628. static Xen g_mus_set_offset(Xen gen, Xen val)
  1629. {
  1630. mus_set_double_generic(S_mus_offset, mus_set_offset);
  1631. }
  1632. static Xen g_mus_increment(Xen gen)
  1633. {
  1634. #define H_mus_increment "(" S_mus_increment " gen): gen's " S_mus_increment " field, if any"
  1635. mus_double_generic(S_mus_increment, mus_increment, sym_increment);
  1636. }
  1637. static Xen g_mus_set_increment(Xen gen, Xen val)
  1638. {
  1639. mus_set_double_generic(S_mus_increment, mus_set_increment);
  1640. }
  1641. static Xen g_mus_hop(Xen gen)
  1642. {
  1643. #define H_mus_hop "(" S_mus_hop " gen): gen's " S_mus_hop " field"
  1644. mus_long_long_generic(S_mus_hop, mus_hop);
  1645. }
  1646. static Xen g_mus_set_hop(Xen gen, Xen val)
  1647. {
  1648. mus_set_long_long_generic(S_mus_hop, mus_set_hop);
  1649. }
  1650. static Xen g_mus_ramp(Xen gen)
  1651. {
  1652. #define H_mus_ramp "(" S_mus_ramp " gen): granulate generator's " S_mus_ramp " field"
  1653. mus_long_long_generic(S_mus_ramp, mus_ramp);
  1654. }
  1655. static Xen g_mus_set_ramp(Xen gen, Xen val)
  1656. {
  1657. mus_set_long_long_generic(S_mus_ramp, mus_set_ramp);
  1658. }
  1659. static Xen g_mus_location(Xen gen)
  1660. {
  1661. #define H_mus_location "(" S_mus_location " gen): gen's " S_mus_location " field, if any"
  1662. mus_long_long_generic(S_mus_location, mus_location);
  1663. }
  1664. static Xen g_mus_set_location(Xen gen, Xen val)
  1665. {
  1666. mus_set_long_long_generic(S_mus_location, mus_set_location);
  1667. }
  1668. static Xen g_mus_order(Xen gen)
  1669. {
  1670. #define H_mus_order "(" S_mus_order " gen): gen's order, if any"
  1671. mus_long_long_generic(S_mus_order, mus_length);
  1672. }
  1673. static Xen g_mus_channel(Xen gen)
  1674. {
  1675. #define H_mus_channel "(" S_mus_channel " gen): gen's " S_mus_channel " field, if any"
  1676. mus_int_generic(S_mus_channel, mus_channel);
  1677. }
  1678. static Xen g_mus_interp_type(Xen gen)
  1679. {
  1680. #define H_mus_interp_type "(" S_mus_interp_type " gen): gen's " S_mus_interp_type " field, if any"
  1681. mus_int_generic(S_mus_interp_type, mus_channels);
  1682. }
  1683. static Xen g_mus_type(Xen gen)
  1684. {
  1685. #define H_mus_type "(" S_mus_type " gen): gen's type"
  1686. mus_int_generic(S_mus_type, mus_type);
  1687. }
  1688. static Xen g_mus_name(Xen gen)
  1689. {
  1690. #define H_mus_name "(" S_mus_name " gen): gen's (type) name, if any"
  1691. mus_xen *ms;
  1692. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1693. if (ms)
  1694. return(C_string_to_Xen_string(mus_name(mus_xen_to_mus_any(ms))));
  1695. #if HAVE_SCHEME
  1696. {
  1697. s7_pointer func;
  1698. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-name"));
  1699. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1700. }
  1701. #endif
  1702. Xen_check_type(false, gen, 1, S_mus_name, "a generator");
  1703. return(gen);
  1704. }
  1705. Xen g_mus_file_name(Xen gen)
  1706. {
  1707. #define H_mus_file_name "(" S_mus_file_name " gen): file associated with gen, if any"
  1708. mus_xen *gn;
  1709. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1710. if (gn)
  1711. return(C_string_to_Xen_string(mus_file_name(gn->gen)));
  1712. #if HAVE_SCHEME
  1713. {
  1714. s7_pointer func;
  1715. func = s7_method(s7, gen, s7_make_symbol(s7, S_mus_file_name));
  1716. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1717. }
  1718. #endif
  1719. Xen_check_type(false, gen, 1, S_mus_file_name, "a generator");
  1720. return(gen);
  1721. }
  1722. Xen g_mus_data(Xen gen)
  1723. {
  1724. #define H_mus_data "(" S_mus_data " gen): gen's internal data (a " S_vct "), if any"
  1725. mus_xen *ms;
  1726. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1727. if (ms)
  1728. {
  1729. if (ms->vcts)
  1730. return(ms->vcts[MUS_DATA_WRAPPER]);
  1731. else return(Xen_false);
  1732. }
  1733. #if HAVE_SCHEME
  1734. {
  1735. s7_pointer func;
  1736. func = s7_method(s7, gen, s7_make_symbol(s7, S_mus_data));
  1737. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1738. }
  1739. #endif
  1740. Xen_check_type(false, gen, 1, S_mus_data, "a generator");
  1741. return(gen);
  1742. }
  1743. static Xen g_mus_set_data(Xen gen, Xen val)
  1744. {
  1745. mus_xen *ms;
  1746. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1747. if (ms)
  1748. {
  1749. Xen_check_type((mus_is_vct(val)), val, 2, S_set S_mus_data, "a " S_vct);
  1750. if (ms->vcts)
  1751. {
  1752. vct *v;
  1753. mus_any *ma;
  1754. v = Xen_to_vct(val);
  1755. ma = ms->gen;
  1756. mus_set_data(ma, mus_vct_data(v)); /* TO REMEMBER: if allocated, should have freed, and set to not allocated */
  1757. ms->vcts[MUS_DATA_WRAPPER] = val;
  1758. return(val);
  1759. }
  1760. }
  1761. #if HAVE_SCHEME
  1762. {
  1763. s7_pointer func;
  1764. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-data"));
  1765. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func)))
  1766. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 2, gen, val)));
  1767. }
  1768. #endif
  1769. Xen_check_type(false, gen, 1, S_set S_mus_data, "a generator with a data field");
  1770. return(Xen_false);
  1771. }
  1772. static Xen c_xcoeffs(mus_xen *ms)
  1773. {
  1774. mus_any *g;
  1775. g = ms->gen;
  1776. if (ms->vcts)
  1777. {
  1778. if (mus_is_polywave(g))
  1779. return(ms->vcts[0]);
  1780. if (ms->nvcts > G_FILTER_XCOEFFS)
  1781. return(ms->vcts[G_FILTER_XCOEFFS]);
  1782. }
  1783. if ((mus_is_one_zero(g)) ||
  1784. (mus_is_one_pole(g)) ||
  1785. (mus_is_two_zero(g)) ||
  1786. (mus_is_two_pole(g)))
  1787. return(xen_make_vct_wrapper(3, mus_xcoeffs(g)));
  1788. return(Xen_false);
  1789. }
  1790. static Xen g_mus_xcoeffs(Xen gen)
  1791. {
  1792. #define H_mus_xcoeffs "(" S_mus_xcoeffs " gen): gen's filter xcoeffs (" S_vct " of coefficients on inputs)"
  1793. mus_xen *ms;
  1794. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1795. if (ms) return(c_xcoeffs(ms));
  1796. #if HAVE_SCHEME
  1797. {
  1798. s7_pointer func;
  1799. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-xcoeffs"));
  1800. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1801. }
  1802. #endif
  1803. Xen_check_type(false, gen, 1, S_mus_xcoeffs, "a generator");
  1804. return(gen);
  1805. }
  1806. static Xen g_mus_ycoeffs(Xen gen)
  1807. {
  1808. #define H_mus_ycoeffs "(" S_mus_ycoeffs " gen): gen's filter ycoeffs (" S_vct " of coefficients on outputs)"
  1809. mus_xen *ms;
  1810. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1811. if (ms)
  1812. {
  1813. mus_any *g;
  1814. g = ms->gen;
  1815. if (ms->vcts)
  1816. {
  1817. if ((mus_is_polywave(Xen_to_mus_any(gen))) && (ms->nvcts == 2))
  1818. return(ms->vcts[1]);
  1819. if (ms->nvcts > G_FILTER_YCOEFFS)
  1820. return(ms->vcts[G_FILTER_YCOEFFS]);
  1821. }
  1822. if ((mus_is_one_zero(g)) ||
  1823. (mus_is_one_pole(g)) ||
  1824. (mus_is_two_zero(g)) ||
  1825. (mus_is_two_pole(g)))
  1826. return(xen_make_vct_wrapper(3, mus_ycoeffs(g)));
  1827. return(Xen_false);
  1828. }
  1829. #if HAVE_SCHEME
  1830. {
  1831. s7_pointer func;
  1832. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-ycoeffs"));
  1833. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1834. }
  1835. #endif
  1836. Xen_check_type(false, gen, 1, S_mus_ycoeffs, "a generator");
  1837. return(gen);
  1838. }
  1839. static Xen g_mus_xcoeff(Xen gen, Xen index)
  1840. {
  1841. #define H_mus_xcoeff "(" S_mus_xcoeff " gen index): gen's filter xcoeff value at index (0-based)"
  1842. mus_xen *ms;
  1843. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1844. if (ms)
  1845. {
  1846. int ind = 0;
  1847. Xen_to_C_integer_or_error(index, ind, S_mus_xcoeff, 2);
  1848. if (ind < 0)
  1849. Xen_out_of_range_error(S_mus_xcoeff, 2, index, "index must be non-negative");
  1850. return(C_double_to_Xen_real(mus_xcoeff(mus_xen_to_mus_any(ms), ind)));
  1851. }
  1852. #if HAVE_SCHEME
  1853. {
  1854. s7_pointer func;
  1855. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-xcoeff"));
  1856. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 2, gen, index)));
  1857. }
  1858. #endif
  1859. Xen_check_type(false, gen, 1, S_mus_xcoeff, "a generator");
  1860. return(index);
  1861. }
  1862. static Xen g_mus_set_xcoeff(Xen gen, Xen index, Xen val)
  1863. {
  1864. mus_xen *ms;
  1865. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1866. if (ms)
  1867. {
  1868. int ind = 0;
  1869. mus_float_t x;
  1870. Xen_to_C_integer_or_error(index, ind, S_set S_mus_xcoeff, 2);
  1871. Xen_to_C_double_or_error(val, x, S_set S_mus_xcoeff, 3);
  1872. if (ind < 0)
  1873. Xen_out_of_range_error(S_set S_mus_xcoeff, 2, index, "index must be non-negative");
  1874. mus_set_xcoeff(mus_xen_to_mus_any(ms), ind, x);
  1875. return(val);
  1876. }
  1877. #if HAVE_SCHEME
  1878. {
  1879. s7_pointer func;
  1880. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-xcoeff"));
  1881. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func)))
  1882. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 3, gen, index, val)));
  1883. }
  1884. #endif
  1885. Xen_check_type(false, gen, 1, S_set S_mus_xcoeff, "a generator");
  1886. return(val);
  1887. }
  1888. static Xen g_mus_ycoeff(Xen gen, Xen index)
  1889. {
  1890. #define H_mus_ycoeff "(" S_mus_ycoeff " gen index): gen's filter ycoeff value at index (0-based)"
  1891. mus_xen *ms;
  1892. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1893. if (ms)
  1894. {
  1895. int ind = 0;
  1896. Xen_to_C_integer_or_error(index, ind, S_mus_ycoeff, 2);
  1897. if (ind < 0)
  1898. Xen_out_of_range_error(S_mus_ycoeff, 2, index, "index must be non-negative");
  1899. return(C_double_to_Xen_real(mus_ycoeff(mus_xen_to_mus_any(ms), ind)));
  1900. }
  1901. #if HAVE_SCHEME
  1902. {
  1903. s7_pointer func;
  1904. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-ycoeff"));
  1905. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 2, gen, index)));
  1906. }
  1907. #endif
  1908. Xen_check_type(false, gen, 1, S_mus_ycoeff, "a generator");
  1909. return(index);
  1910. }
  1911. static Xen g_mus_set_ycoeff(Xen gen, Xen index, Xen val)
  1912. {
  1913. mus_xen *ms;
  1914. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1915. if (ms)
  1916. {
  1917. int ind = 0;
  1918. mus_float_t x;
  1919. Xen_to_C_integer_or_error(index, ind, S_set S_mus_ycoeff, 2);
  1920. Xen_to_C_double_or_error(val, x, S_set S_mus_ycoeff, 3);
  1921. if (ind < 0)
  1922. Xen_out_of_range_error(S_set S_mus_ycoeff, 2, index, "index must be non-negative");
  1923. mus_set_ycoeff(mus_xen_to_mus_any(ms), ind, x);
  1924. return(val);
  1925. }
  1926. #if HAVE_SCHEME
  1927. {
  1928. s7_pointer func;
  1929. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-ycoeff"));
  1930. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func)))
  1931. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 3, gen, index, val)));
  1932. }
  1933. #endif
  1934. Xen_check_type(false, gen, 1, S_set S_mus_ycoeff, "a generator");
  1935. return(val);
  1936. }
  1937. Xen g_mus_channels(Xen gen)
  1938. {
  1939. #define H_mus_channels "(" S_mus_channels " gen): gen's " S_mus_channels " field, if any"
  1940. mus_xen *gn;
  1941. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1942. if (gn)
  1943. return(C_int_to_Xen_integer(mus_channels(gn->gen)));
  1944. #if HAVE_SCHEME
  1945. if (mus_is_vct(gen))
  1946. {
  1947. if (Xen_vector_rank(gen) > 1)
  1948. return(C_int_to_Xen_integer(s7_vector_dimensions(gen)[0]));
  1949. else return(C_int_to_Xen_integer(1));
  1950. }
  1951. #else
  1952. if (mus_is_vct(gen))
  1953. return(C_int_to_Xen_integer(1));
  1954. #endif
  1955. #if HAVE_SCHEME
  1956. {
  1957. s7_pointer func;
  1958. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-channels"));
  1959. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1960. }
  1961. #endif
  1962. Xen_check_type(false, gen, 1, S_mus_channels, "an output generator, " S_vct ", or sound-data object");
  1963. return(Xen_false); /* make compiler happy */
  1964. }
  1965. Xen g_mus_length(Xen gen)
  1966. {
  1967. #define H_mus_length "(" S_mus_length " gen): gen's length, if any"
  1968. mus_xen *gn;
  1969. gn = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1970. if (gn)
  1971. return(C_llong_to_Xen_llong(mus_length(gn->gen)));
  1972. if (mus_is_vct(gen))
  1973. return(C_int_to_Xen_integer(mus_vct_length(Xen_to_vct(gen))));
  1974. #if HAVE_SCHEME
  1975. {
  1976. s7_pointer func;
  1977. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-length"));
  1978. if (func != Xen_undefined) return(s7_apply_function(s7, func, s7_list(s7, 1, gen)));
  1979. }
  1980. #endif
  1981. Xen_check_type(false, gen, 1, S_mus_length, "a generator, " S_vct ", or sound-data object");
  1982. return(Xen_false); /* make compiler happy */
  1983. }
  1984. static Xen g_mus_set_length(Xen gen, Xen val)
  1985. {
  1986. mus_xen *ms;
  1987. ms = (mus_xen *)Xen_object_ref_checked(gen, mus_xen_tag);
  1988. if (ms)
  1989. {
  1990. mus_long_t len = 0;
  1991. mus_any *ptr = NULL;
  1992. Xen_to_C_integer_or_error(val, len, S_set S_mus_length, 2);
  1993. if (len <= 0)
  1994. Xen_out_of_range_error(S_set S_mus_length, 1, val, "must be > 0");
  1995. ptr = ms->gen;
  1996. if ((!mus_is_env(ptr)) && (!mus_is_src(ptr))) /* set length doesn't refer to data vct here */
  1997. {
  1998. if ((ms->vcts) && (!(Xen_is_eq(ms->vcts[MUS_DATA_WRAPPER], Xen_undefined))))
  1999. {
  2000. vct *v;
  2001. v = Xen_to_vct(ms->vcts[MUS_DATA_WRAPPER]);
  2002. if ((v) && (len > mus_vct_length(v)))
  2003. Xen_out_of_range_error(S_set S_mus_length, 1, val, "must be <= current data size");
  2004. /* set_offset refers only to env, set_width only to square_wave et al, set_location only readin */
  2005. /* filters are protected by keeping allocated_size and not allowing arrays to be set */
  2006. }
  2007. }
  2008. mus_set_length(ptr, len);
  2009. return(val);
  2010. }
  2011. #if HAVE_SCHEME
  2012. {
  2013. s7_pointer func;
  2014. func = s7_method(s7, gen, s7_make_symbol(s7, "mus-length"));
  2015. if ((func != Xen_undefined) && (s7_procedure_setter(s7, func)))
  2016. return(s7_apply_function(s7, s7_procedure_setter(s7, func), s7_list(s7, 2, gen, val)));
  2017. }
  2018. #endif
  2019. Xen_check_type(false, gen, 1, S_set S_mus_length, "a generator");
  2020. return(val);
  2021. }
  2022. /* ---------------- oscil ---------------- */
  2023. static Xen g_make_oscil(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  2024. {
  2025. #define H_make_oscil "(" S_make_oscil " (frequency *clm-default-frequency*) (initial-phase 0.0)): return a new " S_oscil " (sinewave) generator"
  2026. mus_any *ge;
  2027. mus_float_t freq, phase = 0.0;
  2028. freq = clm_default_frequency;
  2029. if (Xen_is_bound(arg1))
  2030. {
  2031. if (!Xen_is_bound(arg2))
  2032. {
  2033. Xen_check_type(Xen_is_number(arg1), arg1, 1, S_make_oscil, "a number");
  2034. freq = Xen_real_to_C_double(arg1);
  2035. if (freq > (0.5 * mus_srate()))
  2036. Xen_out_of_range_error(S_make_oscil, 1, arg1, "freq > srate/2?");
  2037. }
  2038. else
  2039. {
  2040. int vals;
  2041. Xen args[4];
  2042. Xen keys[2];
  2043. int orig_arg[2] = {0, 0};
  2044. keys[0] = kw_frequency;
  2045. keys[1] = kw_initial_phase;
  2046. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  2047. vals = mus_optkey_unscramble(S_make_oscil, 2, keys, args, orig_arg);
  2048. if (vals > 0)
  2049. {
  2050. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_oscil, orig_arg[0], freq);
  2051. if (freq > (0.5 * mus_srate()))
  2052. Xen_out_of_range_error(S_make_oscil, orig_arg[0], keys[0], "freq > srate/2?");
  2053. phase = Xen_optkey_to_float(kw_initial_phase, keys[1], S_make_oscil, orig_arg[1], phase);
  2054. }
  2055. }
  2056. }
  2057. ge = mus_make_oscil(freq, phase);
  2058. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  2059. return(Xen_false);
  2060. }
  2061. static Xen g_oscil(Xen osc, Xen fm, Xen pm)
  2062. {
  2063. #define H_oscil "(" S_oscil " gen (fm 0.0) (pm 0.0)): next sample from " S_oscil " gen: val = sin(phase + pm); phase += (freq + fm)"
  2064. #define Q_oscil s7_make_circular_signature(s7, 2, 3, s7_make_symbol(s7, "float?"), s7_make_symbol(s7, S_is_oscil), s7_make_symbol(s7, "real?"))
  2065. mus_float_t fm1;
  2066. mus_any *g = NULL;
  2067. mus_xen *gn;
  2068. Xen_to_C_generator(osc, gn, g, mus_is_oscil, S_oscil, "an oscil");
  2069. if (!Xen_is_bound(fm))
  2070. return(C_double_to_Xen_real(mus_oscil_unmodulated(g)));
  2071. if (!Xen_is_bound(pm))
  2072. return(C_double_to_Xen_real(mus_oscil_fm(g, Xen_real_to_C_double(fm))));
  2073. fm1 = Xen_real_to_C_double(fm);
  2074. if (fm1 == 0.0)
  2075. return(C_double_to_Xen_real(mus_oscil_pm(g, Xen_real_to_C_double(pm))));
  2076. return(C_double_to_Xen_real(mus_oscil(g, fm1, Xen_real_to_C_double(pm))));
  2077. }
  2078. static Xen g_is_oscil(Xen os)
  2079. {
  2080. #define H_is_oscil "(" S_is_oscil " gen): " PROC_TRUE " if gen is an " S_oscil
  2081. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_oscil(Xen_to_mus_any(os)))));
  2082. }
  2083. static Xen g_make_oscil_bank(Xen freqs, Xen phases, Xen amps, XEN stable)
  2084. {
  2085. #define H_make_oscil_bank "(" S_make_oscil_bank " freqs phases amps stable): return a new oscil-bank generator. (freqs in radians)"
  2086. mus_any *ge = NULL;
  2087. vct *f, *p, *a = NULL;
  2088. mus_xen *gn;
  2089. Xen_check_type(mus_is_vct(freqs), freqs, 1, S_make_oscil_bank, "a " S_vct);
  2090. Xen_check_type(mus_is_vct(phases), phases, 2, S_make_oscil_bank, "a " S_vct);
  2091. Xen_check_type(Xen_is_boolean_or_unbound(stable), stable, 3, S_make_oscil_bank, "a boolean");
  2092. f = Xen_to_vct(freqs);
  2093. p = Xen_to_vct(phases);
  2094. if (mus_is_vct(amps)) a = Xen_to_vct(amps);
  2095. ge = mus_make_oscil_bank(mus_vct_length(f), mus_vct_data(f), mus_vct_data(p), (a) ? mus_vct_data(a) : NULL, Xen_is_true(stable));
  2096. /* Xen_is_true looks specifically for #t */
  2097. gn = mx_alloc(3);
  2098. gn->gen = ge;
  2099. gn->vcts[0] = freqs;
  2100. gn->vcts[1] = phases;
  2101. gn->vcts[2] = amps;
  2102. return(mus_xen_to_object(gn));
  2103. }
  2104. static Xen g_is_oscil_bank(Xen os)
  2105. {
  2106. #define H_is_oscil_bank "(" S_is_oscil_bank " gen): " PROC_TRUE " if gen is an " S_oscil_bank
  2107. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_oscil_bank(Xen_to_mus_any(os)))));
  2108. }
  2109. static Xen g_oscil_bank(Xen g)
  2110. {
  2111. #define H_oscil_bank "(" S_oscil_bank " bank): sum an array of oscils"
  2112. mus_any *ob = NULL;
  2113. mus_xen *gn;
  2114. Xen_to_C_generator(g, gn, ob, mus_is_oscil_bank, S_oscil_bank, "an oscil-bank generator");
  2115. return(C_double_to_Xen_real(mus_oscil_bank(ob)));
  2116. }
  2117. /* ---------------- delay ---------------- */
  2118. typedef enum {G_DELAY, G_COMB, G_NOTCH, G_ALL_PASS, G_FCOMB} xclm_delay_t;
  2119. static Xen g_make_delay_1(xclm_delay_t choice, Xen arglist)
  2120. {
  2121. mus_any *ge = NULL, *filt = NULL;
  2122. const char *caller = NULL;
  2123. Xen args[18];
  2124. Xen keys[9];
  2125. Xen xen_filt = Xen_false;
  2126. int orig_arg[9] = {0, 0, 0, 0, 0, 0, 0, (int)MUS_INTERP_NONE, 0};
  2127. int vals, i, argn = 0;
  2128. mus_long_t max_size = -1, size = -1;
  2129. int interp_type = (int)MUS_INTERP_NONE;
  2130. mus_float_t *line = NULL;
  2131. mus_float_t scaler = 0.0, feedback = 0.0, feedforward = 0.0;
  2132. vct *initial_contents = NULL;
  2133. Xen orig_v = Xen_false; /* initial-contents can be a vct */
  2134. mus_float_t initial_element = 0.0;
  2135. int scaler_key = -1, feedback_key = -1, feedforward_key = -1, size_key = -1, initial_contents_key = -1;
  2136. int initial_element_key = -1, max_size_key = -1, interp_type_key = -1, filter_key = -1;
  2137. switch (choice)
  2138. {
  2139. case G_DELAY: caller = S_make_delay; break;
  2140. case G_COMB: caller = S_make_comb; scaler_key = argn; keys[argn++] = kw_scaler; break;
  2141. case G_FCOMB: caller = S_make_filtered_comb; scaler_key = argn; keys[argn++] = kw_scaler; break;
  2142. case G_NOTCH: caller = S_make_notch; scaler_key = argn; keys[argn++] = kw_scaler; break;
  2143. case G_ALL_PASS:
  2144. caller = S_make_all_pass;
  2145. feedback_key = argn;
  2146. keys[argn++] = kw_feedback;
  2147. feedforward_key = argn;
  2148. keys[argn++] = kw_feedforward;
  2149. break;
  2150. }
  2151. size_key = argn; keys[argn++] = kw_size;
  2152. initial_contents_key = argn; keys[argn++] = kw_initial_contents;
  2153. initial_element_key = argn; keys[argn++] = kw_initial_element;
  2154. max_size_key = argn; keys[argn++] = kw_max_size;
  2155. interp_type_key = argn; keys[argn++] = kw_type;
  2156. filter_key = argn; keys[argn++] = kw_filter;
  2157. {
  2158. Xen p;
  2159. int a2, arglist_len;
  2160. a2 = argn * 2;
  2161. arglist_len = Xen_list_length(arglist);
  2162. if (arglist_len > a2) clm_error(caller, "too many arguments!", arglist);
  2163. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  2164. for (i = arglist_len; i < a2; i++) args[i] = Xen_undefined;
  2165. }
  2166. vals = mus_optkey_unscramble(caller, argn, keys, args, orig_arg);
  2167. if (vals > 0)
  2168. {
  2169. bool size_set = false, max_size_set = false;
  2170. /* try to catch obvious type/range errors before allocations
  2171. * a major complication here is that size can be 0
  2172. */
  2173. if (!(Xen_is_keyword(keys[size_key])))
  2174. {
  2175. size = Xen_optkey_to_mus_long_t(kw_size, keys[size_key], caller, orig_arg[size_key], size); /* size can be 0? -- surely we need a line in any case? */
  2176. if (size < 0)
  2177. Xen_out_of_range_error(caller, orig_arg[size_key], keys[size_key], "size < 0?");
  2178. if (size > mus_max_table_size())
  2179. Xen_out_of_range_error(caller, orig_arg[size_key], keys[size_key], "size too large (see mus-max-table-size)");
  2180. size_set = true;
  2181. }
  2182. if (!(Xen_is_keyword(keys[max_size_key])))
  2183. {
  2184. max_size = Xen_optkey_to_mus_long_t(kw_max_size, keys[max_size_key], caller, orig_arg[max_size_key], max_size); /* -1 = unset */
  2185. if (max_size <= 0)
  2186. Xen_out_of_range_error(caller, orig_arg[max_size_key], keys[max_size_key], "max-size <= 0?");
  2187. if (max_size > mus_max_table_size())
  2188. Xen_out_of_range_error(caller, orig_arg[max_size_key], keys[max_size_key], "max-size too large (see mus-max-table-size)");
  2189. max_size_set = true;
  2190. }
  2191. if (Xen_is_keyword(keys[interp_type_key]))
  2192. {
  2193. /* if type not given, if max_size, assume linear interp (for possible tap), else no interp */
  2194. if ((max_size_set) && (max_size != size))
  2195. interp_type = (int)MUS_INTERP_LINEAR;
  2196. else interp_type = (int)MUS_INTERP_NONE;
  2197. }
  2198. else
  2199. {
  2200. interp_type = Xen_optkey_to_int(kw_type, keys[interp_type_key], caller, orig_arg[interp_type_key], (int)MUS_INTERP_LINEAR);
  2201. if (!(mus_is_interp_type(interp_type)))
  2202. Xen_out_of_range_error(caller, orig_arg[interp_type_key], keys[interp_type_key], "no such interp-type");
  2203. }
  2204. initial_element = Xen_optkey_to_float(kw_initial_element, keys[initial_element_key], caller, orig_arg[initial_element_key], initial_element);
  2205. switch (choice)
  2206. {
  2207. case G_DELAY:
  2208. break;
  2209. case G_COMB: case G_NOTCH: case G_FCOMB:
  2210. scaler = Xen_optkey_to_float(kw_scaler, keys[scaler_key], caller, orig_arg[scaler_key], scaler);
  2211. break;
  2212. case G_ALL_PASS:
  2213. feedback = Xen_optkey_to_float(kw_feedback, keys[feedback_key], caller, orig_arg[feedback_key], feedback);
  2214. feedforward = Xen_optkey_to_float(kw_feedforward, keys[feedforward_key], caller, orig_arg[feedforward_key], feedforward);
  2215. break;
  2216. }
  2217. if (!(Xen_is_keyword(keys[filter_key])))
  2218. {
  2219. if (choice != G_FCOMB)
  2220. clm_error(caller, "filter arg passed??", keys[filter_key]);
  2221. Xen_check_type(mus_is_xen(keys[filter_key]), keys[filter_key], orig_arg[filter_key], caller, "filter arg must be a generator");
  2222. xen_filt = keys[filter_key];
  2223. filt = Xen_to_mus_any(xen_filt);
  2224. }
  2225. if (!(Xen_is_keyword(keys[initial_contents_key])))
  2226. {
  2227. if (!(Xen_is_keyword(keys[initial_element_key])))
  2228. Xen_out_of_range_error(caller,
  2229. orig_arg[initial_contents_key],
  2230. keys[initial_contents_key],
  2231. "initial-contents and initial-element in same call?");
  2232. if (mus_is_vct(keys[initial_contents_key]))
  2233. {
  2234. initial_contents = Xen_to_vct(keys[initial_contents_key]);
  2235. orig_v = keys[initial_contents_key];
  2236. }
  2237. else
  2238. {
  2239. if (Xen_is_list(keys[initial_contents_key]))
  2240. {
  2241. int len;
  2242. len = Xen_list_length(keys[initial_contents_key]);
  2243. if (len <= 0)
  2244. Xen_error(NO_DATA,
  2245. Xen_list_2(C_string_to_Xen_string("~A: initial-contents not a proper list?"),
  2246. C_string_to_Xen_string(caller)));
  2247. orig_v = xen_list_to_vct(keys[initial_contents_key]);
  2248. initial_contents = Xen_to_vct(orig_v);
  2249. /* do I need to protect this until we read its contents? -- no extlang stuff except error returns */
  2250. }
  2251. else Xen_check_type(Xen_is_false(keys[initial_contents_key]),
  2252. keys[initial_contents_key],
  2253. orig_arg[initial_contents_key],
  2254. caller, "a " S_vct " or a list");
  2255. }
  2256. if (initial_contents)
  2257. {
  2258. if (size_set)
  2259. {
  2260. if (size > mus_vct_length(initial_contents))
  2261. Xen_out_of_range_error(caller, orig_arg[initial_contents_key], keys[initial_contents_key], "size > initial-contents length");
  2262. }
  2263. else size = mus_vct_length(initial_contents);
  2264. if (max_size_set)
  2265. {
  2266. if (max_size > mus_vct_length(initial_contents))
  2267. Xen_out_of_range_error(caller, orig_arg[initial_contents_key], keys[initial_contents_key], "max-size > initial-contents length");
  2268. }
  2269. else max_size = mus_vct_length(initial_contents);
  2270. }
  2271. }
  2272. }
  2273. /* here size can be (user-set to) 0, but max_size needs to be a reasonable allocation size */
  2274. if (size < 0) size = 1;
  2275. if (max_size < size)
  2276. {
  2277. if (size == 0)
  2278. max_size = 1;
  2279. else max_size = size;
  2280. }
  2281. if (initial_contents == NULL)
  2282. {
  2283. line = (mus_float_t *)malloc(max_size * sizeof(mus_float_t));
  2284. if (line == NULL)
  2285. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate delay line", caller));
  2286. orig_v = xen_make_vct(max_size, line);
  2287. if (initial_element != 0.0)
  2288. {
  2289. for (i = 0; i < max_size; i++)
  2290. line[i] = initial_element;
  2291. }
  2292. else memset((void *)line, 0, max_size * sizeof(mus_float_t));
  2293. }
  2294. else
  2295. {
  2296. line = mus_vct_data(initial_contents);
  2297. }
  2298. {
  2299. mus_error_handler_t *old_error_handler;
  2300. old_error_handler = mus_error_set_handler(local_mus_error);
  2301. switch (choice)
  2302. {
  2303. case G_DELAY: ge = mus_make_delay(size, line, max_size, (mus_interp_t)interp_type); break;
  2304. case G_COMB: ge = mus_make_comb(scaler, size, line, max_size, (mus_interp_t)interp_type); break;
  2305. case G_NOTCH: ge = mus_make_notch(scaler, size, line, max_size, (mus_interp_t)interp_type); break;
  2306. case G_ALL_PASS: ge = mus_make_all_pass(feedback, feedforward, size, line, max_size, (mus_interp_t)interp_type); break;
  2307. case G_FCOMB: ge = mus_make_filtered_comb(scaler, size, line, max_size, (mus_interp_t)interp_type, filt); break;
  2308. }
  2309. mus_error_set_handler(old_error_handler);
  2310. }
  2311. if (ge)
  2312. {
  2313. if (choice != G_FCOMB)
  2314. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  2315. return(mus_xen_to_object(mus_any_to_mus_xen_with_two_vcts(ge, orig_v, xen_filt)));
  2316. }
  2317. return(clm_mus_error(local_error_type, local_error_msg, caller));
  2318. }
  2319. static Xen g_make_delay(Xen args)
  2320. {
  2321. #define H_make_delay "(" S_make_delay " (size) (initial-contents) (initial-element 0.0) (max-size) (type mus-interp-linear)): \
  2322. return a new delay line of size elements. \
  2323. If the delay length will be changing at run-time, max-size sets its maximum length, so\n\
  2324. (" S_make_delay " len :max-size (+ len 10))\n\
  2325. provides 10 extra elements of delay for subsequent phasing or flanging. \
  2326. initial-contents can be either a list or a " S_vct "."
  2327. if ((Xen_is_pair(args)) && (!Xen_is_pair(Xen_cdr(args))))
  2328. {
  2329. Xen val, v;
  2330. mus_any *ge;
  2331. mus_long_t size, max_size;
  2332. mus_float_t *line;
  2333. mus_error_handler_t *old_error_handler;
  2334. val = Xen_car(args);
  2335. Xen_check_type(Xen_is_integer(val), val, 1, S_make_delay, "an integer");
  2336. size = Xen_integer_to_C_int(val);
  2337. if (size < 0)
  2338. Xen_out_of_range_error(S_make_delay, 1, val, "size < 0?");
  2339. if (size > mus_max_table_size())
  2340. Xen_out_of_range_error(S_make_delay, 1, val, "size too large (see mus-max-table-size)");
  2341. if (size == 0) max_size = 1; else max_size = size;
  2342. line = (mus_float_t *)calloc(max_size, sizeof(mus_float_t));
  2343. v = xen_make_vct(max_size, line); /* we need this for mus-data */
  2344. old_error_handler = mus_error_set_handler(local_mus_error);
  2345. ge = mus_make_delay(size, line, max_size, MUS_INTERP_NONE);
  2346. mus_error_set_handler(old_error_handler);
  2347. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, v)));
  2348. return(clm_mus_error(local_error_type, local_error_msg, S_make_delay));
  2349. }
  2350. return(g_make_delay_1(G_DELAY, args));
  2351. }
  2352. static Xen g_make_comb(Xen args)
  2353. {
  2354. #define H_make_comb "(" S_make_comb " (scaler) (size) (initial-contents) (initial-element 0.0) (max-size) (type " S_mus_interp_linear ")): \
  2355. return a new comb filter (a delay line with a scaler on the feedback) of size elements. \
  2356. If the comb length will be changing at run-time, max-size sets its maximum length. \
  2357. initial-contents can be either a list or a " S_vct "."
  2358. return(g_make_delay_1(G_COMB, args));
  2359. }
  2360. static Xen g_make_filtered_comb(Xen args)
  2361. {
  2362. #define H_make_filtered_comb "(" S_make_filtered_comb " (scaler) (size) (initial-contents) (initial-element 0.0) (max-size) (type " S_mus_interp_linear ") :filter): \
  2363. return a new filtered comb filter (a delay line with a scaler and a filter on the feedback) of size elements. \
  2364. If the comb length will be changing at run-time, max-size sets its maximum length. \
  2365. initial-contents can be either a list or a " S_vct "."
  2366. return(g_make_delay_1(G_FCOMB, args));
  2367. }
  2368. static Xen g_make_notch(Xen args)
  2369. {
  2370. #define H_make_notch "(" S_make_notch " (scaler) (size) (initial-contents) (initial-element 0.0) (max-size) (type " S_mus_interp_linear ")): \
  2371. return a new notch filter (a delay line with a scaler on the feedforward) of size elements. \
  2372. If the notch length will be changing at run-time, max-size sets its maximum length. \
  2373. initial-contents can be either a list or a " S_vct "."
  2374. return(g_make_delay_1(G_NOTCH, args));
  2375. }
  2376. static Xen g_make_all_pass(Xen args)
  2377. {
  2378. #define H_make_all_pass "(" S_make_all_pass " (feedback) (feedforward) (size) (initial-contents) (initial-element 0.0) (max-size) (type " S_mus_interp_linear ")): \
  2379. return a new allpass filter (a delay line with a scalers on both the feedback and the feedforward). \
  2380. If the " S_all_pass " length will be changing at run-time, max-size sets its maximum length. \
  2381. initial-contents can be either a list or a " S_vct "."
  2382. return(g_make_delay_1(G_ALL_PASS, args));
  2383. }
  2384. typedef enum {G_MOVING_AVERAGE, G_MOVING_MAX, G_MOVING_NORM} xclm_moving_t;
  2385. static Xen g_make_moving_any(xclm_moving_t choice, const char *caller, Xen arglist)
  2386. {
  2387. mus_any *ge = NULL;
  2388. Xen args[8];
  2389. Xen keys[4];
  2390. int orig_arg[4] = {0, 0, 0, 0};
  2391. int vals, i, argn = 0, arglist_len;
  2392. mus_long_t size = -1;
  2393. mus_float_t scaler = 1.0, sum = 0.0;
  2394. vct *initial_contents = NULL;
  2395. Xen orig_v = Xen_false, p;
  2396. mus_float_t initial_element = 0.0;
  2397. mus_float_t *line = NULL;
  2398. int scaler_key = -1, size_key, initial_contents_key, initial_element_key;
  2399. mus_error_handler_t *old_error_handler;
  2400. size_key = argn;
  2401. keys[argn++] = kw_size;
  2402. if (choice == G_MOVING_NORM)
  2403. {
  2404. scaler_key = argn;
  2405. keys[argn++] = kw_scaler;
  2406. }
  2407. initial_contents_key = argn;
  2408. keys[argn++] = kw_initial_contents;
  2409. initial_element_key = argn;
  2410. keys[argn++] = kw_initial_element;
  2411. arglist_len = Xen_list_length(arglist);
  2412. if (arglist_len > 8) clm_error(caller, "too many arguments!", arglist);
  2413. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  2414. for (i = arglist_len; i < argn * 2; i++) args[i] = Xen_undefined;
  2415. vals = mus_optkey_unscramble(caller, argn, keys, args, orig_arg);
  2416. if (vals > 0)
  2417. {
  2418. bool size_set = false;
  2419. if (!(Xen_is_keyword(keys[size_key])))
  2420. {
  2421. size = Xen_optkey_to_mus_long_t(kw_size, keys[size_key], caller, orig_arg[size_key], size); /* size can be 0? -- surely we need a line in any case? */
  2422. if (size < 0)
  2423. Xen_out_of_range_error(caller, orig_arg[size_key], keys[size_key], "size < 0?");
  2424. if (size > mus_max_table_size())
  2425. Xen_out_of_range_error(caller, orig_arg[size_key], keys[size_key], "size too large (see mus-max-table-size)");
  2426. size_set = true;
  2427. }
  2428. if (choice == G_MOVING_NORM)
  2429. scaler = Xen_optkey_to_float(kw_scaler, keys[scaler_key], caller, orig_arg[scaler_key], scaler);
  2430. initial_element = Xen_optkey_to_float(kw_initial_element, keys[initial_element_key], caller, orig_arg[initial_element_key], initial_element);
  2431. if (!(Xen_is_keyword(keys[initial_contents_key])))
  2432. {
  2433. if (!(Xen_is_keyword(keys[initial_element_key])))
  2434. Xen_out_of_range_error(caller,
  2435. orig_arg[initial_contents_key],
  2436. keys[initial_contents_key],
  2437. "initial-contents and initial-element in same call?");
  2438. if (mus_is_vct(keys[initial_contents_key]))
  2439. {
  2440. initial_contents = Xen_to_vct(keys[initial_contents_key]);
  2441. orig_v = keys[initial_contents_key];
  2442. }
  2443. else
  2444. {
  2445. if (Xen_is_list(keys[initial_contents_key]))
  2446. {
  2447. int len;
  2448. len = Xen_list_length(keys[initial_contents_key]);
  2449. if (len <= 0)
  2450. Xen_error(NO_DATA,
  2451. Xen_list_2(C_string_to_Xen_string("~A: initial-contents not a proper list?"),
  2452. C_string_to_Xen_string(caller)));
  2453. orig_v = xen_list_to_vct(keys[initial_contents_key]);
  2454. initial_contents = Xen_to_vct(orig_v);
  2455. /* do I need to protect this until we read its contents? -- no extlang stuff except error returns */
  2456. }
  2457. else Xen_check_type(Xen_is_false(keys[initial_contents_key]),
  2458. keys[initial_contents_key],
  2459. orig_arg[initial_contents_key],
  2460. caller, "a " S_vct " or a list");
  2461. }
  2462. if (initial_contents)
  2463. {
  2464. if (size_set)
  2465. {
  2466. if (size > mus_vct_length(initial_contents))
  2467. Xen_out_of_range_error(caller, orig_arg[initial_contents_key], keys[initial_contents_key], "size > initial-contents length");
  2468. }
  2469. else size = mus_vct_length(initial_contents);
  2470. }
  2471. }
  2472. }
  2473. if (size < 0) size = 1;
  2474. if (size == 0)
  2475. Xen_out_of_range_error(caller, 0, C_llong_to_Xen_llong(size), "size = 0?");
  2476. if (initial_contents == NULL)
  2477. {
  2478. line = (mus_float_t *)malloc(size * sizeof(mus_float_t));
  2479. if (line == NULL)
  2480. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate delay line", caller));
  2481. orig_v = xen_make_vct(size, line);
  2482. if (initial_element != 0.0)
  2483. {
  2484. for (i = 0; i < size; i++)
  2485. line[i] = initial_element;
  2486. sum = initial_element * size;
  2487. }
  2488. else memset((void *)line, 0, size * sizeof(mus_float_t));
  2489. }
  2490. else
  2491. {
  2492. line = mus_vct_data(initial_contents);
  2493. if ((line) && (choice == G_MOVING_AVERAGE))
  2494. {
  2495. sum = line[0];
  2496. for (i = 1; i < size; i++)
  2497. sum += line[i];
  2498. }
  2499. }
  2500. old_error_handler = mus_error_set_handler(local_mus_error);
  2501. switch (choice)
  2502. {
  2503. case G_MOVING_AVERAGE: ge = mus_make_moving_average_with_initial_sum(size, line, sum); break;
  2504. case G_MOVING_MAX: ge = mus_make_moving_max(size, line); break;
  2505. case G_MOVING_NORM: ge = mus_make_moving_norm(size, line, scaler); break;
  2506. }
  2507. mus_error_set_handler(old_error_handler);
  2508. if (ge)
  2509. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  2510. return(clm_mus_error(local_error_type, local_error_msg, caller));
  2511. }
  2512. static Xen g_make_moving_average(Xen args)
  2513. {
  2514. #define H_make_moving_average "(" S_make_moving_average " (size) (initial-contents) (initial-element 0.0)): \
  2515. return a new moving_average generator. initial-contents can be either a list or a " S_vct "."
  2516. return(g_make_moving_any(G_MOVING_AVERAGE, S_make_moving_average, args));
  2517. }
  2518. static Xen g_make_moving_max(Xen args)
  2519. {
  2520. #define H_make_moving_max "(" S_make_moving_max " (size) (initial-contents) (initial-element 0.0)): \
  2521. return a new moving-max generator. initial-contents can be either a list or a " S_vct "."
  2522. return(g_make_moving_any(G_MOVING_MAX, S_make_moving_max, args));
  2523. }
  2524. static Xen g_make_moving_norm(Xen args)
  2525. {
  2526. #define H_make_moving_norm "(" S_make_moving_norm " (size (scaler 1.0))): return a new moving-norm generator."
  2527. return(g_make_moving_any(G_MOVING_NORM, S_make_moving_norm, args));
  2528. }
  2529. static Xen g_delay(Xen obj, Xen input, Xen pm)
  2530. {
  2531. #define H_delay "(" S_delay " gen (val 0.0) (pm 0.0)): \
  2532. delay val according to the delay line's length and pm ('phase-modulation'). \
  2533. If pm is greater than 0.0, the max-size argument used to create gen should have accommodated its maximum value."
  2534. mus_any *g = NULL;
  2535. mus_xen *gn;
  2536. Xen_to_C_generator(obj, gn, g, mus_is_delay, S_delay, "a delay line");
  2537. if (!Xen_is_bound(input))
  2538. return(C_double_to_Xen_real(mus_delay_unmodulated(g, 0.0)));
  2539. if (!Xen_is_bound(pm))
  2540. return(C_double_to_Xen_real(mus_delay_unmodulated(g, Xen_real_to_C_double(input))));
  2541. return(C_double_to_Xen_real(mus_delay(g, Xen_real_to_C_double(input), Xen_real_to_C_double(pm))));
  2542. }
  2543. static Xen g_delay_tick(Xen obj, Xen input)
  2544. {
  2545. #define H_delay_tick "(" S_delay_tick " gen (val 0.0)): \
  2546. delay val according to the delay line's length. This merely 'ticks' the delay line forward.\
  2547. The argument 'val' is returned."
  2548. mus_float_t in1 = 0.0;
  2549. mus_any *g = NULL;
  2550. mus_xen *gn;
  2551. Xen_to_C_generator(obj, gn, g, mus_is_delay, S_delay_tick, "a delay line");
  2552. Xen_real_to_C_double_if_bound(input, in1, S_delay_tick, 2);
  2553. return(C_double_to_Xen_real(mus_delay_tick(g, in1)));
  2554. }
  2555. static Xen g_notch(Xen obj, Xen input, Xen pm)
  2556. {
  2557. #define H_notch "(" S_notch " gen (val 0.0) (pm 0.0)): notch filter val, pm changes the delay length."
  2558. mus_float_t in1 = 0.0, pm1 = 0.0;
  2559. mus_any *g = NULL;
  2560. mus_xen *gn;
  2561. Xen_to_C_generator(obj, gn, g, mus_is_notch, S_notch, "a notch filter");
  2562. Xen_real_to_C_double_if_bound(input, in1, S_notch, 2);
  2563. Xen_real_to_C_double_if_bound(pm, pm1, S_notch, 3);
  2564. return(C_double_to_Xen_real(mus_notch(g, in1, pm1)));
  2565. }
  2566. static Xen g_comb(Xen obj, Xen input, Xen pm)
  2567. {
  2568. #define H_comb "(" S_comb " gen (val 0.0) (pm 0.0)): comb filter val, pm changes the delay length."
  2569. mus_float_t in1 = 0.0, pm1 = 0.0;
  2570. mus_any *g = NULL;
  2571. mus_xen *gn;
  2572. Xen_to_C_generator(obj, gn, g, mus_is_comb, S_comb, "a comb generator");
  2573. Xen_real_to_C_double_if_bound(input, in1, S_comb, 2);
  2574. Xen_real_to_C_double_if_bound(pm, pm1, S_comb, 3);
  2575. return(C_double_to_Xen_real(mus_comb(g, in1, pm1)));
  2576. }
  2577. static Xen g_make_comb_bank(Xen arg)
  2578. {
  2579. #define H_make_comb_bank "(" S_make_comb_bank " gens): return a new comb-bank generator."
  2580. mus_any *ge = NULL;
  2581. mus_any **gens;
  2582. int i, j, size;
  2583. Xen_check_type(Xen_is_vector(arg), arg, 1, S_make_comb_bank, "a vector of comb generators");
  2584. size = Xen_vector_length(arg);
  2585. if (size == 0) return(Xen_false);
  2586. gens = (mus_any **)calloc(size, sizeof(mus_any *));
  2587. for (i = 0, j = 0; i < size; i++)
  2588. {
  2589. Xen g;
  2590. g = Xen_vector_ref(arg, i);
  2591. if (mus_is_xen(g))
  2592. {
  2593. mus_any *fg;
  2594. fg = Xen_to_mus_any(g);
  2595. if (mus_is_comb(fg))
  2596. gens[j++] = fg;
  2597. }
  2598. }
  2599. if (j > 0)
  2600. ge = mus_make_comb_bank(j, gens);
  2601. free(gens);
  2602. if (ge)
  2603. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, arg)));
  2604. return(Xen_false);
  2605. }
  2606. static Xen g_is_comb_bank(Xen os)
  2607. {
  2608. #define H_is_comb_bank "(" S_is_comb_bank " gen): " PROC_TRUE " if gen is a " S_comb_bank
  2609. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_comb_bank(Xen_to_mus_any(os)))));
  2610. }
  2611. static Xen g_comb_bank(Xen gens, Xen inp)
  2612. {
  2613. #define H_comb_bank "(" S_comb_bank " bank inval): sum an array of " S_comb " filters."
  2614. mus_any *bank = NULL;
  2615. mus_xen *gn;
  2616. mus_float_t x = 0.0;
  2617. Xen_to_C_generator(gens, gn, bank, mus_is_comb_bank, S_comb_bank, "a comb-bank generator");
  2618. Xen_real_to_C_double_if_bound(inp, x, S_comb_bank, 2);
  2619. return(C_double_to_Xen_real(mus_comb_bank(bank, x)));
  2620. }
  2621. static Xen g_filtered_comb(Xen obj, Xen input, Xen pm)
  2622. {
  2623. #define H_filtered_comb "(" S_filtered_comb " gen (val 0.0) (pm 0.0)): filtered comb filter val, pm changes the delay length."
  2624. mus_float_t in1 = 0.0, pm1 = 0.0;
  2625. mus_any *g = NULL;
  2626. mus_xen *gn;
  2627. Xen_to_C_generator(obj, gn, g, mus_is_filtered_comb, S_filtered_comb, "a filtered-comb generator");
  2628. Xen_real_to_C_double_if_bound(input, in1, S_filtered_comb, 2);
  2629. Xen_real_to_C_double_if_bound(pm, pm1, S_filtered_comb, 3);
  2630. return(C_double_to_Xen_real(mus_filtered_comb(g, in1, pm1)));
  2631. }
  2632. static Xen g_make_filtered_comb_bank(Xen arg)
  2633. {
  2634. #define H_make_filtered_comb_bank "(" S_make_filtered_comb_bank " gens): return a new filtered_comb-bank generator."
  2635. mus_any *ge = NULL;
  2636. mus_any **gens;
  2637. int i, j, size;
  2638. Xen_check_type(Xen_is_vector(arg), arg, 1, S_make_filtered_comb_bank, "a vector of filtered_comb generators");
  2639. size = Xen_vector_length(arg);
  2640. if (size == 0) return(Xen_false);
  2641. gens = (mus_any **)calloc(size, sizeof(mus_any *));
  2642. for (i = 0, j = 0; i < size; i++)
  2643. {
  2644. Xen g;
  2645. g = Xen_vector_ref(arg, i);
  2646. if (mus_is_xen(g))
  2647. {
  2648. mus_any *fg;
  2649. fg = Xen_to_mus_any(g);
  2650. if (mus_is_filtered_comb(fg))
  2651. gens[j++] = fg;
  2652. }
  2653. }
  2654. if (j > 0)
  2655. ge = mus_make_filtered_comb_bank(j, gens);
  2656. free(gens);
  2657. if (ge)
  2658. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, arg)));
  2659. return(Xen_false);
  2660. }
  2661. static Xen g_is_filtered_comb_bank(Xen os)
  2662. {
  2663. #define H_is_filtered_comb_bank "(" S_is_filtered_comb_bank " gen): " PROC_TRUE " if gen is a " S_filtered_comb_bank
  2664. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_filtered_comb_bank(Xen_to_mus_any(os)))));
  2665. }
  2666. static Xen g_filtered_comb_bank(Xen gens, Xen inp)
  2667. {
  2668. #define H_filtered_comb_bank "(" S_filtered_comb_bank " bank inval): sum an array of " S_filtered_comb " filters."
  2669. mus_any *bank = NULL;
  2670. mus_xen *gn;
  2671. mus_float_t x = 0.0;
  2672. Xen_to_C_generator(gens, gn, bank, mus_is_filtered_comb_bank, S_filtered_comb_bank, "a filtered-comb-bank generator");
  2673. Xen_real_to_C_double_if_bound(inp, x, S_filtered_comb_bank, 2);
  2674. return(C_double_to_Xen_real(mus_filtered_comb_bank(bank, x)));
  2675. }
  2676. static Xen g_all_pass(Xen obj, Xen input, Xen pm)
  2677. {
  2678. #define H_all_pass "(" S_all_pass " gen (val 0.0) (pm 0.0)): all-pass filter val, pm changes the delay length."
  2679. mus_float_t in1 = 0.0, pm1 = 0.0;
  2680. mus_any *g = NULL;
  2681. mus_xen *gn;
  2682. Xen_to_C_generator(obj, gn, g, mus_is_all_pass, S_all_pass, "an all-pass filter");
  2683. Xen_real_to_C_double_if_bound(input, in1, S_all_pass, 2);
  2684. Xen_real_to_C_double_if_bound(pm, pm1, S_all_pass, 3);
  2685. return(C_double_to_Xen_real(mus_all_pass(g, in1, pm1)));
  2686. }
  2687. static Xen g_make_all_pass_bank(Xen arg)
  2688. {
  2689. #define H_make_all_pass_bank "(" S_make_all_pass_bank " gens): return a new all_pass-bank generator."
  2690. mus_any *ge = NULL;
  2691. mus_any **gens;
  2692. int i, j, size;
  2693. Xen_check_type(Xen_is_vector(arg), arg, 1, S_make_all_pass_bank, "a vector of all_pass generators");
  2694. size = Xen_vector_length(arg);
  2695. if (size == 0) return(Xen_false);
  2696. gens = (mus_any **)calloc(size, sizeof(mus_any *));
  2697. for (i = 0, j = 0; i < size; i++)
  2698. {
  2699. Xen g;
  2700. g = Xen_vector_ref(arg, i);
  2701. if (mus_is_xen(g))
  2702. {
  2703. mus_any *fg;
  2704. fg = Xen_to_mus_any(g);
  2705. if (mus_is_all_pass(fg))
  2706. gens[j++] = fg;
  2707. }
  2708. }
  2709. if (j > 0)
  2710. ge = mus_make_all_pass_bank(j, gens);
  2711. free(gens);
  2712. if (ge)
  2713. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, arg)));
  2714. return(Xen_false);
  2715. }
  2716. static Xen g_is_all_pass_bank(Xen os)
  2717. {
  2718. #define H_is_all_pass_bank "(" S_is_all_pass_bank " gen): " PROC_TRUE " if gen is a " S_all_pass_bank
  2719. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_all_pass_bank(Xen_to_mus_any(os)))));
  2720. }
  2721. static Xen g_all_pass_bank(Xen gens, Xen inp)
  2722. {
  2723. #define H_all_pass_bank "(" S_all_pass_bank " bank inval): sum an array of " S_all_pass " filters."
  2724. mus_any *bank = NULL;
  2725. mus_xen *gn;
  2726. mus_float_t x = 0.0;
  2727. Xen_to_C_generator(gens, gn, bank, mus_is_all_pass_bank, S_all_pass_bank, "an all-pass-bank generator");
  2728. Xen_real_to_C_double_if_bound(inp, x, S_all_pass_bank, 2);
  2729. return(C_double_to_Xen_real(mus_all_pass_bank(bank, x)));
  2730. }
  2731. static Xen g_moving_average(Xen obj, Xen input)
  2732. {
  2733. #define H_moving_average "(" S_moving_average " gen (val 0.0)): moving window average."
  2734. mus_float_t in1 = 0.0;
  2735. mus_any *g = NULL;
  2736. mus_xen *gn;
  2737. Xen_to_C_generator(obj, gn, g, mus_is_moving_average, S_moving_average, "a moving-average generator");
  2738. Xen_real_to_C_double_if_bound(input, in1, S_moving_average, 2);
  2739. return(C_double_to_Xen_real(mus_moving_average(g, in1)));
  2740. }
  2741. static Xen g_moving_max(Xen obj, Xen input)
  2742. {
  2743. #define H_moving_max "(" S_moving_max " gen (val 0.0)): moving window max."
  2744. mus_float_t in1 = 0.0;
  2745. mus_any *g = NULL;
  2746. mus_xen *gn;
  2747. Xen_to_C_generator(obj, gn, g, mus_is_moving_max, S_moving_max, "a moving-max generator");
  2748. Xen_real_to_C_double_if_bound(input, in1, S_moving_max, 2);
  2749. return(C_double_to_Xen_real(mus_moving_max(g, in1)));
  2750. }
  2751. static Xen g_moving_norm(Xen obj, Xen input)
  2752. {
  2753. #define H_moving_norm "(" S_moving_norm " gen (val 0.0)): moving window norm."
  2754. mus_float_t in1 = 0.0;
  2755. mus_any *g = NULL;
  2756. mus_xen *gn;
  2757. Xen_to_C_generator(obj, gn, g, mus_is_moving_norm, S_moving_norm, "a moving-norm generator");
  2758. Xen_real_to_C_double_if_bound(input, in1, S_moving_norm, 2);
  2759. return(C_double_to_Xen_real(mus_moving_norm(g, in1)));
  2760. }
  2761. static Xen g_tap(Xen obj, Xen loc)
  2762. {
  2763. #define H_tap "(" S_tap " gen (pm 0.0)): tap the " S_delay " generator offset by pm"
  2764. mus_float_t dloc = 0.0;
  2765. mus_any *g = NULL;
  2766. mus_xen *gn;
  2767. Xen_to_C_generator(obj, gn, g, mus_is_tap, S_tap, "a delay line tap");
  2768. Xen_real_to_C_double_if_bound(loc, dloc, S_tap, 3);
  2769. return(C_double_to_Xen_real(mus_tap(g, dloc)));
  2770. }
  2771. static Xen g_is_tap(Xen obj)
  2772. {
  2773. #define H_is_tap "(" S_is_tap " gen): " PROC_TRUE " if gen is a delay line tap"
  2774. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_tap(Xen_to_mus_any(obj)))));
  2775. }
  2776. static Xen g_is_delay(Xen obj)
  2777. {
  2778. #define H_is_delay "(" S_is_delay " gen): " PROC_TRUE " if gen is a delay line"
  2779. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_delay(Xen_to_mus_any(obj)))));
  2780. }
  2781. static Xen g_is_comb(Xen obj)
  2782. {
  2783. #define H_is_comb "(" S_is_comb " gen): " PROC_TRUE " if gen is a comb filter"
  2784. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_comb(Xen_to_mus_any(obj)))));
  2785. }
  2786. static Xen g_is_filtered_comb(Xen obj)
  2787. {
  2788. #define H_is_filtered_comb "(" S_is_filtered_comb " gen): " PROC_TRUE " if gen is a filtered-comb filter"
  2789. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_filtered_comb(Xen_to_mus_any(obj)))));
  2790. }
  2791. static Xen g_is_notch(Xen obj)
  2792. {
  2793. #define H_is_notch "(" S_is_notch " gen): " PROC_TRUE " if gen is a notch filter"
  2794. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_notch(Xen_to_mus_any(obj)))));
  2795. }
  2796. static Xen g_is_all_pass(Xen obj)
  2797. {
  2798. #define H_is_all_pass "(" S_is_all_pass " gen): " PROC_TRUE " if gen is an all-pass filter"
  2799. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_all_pass(Xen_to_mus_any(obj)))));
  2800. }
  2801. static Xen g_is_moving_average(Xen obj)
  2802. {
  2803. #define H_is_moving_average "(" S_is_moving_average " gen): " PROC_TRUE " if gen is a moving-average generator"
  2804. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_moving_average(Xen_to_mus_any(obj)))));
  2805. }
  2806. static Xen g_is_moving_max(Xen obj)
  2807. {
  2808. #define H_is_moving_max "(" S_is_moving_max " gen): " PROC_TRUE " if gen is a moving-max generator"
  2809. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_moving_max(Xen_to_mus_any(obj)))));
  2810. }
  2811. static Xen g_is_moving_norm(Xen obj)
  2812. {
  2813. #define H_is_moving_norm "(" S_is_moving_norm " gen): " PROC_TRUE " if gen is a moving-norm generator"
  2814. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_moving_norm(Xen_to_mus_any(obj)))));
  2815. }
  2816. /* -------- ncos -------- */
  2817. static Xen g_is_ncos(Xen obj)
  2818. {
  2819. #define H_is_ncos "(" S_is_ncos " gen): " PROC_TRUE " if gen is an " S_ncos " generator"
  2820. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  2821. (mus_is_ncos(Xen_to_mus_any(obj)))));
  2822. }
  2823. static Xen g_make_ncos(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  2824. {
  2825. #define H_make_ncos "(" S_make_ncos " (frequency *clm-default-frequency*) (n 1)): \
  2826. return a new " S_ncos " generator, producing a sum of 'n' equal amplitude cosines."
  2827. mus_any *ge;
  2828. Xen args[4];
  2829. Xen keys[2];
  2830. int orig_arg[2] = {0, 0};
  2831. int vals, n = 1;
  2832. mus_float_t freq;
  2833. freq = clm_default_frequency;
  2834. keys[0] = kw_frequency;
  2835. keys[1] = kw_n;
  2836. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  2837. vals = mus_optkey_unscramble(S_make_ncos, 2, keys, args, orig_arg);
  2838. if (vals > 0)
  2839. {
  2840. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_ncos, orig_arg[0], freq);
  2841. if (freq > (0.5 * mus_srate()))
  2842. Xen_out_of_range_error(S_make_ncos, orig_arg[0], keys[0], "freq > srate/2?");
  2843. n = Xen_optkey_to_int(kw_n, keys[1], S_make_ncos, orig_arg[1], n);
  2844. if (n <= 0)
  2845. Xen_out_of_range_error(S_make_ncos, orig_arg[1], keys[1], "n <= 0?");
  2846. }
  2847. ge = mus_make_ncos(freq, n);
  2848. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  2849. return(Xen_false);
  2850. }
  2851. static Xen g_ncos(Xen obj, Xen fm)
  2852. {
  2853. #define H_ncos "(" S_ncos " gen (fm 0.0)): get the next sample from 'gen', an " S_ncos " generator"
  2854. mus_float_t fm1 = 0.0;
  2855. mus_any *g = NULL;
  2856. mus_xen *gn;
  2857. Xen_to_C_generator(obj, gn, g, mus_is_ncos, S_ncos, "an ncos generator");
  2858. Xen_real_to_C_double_if_bound(fm, fm1, S_ncos, 2);
  2859. return(C_double_to_Xen_real(mus_ncos(g, fm1)));
  2860. }
  2861. /* -------- nsin -------- */
  2862. static Xen g_is_nsin(Xen obj)
  2863. {
  2864. #define H_is_nsin "(" S_is_nsin " gen): " PROC_TRUE " if gen is an " S_nsin " generator"
  2865. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  2866. (mus_is_nsin(Xen_to_mus_any(obj)))));
  2867. }
  2868. static Xen g_make_nsin(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  2869. {
  2870. #define H_make_nsin "(" S_make_nsin " (frequency *clm-default-frequency*) (n 1)): \
  2871. return a new " S_nsin " generator, producing a sum of 'n' equal amplitude sines"
  2872. mus_any *ge;
  2873. Xen args[4];
  2874. Xen keys[2];
  2875. int orig_arg[2] = {0, 0};
  2876. int vals, n = 1;
  2877. mus_float_t freq;
  2878. freq = clm_default_frequency;
  2879. keys[0] = kw_frequency;
  2880. keys[1] = kw_n;
  2881. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  2882. vals = mus_optkey_unscramble(S_make_nsin, 2, keys, args, orig_arg);
  2883. if (vals > 0)
  2884. {
  2885. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_nsin, orig_arg[0], freq);
  2886. if (freq > (0.5 * mus_srate()))
  2887. Xen_out_of_range_error(S_make_nsin, orig_arg[0], keys[0], "freq > srate/2?");
  2888. n = Xen_optkey_to_int(kw_n, keys[1], S_make_nsin, orig_arg[1], n);
  2889. if (n <= 0)
  2890. Xen_out_of_range_error(S_make_nsin, orig_arg[1], keys[1], "n <= 0?");
  2891. }
  2892. ge = mus_make_nsin(freq, n);
  2893. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  2894. return(Xen_false);
  2895. }
  2896. static Xen g_nsin(Xen obj, Xen fm)
  2897. {
  2898. #define H_nsin "(" S_nsin " gen (fm 0.0)): get the next sample from 'gen', an " S_nsin " generator"
  2899. mus_float_t fm1 = 0.0;
  2900. mus_any *g = NULL;
  2901. mus_xen *gn;
  2902. Xen_to_C_generator(obj, gn, g, mus_is_nsin, S_nsin, "an nsin generator");
  2903. Xen_real_to_C_double_if_bound(fm, fm1, S_nsin, 2);
  2904. return(C_double_to_Xen_real(mus_nsin(g, fm1)));
  2905. }
  2906. /* ---------------- rand, rand_interp ---------------- */
  2907. #define RANDOM_DISTRIBUTION_TABLE_SIZE 512
  2908. #define RANDOM_DISTRIBUTION_ENVELOPE_SIZE 50
  2909. static mus_float_t *inverse_integrate(Xen dist, int data_size)
  2910. {
  2911. /* e = env possibly starting < 0 */
  2912. int e_size = RANDOM_DISTRIBUTION_ENVELOPE_SIZE;
  2913. mus_float_t *e, *data;
  2914. int i, e_len, lim, e_loc = 2;
  2915. Xen ex0, ex1, ey0, ey1;
  2916. mus_float_t x, x0, x1, xincr, y0, y1, sum, first_sum, last_sum = 0.0;
  2917. lim = (e_size + 1) * 2;
  2918. e = (mus_float_t *)calloc(lim, sizeof(mus_float_t));
  2919. e_len = Xen_list_length(dist);
  2920. ex0 = Xen_list_ref(dist, 0);
  2921. ex1 = Xen_list_ref(dist, e_len - 2);
  2922. x0 = Xen_real_to_C_double(ex0);
  2923. /* get x range first */
  2924. x1 = Xen_real_to_C_double(ex1);
  2925. xincr = (x1 - x0) / (mus_float_t)e_size;
  2926. /* now true x1 */
  2927. ex1 = Xen_list_ref(dist, 2);
  2928. x1 = Xen_real_to_C_double(ex1);
  2929. ey0 = Xen_list_ref(dist, 1);
  2930. ey1 = Xen_list_ref(dist, 3);
  2931. y0 = Xen_real_to_C_double(ey0);
  2932. y1 = Xen_real_to_C_double(ey1);
  2933. sum = y0;
  2934. first_sum = sum;
  2935. for (i = 0, x = x0; i < lim; i += 2, x += xincr)
  2936. {
  2937. e[i] = sum;
  2938. last_sum = sum;
  2939. e[i + 1] = x;
  2940. while ((x >= x1) && ((e_loc + 2) < e_len))
  2941. {
  2942. x0 = x1;
  2943. y0 = y1;
  2944. e_loc += 2;
  2945. ex1 = Xen_list_ref(dist, e_loc);
  2946. ey1 = Xen_list_ref(dist, e_loc + 1);
  2947. x1 = Xen_real_to_C_double(ex1);
  2948. y1 = Xen_real_to_C_double(ey1);
  2949. }
  2950. if ((x == x0) || (x0 == x1))
  2951. sum += y0;
  2952. else sum += (y0 + (y1 - y0) * (x - x0) / (x1 - x0));
  2953. }
  2954. xincr = (last_sum - first_sum) / (mus_float_t)(data_size - 1);
  2955. data = (mus_float_t *)calloc(data_size, sizeof(mus_float_t));
  2956. x0 = e[0];
  2957. x1 = e[2];
  2958. y0 = e[1];
  2959. y1 = e[3];
  2960. e_len = lim;
  2961. e_loc = 2;
  2962. for (i = 0, x = first_sum; i < data_size; i++, x += xincr)
  2963. {
  2964. while ((x >= x1) && ((e_loc + 2) < e_len))
  2965. {
  2966. x0 = x1;
  2967. y0 = y1;
  2968. e_loc += 2;
  2969. x1 = e[e_loc];
  2970. y1 = e[e_loc + 1];
  2971. }
  2972. if ((x == x0) || (x0 == x1))
  2973. data[i] = y0;
  2974. else data[i] = (y0 + (y1 - y0) * (x - x0) / (x1 - x0));
  2975. }
  2976. free(e);
  2977. return(data);
  2978. }
  2979. static Xen g_make_noi(bool rand_case, const char *caller, Xen arglist)
  2980. {
  2981. mus_any *ge = NULL;
  2982. Xen args[10];
  2983. Xen keys[5];
  2984. int orig_arg[5] = {0, 0, 0, 0, 0};
  2985. int vals;
  2986. mus_float_t freq, base = 1.0;
  2987. mus_float_t *distribution = NULL;
  2988. Xen orig_v = Xen_false;
  2989. int distribution_size = RANDOM_DISTRIBUTION_TABLE_SIZE;
  2990. freq = clm_default_frequency;
  2991. keys[0] = kw_frequency;
  2992. keys[1] = kw_amplitude;
  2993. keys[2] = kw_envelope;
  2994. keys[3] = kw_distribution;
  2995. keys[4] = kw_size;
  2996. {
  2997. int i, arglist_len;
  2998. Xen p;
  2999. arglist_len = Xen_list_length(arglist);
  3000. if (arglist_len > 10) clm_error(caller, "too many arguments!", arglist);
  3001. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  3002. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  3003. }
  3004. vals = mus_optkey_unscramble(caller, 5, keys, args, orig_arg);
  3005. if (vals > 0)
  3006. {
  3007. freq = Xen_optkey_to_float(kw_frequency, keys[0], caller, orig_arg[0], freq);
  3008. if (freq > mus_srate())
  3009. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "freq > srate/2?");
  3010. base = Xen_optkey_to_float(kw_amplitude, keys[1], caller, orig_arg[1], base);
  3011. distribution_size = Xen_optkey_to_int(kw_size, keys[4], caller, orig_arg[4], distribution_size);
  3012. if (distribution_size <= 0)
  3013. Xen_out_of_range_error(caller, orig_arg[4], keys[4], "distribution size <= 0?");
  3014. if (distribution_size > mus_max_table_size())
  3015. Xen_out_of_range_error(caller, orig_arg[4], keys[4], "distribution size too large (see mus-max-table-size)");
  3016. if (!(Xen_is_keyword(keys[2]))) /* i.e. envelope arg was specified */
  3017. {
  3018. int len;
  3019. Xen_check_type(Xen_is_list(keys[2]), keys[2], orig_arg[2], caller, "an envelope");
  3020. len = Xen_list_length(keys[2]);
  3021. if ((len < 4) || (len & 1))
  3022. clm_error(caller, "bad distribution envelope", keys[2]);
  3023. /* envelope and distribution are incompatible */
  3024. if (!(Xen_is_keyword(keys[3])))
  3025. clm_error(caller, ":envelope and :distribution in same call?", keys[3]);
  3026. distribution = inverse_integrate(keys[2], distribution_size);
  3027. orig_v = xen_make_vct(distribution_size, distribution);
  3028. }
  3029. else
  3030. {
  3031. if (!(Xen_is_keyword(keys[3]))) /* i.e. distribution arg was specified */
  3032. {
  3033. Xen_check_type(mus_is_vct(keys[3]) || Xen_is_false(keys[3]), keys[3], orig_arg[3], caller, "a " S_vct);
  3034. if (mus_is_vct(keys[3]))
  3035. {
  3036. vct *v = NULL;
  3037. orig_v = keys[3];
  3038. v = mus_optkey_to_vct(orig_v, caller, orig_arg[3], NULL);
  3039. distribution_size = mus_vct_length(v);
  3040. distribution = mus_vct_data(v);
  3041. }
  3042. }
  3043. }
  3044. }
  3045. if (!distribution)
  3046. {
  3047. if (rand_case)
  3048. ge = mus_make_rand(freq, base);
  3049. else ge = mus_make_rand_interp(freq, base);
  3050. }
  3051. else
  3052. {
  3053. if (rand_case)
  3054. ge = mus_make_rand_with_distribution(freq, base, distribution, distribution_size);
  3055. else ge = mus_make_rand_interp_with_distribution(freq, base, distribution, distribution_size);
  3056. }
  3057. if (ge)
  3058. {
  3059. if (mus_is_vct(orig_v))
  3060. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  3061. return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  3062. }
  3063. return(Xen_false);
  3064. }
  3065. static Xen g_make_rand_interp(Xen arglist)
  3066. {
  3067. #define H_make_rand_interp "(" S_make_rand_interp " (frequency *clm-default-frequency*) (amplitude 1.0) (envelope) (distribution) (size)): \
  3068. return a new " S_rand_interp " generator, producing linearly interpolated random numbers. \
  3069. frequency is the rate at which new end-points are chosen."
  3070. return(g_make_noi(false, S_make_rand_interp, arglist));
  3071. }
  3072. static Xen g_make_rand(Xen arglist)
  3073. {
  3074. #define H_make_rand "(" S_make_rand " (frequency *clm-default-frequency*) (amplitude 1.0) (envelope) (distribution) (size)): \
  3075. return a new " S_rand " generator, producing a sequence of random numbers (a step function). \
  3076. frequency is the rate at which new numbers are chosen."
  3077. return(g_make_noi(true, S_make_rand, arglist));
  3078. }
  3079. static Xen g_rand(Xen obj, Xen fm)
  3080. {
  3081. #define H_rand "(" S_rand " gen (fm 0.0)): gen's current random number. \
  3082. fm modulates the rate at which the current number is changed."
  3083. mus_float_t fm1 = 0.0;
  3084. mus_any *g = NULL;
  3085. mus_xen *gn;
  3086. Xen_to_C_generator(obj, gn, g, mus_is_rand, S_rand, "a rand generator");
  3087. Xen_real_to_C_double_if_bound(fm, fm1, S_rand, 2);
  3088. return(C_double_to_Xen_real(mus_rand(g, fm1)));
  3089. }
  3090. static Xen g_is_rand(Xen obj)
  3091. {
  3092. #define H_is_rand "(" S_is_rand " gen): " PROC_TRUE " if gen is a " S_rand
  3093. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_rand(Xen_to_mus_any(obj)))));
  3094. }
  3095. static Xen g_rand_interp(Xen obj, Xen fm)
  3096. {
  3097. #define H_rand_interp "(" S_rand_interp " gen (fm 0.0)): gen's current (interpolating) random number. \
  3098. fm modulates the rate at which new segment end-points are chosen."
  3099. mus_float_t fm1 = 0.0;
  3100. mus_any *g = NULL;
  3101. mus_xen *gn;
  3102. Xen_to_C_generator(obj, gn, g, mus_is_rand_interp, S_rand_interp, "a rand-interp generator");
  3103. Xen_real_to_C_double_if_bound(fm, fm1, S_rand_interp, 2);
  3104. return(C_double_to_Xen_real(mus_rand_interp(g, fm1)));
  3105. }
  3106. static Xen g_is_rand_interp(Xen obj)
  3107. {
  3108. #define H_is_rand_interp "(" S_is_rand_interp " gen): " PROC_TRUE " if gen is a " S_rand_interp
  3109. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_rand_interp(Xen_to_mus_any(obj)))));
  3110. }
  3111. static Xen g_mus_random(Xen a)
  3112. {
  3113. #define H_mus_random "(" S_mus_random " val): a random number between -val and val. \
  3114. the built-in 'random' function returns values between 0 and its argument"
  3115. mus_float_t x;
  3116. Xen_to_C_double_or_error(a, x, S_mus_random, 1);
  3117. return(C_double_to_Xen_real(mus_random(x)));
  3118. }
  3119. static Xen g_mus_rand_seed(void)
  3120. {
  3121. #define H_mus_rand_seed "(" S_mus_rand_seed "): the random number seed; \
  3122. this can be used to re-run a particular random number sequence."
  3123. return(C_int_to_Xen_integer(mus_rand_seed()));
  3124. }
  3125. static Xen g_mus_set_rand_seed(Xen a)
  3126. {
  3127. Xen_check_type(Xen_is_integer(a), a, 1, S_set S_mus_rand_seed, "an integer");
  3128. mus_set_rand_seed((unsigned long)Xen_integer_to_C_int(a));
  3129. return(a);
  3130. }
  3131. /* ---------------- table lookup ---------------- */
  3132. static Xen g_is_table_lookup(Xen obj)
  3133. {
  3134. #define H_is_table_lookup "(" S_is_table_lookup " gen): " PROC_TRUE " if gen is a " S_table_lookup
  3135. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_table_lookup(Xen_to_mus_any(obj)))));
  3136. }
  3137. static Xen g_partials_to_wave(Xen partials, Xen utable, Xen normalize)
  3138. {
  3139. #define H_partials_to_wave "(" S_partials_to_wave " partials wave (normalize " PROC_FALSE ")): \
  3140. take a list or " S_vct " of partials (harmonic number and associated amplitude) and produce \
  3141. a waveform for use in " S_table_lookup ". If wave (a " S_vct ") is not given, \
  3142. a new one is created. If normalize is " PROC_TRUE ", the resulting waveform goes between -1.0 and 1.0.\n\
  3143. (set! gen (" S_make_table_lookup " 440.0 :wave (" S_partials_to_wave " '(1 1.0 2 .5))))"
  3144. vct *f;
  3145. Xen table;
  3146. mus_float_t *partial_data = NULL;
  3147. mus_long_t len = 0;
  3148. bool partials_allocated = true;
  3149. #if HAVE_SCHEME
  3150. int gc_loc;
  3151. #endif
  3152. Xen_check_type(mus_is_vct(partials) || Xen_is_list(partials), partials, 1, S_partials_to_wave, "a list or a " S_vct);
  3153. Xen_check_type(mus_is_vct(utable) || Xen_is_false(utable) || (!(Xen_is_bound(utable))), utable, 2, S_partials_to_wave, "a " S_vct " or " PROC_FALSE);
  3154. Xen_check_type(Xen_is_boolean_or_unbound(normalize), normalize, 3, S_partials_to_wave, "a boolean");
  3155. if (mus_is_vct(partials))
  3156. {
  3157. vct *v;
  3158. v = Xen_to_vct(partials);
  3159. partial_data = mus_vct_data(v);
  3160. len = mus_vct_length(v);
  3161. partials_allocated = false;
  3162. }
  3163. else
  3164. {
  3165. len = Xen_list_length(partials);
  3166. if (len == 0)
  3167. Xen_error(NO_DATA,
  3168. Xen_list_2(C_string_to_Xen_string("~A: partials list empty?"),
  3169. C_string_to_Xen_string(S_partials_to_wave)));
  3170. if (!(Xen_is_number(Xen_car(partials))))
  3171. Xen_check_type(false, partials, 1, S_partials_to_wave, "a list of numbers (partial numbers with amplitudes)");
  3172. }
  3173. if (len & 1)
  3174. Xen_error(BAD_TYPE,
  3175. Xen_list_3(C_string_to_Xen_string("~A: odd length partials list? ~A"),
  3176. C_string_to_Xen_string(S_partials_to_wave),
  3177. partials));
  3178. if ((!Xen_is_bound(utable)) || (!(mus_is_vct(utable))))
  3179. {
  3180. mus_float_t *wave;
  3181. wave = (mus_float_t *)calloc(clm_table_size, sizeof(mus_float_t));
  3182. if (wave == NULL)
  3183. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate wave table", S_partials_to_wave));
  3184. table = xen_make_vct(clm_table_size, wave);
  3185. }
  3186. else table = utable;
  3187. #if HAVE_SCHEME
  3188. gc_loc = s7_gc_protect(s7, table);
  3189. #endif
  3190. f = Xen_to_vct(table);
  3191. if (!partial_data)
  3192. {
  3193. Xen lst;
  3194. int i;
  3195. partial_data = (mus_float_t *)malloc(len * sizeof(mus_float_t));
  3196. if (partial_data == NULL)
  3197. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate partials table", S_partials_to_wave));
  3198. for (i = 0, lst = Xen_copy_arg(partials); i < len; i++, lst = Xen_cdr(lst))
  3199. partial_data[i] = Xen_real_to_C_double(Xen_car(lst));
  3200. }
  3201. mus_partials_to_wave(partial_data, len / 2, mus_vct_data(f), mus_vct_length(f), (Xen_is_true(normalize)));
  3202. if (partials_allocated)
  3203. free(partial_data);
  3204. #if HAVE_SCHEME
  3205. s7_gc_unprotect_at(s7, gc_loc);
  3206. #endif
  3207. return(table);
  3208. }
  3209. static Xen g_phase_partials_to_wave(Xen partials, Xen utable, Xen normalize)
  3210. {
  3211. vct *f;
  3212. Xen table;
  3213. mus_float_t *partial_data = NULL;
  3214. mus_long_t len = 0;
  3215. bool partials_allocated = true;
  3216. #if HAVE_SCHEME
  3217. int gc_loc;
  3218. #endif
  3219. #if HAVE_SCHEME
  3220. #define pp2w_example "(" S_make_table_lookup " 440.0 :wave (" S_phase_partials_to_wave " (list 1 .75 0.0 2 .25 (* 3.14159 .5))))"
  3221. #endif
  3222. #if HAVE_RUBY
  3223. #define pp2w_example "make_table_lookup(440.0, :wave, phase_partials2wave([1.0, 0.75, 0.0, 2.0, 0.25, 3.14159 * 0.5]))"
  3224. #endif
  3225. #if HAVE_FORTH
  3226. #define pp2w_example "440.0 0.0 '( 1.0 0.75 0.0 2.0 0.25 3.14159 0.5 f* ) #f #f phase-partials->wave make-table-lookup"
  3227. #endif
  3228. #define H_phase_partials_to_wave "(" S_phase_partials_to_wave " partials wave (normalize " PROC_FALSE ")): \
  3229. take a list or " S_vct " of partials (harmonic number, amplitude, initial phase) and produce \
  3230. a waveform for use in " S_table_lookup ". If wave (a " S_vct ") is not given, \
  3231. a new one is created. If normalize is " PROC_TRUE ", the resulting waveform goes between -1.0 and 1.0.\n " pp2w_example
  3232. Xen_check_type(mus_is_vct(partials) || Xen_is_list(partials), partials, 1, S_phase_partials_to_wave, "a list or a " S_vct);
  3233. Xen_check_type(mus_is_vct(utable) || Xen_is_false(utable) || (!(Xen_is_bound(utable))), utable, 2, S_phase_partials_to_wave, "a " S_vct " or " PROC_FALSE);
  3234. Xen_check_type(Xen_is_boolean_or_unbound(normalize), normalize, 3, S_phase_partials_to_wave, "a boolean");
  3235. if (mus_is_vct(partials))
  3236. {
  3237. vct *v;
  3238. v = Xen_to_vct(partials);
  3239. partial_data = mus_vct_data(v);
  3240. len = mus_vct_length(v);
  3241. partials_allocated = false;
  3242. }
  3243. else
  3244. {
  3245. len = Xen_list_length(partials);
  3246. if (len == 0)
  3247. Xen_error(NO_DATA,
  3248. Xen_list_2(C_string_to_Xen_string("~A: partials list empty?"),
  3249. C_string_to_Xen_string(S_phase_partials_to_wave)));
  3250. if (!(Xen_is_number(Xen_car(partials))))
  3251. Xen_check_type(false, partials, 1, S_phase_partials_to_wave, "a list of numbers (partial numbers with amplitudes and phases)");
  3252. }
  3253. if ((len % 3) != 0)
  3254. Xen_error(Xen_make_error_type("wrong-type-arg"),
  3255. Xen_list_3(C_string_to_Xen_string("~A: partials list, ~A, should have 3 entries for each harmonic (number amp phase)"),
  3256. C_string_to_Xen_string(S_phase_partials_to_wave),
  3257. partials));
  3258. if ((!Xen_is_bound(utable)) || (!(mus_is_vct(utable))))
  3259. {
  3260. mus_float_t *wave;
  3261. wave = (mus_float_t *)calloc(clm_table_size, sizeof(mus_float_t));
  3262. if (wave == NULL)
  3263. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate wave table", S_phase_partials_to_wave));
  3264. table = xen_make_vct(clm_table_size, wave);
  3265. }
  3266. else table = utable;
  3267. #if HAVE_SCHEME
  3268. gc_loc = s7_gc_protect(s7, table);
  3269. #endif
  3270. f = Xen_to_vct(table);
  3271. if (!partial_data)
  3272. {
  3273. int i;
  3274. Xen lst;
  3275. partial_data = (mus_float_t *)malloc(len * sizeof(mus_float_t));
  3276. if (partial_data == NULL)
  3277. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate partials table", S_phase_partials_to_wave));
  3278. for (i = 0, lst = Xen_copy_arg(partials); i < len; i++, lst = Xen_cdr(lst))
  3279. partial_data[i] = Xen_real_to_C_double(Xen_car(lst));
  3280. }
  3281. mus_phase_partials_to_wave(partial_data, len / 3, mus_vct_data(f), mus_vct_length(f), (Xen_is_true(normalize)));
  3282. if (partials_allocated)
  3283. free(partial_data);
  3284. #if HAVE_SCHEME
  3285. s7_gc_unprotect_at(s7, gc_loc);
  3286. #endif
  3287. return(table);
  3288. }
  3289. static Xen g_make_table_lookup(Xen arglist)
  3290. {
  3291. #define H_make_table_lookup "(" S_make_table_lookup " (frequency *clm-default-frequency*) (initial-phase 0.0) (wave) (size clm-table-size) (type)): \
  3292. return a new " S_table_lookup " generator. \
  3293. The default table size is 512; use :size to set some other size, or pass your own " S_vct " as the 'wave'.\n\
  3294. (set! gen (" S_make_table_lookup " 440.0 :wave (" S_partials_to_wave " '(1 1.0))))\n\
  3295. is the same in effect as " S_make_oscil ". 'type' sets the interpolation choice which defaults to " S_mus_interp_linear "."
  3296. mus_any *ge;
  3297. int vals;
  3298. mus_long_t table_size = clm_table_size;
  3299. Xen args[10];
  3300. Xen keys[5];
  3301. int orig_arg[5] = {0, 0, 0, 0, MUS_INTERP_LINEAR};
  3302. mus_float_t freq, phase = 0.0;
  3303. mus_float_t *table = NULL;
  3304. Xen orig_v = Xen_false;
  3305. int interp_type = (int)MUS_INTERP_LINEAR;
  3306. freq = clm_default_frequency;
  3307. keys[0] = kw_frequency;
  3308. keys[1] = kw_initial_phase;
  3309. keys[2] = kw_wave;
  3310. keys[3] = kw_size;
  3311. keys[4] = kw_type;
  3312. {
  3313. int i, arglist_len;
  3314. Xen p;
  3315. arglist_len = Xen_list_length(arglist);
  3316. if (arglist_len > 10) clm_error(S_make_table_lookup, "too many arguments!", arglist);
  3317. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  3318. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  3319. }
  3320. vals = mus_optkey_unscramble(S_make_table_lookup, 5, keys, args, orig_arg);
  3321. if (vals > 0)
  3322. {
  3323. vct *v = NULL;
  3324. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_table_lookup, orig_arg[0], freq);
  3325. if (freq > (0.5 * mus_srate()))
  3326. Xen_out_of_range_error(S_make_table_lookup, orig_arg[0], keys[0], "freq > srate/2?");
  3327. phase = Xen_optkey_to_float(kw_initial_phase, keys[1], S_make_table_lookup, orig_arg[1], phase);
  3328. if (phase < 0.0)
  3329. Xen_out_of_range_error(S_make_table_lookup, orig_arg[1], keys[1], "initial phase <= 0.0?"); /* is this actually an error? */
  3330. v = mus_optkey_to_vct(keys[2], S_make_table_lookup, orig_arg[2], NULL);
  3331. if (v)
  3332. {
  3333. orig_v = keys[2];
  3334. table = mus_vct_data(v);
  3335. table_size = mus_vct_length(v);
  3336. }
  3337. table_size = Xen_optkey_to_mus_long_t(kw_size, keys[3], S_make_table_lookup, orig_arg[3], table_size);
  3338. if (table_size <= 0)
  3339. Xen_out_of_range_error(S_make_table_lookup, orig_arg[3], keys[3], "size <= 0?");
  3340. if (table_size > mus_max_table_size())
  3341. Xen_out_of_range_error(S_make_table_lookup, orig_arg[3], keys[3], "size too large (see mus-max-table-size)");
  3342. if ((v) && (table_size > mus_vct_length(v)))
  3343. Xen_out_of_range_error(S_make_table_lookup, orig_arg[3], keys[3], "table size > wave size");
  3344. interp_type = Xen_optkey_to_int(kw_type, keys[4], S_make_table_lookup, orig_arg[4], interp_type);
  3345. if (!(mus_is_interp_type(interp_type)))
  3346. Xen_out_of_range_error(S_make_table_lookup, orig_arg[4], keys[4], "no such interp-type");
  3347. }
  3348. if (!(mus_is_vct(orig_v)))
  3349. {
  3350. table = (mus_float_t *)calloc(table_size, sizeof(mus_float_t));
  3351. if (table == NULL)
  3352. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate table-lookup table", S_make_table_lookup));
  3353. orig_v = xen_make_vct(table_size, table);
  3354. }
  3355. ge = mus_make_table_lookup(freq, phase, table, table_size, (mus_interp_t)interp_type);
  3356. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  3357. }
  3358. static Xen g_table_lookup(Xen obj, Xen fm)
  3359. {
  3360. #define H_table_lookup "(" S_table_lookup " gen (fm 0.0)): interpolated table-lookup \
  3361. with 'wrap-around' when gen's phase marches off either end of its table."
  3362. mus_float_t fm1 = 0.0;
  3363. mus_any *g = NULL;
  3364. mus_xen *gn;
  3365. Xen_to_C_generator(obj, gn, g, mus_is_table_lookup, S_table_lookup, "a table-lookup generator");
  3366. Xen_real_to_C_double_if_bound(fm, fm1, S_table_lookup, 2);
  3367. return(C_double_to_Xen_real(mus_table_lookup(g, fm1)));
  3368. }
  3369. /* ---------------- sawtooth et al ---------------- */
  3370. typedef enum {G_SAWTOOTH_WAVE, G_SQUARE_WAVE, G_TRIANGLE_WAVE, G_PULSE_TRAIN} xclm_wave_t;
  3371. static Xen g_make_sw(xclm_wave_t type, mus_float_t def_phase, Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3372. {
  3373. mus_any *ge = NULL;
  3374. const char *caller = NULL;
  3375. Xen args[6];
  3376. Xen keys[3];
  3377. int orig_arg[3] = {0, 0, 0};
  3378. int vals;
  3379. mus_float_t freq, base = 1.0, phase;
  3380. freq = clm_default_frequency;
  3381. phase = def_phase;
  3382. switch (type)
  3383. {
  3384. case G_SAWTOOTH_WAVE: caller = S_make_sawtooth_wave; break;
  3385. case G_SQUARE_WAVE: caller = S_make_square_wave; break;
  3386. case G_TRIANGLE_WAVE: caller = S_make_triangle_wave; break;
  3387. case G_PULSE_TRAIN: caller = S_make_pulse_train; break;
  3388. }
  3389. keys[0] = kw_frequency;
  3390. keys[1] = kw_amplitude;
  3391. keys[2] = kw_initial_phase;
  3392. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6;
  3393. vals = mus_optkey_unscramble(caller, 3, keys, args, orig_arg);
  3394. if (vals > 0)
  3395. {
  3396. freq = Xen_optkey_to_float(kw_frequency, keys[0], caller, orig_arg[0], freq);
  3397. if (freq > mus_srate())
  3398. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "freq > srate/2?");
  3399. base = Xen_optkey_to_float(kw_amplitude, keys[1], caller, orig_arg[1], base);
  3400. phase = Xen_optkey_to_float(kw_initial_phase, keys[2], caller, orig_arg[2], phase);
  3401. }
  3402. switch (type)
  3403. {
  3404. case G_SAWTOOTH_WAVE: ge = mus_make_sawtooth_wave(freq, base, phase); break;
  3405. case G_SQUARE_WAVE: ge = mus_make_square_wave(freq, base, phase); break;
  3406. case G_TRIANGLE_WAVE: ge = mus_make_triangle_wave(freq, base, phase); break;
  3407. case G_PULSE_TRAIN: ge = mus_make_pulse_train(freq, base, phase); break;
  3408. }
  3409. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  3410. return(Xen_false);
  3411. }
  3412. static Xen g_make_sawtooth_wave(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3413. {
  3414. #define H_make_sawtooth_wave "(" S_make_sawtooth_wave " (frequency *clm-default-frequency*) (amplitude 1.0) (initial-phase 0.0)): \
  3415. return a new " S_sawtooth_wave " generator."
  3416. return(g_make_sw(G_SAWTOOTH_WAVE, M_PI, arg1, arg2, arg3, arg4, arg5, arg6));
  3417. }
  3418. static Xen g_make_square_wave(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3419. {
  3420. #define H_make_square_wave "(" S_make_square_wave " (frequency *clm-default-frequency*) (amplitude 1.0) (initial-phase 0.0)): \
  3421. return a new " S_square_wave " generator."
  3422. return(g_make_sw(G_SQUARE_WAVE, 0.0, arg1, arg2, arg3, arg4, arg5, arg6));
  3423. }
  3424. static Xen g_make_triangle_wave(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3425. {
  3426. #define H_make_triangle_wave "(" S_make_triangle_wave " (frequency *clm-default-frequency*) (amplitude 1.0) (initial-phase 0.0)): \
  3427. return a new " S_triangle_wave " generator."
  3428. return(g_make_sw(G_TRIANGLE_WAVE, 0.0, arg1, arg2, arg3, arg4, arg5, arg6));
  3429. }
  3430. static Xen g_make_pulse_train(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3431. {
  3432. #define H_make_pulse_train "(" S_make_pulse_train " (frequency *clm-default-frequency*) (amplitude 1.0) (initial-phase 0.0)): \
  3433. return a new " S_pulse_train " generator. This produces a sequence of impulses."
  3434. return(g_make_sw(G_PULSE_TRAIN, TWO_PI, arg1, arg2, arg3, arg4, arg5, arg6));
  3435. }
  3436. static Xen g_sawtooth_wave(Xen obj, Xen fm)
  3437. {
  3438. #define H_sawtooth_wave "(" S_sawtooth_wave " gen (fm 0.0)): next sawtooth sample from generator"
  3439. mus_float_t fm1 = 0.0;
  3440. mus_any *g = NULL;
  3441. mus_xen *gn;
  3442. Xen_to_C_generator(obj, gn, g, mus_is_sawtooth_wave, S_sawtooth_wave, "a sawtooth-wave generator");
  3443. Xen_real_to_C_double_if_bound(fm, fm1, S_sawtooth_wave, 2);
  3444. return(C_double_to_Xen_real(mus_sawtooth_wave(g, fm1)));
  3445. }
  3446. static Xen g_square_wave(Xen obj, Xen fm)
  3447. {
  3448. #define H_square_wave "(" S_square_wave " gen (fm 0.0)): next square wave sample from generator"
  3449. mus_float_t fm1 = 0.0;
  3450. mus_any *g = NULL;
  3451. mus_xen *gn;
  3452. Xen_to_C_generator(obj, gn, g, mus_is_square_wave, S_square_wave, "a square-wave generator");
  3453. Xen_real_to_C_double_if_bound(fm, fm1, S_square_wave, 2);
  3454. return(C_double_to_Xen_real(mus_square_wave(g, fm1)));
  3455. }
  3456. static Xen g_triangle_wave(Xen obj, Xen fm)
  3457. {
  3458. #define H_triangle_wave "(" S_triangle_wave " gen (fm 0.0)): next triangle wave sample from generator"
  3459. mus_float_t fm1 = 0.0;
  3460. mus_any *g = NULL;
  3461. mus_xen *gn;
  3462. Xen_to_C_generator(obj, gn, g, mus_is_triangle_wave, S_triangle_wave, "a triangle-wave generator");
  3463. Xen_real_to_C_double_if_bound(fm, fm1, S_triangle_wave, 2);
  3464. return(C_double_to_Xen_real(mus_triangle_wave(g, fm1)));
  3465. }
  3466. static Xen g_pulse_train(Xen obj, Xen fm)
  3467. {
  3468. #define H_pulse_train "(" S_pulse_train " gen (fm 0.0)): next pulse train sample from generator"
  3469. mus_float_t fm1 = 0.0;
  3470. mus_any *g = NULL;
  3471. mus_xen *gn;
  3472. Xen_to_C_generator(obj, gn, g, mus_is_pulse_train, S_pulse_train, "a pulse-train generator");
  3473. Xen_real_to_C_double_if_bound(fm, fm1, S_pulse_train, 2);
  3474. return(C_double_to_Xen_real(mus_pulse_train(g, fm1)));
  3475. }
  3476. static Xen g_is_sawtooth_wave(Xen obj)
  3477. {
  3478. #define H_is_sawtooth_wave "(" S_is_sawtooth_wave " gen): " PROC_TRUE " if gen is a " S_sawtooth_wave
  3479. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_sawtooth_wave(Xen_to_mus_any(obj)))));
  3480. }
  3481. static Xen g_is_square_wave(Xen obj)
  3482. {
  3483. #define H_is_square_wave "(" S_is_square_wave " gen): " PROC_TRUE " if gen is a " S_square_wave
  3484. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_square_wave(Xen_to_mus_any(obj)))));
  3485. }
  3486. static Xen g_is_triangle_wave(Xen obj)
  3487. {
  3488. #define H_is_triangle_wave "(" S_is_triangle_wave " gen): " PROC_TRUE " if gen is a " S_triangle_wave
  3489. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_triangle_wave(Xen_to_mus_any(obj)))));
  3490. }
  3491. static Xen g_is_pulse_train(Xen obj)
  3492. {
  3493. #define H_is_pulse_train "(" S_is_pulse_train " gen): " PROC_TRUE " if gen is a " S_pulse_train
  3494. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_pulse_train(Xen_to_mus_any(obj)))));
  3495. }
  3496. /* ---------------- asymmetric-fm ---------------- */
  3497. static Xen g_make_asymmetric_fm(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6, Xen arg7, Xen arg8)
  3498. {
  3499. #define H_make_asymmetric_fm "(" S_make_asymmetric_fm " (frequency *clm-default-frequency*) (initial-phase 0.0) (r 1.0) (ratio 1.0)): \
  3500. return a new " S_asymmetric_fm " generator."
  3501. mus_any *ge;
  3502. Xen args[8];
  3503. Xen keys[4];
  3504. int orig_arg[4] = {0, 0, 0, 0};
  3505. int vals;
  3506. mus_float_t freq, phase = 0.0, r = 1.0, ratio = 1.0;
  3507. freq = clm_default_frequency;
  3508. keys[0] = kw_frequency;
  3509. keys[1] = kw_initial_phase;
  3510. keys[2] = kw_r;
  3511. keys[3] = kw_ratio;
  3512. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8;
  3513. vals = mus_optkey_unscramble(S_make_asymmetric_fm, 4, keys, args, orig_arg);
  3514. if (vals > 0)
  3515. {
  3516. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_asymmetric_fm, orig_arg[0], freq);
  3517. if (freq > (0.5 * mus_srate()))
  3518. Xen_out_of_range_error(S_make_asymmetric_fm, orig_arg[0], keys[0], "freq > srate/2?");
  3519. phase = Xen_optkey_to_float(kw_initial_phase, keys[1], S_make_asymmetric_fm, orig_arg[1], phase);
  3520. r = Xen_optkey_to_float(kw_r, keys[2], S_make_asymmetric_fm, orig_arg[2], r);
  3521. ratio = Xen_optkey_to_float(kw_ratio, keys[3], S_make_asymmetric_fm, orig_arg[3], ratio);
  3522. }
  3523. ge = mus_make_asymmetric_fm(freq, phase, r, ratio);
  3524. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  3525. return(Xen_false);
  3526. }
  3527. static Xen g_asymmetric_fm(Xen obj, Xen index, Xen fm)
  3528. {
  3529. #define H_asymmetric_fm "(" S_asymmetric_fm " gen (index 0.0) (fm 0.0)): next sample from asymmetric fm generator"
  3530. mus_float_t fm1 = 0.0, index1 = 0.0;
  3531. mus_any *g = NULL;
  3532. mus_xen *gn;
  3533. Xen_to_C_generator(obj, gn, g, mus_is_asymmetric_fm, S_asymmetric_fm, "an asymmetric-fm generator");
  3534. Xen_real_to_C_double_if_bound(fm, fm1, S_asymmetric_fm, 2);
  3535. Xen_real_to_C_double_if_bound(index, index1, S_asymmetric_fm, 3);
  3536. return(C_double_to_Xen_real(mus_asymmetric_fm(g, index1, fm1)));
  3537. }
  3538. static Xen g_is_asymmetric_fm(Xen obj)
  3539. {
  3540. #define H_is_asymmetric_fm "(" S_is_asymmetric_fm " gen): " PROC_TRUE " if gen is a " S_asymmetric_fm
  3541. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_asymmetric_fm(Xen_to_mus_any(obj)))));
  3542. }
  3543. /* ---------------- simple filters ---------------- */
  3544. typedef enum {G_ONE_POLE, G_ONE_ZERO, G_TWO_POLE, G_TWO_ZERO} xclm_filter_t;
  3545. static const char *smpflts[6] = {S_make_one_pole, S_make_one_zero, S_make_two_pole, S_make_two_zero};
  3546. static Xen g_make_smpflt_1(xclm_filter_t choice, Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3547. {
  3548. mus_any *gen = NULL;
  3549. Xen args[4];
  3550. Xen keys[2];
  3551. int orig_arg[2] = {0, 0};
  3552. int vals;
  3553. mus_float_t a0 = 0.0;
  3554. mus_float_t a1 = 0.0;
  3555. switch (choice)
  3556. {
  3557. case G_ONE_ZERO: keys[0] = kw_a0; keys[1] = kw_a1; break;
  3558. case G_ONE_POLE: keys[0] = kw_a0; keys[1] = kw_b1; break;
  3559. default: keys[0] = kw_frequency; keys[1] = kw_radius; break;
  3560. }
  3561. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  3562. vals = mus_optkey_unscramble(smpflts[choice], 2, keys, args, orig_arg);
  3563. if (vals > 0)
  3564. {
  3565. a0 = mus_optkey_to_float(keys[0], smpflts[choice], orig_arg[0], a0);
  3566. a1 = mus_optkey_to_float(keys[1], smpflts[choice], orig_arg[1], a1);
  3567. }
  3568. switch (choice)
  3569. {
  3570. case G_ONE_ZERO: gen = mus_make_one_zero(a0, a1); break;
  3571. case G_ONE_POLE: gen = mus_make_one_pole(a0, a1); break;
  3572. case G_TWO_ZERO: gen = mus_make_two_zero_from_frequency_and_radius(a0, a1); break;
  3573. case G_TWO_POLE: gen = mus_make_two_pole_from_frequency_and_radius(a0, a1); break;
  3574. default: break;
  3575. }
  3576. if (gen) return(mus_xen_to_object(mus_any_to_mus_xen(gen)));
  3577. return(Xen_false);
  3578. }
  3579. static Xen g_make_one_zero(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3580. {
  3581. #define H_make_one_zero "(" S_make_one_zero " a0 a1): return a new " S_one_zero " filter; a0*x(n) + a1*x(n-1)"
  3582. return(g_make_smpflt_1(G_ONE_ZERO, arg1, arg2, arg3, arg4));
  3583. }
  3584. static Xen g_make_one_pole(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3585. {
  3586. #define H_make_one_pole "(" S_make_one_pole " a0 b1): return a new " S_one_pole " filter; a0*x(n) - b1*y(n-1)"
  3587. return(g_make_smpflt_1(G_ONE_POLE, arg1, arg2, arg3, arg4));
  3588. }
  3589. static Xen g_make_smpflt_2(xclm_filter_t choice, Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3590. {
  3591. mus_any *gen = NULL;
  3592. Xen args[6];
  3593. Xen keys[3];
  3594. int orig_arg[3] = {0, 0, 0};
  3595. int vals;
  3596. mus_float_t a0 = 0.0;
  3597. mus_float_t a1 = 0.0;
  3598. mus_float_t a2 = 0.0;
  3599. if (choice == G_TWO_ZERO)
  3600. {
  3601. keys[0] = kw_a0;
  3602. keys[1] = kw_a1;
  3603. keys[2] = kw_a2;
  3604. }
  3605. else
  3606. {
  3607. keys[0] = kw_a0;
  3608. keys[1] = kw_b1;
  3609. keys[2] = kw_b2;
  3610. }
  3611. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6;
  3612. vals = mus_optkey_unscramble(smpflts[choice], 3, keys, args, orig_arg);
  3613. if (vals > 0)
  3614. {
  3615. a0 = Xen_optkey_to_float(kw_a0, keys[0], smpflts[choice], orig_arg[0], a0);
  3616. a1 = mus_optkey_to_float(keys[1], smpflts[choice], orig_arg[1], a1);
  3617. a2 = mus_optkey_to_float(keys[2], smpflts[choice], orig_arg[2], a2);
  3618. }
  3619. if (choice == G_TWO_ZERO)
  3620. gen = mus_make_two_zero(a0, a1, a2);
  3621. else gen = mus_make_two_pole(a0, a1, a2);
  3622. if (gen) return(mus_xen_to_object(mus_any_to_mus_xen(gen)));
  3623. return(Xen_false);
  3624. }
  3625. static bool found_polar_key(Xen arg)
  3626. {
  3627. return((Xen_is_keyword(arg)) &&
  3628. ((Xen_keyword_is_eq(arg, kw_radius)) ||
  3629. (Xen_keyword_is_eq(arg, kw_frequency))));
  3630. }
  3631. static bool found_coeff_key(Xen arg)
  3632. {
  3633. return((Xen_is_keyword(arg)) &&
  3634. (!(Xen_keyword_is_eq(arg, kw_radius))) &&
  3635. (!(Xen_keyword_is_eq(arg, kw_frequency))));
  3636. }
  3637. static Xen g_make_two_zero(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3638. {
  3639. #define H_make_two_zero "(" S_make_two_zero " a0 a1 a2) or (" S_make_two_zero " frequency radius): return a new " S_two_zero " filter; \
  3640. a0*x(n) + a1*x(n-1) + a2*x(n-2)"
  3641. if ((Xen_is_bound(arg2)) && /* 0 or 1 args -> coeffs */
  3642. (!(Xen_is_bound(arg5)))) /* 5 or more args -> coeffs */
  3643. {
  3644. if ((found_polar_key(arg1)) ||
  3645. (found_polar_key(arg2)) || /* if arg1 is frequency as number, then arg2 is either key or number */
  3646. ((!(Xen_is_bound(arg3))) && /* make a guess that if 2 args, no keys, and a0 > 20, it is intended as a frequency */
  3647. (!(found_coeff_key(arg1))) &&
  3648. ((Xen_is_number(arg1)) && (Xen_real_to_C_double(arg1) >= 20.0))))
  3649. return(g_make_smpflt_1(G_TWO_ZERO, arg1, arg2, arg3, arg4));
  3650. }
  3651. return(g_make_smpflt_2(G_TWO_ZERO, arg1, arg2, arg3, arg4, arg5, arg6));
  3652. }
  3653. static Xen g_make_two_pole(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  3654. {
  3655. #define H_make_two_pole "(" S_make_two_pole " a0 b1 b2) or (" S_make_two_pole " frequency radius): return a new " S_two_pole " filter; \
  3656. a0*x(n) - b1*y(n-1) - b2*y(n-2)"
  3657. if ((Xen_is_bound(arg2)) && /* 0 or 1 args -> coeffs */
  3658. (!(Xen_is_bound(arg5)))) /* 5 or more args -> coeffs */
  3659. {
  3660. if ((found_polar_key(arg1)) ||
  3661. (found_polar_key(arg2)) || /* if arg1 is frequency as number, then arg2 is either key or number */
  3662. ((!(Xen_is_bound(arg3))) &&
  3663. (!(found_coeff_key(arg1))) &&
  3664. ((Xen_is_number(arg1)) && (Xen_real_to_C_double(arg1) >= 2.0))))
  3665. return(g_make_smpflt_1(G_TWO_POLE, arg1, arg2, arg3, arg4));
  3666. }
  3667. return(g_make_smpflt_2(G_TWO_POLE, arg1, arg2, arg3, arg4, arg5, arg6));
  3668. }
  3669. static Xen g_one_zero(Xen obj, Xen fm)
  3670. {
  3671. #define H_one_zero "(" S_one_zero " gen (input 0.0)): one zero filter of input"
  3672. mus_float_t fm1 = 0.0;
  3673. mus_any *g = NULL;
  3674. mus_xen *gn;
  3675. Xen_to_C_generator(obj, gn, g, mus_is_one_zero, S_one_zero, "a one-zero filter");
  3676. Xen_real_to_C_double_if_bound(fm, fm1, S_one_zero, 2);
  3677. return(C_double_to_Xen_real(mus_one_zero(g, fm1)));
  3678. }
  3679. static Xen g_one_pole(Xen obj, Xen fm)
  3680. {
  3681. #define H_one_pole "(" S_one_pole " gen (input 0.0)): one pole filter of input"
  3682. mus_float_t fm1 = 0.0;
  3683. mus_any *g = NULL;
  3684. mus_xen *gn;
  3685. Xen_to_C_generator(obj, gn, g, mus_is_one_pole, S_one_pole, "a one-pole filter");
  3686. Xen_real_to_C_double_if_bound(fm, fm1, S_one_pole, 2);
  3687. return(C_double_to_Xen_real(mus_one_pole(g, fm1)));
  3688. }
  3689. static Xen g_two_zero(Xen obj, Xen fm)
  3690. {
  3691. #define H_two_zero "(" S_two_zero " gen (input 0.0)): two zero filter of input"
  3692. mus_float_t fm1 = 0.0;
  3693. mus_any *g = NULL;
  3694. mus_xen *gn;
  3695. Xen_to_C_generator(obj, gn, g, mus_is_two_zero, S_two_zero, "a two-zero filter");
  3696. Xen_real_to_C_double_if_bound(fm, fm1, S_two_zero, 2);
  3697. return(C_double_to_Xen_real(mus_two_zero(g, fm1)));
  3698. }
  3699. static Xen g_two_pole(Xen obj, Xen fm)
  3700. {
  3701. #define H_two_pole "(" S_two_pole " gen (input 0.0)): two pole filter of input"
  3702. mus_float_t fm1 = 0.0;
  3703. mus_any *g = NULL;
  3704. mus_xen *gn;
  3705. Xen_to_C_generator(obj, gn, g, mus_is_two_pole, S_two_pole, "a two-pole filter");
  3706. Xen_real_to_C_double_if_bound(fm, fm1, S_two_pole, 2);
  3707. return(C_double_to_Xen_real(mus_two_pole(g, fm1)));
  3708. }
  3709. static Xen g_is_one_zero(Xen obj)
  3710. {
  3711. #define H_is_one_zero "(" S_is_one_zero " gen): " PROC_TRUE " if gen is a " S_one_zero
  3712. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_one_zero(Xen_to_mus_any(obj)))));
  3713. }
  3714. static Xen g_is_one_pole(Xen obj)
  3715. {
  3716. #define H_is_one_pole "(" S_is_one_pole " gen): " PROC_TRUE " if gen is a " S_one_pole
  3717. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_one_pole(Xen_to_mus_any(obj)))));
  3718. }
  3719. static Xen g_is_two_zero(Xen obj)
  3720. {
  3721. #define H_is_two_zero "(" S_is_two_zero " gen): " PROC_TRUE " if gen is a " S_two_zero
  3722. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_two_zero(Xen_to_mus_any(obj)))));
  3723. }
  3724. static Xen g_is_two_pole(Xen obj)
  3725. {
  3726. #define H_is_two_pole "(" S_is_two_pole " gen): " PROC_TRUE " if gen is a " S_two_pole
  3727. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_two_pole(Xen_to_mus_any(obj)))));
  3728. }
  3729. /* ---------------- formant ---------------- */
  3730. static Xen g_make_frm(bool formant_case, const char *caller, Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3731. {
  3732. mus_any *ge;
  3733. int vals;
  3734. Xen args[4];
  3735. Xen keys[2];
  3736. int orig_arg[2] = {0, 0};
  3737. mus_float_t freq = 0.0, radius = 0.0;
  3738. keys[0] = kw_frequency;
  3739. keys[1] = kw_radius;
  3740. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  3741. vals = mus_optkey_unscramble(caller, 2, keys, args, orig_arg);
  3742. if (vals > 0)
  3743. {
  3744. freq = Xen_optkey_to_float(kw_frequency, keys[0], caller, orig_arg[0], freq);
  3745. if (freq > (0.5 * mus_srate()))
  3746. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "freq > srate/2?");
  3747. radius = Xen_optkey_to_float(kw_radius, keys[1], caller, orig_arg[1], radius);
  3748. }
  3749. if (formant_case)
  3750. {
  3751. ge = mus_make_formant(freq, radius);
  3752. if (ge)
  3753. {
  3754. mus_xen *gn;
  3755. gn = mus_any_to_mus_xen(ge);
  3756. return(mus_xen_to_object(gn));
  3757. }
  3758. }
  3759. else
  3760. {
  3761. ge = mus_make_firmant(freq, radius);
  3762. if (ge)
  3763. return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  3764. }
  3765. return(Xen_false);
  3766. }
  3767. static Xen g_formant(Xen gen, Xen input, Xen freq)
  3768. {
  3769. #define H_formant "(" S_formant " gen (input 0.0) freq-in-radians): next sample from resonator generator"
  3770. mus_float_t in1 = 0.0;
  3771. mus_any *g = NULL;
  3772. mus_xen *gn;
  3773. Xen_to_C_generator(gen, gn, g, mus_is_formant, S_formant, "a formant generator");
  3774. Xen_real_to_C_double_if_bound(input, in1, S_formant, 2);
  3775. if (Xen_is_bound(freq))
  3776. return(C_double_to_Xen_real(mus_formant_with_frequency(g, in1, Xen_real_to_C_double(freq))));
  3777. return(C_double_to_Xen_real(mus_formant(g, in1)));
  3778. }
  3779. static Xen g_make_formant(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3780. {
  3781. #define H_make_formant "(" S_make_formant " frequency radius): \
  3782. return a new formant generator (a resonator). radius sets the pole radius (in terms of the 'unit circle'). \
  3783. frequency sets the resonance center frequency (Hz)."
  3784. return(g_make_frm(true, S_make_formant, arg1, arg2, arg3, arg4));
  3785. }
  3786. static Xen g_is_formant(Xen os)
  3787. {
  3788. #define H_is_formant "(" S_is_formant " gen): " PROC_TRUE " if gen is a " S_formant
  3789. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_formant(Xen_to_mus_any(os)))));
  3790. }
  3791. static Xen g_set_formant_radius_and_frequency(Xen gen, Xen rad, Xen frq)
  3792. {
  3793. #define H_mus_set_formant_radius_and_frequency "(" S_mus_set_formant_radius_and_frequency " gen radius frequency): set " S_formant " \
  3794. generator gen's radius and frequency"
  3795. mus_any *g = NULL;
  3796. mus_float_t radius, frequency;
  3797. mus_xen *gn;
  3798. Xen_to_C_generator(gen, gn, g, mus_is_formant, S_mus_set_formant_radius_and_frequency, "a formant generator");
  3799. Xen_to_C_double_or_error(rad, radius, S_mus_set_formant_radius_and_frequency, 2);
  3800. Xen_to_C_double_or_error(frq, frequency, S_mus_set_formant_radius_and_frequency, 3);
  3801. mus_set_formant_radius_and_frequency(g, radius, frequency);
  3802. return(rad);
  3803. }
  3804. static Xen g_set_formant_frequency(Xen gen, Xen frq)
  3805. {
  3806. #define H_mus_set_formant_frequency "(" S_mus_set_formant_frequency " gen frequency): set " S_formant " generator gen's frequency"
  3807. mus_any *g = NULL;
  3808. mus_float_t frequency;
  3809. mus_xen *gn;
  3810. Xen_to_C_generator(gen, gn, g, mus_is_formant, S_mus_set_formant_frequency, "a formant generator");
  3811. Xen_to_C_double_or_error(frq, frequency, S_mus_set_formant_frequency, 2);
  3812. mus_set_formant_frequency(g, frequency);
  3813. return(frq);
  3814. }
  3815. static Xen g_make_formant_bank(Xen frms, Xen amps)
  3816. {
  3817. #define H_make_formant_bank "(" S_make_formant_bank " gens amps): return a new formant-bank generator."
  3818. mus_any *ge = NULL;
  3819. mus_any **gens;
  3820. int i, j, size;
  3821. vct *v = NULL;
  3822. Xen_check_type(Xen_is_vector(frms), frms, 1, S_make_formant_bank, "a vector of formant generators");
  3823. /* need size and elements -> mus_any */
  3824. size = Xen_vector_length(frms);
  3825. if (size == 0) return(Xen_false);
  3826. gens = (mus_any **)calloc(size, sizeof(mus_any *));
  3827. if (Xen_is_bound(amps))
  3828. {
  3829. v = Xen_to_vct(amps);
  3830. if (!v) Xen_check_type(false, amps, 2, S_make_formant_bank, "a " S_vct " if anything");
  3831. }
  3832. for (i = 0, j = 0; i < size; i++)
  3833. {
  3834. Xen g;
  3835. g = Xen_vector_ref(frms, i);
  3836. if (mus_is_xen(g))
  3837. {
  3838. mus_any *fg;
  3839. fg = Xen_to_mus_any(g);
  3840. if (mus_is_formant(fg))
  3841. gens[j++] = fg;
  3842. }
  3843. }
  3844. if (j > 0)
  3845. ge = mus_make_formant_bank(j, gens, (v) ? mus_vct_data(v) : NULL);
  3846. free(gens);
  3847. if (ge)
  3848. {
  3849. if (v)
  3850. return(mus_xen_to_object(mus_any_to_mus_xen_with_two_vcts(ge, frms, amps)));
  3851. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, frms)));
  3852. }
  3853. return(Xen_false);
  3854. }
  3855. static Xen g_is_formant_bank(Xen os)
  3856. {
  3857. #define H_is_formant_bank "(" S_is_formant_bank " gen): " PROC_TRUE " if gen is a " S_formant_bank
  3858. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_formant_bank(Xen_to_mus_any(os)))));
  3859. }
  3860. static Xen g_formant_bank(Xen gens, Xen inp)
  3861. {
  3862. #define H_formant_bank "(" S_formant_bank " gens inval): sum a bank of " S_formant " generators"
  3863. mus_any *bank = NULL;
  3864. mus_xen *gn;
  3865. Xen_to_C_generator(gens, gn, bank, mus_is_formant_bank, S_formant_bank, "a formant-bank generator");
  3866. if (mus_is_vct(inp))
  3867. return(C_double_to_Xen_real(mus_formant_bank_with_inputs(bank, mus_vct_data(Xen_to_vct(inp)))));
  3868. if (Xen_is_number(inp))
  3869. return(C_double_to_Xen_real(mus_formant_bank(bank, Xen_real_to_C_double(inp))));
  3870. if (!Xen_is_bound(inp))
  3871. return(C_double_to_Xen_real(mus_formant_bank(bank, 0.0)));
  3872. Xen_check_type(false, inp, 2, S_formant_bank, "a number or a " S_vct);
  3873. return(Xen_false);
  3874. }
  3875. /* ---------------- one-pole-all-pass ---------------- */
  3876. static Xen g_make_one_pole_all_pass(Xen arg1, Xen arg2)
  3877. {
  3878. #define H_make_one_pole_all_pass "(" S_make_one_pole_all_pass " size coeff): return a new one-pole-all-pass generator."
  3879. mus_any *ge = NULL;
  3880. int size;
  3881. mus_float_t coeff;
  3882. Xen_check_type(Xen_is_integer(arg1), arg1, 1, S_make_one_pole_all_pass, "an integer");
  3883. #if (!HAVE_SCHEME)
  3884. Xen_check_type(Xen_is_number(arg2), arg2, 2, S_make_one_pole_all_pass, "a number");
  3885. #endif
  3886. size = Xen_integer_to_C_int(arg1);
  3887. if (size < 0)
  3888. Xen_out_of_range_error(S_make_one_pole_all_pass, 1, arg1, "size < 0?");
  3889. if (size == 0) return(Xen_false);
  3890. coeff = Xen_real_to_C_double(arg2);
  3891. ge = mus_make_one_pole_all_pass(size, coeff);
  3892. if (ge)
  3893. return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  3894. return(Xen_false);
  3895. }
  3896. static Xen g_is_one_pole_all_pass(Xen os)
  3897. {
  3898. #define H_is_one_pole_all_pass "(" S_is_one_pole_all_pass " gen): " PROC_TRUE " if gen is a " S_one_pole_all_pass
  3899. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_one_pole_all_pass(Xen_to_mus_any(os)))));
  3900. }
  3901. static Xen g_one_pole_all_pass(Xen gen, Xen fm)
  3902. {
  3903. #define H_one_pole_all_pass "(" S_one_pole_all_pass " gen (input 0.0)): run a one-pole-all-pass generator"
  3904. mus_float_t in1 = 0.0;
  3905. mus_any *g = NULL;
  3906. mus_xen *gn;
  3907. Xen_to_C_generator(gen, gn, g, mus_is_one_pole_all_pass, S_one_pole_all_pass, "a one-pole-all-pass generator");
  3908. Xen_real_to_C_double_if_bound(fm, in1, S_one_pole_all_pass, 2);
  3909. return(C_double_to_Xen_real(mus_one_pole_all_pass(g, in1)));
  3910. }
  3911. /* ---------------- firmant ---------------- */
  3912. static Xen g_make_firmant(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  3913. {
  3914. #define H_make_firmant "(" S_make_firmant " frequency radius): \
  3915. return a new firmant generator (a resonator). radius sets the pole radius (in terms of the 'unit circle'). \
  3916. frequency sets the resonance center frequency (Hz)."
  3917. return(g_make_frm(false, S_make_firmant, arg1, arg2, arg3, arg4));
  3918. }
  3919. static Xen g_is_firmant(Xen os)
  3920. {
  3921. #define H_is_firmant "(" S_is_firmant " gen): " PROC_TRUE " if gen is a " S_firmant " generator"
  3922. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_firmant(Xen_to_mus_any(os)))));
  3923. }
  3924. static Xen g_firmant(Xen gen, Xen input, Xen freq)
  3925. {
  3926. #define H_firmant "(" S_firmant " gen (input 0.0) freq-in-radians): next sample from resonator generator"
  3927. mus_float_t in1 = 0.0;
  3928. mus_any *g = NULL;
  3929. mus_xen *gn;
  3930. Xen_to_C_generator(gen, gn, g, mus_is_firmant, S_firmant, "a firmant generator");
  3931. Xen_real_to_C_double_if_bound(input, in1, S_firmant, 2);
  3932. if (Xen_is_bound(freq))
  3933. return(C_double_to_Xen_real(mus_firmant_with_frequency(g, in1, Xen_real_to_C_double(freq))));
  3934. return(C_double_to_Xen_real(mus_firmant(g, in1)));
  3935. }
  3936. static mus_float_t mus_pink_noise(vct *v)
  3937. {
  3938. int i, size;
  3939. mus_float_t sum = 0.0, amp, x;
  3940. mus_float_t *data;
  3941. size = mus_vct_length(v);
  3942. data = mus_vct_data(v);
  3943. amp = data[0];
  3944. for (i = 2, x = 0.5; i < size; i += 2, x *= 0.5)
  3945. {
  3946. sum += data[i];
  3947. data[i + 1] -= x;
  3948. if (data[i + 1] < 0.0)
  3949. {
  3950. data[i] = mus_random(amp);
  3951. data[i + 1] += 1.0;
  3952. }
  3953. }
  3954. return(sum + mus_random(amp));
  3955. }
  3956. #define S_pink_noise "pink-noise"
  3957. static Xen g_pink_noise(Xen gens)
  3958. {
  3959. #define H_pink_noise "(pink-noise gens) generates an approximation to pink noise."
  3960. int size;
  3961. vct *v;
  3962. Xen_check_type((mus_is_vct(gens)) && (Xen_vector_rank(gens) == 1), gens, 1, S_pink_noise, "a " S_vct);
  3963. v = Xen_to_vct(gens);
  3964. size = mus_vct_length(v);
  3965. if (size == 0)
  3966. return(XEN_ZERO); /* needs to be upper case for Forth/Ruby */
  3967. Xen_check_type((size & 1) == 0, gens, 1, S_pink_noise, "an even length " S_vct);
  3968. return(C_double_to_Xen_real(mus_pink_noise(v)));
  3969. }
  3970. #if HAVE_SCHEME
  3971. static s7_double piano_noise(s7_int *g, s7_double noi)
  3972. {
  3973. g[0] = ((g[0] * 1103515245) + 12345) & 0xffffffff;
  3974. noi *= (((s7_double)g[0] * 4.6566128730774e-10) - 1.0);
  3975. return(noi);
  3976. }
  3977. #define S_piano_noise "piano-noise"
  3978. static Xen g_piano_noise(Xen gen, XEN amp)
  3979. {
  3980. #define H_piano_noise "(piano-noise gen amp) generates the noise used in the piano instrument."
  3981. if (!s7_is_int_vector(gen)) s7_wrong_type_arg_error(s7, S_piano_noise, 1, gen, "an int-vector");
  3982. if (!s7_is_real(amp)) s7_wrong_type_arg_error(s7, S_piano_noise, 2, amp, "a real");
  3983. return(C_double_to_Xen_real(piano_noise(s7_int_vector_elements(gen), Xen_real_to_C_double(amp))));
  3984. }
  3985. #define S_singer_filter "singer-filter"
  3986. static Xen g_singer_filter(Xen start, Xen end, Xen tmp, Xen dline1, Xen dline2, Xen coeffs)
  3987. {
  3988. #define H_singer_filter "this is an optimization for the singer instrument"
  3989. int j, k, beg, lim;
  3990. s7_double *d1, *d2, *cf;
  3991. s7_double temp;
  3992. if (!s7_is_integer(start)) s7_wrong_type_arg_error(s7, S_singer_filter, 1, start, "an integer");
  3993. if (!s7_is_integer(end)) s7_wrong_type_arg_error(s7, S_singer_filter, 2, end, "an integer");
  3994. if (!s7_is_real(tmp)) s7_wrong_type_arg_error(s7, S_singer_filter, 3, tmp, "a real");
  3995. if (!s7_is_float_vector(dline1)) s7_wrong_type_arg_error(s7, S_singer_filter, 4, dline1, "a float-vector");
  3996. if (!s7_is_float_vector(dline2)) s7_wrong_type_arg_error(s7, S_singer_filter, 5, dline2, "a float-vector");
  3997. if (!s7_is_float_vector(coeffs)) s7_wrong_type_arg_error(s7, S_singer_filter, 6, coeffs, "a float-vector");
  3998. beg = s7_integer(start);
  3999. lim = s7_integer(end);
  4000. d1 = s7_float_vector_elements(dline1);
  4001. d2 = s7_float_vector_elements(dline2);
  4002. cf = s7_float_vector_elements(coeffs);
  4003. temp = s7_number_to_real(s7, tmp);
  4004. for (k = beg, j = beg + 1; j < lim; k++, j++)
  4005. {
  4006. s7_double temp1, x;
  4007. x = d2[j + 1];
  4008. d2[j] = x + (cf[j] * (d1[k] - x));
  4009. temp1 = temp;
  4010. temp = d1[k] + d2[j] - x;
  4011. d1[k] = temp1;
  4012. }
  4013. return(s7_make_real(s7, temp));
  4014. }
  4015. #define S_singer_nose_filter "singer-nose-filter"
  4016. static Xen g_singer_nose_filter(Xen end, Xen tmp, Xen dline1, Xen dline2, Xen coeffs)
  4017. {
  4018. #define H_singer_nose_filter "this is an optimization for the singer instrument"
  4019. int j, k, lim;
  4020. s7_double *d1, *d2, *cf;
  4021. s7_double temp;
  4022. if (!s7_is_integer(end)) s7_wrong_type_arg_error(s7, S_singer_nose_filter, 1, end, "an integer");
  4023. if (!s7_is_real(tmp)) s7_wrong_type_arg_error(s7, S_singer_nose_filter, 2, tmp, "a real");
  4024. if (!s7_is_float_vector(dline1)) s7_wrong_type_arg_error(s7, S_singer_nose_filter, 3, dline1, "a float-vector");
  4025. if (!s7_is_float_vector(dline2)) s7_wrong_type_arg_error(s7, S_singer_nose_filter, 4, dline2, "a float-vector");
  4026. if (!s7_is_float_vector(coeffs)) s7_wrong_type_arg_error(s7, S_singer_nose_filter, 5, coeffs, "a float-vector");
  4027. lim = s7_integer(end);
  4028. d1 = s7_float_vector_elements(dline1);
  4029. d2 = s7_float_vector_elements(dline2);
  4030. cf = s7_float_vector_elements(coeffs);
  4031. temp = s7_number_to_real(s7, tmp);
  4032. for (k = 1, j = 2; j < lim; k++, j++)
  4033. {
  4034. s7_double t1, reftemp;
  4035. reftemp = cf[j] * (d1[k] - d2[j + 1]);
  4036. d2[j] = d2[j + 1] + reftemp;
  4037. t1 = temp;
  4038. temp = d1[k] + reftemp;
  4039. d1[k] = t1;
  4040. }
  4041. return(s7_make_real(s7, temp));
  4042. }
  4043. #endif
  4044. /* ---------------- wave-train ---------------- */
  4045. static Xen g_make_wave_train(Xen arglist)
  4046. {
  4047. #define H_make_wave_train "(" S_make_wave_train " (frequency *clm-default-frequency*) (initial-phase 0.0) (wave) (size clm-table-size) (type)): \
  4048. return a new wave-train generator (an extension of pulse-train). Frequency is \
  4049. the repetition rate of the wave found in wave. Successive waves can overlap."
  4050. mus_any *ge;
  4051. Xen args[10];
  4052. Xen keys[5];
  4053. int orig_arg[5] = {0, 0, 0, 0, MUS_INTERP_LINEAR};
  4054. int vals;
  4055. mus_long_t wsize = clm_table_size;
  4056. Xen orig_v = Xen_false;
  4057. mus_float_t freq, phase = 0.0;
  4058. mus_float_t *wave = NULL;
  4059. int interp_type = (int)MUS_INTERP_LINEAR;
  4060. freq = clm_default_frequency;
  4061. keys[0] = kw_frequency;
  4062. keys[1] = kw_initial_phase;
  4063. keys[2] = kw_wave;
  4064. keys[3] = kw_size;
  4065. keys[4] = kw_type;
  4066. {
  4067. Xen p;
  4068. int i, arglist_len;
  4069. arglist_len = Xen_list_length(arglist);
  4070. if (arglist_len > 10) clm_error(S_make_wave_train, "too many arguments!", arglist);
  4071. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  4072. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  4073. }
  4074. vals = mus_optkey_unscramble(S_make_wave_train, 5, keys, args, orig_arg);
  4075. if (vals > 0)
  4076. {
  4077. vct *v = NULL;
  4078. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_wave_train, orig_arg[0], freq);
  4079. if (freq > (0.5 * mus_srate()))
  4080. Xen_out_of_range_error(S_make_wave_train, orig_arg[0], keys[0], "freq > srate/2?");
  4081. if (freq < 0.0)
  4082. Xen_out_of_range_error(S_make_wave_train, orig_arg[0], keys[0], "freq < 0.0?");
  4083. phase = Xen_optkey_to_float(kw_initial_phase, keys[1], S_make_wave_train, orig_arg[1], phase);
  4084. if (phase < 0.0)
  4085. Xen_out_of_range_error(S_make_wave_train, orig_arg[1], keys[1], "phase < 0.0?");
  4086. v = mus_optkey_to_vct(keys[2], S_make_wave_train, orig_arg[2], NULL);
  4087. if (v)
  4088. {
  4089. orig_v = keys[2];
  4090. wave = mus_vct_data(v);
  4091. wsize = mus_vct_length(v);
  4092. }
  4093. wsize = Xen_optkey_to_mus_long_t(kw_size, keys[3], S_make_wave_train, orig_arg[3], wsize);
  4094. if (wsize <= 0)
  4095. Xen_out_of_range_error(S_make_wave_train, orig_arg[3], keys[3], "size <= 0?");
  4096. if (wsize > mus_max_table_size())
  4097. Xen_out_of_range_error(S_make_wave_train, orig_arg[3], keys[3], "size too large (see mus-max-table-size)");
  4098. if ((v) && (wsize > mus_vct_length(v)))
  4099. Xen_out_of_range_error(S_make_wave_train, orig_arg[3], keys[3], "table size > wave size");
  4100. interp_type = Xen_optkey_to_int(kw_type, keys[4], S_make_wave_train, orig_arg[4], interp_type);
  4101. if (!(mus_is_interp_type(interp_type)))
  4102. Xen_out_of_range_error(S_make_wave_train, orig_arg[4], keys[4], "no such interp-type");
  4103. }
  4104. if (wave == NULL)
  4105. {
  4106. wave = (mus_float_t *)calloc(wsize, sizeof(mus_float_t));
  4107. if (wave == NULL)
  4108. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate wave-train table", S_make_wave_train));
  4109. orig_v = xen_make_vct(wsize, wave);
  4110. }
  4111. ge = mus_make_wave_train(freq, phase, wave, wsize, (mus_interp_t)interp_type);
  4112. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  4113. }
  4114. static Xen g_wave_train(Xen obj, Xen fm)
  4115. {
  4116. #define H_wave_train "(" S_wave_train " gen (fm 0.0)): next sample of " S_wave_train
  4117. mus_float_t fm1 = 0.0;
  4118. mus_any *g = NULL;
  4119. mus_xen *gn;
  4120. Xen_to_C_generator(obj, gn, g, mus_is_wave_train, S_wave_train, "a wave-train generator");
  4121. Xen_real_to_C_double_if_bound(fm, fm1, S_wave_train, 2);
  4122. return(C_double_to_Xen_real(mus_wave_train(g, fm1)));
  4123. }
  4124. static Xen g_is_wave_train(Xen obj)
  4125. {
  4126. #define H_is_wave_train "(" S_is_wave_train " gen): " PROC_TRUE " if gen is a " S_wave_train
  4127. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_wave_train(Xen_to_mus_any(obj)))));
  4128. }
  4129. /* ---------------- waveshaping ---------------- */
  4130. enum {NO_PROBLEM_IN_LIST, NULL_LIST, ODD_LENGTH_LIST, NON_NUMBER_IN_LIST, NEGATIVE_NUMBER_IN_LIST, HUGE_NUMBER_IN_LIST};
  4131. static const char *list_to_partials_error_to_string(int code)
  4132. {
  4133. switch (code)
  4134. {
  4135. case NO_PROBLEM_IN_LIST: return("~A: nothing wrong with partials list?? ~A"); break;
  4136. case NULL_LIST: return("~A: partials list is null, ~A"); break;
  4137. case ODD_LENGTH_LIST: return("~A: partials list has an odd number of elements: ~A"); break;
  4138. case NON_NUMBER_IN_LIST: return("~A: partials list has a non-numerical element: ~A"); break;
  4139. case NEGATIVE_NUMBER_IN_LIST: return("~A: partials list has a partial number that is negative: ~A"); break;
  4140. case HUGE_NUMBER_IN_LIST: return("~A: partials list has a partial number that is too large: ~A"); break;
  4141. }
  4142. return("~A: unknown error, ~A");
  4143. }
  4144. static mus_float_t *list_to_partials(Xen harms, int *npartials, int *error_code)
  4145. {
  4146. int listlen, i, maxpartial = 0, curpartial;
  4147. mus_float_t *partials = NULL;
  4148. Xen lst;
  4149. listlen = Xen_list_length(harms);
  4150. if (listlen == 0)
  4151. {
  4152. (*error_code) = NULL_LIST;
  4153. return(NULL);
  4154. }
  4155. if (listlen & 1)
  4156. {
  4157. (*error_code) = ODD_LENGTH_LIST;
  4158. return(NULL);
  4159. }
  4160. if (!(Xen_is_number(Xen_car(harms))))
  4161. {
  4162. (*error_code) = NON_NUMBER_IN_LIST;
  4163. return(NULL);
  4164. }
  4165. /* the list is '(partial-number partial-amp ... ) */
  4166. (*error_code) = NO_PROBLEM_IN_LIST;
  4167. for (i = 0, lst = Xen_copy_arg(harms); i < listlen; i += 2, lst = Xen_cddr(lst))
  4168. {
  4169. if ((!(Xen_is_integer(Xen_car(lst)))) ||
  4170. (!(Xen_is_number(Xen_cadr(lst)))))
  4171. {
  4172. (*error_code) = NON_NUMBER_IN_LIST;
  4173. return(NULL);
  4174. }
  4175. curpartial = Xen_integer_to_C_int(Xen_car(lst));
  4176. if (curpartial < 0)
  4177. {
  4178. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4179. return(NULL);
  4180. }
  4181. if (curpartial > maxpartial)
  4182. maxpartial = curpartial;
  4183. }
  4184. if (maxpartial > 10000000)
  4185. {
  4186. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4187. return(NULL);
  4188. }
  4189. partials = (mus_float_t *)calloc(maxpartial + 1, sizeof(mus_float_t));
  4190. /* here and elsewhere? this won't be null until we touch it in linux, but that gloms up all our
  4191. * code with once-in-a-billion-years error checks.
  4192. */
  4193. if (partials == NULL)
  4194. mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate waveshaping partials list");
  4195. (*npartials) = maxpartial + 1;
  4196. for (i = 0, lst = Xen_copy_arg(harms); i < listlen; i += 2, lst = Xen_cddr(lst))
  4197. {
  4198. curpartial = Xen_integer_to_C_int(Xen_car(lst));
  4199. partials[curpartial] = (mus_float_t)Xen_real_to_C_double(Xen_cadr(lst));
  4200. }
  4201. return(partials);
  4202. }
  4203. static mus_float_t *mus_vct_to_partials(vct *v, int *npartials, int *error_code)
  4204. {
  4205. int len, i, maxpartial, curpartial;
  4206. mus_float_t *partials = NULL, *vdata;
  4207. len = mus_vct_length(v);
  4208. if (len == 0)
  4209. {
  4210. (*error_code) = NULL_LIST;
  4211. return(NULL);
  4212. }
  4213. if (len & 1)
  4214. {
  4215. (*error_code) = ODD_LENGTH_LIST;
  4216. return(NULL);
  4217. }
  4218. (*error_code) = NO_PROBLEM_IN_LIST;
  4219. vdata = mus_vct_data(v);
  4220. maxpartial = (int)(vdata[0]);
  4221. if (maxpartial < 0)
  4222. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4223. else
  4224. {
  4225. for (i = 2; i < len; i += 2)
  4226. {
  4227. curpartial = (int)(vdata[i]);
  4228. if (curpartial > maxpartial)
  4229. maxpartial = curpartial;
  4230. if (curpartial < 0)
  4231. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4232. }
  4233. }
  4234. if ((*error_code) != NO_PROBLEM_IN_LIST)
  4235. return(NULL);
  4236. partials = (mus_float_t *)calloc(maxpartial + 1, sizeof(mus_float_t));
  4237. if (partials == NULL)
  4238. mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate waveshaping partials list");
  4239. (*npartials) = maxpartial + 1;
  4240. for (i = 0; i < len; i += 2)
  4241. {
  4242. curpartial = (int)(vdata[i]);
  4243. partials[curpartial] = vdata[i + 1];
  4244. }
  4245. return(partials);
  4246. }
  4247. static mus_float_t *mus_vector_to_partials(Xen v, int *npartials, int *error_code)
  4248. {
  4249. int len, i, maxpartial, curpartial;
  4250. mus_float_t *partials = NULL;
  4251. len = Xen_vector_length(v);
  4252. if (len == 0)
  4253. {
  4254. (*error_code) = NULL_LIST;
  4255. return(NULL);
  4256. }
  4257. if (len & 1)
  4258. {
  4259. (*error_code) = ODD_LENGTH_LIST;
  4260. return(NULL);
  4261. }
  4262. (*error_code) = NO_PROBLEM_IN_LIST;
  4263. maxpartial = (int)(Xen_integer_to_C_int(Xen_vector_ref(v, 0)));
  4264. if (maxpartial < 0)
  4265. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4266. else
  4267. {
  4268. for (i = 2; i < len; i += 2)
  4269. {
  4270. curpartial = (int)(Xen_integer_to_C_int(Xen_vector_ref(v, i)));
  4271. if (curpartial > maxpartial)
  4272. maxpartial = curpartial;
  4273. if (curpartial < 0)
  4274. (*error_code) = NEGATIVE_NUMBER_IN_LIST;
  4275. }
  4276. }
  4277. if ((*error_code) != NO_PROBLEM_IN_LIST)
  4278. return(NULL);
  4279. partials = (mus_float_t *)calloc(maxpartial + 1, sizeof(mus_float_t));
  4280. if (partials == NULL)
  4281. mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate waveshaping partials list");
  4282. (*npartials) = maxpartial + 1;
  4283. for (i = 0; i < len; i += 2)
  4284. {
  4285. curpartial = (int)(Xen_integer_to_C_int(Xen_vector_ref(v, i)));
  4286. partials[curpartial] = Xen_real_to_C_double(Xen_vector_ref(v, i + 1));
  4287. }
  4288. return(partials);
  4289. }
  4290. static Xen g_partials_to_polynomial(Xen amps, Xen ukind)
  4291. {
  4292. #if HAVE_SCHEME
  4293. #define p2p_example "(let ((v0 (partials->polynomial '(1 1.0 2 1.0)))\n (os (make-oscil)))\n (polynomial v0 (oscil os)))"
  4294. #endif
  4295. #if HAVE_RUBY
  4296. #define p2p_example "v0 = partials2polynomial([1, 1.0, 2, 1.0])\n os = make_oscil()\n polynomial(v0, oscil(os))"
  4297. #endif
  4298. #if HAVE_FORTH
  4299. #define p2p_example "'( 1 1.0 2 1.0 ) partials->polynomial value v0\n make-oscil value os\n v0 os 0.0 0.0 oscil polynomial"
  4300. #endif
  4301. #define H_partials_to_polynomial "(" S_partials_to_polynomial " partials (kind " S_mus_chebyshev_first_kind ")): \
  4302. produce a Chebyshev polynomial suitable for use with the " S_polynomial " generator \
  4303. to create (via waveshaping) the harmonic spectrum described by the partials argument:\n " p2p_example
  4304. int npartials = 0;
  4305. mus_polynomial_t kind = MUS_CHEBYSHEV_FIRST_KIND;
  4306. mus_float_t *partials = NULL, *wave;
  4307. int error = NO_PROBLEM_IN_LIST;
  4308. Xen_check_type(mus_is_vct(amps) || Xen_is_list(amps), amps, 1, S_partials_to_polynomial, "a list or a " S_vct);
  4309. Xen_check_type(Xen_is_integer_or_unbound(ukind), ukind, 2, S_partials_to_polynomial, "either " S_mus_chebyshev_first_kind " or " S_mus_chebyshev_second_kind);
  4310. if (Xen_is_integer(ukind))
  4311. {
  4312. int ck;
  4313. ck = Xen_integer_to_C_int(ukind);
  4314. if ((ck >= MUS_CHEBYSHEV_EITHER_KIND) && (ck <= MUS_CHEBYSHEV_SECOND_KIND))
  4315. kind = (mus_polynomial_t)ck;
  4316. else Xen_out_of_range_error(S_partials_to_polynomial, 2, ukind, "unknown Chebyshev polynomial kind");
  4317. }
  4318. if (mus_is_vct(amps))
  4319. partials = mus_vct_to_partials(Xen_to_vct(amps), &npartials, &error);
  4320. else partials = list_to_partials(amps, &npartials, &error);
  4321. if (partials == NULL)
  4322. Xen_error(NO_DATA,
  4323. Xen_list_3(C_string_to_Xen_string(list_to_partials_error_to_string(error)),
  4324. C_string_to_Xen_string(S_partials_to_polynomial),
  4325. amps));
  4326. wave = mus_partials_to_polynomial(npartials, partials, kind); /* wave == partials; in both vct and list cases, partials is newly allocated */
  4327. return(xen_make_vct(npartials, wave));
  4328. }
  4329. static Xen g_normalize_partials(Xen partials)
  4330. {
  4331. #define H_normalize_partials "(" S_normalize_partials " partials) scales the \
  4332. partial amplitudes in the " S_vct " or list 'partials' by the inverse of their sum (so that they add to 1.0)."
  4333. vct *v;
  4334. Xen xv = Xen_false;
  4335. Xen_check_type(((Xen_is_list(partials)) && (!Xen_is_null(partials))) || (mus_is_vct(partials)), partials, 1, S_normalize_partials, "a " S_vct " or (non-empty) list");
  4336. if (mus_is_vct(partials))
  4337. xv = partials;
  4338. else xv = xen_list_to_vct(partials);
  4339. v = Xen_to_vct(xv);
  4340. if ((mus_vct_length(v) > 1) &&
  4341. ((mus_vct_length(v) & 1) == 0))
  4342. mus_normalize_partials(mus_vct_length(v) / 2, mus_vct_data(v));
  4343. else Xen_error(BAD_TYPE,
  4344. Xen_list_3(C_string_to_Xen_string("~A: partials, ~A, must be a non-empty list or " S_vct " of even length (partial-number partial-amp ...)"),
  4345. C_string_to_Xen_string(S_normalize_partials),
  4346. partials));
  4347. return(xv);
  4348. }
  4349. static mus_float_t *vector_to_float_array(Xen v)
  4350. {
  4351. mus_float_t *data;
  4352. mus_long_t i, len;
  4353. len = Xen_vector_length(v);
  4354. data = (mus_float_t *)malloc(len * sizeof(mus_float_t));
  4355. for (i = 0; i < len; i++)
  4356. data[i] = Xen_real_to_C_double(Xen_vector_ref(v, i));
  4357. return(data);
  4358. }
  4359. static Xen g_chebyshev_tu_sum(Xen x, Xen tn, Xen un)
  4360. {
  4361. #define H_chebyshev_tu_sum "(" S_mus_chebyshev_tu_sum " x tn un) returns the sum of the weighted\
  4362. Chebyshev polynomials Tn and Un (vectors or " S_vct "s), with phase x."
  4363. bool need_free = false;
  4364. int len = 0;
  4365. mus_float_t *tdata = NULL, *udata = NULL;
  4366. Xen result;
  4367. Xen_check_type(Xen_is_double(x), x, 1, S_mus_chebyshev_tu_sum, "a float");
  4368. if ((mus_is_vct(tn)) &&
  4369. (mus_is_vct(un)))
  4370. {
  4371. vct *Tn, *Un;
  4372. Tn = Xen_to_vct(tn);
  4373. tdata = mus_vct_data(Tn);
  4374. Un = Xen_to_vct(un);
  4375. udata = mus_vct_data(Un);
  4376. len = mus_vct_length(Tn);
  4377. if (len == 0) return(C_double_to_Xen_real(0.0));
  4378. if (len != mus_vct_length(Un)) return(C_double_to_Xen_real(0.0));
  4379. }
  4380. else
  4381. {
  4382. if ((Xen_is_vector(tn)) &&
  4383. (Xen_is_vector(un)))
  4384. {
  4385. len = Xen_vector_length(tn);
  4386. if (len == 0) return(C_double_to_Xen_real(0.0));
  4387. if (len != Xen_vector_length(un)) return(C_double_to_Xen_real(0.0));
  4388. tdata = vector_to_float_array(tn);
  4389. udata = vector_to_float_array(un);
  4390. need_free = true;
  4391. }
  4392. else
  4393. {
  4394. Xen_check_type(false, tn, 1, S_mus_chebyshev_tu_sum, "both arrays should be either " S_vct "s or vectors");
  4395. }
  4396. }
  4397. result = C_double_to_Xen_real(mus_chebyshev_tu_sum(Xen_real_to_C_double(x), len, tdata, udata));
  4398. if (need_free)
  4399. {
  4400. free(tdata);
  4401. free(udata);
  4402. }
  4403. return(result);
  4404. }
  4405. static Xen g_chebyshev_t_sum(Xen x, Xen tn)
  4406. {
  4407. #define H_chebyshev_t_sum "(" S_mus_chebyshev_t_sum " x tn) returns the sum of the weighted \
  4408. Chebyshev polynomials Tn (a " S_vct ")."
  4409. bool need_free = false;
  4410. int len = 0;
  4411. mus_float_t *data = NULL;
  4412. Xen result;
  4413. Xen_check_type(Xen_is_double(x), x, 1, S_mus_chebyshev_t_sum, "a float");
  4414. if (mus_is_vct(tn))
  4415. {
  4416. vct *Tn;
  4417. Tn = Xen_to_vct(tn);
  4418. data = mus_vct_data(Tn);
  4419. len = mus_vct_length(Tn);
  4420. if (len == 0) return(C_double_to_Xen_real(0.0));
  4421. }
  4422. else
  4423. {
  4424. if (Xen_is_vector(tn))
  4425. {
  4426. len = Xen_vector_length(tn);
  4427. if (len == 0) return(C_double_to_Xen_real(0.0));
  4428. data = vector_to_float_array(tn);
  4429. need_free = true;
  4430. }
  4431. else Xen_check_type(false, tn, 1, S_mus_chebyshev_t_sum, "a " S_vct " or a vector");
  4432. }
  4433. result = C_double_to_Xen_real(mus_chebyshev_t_sum(Xen_real_to_C_double(x), len, data));
  4434. if (need_free)
  4435. free(data);
  4436. return(result);
  4437. }
  4438. static Xen g_chebyshev_u_sum(Xen x, Xen un)
  4439. {
  4440. #define H_chebyshev_u_sum "(" S_mus_chebyshev_u_sum " x un) returns the sum of the weighted \
  4441. Chebyshev polynomials Un (a " S_vct ")."
  4442. bool need_free = false;
  4443. int len = 0;
  4444. mus_float_t *data = NULL;
  4445. Xen result;
  4446. Xen_check_type(Xen_is_double(x), x, 1, S_mus_chebyshev_u_sum, "a float");
  4447. if (mus_is_vct(un))
  4448. {
  4449. vct *Un;
  4450. Un = Xen_to_vct(un);
  4451. len = mus_vct_length(Un);
  4452. if (len == 0) return(C_double_to_Xen_real(0.0));
  4453. data = mus_vct_data(Un);
  4454. }
  4455. else
  4456. {
  4457. if (Xen_is_vector(un))
  4458. {
  4459. len = Xen_vector_length(un);
  4460. if (len == 0) return(C_double_to_Xen_real(0.0));
  4461. data = vector_to_float_array(un);
  4462. need_free = true;
  4463. }
  4464. else Xen_check_type(false, un, 1, S_mus_chebyshev_u_sum, "a " S_vct " or a vector");
  4465. }
  4466. result = C_double_to_Xen_real(mus_chebyshev_u_sum(Xen_real_to_C_double(x), len, data));
  4467. if (need_free)
  4468. free(data);
  4469. return(result);
  4470. }
  4471. /* ---------------- polyshape ---------------- */
  4472. static Xen g_polyshape(Xen obj, Xen index, Xen fm)
  4473. {
  4474. #define H_polyshape "(" S_polyshape " gen (index 1.0) (fm 0.0)): next sample of polynomial-based waveshaper"
  4475. mus_float_t fm1 = 0.0, index1 = 1.0;
  4476. mus_any *g = NULL;
  4477. mus_xen *gn;
  4478. Xen_to_C_generator(obj, gn, g, mus_is_polyshape, S_polyshape, "a polyshape generator");
  4479. Xen_real_to_C_double_if_bound(index, index1, S_polyshape, 2);
  4480. Xen_real_to_C_double_if_bound(fm, fm1, S_polyshape, 3);
  4481. return(C_double_to_Xen_real(mus_polyshape(g, index1, fm1)));
  4482. }
  4483. static Xen g_is_polyshape(Xen obj)
  4484. {
  4485. #define H_is_polyshape "(" S_is_polyshape " gen): " PROC_TRUE " if gen is a " S_polyshape
  4486. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_polyshape(Xen_to_mus_any(obj)))));
  4487. }
  4488. static Xen g_make_polyshape(Xen arglist)
  4489. {
  4490. #define H_make_polyshape "(" S_make_polyshape " (frequency *clm-default-frequency*) (initial-phase 0.0) (coeffs) (partials '(1 1)) (kind " S_mus_chebyshev_first_kind ")): \
  4491. return a new polynomial-based waveshaping generator:\n\
  4492. (" S_make_polyshape " :coeffs (" S_partials_to_polynomial " '(1 1.0)))\n\
  4493. is the same in effect as " S_make_oscil
  4494. mus_any *ge;
  4495. Xen args[10];
  4496. Xen keys[5];
  4497. int orig_arg[5] = {0, 0, 0, 0, 0};
  4498. int vals, csize = 0, npartials = 0;
  4499. Xen orig_v = Xen_false;
  4500. mus_float_t freq, phase = 0.0;
  4501. /*
  4502. * if we followed the definition directly, the initial phase default would be M_PI_2 (pi/2) so that
  4503. * we drive the Tn's with a cosine. But I've always used sine instead, so I think I'll leave
  4504. * it that way. There is no difference in the output waveform except an overall phase
  4505. * offset. So, with sine, the phases rotate through cos sin -cos -sin... rather than being all cos,
  4506. * but these add to exactly the same actual wave -- what you'd expect since Tn doesn't know
  4507. * where we started. This also does not affect "signification".
  4508. */
  4509. mus_float_t *coeffs = NULL;
  4510. mus_polynomial_t kind = MUS_CHEBYSHEV_FIRST_KIND;
  4511. freq = clm_default_frequency;
  4512. keys[0] = kw_frequency;
  4513. keys[1] = kw_initial_phase;
  4514. keys[2] = kw_coeffs;
  4515. keys[3] = kw_partials;
  4516. keys[4] = kw_kind;
  4517. {
  4518. int i, arglist_len;
  4519. Xen p;
  4520. arglist_len = Xen_list_length(arglist);
  4521. if (arglist_len > 10) clm_error(S_make_polyshape, "too many arguments!", arglist);
  4522. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  4523. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  4524. }
  4525. vals = mus_optkey_unscramble(S_make_polyshape, 5, keys, args, orig_arg);
  4526. if (vals > 0)
  4527. {
  4528. vct *v = NULL;
  4529. int ck;
  4530. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_polyshape, orig_arg[0], freq);
  4531. if (freq > (0.5 * mus_srate()))
  4532. Xen_out_of_range_error(S_make_polyshape, orig_arg[0], keys[0], "freq > srate/2?");
  4533. phase = Xen_optkey_to_float(kw_initial_phase, keys[1], S_make_polyshape, orig_arg[2], phase);
  4534. ck = Xen_optkey_to_int(kw_kind, keys[4], S_make_polyshape, orig_arg[4], (int)kind);
  4535. if ((ck >= MUS_CHEBYSHEV_EITHER_KIND) && (ck <= MUS_CHEBYSHEV_SECOND_KIND))
  4536. kind = (mus_polynomial_t)ck;
  4537. else Xen_out_of_range_error(S_make_polyshape, orig_arg[4], keys[4], "unknown Chebyshev polynomial kind");
  4538. v = mus_optkey_to_vct(keys[2], S_make_polyshape, orig_arg[2], NULL);
  4539. if (v)
  4540. {
  4541. orig_v = keys[2];
  4542. coeffs = mus_vct_data(v);
  4543. csize = mus_vct_length(v);
  4544. }
  4545. else
  4546. {
  4547. if (!(Xen_is_keyword(keys[3])))
  4548. {
  4549. mus_float_t *partials = NULL;
  4550. int error = NO_PROBLEM_IN_LIST;
  4551. if (mus_is_vct(keys[3]))
  4552. partials = mus_vct_to_partials(Xen_to_vct(keys[3]), &npartials, &error);
  4553. else
  4554. {
  4555. Xen_check_type(Xen_is_list(keys[3]), keys[3], orig_arg[3], S_make_polyshape, "a list or a " S_vct);
  4556. partials = list_to_partials(keys[3], &npartials, &error);
  4557. }
  4558. if (partials == NULL)
  4559. Xen_error(NO_DATA,
  4560. Xen_list_3(C_string_to_Xen_string(list_to_partials_error_to_string(error)),
  4561. C_string_to_Xen_string(S_make_polyshape),
  4562. keys[3]));
  4563. coeffs = mus_partials_to_polynomial(npartials, partials, kind);
  4564. csize = npartials;
  4565. /* coeffs = partials here, so don't delete */
  4566. }
  4567. }
  4568. }
  4569. if (!coeffs)
  4570. {
  4571. /* clm.html says '(1 1) is the default */
  4572. mus_float_t *data;
  4573. data = (mus_float_t *)malloc(2 * sizeof(mus_float_t));
  4574. data[0] = 0.0;
  4575. data[1] = 1.0;
  4576. coeffs = mus_partials_to_polynomial(2, data, kind);
  4577. csize = 2;
  4578. }
  4579. if (Xen_is_false(orig_v))
  4580. orig_v = xen_make_vct(csize, coeffs);
  4581. ge = mus_make_polyshape(freq, phase, coeffs, csize, kind);
  4582. if (ge)
  4583. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_v)));
  4584. return(Xen_false);
  4585. }
  4586. /* ---------------- polywave ---------------- */
  4587. static Xen g_polywave(Xen obj, Xen fm)
  4588. {
  4589. #define H_polywave "(" S_polywave " gen (fm 0.0)): next sample of polywave waveshaper"
  4590. mus_float_t fm1 = 0.0;
  4591. mus_any *g = NULL;
  4592. mus_xen *gn;
  4593. Xen_to_C_generator(obj, gn, g, mus_is_polywave, S_polywave, "a polywave generator");
  4594. Xen_real_to_C_double_if_bound(fm, fm1, S_polywave, 3);
  4595. return(C_double_to_Xen_real(mus_polywave(g, fm1)));
  4596. }
  4597. static Xen g_is_polywave(Xen obj)
  4598. {
  4599. #define H_is_polywave "(" S_is_polywave " gen): " PROC_TRUE " if gen is a " S_polywave " generator"
  4600. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_polywave(Xen_to_mus_any(obj)))));
  4601. }
  4602. static Xen g_make_polywave(Xen arglist)
  4603. {
  4604. #define H_make_polywave "(" S_make_polywave " (frequency *clm-default-frequency*) (partials '(1 1)) (type " S_mus_chebyshev_first_kind ") xcoeffs ycoeffs): \
  4605. return a new polynomial-based waveshaping generator. (" S_make_polywave " :partials (float-vector 1 1.0)) is the same in effect as " S_make_oscil "."
  4606. mus_any *ge;
  4607. Xen args[10];
  4608. Xen keys[5];
  4609. int orig_arg[5] = {0, 0, 0, 0, 0};
  4610. int vals, n = 0, npartials = 0;
  4611. Xen orig_x = Xen_false, orig_y = Xen_false;
  4612. mus_float_t freq;
  4613. mus_float_t *xcoeffs = NULL, *ycoeffs = NULL, *partials = NULL;
  4614. mus_polynomial_t kind = MUS_CHEBYSHEV_FIRST_KIND;
  4615. int error = NO_PROBLEM_IN_LIST;
  4616. freq = clm_default_frequency;
  4617. keys[0] = kw_frequency;
  4618. keys[1] = kw_partials;
  4619. keys[2] = kw_type;
  4620. keys[3] = kw_x_coeffs;
  4621. keys[4] = kw_y_coeffs;
  4622. {
  4623. int i, arglist_len;
  4624. Xen p;
  4625. arglist_len = Xen_list_length(arglist);
  4626. if (arglist_len > 10) clm_error(S_make_polywave, "too many arguments!", arglist);
  4627. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  4628. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  4629. }
  4630. vals = mus_optkey_unscramble(S_make_polywave, 5, keys, args, orig_arg);
  4631. if (vals > 0)
  4632. {
  4633. vct *v;
  4634. int type;
  4635. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_polywave, orig_arg[0], freq);
  4636. if (freq > (0.5 * mus_srate()))
  4637. Xen_out_of_range_error(S_make_polywave, orig_arg[0], keys[0], "freq > srate/2?");
  4638. type = Xen_optkey_to_int(kw_type, keys[2], S_make_polywave, orig_arg[2], (int)kind);
  4639. if ((type >= MUS_CHEBYSHEV_EITHER_KIND) &&
  4640. (type <= MUS_CHEBYSHEV_BOTH_KINDS))
  4641. kind = (mus_polynomial_t)type;
  4642. else Xen_out_of_range_error(S_make_polywave, orig_arg[2], keys[2], "unknown Chebyshev polynomial kind");
  4643. if (!(Xen_is_keyword(keys[1]))) /* partials were supplied */
  4644. {
  4645. if (mus_is_vct(keys[1]))
  4646. partials = mus_vct_to_partials(Xen_to_vct(keys[1]), &npartials, &error);
  4647. else
  4648. {
  4649. if (Xen_is_vector(keys[1]))
  4650. partials = mus_vector_to_partials(keys[1], &npartials, &error);
  4651. else
  4652. {
  4653. Xen_check_type(Xen_is_list(keys[1]), keys[1], orig_arg[1], S_make_polywave, "a list or a " S_vct);
  4654. partials = list_to_partials(keys[1], &npartials, &error);
  4655. }
  4656. }
  4657. if (partials == NULL) /* here if null, something went wrong in the translation functions */
  4658. Xen_error(NO_DATA,
  4659. Xen_list_3(C_string_to_Xen_string(list_to_partials_error_to_string(error)),
  4660. C_string_to_Xen_string(S_make_polywave),
  4661. keys[1]));
  4662. xcoeffs = partials;
  4663. n = npartials;
  4664. orig_x = xen_make_vct(n, xcoeffs);
  4665. /* xcoeffs = partials here, so don't delete */
  4666. }
  4667. if (!(Xen_is_keyword(keys[3])))
  4668. {
  4669. Xen_check_type(mus_is_vct(keys[3]), keys[3], orig_arg[3], S_make_polywave, "a " S_vct);
  4670. orig_x = keys[3];
  4671. v = Xen_to_vct(orig_x);
  4672. n = mus_vct_length(v);
  4673. xcoeffs = mus_vct_data(v);
  4674. }
  4675. if (!(Xen_is_keyword(keys[4])))
  4676. {
  4677. /* make-polyoid in generators.scm */
  4678. int yn;
  4679. Xen_check_type(mus_is_vct(keys[4]), keys[4], orig_arg[4], S_make_polywave, "a " S_vct);
  4680. orig_y = keys[4];
  4681. v = Xen_to_vct(orig_y);
  4682. yn = mus_vct_length(v);
  4683. if ((n == 0) || (yn < n))
  4684. n = yn;
  4685. ycoeffs = mus_vct_data(v);
  4686. }
  4687. }
  4688. if (!xcoeffs)
  4689. {
  4690. /* clm.html says '(1 1) is the default but table-lookup is 0? */
  4691. mus_float_t *data;
  4692. data = (mus_float_t *)malloc(2 * sizeof(mus_float_t));
  4693. data[0] = 0.0;
  4694. data[1] = 1.0;
  4695. xcoeffs = data;
  4696. n = 2;
  4697. orig_x = xen_make_vct(n, xcoeffs);
  4698. }
  4699. if (ycoeffs)
  4700. {
  4701. ge = mus_make_polywave_tu(freq, xcoeffs, ycoeffs, n);
  4702. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen_with_two_vcts(ge, orig_x, orig_y)));
  4703. }
  4704. ge = mus_make_polywave(freq, xcoeffs, n, kind);
  4705. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, orig_x)));
  4706. return(Xen_false);
  4707. }
  4708. /* ---------------- nrxysin and nrxycos ---------------- */
  4709. static Xen g_is_nrxysin(Xen obj)
  4710. {
  4711. #define H_is_nrxysin "(" S_is_nrxysin " gen): " PROC_TRUE " if gen is an " S_nrxysin " generator"
  4712. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  4713. (mus_is_nrxysin(Xen_to_mus_any(obj)))));
  4714. }
  4715. static Xen g_is_nrxycos(Xen obj)
  4716. {
  4717. #define H_is_nrxycos "(" S_is_nrxycos " gen): " PROC_TRUE " if gen is an " S_nrxycos " generator"
  4718. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  4719. (mus_is_nrxycos(Xen_to_mus_any(obj)))));
  4720. }
  4721. static Xen g_nrxysin(Xen obj, Xen fm)
  4722. {
  4723. #define H_nrxysin "(" S_nrxysin " gen (fm 0.0)): next sample of nrxysin generator"
  4724. mus_float_t fm1 = 0.0;
  4725. mus_any *g = NULL;
  4726. mus_xen *gn;
  4727. Xen_to_C_generator(obj, gn, g, mus_is_nrxysin, S_nrxysin, "an nrxysin generator");
  4728. Xen_real_to_C_double_if_bound(fm, fm1, S_nrxysin, 2);
  4729. return(C_double_to_Xen_real(mus_nrxysin(g, fm1)));
  4730. }
  4731. static Xen g_nrxycos(Xen obj, Xen fm)
  4732. {
  4733. #define H_nrxycos "(" S_nrxycos " gen (fm 0.0)): next sample of nrxycos generator"
  4734. mus_float_t fm1 = 0.0;
  4735. mus_any *g = NULL;
  4736. mus_xen *gn;
  4737. Xen_to_C_generator(obj, gn, g, mus_is_nrxycos, S_nrxycos, "an nrxycos generator");
  4738. Xen_real_to_C_double_if_bound(fm, fm1, S_nrxycos, 2);
  4739. return(C_double_to_Xen_real(mus_nrxycos(g, fm1)));
  4740. }
  4741. static Xen g_make_nrxy(bool sin_case, const char *caller, Xen arglist)
  4742. {
  4743. mus_any *ge;
  4744. Xen args[8];
  4745. Xen keys[4];
  4746. int orig_arg[4] = {0, 0, 0, 0};
  4747. int vals;
  4748. mus_float_t freq, r = 0.5, ratio = 1.0;
  4749. int n = 1;
  4750. freq = clm_default_frequency;
  4751. keys[0] = kw_frequency;
  4752. keys[1] = kw_ratio;
  4753. keys[2] = kw_n;
  4754. keys[3] = kw_r;
  4755. {
  4756. int i, arglist_len;
  4757. Xen p;
  4758. arglist_len = Xen_list_length(arglist);
  4759. if (arglist_len > 8) clm_error(caller, "too many arguments!", arglist);
  4760. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  4761. for (i = arglist_len; i < 8; i++) args[i] = Xen_undefined;
  4762. }
  4763. vals = mus_optkey_unscramble(caller, 4, keys, args, orig_arg);
  4764. if (vals > 0)
  4765. {
  4766. freq = Xen_optkey_to_float(kw_frequency, keys[0], caller, orig_arg[0], freq);
  4767. if (freq > (0.5 * mus_srate()))
  4768. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "freq > srate/2?");
  4769. ratio = Xen_optkey_to_float(kw_ratio, keys[1], caller, orig_arg[1], ratio);
  4770. n = Xen_optkey_to_int(kw_n, keys[2], caller, orig_arg[2], n);
  4771. if (n < 0)
  4772. Xen_out_of_range_error(caller, orig_arg[2], keys[2], "n (sidebands) < 0?");
  4773. r = Xen_optkey_to_float(kw_r, keys[3], caller, orig_arg[3], r);
  4774. if ((r >= 1.0) ||
  4775. (r <= -1.0))
  4776. Xen_out_of_range_error(caller, orig_arg[3], keys[3], "r (sideband amp ratio) not within -1.0 to 1.0?");
  4777. /* if not with doubles, this actually maxes out around .99999999 because mus_optkey_to_float (apparently) rounds up */
  4778. }
  4779. if (sin_case)
  4780. ge = mus_make_nrxysin(freq, ratio, n, r);
  4781. else ge = mus_make_nrxycos(freq, ratio, n, r);
  4782. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  4783. return(Xen_false);
  4784. }
  4785. static Xen g_make_nrxysin(Xen arglist)
  4786. {
  4787. #define H_make_nrxysin "(" S_make_nrxysin " (frequency *clm-default-frequency*) (ratio 1.0) (n 1) (r 0.5)): \
  4788. return a new nrxysin generator."
  4789. return(g_make_nrxy(true, S_make_nrxysin, arglist));
  4790. }
  4791. static Xen g_make_nrxycos(Xen arglist)
  4792. {
  4793. #define H_make_nrxycos "(" S_make_nrxycos " (frequency *clm-default-frequency*) (ratio 1.0) (n 1) (r 0.5)): \
  4794. return a new nrxycos generator."
  4795. return(g_make_nrxy(false, S_make_nrxycos, arglist));
  4796. }
  4797. /* ---------------- rxyksin and rxykcos ---------------- */
  4798. static Xen g_is_rxyksin(Xen obj)
  4799. {
  4800. #define H_is_rxyksin "(" S_is_rxyksin " gen): " PROC_TRUE " if gen is an " S_rxyksin " generator"
  4801. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  4802. (mus_is_rxyksin(Xen_to_mus_any(obj)))));
  4803. }
  4804. static Xen g_is_rxykcos(Xen obj)
  4805. {
  4806. #define H_is_rxykcos "(" S_is_rxykcos " gen): " PROC_TRUE " if gen is an " S_rxykcos " generator"
  4807. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) &&
  4808. (mus_is_rxykcos(Xen_to_mus_any(obj)))));
  4809. }
  4810. static Xen g_rxyksin(Xen obj, Xen fm)
  4811. {
  4812. #define H_rxyksin "(" S_rxyksin " gen (fm 0.0)): next sample of rxyksin generator"
  4813. mus_float_t fm1 = 0.0;
  4814. mus_any *g = NULL;
  4815. mus_xen *gn;
  4816. Xen_to_C_generator(obj, gn, g, mus_is_rxyksin, S_rxyksin, "an rxyksin generator");
  4817. Xen_real_to_C_double_if_bound(fm, fm1, S_rxyksin, 2);
  4818. return(C_double_to_Xen_real(mus_rxyksin(g, fm1)));
  4819. }
  4820. static Xen g_rxykcos(Xen obj, Xen fm)
  4821. {
  4822. #define H_rxykcos "(" S_rxykcos " gen (fm 0.0)): next sample of rxykcos generator"
  4823. mus_float_t fm1 = 0.0;
  4824. mus_any *g = NULL;
  4825. mus_xen *gn;
  4826. Xen_to_C_generator(obj, gn, g, mus_is_rxykcos, S_rxykcos, "an rxykcos generator");
  4827. Xen_real_to_C_double_if_bound(fm, fm1, S_rxykcos, 2);
  4828. return(C_double_to_Xen_real(mus_rxykcos(g, fm1)));
  4829. }
  4830. static Xen g_make_rxyk(bool sin_case, const char *caller, Xen arglist)
  4831. {
  4832. mus_any *ge;
  4833. Xen args[6];
  4834. Xen keys[3];
  4835. int orig_arg[3] = {0, 0, 0};
  4836. int vals;
  4837. mus_float_t freq, r = 0.5, ratio = 1.0; /* original in generators.scm assumes initial-phase = 0.0 */
  4838. freq = clm_default_frequency;
  4839. keys[0] = kw_frequency;
  4840. keys[1] = kw_ratio;
  4841. keys[2] = kw_r;
  4842. {
  4843. int i, arglist_len;
  4844. Xen p;
  4845. arglist_len = Xen_list_length(arglist);
  4846. if (arglist_len > 6) clm_error(caller, "too many arguments!", arglist);
  4847. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  4848. for (i = arglist_len; i < 6; i++) args[i] = Xen_undefined;
  4849. }
  4850. vals = mus_optkey_unscramble(caller, 3, keys, args, orig_arg);
  4851. if (vals > 0)
  4852. {
  4853. freq = Xen_optkey_to_float(kw_frequency, keys[0], caller, orig_arg[0], freq);
  4854. if (freq > (0.5 * mus_srate()))
  4855. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "freq > srate/2?");
  4856. ratio = Xen_optkey_to_float(kw_ratio, keys[1], caller, orig_arg[1], ratio);
  4857. r = Xen_optkey_to_float(kw_r, keys[2], caller, orig_arg[2], r);
  4858. }
  4859. if (sin_case)
  4860. ge = mus_make_rxyksin(freq, 0.0, r, ratio);
  4861. else ge = mus_make_rxykcos(freq, 0.0, r, ratio);
  4862. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  4863. return(Xen_false);
  4864. }
  4865. static Xen g_make_rxyksin(Xen arglist)
  4866. {
  4867. #define H_make_rxyksin "(" S_make_rxyksin " (frequency *clm-default-frequency*) (initial-phase 0.0) (ratio 1.0) (r 0.5)): \
  4868. return a new rxyksin generator."
  4869. return(g_make_rxyk(true, S_make_rxyksin, arglist));
  4870. }
  4871. static Xen g_make_rxykcos(Xen arglist)
  4872. {
  4873. #define H_make_rxykcos "(" S_make_rxykcos " (frequency *clm-default-frequency*) (initial-phase 0.0) (ratio 1.0) (r 0.5)): \
  4874. return a new rxykcos generator."
  4875. return(g_make_rxyk(false, S_make_rxykcos, arglist));
  4876. }
  4877. /* ---------------- filter ---------------- */
  4878. typedef enum {G_FILTER, G_FIR_FILTER, G_IIR_FILTER} xclm_fir_t;
  4879. static Xen g_make_fir_coeffs(Xen order, Xen envl)
  4880. {
  4881. #define H_make_fir_coeffs "(" S_make_fir_coeffs " order v): turn spectral envelope in " S_vct " v into coeffs for FIR filter"
  4882. int size;
  4883. mus_float_t *a;
  4884. vct *v;
  4885. Xen_check_type(Xen_is_integer(order), order, 1, S_make_fir_coeffs, "int");
  4886. Xen_check_type(mus_is_vct(envl), envl, 2, S_make_fir_coeffs, "a " S_vct);
  4887. v = Xen_to_vct(envl);
  4888. size = Xen_integer_to_C_int(order);
  4889. if (size != mus_vct_length(v))
  4890. Xen_error(CLM_ERROR,
  4891. Xen_list_3(C_string_to_Xen_string(S_make_fir_coeffs ": order ~A != " S_vct " length ~A"),
  4892. order,
  4893. envl));
  4894. a = mus_make_fir_coeffs(Xen_integer_to_C_int(order), mus_vct_data(v), NULL);
  4895. return(xen_make_vct(mus_vct_length(v), a));
  4896. }
  4897. static Xen g_is_filter(Xen obj)
  4898. {
  4899. #define H_is_filter "(" S_is_filter " gen): " PROC_TRUE " if gen is a " S_filter
  4900. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_filter(Xen_to_mus_any(obj)))));
  4901. }
  4902. static Xen g_is_fir_filter(Xen obj)
  4903. {
  4904. #define H_is_fir_filter "(" S_is_fir_filter " gen): " PROC_TRUE " if gen is an " S_fir_filter
  4905. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_fir_filter(Xen_to_mus_any(obj)))));
  4906. }
  4907. static Xen g_is_iir_filter(Xen obj)
  4908. {
  4909. #define H_is_iir_filter "(" S_is_iir_filter " gen): " PROC_TRUE " if gen is an " S_iir_filter
  4910. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_iir_filter(Xen_to_mus_any(obj)))));
  4911. }
  4912. static Xen g_filter(Xen obj, Xen input)
  4913. {
  4914. #define H_filter "(" S_filter " gen (input 0.0)): next sample from filter"
  4915. mus_any *g = NULL;
  4916. mus_xen *gn;
  4917. mus_float_t x = 0.0;
  4918. Xen_to_C_generator(obj, gn, g, mus_is_filter, S_filter, "a filter");
  4919. Xen_real_to_C_double_if_bound(input, x, S_filter, 2);
  4920. return(C_double_to_Xen_real(mus_filter(g, x)));
  4921. }
  4922. static Xen g_fir_filter(Xen obj, Xen input)
  4923. {
  4924. #define H_fir_filter "(" S_fir_filter " gen (input 0.0)): next sample from FIR filter"
  4925. mus_any *g = NULL;
  4926. mus_xen *gn;
  4927. mus_float_t x = 0.0;
  4928. Xen_to_C_generator(obj, gn, g, mus_is_fir_filter, S_fir_filter, "an FIR filter");
  4929. Xen_real_to_C_double_if_bound(input, x, S_fir_filter, 2);
  4930. return(C_double_to_Xen_real(mus_fir_filter(g, x)));
  4931. }
  4932. static Xen g_iir_filter(Xen obj, Xen input)
  4933. {
  4934. #define H_iir_filter "(" S_iir_filter " gen (input 0.0)): next sample from IIR filter"
  4935. mus_any *g = NULL;
  4936. mus_xen *gn;
  4937. mus_float_t x = 0.0;
  4938. Xen_to_C_generator(obj, gn, g, mus_is_iir_filter, S_iir_filter, "an IIR filter");
  4939. Xen_real_to_C_double_if_bound(input, x, S_iir_filter, 2);
  4940. return(C_double_to_Xen_real(mus_iir_filter(g, x)));
  4941. }
  4942. static Xen g_make_filter_1(xclm_fir_t choice, Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  4943. {
  4944. Xen xwave = Xen_undefined, ywave = Xen_undefined;
  4945. mus_any *fgen = NULL;
  4946. Xen args[8];
  4947. Xen keys[4];
  4948. int orig_arg[4] = {0, 0, 0, 0};
  4949. vct *x = NULL, *y = NULL;
  4950. int vals, order = 0;
  4951. const char *caller;
  4952. if (choice == G_FILTER) caller = S_make_filter; else if (choice == G_FIR_FILTER) caller = S_make_fir_filter; else caller = S_make_iir_filter;
  4953. keys[0] = kw_order;
  4954. keys[1] = kw_x_coeffs;
  4955. keys[2] = kw_y_coeffs;
  4956. keys[3] = kw_coeffs;
  4957. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = Xen_undefined; args[7] = Xen_undefined;
  4958. vals = mus_optkey_unscramble(caller, 4, keys, args, orig_arg);
  4959. if (vals > 0)
  4960. {
  4961. if (!(Xen_is_keyword(keys[0])))
  4962. {
  4963. order = Xen_optkey_to_int(kw_order, keys[0], caller, orig_arg[0], 0);
  4964. if (order <= 0)
  4965. Xen_out_of_range_error(caller, orig_arg[0], keys[0], "order <= 0?");
  4966. }
  4967. if (!(Xen_is_keyword(keys[1])))
  4968. {
  4969. Xen_check_type(mus_is_vct(keys[1]), keys[1], orig_arg[1], caller, "a " S_vct);
  4970. if (choice == G_IIR_FILTER)
  4971. {
  4972. ywave = keys[1];
  4973. y = Xen_to_vct(ywave);
  4974. }
  4975. else
  4976. {
  4977. xwave = keys[1];
  4978. x = Xen_to_vct(xwave);
  4979. }
  4980. }
  4981. if (!(Xen_is_keyword(keys[2])))
  4982. {
  4983. Xen_check_type(mus_is_vct(keys[2]), keys[2], orig_arg[2], caller, "a " S_vct);
  4984. ywave = keys[2];
  4985. y = Xen_to_vct(ywave);
  4986. }
  4987. if ((choice != G_FILTER) && (!(Xen_is_keyword(keys[3]))))
  4988. {
  4989. if (choice == G_IIR_FILTER)
  4990. clm_error(caller, "redundant arg passed to " S_make_iir_filter "?", keys[3]);
  4991. else clm_error(caller, "redundant arg passed to " S_make_fir_filter "?", keys[3]);
  4992. }
  4993. }
  4994. if (choice == G_FILTER)
  4995. {
  4996. if (y == NULL)
  4997. choice = G_FIR_FILTER;
  4998. else
  4999. {
  5000. if (x == NULL)
  5001. choice = G_IIR_FILTER;
  5002. }
  5003. }
  5004. if (((x == NULL) && (choice != G_IIR_FILTER)) ||
  5005. ((y == NULL) && (choice != G_FIR_FILTER)))
  5006. Xen_error(NO_DATA,
  5007. Xen_list_2(C_string_to_Xen_string("~A: no coeffs?"),
  5008. C_string_to_Xen_string(caller)));
  5009. if (order == 0)
  5010. {
  5011. if (x)
  5012. order = mus_vct_length(x);
  5013. else order = mus_vct_length(y);
  5014. }
  5015. else
  5016. {
  5017. if ((x) && (order > mus_vct_length(x)))
  5018. {
  5019. Xen_error(CLM_ERROR,
  5020. Xen_list_4(C_string_to_Xen_string("~A: xcoeffs, ~A, must match order, ~A"),
  5021. C_string_to_Xen_string(caller),
  5022. keys[1],
  5023. keys[0]));
  5024. }
  5025. else
  5026. {
  5027. if ((y) && (order > mus_vct_length(y)))
  5028. Xen_error(CLM_ERROR,
  5029. Xen_list_4(C_string_to_Xen_string("~A: ycoeffs, ~A, must match order, ~A"),
  5030. C_string_to_Xen_string(caller),
  5031. keys[2],
  5032. keys[0]));
  5033. else
  5034. {
  5035. if ((x) && (y) && (mus_vct_length(x) != mus_vct_length(y)))
  5036. Xen_error(CLM_ERROR,
  5037. Xen_list_4(C_string_to_Xen_string("~A: coeffs must be same length. x len: ~A, y len: ~A"),
  5038. C_string_to_Xen_string(caller),
  5039. C_int_to_Xen_integer(mus_vct_length(x)),
  5040. C_int_to_Xen_integer(mus_vct_length(y))));
  5041. }
  5042. }
  5043. }
  5044. switch (choice)
  5045. {
  5046. case G_FILTER: fgen = mus_make_filter(order, mus_vct_data(x), mus_vct_data(y), NULL); break;
  5047. case G_FIR_FILTER: fgen = mus_make_fir_filter(order, mus_vct_data(x), NULL); break;
  5048. case G_IIR_FILTER: fgen = mus_make_iir_filter(order, mus_vct_data(y), NULL); break;
  5049. }
  5050. if (fgen)
  5051. {
  5052. mus_xen *gn = NULL;
  5053. gn = mx_alloc(3);
  5054. gn->gen = fgen; /* delay gn allocation since make_filter can throw an error */
  5055. gn->vcts[G_FILTER_STATE] = xen_make_vct_wrapper(order, mus_data(fgen));
  5056. gn->vcts[G_FILTER_XCOEFFS] = xwave;
  5057. gn->vcts[G_FILTER_YCOEFFS] = ywave;
  5058. return(mus_xen_to_object(gn));
  5059. }
  5060. return(Xen_false);
  5061. }
  5062. static Xen g_make_filter(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  5063. {
  5064. #define H_make_filter "(" S_make_filter " order xcoeffs ycoeffs): return a new direct form FIR/IIR filter, coeff args are " S_vct "s"
  5065. return(g_make_filter_1(G_FILTER, arg1, arg2, arg3, arg4, arg5, arg6));
  5066. }
  5067. static Xen g_make_fir_filter(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  5068. {
  5069. #define H_make_fir_filter "(" S_make_fir_filter " order xcoeffs): return a new FIR filter, xcoeffs a " S_vct
  5070. return(g_make_filter_1(G_FIR_FILTER, arg1, arg2, arg3, arg4, Xen_undefined, Xen_undefined));
  5071. }
  5072. static Xen g_make_iir_filter(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  5073. {
  5074. #define H_make_iir_filter "(" S_make_iir_filter " order ycoeffs): return a new IIR filter, ycoeffs a " S_vct
  5075. return(g_make_filter_1(G_IIR_FILTER, arg1, arg2, arg3, arg4, Xen_undefined, Xen_undefined));
  5076. }
  5077. /* ---------------- env ---------------- */
  5078. static Xen g_is_env(Xen obj)
  5079. {
  5080. #define H_is_env "(" S_is_env " gen): " PROC_TRUE " if gen is a " S_env
  5081. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_env(Xen_to_mus_any(obj)))));
  5082. }
  5083. static Xen g_env(Xen obj)
  5084. {
  5085. #define H_env "(" S_env " gen): next sample from envelope generator"
  5086. mus_any *g = NULL;
  5087. mus_xen *gn;
  5088. Xen_to_C_generator(obj, gn, g, mus_is_env, S_env, "an env generator");
  5089. return(C_double_to_Xen_real(mus_env(g)));
  5090. }
  5091. static Xen g_make_env(Xen arglist)
  5092. {
  5093. #define H_make_env "(" S_make_env " envelope (scaler 1.0) (duration) (offset 0.0) (base 1.0) (end) (length)): \
  5094. return a new envelope generator. 'envelope' is a list, vector, or " S_vct " of break-point pairs. To create the envelope, \
  5095. these points are offset by 'offset', scaled by 'scaler', and mapped over the time interval defined by \
  5096. either 'duration' (seconds) or 'length' (samples). If 'base' is 1.0, the connecting segments \
  5097. are linear, if 0.0 you get a step function, and anything else produces an exponential connecting segment."
  5098. mus_any *ge;
  5099. Xen args[14];
  5100. Xen keys[7];
  5101. int orig_arg[7] = {0, 0, 0, 0, 0, 0, 0};
  5102. int vals, i;
  5103. mus_float_t base = 1.0, scaler = 1.0, offset = 0.0, duration = 0.0;
  5104. mus_long_t end = 0, dur = -1;
  5105. int npts = 0;
  5106. mus_float_t *brkpts = NULL;
  5107. vct *v = NULL;
  5108. keys[0] = kw_envelope;
  5109. keys[1] = kw_scaler;
  5110. keys[2] = kw_duration;
  5111. keys[3] = kw_offset;
  5112. keys[4] = kw_base;
  5113. keys[5] = kw_end;
  5114. keys[6] = kw_length;
  5115. {
  5116. int arglist_len;
  5117. Xen p;
  5118. arglist_len = Xen_list_length(arglist);
  5119. if (arglist_len > 14) clm_error(S_make_env, "too many arguments!", arglist);
  5120. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  5121. for (i = arglist_len; i < 14; i++) args[i] = Xen_undefined;
  5122. }
  5123. vals = mus_optkey_unscramble(S_make_env, 7, keys, args, orig_arg);
  5124. if (vals > 0)
  5125. {
  5126. scaler = Xen_optkey_to_float(kw_scaler, keys[1], S_make_env, orig_arg[1], 1.0);
  5127. duration = Xen_optkey_to_float(kw_duration, keys[2], S_make_env, orig_arg[2], 0.0);
  5128. if ((duration < 0.0) || ((duration == 0.0) && (!Xen_is_keyword(keys[2]))))
  5129. Xen_out_of_range_error(S_make_env, orig_arg[2], keys[2], "duration <= 0.0?");
  5130. offset = Xen_optkey_to_float(kw_offset, keys[3], S_make_env, orig_arg[3], 0.0);
  5131. base = Xen_optkey_to_float(kw_base, keys[4], S_make_env, orig_arg[4], 1.0);
  5132. if (base < 0.0)
  5133. Xen_out_of_range_error(S_make_env, orig_arg[4], keys[4], "base < 0.0?");
  5134. end = Xen_optkey_to_mus_long_t(kw_end, keys[5], S_make_env, orig_arg[5], 0);
  5135. if (end < 0)
  5136. Xen_out_of_range_error(S_make_env, orig_arg[5], keys[5], "end < 0?");
  5137. dur = Xen_optkey_to_mus_long_t(kw_length, keys[6], S_make_env, orig_arg[6], 0);
  5138. if (dur < 0)
  5139. Xen_out_of_range_error(S_make_env, orig_arg[6], keys[6], "length < 0?");
  5140. /* env data is a list, checked last to let the preceding throw wrong-type error before calloc */
  5141. if (!(Xen_is_keyword(keys[0])))
  5142. {
  5143. int len;
  5144. Xen vect = XEN_NULL;
  5145. if (mus_is_vct(keys[0]))
  5146. {
  5147. v = Xen_to_vct(keys[0]);
  5148. len = mus_vct_length(v);
  5149. if ((len < 2) || (len & 1))
  5150. Xen_error(BAD_TYPE,
  5151. Xen_list_2(C_string_to_Xen_string(S_make_env ": " S_vct " is a bogus breakpoints list, ~A"),
  5152. keys[0]));
  5153. }
  5154. else
  5155. {
  5156. #if HAVE_SCHEME
  5157. /* in Ruby and Forth vectors and lists are the same, so stay with the old code */
  5158. if (Xen_is_vector(keys[0]))
  5159. {
  5160. vect = keys[0];
  5161. len = Xen_vector_length(vect);
  5162. if ((len < 2) || (len & 1))
  5163. Xen_error(BAD_TYPE, Xen_list_2(C_string_to_Xen_string(S_make_env ": vector is a bogus breakpoints list, ~A"), vect));
  5164. }
  5165. else
  5166. {
  5167. #endif
  5168. Xen_check_type(Xen_is_list(keys[0]), keys[0], orig_arg[0], S_make_env, "a list, vector, or " S_vct);
  5169. len = Xen_list_length(keys[0]);
  5170. if (len == 0)
  5171. Xen_error(NO_DATA,
  5172. Xen_list_2(C_string_to_Xen_string(S_make_env ": null env? ~A"),
  5173. keys[0]));
  5174. if (Xen_is_list(Xen_car(keys[0])))
  5175. len *= 2;
  5176. else
  5177. {
  5178. if (len & 1)
  5179. Xen_error(BAD_TYPE,
  5180. Xen_list_2(C_string_to_Xen_string(S_make_env ": odd length breakpoints list? ~A"),
  5181. keys[0]));
  5182. if (!(Xen_is_number(Xen_car(keys[0]))))
  5183. Xen_check_type(false, keys[0], orig_arg[0], S_make_env, "a list of numbers (breakpoints)");
  5184. }
  5185. }
  5186. #if HAVE_SCHEME
  5187. }
  5188. #endif
  5189. npts = len / 2;
  5190. if (v)
  5191. brkpts = mus_vct_data(v);
  5192. else
  5193. {
  5194. brkpts = (mus_float_t *)malloc(len * sizeof(mus_float_t));
  5195. if (brkpts == NULL)
  5196. return(clm_mus_error(MUS_MEMORY_ALLOCATION_FAILED, "can't allocate env list", S_make_env));
  5197. if (vect)
  5198. {
  5199. for (i = 0; i < len; i++)
  5200. brkpts[i] = Xen_real_to_C_double(Xen_vector_ref(vect, i));
  5201. }
  5202. else
  5203. {
  5204. Xen lst;
  5205. if (Xen_is_number(Xen_car(keys[0])))
  5206. {
  5207. for (i = 0, lst = Xen_copy_arg(keys[0]); (i < len) && (!Xen_is_null(lst)); i++, lst = Xen_cdr(lst))
  5208. brkpts[i] = Xen_real_to_C_double(Xen_car(lst));
  5209. }
  5210. else
  5211. {
  5212. for (i = 0, lst = Xen_copy_arg(keys[0]); (i < len) && (!Xen_is_null(lst)); i += 2, lst = Xen_cdr(lst))
  5213. {
  5214. Xen el;
  5215. el = Xen_car(lst);
  5216. if ((Xen_is_pair(el)) &&
  5217. (Xen_is_number(Xen_car(el))) &&
  5218. (Xen_is_pair(Xen_cdr(el))) &&
  5219. (Xen_is_number(Xen_cadr(el))))
  5220. {
  5221. brkpts[i] = Xen_real_to_C_double(Xen_car(el));
  5222. brkpts[i + 1] = Xen_real_to_C_double(Xen_cadr(el));
  5223. }
  5224. else
  5225. {
  5226. Xen_error(BAD_TYPE,
  5227. Xen_list_2(C_string_to_Xen_string(S_make_env ": odd breakpoints list? ~A"),
  5228. keys[0]));
  5229. }
  5230. }
  5231. }
  5232. }
  5233. }
  5234. }
  5235. }
  5236. if (brkpts == NULL)
  5237. {
  5238. Xen_error(NO_DATA,
  5239. Xen_list_1(C_string_to_Xen_string(S_make_env ": no envelope?")));
  5240. }
  5241. if (dur > 0)
  5242. {
  5243. if ((end > 0) && ((end + 1) != dur))
  5244. {
  5245. if ((!v) && (brkpts)) {free(brkpts); brkpts = NULL;}
  5246. Xen_error(CLM_ERROR,
  5247. Xen_list_3(C_string_to_Xen_string(S_make_env ": end, ~A, and dur, ~A, specified, but dur != end+1"),
  5248. keys[5],
  5249. keys[6]));
  5250. }
  5251. end = dur - 1;
  5252. }
  5253. /* (make-env '(0 1 1 0) :duration most-positive-fixnum) -> env linear, pass: 0 (dur: -9223372036854775808)...
  5254. */
  5255. if ((end <= 0) && (duration <= 0.0))
  5256. Xen_out_of_range_error(S_make_env, 0, C_double_to_Xen_real(duration), "duration <= 0.0?");
  5257. if (duration > (24 * 3600 * 365))
  5258. Xen_out_of_range_error(S_make_env, 0, C_double_to_Xen_real(duration), "duration > year?");
  5259. {
  5260. mus_error_handler_t *old_error_handler;
  5261. old_error_handler = mus_error_set_handler(local_mus_error);
  5262. ge = mus_make_env(brkpts, npts, scaler, offset, base, duration, end, NULL);
  5263. mus_error_set_handler(old_error_handler);
  5264. }
  5265. if (ge)
  5266. {
  5267. if (v)
  5268. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, keys[0]))); /* in s7, keys[0] == v */
  5269. return(mus_xen_to_object(mus_any_to_mus_xen_with_vct(ge, xen_make_vct(mus_env_breakpoints(ge) * 2, brkpts))));
  5270. }
  5271. return(clm_mus_error(local_error_type, local_error_msg, S_make_env));
  5272. }
  5273. static Xen g_env_interp(Xen x, Xen env1) /* "env" causes trouble in Objective-C!! */
  5274. {
  5275. #define H_env_interp "(" S_env_interp " x env): value of envelope env at x"
  5276. Xen_check_type(Xen_is_number(x), x, 1, S_env_interp, "a number");
  5277. Xen_check_type((mus_is_xen(env1)) && (mus_is_env(Xen_to_mus_any(env1))), env1, 2, S_env_interp, "an env generator");
  5278. return(C_double_to_Xen_real(mus_env_interp(Xen_real_to_C_double(x), Xen_to_mus_any(env1))));
  5279. }
  5280. /* mus_env_any calls the C function itself, so we pass it connect_func,
  5281. * connect_func uses the function passed as an argument to g_env_any.
  5282. * I can't think of a cleaner way to handle this except via nested functions.
  5283. * Both versions seem to work ok with recursive env-any calls.
  5284. */
  5285. static Xen current_connect_func;
  5286. static mus_float_t connect_func(mus_float_t val)
  5287. {
  5288. return(Xen_real_to_C_double(Xen_call_with_1_arg(current_connect_func,
  5289. C_double_to_Xen_real(val),
  5290. S_env_any " connect function")));
  5291. }
  5292. static Xen g_env_any(Xen e, Xen func)
  5293. {
  5294. Xen val;
  5295. Xen old_connect_func = Xen_false;
  5296. #define H_env_any "(" S_env_any " e func) uses 'func' to connect the dots in the env 'e'"
  5297. Xen_check_type((mus_is_xen(e)) && (mus_is_env(Xen_to_mus_any(e))), e, 1, S_env_any, "an env generator");
  5298. Xen_check_type((Xen_is_procedure(func)) && (Xen_is_aritable(func, 1)), func, 2, S_env_any, "a function of one arg");
  5299. old_connect_func = current_connect_func;
  5300. current_connect_func = func;
  5301. val = C_double_to_Xen_real(mus_env_any(Xen_to_mus_any(e), connect_func));
  5302. current_connect_func = old_connect_func;
  5303. return(val);
  5304. }
  5305. #define S_envelope_interp "envelope-interp"
  5306. static Xen g_envelope_interp(Xen ux, Xen e, Xen ubase)
  5307. {
  5308. #define H_envelope_interp "(envelope-interp x e (base 1.0)) -> value of e at x; base controls connecting segment type: (envelope-interp .3 '(0 0 .5 1 1 0)) -> .6"
  5309. mus_float_t x, base = 1.0, x0, y0, y1;
  5310. Xen_check_type(Xen_is_number(ux), ux, 1, S_envelope_interp, "a number");
  5311. Xen_check_type(Xen_is_list(e), e, 2, S_envelope_interp, "a list");
  5312. if (Xen_is_null(e))
  5313. return(Xen_integer_zero);
  5314. x = Xen_real_to_C_double(ux);
  5315. if (Xen_is_bound(ubase)) base = Xen_real_to_C_double(ubase);
  5316. x0 = Xen_real_to_C_double(Xen_car(e));
  5317. while (true)
  5318. {
  5319. mus_float_t x1;
  5320. Xen ey;
  5321. if (!Xen_is_pair(Xen_cdr(e)))
  5322. Xen_check_type(false, e, 2, S_envelope_interp, "a list of breakpoint values");
  5323. ey = Xen_cadr(e);
  5324. if ((x <= x0) ||
  5325. (!Xen_is_pair(Xen_cddr(e))))
  5326. return(ey);
  5327. x1 = Xen_real_to_C_double(Xen_caddr(e));
  5328. if (x < x1)
  5329. {
  5330. if (base == 0.0)
  5331. return(ey);
  5332. y0 = Xen_real_to_C_double(ey);
  5333. y1 = Xen_real_to_C_double(Xen_cadddr(e));
  5334. if (y0 == y1)
  5335. return(ey);
  5336. if (base == 1.0)
  5337. return(C_double_to_Xen_real(y0 + ((x - x0) * (y1 - y0) / (x1 - x0))));
  5338. return(C_double_to_Xen_real(y0 + (((y1 - y0) / (base - 1.0)) * (pow(base, (x - x0) / (x1 - x0)) - 1.0))));
  5339. }
  5340. e = Xen_cddr(e);
  5341. x0 = x1;
  5342. }
  5343. return(Xen_false);
  5344. }
  5345. /* -------------------------------- pulsed-env -------------------------------- */
  5346. static Xen g_make_pulsed_env(Xen e, Xen dur, Xen frq)
  5347. {
  5348. #define H_make_pulsed_env "(" S_make_pulsed_env " envelope duration frequency) returns a pulsed-env generator."
  5349. Xen gp, ge;
  5350. mus_any *pl;
  5351. gp = g_make_pulse_train(frq, Xen_undefined, Xen_undefined, Xen_undefined, Xen_undefined, Xen_undefined);
  5352. ge = g_make_env(Xen_list_3(e, C_double_to_Xen_real(1.0), dur));
  5353. pl = mus_make_pulsed_env(Xen_to_mus_any(ge), Xen_to_mus_any(gp));
  5354. return(mus_xen_to_object(mus_any_to_mus_xen_with_two_vcts(pl, ge, gp)));
  5355. }
  5356. static Xen g_is_pulsed_env(Xen os)
  5357. {
  5358. #define H_is_pulsed_env "(" S_is_pulsed_env " gen) returns " PROC_TRUE " if gen is a pulsed-env generator."
  5359. return(C_bool_to_Xen_boolean((mus_is_xen(os)) && (mus_is_pulsed_env(Xen_to_mus_any(os)))));
  5360. }
  5361. static Xen g_pulsed_env(Xen g, Xen fm)
  5362. {
  5363. #define H_pulsed_env "(" S_pulsed_env " gen fm) runs a pulsed-env generator."
  5364. mus_any *pl = NULL;
  5365. Xen_check_type((mus_is_xen(g)) && (mus_is_pulsed_env(pl = Xen_to_mus_any(g))), g, 1, S_pulsed_env, "a pulsed-env object");
  5366. if (Xen_is_number(fm))
  5367. return(C_double_to_Xen_real(mus_pulsed_env(pl, Xen_real_to_C_double(fm))));
  5368. return(C_double_to_Xen_real(mus_pulsed_env_unmodulated(pl)));
  5369. }
  5370. /* ---------------- io ---------------- */
  5371. #if (!HAVE_RUBY)
  5372. #define S_output "*output*"
  5373. #define S_reverb "*reverb*"
  5374. #else
  5375. #define S_output "output"
  5376. #define S_reverb "reverb"
  5377. #endif
  5378. static Xen clm_output, clm_reverb; /* *output* and *reverb* at extlang level -- these can be output streams, vct, sound-data objects etc */
  5379. #if (HAVE_SCHEME)
  5380. static Xen clm_output_slot = NULL, clm_reverb_slot = NULL;
  5381. #define CLM_OUTPUT s7_slot_value(clm_output_slot)
  5382. #define CLM_REVERB s7_slot_value(clm_reverb_slot)
  5383. #else
  5384. #define CLM_OUTPUT Xen_variable_ref(S_output)
  5385. #define CLM_REVERB Xen_variable_ref(S_reverb)
  5386. #endif
  5387. static Xen g_is_mus_input(Xen obj)
  5388. {
  5389. #define H_is_mus_input "(" S_is_mus_input " gen): " PROC_TRUE " if gen is an input generator"
  5390. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_input(Xen_to_mus_any(obj)))));
  5391. }
  5392. static Xen g_is_mus_output(Xen obj)
  5393. {
  5394. #define H_is_mus_output "(" S_is_mus_output " gen): " PROC_TRUE " if gen is an output generator"
  5395. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_output(Xen_to_mus_any(obj)))));
  5396. }
  5397. static Xen g_is_file_to_sample(Xen obj)
  5398. {
  5399. #define H_is_file_to_sample "(" S_is_file_to_sample " gen): " PROC_TRUE " if gen is a " S_file_to_sample " generator"
  5400. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_file_to_sample(Xen_to_mus_any(obj)))));
  5401. }
  5402. static Xen mus_clm_output(void) {return(CLM_OUTPUT);}
  5403. static Xen mus_clm_reverb(void) {return(CLM_REVERB);}
  5404. static Xen g_is_file_to_frample(Xen obj)
  5405. {
  5406. #define H_is_file_to_frample "(" S_is_file_to_frample " gen): " PROC_TRUE " if gen is a " S_file_to_frample " generator"
  5407. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_file_to_frample(Xen_to_mus_any(obj)))));
  5408. }
  5409. static Xen g_is_sample_to_file(Xen obj)
  5410. {
  5411. #define H_is_sample_to_file "(" S_is_sample_to_file " gen): " PROC_TRUE " if gen is a " S_sample_to_file " generator"
  5412. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_sample_to_file(Xen_to_mus_any(obj)))));
  5413. }
  5414. static Xen g_is_frample_to_file(Xen obj)
  5415. {
  5416. #define H_is_frample_to_file "(" S_is_frample_to_file " gen): " PROC_TRUE " if gen is a " S_frample_to_file " generator"
  5417. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_frample_to_file(Xen_to_mus_any(obj)))));
  5418. }
  5419. #if HAVE_SCHEME
  5420. static mus_float_t (*in_any_2)(mus_long_t pos, int chn);
  5421. #endif
  5422. static Xen g_in_any_1(const char *caller, Xen frample, int in_chan, Xen inp)
  5423. {
  5424. mus_long_t pos;
  5425. Xen_check_type(Xen_is_integer(frample), frample, 1, caller, "an integer");
  5426. pos = Xen_llong_to_C_llong(frample);
  5427. if (pos < 0)
  5428. Xen_out_of_range_error(caller, 1, frample, "location should be >= 0");
  5429. if (in_chan < 0)
  5430. Xen_out_of_range_error(caller, 2, C_int_to_Xen_integer(in_chan), "must be >= 0");
  5431. #if HAVE_SCHEME
  5432. if (Xen_is_false(inp)) return(C_double_to_Xen_real(0.0)); /* ws.scm default for *clm-reverb* is #f */
  5433. if (inp == CLM_REVERB)
  5434. return(s7_make_real(s7, in_any_2(pos, in_chan)));
  5435. #endif
  5436. if (mus_is_xen(inp))
  5437. {
  5438. Xen_check_type(mus_is_input(Xen_to_mus_any(inp)), inp, 3, caller, "an input generator");
  5439. return(C_double_to_Xen_real(mus_in_any(pos, in_chan, (mus_any *)Xen_to_mus_any(inp))));
  5440. }
  5441. if (mus_is_vct(inp))
  5442. {
  5443. #if HAVE_SCHEME
  5444. if (pos < s7_vector_length(inp))
  5445. {
  5446. if (s7_vector_rank(inp) > 1)
  5447. return(s7_vector_ref_n(s7, inp, 2, in_chan, pos));
  5448. return(s7_vector_ref(s7, inp, pos));
  5449. }
  5450. return(C_double_to_Xen_real(0.0));
  5451. #else
  5452. vct *v;
  5453. mus_float_t *vdata;
  5454. v = Xen_to_vct(inp);
  5455. vdata = mus_vct_data(v);
  5456. if (pos < mus_vct_length(v))
  5457. return(C_double_to_Xen_real(vdata[pos]));
  5458. return(C_double_to_Xen_real(0.0));
  5459. #endif
  5460. }
  5461. if (Xen_is_vector(inp))
  5462. {
  5463. if (pos < Xen_vector_length(inp))
  5464. return(Xen_vector_ref(inp, pos));
  5465. }
  5466. return(C_double_to_Xen_real(0.0));
  5467. }
  5468. static Xen g_in_any(Xen frample, Xen chan, Xen inp)
  5469. {
  5470. #define H_in_any "(" S_in_any " frample chan stream): input stream sample at frample in channel chan"
  5471. Xen_check_type(Xen_is_integer(chan), chan, 2, S_in_any, "an integer");
  5472. return(g_in_any_1(S_in_any, frample, Xen_integer_to_C_int(chan), inp));
  5473. }
  5474. static Xen g_ina(Xen frample, Xen inp)
  5475. {
  5476. #define H_ina "(" S_ina " frample stream): input stream sample in channel 0 at frample"
  5477. return(g_in_any_1(S_ina, frample, 0, inp));
  5478. }
  5479. static Xen g_inb(Xen frample, Xen inp)
  5480. {
  5481. #define H_inb "(" S_inb " frample stream): input stream sample in channel 1 at frample"
  5482. return(g_in_any_1(S_inb, frample, 1, inp));
  5483. }
  5484. #if (!HAVE_SCHEME)
  5485. static Xen out_any_2(Xen outp, mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5486. #else
  5487. static Xen fallback_out_any_2(Xen outp, mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5488. #endif
  5489. {
  5490. mus_xen *gn;
  5491. gn = (mus_xen *)Xen_object_ref_checked(outp, mus_xen_tag);
  5492. if (gn)
  5493. {
  5494. /* mus_out_any will check the writer so output_p is pointless */
  5495. mus_out_any(pos, inv, chn, mus_xen_to_mus_any(gn));
  5496. return(Xen_integer_zero);
  5497. }
  5498. if (mus_is_vct(outp))
  5499. {
  5500. mus_float_t *vdata;
  5501. vct *v;
  5502. v = xen_to_vct(outp);
  5503. vdata = mus_vct_data(v);
  5504. if (Xen_vector_rank(outp) == 1)
  5505. {
  5506. if (chn == 0)
  5507. {
  5508. if (pos < mus_vct_length(v))
  5509. vdata[pos] += inv;
  5510. }
  5511. }
  5512. #if HAVE_SCHEME
  5513. else
  5514. {
  5515. s7_int *offsets;
  5516. offsets = s7_vector_offsets(outp);
  5517. pos += (chn * offsets[0]);
  5518. if (pos < mus_vct_length(v))
  5519. vdata[pos] += inv;
  5520. }
  5521. #endif
  5522. return(Xen_integer_zero);
  5523. }
  5524. if (Xen_is_vector(outp))
  5525. {
  5526. if (pos < Xen_vector_length(outp))
  5527. Xen_vector_set(outp, pos, C_double_to_Xen_real(Xen_real_to_C_double(Xen_vector_ref(outp, pos)) + inv));
  5528. }
  5529. return(Xen_integer_zero);
  5530. }
  5531. #if HAVE_SCHEME
  5532. static Xen (*out_any_2)(mus_long_t pos, mus_float_t inv, int chn, const char *caller);
  5533. bool mus_simple_out_any_to_file(mus_long_t samp, mus_float_t val, int chan, mus_any *IO);
  5534. bool mus_simple_outa_to_file(mus_long_t samp, mus_float_t val, mus_any *IO);
  5535. static mus_xen *clm_output_gn = NULL;
  5536. static mus_any *clm_output_gen = NULL;
  5537. static vct *clm_output_vct;
  5538. static Xen out_any_2_to_mus_xen(mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5539. {
  5540. mus_out_any(pos, inv, chn, clm_output_gen);
  5541. return(xen_zero);
  5542. }
  5543. static Xen safe_out_any_2_to_mus_xen(mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5544. {
  5545. if (!mus_simple_out_any_to_file(pos, inv, chn, clm_output_gen))
  5546. mus_safe_out_any_to_file(pos, inv, chn, clm_output_gen);
  5547. return(xen_zero);
  5548. }
  5549. static Xen out_any_2_to_vct(mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5550. {
  5551. mus_float_t *vdata;
  5552. vdata = mus_vct_data(clm_output_vct);
  5553. #if (!HAVE_SCHEME)
  5554. if ((chn == 0) &&
  5555. (pos < mus_vct_length(clm_output_vct)))
  5556. vdata[pos] += inv;
  5557. #else
  5558. if (Xen_vector_rank(clm_output_vct) == 1)
  5559. {
  5560. if ((chn == 0) &&
  5561. (pos < mus_vct_length(clm_output_vct)))
  5562. vdata[pos] += inv;
  5563. }
  5564. else
  5565. {
  5566. s7_int chans;
  5567. chans = s7_vector_dimensions(clm_output_vct)[0];
  5568. if (chn < chans)
  5569. {
  5570. s7_int chan_len;
  5571. chan_len = s7_vector_dimensions(clm_output_vct)[1];
  5572. if (pos < chan_len)
  5573. vdata[chn * chan_len + pos] += inv;
  5574. }
  5575. }
  5576. #endif
  5577. return(xen_zero);
  5578. }
  5579. static Xen out_any_2_to_vector(mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5580. {
  5581. if (pos < Xen_vector_length(CLM_OUTPUT))
  5582. Xen_vector_set(CLM_OUTPUT, pos, C_double_to_Xen_real(Xen_real_to_C_double(Xen_vector_ref(CLM_OUTPUT, pos)) + inv));
  5583. return(xen_zero);
  5584. }
  5585. static Xen out_any_2_no_op(mus_long_t pos, mus_float_t inv, int chn, const char *caller)
  5586. {
  5587. return(xen_zero);
  5588. }
  5589. static s7_pointer g_clm_output_set(s7_scheme *sc, s7_pointer args)
  5590. {
  5591. s7_pointer new_output;
  5592. new_output = s7_cadr(args);
  5593. clm_output_gn = (mus_xen *)Xen_object_ref_checked(new_output, mus_xen_tag);
  5594. if (clm_output_gn)
  5595. {
  5596. out_any_2 = out_any_2_to_mus_xen;
  5597. clm_output_gen = clm_output_gn->gen;
  5598. if (mus_out_any_is_safe(clm_output_gen))
  5599. out_any_2 = safe_out_any_2_to_mus_xen;
  5600. }
  5601. else
  5602. {
  5603. clm_output_gen = NULL;
  5604. if (mus_is_vct(new_output))
  5605. {
  5606. out_any_2 = out_any_2_to_vct;
  5607. clm_output_vct = xen_to_vct(new_output);
  5608. }
  5609. else
  5610. {
  5611. if (Xen_is_vector(new_output))
  5612. {
  5613. out_any_2 = out_any_2_to_vector;
  5614. }
  5615. else out_any_2 = out_any_2_no_op;
  5616. }
  5617. }
  5618. return(new_output);
  5619. }
  5620. /* need in_any_2(pos, 0, caller) -> double + safe case + none-file cases
  5621. */
  5622. static mus_xen *clm_input_gn;
  5623. static mus_any *clm_input_gen;
  5624. static vct *clm_input_vct;
  5625. static mus_float_t in_any_2_to_mus_xen(mus_long_t pos, int chn)
  5626. {
  5627. return(mus_in_any(pos, chn, clm_input_gen));
  5628. }
  5629. static mus_float_t safe_in_any_2_to_mus_xen(mus_long_t pos, int chn)
  5630. {
  5631. return(mus_file_to_sample(clm_input_gen, pos, chn));
  5632. }
  5633. static mus_float_t in_any_2_to_vct(mus_long_t pos, int chn)
  5634. {
  5635. mus_float_t *vdata;
  5636. vdata = mus_vct_data(clm_input_vct);
  5637. if ((chn == 0) &&
  5638. (pos < mus_vct_length(clm_input_vct)))
  5639. return(vdata[pos]);
  5640. return(0.0);
  5641. }
  5642. static mus_float_t in_any_2_to_vector(mus_long_t pos, int chn)
  5643. {
  5644. if (pos < Xen_vector_length(CLM_REVERB))
  5645. return(Xen_real_to_C_double(Xen_vector_ref(CLM_REVERB, pos)));
  5646. return(0.0);
  5647. }
  5648. static mus_float_t in_any_2_no_op(mus_long_t pos, int chn)
  5649. {
  5650. return(0.0);
  5651. }
  5652. static s7_pointer g_clm_reverb_set(s7_scheme *sc, s7_pointer args)
  5653. {
  5654. s7_pointer new_input;
  5655. new_input = s7_cadr(args);
  5656. clm_input_gn = (mus_xen *)Xen_object_ref_checked(new_input, mus_xen_tag);
  5657. if (clm_input_gn)
  5658. {
  5659. in_any_2 = in_any_2_to_mus_xen;
  5660. clm_input_gen = clm_input_gn->gen;
  5661. if (mus_in_any_is_safe(clm_input_gen))
  5662. in_any_2 = safe_in_any_2_to_mus_xen;
  5663. }
  5664. else
  5665. {
  5666. if (mus_is_vct(new_input))
  5667. {
  5668. in_any_2 = in_any_2_to_vct;
  5669. clm_input_vct = xen_to_vct(new_input);
  5670. }
  5671. else
  5672. {
  5673. if (Xen_is_vector(new_input))
  5674. {
  5675. in_any_2 = in_any_2_to_vector;
  5676. }
  5677. else in_any_2 = in_any_2_no_op;
  5678. }
  5679. }
  5680. return(new_input);
  5681. }
  5682. #endif
  5683. #define S_out_bank "out-bank"
  5684. static Xen g_out_bank(Xen gens, Xen loc, Xen inval)
  5685. {
  5686. #define H_out_bank "(out-bank gens location val) calls each generator in the gens vector, passing it the argument val, then \
  5687. sends that output to the output channels in the vector order (the first generator writes to outa, the second to outb, etc)."
  5688. mus_long_t pos;
  5689. int i, size;
  5690. mus_float_t x = 0.0;
  5691. Xen_check_type(Xen_is_integer(loc), loc, 2, S_out_bank, "an integer");
  5692. pos = Xen_llong_to_C_llong(loc);
  5693. if (pos < 0)
  5694. Xen_out_of_range_error(S_out_bank, 2, loc, "must be >= 0");
  5695. Xen_check_type(Xen_is_vector(gens), gens, 1, S_out_bank, "a vector of generators");
  5696. size = Xen_vector_length(gens);
  5697. Xen_check_type(Xen_is_number(inval), inval, 3, S_out_bank, "a number");
  5698. x = Xen_real_to_C_double(inval);
  5699. #if HAVE_SCHEME
  5700. for (i = 0; i < size; i++)
  5701. {
  5702. mus_any *g = NULL;
  5703. mus_xen *gn;
  5704. Xen_to_C_any_generator(Xen_vector_ref(gens, i), gn, g, S_out_bank, "an output generator");
  5705. out_any_2(pos, mus_apply(g, x, 0.0), i, S_out_bank);
  5706. }
  5707. #else
  5708. for (i = 0; i < size; i++)
  5709. {
  5710. mus_any *g = NULL;
  5711. mus_xen *gn;
  5712. Xen_to_C_any_generator(Xen_vector_ref(gens, i), gn, g, S_out_bank, "an output generator");
  5713. out_any_2(CLM_OUTPUT, pos, mus_apply(g, x, 0.0), i, S_out_bank);
  5714. }
  5715. #endif
  5716. return(inval);
  5717. }
  5718. static Xen g_out_any_1(const char *caller, Xen frample, int chn, Xen val, Xen outp)
  5719. {
  5720. mus_long_t pos = 0;
  5721. mus_float_t inv;
  5722. if (chn < 0)
  5723. Xen_out_of_range_error(caller, 3, C_int_to_Xen_integer(chn), "must be >= 0");
  5724. Xen_to_C_integer_or_error(frample, pos, caller, 1);
  5725. if (pos < 0)
  5726. Xen_out_of_range_error(caller, 1, frample, "must be >= 0");
  5727. Xen_to_C_double_or_error(val, inv, caller, 2);
  5728. if (!Xen_is_bound(outp))
  5729. #if (!HAVE_SCHEME)
  5730. return(out_any_2(CLM_OUTPUT, pos, inv, chn, caller));
  5731. #else
  5732. return(out_any_2(pos, inv, chn, caller));
  5733. #endif
  5734. #if (!HAVE_SCHEME)
  5735. return(out_any_2(outp, pos, inv, chn, caller));
  5736. #else
  5737. if (outp == CLM_OUTPUT)
  5738. return(out_any_2(pos, inv, chn, caller));
  5739. return(fallback_out_any_2(outp, pos, inv, chn, caller));
  5740. #endif
  5741. }
  5742. static Xen g_out_any(Xen frample, Xen val, Xen chan, Xen outp)
  5743. {
  5744. #define H_out_any "(" S_out_any " frample val chan stream): add val to output stream at frample in channel chan"
  5745. Xen_check_type(Xen_is_integer(chan), chan, 3, S_out_any, "an integer");
  5746. return(g_out_any_1(S_out_any, frample, Xen_integer_to_C_int(chan), val, outp));
  5747. }
  5748. static Xen g_outa(Xen frample, Xen val, Xen outp)
  5749. {
  5750. #define H_outa "(" S_outa " frample val stream): add val to output stream at frample in channel 0"
  5751. return(g_out_any_1(S_outa, frample, 0, val, outp));
  5752. }
  5753. static Xen g_outb(Xen frample, Xen val, Xen outp)
  5754. {
  5755. #define H_outb "(" S_outb " frample val stream): add val to output stream at frample in channel 1"
  5756. return(g_out_any_1(S_outb, frample, 1, val, outp));
  5757. }
  5758. static Xen g_outc(Xen frample, Xen val, Xen outp)
  5759. {
  5760. #define H_outc "(" S_outc " frample val stream): add val to output stream at frample in channel 2"
  5761. return(g_out_any_1(S_outc, frample, 2, val, outp));
  5762. }
  5763. static Xen g_outd(Xen frample, Xen val, Xen outp)
  5764. {
  5765. #define H_outd "(" S_outd " frample val stream): add val to output stream at frample in channel 3"
  5766. return(g_out_any_1(S_outd, frample, 3, val, outp));
  5767. }
  5768. static Xen g_mus_close(Xen ptr)
  5769. {
  5770. #define H_mus_close "(" S_mus_close " gen): close the IO stream managed by 'gen' (a sample->file generator, for example)"
  5771. if (mus_is_xen(ptr))
  5772. return(C_int_to_Xen_integer(mus_close_file((mus_any *)Xen_to_mus_any(ptr))));
  5773. Xen_check_type(mus_is_vct(ptr) || Xen_is_false(ptr) || Xen_is_vector(ptr),
  5774. ptr, 1, S_mus_close, "an IO gen or its outa equivalent");
  5775. return(Xen_integer_zero);
  5776. }
  5777. static Xen g_make_file_to_sample(Xen name, Xen buffer_size)
  5778. {
  5779. #define H_make_file_to_sample "(" S_make_file_to_sample " filename buffer-size): return an input generator reading 'filename' (a sound file)"
  5780. mus_any *ge;
  5781. mus_long_t size;
  5782. Xen_check_type(Xen_is_string(name), name, 1, S_make_file_to_sample, "a string");
  5783. Xen_check_type(Xen_is_llong_or_unbound(buffer_size), buffer_size, 2, S_make_file_to_sample, "an integer");
  5784. if (!(mus_file_probe(Xen_string_to_C_string(name))))
  5785. Xen_error(NO_SUCH_FILE,
  5786. Xen_list_3(C_string_to_Xen_string(S_make_file_to_sample ": ~S, ~A"),
  5787. name,
  5788. C_string_to_Xen_string(STRERROR(errno))));
  5789. if (Xen_is_llong(buffer_size))
  5790. {
  5791. size = Xen_llong_to_C_llong(buffer_size);
  5792. if (size <= 0)
  5793. Xen_out_of_range_error(S_make_file_to_sample, 2, buffer_size, "must be > 0");
  5794. }
  5795. else size = mus_file_buffer_size();
  5796. ge = mus_make_file_to_sample_with_buffer_size(Xen_string_to_C_string(name), size);
  5797. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  5798. return(Xen_false);
  5799. }
  5800. static Xen g_file_to_sample(Xen obj, Xen samp, Xen chan)
  5801. {
  5802. #define H_file_to_sample "(" S_file_to_sample " obj frample chan): sample value in sound file read by 'obj' in channel chan at frample"
  5803. int channel = 0;
  5804. mus_any *g = NULL;
  5805. mus_xen *gn;
  5806. Xen_to_C_generator(obj, gn, g, mus_is_input, S_file_to_sample, "an input generator");
  5807. Xen_check_type(Xen_is_llong(samp), samp, 2, S_file_to_sample, "an integer");
  5808. if (Xen_is_bound(chan))
  5809. {
  5810. Xen_check_type(Xen_is_integer(chan), chan, 3, S_file_to_sample, "an integer");
  5811. channel = Xen_integer_to_C_int(chan);
  5812. }
  5813. return(C_double_to_Xen_real(mus_file_to_sample(g, Xen_llong_to_C_llong(samp), channel)));
  5814. }
  5815. static Xen g_make_sample_to_file(Xen name, Xen chans, Xen out_format, Xen out_type, Xen comment)
  5816. {
  5817. #if HAVE_SCHEME
  5818. #define make_sample_to_file_example "(" S_make_sample_to_file " \"test.snd\" 2 mus-lshort mus-riff)"
  5819. #endif
  5820. #if HAVE_RUBY
  5821. #define make_sample_to_file_example "\"test.snd\" 2 Mus_lshort Mus_riff make_sample2file"
  5822. #endif
  5823. #if HAVE_FORTH
  5824. #define make_sample_to_file_example "\"test.snd\" 2 mus-lshort mus-riff make-sample->file"
  5825. #endif
  5826. #define H_make_sample_to_file "(" S_make_sample_to_file " filename chans sample-type header-type comment): \
  5827. return an output generator writing the sound file 'filename' which is set up to have \
  5828. 'chans' channels of 'sample-type' samples with a header of 'header-type'. The latter \
  5829. should be sndlib identifiers:\n " make_sample_to_file_example
  5830. mus_sample_t df = MUS_OUT_SAMPLE_TYPE;
  5831. Xen_check_type(Xen_is_string(name), name, 1, S_make_sample_to_file, "a string");
  5832. Xen_check_type(Xen_is_integer_or_unbound(chans), chans, 2, S_make_sample_to_file, "an integer");
  5833. Xen_check_type(Xen_is_integer_or_unbound(out_format), out_format, 3, S_make_sample_to_file, "an integer (sample type)");
  5834. Xen_check_type(Xen_is_integer_or_unbound(out_type), out_type, 4, S_make_sample_to_file, "an integer (header type)");
  5835. if (Xen_is_integer(out_format)) df = (mus_sample_t)Xen_integer_to_C_int(out_format);
  5836. if (mus_is_sample_type(df))
  5837. {
  5838. mus_header_t ht = MUS_NEXT;
  5839. if (Xen_is_integer(out_type)) ht = (mus_header_t)Xen_integer_to_C_int(out_type);
  5840. if (mus_is_header_type(ht))
  5841. {
  5842. int chns = 1;
  5843. if (Xen_is_integer(chans)) chns = Xen_integer_to_C_int(chans);
  5844. if (chns > 0)
  5845. {
  5846. mus_any *rgen;
  5847. rgen = mus_make_sample_to_file_with_comment(Xen_string_to_C_string(name),
  5848. chns, df, ht,
  5849. (Xen_is_string(comment)) ? Xen_string_to_C_string(comment) : NULL);
  5850. if (rgen) return(mus_xen_to_object(mus_any_to_mus_xen(rgen)));
  5851. }
  5852. else Xen_out_of_range_error(S_make_sample_to_file, 2, chans, "chans <= 0?");
  5853. }
  5854. else Xen_out_of_range_error(S_make_sample_to_file, 4, out_type, "invalid header type");
  5855. }
  5856. else Xen_out_of_range_error(S_make_sample_to_file, 3, out_format, "invalid sample type");
  5857. return(Xen_false);
  5858. }
  5859. static Xen g_continue_sample_to_file(Xen name)
  5860. {
  5861. #define H_continue_sample_to_file "(" S_continue_sample_to_file " filename): return an output generator \
  5862. that reopens an existing sound file 'filename' ready for output via " S_sample_to_file
  5863. mus_any *rgen = NULL;
  5864. Xen_check_type(Xen_is_string(name), name, 1, S_continue_sample_to_file, "a string");
  5865. rgen = mus_continue_sample_to_file(Xen_string_to_C_string(name));
  5866. if (rgen) return(mus_xen_to_object(mus_any_to_mus_xen(rgen)));
  5867. return(Xen_false);
  5868. }
  5869. static Xen g_sample_to_file(Xen obj, Xen samp, Xen chan, Xen val)
  5870. {
  5871. #define H_sample_to_file "(" S_sample_to_file " obj samp chan val): add val to the output stream \
  5872. handled by the output generator 'obj', in channel 'chan' at frample 'samp'"
  5873. mus_any *g = NULL;
  5874. mus_xen *gn;
  5875. Xen_to_C_any_generator(obj, gn, g, S_sample_to_file, "an output generator");
  5876. Xen_check_type(mus_is_output(g), obj, 1, S_sample_to_file, "an output generator");
  5877. Xen_check_type(Xen_is_integer(samp), samp, 2, S_sample_to_file, "an integer");
  5878. Xen_check_type(Xen_is_integer(chan), chan, 3, S_sample_to_file, "an integer");
  5879. Xen_check_type(Xen_is_number(val), val, 4, S_sample_to_file, "a number");
  5880. mus_sample_to_file(g,
  5881. Xen_llong_to_C_llong(samp),
  5882. Xen_integer_to_C_int(chan),
  5883. Xen_real_to_C_double(val));
  5884. return(val);
  5885. }
  5886. static Xen g_sample_to_file_add(Xen obj1, Xen obj2)
  5887. {
  5888. #define H_sample_to_file_add "(" S_sample_to_file_add " obj1 obj2): mixes obj2 (an output generator) into obj1 (also an output generator)"
  5889. mus_any *g1 = NULL, *g2 = NULL;
  5890. mus_xen *gn1, *gn2;
  5891. Xen_to_C_any_generator(obj1, gn1, g1, S_sample_to_file_add, "an output generator");
  5892. Xen_to_C_any_generator(obj2, gn2, g2, S_sample_to_file_add, "an output generator");
  5893. Xen_check_type(mus_is_output(g1), obj1, 1, S_sample_to_file_add, "an output generator");
  5894. Xen_check_type(mus_is_output(g2), obj2, 2, S_sample_to_file_add, "an output generator");
  5895. mus_sample_to_file_add(g1, g2);
  5896. return(obj1);
  5897. }
  5898. static Xen g_make_file_to_frample(Xen name, Xen buffer_size)
  5899. {
  5900. #define H_make_file_to_frample "(" S_make_file_to_frample " filename buffer-size): return an input generator reading 'filename' (a sound file)"
  5901. mus_any *ge;
  5902. mus_long_t size;
  5903. Xen_check_type(Xen_is_string(name), name, 1, S_make_file_to_frample, "a string");
  5904. Xen_check_type(Xen_is_llong_or_unbound(buffer_size), buffer_size, 2, S_make_file_to_frample, "an integer");
  5905. if (!(mus_file_probe(Xen_string_to_C_string(name))))
  5906. Xen_error(NO_SUCH_FILE,
  5907. Xen_list_3(C_string_to_Xen_string(S_make_file_to_frample ": ~S, ~A"),
  5908. name,
  5909. C_string_to_Xen_string(STRERROR(errno))));
  5910. if (Xen_is_llong(buffer_size))
  5911. {
  5912. size = Xen_llong_to_C_llong(buffer_size);
  5913. if (size <= 0)
  5914. Xen_out_of_range_error(S_make_file_to_frample, 2, buffer_size, "must be > 0");
  5915. }
  5916. else size = mus_file_buffer_size();
  5917. ge = mus_make_file_to_frample_with_buffer_size(Xen_string_to_C_string(name), size);
  5918. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  5919. return(Xen_false);
  5920. }
  5921. static Xen g_file_to_frample(Xen obj, Xen samp, Xen outfr)
  5922. {
  5923. #define H_file_to_frample "(" S_file_to_frample " obj samp outf): frample of samples at frample 'samp' in sound file read by 'obj'"
  5924. Xen_check_type((mus_is_xen(obj)) && (mus_is_input(Xen_to_mus_any(obj))), obj, 1, S_file_to_frample, "an input generator");
  5925. Xen_check_type(Xen_is_integer(samp), samp, 2, S_file_to_frample, "an integer");
  5926. mus_file_to_frample(Xen_to_mus_any(obj), Xen_llong_to_C_llong(samp), mus_vct_data(Xen_to_vct(outfr)));
  5927. return(outfr);
  5928. }
  5929. static Xen g_make_frample_to_file(Xen name, Xen chans, Xen out_format, Xen out_type, Xen comment)
  5930. {
  5931. #if HAVE_SCHEME
  5932. #define make_frample_to_file_example "(" S_make_frample_to_file " \"test.snd\" 2 mus-lshort mus-riff)"
  5933. #endif
  5934. #if HAVE_RUBY
  5935. #define make_frample_to_file_example "\"test.snd\" 2 Mus_lshort Mus_riff make_frample2file"
  5936. #endif
  5937. #if HAVE_FORTH
  5938. #define make_frample_to_file_example "\"test.snd\" 2 mus-lshort mus-riff make-frample->file"
  5939. #endif
  5940. #define H_make_frample_to_file "(" S_make_frample_to_file " filename chans sample-type header-type comment): \
  5941. return an output generator writing the sound file 'filename' which is set up to have \
  5942. 'chans' channels of 'sample-type' samples with a header of 'header-type'. The latter \
  5943. should be sndlib identifiers:\n " make_frample_to_file_example
  5944. mus_any *fgen = NULL;
  5945. Xen_check_type(Xen_is_string(name), name, 1, S_make_frample_to_file, "a string");
  5946. Xen_check_type(Xen_is_integer_or_unbound(chans), chans, 2, S_make_frample_to_file, "an integer");
  5947. Xen_check_type(Xen_is_integer_or_unbound(out_format), out_format, 3, S_make_frample_to_file, "an integer (sample type id)");
  5948. Xen_check_type(Xen_is_integer_or_unbound(out_type), out_type, 4, S_make_frample_to_file, "an integer (header-type id)");
  5949. fgen = mus_make_frample_to_file_with_comment(Xen_string_to_C_string(name),
  5950. (Xen_is_integer(chans)) ? Xen_integer_to_C_int(chans) : 1,
  5951. (Xen_is_integer(out_format)) ? (mus_sample_t)Xen_integer_to_C_int(out_format) : MUS_OUT_SAMPLE_TYPE,
  5952. (Xen_is_integer(out_type)) ? (mus_header_t)Xen_integer_to_C_int(out_type) : MUS_NEXT,
  5953. (Xen_is_string(comment)) ? Xen_string_to_C_string(comment) : NULL);
  5954. if (fgen) return(mus_xen_to_object(mus_any_to_mus_xen(fgen)));
  5955. return(Xen_false);
  5956. }
  5957. static Xen g_continue_frample_to_file(Xen name)
  5958. {
  5959. #define H_continue_frample_to_file "(" S_continue_frample_to_file " filename): return an output generator \
  5960. that reopens an existing sound file 'filename' ready for output via " S_frample_to_file
  5961. mus_any *rgen = NULL;
  5962. Xen_check_type(Xen_is_string(name), name, 1, S_continue_frample_to_file, "a string");
  5963. rgen = mus_continue_frample_to_file(Xen_string_to_C_string(name));
  5964. if (rgen) return(mus_xen_to_object(mus_any_to_mus_xen(rgen)));
  5965. return(Xen_false);
  5966. }
  5967. static Xen g_frample_to_file(Xen obj, Xen samp, Xen val)
  5968. {
  5969. #define H_frample_to_file "(" S_frample_to_file " obj samp val): add frample 'val' to the output stream \
  5970. handled by the output generator 'obj' at frample 'samp'"
  5971. mus_xen *gn;
  5972. gn = (mus_xen *)Xen_object_ref_checked(obj, mus_xen_tag);
  5973. Xen_check_type(((gn) && (mus_is_output(gn->gen))), obj, 1, S_frample_to_file, "an output generator");
  5974. Xen_check_type(Xen_is_integer(samp), samp, 2, S_frample_to_file, "an integer");
  5975. mus_frample_to_file(gn->gen, Xen_llong_to_C_llong(samp), mus_vct_data(Xen_to_vct(val)));
  5976. return(val);
  5977. }
  5978. /* ---------------- readin ---------------- */
  5979. static Xen g_is_readin(Xen obj)
  5980. {
  5981. #define H_is_readin "(" S_is_readin " gen): " PROC_TRUE " if gen is a " S_readin
  5982. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_readin(Xen_to_mus_any(obj)))));
  5983. }
  5984. static Xen g_readin(Xen obj)
  5985. {
  5986. #define H_readin "(" S_readin " gen): next sample from readin generator (a sound file reader)"
  5987. mus_any *g = NULL;
  5988. mus_xen *gn;
  5989. Xen_to_C_generator(obj, gn, g, mus_is_readin, S_readin, "a readin generator");
  5990. return(C_double_to_Xen_real(mus_readin(g)));
  5991. }
  5992. static Xen g_make_readin(Xen arglist)
  5993. {
  5994. #define H_make_readin "(" S_make_readin " file (channel 0) (start 0) (direction 1) size): \
  5995. return a new readin (file input) generator reading the sound file 'file' starting at frample \
  5996. 'start' in channel 'channel' and reading forward if 'direction' is not -1"
  5997. /* optkey file channel start direction size */
  5998. mus_any *ge;
  5999. const char *file = NULL;
  6000. Xen args[10];
  6001. Xen keys[5];
  6002. int orig_arg[5] = {0, 0, 0, 0, 0};
  6003. int vals, chans;
  6004. mus_long_t buffer_size;
  6005. int channel = 0, direction = 1;
  6006. mus_long_t start = 0;
  6007. keys[0] = kw_file;
  6008. keys[1] = kw_channel;
  6009. keys[2] = kw_start;
  6010. keys[3] = kw_direction;
  6011. keys[4] = kw_size;
  6012. buffer_size = mus_file_buffer_size();
  6013. /* this is only 8192! (clm.h MUS_DEFAULT_FILE_BUFFER_SIZE) */
  6014. {
  6015. int i, arglist_len;
  6016. Xen p;
  6017. arglist_len = Xen_list_length(arglist);
  6018. if (arglist_len > 10) clm_error(S_make_readin, "too many arguments!", arglist);
  6019. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  6020. for (i = arglist_len; i < 10; i++) args[i] = Xen_undefined;
  6021. }
  6022. vals = mus_optkey_unscramble(S_make_readin, 5, keys, args, orig_arg);
  6023. if (vals > 0)
  6024. {
  6025. file = mus_optkey_to_string(keys[0], S_make_readin, orig_arg[0], NULL); /* not copied */
  6026. channel = Xen_optkey_to_int(kw_channel, keys[1], S_make_readin, orig_arg[1], channel);
  6027. if (channel < 0)
  6028. Xen_out_of_range_error(S_make_readin, orig_arg[1], keys[1], "channel < 0?");
  6029. start = Xen_optkey_to_mus_long_t(kw_start, keys[2], S_make_readin, orig_arg[2], start);
  6030. direction = Xen_optkey_to_int(kw_direction, keys[3], S_make_readin, orig_arg[3], direction);
  6031. buffer_size = Xen_optkey_to_mus_long_t(kw_size, keys[4], S_make_readin, orig_arg[4], buffer_size);
  6032. if (buffer_size <= 0)
  6033. Xen_out_of_range_error(S_make_readin, orig_arg[4], keys[4], "must be > 0");
  6034. }
  6035. if (file == NULL)
  6036. Xen_out_of_range_error(S_make_readin, orig_arg[0], keys[0], "no file name given");
  6037. if (!(mus_file_probe(file)))
  6038. Xen_error(NO_SUCH_FILE,
  6039. Xen_list_3(C_string_to_Xen_string(S_make_readin ": ~S, ~A"),
  6040. C_string_to_Xen_string(file),
  6041. C_string_to_Xen_string(STRERROR(errno))));
  6042. chans = mus_sound_chans(file);
  6043. if (chans <= 0)
  6044. Xen_error(BAD_HEADER,
  6045. Xen_list_2(C_string_to_Xen_string(S_make_readin ": ~S chans <= 0?"),
  6046. C_string_to_Xen_string(file)));
  6047. if (channel >= chans)
  6048. Xen_out_of_range_error(S_make_readin, orig_arg[1], keys[1], "channel > available chans?");
  6049. ge = mus_make_readin_with_buffer_size(file, channel, start, direction, buffer_size);
  6050. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  6051. return(Xen_false);
  6052. }
  6053. /* ---------------- locsig ---------------- */
  6054. static Xen g_locsig_ref(Xen obj, Xen chan)
  6055. {
  6056. #define H_locsig_ref "(" S_locsig_ref " gen chan): locsig 'gen' channel 'chan' scaler"
  6057. Xen_check_type((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj))), obj, 1, S_locsig_ref, "a locsig generator");
  6058. Xen_check_type(Xen_is_integer(chan), chan, 2, S_locsig_ref, "an integer");
  6059. return(C_double_to_Xen_real(mus_locsig_ref(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan))));
  6060. }
  6061. static Xen g_locsig_set(Xen obj, Xen chan, Xen val)
  6062. {
  6063. #define H_locsig_set "(" S_locsig_set " gen chan val): set the locsig generator's channel 'chan' scaler to 'val'"
  6064. Xen_check_type((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj))), obj, 1, S_locsig_set, "a locsig generator");
  6065. Xen_check_type(Xen_is_integer(chan), chan, 2, S_locsig_set, "an integer");
  6066. #if (!HAVE_SCHEME)
  6067. Xen_check_type(Xen_is_number(val), val, 3, S_locsig_set, "a number");
  6068. mus_locsig_set(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan), Xen_real_to_C_double(val));
  6069. #else
  6070. mus_locsig_set(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan), s7_number_to_real_with_caller(s7, val, S_locsig_set));
  6071. #endif
  6072. return(val);
  6073. }
  6074. static Xen g_locsig_reverb_ref(Xen obj, Xen chan)
  6075. {
  6076. #define H_locsig_reverb_ref "(" S_locsig_reverb_ref " gen chan): locsig reverb channel 'chan' scaler"
  6077. Xen_check_type((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj))), obj, 1, S_locsig_reverb_ref, "a locsig generator");
  6078. Xen_check_type(Xen_is_integer(chan), chan, 2, S_locsig_reverb_ref, "an integer");
  6079. return(C_double_to_Xen_real(mus_locsig_reverb_ref(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan))));
  6080. }
  6081. static Xen g_locsig_reverb_set(Xen obj, Xen chan, Xen val)
  6082. {
  6083. #define H_locsig_reverb_set "(" S_locsig_reverb_set " gen chan val): set the locsig reverb channel 'chan' scaler to 'val'"
  6084. Xen_check_type((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj))), obj, 1, S_locsig_reverb_set, "a locsig generator");
  6085. Xen_check_type(Xen_is_integer(chan), chan, 2, S_locsig_reverb_set, "an integer");
  6086. #if (!HAVE_SCHEME)
  6087. Xen_check_type(Xen_is_number(val), val, 3, S_locsig_reverb_set, "a number");
  6088. mus_locsig_reverb_set(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan), Xen_real_to_C_double(val));
  6089. #else
  6090. mus_locsig_reverb_set(Xen_to_mus_any(obj), Xen_integer_to_C_int(chan), s7_number_to_real_with_caller(s7, val, S_locsig_reverb_set));
  6091. #endif
  6092. return(val);
  6093. }
  6094. static Xen g_is_locsig(Xen obj)
  6095. {
  6096. #define H_is_locsig "(" S_is_locsig " gen): " PROC_TRUE " if gen is a " S_locsig
  6097. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj)))));
  6098. }
  6099. static void mus_locsig_or_move_sound_to_vct_or_sound_data(mus_xen *ms, mus_any *loc_gen, mus_long_t pos, bool from_locsig)
  6100. {
  6101. mus_float_t *outfr = NULL, *revfr = NULL;
  6102. Xen output, reverb;
  6103. #if HAVE_SCHEME
  6104. int chans, rev_chans;
  6105. #endif
  6106. if (pos < 0) return;
  6107. if (from_locsig)
  6108. {
  6109. outfr = mus_locsig_outf(loc_gen);
  6110. revfr = mus_locsig_revf(loc_gen);
  6111. #if HAVE_SCHEME
  6112. chans = mus_locsig_channels(loc_gen);
  6113. rev_chans = mus_locsig_reverb_channels(loc_gen);
  6114. #endif
  6115. }
  6116. else
  6117. {
  6118. outfr = mus_move_sound_outf(loc_gen);
  6119. revfr = mus_move_sound_revf(loc_gen);
  6120. #if HAVE_SCHEME
  6121. chans = mus_move_sound_channels(loc_gen);
  6122. rev_chans = mus_move_sound_reverb_channels(loc_gen);
  6123. #endif
  6124. }
  6125. output = ms->vcts[G_LOCSIG_OUT];
  6126. if (outfr)
  6127. {
  6128. if (mus_is_vct(output))
  6129. {
  6130. vct *v;
  6131. mus_float_t *vdata;
  6132. v = Xen_to_vct(output);
  6133. vdata = mus_vct_data(v);
  6134. if (Xen_vector_rank(output) == 1)
  6135. {
  6136. if (pos < mus_vct_length(v))
  6137. vdata[pos] += outfr[0];
  6138. }
  6139. #if HAVE_SCHEME
  6140. else
  6141. {
  6142. s7_int chan_len;
  6143. chan_len = s7_vector_dimensions(output)[1]; /* '(4 20) so each chan len is [1] */
  6144. if (pos < chan_len)
  6145. {
  6146. int i;
  6147. for (i = 0; i < chans; i++)
  6148. vdata[i * chan_len + pos] += outfr[i];
  6149. }
  6150. }
  6151. #endif
  6152. }
  6153. else
  6154. {
  6155. if ((Xen_is_vector(output)) &&
  6156. (pos < Xen_vector_length(output)))
  6157. Xen_vector_set(output, pos, C_double_to_Xen_real(Xen_real_to_C_double(Xen_vector_ref(output, pos)) + outfr[0]));
  6158. }
  6159. }
  6160. if ((revfr) &&
  6161. (Xen_is_bound(ms->vcts[G_LOCSIG_REVOUT])))
  6162. {
  6163. reverb = ms->vcts[G_LOCSIG_REVOUT];
  6164. if (mus_is_vct(reverb))
  6165. {
  6166. vct *v;
  6167. mus_float_t *vdata;
  6168. v = Xen_to_vct(reverb);
  6169. vdata = mus_vct_data(v);
  6170. if (Xen_vector_rank(reverb) == 1)
  6171. {
  6172. if (pos < mus_vct_length(v))
  6173. vdata[pos] += revfr[0];
  6174. }
  6175. #if HAVE_SCHEME
  6176. else
  6177. {
  6178. s7_int chan_len;
  6179. chan_len = s7_vector_dimensions(reverb)[1];
  6180. if (pos < chan_len)
  6181. {
  6182. int i;
  6183. for (i = 0; i < rev_chans; i++)
  6184. vdata[i * chan_len + pos] += revfr[i];
  6185. }
  6186. }
  6187. #endif
  6188. }
  6189. else
  6190. {
  6191. if ((Xen_is_vector(reverb)) &&
  6192. (pos < Xen_vector_length(reverb)))
  6193. Xen_vector_set(reverb, pos, C_double_to_Xen_real(Xen_real_to_C_double(Xen_vector_ref(reverb, pos)) + revfr[0]));
  6194. }
  6195. }
  6196. }
  6197. static Xen g_locsig(Xen xobj, Xen xpos, Xen xval)
  6198. {
  6199. #define H_locsig "(" S_locsig " gen loc val): add 'val' to the output of locsig at frample 'loc'"
  6200. mus_any *loc_gen;
  6201. mus_xen *ms;
  6202. mus_long_t pos;
  6203. mus_float_t fval;
  6204. ms = (mus_xen *)Xen_object_ref_checked(xobj, mus_xen_tag);
  6205. if (!ms) Xen_check_type(false, xobj, 1, S_locsig, "a locsig generator");
  6206. loc_gen = ms->gen;
  6207. Xen_check_type(mus_is_locsig(loc_gen), xobj, 1, S_locsig, "a locsig generator");
  6208. Xen_check_type(Xen_is_integer(xpos), xpos, 2, S_locsig, "an integer");
  6209. pos = Xen_llong_to_C_llong(xpos);
  6210. if (pos < 0)
  6211. Xen_out_of_range_error(S_locsig, 2, xpos, "must be >= 0");
  6212. #if (!HAVE_SCHEME)
  6213. Xen_check_type(Xen_is_number(xval), xval, 3, S_locsig, "a number");
  6214. fval = Xen_real_to_C_double(xval);
  6215. #else
  6216. fval = s7_number_to_real_with_caller(s7, xval, S_locsig);
  6217. #endif
  6218. mus_locsig(loc_gen, pos, fval);
  6219. return(xval); /* changed 30-June-06 to return val rather than a wrapped frample */
  6220. }
  6221. static mus_interp_t clm_locsig_type = MUS_INTERP_LINEAR;
  6222. static Xen g_locsig_type(void)
  6223. {
  6224. #define H_locsig_type "(" S_locsig_type "): locsig interpolation type, either " S_mus_interp_linear " or " S_mus_interp_sinusoidal "."
  6225. return(C_int_to_Xen_integer((int)clm_locsig_type));
  6226. }
  6227. static Xen g_set_locsig_type(Xen val)
  6228. {
  6229. mus_interp_t newval;
  6230. Xen_check_type(Xen_is_integer(val), val, 1, S_locsig_type, S_mus_interp_linear " or " S_mus_interp_sinusoidal);
  6231. newval = (mus_interp_t)Xen_integer_to_C_int(val);
  6232. if ((newval == MUS_INTERP_LINEAR) || (newval == MUS_INTERP_SINUSOIDAL))
  6233. clm_locsig_type = newval;
  6234. return(C_int_to_Xen_integer((int)clm_locsig_type));
  6235. }
  6236. static void clm_locsig_detour(mus_any *ptr, mus_long_t pos)
  6237. {
  6238. mus_xen *ms;
  6239. ms = (mus_xen *)mus_locsig_closure(ptr);
  6240. /* now check for vct/sound-data special cases */
  6241. if (ms->nvcts == 4)
  6242. mus_locsig_or_move_sound_to_vct_or_sound_data(ms, ms->gen, pos, true);
  6243. }
  6244. static Xen g_make_locsig(Xen arglist)
  6245. {
  6246. #define H_make_locsig "(" S_make_locsig " (degree 0.0) (distance 1.0) (reverb 0.0) (output *output*) (revout *reverb*) (channels (mus-channels *output*)) (type " S_mus_interp_linear ")): \
  6247. return a new generator for signal placement in n channels. Channel 0 corresponds to 0 degrees."
  6248. mus_any *ge;
  6249. mus_any *outp = NULL, *revp = NULL;
  6250. Xen args[14];
  6251. Xen keys[7];
  6252. Xen ov = Xen_undefined, rv = Xen_undefined;
  6253. Xen keys3 = Xen_undefined, keys4 = Xen_undefined;
  6254. int orig_arg[7] = {0, 0, 0, 0, 0, 0, 0};
  6255. int vals, out_chans = -1, rev_chans = -1;
  6256. mus_interp_t type;
  6257. mus_float_t degree = 0.0, distance = 1.0, reverb = 0.0;
  6258. type = clm_locsig_type;
  6259. keys[0] = kw_degree;
  6260. keys[1] = kw_distance;
  6261. keys[2] = kw_reverb;
  6262. keys[3] = kw_output;
  6263. keys[4] = kw_revout;
  6264. keys[5] = kw_channels;
  6265. keys[6] = kw_type;
  6266. {
  6267. int i, arglist_len;
  6268. Xen p;
  6269. arglist_len = Xen_list_length(arglist);
  6270. if (arglist_len > 14) clm_error(S_make_locsig, "too many arguments!", arglist);
  6271. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  6272. for (i = arglist_len; i < 14; i++) args[i] = Xen_undefined;
  6273. }
  6274. vals = mus_optkey_unscramble(S_make_locsig, 7, keys, args, orig_arg);
  6275. if (vals > 0)
  6276. {
  6277. degree = Xen_optkey_to_float(kw_degree, keys[0], S_make_locsig, orig_arg[0], degree);
  6278. distance = Xen_optkey_to_float(kw_distance, keys[1], S_make_locsig, orig_arg[1], distance);
  6279. reverb = Xen_optkey_to_float(kw_reverb, keys[2], S_make_locsig, orig_arg[2], reverb);
  6280. if (!(Xen_is_keyword(keys[3])))
  6281. keys3 = keys[3];
  6282. if (!(Xen_is_keyword(keys[4])))
  6283. keys4 = keys[4];
  6284. if (!(Xen_is_keyword(keys[5])))
  6285. {
  6286. Xen_check_type(Xen_is_integer(keys[5]), keys[5], orig_arg[5], S_make_locsig, "an integer");
  6287. out_chans = Xen_integer_to_C_int(keys[5]);
  6288. if (out_chans < 0)
  6289. Xen_out_of_range_error(S_make_locsig, orig_arg[5], keys[5], "chans < 0?");
  6290. if (out_chans > mus_max_table_size())
  6291. Xen_out_of_range_error(S_make_locsig, orig_arg[5], keys[5], "too many chans");
  6292. }
  6293. type = (mus_interp_t)Xen_optkey_to_int(kw_type, keys[6], S_make_locsig, orig_arg[6], (int)type);
  6294. if ((type != MUS_INTERP_LINEAR) && (type != MUS_INTERP_SINUSOIDAL))
  6295. Xen_out_of_range_error(S_make_locsig, orig_arg[6], keys[6], "type must be " S_mus_interp_linear " or " S_mus_interp_sinusoidal ".");
  6296. }
  6297. if (!Xen_is_bound(keys3))
  6298. keys3 = CLM_OUTPUT;
  6299. if (!Xen_is_bound(keys4))
  6300. keys4 = CLM_REVERB;
  6301. /* try to default output to *output* and reverb to *reverb*, if they're currently set and not closed */
  6302. /* mus_close is actually mus_close_file = sample_to_file_end = free and nullify obufs so we're hoping dynamic-wind works... */
  6303. if ((mus_is_xen(keys3)) &&
  6304. (mus_is_output(Xen_to_mus_any(keys3))))
  6305. {
  6306. outp = (mus_any *)Xen_to_mus_any(keys3);
  6307. if (out_chans < 0)
  6308. out_chans = mus_channels((mus_any *)outp);
  6309. }
  6310. else
  6311. {
  6312. if (mus_is_vct(keys3))
  6313. ov = keys3;
  6314. else Xen_check_type(Xen_is_keyword(keys[3]) || Xen_is_false(keys[3]), keys[3], orig_arg[3], S_make_locsig, "an output gen, " S_vct ", vector, or a sound-data object");
  6315. #if HAVE_SCHEME
  6316. if ((out_chans < 0) &&
  6317. (s7_is_vector(ov)) &&
  6318. (s7_vector_rank(ov) > 1))
  6319. out_chans = s7_vector_dimensions(ov)[0];
  6320. #endif
  6321. }
  6322. if ((mus_is_xen(keys4)) &&
  6323. (mus_is_output(Xen_to_mus_any(keys4))))
  6324. {
  6325. revp = (mus_any *)Xen_to_mus_any(keys4);
  6326. if (rev_chans < 0)
  6327. rev_chans = mus_channels((mus_any *)revp);
  6328. }
  6329. else
  6330. {
  6331. if (mus_is_vct(keys4))
  6332. {
  6333. rv = keys4;
  6334. rev_chans = 1;
  6335. #if HAVE_SCHEME
  6336. if (Xen_vector_rank(rv) > 1)
  6337. rev_chans = s7_vector_dimensions(rv)[0];
  6338. #endif
  6339. }
  6340. else Xen_check_type(Xen_is_keyword(keys[4]) || Xen_is_false(keys[4]), keys[4], orig_arg[4], S_make_locsig, "a reverb output generator");
  6341. }
  6342. if (out_chans < 0) out_chans = 1;
  6343. if (rev_chans < 0) rev_chans = 0;
  6344. ge = mus_make_locsig(degree, distance, reverb, out_chans, outp, rev_chans, revp, type);
  6345. if (ge)
  6346. {
  6347. mus_xen *gn;
  6348. if (((Xen_is_bound(ov)) && (!Xen_is_false(ov))) ||
  6349. ((Xen_is_bound(rv)) && (!Xen_is_false(rv))))
  6350. gn = mx_alloc(4);
  6351. else gn = mx_alloc(2);
  6352. /* these two are for the mus-data and mus-xcoeffs methods in Scheme (etc) = MUS_DATA_WRAPPER and G_FILTER_XCOEFFS */
  6353. if (out_chans > 0)
  6354. gn->vcts[G_LOCSIG_DATA] = xen_make_vct_wrapper(out_chans, mus_data(ge));
  6355. else gn->vcts[G_LOCSIG_DATA] = Xen_undefined;
  6356. if (rev_chans > 0)
  6357. gn->vcts[G_LOCSIG_REVDATA] = xen_make_vct_wrapper(rev_chans, mus_xcoeffs(ge));
  6358. else gn->vcts[G_LOCSIG_REVDATA] = Xen_undefined;
  6359. if (gn->nvcts == 4)
  6360. {
  6361. mus_locsig_set_detour(ge, clm_locsig_detour);
  6362. gn->vcts[G_LOCSIG_OUT] = ov;
  6363. gn->vcts[G_LOCSIG_REVOUT] = rv;
  6364. mus_set_environ(ge, (void *)gn);
  6365. }
  6366. gn->gen = ge;
  6367. return(mus_xen_to_object(gn));
  6368. }
  6369. return(Xen_false);
  6370. }
  6371. static Xen g_move_locsig(Xen obj, Xen degree, Xen distance)
  6372. {
  6373. #define H_move_locsig "(" S_move_locsig " gen degree distance): move locsig gen to reflect degree and distance"
  6374. Xen_check_type((mus_is_xen(obj)) && (mus_is_locsig(Xen_to_mus_any(obj))), obj, 1, S_move_locsig, "a locsig generator");
  6375. #if (!HAVE_SCHEME)
  6376. Xen_check_type(Xen_is_number(degree), degree, 2, S_move_locsig, "a number in degrees");
  6377. Xen_check_type(Xen_is_number(distance), distance, 3, S_move_locsig, "a number > 1.0");
  6378. mus_move_locsig(Xen_to_mus_any(obj), Xen_real_to_C_double(degree), Xen_real_to_C_double(distance));
  6379. #else
  6380. mus_move_locsig(Xen_to_mus_any(obj),
  6381. s7_number_to_real_with_caller(s7, degree, S_move_locsig),
  6382. s7_number_to_real_with_caller(s7, distance, S_move_locsig));
  6383. #endif
  6384. return(obj);
  6385. }
  6386. /* ---------------- move-sound ---------------- */
  6387. static Xen g_is_move_sound(Xen obj)
  6388. {
  6389. #define H_is_move_sound "(" S_is_move_sound " gen): " PROC_TRUE " if gen is a " S_move_sound
  6390. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_move_sound(Xen_to_mus_any(obj)))));
  6391. }
  6392. static Xen g_move_sound(Xen obj, Xen loc, Xen val)
  6393. {
  6394. #define H_move_sound "(" S_move_sound " gen loc val): dlocsig run-time generator handling 'val' at sample 'loc'"
  6395. mus_any *move_gen;
  6396. mus_xen *ms;
  6397. mus_long_t pos;
  6398. mus_float_t fval;
  6399. Xen_check_type(mus_is_xen(obj), obj, 1, S_move_sound, "a move-sound generator");
  6400. ms = Xen_to_mus_xen(obj);
  6401. move_gen = (mus_any *)(ms->gen);
  6402. Xen_check_type(mus_is_move_sound(move_gen), obj, 1, S_move_sound, "a move-sound generator");
  6403. Xen_check_type(Xen_is_integer(loc), loc, 2, S_move_sound, "an integer");
  6404. Xen_check_type(Xen_is_number(val), val, 3, S_move_sound, "a number");
  6405. pos = Xen_llong_to_C_llong(loc);
  6406. if (pos < 0)
  6407. Xen_out_of_range_error(S_move_sound, 2, loc, "must be >= 0");
  6408. fval = Xen_real_to_C_double(val);
  6409. mus_move_sound(move_gen, pos, fval);
  6410. return(val);
  6411. }
  6412. static mus_any **xen_vector_to_mus_any_array(Xen vect)
  6413. {
  6414. mus_any **gens;
  6415. mus_long_t i, len;
  6416. if (!(Xen_is_vector(vect))) return(NULL);
  6417. len = Xen_vector_length(vect);
  6418. gens = (mus_any **)calloc(len, sizeof(mus_any *));
  6419. for (i = 0; i < len; i++)
  6420. if (mus_is_xen(Xen_vector_ref(vect, i)))
  6421. gens[i] = Xen_to_mus_any(Xen_vector_ref(vect, i));
  6422. return(gens);
  6423. }
  6424. static int *xen_vector_to_int_array(Xen vect)
  6425. {
  6426. int *vals;
  6427. mus_long_t i, len;
  6428. len = Xen_vector_length(vect);
  6429. vals = (int *)calloc(len, sizeof(int));
  6430. for (i = 0; i < len; i++)
  6431. vals[i] = Xen_integer_to_C_int(Xen_vector_ref(vect, i));
  6432. return(vals);
  6433. }
  6434. static void clm_move_sound_detour(mus_any *ptr, mus_long_t pos)
  6435. {
  6436. mus_xen *ms;
  6437. ms = (mus_xen *)mus_move_sound_closure(ptr);
  6438. /* now check for vct/sound-data special cases */
  6439. if (ms->nvcts == 4)
  6440. mus_locsig_or_move_sound_to_vct_or_sound_data(ms, ms->gen, pos, false);
  6441. }
  6442. static Xen g_make_move_sound(Xen dloc_list, Xen outp, Xen revp)
  6443. {
  6444. Xen ov = Xen_undefined, rv = Xen_undefined;
  6445. mus_any *ge, *dopdly, *dopenv, *globrevenv = NULL, *output = NULL, *revput = NULL;
  6446. mus_any **out_delays, **out_envs, **rev_envs;
  6447. int *out_map;
  6448. mus_long_t start, end;
  6449. int outchans = 0, revchans = 0;
  6450. Xen ref;
  6451. #define H_make_move_sound "(" S_make_move_sound " dloc-list (out *output*) (rev *reverb*)): make a dlocsig run-time generator"
  6452. /* dloc-list is (list start end outchans revchans dopdly dopenv revenv outdelays outenvs revenvs outmap) */
  6453. /* outdelays envs and revenvs are vectors */
  6454. Xen_check_type(Xen_is_list(dloc_list) && (Xen_list_length(dloc_list) == 11), dloc_list, 1, S_make_move_sound, "a dlocsig list");
  6455. if (!Xen_is_bound(outp))
  6456. outp = CLM_OUTPUT;
  6457. if (!Xen_is_bound(revp))
  6458. revp = CLM_REVERB;
  6459. if (mus_is_xen(outp))
  6460. {
  6461. output = Xen_to_mus_any(outp);
  6462. Xen_check_type(mus_is_output(output), outp, 2, S_make_move_sound, "output stream");
  6463. }
  6464. else
  6465. {
  6466. if ((mus_is_vct(outp)) ||
  6467. (Xen_is_false(outp)) ||
  6468. (!Xen_is_bound(outp)))
  6469. ov = outp;
  6470. else Xen_check_type(false, outp, 2, S_make_move_sound, "output stream, " S_vct ", or a sound-data object");
  6471. }
  6472. if (mus_is_xen(revp))
  6473. {
  6474. revput = Xen_to_mus_any(revp);
  6475. Xen_check_type(mus_is_output(revput), revp, 3, S_make_move_sound, "reverb stream");
  6476. }
  6477. else
  6478. {
  6479. if ((mus_is_vct(revp)) ||
  6480. (Xen_is_false(revp)) ||
  6481. (!Xen_is_bound(revp)))
  6482. rv = revp;
  6483. else Xen_check_type(false, revp, 3, S_make_move_sound, "reverb stream, " S_vct ", or a sound-data object");
  6484. }
  6485. ref = Xen_list_ref(dloc_list, 0);
  6486. Xen_check_type(Xen_is_llong(ref), ref, 1, S_make_move_sound, "dlocsig list[0] (start): a sample number");
  6487. start = Xen_llong_to_C_llong(ref);
  6488. ref = Xen_list_ref(dloc_list, 1);
  6489. Xen_check_type(Xen_is_llong(ref), ref, 1, S_make_move_sound, "dlocsig list[1] (end): a sample number");
  6490. end = Xen_llong_to_C_llong(ref);
  6491. ref = Xen_list_ref(dloc_list, 2);
  6492. Xen_check_type(Xen_is_integer(ref), ref, 1, S_make_move_sound, "dlocsig list[2] (outchans): an integer");
  6493. outchans = Xen_integer_to_C_int(ref);
  6494. ref = Xen_list_ref(dloc_list, 3);
  6495. Xen_check_type(Xen_is_integer(ref), ref, 1, S_make_move_sound, "dlocsig list[3] (revchans): an integer");
  6496. revchans = Xen_integer_to_C_int(ref);
  6497. ref = Xen_list_ref(dloc_list, 4);
  6498. Xen_check_type(mus_is_xen(ref), ref, 1, S_make_move_sound, "dlocsig list[4] (doppler delay): a delay generator");
  6499. dopdly = Xen_to_mus_any(ref);
  6500. Xen_check_type(mus_is_delay(dopdly), ref, 1, S_make_move_sound, "dlocsig list[4] (doppler delay): a delay generator");
  6501. ref = Xen_list_ref(dloc_list, 5);
  6502. Xen_check_type(mus_is_xen(ref), ref, 1, S_make_move_sound, "dlocsig list[5] (doppler env): an env generator");
  6503. dopenv = Xen_to_mus_any(ref);
  6504. Xen_check_type(mus_is_env(dopenv), ref, 1, S_make_move_sound, "dlocsig list[5] (doppler env): an env generator");
  6505. ref = Xen_list_ref(dloc_list, 6);
  6506. Xen_check_type(Xen_is_false(ref) || mus_is_xen(ref), ref, 1, S_make_move_sound, "dlocsig list[6] (global rev env): an env generator");
  6507. if (mus_is_xen(ref))
  6508. {
  6509. globrevenv = Xen_to_mus_any(ref);
  6510. Xen_check_type(mus_is_env(globrevenv), ref, 1, S_make_move_sound, "dlocsig list[6] (global rev env): an env generator");
  6511. }
  6512. ref = Xen_list_ref(dloc_list, 7);
  6513. Xen_check_type(Xen_is_vector(ref) && ((int)Xen_vector_length(ref) >= outchans),
  6514. ref, 1, S_make_move_sound, "dlocsig list[7] (out delays): a vector of delay gens");
  6515. ref = Xen_list_ref(dloc_list, 8);
  6516. Xen_check_type(Xen_is_false(ref) || (Xen_is_vector(ref) && ((int)Xen_vector_length(ref) >= outchans)),
  6517. ref, 1, S_make_move_sound, "dlocsig list[8] (out envs): " PROC_FALSE " or a vector of envs");
  6518. ref = Xen_list_ref(dloc_list, 9);
  6519. Xen_check_type(Xen_is_false(ref) || (Xen_is_vector(ref) && ((int)Xen_vector_length(ref) >= revchans)),
  6520. ref, 1, S_make_move_sound, "dlocsig list[9] (rev envs): " PROC_FALSE " or a vector of envs");
  6521. ref = Xen_list_ref(dloc_list, 10);
  6522. Xen_check_type(Xen_is_vector(ref) && ((int)Xen_vector_length(ref) >= outchans),
  6523. ref, 1, S_make_move_sound, "dlocsig list[10] (out map): vector of ints");
  6524. /* put off allocation until all type error checks are done */
  6525. out_delays = xen_vector_to_mus_any_array(Xen_list_ref(dloc_list, 7));
  6526. out_envs = xen_vector_to_mus_any_array(Xen_list_ref(dloc_list, 8));
  6527. rev_envs = xen_vector_to_mus_any_array(Xen_list_ref(dloc_list, 9));
  6528. out_map = xen_vector_to_int_array(Xen_list_ref(dloc_list, 10));
  6529. ge = mus_make_move_sound(start, end, outchans, revchans,
  6530. dopdly, dopenv, globrevenv,
  6531. out_delays, out_envs, rev_envs, out_map,
  6532. output, revput,
  6533. true, false); /* free outer arrays but not gens */
  6534. if (ge)
  6535. {
  6536. mus_xen *gn;
  6537. if (((Xen_is_bound(ov)) && (!Xen_is_false(ov))) ||
  6538. ((Xen_is_bound(rv)) && (!Xen_is_false(rv))))
  6539. gn = mx_alloc(4);
  6540. else gn = mx_alloc(1);
  6541. gn->vcts[G_LOCSIG_DATA] = dloc_list; /* it is crucial that the list be gc-protected! */
  6542. if (gn->nvcts == 4)
  6543. {
  6544. mus_move_sound_set_detour(ge, clm_move_sound_detour);
  6545. gn->vcts[G_LOCSIG_OUT] = ov;
  6546. gn->vcts[G_LOCSIG_REVOUT] = rv;
  6547. gn->vcts[G_LOCSIG_REVDATA] = Xen_undefined;
  6548. mus_set_environ(ge, (void *)gn);
  6549. }
  6550. gn->gen = ge;
  6551. return(mus_xen_to_object(gn));
  6552. }
  6553. return(Xen_false);
  6554. }
  6555. /* ---------------- src ---------------- */
  6556. static Xen xen_one, xen_minus_one;
  6557. #if HAVE_SCHEME
  6558. static Xen as_needed_arglist;
  6559. static s7_pointer env_symbol, polywave_symbol, triangle_wave_symbol, rand_interp_symbol, oscil_symbol;
  6560. static s7_pointer multiply_symbol, add_symbol, vector_ref_symbol, quote_symbol, cos_symbol, comb_bank_symbol;
  6561. static mus_float_t as_needed_input_float(void *ptr, int direction)
  6562. {
  6563. mus_xen *gn = (mus_xen *)ptr;
  6564. return(s7_real(gn->vcts[MUS_INPUT_DATA]));
  6565. }
  6566. static mus_float_t as_needed_block_input_float(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6567. {
  6568. mus_xen *gn = (mus_xen *)ptr;
  6569. mus_float_t val;
  6570. mus_long_t i, lim4;
  6571. lim4 = end - 4;
  6572. val = (mus_float_t)s7_real(gn->vcts[MUS_INPUT_DATA]); /* set in the chooser below */
  6573. for (i = start; i <= lim4;)
  6574. {
  6575. data[i++] = val;
  6576. data[i++] = val;
  6577. data[i++] = val;
  6578. data[i++] = val;
  6579. }
  6580. for (;i < end; i++)
  6581. data[i] = val;
  6582. return(val);
  6583. }
  6584. static mus_float_t as_needed_input_any(void *ptr, int direction)
  6585. {
  6586. mus_xen *gn = (mus_xen *)ptr;
  6587. s7_set_car(as_needed_arglist, (direction == 1) ? xen_one : xen_minus_one);
  6588. return(s7_number_to_real(s7, s7_apply_function(s7, gn->vcts[MUS_INPUT_FUNCTION], as_needed_arglist)));
  6589. }
  6590. #endif
  6591. static mus_float_t as_needed_input_generator(void *ptr, int direction)
  6592. {
  6593. #if HAVE_EXTENSION_LANGUAGE
  6594. return(mus_apply((mus_any *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]), 0.0, 0.0));
  6595. #else
  6596. return(0.0);
  6597. #endif
  6598. }
  6599. static mus_float_t as_needed_block_input_generator(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6600. {
  6601. #if HAVE_EXTENSION_LANGUAGE
  6602. mus_any *g;
  6603. mus_long_t i;
  6604. g = (mus_any *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]);
  6605. for (i = start; i < end; i++)
  6606. data[i] = mus_apply(g, 0.0, 0.0);
  6607. #endif
  6608. return(0.0);
  6609. }
  6610. static mus_float_t as_needed_input_readin(void *ptr, int direction)
  6611. {
  6612. #if HAVE_EXTENSION_LANGUAGE
  6613. return(mus_readin((mus_any *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA])));
  6614. #else
  6615. return(0.0);
  6616. #endif
  6617. }
  6618. static mus_float_t as_needed_block_input_readin(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6619. {
  6620. #if HAVE_EXTENSION_LANGUAGE
  6621. mus_any *g;
  6622. mus_long_t i;
  6623. g = (mus_any *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]);
  6624. for (i = start; i < end; i++)
  6625. data[i] = mus_readin(g);
  6626. #endif
  6627. return(0.0);
  6628. }
  6629. #if USE_SND && HAVE_SCHEME
  6630. static mus_float_t as_needed_input_sampler(void *ptr, int direction)
  6631. {
  6632. return(read_sample((snd_fd *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA])));
  6633. }
  6634. static mus_float_t as_needed_block_input_sampler(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6635. {
  6636. snd_fd *p;
  6637. mus_long_t i;
  6638. p = (snd_fd *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]);
  6639. for (i = start; i < end; i++)
  6640. data[i] = read_sample(p);
  6641. return(0.0);
  6642. }
  6643. mus_float_t read_sample_with_direction(void *p, int dir);
  6644. static mus_float_t as_needed_input_sampler_with_direction(void *ptr, int direction)
  6645. {
  6646. return(read_sample_with_direction((snd_fd *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]), direction));
  6647. }
  6648. static mus_float_t as_needed_block_input_sampler_with_direction(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6649. {
  6650. snd_fd *p;
  6651. mus_long_t i;
  6652. p = (snd_fd *)(((mus_xen *)ptr)->vcts[MUS_INPUT_DATA]);
  6653. for (i = start; i < end; i++)
  6654. data[i] = read_sample_with_direction(p, direction);
  6655. return(0.0);
  6656. }
  6657. #endif
  6658. static mus_float_t as_needed_input_func(void *ptr, int direction) /* intended for "as-needed" input funcs */
  6659. {
  6660. mus_xen *gn = (mus_xen *)ptr;
  6661. if (gn)
  6662. {
  6663. Xen in_obj;
  6664. in_obj = gn->vcts[MUS_INPUT_FUNCTION];
  6665. if (Xen_is_procedure(in_obj))
  6666. return(Xen_real_to_C_double(Xen_unprotected_call_with_1_arg(gn->vcts[MUS_INPUT_FUNCTION], (direction == 1) ? xen_one : xen_minus_one)));
  6667. }
  6668. return(0.0);
  6669. }
  6670. #if HAVE_SCHEME
  6671. static mus_float_t as_needed_input_rf(void *ptr, int direction)
  6672. {
  6673. mus_xen *gn = (mus_xen *)ptr;
  6674. if (gn)
  6675. {
  6676. s7_rf_t rf;
  6677. s7_pointer *top, *p;
  6678. rf = (s7_rf_t)(gn->vcts[MUS_INPUT_FUNCTION]);
  6679. top = s7_xf_top(s7, (void *)(gn->vcts[MUS_INPUT_DATA]));
  6680. p = top;
  6681. return(rf(s7, &p));
  6682. }
  6683. return(0.0);
  6684. }
  6685. static mus_float_t as_needed_block_input_rf(void *ptr, int direction, mus_float_t *data, mus_long_t start, mus_long_t end)
  6686. {
  6687. mus_xen *gn = (mus_xen *)ptr;
  6688. if (gn)
  6689. {
  6690. mus_long_t i;
  6691. s7_rf_t rf;
  6692. s7_pointer *top, *p;
  6693. rf = (s7_rf_t)(gn->vcts[MUS_INPUT_FUNCTION]);
  6694. top = s7_xf_top(s7, (void *)(gn->vcts[MUS_INPUT_DATA]));
  6695. for (i = start; i < end; i++)
  6696. {
  6697. p = top;
  6698. data[i] = rf(s7, &p);
  6699. }
  6700. }
  6701. return(0.0);
  6702. }
  6703. #endif
  6704. static void set_as_needed_input_choices(mus_any *gen, Xen obj, mus_xen *gn)
  6705. {
  6706. /* fprintf(stderr, "set_as_needed_input for %s: %s\n", mus_name(gen), DISPLAY(obj)); */
  6707. if (mus_is_xen(obj)) /* input function is a generator */
  6708. {
  6709. mus_any *p;
  6710. p = Xen_to_mus_any(obj);
  6711. if (p)
  6712. {
  6713. #if HAVE_EXTENSION_LANGUAGE
  6714. gn->vcts[MUS_INPUT_DATA] = (Xen)p;
  6715. #endif
  6716. if (mus_is_readin(p))
  6717. mus_generator_set_feeders(gen, as_needed_input_readin, as_needed_block_input_readin);
  6718. else mus_generator_set_feeders(gen, as_needed_input_generator, as_needed_block_input_generator);
  6719. return;
  6720. }
  6721. }
  6722. #if HAVE_SCHEME
  6723. if ((Xen_is_procedure(obj)) &&
  6724. (!Xen_is_procedure(gn->vcts[MUS_ANALYZE_FUNCTION]))) /* this assumes scheme-ready input function at least in phase-vocoder case */
  6725. {
  6726. s7_pointer body;
  6727. body = s7_closure_body(s7, obj);
  6728. if (s7_is_pair(body))
  6729. {
  6730. if (s7_is_null(s7, s7_cdr(body)))
  6731. {
  6732. s7_pointer res;
  6733. res = s7_car(body);
  6734. if (s7_is_real(res))
  6735. {
  6736. gn->vcts[MUS_INPUT_DATA] = res;
  6737. mus_generator_set_feeders(gen, as_needed_input_float, as_needed_block_input_float);
  6738. return;
  6739. }
  6740. if (s7_is_pair(res))
  6741. {
  6742. if (s7_is_symbol(s7_car(res)))
  6743. {
  6744. s7_pointer fcar;
  6745. fcar = s7_symbol_value(s7, s7_car(res));
  6746. if (s7_rf_function(s7, fcar))
  6747. {
  6748. s7_rf_t rf;
  6749. s7_pointer old_e, e;
  6750. e = s7_sublet(s7, s7_closure_let(s7, obj), s7_nil(s7));
  6751. old_e = s7_set_curlet(s7, e);
  6752. s7_xf_new(s7, e);
  6753. rf = s7_rf_function(s7, fcar)(s7, res);
  6754. if (rf)
  6755. {
  6756. gn->vcts[MUS_SAVED_FUNCTION] = gn->vcts[MUS_INPUT_FUNCTION]; /* needed for GC protection */
  6757. gn->vcts[MUS_INPUT_DATA] = (s7_pointer)s7_xf_detach(s7);
  6758. gn->vcts[MUS_INPUT_FUNCTION] = (s7_pointer)rf;
  6759. gn->free_data = true;
  6760. mus_generator_set_feeders(gen, as_needed_input_rf, as_needed_block_input_rf);
  6761. s7_set_curlet(s7, old_e);
  6762. return;
  6763. }
  6764. s7_xf_free(s7);
  6765. s7_set_curlet(s7, old_e);
  6766. }
  6767. }
  6768. #if USE_SND
  6769. {
  6770. s7_pointer arg;
  6771. arg = s7_car(s7_closure_args(s7, obj));
  6772. if ((arg == s7_caddr(res)) &&
  6773. (s7_car(res) == s7_make_symbol(s7, "read-sample-with-direction")))
  6774. {
  6775. gn->vcts[MUS_INPUT_DATA] = (Xen)xen_to_sampler(s7_symbol_local_value(s7, s7_cadr(res), s7_closure_let(s7, obj)));
  6776. mus_generator_set_feeders(gen, as_needed_input_sampler_with_direction, as_needed_block_input_sampler_with_direction);
  6777. return;
  6778. }
  6779. }
  6780. #endif
  6781. }
  6782. }
  6783. }
  6784. #if USE_SND
  6785. /* check for a sampler (snd-edits.c) */
  6786. if (is_sampler(obj))
  6787. {
  6788. gn->vcts[MUS_INPUT_DATA] = (Xen)xen_to_sampler(obj);
  6789. mus_generator_set_feeders(gen, as_needed_input_sampler, as_needed_block_input_sampler);
  6790. return;
  6791. }
  6792. mus_generator_set_feeders(gen, as_needed_input_any, NULL);
  6793. return;
  6794. #endif
  6795. }
  6796. #endif
  6797. mus_generator_set_feeders(gen, as_needed_input_func, NULL);
  6798. }
  6799. static Xen g_mus_clear_sincs(void)
  6800. {
  6801. mus_clear_sinc_tables();
  6802. return(Xen_false);
  6803. }
  6804. static Xen g_is_src(Xen obj)
  6805. {
  6806. #define H_is_src "(" S_is_src " gen): " PROC_TRUE " if gen is an " S_src
  6807. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_src(Xen_to_mus_any(obj)))));
  6808. }
  6809. #define SRC_CHANGE_MAX 1000000.0
  6810. static Xen g_src(Xen obj, Xen pm, Xen func)
  6811. {
  6812. #define H_src "(" S_src " gen (pm 0.0) input-function): next sampling rate conversion sample. \
  6813. 'pm' can be used to change the sampling rate on a sample-by-sample basis. 'input-function' \
  6814. is a function of one argument (the current input direction, normally ignored) that is called \
  6815. internally whenever a new sample of input data is needed. If the associated " S_make_src " \
  6816. included an 'input' argument, input-function is ignored."
  6817. mus_float_t pm1 = 0.0;
  6818. mus_xen *gn;
  6819. mus_any *g = NULL;
  6820. Xen_to_C_generator(obj, gn, g, mus_is_src, S_src, "an src generator");
  6821. Xen_real_to_C_double_if_bound(pm, pm1, S_src, 2);
  6822. /* if sr_change (pm1) is ridiculous, complain! */
  6823. if ((pm1 > SRC_CHANGE_MAX) || (pm1 < -SRC_CHANGE_MAX))
  6824. Xen_out_of_range_error(S_src, 2, pm, "src change too large");
  6825. if (!Xen_is_bound(gn->vcts[MUS_INPUT_DATA]))
  6826. {
  6827. if (Xen_is_procedure(func))
  6828. {
  6829. if (Xen_is_aritable(func, 1))
  6830. gn->vcts[MUS_INPUT_FUNCTION] = func;
  6831. else Xen_bad_arity_error(S_src, 3, func, "src input function wants 1 arg");
  6832. }
  6833. }
  6834. return(C_double_to_Xen_real(mus_src(g, pm1, NULL)));
  6835. }
  6836. static void set_gn_gen(void *p, mus_any *g)
  6837. {
  6838. mus_xen *gn = (mus_xen *)p;
  6839. gn->gen = g;
  6840. }
  6841. static Xen g_make_src(Xen arg1, Xen arg2, Xen arg3, Xen arg4, Xen arg5, Xen arg6)
  6842. {
  6843. #define H_make_src "(" S_make_src " input (srate 1.0) (width 10)): \
  6844. return a new sampling-rate conversion generator (using 'warped sinc interpolation'). \
  6845. 'srate' is the ratio between the new rate and the old. 'width' is the sine \
  6846. width (effectively the steepness of the low-pass filter), normally between 10 and 100. \
  6847. 'input' if given is an open file stream."
  6848. Xen in_obj = Xen_undefined;
  6849. mus_xen *gn;
  6850. mus_any *ge = NULL;
  6851. int vals, wid = 0; /* 0 here picks up the current default width in clm.c */
  6852. Xen args[6];
  6853. Xen keys[3];
  6854. int orig_arg[3] = {0, 0, 0};
  6855. mus_float_t srate = 1.0;
  6856. keys[0] = kw_input;
  6857. keys[1] = kw_srate;
  6858. keys[2] = kw_width;
  6859. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6;
  6860. vals = mus_optkey_unscramble(S_make_src, 3, keys, args, orig_arg);
  6861. if (vals > 0)
  6862. {
  6863. in_obj = mus_optkey_to_input_procedure(keys[0], S_make_src, orig_arg[0], Xen_undefined, 1, "src input procedure takes 1 arg");
  6864. srate = Xen_optkey_to_float(kw_srate, keys[1], S_make_src, orig_arg[1], srate);
  6865. /* srate can be negative => read in reverse */
  6866. wid = Xen_optkey_to_int(kw_width, keys[2], S_make_src, orig_arg[2], wid);
  6867. if (wid < 0)
  6868. Xen_out_of_range_error(S_make_src, orig_arg[2], keys[2], "width < 0?");
  6869. if (wid > 2000)
  6870. Xen_out_of_range_error(S_make_src, orig_arg[2], keys[2], "width > 2000?");
  6871. }
  6872. gn = mx_alloc(MUS_MAX_VCTS);
  6873. {int i; for (i = 0; i < MUS_MAX_VCTS; i++) gn->vcts[i] = Xen_undefined;}
  6874. /* mus_make_src assumes it can invoke the input function! */
  6875. gn->vcts[MUS_INPUT_FUNCTION] = in_obj;
  6876. {
  6877. mus_error_handler_t *old_error_handler;
  6878. old_error_handler = mus_error_set_handler(local_mus_error);
  6879. ge = mus_make_src_with_init(NULL, srate, wid, gn, set_gn_gen);
  6880. mus_error_set_handler(old_error_handler);
  6881. }
  6882. if (ge)
  6883. {
  6884. Xen src_obj;
  6885. #if HAVE_SCHEME
  6886. int loc;
  6887. #endif
  6888. gn->gen = ge;
  6889. src_obj = mus_xen_to_object(gn);
  6890. #if HAVE_SCHEME
  6891. loc = s7_gc_protect(s7, src_obj);
  6892. #endif
  6893. /* src_init can call an input function which can trigger the GC, so we need to GC-protect the new object */
  6894. gn->vcts[MUS_SELF_WRAPPER] = src_obj;
  6895. set_as_needed_input_choices(ge, in_obj, gn);
  6896. mus_src_init(ge);
  6897. #if HAVE_SCHEME
  6898. s7_gc_unprotect_at(s7, loc);
  6899. #endif
  6900. return(src_obj);
  6901. }
  6902. free(gn->vcts);
  6903. free(gn);
  6904. return(clm_mus_error(local_error_type, local_error_msg, S_make_src));
  6905. }
  6906. /* ---------------- granulate ---------------- */
  6907. static Xen g_is_granulate(Xen obj)
  6908. {
  6909. #define H_is_granulate "(" S_is_granulate " gen): " PROC_TRUE " if gen is a " S_granulate " generator"
  6910. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_granulate(Xen_to_mus_any(obj)))));
  6911. }
  6912. static int grnedit(void *ptr)
  6913. {
  6914. mus_xen *gn = (mus_xen *)ptr;
  6915. return(Xen_integer_to_C_int(Xen_unprotected_call_with_1_arg(gn->vcts[MUS_EDIT_FUNCTION], gn->vcts[MUS_SELF_WRAPPER])));
  6916. }
  6917. static Xen g_granulate(Xen obj, Xen func, Xen edit_func)
  6918. {
  6919. #define H_granulate "(" S_granulate " gen input-func edit-func): next sample from granular synthesis generator"
  6920. mus_xen *gn;
  6921. mus_any *g = NULL;
  6922. Xen_to_C_generator(obj, gn, g, mus_is_granulate, S_granulate, "a granulate generator");
  6923. if ((Xen_is_bound(func)) &&
  6924. (!Xen_is_bound(gn->vcts[MUS_INPUT_DATA])))
  6925. {
  6926. if (Xen_is_procedure(func))
  6927. {
  6928. if (Xen_is_aritable(func, 1))
  6929. gn->vcts[MUS_INPUT_FUNCTION] = func;
  6930. else Xen_bad_arity_error(S_granulate, 2, func, "granulate input function wants 1 arg");
  6931. }
  6932. if (Xen_is_procedure(edit_func))
  6933. {
  6934. if (Xen_is_aritable(edit_func, 1))
  6935. {
  6936. if (!(Xen_is_bound(gn->vcts[MUS_EDIT_FUNCTION]))) /* default value is Xen_undefined */
  6937. {
  6938. mus_granulate_set_edit_function(gn->gen, grnedit);
  6939. gn->vcts[MUS_EDIT_FUNCTION] = edit_func;
  6940. }
  6941. }
  6942. else Xen_bad_arity_error(S_granulate, 3, edit_func, "granulate edit function wants 1 arg");
  6943. }
  6944. }
  6945. return(C_double_to_Xen_real(mus_granulate(g, NULL)));
  6946. }
  6947. static Xen g_make_granulate(Xen arglist)
  6948. {
  6949. #define H_make_granulate "(" S_make_granulate " input (expansion 1.0) (length .15) (scaler .6) (hop .05) (ramp .4) (jitter 1.0) max-size edit): \
  6950. return a new granular synthesis generator. 'length' is the grain length (seconds), 'expansion' is the ratio in timing \
  6951. between the new and old (expansion > 1.0 slows things down), 'scaler' scales the grains \
  6952. to avoid overflows, 'hop' is the spacing (seconds) between successive grains upon output. \
  6953. 'jitter' controls the randomness in that spacing, 'input' can be a file pointer. 'edit' can \
  6954. be a function of one arg, the current granulate generator. It is called just before \
  6955. a grain is added into the output buffer. The current grain is accessible via " S_mus_data ". \
  6956. The edit function, if any, should return the length in samples of the grain, or 0."
  6957. Xen in_obj = Xen_undefined;
  6958. mus_xen *gn;
  6959. mus_any *ge;
  6960. Xen args[18];
  6961. Xen keys[9];
  6962. int orig_arg[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  6963. int vals, maxsize = 0;
  6964. mus_float_t expansion = 1.0, segment_length = .15, segment_scaler = .6, ramp_time = .4, output_hop = .05;
  6965. mus_float_t jitter = 1.0;
  6966. Xen edit_obj = Xen_undefined, grn_obj;
  6967. keys[0] = kw_input;
  6968. keys[1] = kw_expansion;
  6969. keys[2] = kw_length;
  6970. keys[3] = kw_scaler;
  6971. keys[4] = kw_hop;
  6972. keys[5] = kw_ramp;
  6973. keys[6] = kw_jitter;
  6974. keys[7] = kw_max_size;
  6975. keys[8] = kw_edit;
  6976. {
  6977. int i, arglist_len;
  6978. Xen p;
  6979. arglist_len = Xen_list_length(arglist);
  6980. if (arglist_len > 18) clm_error(S_make_granulate, "too many arguments!", arglist);
  6981. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  6982. for (i = arglist_len; i < 18; i++) args[i] = Xen_undefined;
  6983. }
  6984. vals = mus_optkey_unscramble(S_make_granulate, 9, keys, args, orig_arg);
  6985. if (vals > 0)
  6986. {
  6987. in_obj = mus_optkey_to_input_procedure(keys[0], S_make_granulate, orig_arg[0], Xen_undefined, 1, "granulate input procedure takes 1 arg");
  6988. expansion = Xen_optkey_to_float(kw_expansion, keys[1], S_make_granulate, orig_arg[1], expansion);
  6989. if (expansion <= 0.0)
  6990. Xen_out_of_range_error(S_make_granulate, orig_arg[1], keys[1], "expansion <= 0.0?");
  6991. segment_length = Xen_optkey_to_float(kw_length, keys[2], S_make_granulate, orig_arg[2], segment_length);
  6992. if (segment_length <= 0.0)
  6993. Xen_out_of_range_error(S_make_granulate, orig_arg[2], keys[2], "segment-length <= 0.0?");
  6994. segment_scaler = Xen_optkey_to_float(kw_scaler, keys[3], S_make_granulate, orig_arg[3], segment_scaler);
  6995. if (segment_scaler == 0.0)
  6996. Xen_out_of_range_error(S_make_granulate, orig_arg[3], keys[3], "segment-scaler should be greater than 0.0?");
  6997. output_hop = Xen_optkey_to_float(kw_hop, keys[4], S_make_granulate, orig_arg[4], output_hop);
  6998. if (output_hop <= 0.0)
  6999. Xen_out_of_range_error(S_make_granulate, orig_arg[4], keys[4], "hop <= 0?");
  7000. if (output_hop > 3600.0)
  7001. Xen_out_of_range_error(S_make_granulate, orig_arg[4], keys[4], "hop > 3600?");
  7002. if ((segment_length + output_hop) > 60.0) /* multiplied by srate in mus_make_granulate in array allocation */
  7003. Xen_out_of_range_error(S_make_granulate, orig_arg[2], Xen_list_2(keys[2], keys[4]), "segment_length + output_hop too large!");
  7004. ramp_time = Xen_optkey_to_float(kw_ramp, keys[5], S_make_granulate, orig_arg[5], ramp_time);
  7005. if ((ramp_time < 0.0) || (ramp_time > 0.5))
  7006. Xen_out_of_range_error(S_make_granulate, orig_arg[5], keys[5], "ramp must be between 0.0 and 0.5");
  7007. jitter = Xen_optkey_to_float(kw_jitter, keys[6], S_make_granulate, orig_arg[6], jitter);
  7008. Xen_check_type((jitter >= 0.0) && (jitter < 100.0), keys[6], orig_arg[6], S_make_granulate, "0.0 .. 100.0");
  7009. maxsize = Xen_optkey_to_int(kw_max_size, keys[7], S_make_granulate, orig_arg[7], maxsize);
  7010. if ((maxsize > mus_max_malloc()) ||
  7011. (maxsize < 0) ||
  7012. ((maxsize == 0) && (!Xen_is_keyword(keys[7]))))
  7013. Xen_out_of_range_error(S_make_granulate, orig_arg[7], keys[7], "max-size invalid");
  7014. edit_obj = mus_optkey_to_procedure(keys[8], S_make_granulate, orig_arg[8], Xen_undefined, 1, "granulate edit procedure takes 1 arg");
  7015. }
  7016. gn = mx_alloc(MUS_MAX_VCTS);
  7017. {int i; for (i = 0; i < MUS_MAX_VCTS; i++) gn->vcts[i] = Xen_undefined;}
  7018. {
  7019. mus_error_handler_t *old_error_handler;
  7020. old_error_handler = mus_error_set_handler(local_mus_error);
  7021. ge = mus_make_granulate(NULL,
  7022. expansion, segment_length, segment_scaler, output_hop, ramp_time, jitter, maxsize,
  7023. (!Xen_is_bound(edit_obj) ? NULL : grnedit),
  7024. (void *)gn);
  7025. mus_error_set_handler(old_error_handler);
  7026. }
  7027. if (ge)
  7028. {
  7029. gn->vcts[MUS_DATA_WRAPPER] = xen_make_vct_wrapper(mus_granulate_grain_max_length(ge), mus_data(ge));
  7030. gn->vcts[MUS_INPUT_FUNCTION] = in_obj;
  7031. gn->vcts[MUS_EDIT_FUNCTION] = edit_obj;
  7032. gn->gen = ge;
  7033. grn_obj = mus_xen_to_object(gn);
  7034. gn->vcts[MUS_SELF_WRAPPER] = grn_obj;
  7035. set_as_needed_input_choices(ge, in_obj, gn);
  7036. return(grn_obj);
  7037. }
  7038. free(gn->vcts);
  7039. free(gn);
  7040. return(clm_mus_error(local_error_type, local_error_msg, S_make_granulate));
  7041. }
  7042. /* ---------------- convolve ---------------- */
  7043. static Xen g_is_convolve(Xen obj)
  7044. {
  7045. #define H_is_convolve "(" S_is_convolve " gen): " PROC_TRUE " if gen is a " S_convolve " generator"
  7046. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_convolve(Xen_to_mus_any(obj)))));
  7047. }
  7048. static Xen g_convolve(Xen obj, Xen func)
  7049. {
  7050. #define H_convolve_gen "(" S_convolve " gen input-func): next sample from convolution generator"
  7051. mus_xen *gn;
  7052. mus_any *g = NULL;
  7053. Xen_to_C_generator(obj, gn, g, mus_is_convolve, S_convolve, "a convolve generator");
  7054. if (!Xen_is_bound(gn->vcts[MUS_INPUT_DATA]))
  7055. {
  7056. if (Xen_is_procedure(func))
  7057. {
  7058. if (Xen_is_aritable(func, 1))
  7059. gn->vcts[MUS_INPUT_FUNCTION] = func;
  7060. else Xen_bad_arity_error(S_convolve, 2, func, "convolve input function wants 1 arg");
  7061. }
  7062. }
  7063. return(C_double_to_Xen_real(mus_convolve(g, NULL)));
  7064. }
  7065. /* filter-size? */
  7066. static Xen g_make_convolve(Xen arglist)
  7067. {
  7068. #define H_make_convolve "(" S_make_convolve " input filter fft-size): \
  7069. return a new convolution generator which convolves its input with the impulse response 'filter'."
  7070. mus_xen *gn;
  7071. mus_any *ge;
  7072. Xen args[6];
  7073. Xen keys[3];
  7074. int orig_arg[3] = {0, 0, 0};
  7075. int vals;
  7076. vct *filter = NULL;
  7077. Xen filt = Xen_undefined, in_obj = Xen_undefined;
  7078. mus_long_t fftlen, fft_size = 0;
  7079. keys[0] = kw_input;
  7080. keys[1] = kw_filter;
  7081. keys[2] = kw_fft_size;
  7082. {
  7083. int i, arglist_len;
  7084. Xen p;
  7085. arglist_len = Xen_list_length(arglist);
  7086. if (arglist_len > 6) clm_error(S_make_convolve, "too many arguments!", arglist);
  7087. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  7088. for (i = arglist_len; i < 6; i++) args[i] = Xen_undefined;
  7089. }
  7090. vals = mus_optkey_unscramble(S_make_convolve, 3, keys, args, orig_arg);
  7091. if (vals > 0)
  7092. {
  7093. in_obj = mus_optkey_to_input_procedure(keys[0], S_make_convolve, orig_arg[0], Xen_undefined, 1, "convolve input procedure takes 1 arg");
  7094. filter = mus_optkey_to_vct(keys[1], S_make_convolve, orig_arg[1], NULL);
  7095. if (filter) filt = keys[1];
  7096. fft_size = Xen_optkey_to_mus_long_t(kw_fft_size, keys[2], S_make_convolve, orig_arg[2], fft_size);
  7097. if ((fft_size < 0) ||
  7098. ((fft_size == 0) && (!Xen_is_keyword(keys[2]))) ||
  7099. (fft_size > mus_max_malloc()))
  7100. Xen_out_of_range_error(S_make_convolve, orig_arg[2], keys[2], "fft-size invalid (see mus-max-malloc))");
  7101. }
  7102. if (filter == NULL)
  7103. Xen_error(NO_DATA,
  7104. Xen_list_1(C_string_to_Xen_string(S_make_convolve ": no impulse (filter)?")));
  7105. if (is_power_of_2(mus_vct_length(filter)))
  7106. fftlen = mus_vct_length(filter) * 2;
  7107. else fftlen = (mus_long_t)pow(2.0, 1 + (int)(log((mus_float_t)(mus_vct_length(filter) + 1)) / log(2.0)));
  7108. if (fft_size < fftlen) fft_size = fftlen;
  7109. gn = mx_alloc(MUS_MAX_VCTS);
  7110. {int i; for (i = 0; i < MUS_MAX_VCTS; i++) gn->vcts[i] = Xen_undefined;}
  7111. {
  7112. mus_error_handler_t *old_error_handler;
  7113. old_error_handler = mus_error_set_handler(local_mus_error);
  7114. ge = mus_make_convolve(NULL, mus_vct_data(filter), fft_size, mus_vct_length(filter), gn);
  7115. mus_error_set_handler(old_error_handler);
  7116. }
  7117. if (ge)
  7118. {
  7119. Xen c_obj;
  7120. gn->vcts[MUS_INPUT_FUNCTION] = in_obj;
  7121. gn->vcts[MUS_ANALYZE_FUNCTION] = filt; /* why is this here? GC protection? (might be a locally-allocated vct as from file->vct) */
  7122. gn->gen = ge;
  7123. c_obj = mus_xen_to_object(gn);
  7124. gn->vcts[MUS_SELF_WRAPPER] = c_obj;
  7125. set_as_needed_input_choices(ge, in_obj, gn);
  7126. return(c_obj);
  7127. }
  7128. free(gn->vcts);
  7129. free(gn);
  7130. return(clm_mus_error(local_error_type, local_error_msg, S_make_convolve));
  7131. }
  7132. static Xen g_convolve_files(Xen file1, Xen file2, Xen maxamp, Xen outfile)
  7133. {
  7134. #define H_convolve_files "(" S_convolve_files " file1 file2 maxamp output-file): convolve \
  7135. file1 and file2 writing outfile after scaling the convolution result to maxamp."
  7136. const char *f1, *f2, *f3;
  7137. mus_float_t maxval = 1.0;
  7138. Xen_check_type(Xen_is_string(file1), file1, 1, S_convolve_files, "a string");
  7139. Xen_check_type(Xen_is_string(file2), file2, 2, S_convolve_files, "a string");
  7140. Xen_check_type(Xen_is_number_or_unbound(maxamp), maxamp, 3, S_convolve_files, "a number");
  7141. Xen_check_type((!Xen_is_bound(outfile)) || (Xen_is_string(outfile)), outfile, 4, S_convolve_files, "a string");
  7142. f1 = Xen_string_to_C_string(file1);
  7143. f2 = Xen_string_to_C_string(file2);
  7144. if (Xen_is_string(outfile))
  7145. f3 = Xen_string_to_C_string(outfile);
  7146. else f3 = "tmp.snd";
  7147. if (Xen_is_number(maxamp))
  7148. maxval = Xen_real_to_C_double(maxamp);
  7149. mus_convolve_files(f1, f2, maxval, f3);
  7150. return(C_string_to_Xen_string(f3));
  7151. }
  7152. /* ---------------- phase-vocoder ---------------- */
  7153. /* pvedit pvanalyze pvsynthesize:
  7154. * these three functions provide a path for the call (clm.c) (*(pv->edit))(pv->closure)
  7155. * which is calling a user-supplied edit function within the particular phase-vocoder
  7156. * generator's context. "closure" is an uninterpreted void pointer passed in by the
  7157. * user, and passed here as the edit function argument. In this file, pv->edit is
  7158. * &pvedit, and (void *)ptr is closure; in make_phase_vocoder we set closure to be
  7159. * the mus_xen object that shadows the phase-vocoder generator, with two special
  7160. * pointers in the vcts field: vcts[MUS_EDIT_FUNCTION] is the (Scheme-side) function
  7161. * passed by the user, and vcts[MUS_SELF_WRAPPER] is a pointer to the (Scheme-relevant)
  7162. * object that packages the mus_xen pointer for Scheme. This way, the user's
  7163. * (make-phase-vocoder ... (lambda (v) (mus-length v)) ...)
  7164. * treats v as the current pv gen, vcts[MUS_SELF_WRAPPER] = v, vcts[MUS_EDIT_FUNCTION] =
  7165. * the lambda form, mus_xen obj->gen is the C-side pv struct pointer. See above
  7166. * under as_needed_input_func for more verbiage. (All this complication arises because clm.c
  7167. * is pure C -- no notion that Scheme might be the caller, and the user's pv.scm
  7168. * or whatever is pure Scheme -- no notion that C is actually doing the work,
  7169. * and we have to tie everything together here including the Scheme-C-Scheme-C
  7170. * call chains).
  7171. */
  7172. static int pvedit(void *ptr)
  7173. {
  7174. mus_xen *gn = (mus_xen *)ptr;
  7175. return(Xen_boolean_to_C_bool(Xen_unprotected_call_with_1_arg(gn->vcts[MUS_EDIT_FUNCTION], gn->vcts[MUS_SELF_WRAPPER])));
  7176. }
  7177. static mus_float_t pvsynthesize(void *ptr)
  7178. {
  7179. mus_xen *gn = (mus_xen *)ptr;
  7180. return(Xen_real_to_C_double(Xen_unprotected_call_with_1_arg(gn->vcts[MUS_SYNTHESIZE_FUNCTION], gn->vcts[MUS_SELF_WRAPPER])));
  7181. }
  7182. static bool pvanalyze(void *ptr, mus_float_t (*input)(void *arg1, int direction))
  7183. {
  7184. mus_xen *gn = (mus_xen *)ptr;
  7185. /* we can only get input func if it's already set up by the outer gen call, so (?) we can use that function here.
  7186. * but the gc might be called during this call, and scan the args, so the input function should be
  7187. * in the arg list only if its a legit pointer?
  7188. */
  7189. return(Xen_boolean_to_C_bool(Xen_unprotected_call_with_2_args(gn->vcts[MUS_ANALYZE_FUNCTION],
  7190. gn->vcts[MUS_SELF_WRAPPER],
  7191. gn->vcts[MUS_INPUT_FUNCTION])));
  7192. }
  7193. static Xen g_is_phase_vocoder(Xen obj)
  7194. {
  7195. #define H_is_phase_vocoder "(" S_is_phase_vocoder " gen): " PROC_TRUE " if gen is an " S_phase_vocoder
  7196. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_phase_vocoder(Xen_to_mus_any(obj)))));
  7197. }
  7198. static Xen g_phase_vocoder(Xen obj, Xen func, Xen analyze_func, Xen edit_func, Xen synthesize_func)
  7199. {
  7200. #define H_phase_vocoder "(" S_phase_vocoder " gen input-function analyze-func edit-func synthesize-func): next phase vocoder value"
  7201. mus_xen *gn;
  7202. mus_any *g = NULL;
  7203. Xen_to_C_generator(obj, gn, g, mus_is_phase_vocoder, S_phase_vocoder, "a phase-vocoder generator");
  7204. if (Xen_is_bound(func))
  7205. {
  7206. bool (*analyze)(void *arg, mus_float_t (*input)(void *arg1, int direction)) = NULL;
  7207. int (*edit)(void *arg) = NULL;
  7208. mus_float_t (*synthesize)(void *arg) = NULL;
  7209. if ((Xen_is_procedure(func)) &&
  7210. (!Xen_is_bound(gn->vcts[MUS_INPUT_DATA])))
  7211. {
  7212. if (Xen_is_aritable(func, 1))
  7213. gn->vcts[MUS_INPUT_FUNCTION] = func; /* as_needed_input_func set at make time will pick this up */
  7214. else Xen_bad_arity_error(S_phase_vocoder, 2, func, S_phase_vocoder " input function wants 1 arg");
  7215. }
  7216. if (Xen_is_procedure(analyze_func))
  7217. {
  7218. if (Xen_is_aritable(analyze_func, 2))
  7219. {
  7220. gn->vcts[MUS_ANALYZE_FUNCTION] = analyze_func;
  7221. analyze = pvanalyze;
  7222. }
  7223. else Xen_bad_arity_error(S_phase_vocoder, 3, analyze_func, S_phase_vocoder " analyze function wants 2 args");
  7224. }
  7225. if (Xen_is_procedure(edit_func))
  7226. {
  7227. if (Xen_is_aritable(edit_func, 1))
  7228. {
  7229. gn->vcts[MUS_EDIT_FUNCTION] = edit_func;
  7230. edit = pvedit;
  7231. }
  7232. else Xen_bad_arity_error(S_phase_vocoder, 4, edit_func, S_phase_vocoder " edit function wants 1 arg");
  7233. }
  7234. if (Xen_is_procedure(synthesize_func))
  7235. {
  7236. if (Xen_is_aritable(synthesize_func, 1))
  7237. {
  7238. gn->vcts[MUS_SYNTHESIZE_FUNCTION] = synthesize_func;
  7239. synthesize = pvsynthesize;
  7240. }
  7241. else Xen_bad_arity_error(S_phase_vocoder, 5, synthesize_func, S_phase_vocoder " synthesize function wants 1 arg");
  7242. }
  7243. return(C_double_to_Xen_real(mus_phase_vocoder_with_editors(g, NULL, analyze, edit, synthesize)));
  7244. }
  7245. return(C_double_to_Xen_real(mus_phase_vocoder(g, NULL)));
  7246. }
  7247. static Xen g_make_phase_vocoder(Xen arglist)
  7248. {
  7249. #if HAVE_SCHEME
  7250. #define pv_example "(" S_make_phase_vocoder " #f 512 4 256 1.0 #f #f #f)"
  7251. #define pv_edit_example "(" S_make_phase_vocoder " #f 512 4 256 1.0\n\
  7252. (lambda (v infunc) (snd-print \"analyzing\") #t)\n\
  7253. (lambda (v) (snd-print \"editing\") #t)\n\
  7254. (lambda (v) (snd-print \"resynthesizing\") 0.0))"
  7255. #endif
  7256. #if HAVE_RUBY
  7257. #define pv_example "make_phase_vocoder(false, 512, 4, 256, 1.0, false, false, false)"
  7258. #define pv_edit_example "make_phase_vocoder(false, 512, 4, 256, 1.0,\n\
  7259. lambda do | v, infunc | snd_print(\"analyzing\"); true end,\n\
  7260. lambda do | v | snd_print(\"editing\"); true end,\n\
  7261. lambda do | v | snd_print(\"resynthesizing\"); 0.0 end)"
  7262. #endif
  7263. #if HAVE_FORTH
  7264. #define pv_example "#f 512 4 256 1.0 #f #f #f " S_make_phase_vocoder
  7265. #define pv_edit_example "#f 512 4 256 1.0\n\
  7266. lambda: <{ v infunc -- f }> \"analyzing\" snd-print drop #t ;\n\
  7267. lambda: <{ v -- n }> \"editing\" snd-print drop #t ;\n\
  7268. lambda: <{ v -- r }> \"resynthesizing\" snd-print drop 0.0 ; " S_make_phase_vocoder
  7269. #endif
  7270. #define H_make_phase_vocoder "(" S_make_phase_vocoder " input fft-size overlap interp pitch analyze edit synthesize): \
  7271. return a new phase-vocoder generator; input is the input function (it can be set at run-time), analyze, edit, \
  7272. and synthesize are either " PROC_FALSE " or functions that replace the default innards of the generator, fft-size, overlap \
  7273. and interp set the fftsize, the amount of overlap between ffts, and the time between new analysis calls. \
  7274. 'analyze', if given, takes 2 args, the generator and the input function; if it returns " PROC_TRUE ", the default analysis \
  7275. code is also called. 'edit', if given, takes 1 arg, the generator; if it returns " PROC_TRUE ", the default edit code \
  7276. is run. 'synthesize' is a function of 1 arg, the generator; it is called to get the current vocoder \
  7277. output. \n\n " pv_example "\n\n " pv_edit_example
  7278. Xen in_obj = Xen_undefined, edit_obj = Xen_undefined, synthesize_obj = Xen_undefined, analyze_obj = Xen_undefined;
  7279. mus_xen *gn;
  7280. mus_any *ge;
  7281. Xen args[16];
  7282. Xen keys[8];
  7283. Xen pv_obj;
  7284. int orig_arg[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  7285. int vals;
  7286. int fft_size = 512, overlap = 4, interp = 128;
  7287. mus_float_t pitch = 1.0;
  7288. keys[0] = kw_input;
  7289. keys[1] = kw_fft_size;
  7290. keys[2] = kw_overlap;
  7291. keys[3] = kw_interp;
  7292. keys[4] = kw_pitch;
  7293. keys[5] = kw_analyze;
  7294. keys[6] = kw_edit;
  7295. keys[7] = kw_synthesize;
  7296. {
  7297. int i, arglist_len;
  7298. Xen p;
  7299. arglist_len = Xen_list_length(arglist);
  7300. if (arglist_len > 16) clm_error(S_make_phase_vocoder, "too many arguments!", arglist);
  7301. for (i = 0, p = arglist; i < arglist_len; i++, p = Xen_cdr(p)) args[i] = Xen_car(p);
  7302. for (i = arglist_len; i < 16; i++) args[i] = Xen_undefined;
  7303. }
  7304. vals = mus_optkey_unscramble(S_make_phase_vocoder, 8, keys, args, orig_arg);
  7305. if (vals > 0)
  7306. {
  7307. in_obj = mus_optkey_to_input_procedure(keys[0], S_make_phase_vocoder, orig_arg[0], Xen_undefined, 1, S_phase_vocoder " input procedure takes 1 arg");
  7308. fft_size = Xen_optkey_to_int(kw_fft_size, keys[1], S_make_phase_vocoder, orig_arg[1], fft_size);
  7309. if (fft_size <= 1)
  7310. Xen_out_of_range_error(S_make_phase_vocoder, orig_arg[1], keys[1], "fft size <= 1?");
  7311. if (fft_size > mus_max_malloc())
  7312. Xen_out_of_range_error(S_make_phase_vocoder, orig_arg[1], keys[1], "fft size too large (see mus-max-malloc)");
  7313. if (!is_power_of_2(fft_size))
  7314. Xen_out_of_range_error(S_make_phase_vocoder, orig_arg[1], keys[1], "fft size must be power of 2");
  7315. overlap = Xen_optkey_to_int(kw_overlap, keys[2], S_make_phase_vocoder, orig_arg[2], overlap);
  7316. if (overlap <= 0)
  7317. Xen_out_of_range_error(S_make_phase_vocoder, orig_arg[2], keys[2], "overlap <= 0?");
  7318. interp = Xen_optkey_to_int(kw_interp, keys[3], S_make_phase_vocoder, orig_arg[3], interp);
  7319. if (interp <= 0)
  7320. Xen_out_of_range_error(S_make_phase_vocoder, orig_arg[3], keys[3], "interp <= 0?");
  7321. pitch = Xen_optkey_to_float(kw_pitch, keys[4], S_make_phase_vocoder, orig_arg[4], pitch);
  7322. analyze_obj = mus_optkey_to_procedure(keys[5], S_make_phase_vocoder, orig_arg[5], Xen_undefined, 2, S_phase_vocoder " analyze procedure takes 2 args");
  7323. edit_obj = mus_optkey_to_procedure(keys[6], S_make_phase_vocoder, orig_arg[6], Xen_undefined, 1, S_phase_vocoder " edit procedure takes 1 arg");
  7324. synthesize_obj = mus_optkey_to_procedure(keys[7], S_make_phase_vocoder, orig_arg[7], Xen_undefined, 1, S_phase_vocoder " synthesize procedure takes 1 arg");
  7325. }
  7326. gn = mx_alloc(MUS_MAX_VCTS);
  7327. {int i; for (i = 0; i < MUS_MAX_VCTS; i++) gn->vcts[i] = Xen_undefined;}
  7328. {
  7329. mus_error_handler_t *old_error_handler;
  7330. old_error_handler = mus_error_set_handler(local_mus_error);
  7331. ge = mus_make_phase_vocoder(NULL,
  7332. fft_size, overlap, interp, pitch,
  7333. (!Xen_is_bound(analyze_obj) ? NULL : pvanalyze),
  7334. (!Xen_is_bound(edit_obj) ? NULL : pvedit),
  7335. (!Xen_is_bound(synthesize_obj) ? NULL : pvsynthesize),
  7336. (void *)gn);
  7337. mus_error_set_handler(old_error_handler);
  7338. }
  7339. if (ge)
  7340. {
  7341. gn->vcts[MUS_INPUT_FUNCTION] = in_obj;
  7342. gn->vcts[MUS_EDIT_FUNCTION] = edit_obj;
  7343. gn->vcts[MUS_ANALYZE_FUNCTION] = analyze_obj;
  7344. gn->vcts[MUS_SYNTHESIZE_FUNCTION] = synthesize_obj;
  7345. gn->gen = ge;
  7346. pv_obj = mus_xen_to_object(gn);
  7347. /* need scheme-relative backpointer for possible function calls */
  7348. gn->vcts[MUS_SELF_WRAPPER] = pv_obj;
  7349. set_as_needed_input_choices(ge, in_obj, gn);
  7350. return(pv_obj);
  7351. }
  7352. free(gn->vcts);
  7353. free(gn);
  7354. return(clm_mus_error(local_error_type, local_error_msg, S_make_phase_vocoder));
  7355. }
  7356. static Xen g_phase_vocoder_amps(Xen pv)
  7357. {
  7358. #define H_phase_vocoder_amps "(" S_phase_vocoder_amps " gen): " S_vct " containing the current output sinusoid amplitudes"
  7359. mus_float_t *amps;
  7360. int len;
  7361. mus_xen *gn;
  7362. Xen_check_type((mus_is_xen(pv)) && (mus_is_phase_vocoder(Xen_to_mus_any(pv))), pv, 1, S_phase_vocoder_amps, "a " S_phase_vocoder " generator");
  7363. gn = Xen_to_mus_xen(pv);
  7364. amps = mus_phase_vocoder_amps(gn->gen);
  7365. len = (int)mus_length(gn->gen);
  7366. return(xen_make_vct_wrapper(len / 2, amps));
  7367. }
  7368. static Xen g_phase_vocoder_freqs(Xen pv)
  7369. {
  7370. #define H_phase_vocoder_freqs "(" S_phase_vocoder_freqs " gen): " S_vct " containing the current output sinusoid frequencies"
  7371. mus_float_t *amps;
  7372. int len;
  7373. mus_xen *gn;
  7374. Xen_check_type((mus_is_xen(pv)) && (mus_is_phase_vocoder(Xen_to_mus_any(pv))), pv, 1, S_phase_vocoder_freqs, "a " S_phase_vocoder " generator");
  7375. gn = Xen_to_mus_xen(pv);
  7376. amps = mus_phase_vocoder_freqs(gn->gen);
  7377. len = (int)mus_length(gn->gen);
  7378. return(xen_make_vct_wrapper(len, amps));
  7379. }
  7380. static Xen g_phase_vocoder_phases(Xen pv)
  7381. {
  7382. #define H_phase_vocoder_phases "(" S_phase_vocoder_phases " gen): " S_vct " containing the current output sinusoid phases"
  7383. mus_float_t *amps;
  7384. int len;
  7385. mus_xen *gn;
  7386. Xen_check_type((mus_is_xen(pv)) && (mus_is_phase_vocoder(Xen_to_mus_any(pv))), pv, 1, S_phase_vocoder_phases, "a " S_phase_vocoder " generator");
  7387. gn = Xen_to_mus_xen(pv);
  7388. amps = mus_phase_vocoder_phases(gn->gen);
  7389. len = (int)mus_length(gn->gen);
  7390. return(xen_make_vct_wrapper(len / 2, amps));
  7391. }
  7392. static Xen g_phase_vocoder_amp_increments(Xen pv)
  7393. {
  7394. #define H_phase_vocoder_amp_increments "(" S_phase_vocoder_amp_increments " gen): " S_vct " containing the current output sinusoid amplitude increments per sample"
  7395. mus_float_t *amps;
  7396. int len;
  7397. mus_xen *gn;
  7398. Xen_check_type((mus_is_xen(pv)) && (mus_is_phase_vocoder(Xen_to_mus_any(pv))), pv, 1, S_phase_vocoder_amp_increments, "a " S_phase_vocoder " generator");
  7399. gn = Xen_to_mus_xen(pv);
  7400. amps = mus_phase_vocoder_amp_increments(gn->gen);
  7401. len = (int)mus_length(gn->gen);
  7402. return(xen_make_vct_wrapper(len, amps));
  7403. }
  7404. static Xen g_phase_vocoder_phase_increments(Xen pv)
  7405. {
  7406. #define H_phase_vocoder_phase_increments "(" S_phase_vocoder_phase_increments " gen): " S_vct " containing the current output sinusoid phase increments"
  7407. mus_float_t *amps;
  7408. int len;
  7409. mus_xen *gn;
  7410. Xen_check_type((mus_is_xen(pv)) && (mus_is_phase_vocoder(Xen_to_mus_any(pv))), pv, 1, S_phase_vocoder_phase_increments, "a " S_phase_vocoder " generator");
  7411. gn = Xen_to_mus_xen(pv);
  7412. amps = mus_phase_vocoder_phase_increments(gn->gen);
  7413. len = (int)mus_length(gn->gen);
  7414. return(xen_make_vct_wrapper(len / 2, amps));
  7415. }
  7416. /* -------- ssb-am -------- */
  7417. static Xen g_is_ssb_am(Xen obj)
  7418. {
  7419. #define H_is_ssb_am "(" S_is_ssb_am " gen): " PROC_TRUE " if gen is a " S_ssb_am
  7420. return(C_bool_to_Xen_boolean((mus_is_xen(obj)) && (mus_is_ssb_am(Xen_to_mus_any(obj)))));
  7421. }
  7422. static Xen g_make_ssb_am(Xen arg1, Xen arg2, Xen arg3, Xen arg4)
  7423. {
  7424. #define H_make_ssb_am "(" S_make_ssb_am " (frequency *clm-default-frequency*) (order 40)): \
  7425. return a new " S_ssb_am " generator."
  7426. #define MUS_MAX_SSB_ORDER 65536
  7427. mus_any *ge;
  7428. Xen args[4];
  7429. Xen keys[2];
  7430. int orig_arg[2] = {0, 0};
  7431. int vals;
  7432. int order = 40;
  7433. mus_float_t freq;
  7434. freq = clm_default_frequency;
  7435. keys[0] = kw_frequency;
  7436. keys[1] = kw_order;
  7437. args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4;
  7438. vals = mus_optkey_unscramble(S_make_ssb_am, 2, keys, args, orig_arg);
  7439. if (vals > 0)
  7440. {
  7441. freq = Xen_optkey_to_float(kw_frequency, keys[0], S_make_ssb_am, orig_arg[0], freq);
  7442. if (freq > (0.5 * mus_srate()))
  7443. Xen_out_of_range_error(S_make_ssb_am, orig_arg[0], keys[0], "freq > srate/2?");
  7444. order = Xen_optkey_to_int(kw_order, keys[1], S_make_ssb_am, orig_arg[1], order);
  7445. if (order <= 0)
  7446. Xen_out_of_range_error(S_make_ssb_am, orig_arg[1], keys[1], "order <= 0?");
  7447. if (order > MUS_MAX_SSB_ORDER)
  7448. Xen_out_of_range_error(S_make_ssb_am, orig_arg[1], keys[1], "order too large?");
  7449. }
  7450. ge = mus_make_ssb_am(freq, order);
  7451. if (ge) return(mus_xen_to_object(mus_any_to_mus_xen(ge)));
  7452. return(Xen_false);
  7453. }
  7454. static Xen g_ssb_am(Xen obj, Xen insig, Xen fm)
  7455. {
  7456. #define H_ssb_am "(" S_ssb_am " gen (insig 0.0) (fm 0.0)): get the next sample from " S_ssb_am " generator"
  7457. mus_float_t insig1 = 0.0;
  7458. mus_any *g = NULL;
  7459. mus_xen *gn;
  7460. Xen_to_C_generator(obj, gn, g, mus_is_ssb_am, S_ssb_am, "an ssb-am generator");
  7461. Xen_real_to_C_double_if_bound(insig, insig1, S_ssb_am, 2);
  7462. if (Xen_is_bound(fm))
  7463. {
  7464. Xen_check_type(Xen_is_number(fm), fm, 3, S_ssb_am, "a number");
  7465. return(C_double_to_Xen_real(mus_ssb_am(g, insig1, Xen_real_to_C_double(fm))));
  7466. }
  7467. return(C_double_to_Xen_real(mus_ssb_am_unmodulated(g, insig1)));
  7468. }
  7469. #define S_mus_frandom "mus-frandom"
  7470. #define S_mus_irandom "mus-irandom"
  7471. static Xen g_mus_frandom(Xen val)
  7472. {
  7473. return(C_double_to_Xen_real(mus_frandom(Xen_real_to_C_double_with_caller(val, S_mus_frandom))));
  7474. }
  7475. static Xen g_mus_irandom(Xen val)
  7476. {
  7477. mus_long_t ind;
  7478. Xen_to_C_integer_or_error(val, ind, S_mus_irandom, 1);
  7479. return(C_int_to_Xen_integer(mus_irandom(ind)));
  7480. }
  7481. static Xen mus_clm_output(void);
  7482. static Xen mus_clm_reverb(void);
  7483. /* Xen out, Xen in, Xen ost, Xen olen, Xen ist, Xen mx, Xen envs */
  7484. static Xen g_mus_file_mix(Xen args)
  7485. {
  7486. #define H_mus_file_mix "(" S_mus_file_mix " outfile infile (outloc 0) (framples) (inloc 0) matrix envs): \
  7487. mix infile into outfile starting at outloc in outfile and inloc in infile \
  7488. mixing 'framples' framples into 'outfile'. framples defaults to the length of infile. If matrix, \
  7489. use it to scale the various channels; if envs (an array of envelope generators), use \
  7490. it in conjunction with matrix to scale/envelope all the various ins and outs. \
  7491. 'outfile' can also be a " S_frample_to_file " generator, and 'infile' can be a " S_file_to_frample " generator."
  7492. Xen arg, out, in;
  7493. mus_any *outf = NULL, *inf = NULL;
  7494. mus_float_t *matrix = NULL;
  7495. mus_any ***envs1 = NULL;
  7496. int i;
  7497. mus_long_t ostart = 0, istart = 0, osamps = 0;
  7498. int in_chans = 0, out_chans = 0, mx_chans = 0, in_size = 0; /* mus_mix in clm.c assumes the envs array is large enough */
  7499. const char *outfile = NULL, *infile = NULL;
  7500. /* -------- setup output gen -------- */
  7501. arg = args;
  7502. out = Xen_car(arg);
  7503. Xen_check_type(Xen_is_string(out) || ((mus_is_xen(out)) && (mus_is_output(Xen_to_mus_any(out)))),
  7504. out, 1, S_mus_file_mix, "a filename or a " S_frample_to_file " generator");
  7505. if (Xen_is_string(out))
  7506. {
  7507. outfile = Xen_string_to_C_string(out);
  7508. if (!mus_file_probe(outfile))
  7509. Xen_error(NO_SUCH_FILE, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": no such file, ~S"), out));
  7510. out_chans = mus_sound_chans(outfile);
  7511. if (out_chans <= 0)
  7512. Xen_error(BAD_HEADER, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": ~S output chans <= 0"), out));
  7513. }
  7514. else
  7515. {
  7516. outf = Xen_to_mus_any(out);
  7517. out_chans = mus_channels(outf);
  7518. }
  7519. /* -------- setup input gen -------- */
  7520. arg = Xen_cdr(arg);
  7521. in = Xen_car(arg);
  7522. Xen_check_type(Xen_is_string(in) || ((mus_is_xen(in)) && (mus_is_input(Xen_to_mus_any(in)))),
  7523. in, 2, S_mus_file_mix, "a filename or a " S_file_to_frample " generator");
  7524. if (Xen_is_string(in))
  7525. {
  7526. infile = Xen_string_to_C_string(in);
  7527. if (!mus_file_probe(infile))
  7528. Xen_error(NO_SUCH_FILE, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": no such file, ~S"), in));
  7529. in_chans = mus_sound_chans(infile);
  7530. if (in_chans <= 0)
  7531. Xen_error(BAD_HEADER, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": ~S input chans <= 0"), in));
  7532. osamps = mus_sound_framples(infile);
  7533. }
  7534. else
  7535. {
  7536. inf = Xen_to_mus_any(in);
  7537. in_chans = mus_channels(inf);
  7538. osamps = mus_length(inf);
  7539. }
  7540. /* inf and outf only exist during the rest of the arglist scan if not infile or outfile.
  7541. * we need to delay making the inf/outf gens in this case to greatly simplify error handling.
  7542. */
  7543. /* rest of args are optional */
  7544. arg = Xen_cdr(arg);
  7545. if (!Xen_is_null(arg))
  7546. {
  7547. Xen ost;
  7548. ost = Xen_car(arg);
  7549. Xen_check_type(Xen_is_integer(ost), ost, 3, S_mus_file_mix, "an integer");
  7550. ostart = Xen_llong_to_C_llong(ost);
  7551. arg = Xen_cdr(arg);
  7552. if (!Xen_is_null(arg))
  7553. {
  7554. Xen olen;
  7555. olen = Xen_car(arg);
  7556. Xen_check_type(Xen_is_integer(olen), olen, 4, S_mus_file_mix, "an integer");
  7557. osamps = Xen_llong_to_C_llong(olen);
  7558. if (osamps <= 0) return(Xen_false);
  7559. arg = Xen_cdr(arg);
  7560. if (!Xen_is_null(arg))
  7561. {
  7562. Xen ist;
  7563. ist = Xen_car(arg);
  7564. Xen_check_type(Xen_is_integer(ist), ist, 5, S_mus_file_mix, "an integer");
  7565. istart = Xen_llong_to_C_llong(ist);
  7566. arg = Xen_cdr(arg);
  7567. if (!Xen_is_null(arg))
  7568. {
  7569. Xen mx;
  7570. mx = Xen_car(arg);
  7571. Xen_check_type((mus_is_vct(mx)) || (Xen_is_false(mx)), mx, 6, S_mus_file_mix, "a " S_vct);
  7572. if (mus_is_vct(mx))
  7573. {
  7574. matrix = mus_vct_data(Xen_to_vct(mx));
  7575. mx_chans = (int)sqrt(mus_vct_length(Xen_to_vct(mx)));
  7576. }
  7577. arg = Xen_cdr(arg);
  7578. if (!Xen_is_null(arg))
  7579. {
  7580. Xen envs;
  7581. envs = Xen_car(arg);
  7582. Xen_check_type((Xen_is_false(envs)) || (Xen_is_vector(envs)), envs, 7, S_mus_file_mix, "a vector of envs");
  7583. if (Xen_is_vector(envs))
  7584. {
  7585. int in_len = 0, out_len, j, out_size;
  7586. /* pack into a C-style array of arrays of env pointers */
  7587. in_len = Xen_vector_length(envs);
  7588. if (in_len == 0)
  7589. Xen_error(BAD_TYPE, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": env vector, ~A, can't be empty"), envs));
  7590. for (i = 0; i < in_len; i++)
  7591. {
  7592. Xen datum;
  7593. datum = Xen_vector_ref(envs, i);
  7594. if (!(Xen_is_vector(datum)))
  7595. Xen_error(BAD_TYPE, Xen_list_2(C_string_to_Xen_string(S_mus_file_mix ": vector, ~A, must contain vectors of envelopes"), datum));
  7596. }
  7597. out_len = Xen_vector_length(Xen_vector_ref(envs, 0));
  7598. if (in_len < in_chans) in_size = in_chans; else in_size = in_len;
  7599. if (out_len < out_chans) out_size = out_chans; else out_size = out_len;
  7600. envs1 = (mus_any ***)malloc(in_size * sizeof(mus_any **));
  7601. for (i = 0; i < in_size; i++)
  7602. envs1[i] = (mus_any **)calloc(out_size, sizeof(mus_any *));
  7603. for (i = 0; i < in_len; i++)
  7604. for (j = 0; j < out_len; j++)
  7605. {
  7606. Xen datum1;
  7607. datum1 = Xen_vector_ref(Xen_vector_ref(envs, i), j);
  7608. if (mus_is_xen(datum1))
  7609. {
  7610. if (mus_is_env(Xen_to_mus_any(datum1)))
  7611. envs1[i][j] = Xen_to_mus_any(datum1);
  7612. else
  7613. {
  7614. for (i = 0; i < in_size; i++) if (envs1[i]) free(envs1[i]);
  7615. free(envs1);
  7616. Xen_error(BAD_TYPE, Xen_list_4(C_string_to_Xen_string(S_mus_file_mix ": vector, ~A at ~A ~A, must contain an envelope"),
  7617. datum1,
  7618. C_int_to_Xen_integer(i),
  7619. C_int_to_Xen_integer(j)));
  7620. }
  7621. }
  7622. }
  7623. }
  7624. }
  7625. }
  7626. }
  7627. }
  7628. }
  7629. if ((infile) && (outfile))
  7630. mus_file_mix(outfile, infile, ostart, osamps, istart, matrix, mx_chans, envs1);
  7631. else
  7632. {
  7633. if (infile)
  7634. inf = mus_make_file_to_frample(infile);
  7635. if (outfile)
  7636. outf = mus_continue_sample_to_file(outfile);
  7637. mus_file_mix_with_reader_and_writer(outf, inf, ostart, osamps, istart, matrix, mx_chans, envs1);
  7638. if (infile)
  7639. mus_free((mus_any *)inf);
  7640. if (outfile)
  7641. mus_free((mus_any *)outf);
  7642. }
  7643. if (envs1)
  7644. {
  7645. for (i = 0; i < in_size; i++) if (envs1[i]) free(envs1[i]);
  7646. free(envs1);
  7647. }
  7648. return(Xen_true);
  7649. }
  7650. /* Xen file, Xen beg, Xen dur, Xen mx, Xen revmx, Xen envs, Xen srcs, Xen srcenv, Xen outstream, Xen revstream */
  7651. static Xen g_mus_file_mix_with_envs(Xen args)
  7652. {
  7653. #define H_mus_file_mix_with_envs "(" S_mus_file_mix_with_envs " file beg dur mx revmx envs srcs srcenv out rev) is an extension of " S_mus_file_mix ", primarily \
  7654. intended to speed up the fullmix instrument. file is a vector of readin generators. beg is the sample at which to start mixing \
  7655. output, dur is the number of samples to write. mx is a matrix, revmx is either #f or a matrix. "
  7656. int i, in_chans, out_chans, mx_chans = 0, rev_chans = 0, rev_mix_chans = 0;
  7657. mus_long_t st, nd;
  7658. mus_any *s_env = NULL, *ostr, *rstr = NULL;
  7659. mus_any **mix_envs, **mix_srcs, **mix_rds;
  7660. mus_xen *gn;
  7661. Xen ve, arg, file, beg, dur, mx, revmx, envs, srcs, srcenv, outstream, revstream;
  7662. mus_float_t *mix = NULL, *rev_mix = NULL;
  7663. i = Xen_list_length(args);
  7664. if ((i < 8) || (i > 10)) /* no wrong-number-of-args error in xen.h, so I'll use out-of-range */
  7665. Xen_out_of_range_error(S_mus_file_mix_with_envs, 0, args, "wrong number of args");
  7666. arg = args;
  7667. file = Xen_car(arg);
  7668. Xen_check_type(Xen_is_vector(file), file, 1, S_mus_file_mix_with_envs, "a vector of readin generators");
  7669. in_chans = Xen_vector_length(file);
  7670. arg = Xen_cdr(arg);
  7671. beg = Xen_car(arg);
  7672. Xen_check_type(Xen_is_integer(beg), beg, 2, S_mus_file_mix_with_envs, "an integer");
  7673. st = Xen_integer_to_C_int(beg);
  7674. arg = Xen_cdr(arg);
  7675. dur = Xen_car(arg);
  7676. Xen_check_type(Xen_is_integer(dur), dur, 3, S_mus_file_mix_with_envs, "an integer");
  7677. nd = st + Xen_integer_to_C_int(dur);
  7678. arg = Xen_cdr(arg);
  7679. mx = Xen_car(arg);
  7680. if (mus_is_vct(mx))
  7681. {
  7682. mix = mus_vct_data(Xen_to_vct(mx));
  7683. mx_chans = (int)sqrt(mus_vct_length(Xen_to_vct(mx)));
  7684. }
  7685. arg = Xen_cdr(arg);
  7686. revmx = Xen_car(arg);
  7687. if (mus_is_vct(revmx))
  7688. {
  7689. rev_mix = mus_vct_data(Xen_to_vct(revmx));
  7690. rev_mix_chans = (int)sqrt(mus_vct_length(Xen_to_vct(revmx)));
  7691. }
  7692. arg = Xen_cdr(arg);
  7693. envs = Xen_car(arg);
  7694. if (!Xen_is_false(envs))
  7695. Xen_check_type(Xen_is_vector(envs), envs, 6, S_mus_file_mix_with_envs, "a vector of env generators");
  7696. arg = Xen_cdr(arg);
  7697. srcs = Xen_car(arg);
  7698. if (!Xen_is_false(srcs))
  7699. Xen_check_type(Xen_is_vector(srcs), srcs, 7, S_mus_file_mix_with_envs, "a vector of src generators");
  7700. arg = Xen_cdr(arg);
  7701. srcenv = Xen_car(arg);
  7702. if (!Xen_is_false(srcenv))
  7703. {
  7704. gn = (mus_xen *)Xen_object_ref_checked(srcenv, mus_xen_tag);
  7705. if (!gn) Xen_check_type(false, srcenv, 8, S_mus_file_mix_with_envs, "an env generator");
  7706. s_env = gn->gen;
  7707. Xen_check_type(mus_is_env(s_env), srcenv, 8, S_mus_file_mix_with_envs, "an env generator");
  7708. }
  7709. revstream = Xen_false;
  7710. arg = Xen_cdr(arg);
  7711. if (!Xen_is_null(arg))
  7712. {
  7713. outstream = Xen_car(arg);
  7714. gn = (mus_xen *)Xen_object_ref_checked(outstream, mus_xen_tag);
  7715. if (!gn)
  7716. Xen_check_type(false, outstream, 9, S_mus_file_mix_with_envs, "an output generator");
  7717. ostr = gn->gen;
  7718. arg = Xen_cdr(arg);
  7719. if (!Xen_is_null(arg))
  7720. revstream = Xen_car(arg);
  7721. }
  7722. else ostr = Xen_to_mus_any(mus_clm_output());
  7723. out_chans = mus_channels(ostr);
  7724. if (rev_mix)
  7725. {
  7726. if (!Xen_is_false(revstream))
  7727. {
  7728. gn = (mus_xen *)Xen_object_ref_checked(revstream, mus_xen_tag);
  7729. if (!gn)
  7730. Xen_check_type(false, revstream, 10, S_mus_file_mix_with_envs, "an output generator");
  7731. rstr = gn->gen;
  7732. }
  7733. else rstr = Xen_to_mus_any(mus_clm_reverb());
  7734. rev_chans = mus_channels(rstr);
  7735. }
  7736. mix_rds = (mus_any **)calloc(in_chans, sizeof(mus_any *));
  7737. mix_srcs = (mus_any **)calloc(in_chans, sizeof(mus_any *));
  7738. for (i = 0; i < in_chans; i++)
  7739. mix_rds[i] = Xen_to_mus_any(Xen_vector_ref(file, i));
  7740. if (Xen_is_vector(srcs))
  7741. {
  7742. for (i = 0; i < in_chans; i++)
  7743. {
  7744. ve = Xen_vector_ref(srcs, i);
  7745. if (!Xen_is_false(ve)) mix_srcs[i] = Xen_to_mus_any(ve);
  7746. }
  7747. }
  7748. mix_envs = (mus_any **)calloc(in_chans * out_chans, sizeof(mus_any *));
  7749. if (Xen_is_vector(envs))
  7750. for (i = 0; i < in_chans * out_chans; i++)
  7751. {
  7752. ve = Xen_vector_ref(envs, i);
  7753. if (!Xen_is_false(ve)) mix_envs[i] = Xen_to_mus_any(ve);
  7754. }
  7755. {
  7756. mus_long_t samp;
  7757. int outp;
  7758. mus_float_t src_env_val = 0.0;
  7759. mus_float_t *infs, *out_frample, *rev_frample = NULL;
  7760. infs = (mus_float_t *)calloc(in_chans, sizeof(mus_float_t));
  7761. out_frample = (mus_float_t *)calloc(out_chans, sizeof(mus_float_t));
  7762. if (rev_mix) rev_frample = (mus_float_t *)calloc(rev_chans, sizeof(mus_float_t));
  7763. if (in_chans == 1)
  7764. {
  7765. mus_any *s = NULL, *r = NULL;
  7766. s = mix_srcs[0];
  7767. if (!s) r = mix_rds[0];
  7768. for (samp = st; samp < nd; samp++)
  7769. {
  7770. for (outp = 0; outp < out_chans; outp++)
  7771. {
  7772. mus_any *e;
  7773. e = mix_envs[outp];
  7774. if (e)
  7775. mix[outp] = mus_env(e);
  7776. }
  7777. if (s_env)
  7778. src_env_val = mus_env(s_env);
  7779. if (s)
  7780. infs[0] = mus_src(s, src_env_val, NULL);
  7781. else
  7782. {
  7783. if (r)
  7784. infs[0] = mus_readin(r);
  7785. else infs[0] = 0.0;
  7786. }
  7787. mus_frample_to_file(ostr, samp, mus_frample_to_frample(mix, mx_chans, infs, in_chans, out_frample, out_chans));
  7788. if (rev_mix) mus_frample_to_file(rstr, samp, mus_frample_to_frample(rev_mix, rev_mix_chans, infs, in_chans, rev_frample, rev_chans));
  7789. }
  7790. }
  7791. else
  7792. {
  7793. for (samp = st; samp < nd; samp++)
  7794. {
  7795. int inp, off;
  7796. for (inp = 0, off = 0; inp < in_chans; inp++, off += mx_chans)
  7797. for (outp = 0; outp < out_chans; outp++)
  7798. {
  7799. mus_any *e;
  7800. e = mix_envs[inp * out_chans + outp]; /* this is different from the matrix setup -- I don't know why */
  7801. if (e)
  7802. mix[off + outp] = mus_env(e);
  7803. }
  7804. if (s_env)
  7805. src_env_val = mus_env(s_env);
  7806. for (inp = 0; inp < in_chans; inp++)
  7807. {
  7808. mus_any *s;
  7809. s = mix_srcs[inp];
  7810. if (s)
  7811. infs[inp] = mus_src(s, src_env_val, NULL);
  7812. else
  7813. {
  7814. s = mix_rds[inp];
  7815. if (s)
  7816. infs[inp] = mus_readin(s);
  7817. else infs[inp] = 0.0;
  7818. }
  7819. }
  7820. mus_frample_to_file(ostr, samp, mus_frample_to_frample(mix, mx_chans, infs, in_chans, out_frample, out_chans));
  7821. if (rev_mix) mus_frample_to_file(rstr, samp, mus_frample_to_frample(rev_mix, rev_mix_chans, infs, in_chans, rev_frample, rev_chans));
  7822. }
  7823. }
  7824. free(infs);
  7825. free(out_frample);
  7826. if (rev_frample) free(rev_frample);
  7827. }
  7828. free(mix_rds);
  7829. free(mix_srcs);
  7830. free(mix_envs);
  7831. return(Xen_false);
  7832. }
  7833. static Xen g_frample_to_frample(Xen mx, Xen infr, Xen inchans, Xen outfr, Xen outchans)
  7834. {
  7835. #define H_frample_to_frample "(" S_frample_to_frample " matrix in-data in-chans out-data out-chans): pass frample in-data through matrix \
  7836. returning frample out-data; this is a matrix multiply of matrix and in-data"
  7837. int ins, outs, mxs;
  7838. vct *vin, *vout, *vmx;
  7839. Xen_check_type(mus_is_vct(mx), mx, 1, S_frample_to_frample, "a " S_vct);
  7840. Xen_check_type(mus_is_vct(infr), infr, 2, S_frample_to_frample, "a " S_vct);
  7841. Xen_check_type(mus_is_vct(outfr), outfr, 4, S_frample_to_frample, "a " S_vct);
  7842. Xen_check_type(Xen_is_integer(inchans), inchans, 3, S_frample_to_frample, "an integer");
  7843. Xen_check_type(Xen_is_integer(outchans), outchans, 5, S_frample_to_frample, "an integer");
  7844. ins = Xen_integer_to_C_int(inchans);
  7845. vin = Xen_to_vct(infr);
  7846. if (mus_vct_length(vin) < ins) ins = mus_vct_length(vin);
  7847. if (ins <= 0) return(outfr);
  7848. outs = Xen_integer_to_C_int(outchans);
  7849. vout = Xen_to_vct(outfr);
  7850. if (mus_vct_length(vout) < outs) outs = mus_vct_length(vout);
  7851. if (outs <= 0) return(outfr);
  7852. vmx = Xen_to_vct(mx);
  7853. mxs = (int)sqrt(mus_vct_length(vmx));
  7854. mus_frample_to_frample(mus_vct_data(vmx), mxs, mus_vct_data(vin), ins, mus_vct_data(vout), outs);
  7855. return(outfr);
  7856. }
  7857. #if HAVE_SCHEME
  7858. #ifndef _MSC_VER
  7859. #include <time.h>
  7860. #include <sys/time.h>
  7861. static struct timeval overall_start_time;
  7862. #define S_get_internal_real_time "get-internal-real-time"
  7863. #define S_internal_time_units_per_second "internal-time-units-per-second"
  7864. static Xen g_get_internal_real_time(void)
  7865. {
  7866. #define H_get_internal_real_time "(" S_get_internal_real_time ") returns the number of seconds since \
  7867. the program started. The number is in terms of " S_internal_time_units_per_second ", usually 1"
  7868. struct timezone z0;
  7869. struct timeval t0;
  7870. mus_float_t secs;
  7871. gettimeofday(&t0, &z0);
  7872. secs = difftime(t0.tv_sec, overall_start_time.tv_sec);
  7873. return(C_double_to_Xen_real(secs + 0.000001 * (t0.tv_usec - overall_start_time.tv_usec)));
  7874. }
  7875. #else
  7876. static Xen g_get_internal_real_time(void) {return(C_double_to_Xen_real(0.0));}
  7877. #endif
  7878. Xen_wrap_no_args(g_get_internal_real_time_w, g_get_internal_real_time)
  7879. #endif
  7880. /* -------------------------------- scheme-side optimization -------------------------------- */
  7881. #if HAVE_SCHEME
  7882. #if (!WITH_GMP)
  7883. #define car(E) s7_car(E)
  7884. #define cdr(E) s7_cdr(E)
  7885. #define cadr(E) s7_cadr(E)
  7886. #define caddr(E) s7_caddr(E)
  7887. #define cadddr(E) s7_cadddr(E)
  7888. #define cadddr(E) s7_cadddr(E)
  7889. static mus_float_t mus_nsin_unmodulated(mus_any *p) {return(mus_nsin(p, 0.0));}
  7890. static mus_float_t mus_ncos_unmodulated(mus_any *p) {return(mus_ncos(p, 0.0));}
  7891. static mus_float_t mus_nrxysin_unmodulated(mus_any *p) {return(mus_nrxysin(p, 0.0));}
  7892. static mus_float_t mus_nrxycos_unmodulated(mus_any *p) {return(mus_nrxycos(p, 0.0));}
  7893. static mus_float_t mus_rxyksin_unmodulated(mus_any *p) {return(mus_rxyksin(p, 0.0));}
  7894. static mus_float_t mus_rxykcos_unmodulated(mus_any *p) {return(mus_rxykcos(p, 0.0));}
  7895. static mus_float_t mus_square_wave_unmodulated(mus_any *p) {return(mus_square_wave(p, 0.0));}
  7896. static mus_float_t mus_sawtooth_wave_unmodulated(mus_any *p) {return(mus_sawtooth_wave(p, 0.0));}
  7897. static mus_float_t mus_src_simple(mus_any *p) {return(mus_src(p, 0.0, NULL));}
  7898. static mus_float_t mus_src_two(mus_any *p, mus_float_t x) {return(mus_src(p, x, NULL));}
  7899. static mus_float_t mus_granulate_simple(mus_any *p) {return(mus_granulate_with_editor(p, NULL, NULL));}
  7900. static mus_float_t mus_convolve_simple(mus_any *p) {return(mus_convolve(p, NULL));}
  7901. static mus_float_t mus_phase_vocoder_simple(mus_any *p) {return(mus_phase_vocoder(p, NULL));}
  7902. #define mus_oscil_rf mus_oscil_unmodulated
  7903. #define mus_polywave_rf mus_polywave_unmodulated
  7904. #define mus_ncos_rf mus_ncos_unmodulated
  7905. #define mus_nsin_rf mus_nsin_unmodulated
  7906. #define mus_nrxycos_rf mus_nrxycos_unmodulated
  7907. #define mus_nrxysin_rf mus_nrxysin_unmodulated
  7908. #define mus_rxykcos_rf mus_rxykcos_unmodulated
  7909. #define mus_rxyksin_rf mus_rxyksin_unmodulated
  7910. #define mus_rand_rf mus_rand_unmodulated
  7911. #define mus_rand_interp_rf mus_rand_interp_unmodulated
  7912. #define mus_readin_rf mus_readin
  7913. #define mus_env_rf mus_env
  7914. #define mus_pulsed_env_rf mus_pulsed_env_unmodulated
  7915. #define mus_oscil_bank_rf mus_oscil_bank
  7916. #define mus_table_lookup_rf mus_table_lookup_unmodulated
  7917. #define mus_sawtooth_wave_rf mus_sawtooth_wave_unmodulated
  7918. #define mus_pulse_train_rf mus_pulse_train_unmodulated
  7919. #define mus_triangle_wave_rf mus_triangle_wave_unmodulated
  7920. #define mus_square_wave_rf mus_square_wave_unmodulated
  7921. #define mus_wave_train_rf mus_wave_train_unmodulated
  7922. #define mus_convolve_rf mus_convolve_simple
  7923. #define mus_src_rf mus_src_simple
  7924. #define mus_granulate_rf mus_granulate_simple
  7925. #define mus_phase_vocoder_rf mus_phase_vocoder_simple
  7926. static mus_float_t mus_one_pole_rf(mus_any *p) {return(mus_one_pole(p, 0.0));}
  7927. static mus_float_t mus_two_pole_rf(mus_any *p) {return(mus_two_pole(p, 0.0));}
  7928. static mus_float_t mus_one_zero_rf(mus_any *p) {return(mus_one_zero(p, 0.0));}
  7929. static mus_float_t mus_two_zero_rf(mus_any *p) {return(mus_two_zero(p, 0.0));}
  7930. static mus_float_t mus_delay_rf(mus_any *p) {return(mus_delay_unmodulated(p, 0.0));}
  7931. static mus_float_t mus_comb_rf(mus_any *p) {return(mus_comb_unmodulated(p, 0.0));}
  7932. static mus_float_t mus_comb_bank_rf(mus_any *p) {return(mus_comb_bank(p, 0.0));}
  7933. static mus_float_t mus_all_pass_bank_rf(mus_any *p) {return(mus_all_pass_bank(p, 0.0));}
  7934. static mus_float_t mus_notch_rf(mus_any *p) {return(mus_notch_unmodulated(p, 0.0));}
  7935. static mus_float_t mus_all_pass_rf(mus_any *p) {return(mus_all_pass_unmodulated(p, 0.0));}
  7936. static mus_float_t mus_one_pole_all_pass_rf(mus_any *p) {return(mus_one_pole_all_pass(p, 0.0));}
  7937. static mus_float_t mus_moving_average_rf(mus_any *p) {return(mus_moving_average(p, 0.0));}
  7938. static mus_float_t mus_moving_max_rf(mus_any *p) {return(mus_moving_max(p, 0.0));}
  7939. static mus_float_t mus_moving_norm_rf(mus_any *p) {return(mus_moving_norm(p, 0.0));}
  7940. static mus_float_t mus_filter_rf(mus_any *p) {return(mus_filter(p, 0.0));}
  7941. static mus_float_t mus_fir_filter_rf(mus_any *p) {return(mus_fir_filter(p, 0.0));}
  7942. static mus_float_t mus_iir_filter_rf(mus_any *p) {return(mus_iir_filter(p, 0.0));}
  7943. static mus_float_t mus_polyshape_rf(mus_any *p) {return(mus_polyshape_unmodulated(p, 1.0));}
  7944. static mus_float_t mus_filtered_comb_rf(mus_any *p) {return(mus_filtered_comb_unmodulated(p, 0.0));}
  7945. static mus_float_t mus_filtered_comb_bank_rf(mus_any *p) {return(mus_filtered_comb_bank(p, 0.0));}
  7946. static mus_float_t mus_asymmetric_fm_rf(mus_any *p) {return(mus_asymmetric_fm_unmodulated(p, 0.0));}
  7947. static mus_float_t mus_formant_rf(mus_any *p) {return(mus_formant(p, 0.0));}
  7948. static mus_float_t mus_firmant_rf(mus_any *p) {return(mus_firmant(p, 0.0));}
  7949. static mus_float_t mus_ssb_am_rf_1(mus_any *p) {return(mus_ssb_am(p, 0.0, 0.0));}
  7950. static mus_any *cadr_gen(s7_scheme *sc, s7_pointer expr)
  7951. {
  7952. s7_pointer sym, o;
  7953. mus_xen *gn;
  7954. sym = s7_cadr(expr);
  7955. if (!s7_is_symbol(sym)) return(NULL);
  7956. if (s7_xf_is_stepper(sc, sym)) return(NULL);
  7957. o = s7_symbol_value(sc, sym);
  7958. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  7959. if (!gn) return(NULL);
  7960. return(gn->gen);
  7961. }
  7962. static s7_rf_t caddr_rf(s7_scheme *sc, s7_pointer a2, s7_rf_t func)
  7963. {
  7964. s7_int loc;
  7965. s7_pointer val_sym, val;
  7966. s7_rf_t rf;
  7967. s7_rp_t rp;
  7968. val_sym = car(a2);
  7969. if (!s7_is_symbol(val_sym)) return(NULL);
  7970. val = s7_symbol_value(sc, val_sym);
  7971. rp = s7_rf_function(sc, val);
  7972. if (!rp) return(NULL);
  7973. loc = s7_xf_store(sc, NULL);
  7974. rf = rp(sc, a2);
  7975. if (!rf) return(NULL);
  7976. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  7977. return(func);
  7978. }
  7979. #define GEN_RF_1(Type, Func) \
  7980. static s7_double Type ## _rf_g(s7_scheme *sc, s7_pointer **p) \
  7981. { \
  7982. mus_any *g; g = (mus_any *)(**p); (*p)++; \
  7983. return(Func(g)); \
  7984. } \
  7985. static s7_rf_t Type ## _rf(s7_scheme *sc, s7_pointer expr) \
  7986. { \
  7987. mus_any *g; \
  7988. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  7989. g = cadr_gen(sc, expr); \
  7990. if ((g) && (mus_is_ ## Type(g))) {s7_xf_store(sc, (s7_pointer)g); return(Type ## _rf_g);} \
  7991. return(NULL); \
  7992. } \
  7993. static s7_pointer is_ ## Type ## _pf_g(s7_scheme *sc, s7_pointer **p) \
  7994. { \
  7995. mus_xen *gn; \
  7996. s7_pf_t pf; pf = (s7_pf_t)(**p); (*p)++; \
  7997. gn = (mus_xen *)s7_object_value_checked(pf(sc, p), mus_xen_tag); \
  7998. return(s7_make_boolean(sc, (gn) && (mus_is_ ## Type(gn->gen)))); \
  7999. } \
  8000. static s7_pf_t is_ ## Type ## _pf(s7_scheme *sc, s7_pointer expr) \
  8001. { \
  8002. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  8003. if (s7_arg_to_pf(sc, s7_cadr(expr))) return(is_ ## Type ## _pf_g); \
  8004. return(NULL); \
  8005. }
  8006. #define GEN_RF(Type, Func1, Func2) \
  8007. static s7_double Type ## _rf_g(s7_scheme *sc, s7_pointer **p) \
  8008. { \
  8009. mus_any *g; g = (mus_any *)(*(*p)); (*p)++; \
  8010. return(Func1(g)); \
  8011. } \
  8012. static s7_double Type ## _rf_gr(s7_scheme *sc, s7_pointer **p) \
  8013. { \
  8014. s7_pointer a2; \
  8015. mus_any *g; g = (mus_any *)(*(*p)); (*p)++; \
  8016. a2 = (**p); (*p)++; \
  8017. return(Func2(g, s7_number_to_real(sc, a2))); \
  8018. } \
  8019. static s7_double Type ## _rf_gs(s7_scheme *sc, s7_pointer **p) \
  8020. { \
  8021. s7_double a2; \
  8022. mus_any *g; g = (mus_any *)(*(*p)); (*p)++; \
  8023. a2 = s7_slot_real_value(sc, **p, #Type); (*p)++; \
  8024. return(Func2(g, a2)); \
  8025. } \
  8026. static s7_double Type ## _rf_gx(s7_scheme *sc, s7_pointer **p) \
  8027. { \
  8028. s7_rf_t f; \
  8029. mus_any *g; g = (mus_any *)(*(*p)); (*p)++; \
  8030. f = (s7_rf_t)(**p); (*p)++; \
  8031. return(Func2(g, f(sc, p))); \
  8032. } \
  8033. static s7_rf_t Type ## _rf(s7_scheme *sc, s7_pointer expr) \
  8034. { \
  8035. mus_any *g; \
  8036. g = cadr_gen(sc, expr); \
  8037. if ((g) && (mus_is_ ## Type(g))) \
  8038. { \
  8039. s7_pointer a2; \
  8040. s7_xf_store(sc, (s7_pointer)g); \
  8041. if (s7_is_null(sc, s7_cddr(expr))) return(Type ## _rf_g); \
  8042. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL); \
  8043. a2 = caddr(expr); \
  8044. if (s7_is_real(a2)) {s7_xf_store(sc, a2); return(Type ## _rf_gr);} \
  8045. if (s7_is_symbol(a2)) \
  8046. { \
  8047. s7_pointer slot; \
  8048. slot = s7_slot(sc, a2); \
  8049. if (slot != xen_undefined) {s7_xf_store(sc, (s7_pointer)slot); return(Type ## _rf_gs);} \
  8050. return(NULL); \
  8051. } \
  8052. if (s7_is_pair(a2)) \
  8053. return(caddr_rf(sc, a2, Type ## _rf_gx)); \
  8054. } \
  8055. return(NULL); \
  8056. } \
  8057. static s7_pointer is_ ## Type ## _pf_g(s7_scheme *sc, s7_pointer **p) \
  8058. { \
  8059. mus_xen *gn; \
  8060. s7_pf_t pf; pf = (s7_pf_t)(**p); (*p)++; \
  8061. gn = (mus_xen *)s7_object_value_checked(pf(sc, p), mus_xen_tag); \
  8062. return(s7_make_boolean(sc, (gn) && (mus_is_ ## Type(gn->gen)))); \
  8063. } \
  8064. static s7_pf_t is_ ## Type ## _pf(s7_scheme *sc, s7_pointer expr) \
  8065. { \
  8066. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  8067. if (s7_arg_to_pf(sc, s7_cadr(expr))) return(is_ ## Type ## _pf_g); \
  8068. return(NULL); \
  8069. }
  8070. GEN_RF(all_pass, mus_all_pass_rf, mus_all_pass_unmodulated)
  8071. GEN_RF(asymmetric_fm, mus_asymmetric_fm_rf, mus_asymmetric_fm_unmodulated)
  8072. GEN_RF(comb, mus_comb_rf, mus_comb_unmodulated)
  8073. GEN_RF(comb_bank, mus_comb_bank_rf, mus_comb_bank)
  8074. GEN_RF(all_pass_bank, mus_all_pass_bank_rf, mus_all_pass_bank)
  8075. GEN_RF_1(convolve, mus_convolve_rf)
  8076. GEN_RF(delay, mus_delay_rf, mus_delay_unmodulated)
  8077. GEN_RF_1(env, mus_env_rf)
  8078. GEN_RF(filter, mus_filter_rf, mus_filter)
  8079. GEN_RF(filtered_comb, mus_filtered_comb_rf, mus_filtered_comb_unmodulated)
  8080. GEN_RF(filtered_comb_bank, mus_filtered_comb_bank_rf, mus_filtered_comb_bank)
  8081. GEN_RF(fir_filter, mus_fir_filter_rf, mus_fir_filter)
  8082. GEN_RF(firmant, mus_firmant_rf, mus_firmant)
  8083. GEN_RF(formant, mus_formant_rf, mus_formant)
  8084. GEN_RF_1(granulate, mus_granulate_rf)
  8085. GEN_RF(iir_filter, mus_iir_filter_rf, mus_iir_filter)
  8086. GEN_RF(moving_average, mus_moving_average_rf, mus_moving_average)
  8087. GEN_RF(moving_max, mus_moving_max_rf, mus_moving_max)
  8088. GEN_RF(moving_norm, mus_moving_norm_rf, mus_moving_norm)
  8089. GEN_RF(ncos, mus_ncos_rf, mus_ncos)
  8090. GEN_RF(notch, mus_notch_rf, mus_notch_unmodulated)
  8091. GEN_RF(nrxycos, mus_nrxycos_rf, mus_nrxycos)
  8092. GEN_RF(nrxysin, mus_nrxysin_rf, mus_nrxysin)
  8093. GEN_RF(nsin, mus_nsin_rf, mus_nsin)
  8094. GEN_RF(one_pole, mus_one_pole_rf, mus_one_pole)
  8095. GEN_RF(one_pole_all_pass, mus_one_pole_all_pass_rf, mus_one_pole_all_pass)
  8096. GEN_RF(one_zero, mus_one_zero_rf, mus_one_zero)
  8097. GEN_RF(oscil, mus_oscil_rf, mus_oscil_fm)
  8098. GEN_RF_1(oscil_bank, mus_oscil_bank_rf)
  8099. GEN_RF_1(phase_vocoder, mus_phase_vocoder_rf)
  8100. GEN_RF(polyshape, mus_polyshape_rf, mus_polyshape_unmodulated)
  8101. GEN_RF(polywave, mus_polywave_rf, mus_polywave)
  8102. GEN_RF(pulse_train, mus_pulse_train_rf, mus_pulse_train)
  8103. GEN_RF(pulsed_env, mus_pulsed_env_rf, mus_pulsed_env)
  8104. GEN_RF(rand, mus_rand_rf, mus_rand)
  8105. GEN_RF(rand_interp, mus_rand_interp_rf, mus_rand_interp)
  8106. GEN_RF_1(readin, mus_readin_rf)
  8107. GEN_RF(rxykcos, mus_rxykcos_rf, mus_rxykcos)
  8108. GEN_RF(rxyksin, mus_rxyksin_rf, mus_rxyksin)
  8109. GEN_RF(sawtooth_wave, mus_sawtooth_wave_rf, mus_sawtooth_wave)
  8110. GEN_RF(square_wave, mus_square_wave_rf, mus_square_wave)
  8111. GEN_RF(src, mus_src_rf, mus_src_two)
  8112. GEN_RF(table_lookup, mus_table_lookup_rf, mus_table_lookup)
  8113. GEN_RF(triangle_wave, mus_triangle_wave_rf, mus_triangle_wave)
  8114. GEN_RF(two_pole, mus_two_pole_rf, mus_two_pole)
  8115. GEN_RF(two_zero, mus_two_zero_rf, mus_two_zero)
  8116. GEN_RF(wave_train, mus_wave_train_rf, mus_wave_train)
  8117. GEN_RF(ssb_am, mus_ssb_am_rf_1, mus_ssb_am_unmodulated)
  8118. GEN_RF(tap, mus_tap_unmodulated, mus_tap)
  8119. static s7_double oscil_rf_sxx(s7_scheme *sc, s7_pointer **p)
  8120. {
  8121. s7_rf_t rf1, rf2;
  8122. s7_double v1, v2;
  8123. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8124. rf1 = (s7_rf_t)(**p); (*p)++;
  8125. v1 = rf1(sc, p);
  8126. rf2 = (s7_rf_t)(**p); (*p)++;
  8127. v2 = rf2(sc, p);
  8128. return(mus_oscil(g, v1, v2));
  8129. }
  8130. static s7_double oscil_rf_ssx(s7_scheme *sc, s7_pointer **p)
  8131. {
  8132. s7_rf_t rf1;
  8133. s7_pointer s1;
  8134. s7_double v1;
  8135. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8136. s1 = (**p); (*p)++;
  8137. rf1 = (s7_rf_t)(**p); (*p)++;
  8138. v1 = rf1(sc, p);
  8139. return(mus_oscil(g, s7_slot_real_value(sc, s1, S_oscil), v1));
  8140. }
  8141. static s7_double oscil_rf_sss(s7_scheme *sc, s7_pointer **p)
  8142. {
  8143. s7_pointer s1, s2;
  8144. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8145. s1 = (**p); (*p)++;
  8146. s2 = (**p); (*p)++;
  8147. return(mus_oscil(g, s7_slot_real_value(sc, s1, S_oscil), s7_slot_real_value(sc, s2, S_oscil)));
  8148. }
  8149. static s7_double oscil_rf_srs(s7_scheme *sc, s7_pointer **p)
  8150. {
  8151. s7_pointer s1, s2;
  8152. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8153. s1 = (**p); (*p)++;
  8154. s2 = (**p); (*p)++;
  8155. return(mus_oscil(g, s7_number_to_real(sc, s1), s7_slot_real_value(sc, s2, S_oscil)));
  8156. }
  8157. static s7_double oscil_rf_srx(s7_scheme *sc, s7_pointer **p)
  8158. {
  8159. s7_rf_t rf1;
  8160. s7_pointer s1;
  8161. s7_double v1;
  8162. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8163. s1 = (**p); (*p)++;
  8164. rf1 = (s7_rf_t)(**p); (*p)++;
  8165. v1 = rf1(sc, p);
  8166. return(mus_oscil(g, s7_number_to_real(sc, s1), v1));
  8167. }
  8168. static s7_rf_t oscil_rf_3(s7_scheme *sc, s7_pointer expr)
  8169. {
  8170. mus_any *g;
  8171. int len;
  8172. len = s7_list_length(sc, expr);
  8173. g = cadr_gen(sc, expr);
  8174. if (!g) return(NULL);
  8175. if (len < 4) return(oscil_rf(sc, expr));
  8176. if (len > 5) return(NULL);
  8177. s7_xf_store(sc, (s7_pointer)g);
  8178. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, oscil_rf_srs, oscil_rf_sss, NULL, oscil_rf_srx, oscil_rf_ssx, oscil_rf_sxx));
  8179. }
  8180. static s7_double comb_rf_sxx(s7_scheme *sc, s7_pointer **p)
  8181. {
  8182. s7_rf_t rf1, rf2;
  8183. s7_double v1;
  8184. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8185. rf1 = (s7_rf_t)(**p); (*p)++;
  8186. v1 = rf1(sc, p);
  8187. rf2 = (s7_rf_t)(**p); (*p)++;
  8188. return(mus_comb(g, v1, rf2(sc, p)));
  8189. }
  8190. static s7_double comb_rf_ssx(s7_scheme *sc, s7_pointer **p)
  8191. {
  8192. s7_rf_t rf1;
  8193. s7_pointer s1;
  8194. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8195. s1 = (**p); (*p)++;
  8196. rf1 = (s7_rf_t)(**p); (*p)++;
  8197. return(mus_comb(g, s7_slot_real_value(sc, s1, S_comb), rf1(sc, p)));
  8198. }
  8199. static s7_double comb_rf_sss(s7_scheme *sc, s7_pointer **p)
  8200. {
  8201. s7_pointer s1, s2;
  8202. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8203. s1 = (**p); (*p)++;
  8204. s2 = (**p); (*p)++;
  8205. return(mus_comb(g, s7_slot_real_value(sc, s1, S_comb), s7_slot_real_value(sc, s2, S_comb)));
  8206. }
  8207. static s7_rf_t comb_rf_3(s7_scheme *sc, s7_pointer expr)
  8208. {
  8209. mus_any *g;
  8210. int len;
  8211. len = s7_list_length(sc, expr);
  8212. if (len < 4) return(comb_rf(sc, expr));
  8213. if (len > 5) return(NULL);
  8214. g = cadr_gen(sc, expr);
  8215. if ((!g) || (!mus_is_comb(g))) return(NULL);
  8216. s7_xf_store(sc, (s7_pointer)g);
  8217. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, comb_rf_sss, NULL, NULL, comb_rf_ssx, comb_rf_sxx));
  8218. }
  8219. static s7_double notch_rf_sxx(s7_scheme *sc, s7_pointer **p)
  8220. {
  8221. s7_rf_t rf1, rf2;
  8222. s7_double v1;
  8223. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8224. rf1 = (s7_rf_t)(**p); (*p)++;
  8225. v1 = rf1(sc, p);
  8226. rf2 = (s7_rf_t)(**p); (*p)++;
  8227. return(mus_notch(g, v1, rf2(sc, p)));
  8228. }
  8229. static s7_rf_t notch_rf_3(s7_scheme *sc, s7_pointer expr)
  8230. {
  8231. mus_any *g;
  8232. int len;
  8233. len = s7_list_length(sc, expr);
  8234. if (len < 4) return(notch_rf(sc, expr));
  8235. if (len > 5) return(NULL);
  8236. g = cadr_gen(sc, expr);
  8237. if ((!g) || (!mus_is_notch(g))) return(NULL);
  8238. s7_xf_store(sc, (s7_pointer)g);
  8239. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, notch_rf_sxx));
  8240. }
  8241. static s7_double delay_rf_sxx(s7_scheme *sc, s7_pointer **p)
  8242. {
  8243. s7_rf_t rf1, rf2;
  8244. s7_double v1;
  8245. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8246. rf1 = (s7_rf_t)(**p); (*p)++;
  8247. v1 = rf1(sc, p);
  8248. rf2 = (s7_rf_t)(**p); (*p)++;
  8249. return(mus_delay(g, v1, rf2(sc, p)));
  8250. }
  8251. static s7_rf_t delay_rf_3(s7_scheme *sc, s7_pointer expr)
  8252. {
  8253. mus_any *g;
  8254. int len;
  8255. len = s7_list_length(sc, expr);
  8256. if (len < 4) return(delay_rf(sc, expr));
  8257. if (len > 5) return(NULL);
  8258. g = cadr_gen(sc, expr);
  8259. if ((!g) || (!mus_is_delay(g))) return(NULL);
  8260. s7_xf_store(sc, (s7_pointer)g);
  8261. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, delay_rf_sxx));
  8262. }
  8263. static s7_double all_pass_rf_sxx(s7_scheme *sc, s7_pointer **p)
  8264. {
  8265. s7_rf_t rf1, rf2;
  8266. s7_double v1;
  8267. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8268. rf1 = (s7_rf_t)(**p); (*p)++;
  8269. v1 = rf1(sc, p);
  8270. rf2 = (s7_rf_t)(**p); (*p)++;
  8271. return(mus_all_pass(g, v1, rf2(sc, p)));
  8272. }
  8273. static s7_rf_t all_pass_rf_3(s7_scheme *sc, s7_pointer expr)
  8274. {
  8275. mus_any *g;
  8276. int len;
  8277. len = s7_list_length(sc, expr);
  8278. if (len < 4) return(all_pass_rf(sc, expr));
  8279. if (len > 5) return(NULL);
  8280. g = cadr_gen(sc, expr);
  8281. if ((!g) || (!mus_is_all_pass(g))) return(NULL);
  8282. s7_xf_store(sc, (s7_pointer)g);
  8283. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, all_pass_rf_sxx));
  8284. }
  8285. static s7_double ssb_am_rf_sss(s7_scheme *sc, s7_pointer **p)
  8286. {
  8287. s7_pointer s1, s2;
  8288. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8289. s1 = (**p); (*p)++;
  8290. s2 = (**p); (*p)++;
  8291. return(mus_ssb_am(g, s7_slot_real_value(sc, s1, S_ssb_am), s7_slot_real_value(sc, s2, S_ssb_am)));
  8292. }
  8293. static s7_rf_t ssb_am_rf_3(s7_scheme *sc, s7_pointer expr)
  8294. {
  8295. mus_any *g;
  8296. int len;
  8297. len = s7_list_length(sc, expr);
  8298. if (len < 4) return(ssb_am_rf(sc, expr));
  8299. if (len > 5) return(NULL);
  8300. g = cadr_gen(sc, expr);
  8301. if ((!g) || (!mus_is_ssb_am(g))) return(NULL);
  8302. s7_xf_store(sc, (s7_pointer)g);
  8303. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, ssb_am_rf_sss, NULL, NULL, NULL, NULL));
  8304. }
  8305. static s7_double formant_rf_ssx(s7_scheme *sc, s7_pointer **p)
  8306. {
  8307. s7_rf_t rf1;
  8308. s7_pointer s1;
  8309. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8310. s1 = (**p); (*p)++;
  8311. rf1 = (s7_rf_t)(**p); (*p)++;
  8312. return(mus_formant_with_frequency(g, s7_slot_real_value(sc, s1, S_formant), rf1(sc, p)));
  8313. }
  8314. static s7_double formant_rf_sss(s7_scheme *sc, s7_pointer **p)
  8315. {
  8316. s7_pointer s1, s2;
  8317. mus_any *g; g = (mus_any *)(*(*p)); (*p)++;
  8318. s1 = (**p); (*p)++;
  8319. s2 = (**p); (*p)++;
  8320. return(mus_formant_with_frequency(g, s7_slot_real_value(sc, s1, S_formant), s7_slot_real_value(sc, s2, S_formant)));
  8321. }
  8322. static s7_rf_t formant_rf_3(s7_scheme *sc, s7_pointer expr)
  8323. {
  8324. mus_any *g;
  8325. int len;
  8326. len = s7_list_length(sc, expr);
  8327. if (len < 4) return(formant_rf(sc, expr));
  8328. if (len > 5) return(NULL);
  8329. g = cadr_gen(sc, expr);
  8330. if ((!g) || (!mus_is_formant(g))) return(NULL);
  8331. s7_xf_store(sc, (s7_pointer)g);
  8332. return(s7_rf_2(sc, cdr(expr), NULL, NULL, NULL, NULL, formant_rf_sss, NULL, NULL, formant_rf_ssx, NULL));
  8333. }
  8334. /* formant-bank: c g r, or v for with_inputs */
  8335. static s7_double formant_bank_rf_s(s7_scheme *sc, s7_pointer **p)
  8336. {
  8337. mus_any *bank;
  8338. s7_pointer slot;
  8339. bank = (mus_any *)(**p); (*p)++;
  8340. slot = (**p); (*p)++;
  8341. return(mus_formant_bank(bank, s7_slot_real_value(sc, slot, S_formant_bank)));
  8342. }
  8343. static s7_double formant_bank_rf_r(s7_scheme *sc, s7_pointer **p)
  8344. {
  8345. mus_any *bank;
  8346. s7_pointer slot;
  8347. bank = (mus_any *)(**p); (*p)++;
  8348. slot = (**p); (*p)++;
  8349. return(mus_formant_bank(bank, s7_number_to_real(sc, slot)));
  8350. }
  8351. static s7_double formant_bank_rf_x(s7_scheme *sc, s7_pointer **p)
  8352. {
  8353. mus_any *bank;
  8354. s7_rf_t r1;
  8355. bank = (mus_any *)(**p); (*p)++;
  8356. r1 = (s7_rf_t)(**p); (*p)++;
  8357. return(mus_formant_bank(bank, r1(sc, p)));
  8358. }
  8359. static s7_double formant_bank_rf_v(s7_scheme *sc, s7_pointer **p)
  8360. {
  8361. mus_any *bank;
  8362. s7_double *els;
  8363. bank = (mus_any *)(**p); (*p)++;
  8364. els = (s7_double *)(**p); (*p)++;
  8365. return(mus_formant_bank_with_inputs(bank, els));
  8366. }
  8367. static s7_rf_t formant_bank_rf(s7_scheme *sc, s7_pointer expr)
  8368. {
  8369. mus_any *g;
  8370. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL);
  8371. g = cadr_gen(sc, expr);
  8372. if ((g) && (mus_is_formant_bank(g)))
  8373. {
  8374. s7_pointer a1, val_sym, val;
  8375. s7_int loc;
  8376. s7_rf_t rf;
  8377. s7_xf_store(sc, (s7_pointer)g);
  8378. a1 = caddr(expr);
  8379. if (s7_is_symbol(a1))
  8380. {
  8381. s7_pointer slot;
  8382. slot = s7_slot(sc, a1);
  8383. if (slot == xen_undefined) return(NULL);
  8384. val = s7_slot_value(slot);
  8385. if (s7_is_real(val))
  8386. {
  8387. s7_xf_store(sc, (s7_pointer)slot);
  8388. return(formant_bank_rf_s);
  8389. }
  8390. if (s7_is_float_vector(val))
  8391. {
  8392. s7_xf_store(sc, (s7_pointer)s7_float_vector_elements(val));
  8393. return(formant_bank_rf_v);
  8394. }
  8395. return(NULL);
  8396. }
  8397. if (s7_is_real(a1))
  8398. {
  8399. s7_xf_store(sc, a1);
  8400. return(formant_bank_rf_r);
  8401. }
  8402. if (!s7_is_pair(a1)) return(NULL);
  8403. val_sym = car(a1);
  8404. if (!s7_is_symbol(val_sym)) return(NULL);
  8405. val = s7_symbol_value(sc, val_sym);
  8406. if (!s7_rf_function(sc, val)) return(NULL);
  8407. loc = s7_xf_store(sc, NULL);
  8408. rf = s7_rf_function(sc, val)(sc, a1);
  8409. if (!rf) return(NULL);
  8410. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8411. return(formant_bank_rf_x);
  8412. }
  8413. return(NULL);
  8414. }
  8415. static s7_double set_formant_frequency_rf_x(s7_scheme *sc, s7_pointer **p)
  8416. {
  8417. mus_any *f;
  8418. s7_rf_t r1;
  8419. f = (mus_any *)(**p); (*p)++;
  8420. r1 = (s7_rf_t)(**p); (*p)++;
  8421. return(mus_set_formant_frequency(f, r1(sc, p)));
  8422. }
  8423. static s7_rf_t set_formant_frequency_rf(s7_scheme *sc, s7_pointer expr)
  8424. {
  8425. mus_any *g;
  8426. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL);
  8427. g = cadr_gen(sc, expr);
  8428. if ((g) && (mus_is_formant(g)))
  8429. {
  8430. s7_pointer a1;
  8431. a1 = s7_caddr(expr);
  8432. if (s7_is_pair(a1))
  8433. {
  8434. s7_int loc;
  8435. s7_pointer val, val_sym;
  8436. s7_rf_t rf;
  8437. val_sym = car(a1);
  8438. if (!s7_is_symbol(val_sym)) return(NULL);
  8439. val = s7_symbol_value(sc, val_sym);
  8440. if (!s7_rf_function(sc, val)) return(NULL);
  8441. s7_xf_store(sc, (s7_pointer)g);
  8442. loc = s7_xf_store(sc, NULL);
  8443. rf = s7_rf_function(sc, val)(sc, a1);
  8444. if (!rf) return(NULL);
  8445. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8446. return(set_formant_frequency_rf_x);
  8447. }
  8448. }
  8449. return(NULL);
  8450. }
  8451. static s7_double outa_x_rf(s7_scheme *sc, s7_pointer **p)
  8452. {
  8453. s7_int ind;
  8454. s7_double val;
  8455. s7_rf_t rf;
  8456. ind = s7_slot_integer_value(**p); (*p)++;
  8457. rf = (s7_rf_t)(**p); (*p)++;
  8458. val = rf(sc, p);
  8459. out_any_2(ind, val, 0, S_outa);
  8460. return(val);
  8461. }
  8462. static s7_double outa_x_rf_checked(s7_scheme *sc, s7_pointer **p)
  8463. {
  8464. s7_pointer ind;
  8465. s7_double val;
  8466. s7_rf_t rf;
  8467. ind = s7_slot_value(**p); (*p)++;
  8468. if (!s7_is_integer(ind)) s7_wrong_type_arg_error(s7, S_outa, 1, ind, "an integer");
  8469. rf = (s7_rf_t)(**p); (*p)++;
  8470. val = rf(sc, p);
  8471. out_any_2(s7_integer(ind), val, 0, S_outa);
  8472. return(val);
  8473. }
  8474. static s7_double outa_s_rf(s7_scheme *sc, s7_pointer **p)
  8475. {
  8476. s7_double val;
  8477. s7_int ind;
  8478. ind = s7_slot_integer_value(**p); (*p)++;
  8479. val = s7_slot_real_value(sc, **p, S_outa); (*p)++;
  8480. out_any_2(ind, val, 0, S_outa);
  8481. return(val);
  8482. }
  8483. static s7_double outa_s_rf_checked(s7_scheme *sc, s7_pointer **p)
  8484. {
  8485. s7_double val;
  8486. s7_pointer ind;
  8487. ind = s7_slot_value(**p); (*p)++;
  8488. if (!s7_is_integer(ind)) s7_wrong_type_arg_error(s7, S_outa, 1, ind, "an integer");
  8489. val = s7_slot_real_value(sc, **p, S_outa); (*p)++;
  8490. out_any_2(s7_integer(ind), val, 0, S_outa);
  8491. return(val);
  8492. }
  8493. static s7_double outa_x_rf_to_mus_xen(s7_scheme *sc, s7_pointer **p)
  8494. {
  8495. s7_double val;
  8496. s7_int pos;
  8497. s7_rf_t rf;
  8498. pos = s7_slot_integer_value(**p); (*p)++;
  8499. rf = (s7_rf_t)(**p); (*p)++;
  8500. val = rf(sc, p);
  8501. if (!mus_simple_out_any_to_file(pos, val, 0, clm_output_gen))
  8502. mus_safe_out_any_to_file(pos, val, 0, clm_output_gen);
  8503. return(val);
  8504. }
  8505. static s7_double outa_s_rf_to_mus_xen(s7_scheme *sc, s7_pointer **p)
  8506. {
  8507. s7_double val;
  8508. s7_int pos;
  8509. pos = s7_slot_integer_value(**p); (*p)++;
  8510. val = s7_slot_real_value(sc, **p, S_outa); (*p)++;
  8511. if (!mus_simple_out_any_to_file(pos, val, 0, clm_output_gen))
  8512. mus_safe_out_any_to_file(pos, val, 0, clm_output_gen);
  8513. return(val);
  8514. }
  8515. static s7_double outb_x_rf(s7_scheme *sc, s7_pointer **p)
  8516. {
  8517. s7_int ind;
  8518. s7_double val;
  8519. s7_rf_t rf;
  8520. ind = s7_slot_integer_value(**p); (*p)++;
  8521. rf = (s7_rf_t)(**p); (*p)++;
  8522. val = rf(sc, p);
  8523. out_any_2(ind, val, 1, S_outb);
  8524. return(val);
  8525. }
  8526. static s7_double outb_s_rf(s7_scheme *sc, s7_pointer **p)
  8527. {
  8528. s7_int ind;
  8529. s7_double val;
  8530. ind = s7_slot_integer_value(**p); (*p)++;
  8531. val = s7_slot_real_value(sc, **p, S_outb); (*p)++;
  8532. out_any_2(ind, val, 1, S_outb);
  8533. return(val);
  8534. }
  8535. static s7_double mul_env_x_rf(s7_scheme *sc, s7_pointer **p);
  8536. static s7_double mul_env_polywave_x_rf(s7_scheme *sc, s7_pointer **p);
  8537. static s7_double outa_mul_env_x_rf(s7_scheme *sc, s7_pointer **p)
  8538. {
  8539. s7_double val;
  8540. s7_int pos;
  8541. s7_rf_t r2;
  8542. mus_any *g;
  8543. pos = s7_slot_integer_value(**p); (*p) += 3;
  8544. g = (mus_any *)(**p); (*p)++;
  8545. r2 = (s7_rf_t)(**p); (*p)++;
  8546. val = mus_env(g) * r2(sc, p);
  8547. if (!mus_simple_out_any_to_file(pos, val, 0, clm_output_gen))
  8548. mus_safe_out_any_to_file(pos, val, 0, clm_output_gen);
  8549. return(val);
  8550. }
  8551. static s7_double outa_mul_env_polywave_x_rf(s7_scheme *sc, s7_pointer **p)
  8552. {
  8553. s7_double val;
  8554. s7_int pos;
  8555. s7_rf_t r2;
  8556. mus_any *e, *o;
  8557. pos = s7_slot_integer_value(**p); (*p) += 3;
  8558. e = (mus_any *)(**p); (*p) += 2;
  8559. o = (mus_any *)(**p); (*p)++;
  8560. r2 = (s7_rf_t)(**p); (*p)++;
  8561. val = mus_env(e) * mus_polywave(o, r2(sc, p));
  8562. if (!mus_simple_out_any_to_file(pos, val, 0, clm_output_gen))
  8563. mus_safe_out_any_to_file(pos, val, 0, clm_output_gen);
  8564. return(val);
  8565. }
  8566. static s7_double outa_mul_env_polywave_env_rf(s7_scheme *sc, s7_pointer **p)
  8567. {
  8568. s7_double val;
  8569. s7_int pos;
  8570. mus_any *e, *o, *fe;
  8571. pos = s7_slot_integer_value(**p); (*p) += 3;
  8572. e = (mus_any *)(**p); (*p) += 2;
  8573. o = (mus_any *)(**p); (*p) += 2;
  8574. fe = (mus_any *)(**p); (*p)++;
  8575. val = mus_env(e) * mus_polywave(o, mus_env(fe));
  8576. if (!mus_simple_out_any_to_file(pos, val, 0, clm_output_gen))
  8577. mus_safe_out_any_to_file(pos, val, 0, clm_output_gen);
  8578. return(val);
  8579. }
  8580. static s7_rf_t out_rf(s7_scheme *sc, s7_pointer expr, int chan)
  8581. {
  8582. s7_pointer ind_sym, ind, ind_slot, val_sym, val, val_expr;
  8583. s7_rf_t rf = NULL;
  8584. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL);
  8585. ind_sym = s7_cadr(expr);
  8586. if (!s7_is_symbol(ind_sym)) return(NULL);
  8587. ind_slot = s7_slot(sc, ind_sym);
  8588. if (ind_slot == xen_undefined) return(NULL);
  8589. ind = s7_slot_value(ind_slot);
  8590. if (!s7_is_integer(ind)) return(NULL);
  8591. if (ind < 0) return(NULL);
  8592. s7_xf_store(sc, ind_slot);
  8593. val_expr = s7_caddr(expr);
  8594. if (s7_is_symbol(val_expr))
  8595. {
  8596. s7_pointer slot;
  8597. slot = s7_slot(sc, val_expr);
  8598. if (slot == xen_undefined) return(NULL);
  8599. s7_xf_store(sc, slot);
  8600. }
  8601. else
  8602. {
  8603. s7_int loc;
  8604. if (!s7_is_pair(val_expr)) return(NULL);
  8605. val_sym = car(val_expr);
  8606. if (!s7_is_symbol(val_sym)) return(NULL);
  8607. val = s7_symbol_value(sc, val_sym);
  8608. if (!s7_rf_function(sc, val)) return(NULL);
  8609. loc = s7_xf_store(sc, NULL);
  8610. rf = s7_rf_function(sc, val)(sc, val_expr);
  8611. if (!rf) return(NULL);
  8612. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8613. }
  8614. if (s7_is_stepper(ind_slot))
  8615. {
  8616. if (chan == 0)
  8617. {
  8618. if (out_any_2 == safe_out_any_2_to_mus_xen)
  8619. {
  8620. if (rf == mul_env_polywave_x_rf)
  8621. {
  8622. s7_pointer fm;
  8623. fm = s7_caddr(s7_caddr(val_expr));
  8624. if ((s7_is_pair(fm)) &&
  8625. (s7_car(fm) == env_symbol) &&
  8626. (s7_is_symbol(s7_cadr(fm))))
  8627. return(outa_mul_env_polywave_env_rf);
  8628. return(outa_mul_env_polywave_x_rf);
  8629. }
  8630. if (rf == mul_env_x_rf)
  8631. return(outa_mul_env_x_rf);
  8632. return((rf) ? outa_x_rf_to_mus_xen : outa_s_rf_to_mus_xen);
  8633. }
  8634. return((rf) ? outa_x_rf : outa_s_rf);
  8635. }
  8636. return((rf) ? outb_x_rf : outb_s_rf);
  8637. }
  8638. if (chan == 0)
  8639. return((rf) ? outa_x_rf_checked : outa_s_rf_checked);
  8640. return(NULL);
  8641. }
  8642. static s7_rf_t outa_rf(s7_scheme *sc, s7_pointer expr)
  8643. {
  8644. return(out_rf(sc, expr, 0));
  8645. }
  8646. static s7_rf_t outb_rf(s7_scheme *sc, s7_pointer expr)
  8647. {
  8648. return(out_rf(sc, expr, 1));
  8649. }
  8650. static s7_double sample_to_file_rf_g(s7_scheme *sc, s7_pointer **p)
  8651. {
  8652. /* (sample->file obj samp chan[always int] val) */
  8653. s7_int ind, chan;
  8654. mus_any *lc;
  8655. s7_double val;
  8656. s7_rf_t rf;
  8657. lc = (mus_any *)(**p); (*p)++;
  8658. ind = s7_slot_integer_value(**p); (*p)++;
  8659. chan = s7_integer(**p); (*p)++;
  8660. rf = (s7_rf_t)(**p); (*p)++;
  8661. val = rf(sc, p);
  8662. mus_sample_to_file(lc, ind, chan, val);
  8663. return(val);
  8664. }
  8665. static s7_rf_t sample_to_file_rf(s7_scheme *sc, s7_pointer expr)
  8666. {
  8667. s7_pointer ind_sym, ind, ind_slot, chan, val_sym, val, val_expr;
  8668. s7_int loc;
  8669. s7_rf_t rf;
  8670. mus_any *lc;
  8671. lc = cadr_gen(sc, expr);
  8672. if ((!lc) || (!mus_is_sample_to_file(lc))) return(NULL);
  8673. ind_sym = s7_caddr(expr);
  8674. if (!s7_is_symbol(ind_sym)) return(NULL);
  8675. ind_slot = s7_slot(sc, ind_sym);
  8676. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  8677. ind = s7_slot_value(ind_slot);
  8678. if (!s7_is_integer(ind)) return(NULL);
  8679. chan = s7_cadddr(expr);
  8680. if (!s7_is_integer(chan)) return(NULL);
  8681. val_expr = s7_car(s7_cddddr(expr));
  8682. if (!s7_is_pair(val_expr)) return(NULL);
  8683. val_sym = s7_car(val_expr);
  8684. if (!s7_is_symbol(val_sym)) return(NULL);
  8685. val = s7_symbol_value(sc, val_sym);
  8686. if (!s7_rf_function(sc, val)) return(NULL);
  8687. s7_xf_store(sc, (s7_pointer)lc);
  8688. s7_xf_store(sc, ind_slot);
  8689. s7_xf_store(sc, chan);
  8690. loc = s7_xf_store(sc, NULL);
  8691. rf = s7_rf_function(sc, val)(sc, val_expr);
  8692. if (!rf) return(NULL);
  8693. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8694. return(sample_to_file_rf_g);
  8695. }
  8696. static s7_double locsig_rf_x(s7_scheme *sc, s7_pointer **p)
  8697. {
  8698. s7_int ind;
  8699. mus_any *lc;
  8700. s7_double val;
  8701. s7_rf_t rf;
  8702. lc = (mus_any *)(**p); (*p)++;
  8703. ind = s7_slot_integer_value(**p); (*p)++;
  8704. rf = (s7_rf_t)(**p); (*p)++;
  8705. val = rf(sc, p);
  8706. mus_locsig(lc, ind, val);
  8707. return(val);
  8708. }
  8709. static s7_double locsig_rf_x_checked(s7_scheme *sc, s7_pointer **p)
  8710. {
  8711. s7_pointer ind;
  8712. mus_any *lc;
  8713. s7_double val;
  8714. s7_rf_t rf;
  8715. lc = (mus_any *)(**p); (*p)++;
  8716. ind = s7_slot_value(**p); (*p)++;
  8717. if (!s7_is_integer(ind)) s7_wrong_type_arg_error(s7, S_locsig, 2, ind, "an integer");
  8718. rf = (s7_rf_t)(**p); (*p)++;
  8719. val = rf(sc, p);
  8720. mus_locsig(lc, s7_integer(ind), val);
  8721. return(val);
  8722. }
  8723. static s7_double fm_violin_rf(s7_scheme *sc, s7_pointer **p);
  8724. static s7_double locsig_fm_violin_rf(s7_scheme *sc, s7_pointer **p)
  8725. {
  8726. s7_int ind;
  8727. mus_any *lc, *e, *o, *fp, *a;
  8728. s7_double val, vib;
  8729. lc = (mus_any *)(**p); (*p)++;
  8730. ind = s7_slot_integer_value(**p); (*p) += 3;
  8731. /* fm_violin_rf */
  8732. e = (mus_any *)(**p); (*p) += 2;
  8733. o = (mus_any *)(**p); (*p) += 2;
  8734. vib = s7_slot_real_value(sc, **p, S_oscil); (*p) += 3;
  8735. a = (mus_any *)(**p); (*p) += 2;
  8736. fp = (mus_any *)(**p); (*p)++;
  8737. val = mus_env(e) * mus_oscil_fm(o, vib + (mus_env(a) * mus_polywave(fp, vib)));
  8738. mus_locsig(lc, ind, val);
  8739. return(val);
  8740. }
  8741. static s7_rf_t locsig_rf(s7_scheme *sc, s7_pointer expr)
  8742. {
  8743. s7_pointer ind_sym, ind, ind_slot, val_sym, val, val_expr;
  8744. s7_int loc;
  8745. s7_rf_t rf;
  8746. mus_any *lc;
  8747. lc = cadr_gen(sc, expr);
  8748. if ((!lc) || (!mus_is_locsig(lc))) return(NULL);
  8749. ind_sym = s7_caddr(expr);
  8750. if (!s7_is_symbol(ind_sym)) return(NULL);
  8751. ind_slot = s7_slot(sc, ind_sym);
  8752. if (ind_slot == xen_undefined) return(NULL);
  8753. ind = s7_slot_value(ind_slot);
  8754. if (!s7_is_integer(ind)) return(NULL);
  8755. val_expr = s7_cadddr(expr);
  8756. if (!s7_is_pair(val_expr)) return(NULL);
  8757. val_sym = s7_car(val_expr);
  8758. if (!s7_is_symbol(val_sym)) return(NULL);
  8759. val = s7_symbol_value(sc, val_sym);
  8760. if (!s7_rf_function(sc, val)) return(NULL);
  8761. s7_xf_store(sc, (s7_pointer)lc);
  8762. s7_xf_store(sc, ind_slot);
  8763. loc = s7_xf_store(sc, NULL);
  8764. rf = s7_rf_function(sc, val)(sc, val_expr);
  8765. if (!rf) return(NULL);
  8766. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8767. if (rf == fm_violin_rf)
  8768. return(locsig_fm_violin_rf);
  8769. return((s7_is_stepper(ind_slot)) ? locsig_rf_x : locsig_rf_x_checked);
  8770. }
  8771. static s7_double move_sound_rf_g(s7_scheme *sc, s7_pointer **p)
  8772. {
  8773. s7_int ind;
  8774. mus_any *lc;
  8775. s7_double val;
  8776. s7_rf_t rf;
  8777. lc = (mus_any *)(**p); (*p)++;
  8778. ind = s7_slot_integer_value(**p); (*p)++;
  8779. rf = (s7_rf_t)(**p); (*p)++;
  8780. val = rf(sc, p);
  8781. mus_move_sound(lc, ind, val);
  8782. return(val);
  8783. }
  8784. static s7_rf_t move_sound_rf(s7_scheme *sc, s7_pointer expr)
  8785. {
  8786. s7_pointer ind_sym, ind, ind_slot, val_sym, val, val_expr;
  8787. s7_int loc;
  8788. s7_rf_t rf;
  8789. mus_any *lc;
  8790. lc = cadr_gen(sc, expr);
  8791. if ((!lc) || (!mus_is_move_sound(lc))) return(NULL);
  8792. ind_sym = s7_caddr(expr);
  8793. if (!s7_is_symbol(ind_sym)) return(NULL);
  8794. ind_slot = s7_slot(sc, ind_sym);
  8795. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  8796. ind = s7_slot_value(ind_slot);
  8797. if (!s7_is_integer(ind)) return(NULL);
  8798. val_expr = s7_cadddr(expr);
  8799. if (!s7_is_pair(val_expr)) return(NULL);
  8800. val_sym = s7_car(val_expr);
  8801. if (!s7_is_symbol(val_sym)) return(NULL);
  8802. val = s7_symbol_value(sc, val_sym);
  8803. if (!s7_rf_function(sc, val)) return(NULL);
  8804. s7_xf_store(sc, (s7_pointer)lc);
  8805. s7_xf_store(sc, ind_slot);
  8806. loc = s7_xf_store(sc, NULL);
  8807. rf = s7_rf_function(sc, val)(sc, val_expr);
  8808. if (!rf) return(NULL);
  8809. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8810. return(move_sound_rf_g);
  8811. }
  8812. static s7_double out_bank_rf_1(s7_scheme *sc, s7_pointer **p)
  8813. {
  8814. s7_double val;
  8815. s7_rf_t rf;
  8816. s7_int loc;
  8817. mus_any *g1;
  8818. g1 = (mus_any *)(**p); (*p)++;
  8819. loc = s7_slot_integer_value(**p); (*p)++;
  8820. rf = (s7_rf_t)(**p); (*p)++;
  8821. val = rf(sc, p);
  8822. if (mus_is_delay(g1))
  8823. out_any_2(loc, mus_delay_unmodulated_noz(g1, val), 0, "out-bank");
  8824. else out_any_2(loc, mus_all_pass_unmodulated_noz(g1, val), 0, "out-bank");
  8825. return(val);
  8826. }
  8827. static s7_double mul_s_comb_bank_x_rf(s7_scheme *sc, s7_pointer **p);
  8828. static s7_double out_bank_rf_comb_bank_1(s7_scheme *sc, s7_pointer **p)
  8829. {
  8830. s7_double val, s1;
  8831. s7_rf_t rf;
  8832. s7_int loc;
  8833. mus_any *g1, *o;
  8834. g1 = (mus_any *)(**p); (*p)++;
  8835. loc = s7_slot_integer_value(**p); (*p) += 2;
  8836. s1 = s7_slot_real_value(sc, **p, "out-bank"); (*p) += 2;
  8837. o = (mus_any *)(**p); (*p)++;
  8838. rf = (s7_rf_t)(**p); (*p)++;
  8839. val = s1 * mus_comb_bank(o, rf(sc, p));
  8840. if (mus_is_delay(g1))
  8841. out_any_2(loc, mus_delay_unmodulated_noz(g1, val), 0, "out-bank");
  8842. else out_any_2(loc, mus_all_pass_unmodulated_noz(g1, val), 0, "out-bank");
  8843. return(val);
  8844. }
  8845. static s7_double out_bank_rf_comb_bank_2(s7_scheme *sc, s7_pointer **p)
  8846. {
  8847. s7_double val, s1;
  8848. s7_rf_t rf;
  8849. s7_int loc;
  8850. mus_any *g1, *g2, *o;
  8851. g1 = (mus_any *)(**p); (*p)++;
  8852. g2 = (mus_any *)(**p); (*p)++;
  8853. loc = s7_slot_integer_value(**p); (*p) += 2;
  8854. s1 = s7_slot_real_value(sc, **p, "out-bank"); (*p) += 2;
  8855. o = (mus_any *)(**p); (*p)++;
  8856. rf = (s7_rf_t)(**p); (*p)++;
  8857. val = s1 * mus_comb_bank(o, rf(sc, p));
  8858. if (mus_is_delay(g1))
  8859. {
  8860. out_any_2(loc, mus_delay_unmodulated_noz(g1, val), 0, "out-bank");
  8861. out_any_2(loc, mus_delay_unmodulated_noz(g2, val), 1, "out-bank");
  8862. }
  8863. else
  8864. {
  8865. out_any_2(loc, mus_all_pass_unmodulated_noz(g1, val), 0, "out-bank");
  8866. out_any_2(loc, mus_all_pass_unmodulated_noz(g2, val), 1, "out-bank");
  8867. }
  8868. return(val);
  8869. }
  8870. static s7_double out_bank_rf_2(s7_scheme *sc, s7_pointer **p)
  8871. {
  8872. s7_double val;
  8873. s7_rf_t rf;
  8874. s7_int loc;
  8875. mus_any *g1, *g2;
  8876. g1 = (mus_any *)(**p); (*p)++;
  8877. g2 = (mus_any *)(**p); (*p)++;
  8878. loc = s7_slot_integer_value(**p); (*p)++;
  8879. rf = (s7_rf_t)(**p); (*p)++;
  8880. val = rf(sc, p);
  8881. if (mus_is_delay(g1))
  8882. {
  8883. out_any_2(loc, mus_delay_unmodulated_noz(g1, val), 0, "out-bank");
  8884. out_any_2(loc, mus_delay_unmodulated_noz(g2, val), 1, "out-bank");
  8885. }
  8886. else
  8887. {
  8888. out_any_2(loc, mus_all_pass_unmodulated_noz(g1, val), 0, "out-bank");
  8889. out_any_2(loc, mus_all_pass_unmodulated_noz(g2, val), 1, "out-bank");
  8890. }
  8891. return(val);
  8892. }
  8893. static s7_double out_bank_rf_4(s7_scheme *sc, s7_pointer **p)
  8894. {
  8895. s7_double val;
  8896. s7_rf_t rf;
  8897. s7_int loc;
  8898. mus_any *g1, *g2, *g3, *g4;
  8899. g1 = (mus_any *)(**p); (*p)++;
  8900. g2 = (mus_any *)(**p); (*p)++;
  8901. g3 = (mus_any *)(**p); (*p)++;
  8902. g4 = (mus_any *)(**p); (*p)++;
  8903. loc = s7_slot_integer_value(**p); (*p)++;
  8904. rf = (s7_rf_t)(**p); (*p)++;
  8905. val = rf(sc, p);
  8906. if (mus_is_delay(g1))
  8907. {
  8908. out_any_2(loc, mus_delay_unmodulated_noz(g1, val), 0, "out-bank");
  8909. out_any_2(loc, mus_delay_unmodulated_noz(g2, val), 1, "out-bank");
  8910. out_any_2(loc, mus_delay_unmodulated_noz(g3, val), 2, "out-bank");
  8911. out_any_2(loc, mus_delay_unmodulated_noz(g4, val), 3, "out-bank");
  8912. }
  8913. else
  8914. {
  8915. out_any_2(loc, mus_all_pass_unmodulated_noz(g1, val), 0, "out-bank");
  8916. out_any_2(loc, mus_all_pass_unmodulated_noz(g2, val), 1, "out-bank");
  8917. out_any_2(loc, mus_all_pass_unmodulated_noz(g3, val), 2, "out-bank");
  8918. out_any_2(loc, mus_all_pass_unmodulated_noz(g4, val), 3, "out-bank");
  8919. }
  8920. return(val);
  8921. }
  8922. static s7_rf_t out_bank_rf(s7_scheme *sc, s7_pointer expr)
  8923. {
  8924. s7_pointer ind_sym, ind, ind_slot, val_sym, val, val_expr, filts;
  8925. s7_int loc;
  8926. s7_rf_t rf;
  8927. s7_int i, len;
  8928. mus_xen *gn;
  8929. mus_any *g;
  8930. s7_pointer *els;
  8931. filts = s7_cadr(expr);
  8932. if (!s7_is_symbol(filts)) return(NULL);
  8933. filts = s7_symbol_value(sc, filts);
  8934. if (!s7_is_vector(filts)) return(NULL);
  8935. len = s7_vector_length(filts);
  8936. if ((len != 1) && (len != 2) && (len != 4)) return(NULL);
  8937. els = s7_vector_elements(filts);
  8938. gn = (mus_xen *)s7_object_value_checked(els[0], mus_xen_tag);
  8939. if (!gn) return(NULL);
  8940. g = gn->gen;
  8941. if ((!mus_is_delay(g)) && (!mus_is_all_pass(g))) return(NULL);
  8942. for (i = 0; i < len; i++)
  8943. s7_xf_store(sc, (s7_pointer)((mus_xen *)s7_object_value(els[i]))->gen);
  8944. ind_sym = s7_caddr(expr);
  8945. if (!s7_is_symbol(ind_sym)) return(NULL);
  8946. ind_slot = s7_slot(sc, ind_sym);
  8947. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  8948. ind = s7_slot_value(ind_slot);
  8949. if (!s7_is_integer(ind)) return(NULL);
  8950. s7_xf_store(sc, ind_slot);
  8951. val_expr = s7_cadddr(expr);
  8952. if (!s7_is_pair(val_expr)) return(NULL);
  8953. val_sym = s7_car(val_expr);
  8954. if (!s7_is_symbol(val_sym)) return(NULL);
  8955. val = s7_symbol_value(sc, val_sym);
  8956. if (!s7_rf_function(sc, val)) return(NULL);
  8957. loc = s7_xf_store(sc, NULL);
  8958. rf = s7_rf_function(sc, val)(sc, val_expr);
  8959. if (!rf) return(NULL);
  8960. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  8961. if (len == 1)
  8962. {
  8963. if (rf == mul_s_comb_bank_x_rf)
  8964. return(out_bank_rf_comb_bank_1);
  8965. return(out_bank_rf_1);
  8966. }
  8967. if (len == 2)
  8968. {
  8969. if (rf == mul_s_comb_bank_x_rf)
  8970. return(out_bank_rf_comb_bank_2);
  8971. return(out_bank_rf_2);
  8972. }
  8973. return(out_bank_rf_4);
  8974. }
  8975. static s7_double file_to_sample_rf_ss(s7_scheme *sc, s7_pointer **p)
  8976. {
  8977. s7_int ind;
  8978. mus_any *stream;
  8979. stream = (mus_any *)(**p); (*p)++;
  8980. ind = s7_slot_integer_value(**p); (*p)++;
  8981. return(mus_file_to_sample(stream, ind, 0));
  8982. }
  8983. static s7_rf_t file_to_sample_rf(s7_scheme *sc, s7_pointer expr)
  8984. {
  8985. s7_pointer ind_sym, ind_slot, ind, sym, o;
  8986. mus_xen *gn;
  8987. sym = s7_cadr(expr);
  8988. if (!s7_is_symbol(sym)) return(NULL);
  8989. o = s7_symbol_value(sc, sym);
  8990. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  8991. if (!gn) return(NULL);
  8992. s7_xf_store(sc, (s7_pointer)(gn->gen));
  8993. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL);
  8994. ind_sym = s7_caddr(expr);
  8995. if (!s7_is_symbol(ind_sym)) return(NULL);
  8996. ind_slot = s7_slot(sc, ind_sym);
  8997. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  8998. ind = s7_slot_value(ind_slot);
  8999. if (!s7_is_integer(ind)) return(NULL);
  9000. s7_xf_store(sc, ind_slot);
  9001. return(file_to_sample_rf_ss);
  9002. }
  9003. static s7_pointer file_to_frample_pf_sss(s7_scheme *sc, s7_pointer **p)
  9004. {
  9005. /* (file->frample gen loc fv) -> fv */
  9006. s7_pointer fv;
  9007. s7_int ind;
  9008. mus_any *stream;
  9009. stream = (mus_any *)(**p); (*p)++;
  9010. ind = s7_slot_integer_value(**p); (*p)++;
  9011. fv = s7_slot_value(**p); (*p)++;
  9012. mus_file_to_frample(stream, ind, s7_float_vector_elements(fv));
  9013. return(fv);
  9014. }
  9015. static s7_pf_t file_to_frample_pf(s7_scheme *sc, s7_pointer expr)
  9016. {
  9017. s7_pointer ind_sym, ind_slot, fv_slot, fv_sym, sym, o;
  9018. mus_xen *gn;
  9019. if (!s7_is_null(sc, s7_cddddr(expr))) return(NULL);
  9020. sym = s7_cadr(expr);
  9021. if (!s7_is_symbol(sym)) return(NULL);
  9022. o = s7_symbol_value(sc, sym);
  9023. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  9024. if (!gn) return(NULL);
  9025. s7_xf_store(sc, (s7_pointer)(gn->gen));
  9026. ind_sym = s7_caddr(expr);
  9027. if (!s7_is_symbol(ind_sym)) return(NULL);
  9028. ind_slot = s7_slot(sc, ind_sym);
  9029. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  9030. if (!s7_is_integer(s7_slot_value(ind_slot))) return(NULL);
  9031. s7_xf_store(sc, ind_slot);
  9032. fv_sym = s7_cadddr(expr);
  9033. if (!s7_is_symbol(fv_sym)) return(NULL);
  9034. fv_slot = s7_slot(sc, fv_sym);
  9035. if (fv_slot == xen_undefined) return(NULL);
  9036. if (!s7_is_float_vector(s7_slot_value(fv_slot))) return(NULL);
  9037. s7_xf_store(sc, fv_slot);
  9038. return(file_to_frample_pf_sss);
  9039. }
  9040. static s7_pointer frample_to_file_pf_sss(s7_scheme *sc, s7_pointer **p)
  9041. {
  9042. /* (frample->file gen loc fv) -> fv */
  9043. s7_pointer fv;
  9044. s7_int ind;
  9045. mus_any *stream;
  9046. stream = (mus_any *)(**p); (*p)++;
  9047. ind = s7_slot_integer_value(**p); (*p)++;
  9048. fv = s7_slot_value(**p); (*p)++;
  9049. mus_frample_to_file(stream, ind, s7_float_vector_elements(fv));
  9050. return(fv);
  9051. }
  9052. static s7_pointer frample_to_file_pf_ssx(s7_scheme *sc, s7_pointer **p)
  9053. {
  9054. /* (frample->file gen loc fv) -> fv */
  9055. s7_pointer fv;
  9056. s7_int ind;
  9057. s7_pf_t pf;
  9058. mus_any *stream;
  9059. stream = (mus_any *)(**p); (*p)++;
  9060. ind = s7_slot_integer_value(**p); (*p)++;
  9061. pf = (s7_pf_t)(**p); (*p)++;
  9062. fv = pf(sc, p);
  9063. mus_frample_to_file(stream, ind, s7_float_vector_elements(fv));
  9064. return(fv);
  9065. }
  9066. static s7_pf_t frample_to_file_pf(s7_scheme *sc, s7_pointer expr)
  9067. {
  9068. s7_pointer ind_sym, ind_slot, fv_slot, fv_sym, sym, o;
  9069. mus_xen *gn;
  9070. if (!s7_is_null(sc, s7_cddddr(expr))) return(NULL);
  9071. sym = s7_cadr(expr);
  9072. if (!s7_is_symbol(sym)) return(NULL);
  9073. o = s7_symbol_value(sc, sym);
  9074. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  9075. if (!gn) return(NULL);
  9076. s7_xf_store(sc, (s7_pointer)(gn->gen));
  9077. ind_sym = s7_caddr(expr);
  9078. if (!s7_is_symbol(ind_sym)) return(NULL);
  9079. ind_slot = s7_slot(sc, ind_sym);
  9080. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  9081. if (!s7_is_integer(s7_slot_value(ind_slot))) return(NULL);
  9082. s7_xf_store(sc, ind_slot);
  9083. fv_sym = s7_cadddr(expr);
  9084. if (s7_is_symbol(fv_sym))
  9085. {
  9086. fv_slot = s7_slot(sc, fv_sym);
  9087. if (fv_slot == xen_undefined) return(NULL);
  9088. if (!s7_is_float_vector(s7_slot_value(fv_slot))) return(NULL);
  9089. s7_xf_store(sc, fv_slot);
  9090. return(frample_to_file_pf_sss);
  9091. }
  9092. if (s7_is_pair(fv_sym))
  9093. {
  9094. s7_pp_t pp;
  9095. s7_pf_t pf;
  9096. s7_int loc;
  9097. pp = s7_pf_function(sc, s7_symbol_value(sc, s7_car(fv_sym)));
  9098. if (!pp) return(NULL);
  9099. loc = s7_xf_store(sc, NULL);
  9100. pf = pp(sc, fv_sym);
  9101. if (!pf) return(NULL);
  9102. s7_xf_store_at(sc, loc, (s7_pointer)pf);
  9103. return(frample_to_file_pf_ssx);
  9104. }
  9105. return(NULL);
  9106. }
  9107. static s7_pointer frample_to_frample_pf_all_s(s7_scheme *sc, s7_pointer **p)
  9108. {
  9109. s7_pointer matrix, in_data, in_chans, out_data, out_chans;
  9110. matrix = s7_slot_value(**p); (*p)++;
  9111. in_data = s7_slot_value(**p); (*p)++;
  9112. in_chans = s7_slot_value(**p); (*p)++;
  9113. out_data = s7_slot_value(**p); (*p)++;
  9114. out_chans = s7_slot_value(**p); (*p)++;
  9115. mus_frample_to_frample(s7_float_vector_elements(matrix), (int)sqrt(s7_vector_length(matrix)),
  9116. s7_float_vector_elements(in_data), s7_integer(in_chans),
  9117. s7_float_vector_elements(out_data), s7_integer(out_chans));
  9118. return(out_data);
  9119. }
  9120. static s7_pf_t frample_to_frample_pf(s7_scheme *sc, s7_pointer expr)
  9121. {
  9122. s7_int i;
  9123. s7_pointer p;
  9124. for (i = 0, p = s7_cdr(expr); (s7_is_pair(p)) && (i < 5); i++, p = s7_cdr(p))
  9125. {
  9126. if (s7_is_symbol(s7_car(p)))
  9127. {
  9128. s7_pointer slot;
  9129. slot = s7_slot(sc, s7_car(p));
  9130. if (slot == xen_undefined) return(NULL);
  9131. s7_xf_store(sc, slot);
  9132. }
  9133. else return(NULL);
  9134. }
  9135. if ((i == 5) && (s7_is_null(sc, p)))
  9136. return(frample_to_frample_pf_all_s);
  9137. return(NULL);
  9138. }
  9139. static s7_double ina_rf_ss(s7_scheme *sc, s7_pointer **p)
  9140. {
  9141. s7_int ind;
  9142. mus_any *stream;
  9143. ind = s7_slot_integer_value(**p); (*p)++;
  9144. stream = (mus_any *)(**p); (*p)++;
  9145. return(mus_in_any(ind, 0, stream));
  9146. }
  9147. static s7_double ina_rf_ss_checked(s7_scheme *sc, s7_pointer **p)
  9148. {
  9149. s7_pointer ind;
  9150. mus_any *stream;
  9151. ind = s7_slot_value(**p); (*p)++;
  9152. if (!s7_is_integer(ind)) s7_wrong_type_arg_error(s7, S_ina, 1, ind, "an integer");
  9153. stream = (mus_any *)(**p); (*p)++;
  9154. return(mus_in_any(s7_integer(ind), 0, stream));
  9155. }
  9156. static s7_double inb_rf_ss(s7_scheme *sc, s7_pointer **p)
  9157. {
  9158. s7_int ind;
  9159. mus_any *stream;
  9160. ind = s7_slot_integer_value(**p); (*p)++;
  9161. stream = (mus_any *)(**p); (*p)++;
  9162. return(mus_in_any(ind, 1, stream));
  9163. }
  9164. static s7_double inb_rf_ss_checked(s7_scheme *sc, s7_pointer **p)
  9165. {
  9166. s7_pointer ind;
  9167. mus_any *stream;
  9168. ind = s7_slot_value(**p); (*p)++;
  9169. if (!s7_is_integer(ind)) s7_wrong_type_arg_error(s7, S_inb, 1, ind, "an integer");
  9170. stream = (mus_any *)(**p); (*p)++;
  9171. return(mus_in_any(s7_integer(ind), 1, stream));
  9172. }
  9173. static s7_double ina_rf_fv(s7_scheme *sc, s7_pointer **p)
  9174. {
  9175. s7_pointer fv;
  9176. s7_int index;
  9177. index = s7_slot_integer_value(**p); (*p)++;
  9178. fv = (**p); (*p)++;
  9179. if ((index >= 0) && (index < s7_vector_length(fv)))
  9180. return(s7_float_vector_elements(fv)[index]);
  9181. return(0.0);
  9182. }
  9183. static s7_rf_t in_rf(s7_scheme *sc, s7_pointer expr, int chan)
  9184. {
  9185. s7_pointer ind_sym, ind_slot, ind, sym, o;
  9186. mus_xen *gn;
  9187. if (!s7_is_null(sc, s7_cdddr(expr))) return(NULL);
  9188. ind_sym = s7_cadr(expr);
  9189. if (!s7_is_symbol(ind_sym)) return(NULL);
  9190. ind_slot = s7_slot(sc, ind_sym);
  9191. if (ind_slot == xen_undefined) return(NULL);
  9192. ind = s7_slot_value(ind_slot);
  9193. if (!s7_is_integer(ind)) return(NULL);
  9194. s7_xf_store(sc, ind_slot);
  9195. sym = s7_caddr(expr);
  9196. if (!s7_is_symbol(sym)) return(NULL);
  9197. o = s7_symbol_value(sc, sym);
  9198. if (s7_is_float_vector(o))
  9199. {
  9200. if ((chan == 0) &&
  9201. (s7_is_stepper(ind_slot)))
  9202. {
  9203. s7_xf_store(sc, o);
  9204. return(ina_rf_fv);
  9205. }
  9206. return(NULL);
  9207. }
  9208. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  9209. if (!gn) return(NULL);
  9210. s7_xf_store(sc, (s7_pointer)(gn->gen));
  9211. if (s7_is_stepper(ind_slot))
  9212. {
  9213. if (chan == 0)
  9214. return(ina_rf_ss);
  9215. return(inb_rf_ss);
  9216. }
  9217. if (chan == 0)
  9218. return(ina_rf_ss_checked);
  9219. return(inb_rf_ss_checked);
  9220. }
  9221. static s7_rf_t ina_rf(s7_scheme *sc, s7_pointer expr)
  9222. {
  9223. return(in_rf(sc, expr, 0));
  9224. }
  9225. static s7_rf_t inb_rf(s7_scheme *sc, s7_pointer expr)
  9226. {
  9227. return(in_rf(sc, expr, 1));
  9228. }
  9229. static s7_double in_any_rf_srs(s7_scheme *sc, s7_pointer **p)
  9230. {
  9231. s7_int ind, chan;
  9232. mus_any *stream;
  9233. ind = s7_slot_integer_value(**p); (*p)++;
  9234. chan = s7_integer(**p); (*p)++;
  9235. stream = (mus_any *)(**p); (*p)++;
  9236. return(mus_in_any(ind, chan, stream));
  9237. }
  9238. static s7_rf_t in_any_rf(s7_scheme *sc, s7_pointer expr)
  9239. {
  9240. s7_pointer ind_sym, ind_slot, ind, sym, o, chan;
  9241. mus_xen *gn;
  9242. if (!s7_is_null(sc, s7_cddddr(expr))) return(NULL);
  9243. ind_sym = s7_cadr(expr);
  9244. if (!s7_is_symbol(ind_sym)) return(NULL);
  9245. ind_slot = s7_slot(sc, ind_sym);
  9246. if ((ind_slot == xen_undefined) || (!s7_is_stepper(ind_slot))) return(NULL);
  9247. ind = s7_slot_value(ind_slot);
  9248. if (!s7_is_integer(ind)) return(NULL);
  9249. s7_xf_store(sc, ind_slot);
  9250. chan = s7_caddr(expr);
  9251. if (!s7_is_integer(chan)) return(NULL);
  9252. s7_xf_store(sc, chan);
  9253. sym = s7_cadddr(expr);
  9254. if (!s7_is_symbol(sym)) return(NULL);
  9255. o = s7_symbol_value(sc, sym);
  9256. gn = (mus_xen *)s7_object_value_checked(o, mus_xen_tag);
  9257. if (!gn) return(NULL);
  9258. s7_xf_store(sc, (s7_pointer)(gn->gen));
  9259. return(in_any_rf_srs);
  9260. }
  9261. #define RF2_TO_RF(CName, Rfnc) \
  9262. static s7_double CName ## _rf_r2(s7_scheme *sc, s7_pointer **p) \
  9263. { \
  9264. s7_rf_t f; \
  9265. s7_double x, y; \
  9266. f = (s7_rf_t)(**p); (*p)++; x = f(sc, p); \
  9267. f = (s7_rf_t)(**p); (*p)++; y = f(sc, p); \
  9268. return(Rfnc); \
  9269. } \
  9270. static s7_rf_t CName ## _rf(s7_scheme *sc, s7_pointer expr) \
  9271. { \
  9272. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_null(sc, s7_cdddr(expr))) && \
  9273. (s7_arg_to_rf(sc, s7_cadr(expr))) && \
  9274. (s7_arg_to_rf(sc, s7_caddr(expr)))) \
  9275. return(CName ## _rf_r2); \
  9276. return(NULL); \
  9277. }
  9278. #define RF_0(Call) \
  9279. static s7_double Call ## _rf_0(s7_scheme *sc, s7_pointer **p) \
  9280. { \
  9281. return(mus_ ## Call()); \
  9282. } \
  9283. static s7_rf_t Call ## _rf(s7_scheme *sc, s7_pointer expr) \
  9284. { \
  9285. if (!s7_is_null(sc, s7_cdr(expr))) return(NULL); \
  9286. return(Call ## _rf_0); \
  9287. }
  9288. RF_0(srate)
  9289. #define RF_1(Call) \
  9290. static s7_double Call ## _rf_s(s7_scheme *sc, s7_pointer **p) \
  9291. { \
  9292. s7_pointer slot; \
  9293. slot = (**p); (*p)++; \
  9294. return(mus_ ## Call(s7_slot_real_value(sc, slot, #Call))); \
  9295. } \
  9296. static s7_double Call ## _rf_c(s7_scheme *sc, s7_pointer **p) \
  9297. { \
  9298. s7_pointer slot; \
  9299. slot = (**p); (*p)++; \
  9300. return(mus_ ## Call(s7_number_to_real(sc, slot))); \
  9301. } \
  9302. static s7_double Call ## _rf_r(s7_scheme *sc, s7_pointer **p) \
  9303. { \
  9304. s7_rf_t r; \
  9305. r = (s7_rf_t)(**p); (*p)++; \
  9306. return(mus_ ## Call(r(sc, p))); \
  9307. } \
  9308. static s7_rf_t Call ## _rf(s7_scheme *sc, s7_pointer expr) \
  9309. { \
  9310. return(s7_rf_1(sc, expr, Call ## _rf_c, Call ## _rf_s, Call ## _rf_r)); \
  9311. }
  9312. RF_1(odd_weight)
  9313. RF_1(even_weight)
  9314. RF_1(hz_to_radians)
  9315. RF_1(radians_to_hz)
  9316. RF_1(db_to_linear)
  9317. RF_1(linear_to_db)
  9318. RF_1(radians_to_degrees)
  9319. RF_1(degrees_to_radians)
  9320. RF_1(random)
  9321. RF2_TO_RF(contrast_enhancement, mus_contrast_enhancement(x, y))
  9322. RF2_TO_RF(odd_multiple, mus_odd_multiple(x, y))
  9323. RF2_TO_RF(even_multiple, mus_even_multiple(x, y))
  9324. RF2_TO_RF(ring_modulate, x * y)
  9325. static s7_double polynomial_rf_ss(s7_scheme *sc, s7_pointer **p)
  9326. {
  9327. s7_pointer s1;
  9328. s7_double s2;
  9329. s1 = s7_slot_value(**p); (*p)++;
  9330. s2 = s7_slot_real_value(sc, **p, "polynomial"); (*p)++;
  9331. return(mus_polynomial(s7_float_vector_elements(s1), s2, s7_vector_length(s1)));
  9332. }
  9333. static s7_double polynomial_rf_sx(s7_scheme *sc, s7_pointer **p)
  9334. {
  9335. s7_pointer s1;
  9336. s7_rf_t r1;
  9337. s1 = s7_slot_value(**p); (*p)++;
  9338. r1 = (s7_rf_t)(**p); (*p)++;
  9339. return(mus_polynomial(s7_float_vector_elements(s1), r1(sc, p), s7_vector_length(s1)));
  9340. }
  9341. static s7_rf_t polynomial_rf(s7_scheme *sc, s7_pointer expr)
  9342. {
  9343. if ((s7_is_symbol(s7_cadr(expr))) &&
  9344. (s7_is_float_vector(s7_symbol_value(sc, s7_cadr(expr)))))
  9345. return(s7_rf_2(sc, expr, NULL, NULL, NULL, NULL, polynomial_rf_ss, NULL, NULL, polynomial_rf_sx, NULL));
  9346. return(NULL);
  9347. }
  9348. static s7_double pink_noise_rf_v(s7_scheme *sc, s7_pointer **p)
  9349. {
  9350. s7_pointer s1;
  9351. s1 = s7_slot_value(**p); (*p)++;
  9352. return(mus_pink_noise(s1));
  9353. }
  9354. static s7_rf_t pink_noise_rf(s7_scheme *sc, s7_pointer expr)
  9355. {
  9356. if (s7_is_symbol(s7_cadr(expr)))
  9357. {
  9358. s7_pointer slot;
  9359. slot = s7_slot(sc, s7_cadr(expr));
  9360. if (s7_is_float_vector(s7_slot_value(slot)))
  9361. {
  9362. s7_xf_store(sc, slot);
  9363. return(pink_noise_rf_v);
  9364. }
  9365. }
  9366. return(NULL);
  9367. }
  9368. static s7_double piano_noise_rf_vr(s7_scheme *sc, s7_pointer **p)
  9369. {
  9370. s7_pointer s1;
  9371. s7_double s2;
  9372. s1 = s7_slot_value(**p); (*p)++;
  9373. s2 = s7_slot_real_value(sc, **p, "piano-noise"); (*p)++;
  9374. return(piano_noise(s7_int_vector_elements(s1), s2));
  9375. }
  9376. static s7_rf_t piano_noise_rf(s7_scheme *sc, s7_pointer expr)
  9377. {
  9378. if ((s7_is_symbol(s7_cadr(expr))) &&
  9379. (s7_is_symbol(s7_caddr(expr))))
  9380. {
  9381. s7_pointer slot1, slot2;
  9382. slot1 = s7_slot(sc, s7_cadr(expr));
  9383. slot2 = s7_slot(sc, s7_caddr(expr));
  9384. if ((s7_is_int_vector(s7_slot_value(slot1))) &&
  9385. (s7_is_real(s7_slot_value(slot2))))
  9386. {
  9387. s7_xf_store(sc, slot1);
  9388. s7_xf_store(sc, slot2);
  9389. return(piano_noise_rf_vr);
  9390. }
  9391. }
  9392. return(NULL);
  9393. }
  9394. static s7_double array_interp_rf_sxr(s7_scheme *sc, s7_pointer **p)
  9395. {
  9396. s7_pointer s1;
  9397. s7_int c2;
  9398. s7_rf_t r1;
  9399. s7_double x;
  9400. s1 = s7_slot_value(**p); (*p)++;
  9401. r1 = (s7_rf_t)(**p); (*p)++;
  9402. x = r1(sc, p);
  9403. c2 = s7_integer(**p); (*p)++;
  9404. return(mus_array_interp(s7_float_vector_elements(s1), x, c2));
  9405. }
  9406. static s7_double array_interp_rf_sxs(s7_scheme *sc, s7_pointer **p)
  9407. {
  9408. s7_pointer s1;
  9409. s7_int s2;
  9410. s7_rf_t r1;
  9411. s7_double x;
  9412. s1 = s7_slot_value(**p); (*p)++;
  9413. r1 = (s7_rf_t)(**p); (*p)++;
  9414. x = r1(sc, p);
  9415. s2 = s7_slot_integer_value(**p); (*p)++;
  9416. return(mus_array_interp(s7_float_vector_elements(s1), x, s2));
  9417. }
  9418. static s7_rf_t array_interp_rf(s7_scheme *sc, s7_pointer expr)
  9419. {
  9420. if (s7_is_symbol(s7_cadr(expr)))
  9421. {
  9422. s7_pointer rst, fv;
  9423. rst = cdr(expr);
  9424. fv = s7_slot(sc, s7_car(rst));
  9425. if ((fv != xen_undefined) &&
  9426. (s7_is_float_vector(s7_slot_value(fv))))
  9427. {
  9428. if ((!s7_is_null(sc, s7_cddr(rst))) &&
  9429. (s7_is_null(sc, s7_cdddr(rst))))
  9430. {
  9431. s7_xf_store(sc, fv);
  9432. return(s7_rf_2(sc, rst, NULL, NULL, array_interp_rf_sxr, NULL, NULL, array_interp_rf_sxs, NULL, NULL, NULL));
  9433. }
  9434. }
  9435. }
  9436. return(NULL);
  9437. }
  9438. static s7_double am_rf_rsx(s7_scheme *sc, s7_pointer **p)
  9439. {
  9440. s7_double c1, c2;
  9441. s7_rf_t r1;
  9442. c1 = s7_number_to_real(sc, **p); (*p)++;
  9443. c2 = s7_slot_real_value(sc, **p, "amplitude-modulation"); (*p)++;
  9444. r1 = (s7_rf_t)(**p); (*p)++;
  9445. return(mus_amplitude_modulate(c1, c2, r1(sc, p)));
  9446. }
  9447. static s7_rf_t am_rf(s7_scheme *sc, s7_pointer expr)
  9448. {
  9449. s7_pointer a1, a2, a3;
  9450. a1 = s7_cadr(expr);
  9451. a2 = s7_caddr(expr);
  9452. a3 = s7_cadddr(expr);
  9453. if ((s7_is_real(a1)) &&
  9454. (s7_is_symbol(a2)) &&
  9455. (s7_is_pair(a3)))
  9456. {
  9457. s7_rp_t rp;
  9458. s7_rf_t rf;
  9459. s7_int loc;
  9460. s7_pointer sym, val;
  9461. s7_xf_store(sc, a1);
  9462. val = s7_slot(sc, a2);
  9463. if (val == xen_undefined) return(NULL);
  9464. s7_xf_store(sc, val);
  9465. sym = car(a3);
  9466. if (!s7_is_symbol(sym)) return(NULL);
  9467. val = s7_symbol_value(sc, sym);
  9468. rp = s7_rf_function(sc, val);
  9469. if (!rp) return(NULL);
  9470. loc = s7_xf_store(sc, NULL);
  9471. rf = rp(sc, a3);
  9472. if (!rf) return(NULL);
  9473. s7_xf_store_at(sc, loc, (s7_pointer)rf);
  9474. return(am_rf_rsx);
  9475. }
  9476. return(NULL);
  9477. }
  9478. static s7_double mul_env_x_rf(s7_scheme *sc, s7_pointer **p)
  9479. {
  9480. s7_rf_t r2;
  9481. mus_any *g;
  9482. (*p)++;
  9483. g = (mus_any *)(**p); (*p)++;
  9484. r2 = (s7_rf_t)(**p); (*p)++;
  9485. return(mus_env(g) * r2(sc, p));
  9486. }
  9487. static s7_double mul_env_oscil_x_rf(s7_scheme *sc, s7_pointer **p)
  9488. {
  9489. s7_rf_t r2;
  9490. mus_any *e, *o;
  9491. (*p)++;
  9492. e = (mus_any *)(**p); (*p) += 2;
  9493. o = (mus_any *)(**p); (*p)++;
  9494. r2 = (s7_rf_t)(**p); (*p)++;
  9495. return(mus_env(e) * mus_oscil_fm(o, r2(sc, p)));
  9496. }
  9497. static s7_double fm_violin_rf(s7_scheme *sc, s7_pointer **p)
  9498. {
  9499. mus_any *e, *o, *fp, *a;
  9500. s7_double vib;
  9501. (*p)++;
  9502. e = (mus_any *)(**p); (*p) += 2;
  9503. o = (mus_any *)(**p); (*p) += 2;
  9504. vib = s7_slot_real_value(sc, **p, S_oscil); (*p) += 3;
  9505. a = (mus_any *)(**p); (*p) += 2;
  9506. fp = (mus_any *)(**p); (*p)++;
  9507. return(mus_env(e) * mus_oscil_fm(o, vib + (mus_env(a) * mus_polywave(fp, vib))));
  9508. }
  9509. static s7_double mul_env_polywave_x_rf(s7_scheme *sc, s7_pointer **p)
  9510. {
  9511. s7_rf_t r2;
  9512. mus_any *e, *o;
  9513. (*p)++;
  9514. e = (mus_any *)(**p); (*p) += 2;
  9515. o = (mus_any *)(**p); (*p)++;
  9516. r2 = (s7_rf_t)(**p); (*p)++;
  9517. return(mus_env(e) * mus_polywave(o, r2(sc, p)));
  9518. }
  9519. static s7_double mul_env_polywave_s_rf(s7_scheme *sc, s7_pointer **p)
  9520. {
  9521. s7_double s1;
  9522. mus_any *e, *o;
  9523. (*p)++;
  9524. e = (mus_any *)(**p); (*p) += 2;
  9525. o = (mus_any *)(**p); (*p)++;
  9526. s1 = s7_slot_real_value(sc, **p, S_polywave); (*p)++;
  9527. return(mus_env(e) * mus_polywave(o, s1));
  9528. }
  9529. static s7_double mul_s_comb_bank_x_rf(s7_scheme *sc, s7_pointer **p)
  9530. {
  9531. s7_rf_t r1;
  9532. s7_double s1;
  9533. mus_any *o;
  9534. s1 = s7_slot_real_value(sc, **p, S_comb_bank); (*p) += 2;
  9535. o = (mus_any *)(**p); (*p)++;
  9536. r1 = (s7_rf_t)(**p); (*p)++;
  9537. return(s1 * mus_comb_bank(o, r1(sc, p)));
  9538. }
  9539. static s7_rp_t initial_multiply_rf;
  9540. static s7_rf_t clm_multiply_rf(s7_scheme *sc, s7_pointer expr)
  9541. {
  9542. s7_rf_t f;
  9543. f = initial_multiply_rf(sc, expr);
  9544. if ((f) &&
  9545. (s7_is_null(sc, s7_cdddr(expr))))
  9546. {
  9547. s7_pointer a1, a2;
  9548. a1 = s7_cadr(expr);
  9549. a2 = s7_caddr(expr);
  9550. if (s7_is_pair(a1))
  9551. {
  9552. if ((s7_car(a1) == env_symbol) &&
  9553. (s7_is_pair(a2)) &&
  9554. (s7_is_symbol(s7_cadr(a1))) &&
  9555. (s7_is_null(sc, s7_cdddr(expr))))
  9556. {
  9557. if ((s7_is_symbol(s7_cadr(a2))) &&
  9558. (s7_is_null(sc, s7_cdddr(a2))))
  9559. {
  9560. if (s7_is_pair(s7_caddr(a2)))
  9561. {
  9562. if (s7_car(a2) == oscil_symbol)
  9563. {
  9564. s7_pointer fm;
  9565. fm = s7_caddr(a2);
  9566. if ((s7_car(fm) == add_symbol) &&
  9567. (s7_is_symbol(s7_cadr(fm))) &&
  9568. (s7_is_pair(s7_caddr(fm))))
  9569. {
  9570. s7_pointer vib_sym;
  9571. vib_sym = s7_cadr(fm);
  9572. fm = s7_caddr(fm);
  9573. if ((s7_car(fm) == multiply_symbol) &&
  9574. (s7_is_pair(s7_cadr(fm))) &&
  9575. (s7_caadr(fm) == env_symbol) &&
  9576. (s7_is_pair(s7_caddr(fm))) &&
  9577. (s7_is_null(sc, s7_cdddr(fm))))
  9578. {
  9579. fm = s7_caddr(fm);
  9580. if ((s7_car(fm) == polywave_symbol) &&
  9581. (s7_is_symbol(s7_cadr(fm))) &&
  9582. (s7_is_symbol(s7_caddr(fm))) &&
  9583. (s7_caddr(fm) == vib_sym))
  9584. return(fm_violin_rf);
  9585. }
  9586. }
  9587. return(mul_env_oscil_x_rf);
  9588. }
  9589. else
  9590. {
  9591. if (s7_car(a2) == polywave_symbol)
  9592. return(mul_env_polywave_x_rf);
  9593. }
  9594. }
  9595. if (s7_is_symbol(s7_caddr(a2)))
  9596. {
  9597. if (s7_car(a2) == polywave_symbol)
  9598. return(mul_env_polywave_s_rf);
  9599. }
  9600. }
  9601. return(mul_env_x_rf);
  9602. }
  9603. }
  9604. else
  9605. {
  9606. if ((s7_is_symbol(a1)) &&
  9607. (s7_is_pair(a2)) &&
  9608. (s7_is_symbol(s7_cadr(a2))) &&
  9609. (s7_car(a2) == comb_bank_symbol) &&
  9610. (s7_is_pair(s7_caddr(a2))) &&
  9611. (s7_is_null(sc, s7_cdddr(a2))))
  9612. return(mul_s_comb_bank_x_rf);
  9613. }
  9614. }
  9615. return(f);
  9616. }
  9617. static s7_double add_env_ri_rf(s7_scheme *sc, s7_pointer **p)
  9618. {
  9619. mus_any *e, *o;
  9620. (*p)++;
  9621. e = (mus_any *)(**p); (*p) += 2;
  9622. o = (mus_any *)(**p); (*p)++;
  9623. return(mus_env(e) + mus_rand_interp_unmodulated(o));
  9624. }
  9625. static s7_double add_tri_ri_rf(s7_scheme *sc, s7_pointer **p)
  9626. {
  9627. mus_any *e, *o;
  9628. (*p)++; /* triangle-wave */
  9629. e = (mus_any *)(**p); (*p) += 2; /* rand-interp */
  9630. o = (mus_any *)(**p); (*p)++;
  9631. return(mus_triangle_wave_unmodulated(e) + mus_rand_interp_unmodulated(o));
  9632. }
  9633. static s7_rp_t initial_add_rf;
  9634. static s7_rf_t clm_add_rf(s7_scheme *sc, s7_pointer expr)
  9635. {
  9636. s7_rf_t f;
  9637. f = initial_add_rf(sc, expr);
  9638. if (f)
  9639. {
  9640. s7_pointer a1, a2;
  9641. a1 = s7_cadr(expr);
  9642. a2 = s7_caddr(expr);
  9643. if ((s7_is_pair(a1)) &&
  9644. (s7_is_pair(a2)) &&
  9645. (s7_car(a2) == rand_interp_symbol) &&
  9646. (s7_is_symbol(s7_cadr(a1))) &&
  9647. (s7_is_symbol(s7_cadr(a2))) &&
  9648. (s7_is_null(sc, s7_cddr(a1))) &&
  9649. (s7_is_null(sc, s7_cddr(a2))) &&
  9650. (s7_is_null(sc, s7_cdddr(expr))))
  9651. {
  9652. if (s7_car(a1) == triangle_wave_symbol)
  9653. return(add_tri_ri_rf);
  9654. if (s7_car(a1) == env_symbol)
  9655. return(add_env_ri_rf);
  9656. }
  9657. }
  9658. return(f);
  9659. }
  9660. static s7_double env_rf_v(s7_scheme *sc, s7_pointer **p)
  9661. {
  9662. s7_pointer v;
  9663. mus_xen *gn;
  9664. s7_Int ind;
  9665. v = (**p); (*p)++;
  9666. ind = s7_slot_integer_value(**p); (*p)++;
  9667. if ((ind < 0) || (ind >= s7_vector_length(v)))
  9668. s7_out_of_range_error(s7, "vector-ref", 2, s7_make_integer(sc, ind), "must fit in vector");
  9669. gn = (mus_xen *)s7_object_value_checked(s7_vector_elements(v)[ind], mus_xen_tag);
  9670. return(mus_env(gn->gen));
  9671. }
  9672. static s7_rf_t env_rf_1(s7_scheme *sc, s7_pointer expr)
  9673. {
  9674. if ((s7_is_pair(expr)) &&
  9675. (s7_is_pair(cdr(expr))) &&
  9676. (s7_is_pair(cadr(expr))))
  9677. {
  9678. s7_pointer a1;
  9679. a1 = s7_cadr(expr);
  9680. if ((s7_car(a1) == vector_ref_symbol) &&
  9681. (s7_is_symbol(s7_cadr(a1))) &&
  9682. (s7_is_symbol(s7_caddr(a1))) &&
  9683. (s7_is_null(sc, s7_cdddr(a1))))
  9684. {
  9685. s7_pointer s1, s2, v, ind;
  9686. s7_pointer *els;
  9687. int i, vlen;
  9688. s1 = s7_cadr(a1);
  9689. s2 = s7_caddr(a1);
  9690. v = s7_symbol_value(sc, s1);
  9691. if (!s7_is_vector(v)) return(NULL);
  9692. vlen = s7_vector_length(v);
  9693. els = s7_vector_elements(v);
  9694. for (i= 0; i < vlen; i++)
  9695. {
  9696. mus_xen *gn;
  9697. gn = (mus_xen *)s7_object_value_checked(els[i], mus_xen_tag);
  9698. if ((!gn) || (!(gn->gen)) || (!mus_is_env(gn->gen))) return(NULL);
  9699. }
  9700. ind = s7_slot(sc, s2);
  9701. if ((ind == xen_undefined) || (!s7_is_integer(s7_slot_value(ind)))) return(NULL);
  9702. s7_xf_store(sc, v);
  9703. s7_xf_store(sc, ind);
  9704. return(env_rf_v);
  9705. }
  9706. }
  9707. return(env_rf(sc, expr));
  9708. }
  9709. static s7_double chebyshev_t_rf_a(s7_scheme *sc, s7_pointer **p)
  9710. {
  9711. s7_rf_t rf;
  9712. s7_pf_t pf;
  9713. s7_double x;
  9714. s7_pointer fv;
  9715. rf = (s7_rf_t)(**p); (*p)++;
  9716. x = rf(sc, p);
  9717. pf = (s7_pf_t)(**p); (*p)++;
  9718. fv = pf(sc, p);
  9719. return(mus_chebyshev_t_sum(x, s7_vector_length(fv), s7_float_vector_elements(fv)));
  9720. }
  9721. static s7_rf_t chebyshev_t_rf(s7_scheme *sc, s7_pointer expr)
  9722. {
  9723. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_null(sc, s7_cdddr(expr))) &&
  9724. (s7_arg_to_rf(sc, s7_cadr(expr))) &&
  9725. (s7_arg_to_pf(sc, s7_caddr(expr))))
  9726. return(chebyshev_t_rf_a);
  9727. return(NULL);
  9728. }
  9729. static s7_double chebyshev_u_rf_a(s7_scheme *sc, s7_pointer **p)
  9730. {
  9731. s7_rf_t rf;
  9732. s7_pf_t pf;
  9733. s7_double x;
  9734. s7_pointer fv;
  9735. rf = (s7_rf_t)(**p); (*p)++;
  9736. x = rf(sc, p);
  9737. pf = (s7_pf_t)(**p); (*p)++;
  9738. fv = pf(sc, p);
  9739. return(mus_chebyshev_u_sum(x, s7_vector_length(fv), s7_float_vector_elements(fv)));
  9740. }
  9741. static s7_rf_t chebyshev_u_rf(s7_scheme *sc, s7_pointer expr)
  9742. {
  9743. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_null(sc, s7_cdddr(expr))) &&
  9744. (s7_arg_to_rf(sc, s7_cadr(expr))) &&
  9745. (s7_arg_to_pf(sc, s7_caddr(expr))))
  9746. return(chebyshev_u_rf_a);
  9747. return(NULL);
  9748. }
  9749. static s7_double chebyshev_tu_rf_a(s7_scheme *sc, s7_pointer **p)
  9750. {
  9751. s7_rf_t rf;
  9752. s7_pf_t pf;
  9753. s7_double x;
  9754. s7_pointer t, u;
  9755. rf = (s7_rf_t)(**p); (*p)++;
  9756. x = rf(sc, p);
  9757. pf = (s7_pf_t)(**p); (*p)++;
  9758. t = pf(sc, p);
  9759. pf = (s7_pf_t)(**p); (*p)++;
  9760. u = pf(sc, p);
  9761. return(mus_chebyshev_tu_sum(x, s7_vector_length(t), s7_float_vector_elements(t), s7_float_vector_elements(u)));
  9762. }
  9763. static s7_rf_t chebyshev_tu_rf(s7_scheme *sc, s7_pointer expr)
  9764. {
  9765. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_pair(s7_cdddr(expr))) && (s7_is_null(sc, s7_cddddr(expr))) &&
  9766. (s7_arg_to_rf(sc, s7_cadr(expr))) &&
  9767. (s7_arg_to_pf(sc, s7_caddr(expr))) &&
  9768. (s7_arg_to_pf(sc, s7_cadddr(expr))))
  9769. return(chebyshev_tu_rf_a);
  9770. return(NULL);
  9771. }
  9772. #define PF2_TO_RF(CName, Cfnc) \
  9773. static s7_double CName ## _rf_a(s7_scheme *sc, s7_pointer **p) \
  9774. { \
  9775. s7_pf_t f; \
  9776. s7_pointer x, y; \
  9777. f = (s7_pf_t)(**p); (*p)++; \
  9778. x = f(sc, p); \
  9779. f = (s7_pf_t)(**p); (*p)++; \
  9780. y = f(sc, p); \
  9781. return(Cfnc); \
  9782. } \
  9783. static s7_rf_t CName ## _rf(s7_scheme *sc, s7_pointer expr) \
  9784. { \
  9785. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))) && (s7_is_null(sc, s7_cdddr(expr))) && \
  9786. (s7_arg_to_pf(sc, s7_cadr(expr))) && \
  9787. (s7_arg_to_pf(sc, s7_caddr(expr)))) \
  9788. return(CName ## _rf_a); \
  9789. return(NULL); \
  9790. }
  9791. static s7_double c_dot_product(s7_scheme *sc, s7_pointer x, s7_pointer y)
  9792. {
  9793. s7_int len, lim;
  9794. len = s7_vector_length(x);
  9795. lim = s7_vector_length(y);
  9796. if (lim < len) len = lim;
  9797. if (len == 0) return(0.0);
  9798. return(mus_dot_product(s7_float_vector_elements(x), s7_float_vector_elements(y), len));
  9799. }
  9800. PF2_TO_RF(dot_product, c_dot_product(sc, x, y))
  9801. static s7_pointer mus_fft_pf_i2(s7_scheme *sc, s7_pointer **p)
  9802. {
  9803. s7_pf_t pf;
  9804. s7_if_t xf;
  9805. s7_pointer rl, im;
  9806. s7_int size, dir;
  9807. pf = (s7_pf_t)(**p); (*p)++; rl = pf(sc, p);
  9808. pf = (s7_pf_t)(**p); (*p)++; im = pf(sc, p);
  9809. xf = (s7_if_t)(**p); (*p)++; size = xf(sc, p);
  9810. xf = (s7_if_t)(**p); (*p)++; dir = xf(sc, p);
  9811. mus_fft(s7_float_vector_elements(rl), s7_float_vector_elements(im), size, dir);
  9812. return(rl);
  9813. }
  9814. static s7_pointer mus_fft_pf_i1(s7_scheme *sc, s7_pointer **p)
  9815. {
  9816. s7_pf_t pf;
  9817. s7_if_t xf;
  9818. s7_pointer rl, im;
  9819. s7_int size;
  9820. pf = (s7_pf_t)(**p); (*p)++; rl = pf(sc, p);
  9821. pf = (s7_pf_t)(**p); (*p)++; im = pf(sc, p);
  9822. xf = (s7_if_t)(**p); (*p)++; size = xf(sc, p);
  9823. mus_fft(s7_float_vector_elements(rl), s7_float_vector_elements(im), size, 1);
  9824. return(rl);
  9825. }
  9826. static s7_pointer mus_fft_pf_i0(s7_scheme *sc, s7_pointer **p)
  9827. {
  9828. s7_pf_t pf;
  9829. s7_pointer rl, im;
  9830. pf = (s7_pf_t)(**p); (*p)++; rl = pf(sc, p);
  9831. pf = (s7_pf_t)(**p); (*p)++; im = pf(sc, p);
  9832. mus_fft(s7_float_vector_elements(rl), s7_float_vector_elements(im), s7_vector_length(rl), 1);
  9833. return(rl);
  9834. }
  9835. static s7_pf_t mus_fft_pf(s7_scheme *sc, s7_pointer expr)
  9836. {
  9837. if ((s7_is_pair(s7_cdr(expr))) && (s7_is_pair(s7_cddr(expr))))
  9838. {
  9839. s7_pointer trailers;
  9840. if (!s7_arg_to_pf(sc, s7_cadr(expr))) return(NULL);
  9841. if (!s7_arg_to_pf(sc, s7_caddr(expr))) return(NULL);
  9842. trailers = s7_cdddr(expr);
  9843. if (s7_is_null(sc, trailers)) return(mus_fft_pf_i0);
  9844. if (!s7_arg_to_if(sc, s7_car(trailers))) return(NULL);
  9845. if (s7_is_null(sc, s7_cdr(trailers))) return(mus_fft_pf_i1);
  9846. if (!s7_arg_to_if(sc, s7_cadr(trailers))) return(NULL);
  9847. if (!s7_is_null(sc, s7_cddr(trailers))) return(NULL);
  9848. return(mus_fft_pf_i2);
  9849. }
  9850. return(NULL);
  9851. }
  9852. #define MG_RF(Method, Func) \
  9853. static s7_double mus_ ## Method ## _rf_g(s7_scheme *sc, s7_pointer **p) \
  9854. { \
  9855. mus_any *g; g = (mus_any *)(**p); (*p)++; \
  9856. return(Func(g)); \
  9857. } \
  9858. static s7_rf_t mus_ ## Method ## _rf(s7_scheme *sc, s7_pointer expr) \
  9859. { \
  9860. mus_any *g; \
  9861. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  9862. g = cadr_gen(sc, expr); \
  9863. if (g) {s7_xf_store(sc, (s7_pointer)g); return(mus_ ## Method ## _rf_g);} \
  9864. return(NULL); \
  9865. }
  9866. #define MG_IF(Method, Func) \
  9867. static s7_int mus_ ## Method ## _if_g(s7_scheme *sc, s7_pointer **p) \
  9868. { \
  9869. mus_any *g; g = (mus_any *)(**p); (*p)++; \
  9870. return(Func(g)); \
  9871. } \
  9872. static s7_if_t mus_ ## Method ## _if(s7_scheme *sc, s7_pointer expr) \
  9873. { \
  9874. mus_any *g; \
  9875. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  9876. g = cadr_gen(sc, expr); \
  9877. if (g) {s7_xf_store(sc, (s7_pointer)g); return(mus_ ## Method ## _if_g);} \
  9878. return(NULL); \
  9879. }
  9880. #define PF_PF(Method, Func) \
  9881. static s7_pointer mus_ ## Method ## _pf_g(s7_scheme *sc, s7_pointer **p) \
  9882. { \
  9883. s7_pf_t f; \
  9884. s7_pointer g; \
  9885. f = (s7_pf_t)(**p); (*p)++; \
  9886. g = f(sc, p); \
  9887. return(Func(g)); \
  9888. } \
  9889. static s7_pf_t mus_ ## Method ## _pf(s7_scheme *sc, s7_pointer expr) \
  9890. { \
  9891. if (!s7_is_null(sc, s7_cddr(expr))) return(NULL); \
  9892. if (s7_arg_to_pf(sc, s7_cadr(expr))) return(mus_ ## Method ## _pf_g); \
  9893. return(NULL); \
  9894. }
  9895. MG_RF(scaler, mus_scaler)
  9896. MG_RF(phase, mus_phase)
  9897. MG_RF(frequency, mus_frequency)
  9898. MG_RF(offset, mus_offset)
  9899. MG_RF(width, mus_width)
  9900. MG_RF(increment, mus_increment)
  9901. MG_RF(feedforward, mus_feedforward)
  9902. MG_RF(feedback, mus_feedback)
  9903. MG_IF(length, mus_length)
  9904. MG_IF(order, mus_order)
  9905. MG_IF(location, mus_location)
  9906. MG_IF(channel, mus_channel)
  9907. MG_IF(channels, mus_channels)
  9908. MG_IF(ramp, mus_ramp)
  9909. MG_IF(hop, mus_hop)
  9910. PF_PF(data, g_mus_data)
  9911. PF_PF(reset, g_mus_reset)
  9912. #if 0
  9913. MG_RFIF(xcoeff, mus_xcoeff)
  9914. MG_RFIF(ycoeff, mus_ycoeff)
  9915. MG_PF(xcoeffs, c_mus_xcoeffs) -- x|ycoeffs are complicated and may involve wrapper creation
  9916. MG_PF(ycoeffs, c_mus_ycoeffs)
  9917. MG_PF(file_name, c_mus_file_name) -- requires c->xen string creation
  9918. MG_PF(copy, c_mus_copy) -- allocation
  9919. #endif
  9920. #endif /* gmp */
  9921. static void init_choosers(s7_scheme *sc)
  9922. {
  9923. #if (!WITH_GMP)
  9924. s7_pointer f;
  9925. #endif
  9926. env_symbol = s7_make_symbol(sc, S_env);
  9927. comb_bank_symbol = s7_make_symbol(sc, S_comb_bank);
  9928. vector_ref_symbol = s7_make_symbol(sc, "vector-ref");
  9929. polywave_symbol = s7_make_symbol(sc, S_polywave);
  9930. triangle_wave_symbol = s7_make_symbol(sc, S_triangle_wave);
  9931. rand_interp_symbol = s7_make_symbol(sc, S_rand_interp);
  9932. oscil_symbol = s7_make_symbol(sc, S_oscil);
  9933. multiply_symbol = s7_make_symbol(sc, "*");
  9934. add_symbol = s7_make_symbol(sc, "+");
  9935. quote_symbol = s7_make_symbol(sc, "quote");
  9936. cos_symbol = s7_make_symbol(sc, "cos");
  9937. mus_copy_symbol = s7_make_symbol(sc, "mus-copy");
  9938. copy_function = s7_name_to_value(sc, "copy");
  9939. sym_frequency = s7_make_symbol(sc, S_mus_frequency);
  9940. sym_phase = s7_make_symbol(sc, S_mus_phase);
  9941. sym_scaler = s7_make_symbol(sc, S_mus_scaler);
  9942. sym_increment = s7_make_symbol(sc, S_mus_increment);
  9943. sym_width = s7_make_symbol(sc, S_mus_width);
  9944. sym_offset = s7_make_symbol(sc, S_mus_offset);
  9945. sym_feedforward = s7_make_symbol(sc, S_mus_feedforward);
  9946. sym_feedback = s7_make_symbol(sc, S_mus_feedback);
  9947. #if (!WITH_GMP)
  9948. f = s7_name_to_value(sc, "*");
  9949. initial_multiply_rf = s7_rf_function(sc, f);
  9950. s7_rf_set_function(f, clm_multiply_rf);
  9951. f = s7_name_to_value(sc, "+");
  9952. initial_add_rf = s7_rf_function(sc, f);
  9953. s7_rf_set_function(f, clm_add_rf);
  9954. s7_rf_set_function(s7_name_to_value(sc, S_outa), outa_rf);
  9955. s7_rf_set_function(s7_name_to_value(sc, S_outb), outb_rf);
  9956. s7_rf_set_function(s7_name_to_value(sc, S_ina), ina_rf);
  9957. s7_rf_set_function(s7_name_to_value(sc, S_file_to_sample), file_to_sample_rf);
  9958. s7_pf_set_function(s7_name_to_value(sc, S_file_to_frample), file_to_frample_pf);
  9959. s7_pf_set_function(s7_name_to_value(sc, S_frample_to_file), frample_to_file_pf);
  9960. s7_pf_set_function(s7_name_to_value(sc, S_frample_to_frample), frample_to_frample_pf);
  9961. s7_rf_set_function(s7_name_to_value(sc, S_oscil), oscil_rf_3);
  9962. s7_rf_set_function(s7_name_to_value(sc, S_polywave), polywave_rf);
  9963. s7_rf_set_function(s7_name_to_value(sc, S_wave_train), wave_train_rf);
  9964. s7_rf_set_function(s7_name_to_value(sc, S_granulate), granulate_rf);
  9965. s7_rf_set_function(s7_name_to_value(sc, S_ncos), ncos_rf);
  9966. s7_rf_set_function(s7_name_to_value(sc, S_nrxycos), nrxycos_rf);
  9967. s7_rf_set_function(s7_name_to_value(sc, S_env), env_rf_1);
  9968. s7_rf_set_function(s7_name_to_value(sc, S_readin), readin_rf);
  9969. s7_rf_set_function(s7_name_to_value(sc, S_one_pole), one_pole_rf);
  9970. s7_rf_set_function(s7_name_to_value(sc, S_moving_average), moving_average_rf);
  9971. s7_rf_set_function(s7_name_to_value(sc, S_moving_max), moving_max_rf);
  9972. s7_rf_set_function(s7_name_to_value(sc, S_fir_filter), fir_filter_rf);
  9973. s7_rf_set_function(s7_name_to_value(sc, S_triangle_wave), triangle_wave_rf);
  9974. s7_rf_set_function(s7_name_to_value(sc, S_pulse_train), pulse_train_rf);
  9975. s7_rf_set_function(s7_name_to_value(sc, S_rand_interp), rand_interp_rf);
  9976. s7_rf_set_function(s7_name_to_value(sc, S_formant), formant_rf_3);
  9977. s7_rf_set_function(s7_name_to_value(sc, S_one_pole_all_pass), one_pole_all_pass_rf);
  9978. s7_rf_set_function(s7_name_to_value(sc, S_delay), delay_rf_3);
  9979. s7_rf_set_function(s7_name_to_value(sc, S_formant_bank), formant_bank_rf);
  9980. s7_rf_set_function(s7_name_to_value(sc, S_oscil_bank), oscil_bank_rf);
  9981. s7_rf_set_function(s7_name_to_value(sc, S_rand), rand_rf);
  9982. s7_rf_set_function(s7_name_to_value(sc, S_filter), filter_rf);
  9983. s7_rf_set_function(s7_name_to_value(sc, S_table_lookup), table_lookup_rf);
  9984. s7_rf_set_function(s7_name_to_value(sc, S_src), src_rf);
  9985. s7_rf_set_function(s7_name_to_value(sc, S_sawtooth_wave), sawtooth_wave_rf);
  9986. s7_rf_set_function(s7_name_to_value(sc, S_inb), inb_rf);
  9987. s7_rf_set_function(s7_name_to_value(sc, S_in_any), in_any_rf);
  9988. s7_rf_set_function(s7_name_to_value(sc, S_polynomial), polynomial_rf);
  9989. s7_rf_set_function(s7_name_to_value(sc, S_pink_noise), pink_noise_rf);
  9990. s7_rf_set_function(s7_name_to_value(sc, S_piano_noise), piano_noise_rf);
  9991. s7_rf_set_function(s7_name_to_value(sc, S_nsin), nsin_rf);
  9992. s7_rf_set_function(s7_name_to_value(sc, S_nrxysin), nrxysin_rf);
  9993. s7_rf_set_function(s7_name_to_value(sc, S_rxyksin), rxyksin_rf);
  9994. s7_rf_set_function(s7_name_to_value(sc, S_rxykcos), rxykcos_rf);
  9995. s7_rf_set_function(s7_name_to_value(sc, S_tap), tap_rf);
  9996. s7_rf_set_function(s7_name_to_value(sc, S_comb), comb_rf_3);
  9997. s7_rf_set_function(s7_name_to_value(sc, S_comb_bank), comb_bank_rf);
  9998. s7_rf_set_function(s7_name_to_value(sc, S_notch), notch_rf_3);
  9999. s7_rf_set_function(s7_name_to_value(sc, S_two_zero), two_zero_rf);
  10000. s7_rf_set_function(s7_name_to_value(sc, S_one_zero), one_zero_rf);
  10001. s7_rf_set_function(s7_name_to_value(sc, S_two_pole), two_pole_rf);
  10002. s7_rf_set_function(s7_name_to_value(sc, S_moving_norm), moving_norm_rf);
  10003. s7_rf_set_function(s7_name_to_value(sc, S_iir_filter), iir_filter_rf);
  10004. s7_rf_set_function(s7_name_to_value(sc, S_square_wave), square_wave_rf);
  10005. s7_rf_set_function(s7_name_to_value(sc, S_firmant), firmant_rf);
  10006. s7_rf_set_function(s7_name_to_value(sc, S_all_pass), all_pass_rf_3);
  10007. s7_rf_set_function(s7_name_to_value(sc, S_all_pass_bank), all_pass_bank_rf);
  10008. s7_rf_set_function(s7_name_to_value(sc, S_polyshape), polyshape_rf);
  10009. s7_rf_set_function(s7_name_to_value(sc, S_pulsed_env), pulsed_env_rf);
  10010. s7_rf_set_function(s7_name_to_value(sc, S_ssb_am), ssb_am_rf_3);
  10011. s7_rf_set_function(s7_name_to_value(sc, S_asymmetric_fm), asymmetric_fm_rf);
  10012. s7_rf_set_function(s7_name_to_value(sc, S_filtered_comb), filtered_comb_rf);
  10013. s7_rf_set_function(s7_name_to_value(sc, S_filtered_comb_bank), filtered_comb_bank_rf);
  10014. s7_rf_set_function(s7_name_to_value(sc, S_move_sound), move_sound_rf);
  10015. s7_rf_set_function(s7_name_to_value(sc, S_locsig), locsig_rf);
  10016. s7_rf_set_function(s7_name_to_value(sc, S_out_bank), out_bank_rf);
  10017. s7_rf_set_function(s7_name_to_value(sc, S_phase_vocoder), phase_vocoder_rf);
  10018. s7_rf_set_function(s7_name_to_value(sc, S_convolve), convolve_rf);
  10019. s7_rf_set_function(s7_name_to_value(sc, S_sample_to_file), sample_to_file_rf);
  10020. s7_rf_set_function(s7_name_to_value(sc, S_mus_srate), srate_rf);
  10021. s7_rf_set_function(s7_name_to_value(sc, S_contrast_enhancement), contrast_enhancement_rf);
  10022. s7_rf_set_function(s7_name_to_value(sc, S_mus_set_formant_frequency), set_formant_frequency_rf);
  10023. s7_rf_set_function(s7_name_to_value(sc, S_odd_weight), odd_weight_rf);
  10024. s7_rf_set_function(s7_name_to_value(sc, S_even_weight), even_weight_rf);
  10025. s7_rf_set_function(s7_name_to_value(sc, S_odd_multiple), odd_multiple_rf);
  10026. s7_rf_set_function(s7_name_to_value(sc, S_even_multiple), even_multiple_rf);
  10027. s7_rf_set_function(s7_name_to_value(sc, S_hz_to_radians), hz_to_radians_rf);
  10028. s7_rf_set_function(s7_name_to_value(sc, S_radians_to_hz), radians_to_hz_rf);
  10029. s7_rf_set_function(s7_name_to_value(sc, S_radians_to_degrees), radians_to_degrees_rf);
  10030. s7_rf_set_function(s7_name_to_value(sc, S_degrees_to_radians), degrees_to_radians_rf);
  10031. s7_rf_set_function(s7_name_to_value(sc, S_db_to_linear), db_to_linear_rf);
  10032. s7_rf_set_function(s7_name_to_value(sc, S_linear_to_db), linear_to_db_rf);
  10033. s7_rf_set_function(s7_name_to_value(sc, S_mus_random), random_rf);
  10034. s7_rf_set_function(s7_name_to_value(sc, S_amplitude_modulate), am_rf);
  10035. s7_rf_set_function(s7_name_to_value(sc, S_ring_modulate), ring_modulate_rf);
  10036. s7_rf_set_function(s7_name_to_value(sc, S_array_interp), array_interp_rf);
  10037. s7_pf_set_function(s7_name_to_value(sc, S_is_all_pass), is_all_pass_pf);
  10038. s7_pf_set_function(s7_name_to_value(sc, S_is_asymmetric_fm), is_asymmetric_fm_pf);
  10039. s7_pf_set_function(s7_name_to_value(sc, S_is_comb), is_comb_pf);
  10040. s7_pf_set_function(s7_name_to_value(sc, S_is_comb_bank), is_comb_bank_pf);
  10041. s7_pf_set_function(s7_name_to_value(sc, S_is_all_pass_bank), is_all_pass_bank_pf);
  10042. s7_pf_set_function(s7_name_to_value(sc, S_is_convolve), is_convolve_pf);
  10043. s7_pf_set_function(s7_name_to_value(sc, S_is_delay), is_delay_pf);
  10044. s7_pf_set_function(s7_name_to_value(sc, S_is_env), is_env_pf);
  10045. s7_pf_set_function(s7_name_to_value(sc, S_is_filter), is_filter_pf);
  10046. s7_pf_set_function(s7_name_to_value(sc, S_is_filtered_comb), is_filtered_comb_pf);
  10047. s7_pf_set_function(s7_name_to_value(sc, S_is_filtered_comb_bank), is_filtered_comb_bank_pf);
  10048. s7_pf_set_function(s7_name_to_value(sc, S_is_fir_filter), is_fir_filter_pf);
  10049. s7_pf_set_function(s7_name_to_value(sc, S_is_firmant), is_firmant_pf);
  10050. s7_pf_set_function(s7_name_to_value(sc, S_is_formant), is_formant_pf);
  10051. s7_pf_set_function(s7_name_to_value(sc, S_is_granulate), is_granulate_pf);
  10052. s7_pf_set_function(s7_name_to_value(sc, S_is_iir_filter), is_iir_filter_pf);
  10053. s7_pf_set_function(s7_name_to_value(sc, S_is_moving_average), is_moving_average_pf);
  10054. s7_pf_set_function(s7_name_to_value(sc, S_is_moving_max), is_moving_max_pf);
  10055. s7_pf_set_function(s7_name_to_value(sc, S_is_moving_norm), is_moving_norm_pf);
  10056. s7_pf_set_function(s7_name_to_value(sc, S_is_ncos), is_ncos_pf);
  10057. s7_pf_set_function(s7_name_to_value(sc, S_is_notch), is_notch_pf);
  10058. s7_pf_set_function(s7_name_to_value(sc, S_is_nrxycos), is_nrxycos_pf);
  10059. s7_pf_set_function(s7_name_to_value(sc, S_is_nrxysin), is_nrxysin_pf);
  10060. s7_pf_set_function(s7_name_to_value(sc, S_is_nsin), is_nsin_pf);
  10061. s7_pf_set_function(s7_name_to_value(sc, S_is_one_pole), is_one_pole_pf);
  10062. s7_pf_set_function(s7_name_to_value(sc, S_is_one_pole_all_pass), is_one_pole_all_pass_pf);
  10063. s7_pf_set_function(s7_name_to_value(sc, S_is_one_zero), is_one_zero_pf);
  10064. s7_pf_set_function(s7_name_to_value(sc, S_is_oscil), is_oscil_pf);
  10065. s7_pf_set_function(s7_name_to_value(sc, S_is_oscil_bank), is_oscil_bank_pf);
  10066. s7_pf_set_function(s7_name_to_value(sc, S_is_phase_vocoder), is_phase_vocoder_pf);
  10067. s7_pf_set_function(s7_name_to_value(sc, S_is_polyshape), is_polyshape_pf);
  10068. s7_pf_set_function(s7_name_to_value(sc, S_is_polywave), is_polywave_pf);
  10069. s7_pf_set_function(s7_name_to_value(sc, S_is_pulse_train), is_pulse_train_pf);
  10070. s7_pf_set_function(s7_name_to_value(sc, S_is_pulsed_env), is_pulsed_env_pf);
  10071. s7_pf_set_function(s7_name_to_value(sc, S_is_rand), is_rand_pf);
  10072. s7_pf_set_function(s7_name_to_value(sc, S_is_rand_interp), is_rand_interp_pf);
  10073. s7_pf_set_function(s7_name_to_value(sc, S_is_readin), is_readin_pf);
  10074. s7_pf_set_function(s7_name_to_value(sc, S_is_rxykcos), is_rxykcos_pf);
  10075. s7_pf_set_function(s7_name_to_value(sc, S_is_rxyksin), is_rxyksin_pf);
  10076. s7_pf_set_function(s7_name_to_value(sc, S_is_sawtooth_wave), is_sawtooth_wave_pf);
  10077. s7_pf_set_function(s7_name_to_value(sc, S_is_square_wave), is_square_wave_pf);
  10078. s7_pf_set_function(s7_name_to_value(sc, S_is_src), is_src_pf);
  10079. s7_pf_set_function(s7_name_to_value(sc, S_is_table_lookup), is_table_lookup_pf);
  10080. s7_pf_set_function(s7_name_to_value(sc, S_is_triangle_wave), is_triangle_wave_pf);
  10081. s7_pf_set_function(s7_name_to_value(sc, S_is_two_pole), is_two_pole_pf);
  10082. s7_pf_set_function(s7_name_to_value(sc, S_is_two_zero), is_two_zero_pf);
  10083. s7_pf_set_function(s7_name_to_value(sc, S_is_wave_train), is_wave_train_pf);
  10084. s7_pf_set_function(s7_name_to_value(sc, S_is_ssb_am), is_ssb_am_pf);
  10085. s7_pf_set_function(s7_name_to_value(sc, S_is_tap), is_tap_pf);
  10086. s7_rf_set_function(s7_name_to_value(sc, S_dot_product), dot_product_rf);
  10087. s7_pf_set_function(s7_name_to_value(sc, S_mus_fft), mus_fft_pf);
  10088. s7_pf_set_function(s7_name_to_value(sc, S_rectangular_to_polar), rectangular_to_polar_pf);
  10089. s7_pf_set_function(s7_name_to_value(sc, S_polar_to_rectangular), polar_to_rectangular_pf);
  10090. s7_pf_set_function(s7_name_to_value(sc, S_rectangular_to_magnitudes), rectangular_to_magnitudes_pf);
  10091. s7_rf_set_function(s7_name_to_value(sc, S_mus_chebyshev_t_sum), chebyshev_t_rf);
  10092. s7_rf_set_function(s7_name_to_value(sc, S_mus_chebyshev_u_sum), chebyshev_u_rf);
  10093. s7_rf_set_function(s7_name_to_value(sc, S_mus_chebyshev_tu_sum), chebyshev_tu_rf);
  10094. s7_pf_set_function(s7_name_to_value(sc, S_mus_data), mus_data_pf);
  10095. s7_pf_set_function(s7_name_to_value(sc, S_mus_reset), mus_reset_pf);
  10096. s7_rf_set_function(s7_name_to_value(sc, S_mus_scaler), mus_scaler_rf);
  10097. s7_rf_set_function(s7_name_to_value(sc, S_mus_phase), mus_phase_rf);
  10098. s7_rf_set_function(s7_name_to_value(sc, S_mus_frequency), mus_frequency_rf);
  10099. s7_rf_set_function(s7_name_to_value(sc, S_mus_offset), mus_offset_rf);
  10100. s7_rf_set_function(s7_name_to_value(sc, S_mus_width), mus_width_rf);
  10101. s7_rf_set_function(s7_name_to_value(sc, S_mus_increment), mus_increment_rf);
  10102. s7_rf_set_function(s7_name_to_value(sc, S_mus_feedforward), mus_feedforward_rf);
  10103. s7_rf_set_function(s7_name_to_value(sc, S_mus_feedback), mus_feedback_rf);
  10104. s7_if_set_function(s7_name_to_value(sc, S_mus_length), mus_length_if);
  10105. s7_if_set_function(s7_name_to_value(sc, S_mus_order), mus_order_if);
  10106. s7_if_set_function(s7_name_to_value(sc, S_mus_location), mus_location_if);
  10107. s7_if_set_function(s7_name_to_value(sc, S_mus_channel), mus_channel_if);
  10108. s7_if_set_function(s7_name_to_value(sc, S_mus_channels), mus_channels_if);
  10109. s7_if_set_function(s7_name_to_value(sc, S_mus_ramp), mus_ramp_if);
  10110. s7_if_set_function(s7_name_to_value(sc, S_mus_hop), mus_hop_if);
  10111. #endif /* gmp */
  10112. }
  10113. #endif /*s7 */
  10114. Xen_wrap_no_args(g_mus_srate_w, g_mus_srate)
  10115. Xen_wrap_1_arg(g_mus_set_srate_w, g_mus_set_srate)
  10116. Xen_wrap_no_args(g_mus_float_equal_fudge_factor_w, g_mus_float_equal_fudge_factor)
  10117. Xen_wrap_1_arg(g_mus_set_float_equal_fudge_factor_w, g_mus_set_float_equal_fudge_factor)
  10118. Xen_wrap_no_args(g_mus_array_print_length_w, g_mus_array_print_length)
  10119. Xen_wrap_1_arg(g_mus_set_array_print_length_w, g_mus_set_array_print_length)
  10120. Xen_wrap_1_arg(g_radians_to_hz_w, g_radians_to_hz)
  10121. Xen_wrap_1_arg(g_hz_to_radians_w, g_hz_to_radians)
  10122. Xen_wrap_1_arg(g_radians_to_degrees_w, g_radians_to_degrees)
  10123. Xen_wrap_1_arg(g_degrees_to_radians_w, g_degrees_to_radians)
  10124. Xen_wrap_1_arg(g_db_to_linear_w, g_db_to_linear)
  10125. Xen_wrap_1_arg(g_linear_to_db_w, g_linear_to_db)
  10126. Xen_wrap_1_arg(g_even_weight_w, g_even_weight)
  10127. Xen_wrap_1_arg(g_odd_weight_w, g_odd_weight)
  10128. Xen_wrap_2_args(g_even_multiple_w, g_even_multiple)
  10129. Xen_wrap_2_args(g_odd_multiple_w, g_odd_multiple)
  10130. Xen_wrap_1_arg(g_seconds_to_samples_w, g_seconds_to_samples)
  10131. Xen_wrap_1_arg(g_samples_to_seconds_w, g_samples_to_seconds)
  10132. Xen_wrap_2_args(g_ring_modulate_w, g_ring_modulate)
  10133. Xen_wrap_3_args(g_amplitude_modulate_w, g_amplitude_modulate)
  10134. Xen_wrap_2_optional_args(g_contrast_enhancement_w, g_contrast_enhancement)
  10135. Xen_wrap_3_optional_args(g_dot_product_w, g_dot_product)
  10136. #if HAVE_COMPLEX_TRIG && HAVE_COMPLEX_NUMBERS && (!HAVE_RUBY)
  10137. Xen_wrap_2_args(g_edot_product_w, g_edot_product)
  10138. #endif
  10139. Xen_wrap_2_args(g_polynomial_w, g_polynomial)
  10140. Xen_wrap_4_optional_args(g_make_fft_window_w, g_make_fft_window)
  10141. Xen_wrap_4_optional_args(g_mus_fft_w, g_mus_fft)
  10142. Xen_wrap_4_optional_args(g_spectrum_w, g_spectrum)
  10143. Xen_wrap_1_arg(g_autocorrelate_w, g_autocorrelate)
  10144. Xen_wrap_2_args(g_correlate_w, g_correlate)
  10145. Xen_wrap_3_optional_args(g_convolution_w, g_convolution)
  10146. Xen_wrap_2_args(g_rectangular_to_polar_w, g_rectangular_to_polar)
  10147. Xen_wrap_2_args(g_rectangular_to_magnitudes_w, g_rectangular_to_magnitudes)
  10148. Xen_wrap_2_args(g_polar_to_rectangular_w, g_polar_to_rectangular)
  10149. Xen_wrap_3_optional_args(g_array_interp_w, g_array_interp)
  10150. Xen_wrap_5_optional_args(g_mus_interpolate_w, g_mus_interpolate)
  10151. Xen_wrap_1_arg(g_mus_describe_w, g_mus_describe)
  10152. Xen_wrap_1_arg(g_mus_name_w, g_mus_name)
  10153. Xen_wrap_3_optional_args(g_mus_run_w, g_mus_run)
  10154. Xen_wrap_1_arg(g_mus_phase_w, g_mus_phase)
  10155. Xen_wrap_2_args(g_mus_set_phase_w, g_mus_set_phase)
  10156. Xen_wrap_1_arg(g_mus_width_w, g_mus_width)
  10157. Xen_wrap_2_args(g_mus_set_width_w, g_mus_set_width)
  10158. Xen_wrap_1_arg(g_mus_scaler_w, g_mus_scaler)
  10159. Xen_wrap_2_args(g_mus_set_scaler_w, g_mus_set_scaler)
  10160. Xen_wrap_1_arg(g_mus_feedforward_w, g_mus_feedforward)
  10161. Xen_wrap_2_args(g_mus_set_feedforward_w, g_mus_set_feedforward)
  10162. Xen_wrap_1_arg(g_mus_reset_w, g_mus_reset)
  10163. Xen_wrap_1_arg(g_mus_copy_w, g_mus_copy)
  10164. Xen_wrap_1_arg(g_mus_offset_w, g_mus_offset)
  10165. Xen_wrap_2_args(g_mus_set_offset_w, g_mus_set_offset)
  10166. Xen_wrap_1_arg(g_mus_frequency_w, g_mus_frequency)
  10167. Xen_wrap_2_args(g_mus_set_frequency_w, g_mus_set_frequency)
  10168. Xen_wrap_1_arg(g_mus_length_w, g_mus_length)
  10169. Xen_wrap_1_arg(g_mus_file_name_w, g_mus_file_name)
  10170. Xen_wrap_2_args(g_mus_set_length_w, g_mus_set_length)
  10171. Xen_wrap_1_arg(g_mus_type_w, g_mus_type)
  10172. Xen_wrap_1_arg(g_mus_order_w, g_mus_order)
  10173. Xen_wrap_1_arg(g_mus_data_w, g_mus_data)
  10174. Xen_wrap_2_args(g_mus_set_data_w, g_mus_set_data)
  10175. Xen_wrap_1_arg(g_is_oscil_w, g_is_oscil)
  10176. Xen_wrap_3_optional_args(g_oscil_w, g_oscil)
  10177. Xen_wrap_1_arg(g_is_oscil_bank_w, g_is_oscil_bank)
  10178. Xen_wrap_1_arg(g_oscil_bank_w, g_oscil_bank)
  10179. Xen_wrap_any_args(g_mus_apply_w, g_mus_apply)
  10180. Xen_wrap_any_args(g_make_delay_w, g_make_delay)
  10181. Xen_wrap_any_args(g_make_comb_w, g_make_comb)
  10182. Xen_wrap_any_args(g_make_filtered_comb_w, g_make_filtered_comb)
  10183. Xen_wrap_any_args(g_make_notch_w, g_make_notch)
  10184. Xen_wrap_any_args(g_make_all_pass_w, g_make_all_pass)
  10185. Xen_wrap_any_args(g_make_moving_average_w, g_make_moving_average)
  10186. Xen_wrap_any_args(g_make_moving_max_w, g_make_moving_max)
  10187. Xen_wrap_any_args(g_make_moving_norm_w, g_make_moving_norm)
  10188. Xen_wrap_3_optional_args(g_delay_w, g_delay)
  10189. Xen_wrap_2_optional_args(g_delay_tick_w, g_delay_tick)
  10190. Xen_wrap_2_optional_args(g_tap_w, g_tap)
  10191. Xen_wrap_3_optional_args(g_notch_w, g_notch)
  10192. Xen_wrap_3_optional_args(g_comb_w, g_comb)
  10193. Xen_wrap_3_optional_args(g_filtered_comb_w, g_filtered_comb)
  10194. Xen_wrap_3_optional_args(g_all_pass_w, g_all_pass)
  10195. Xen_wrap_2_optional_args(g_moving_average_w, g_moving_average)
  10196. Xen_wrap_2_optional_args(g_moving_max_w, g_moving_max)
  10197. Xen_wrap_2_optional_args(g_moving_norm_w, g_moving_norm)
  10198. Xen_wrap_1_arg(g_is_tap_w, g_is_tap)
  10199. Xen_wrap_1_arg(g_is_delay_w, g_is_delay)
  10200. Xen_wrap_1_arg(g_is_notch_w, g_is_notch)
  10201. Xen_wrap_1_arg(g_is_comb_w, g_is_comb)
  10202. Xen_wrap_1_arg(g_is_filtered_comb_w, g_is_filtered_comb)
  10203. Xen_wrap_1_arg(g_is_all_pass_w, g_is_all_pass)
  10204. Xen_wrap_1_arg(g_is_moving_average_w, g_is_moving_average)
  10205. Xen_wrap_1_arg(g_is_moving_max_w, g_is_moving_max)
  10206. Xen_wrap_1_arg(g_is_moving_norm_w, g_is_moving_norm)
  10207. Xen_wrap_2_optional_args(g_ncos_w, g_ncos)
  10208. Xen_wrap_1_arg(g_is_ncos_w, g_is_ncos)
  10209. Xen_wrap_2_optional_args(g_nsin_w, g_nsin)
  10210. Xen_wrap_1_arg(g_is_nsin_w, g_is_nsin)
  10211. Xen_wrap_any_args(g_make_rand_w, g_make_rand)
  10212. Xen_wrap_any_args(g_make_rand_interp_w, g_make_rand_interp)
  10213. Xen_wrap_2_optional_args(g_rand_w, g_rand)
  10214. Xen_wrap_2_optional_args(g_rand_interp_w, g_rand_interp)
  10215. Xen_wrap_1_arg(g_is_rand_w, g_is_rand)
  10216. Xen_wrap_1_arg(g_is_rand_interp_w, g_is_rand_interp)
  10217. Xen_wrap_1_arg(g_mus_random_w, g_mus_random)
  10218. Xen_wrap_no_args(g_mus_rand_seed_w, g_mus_rand_seed)
  10219. Xen_wrap_1_arg(g_mus_set_rand_seed_w, g_mus_set_rand_seed)
  10220. Xen_wrap_1_arg(g_is_table_lookup_w, g_is_table_lookup)
  10221. Xen_wrap_any_args(g_make_table_lookup_w, g_make_table_lookup)
  10222. Xen_wrap_2_optional_args(g_table_lookup_w, g_table_lookup)
  10223. Xen_wrap_3_optional_args(g_partials_to_wave_w, g_partials_to_wave)
  10224. Xen_wrap_3_optional_args(g_phase_partials_to_wave_w, g_phase_partials_to_wave)
  10225. Xen_wrap_6_optional_args(g_make_sawtooth_wave_w, g_make_sawtooth_wave)
  10226. Xen_wrap_2_optional_args(g_sawtooth_wave_w, g_sawtooth_wave)
  10227. Xen_wrap_1_arg(g_is_sawtooth_wave_w, g_is_sawtooth_wave)
  10228. Xen_wrap_6_optional_args(g_make_triangle_wave_w, g_make_triangle_wave)
  10229. Xen_wrap_2_optional_args(g_triangle_wave_w, g_triangle_wave)
  10230. Xen_wrap_1_arg(g_is_triangle_wave_w, g_is_triangle_wave)
  10231. Xen_wrap_6_optional_args(g_make_square_wave_w, g_make_square_wave)
  10232. Xen_wrap_2_optional_args(g_square_wave_w, g_square_wave)
  10233. Xen_wrap_1_arg(g_is_square_wave_w, g_is_square_wave)
  10234. Xen_wrap_6_optional_args(g_make_pulse_train_w, g_make_pulse_train)
  10235. Xen_wrap_2_optional_args(g_pulse_train_w, g_pulse_train)
  10236. Xen_wrap_1_arg(g_is_pulse_train_w, g_is_pulse_train)
  10237. Xen_wrap_3_args(g_make_pulsed_env_w, g_make_pulsed_env)
  10238. Xen_wrap_2_optional_args(g_pulsed_env_w, g_pulsed_env)
  10239. Xen_wrap_1_arg(g_is_pulsed_env_w, g_is_pulsed_env)
  10240. Xen_wrap_3_optional_args(g_asymmetric_fm_w, g_asymmetric_fm)
  10241. Xen_wrap_1_arg(g_is_asymmetric_fm_w, g_is_asymmetric_fm)
  10242. Xen_wrap_4_optional_args(g_make_one_zero_w, g_make_one_zero)
  10243. Xen_wrap_2_optional_args(g_one_zero_w, g_one_zero)
  10244. Xen_wrap_1_arg(g_is_one_zero_w, g_is_one_zero)
  10245. Xen_wrap_4_optional_args(g_make_one_pole_w, g_make_one_pole)
  10246. Xen_wrap_2_optional_args(g_one_pole_w, g_one_pole)
  10247. Xen_wrap_1_arg(g_is_one_pole_w, g_is_one_pole)
  10248. Xen_wrap_6_optional_args(g_make_two_zero_w, g_make_two_zero)
  10249. Xen_wrap_2_optional_args(g_two_zero_w, g_two_zero)
  10250. Xen_wrap_1_arg(g_is_two_zero_w, g_is_two_zero)
  10251. Xen_wrap_6_optional_args(g_make_two_pole_w, g_make_two_pole)
  10252. Xen_wrap_2_optional_args(g_two_pole_w, g_two_pole)
  10253. Xen_wrap_1_arg(g_is_two_pole_w, g_is_two_pole)
  10254. Xen_wrap_1_arg(g_is_formant_w, g_is_formant)
  10255. Xen_wrap_4_optional_args(g_make_formant_w, g_make_formant)
  10256. Xen_wrap_3_optional_args(g_formant_w, g_formant)
  10257. Xen_wrap_2_optional_args(g_formant_bank_w, g_formant_bank)
  10258. Xen_wrap_1_arg(g_is_formant_bank_w, g_is_formant_bank)
  10259. Xen_wrap_2_optional_args(g_make_formant_bank_w, g_make_formant_bank)
  10260. Xen_wrap_1_arg(g_is_firmant_w, g_is_firmant)
  10261. Xen_wrap_4_optional_args(g_make_firmant_w, g_make_firmant)
  10262. Xen_wrap_3_optional_args(g_firmant_w, g_firmant)
  10263. Xen_wrap_1_arg(g_is_one_pole_all_pass_w, g_is_one_pole_all_pass)
  10264. Xen_wrap_2_args(g_make_one_pole_all_pass_w, g_make_one_pole_all_pass)
  10265. Xen_wrap_2_optional_args(g_one_pole_all_pass_w, g_one_pole_all_pass)
  10266. Xen_wrap_2_args(g_set_formant_frequency_w, g_set_formant_frequency)
  10267. Xen_wrap_3_args(g_set_formant_radius_and_frequency_w, g_set_formant_radius_and_frequency)
  10268. Xen_wrap_5_args(g_frample_to_frample_w, g_frample_to_frample)
  10269. Xen_wrap_any_args(g_make_wave_train_w, g_make_wave_train)
  10270. Xen_wrap_2_optional_args(g_wave_train_w, g_wave_train)
  10271. Xen_wrap_1_arg(g_is_wave_train_w, g_is_wave_train)
  10272. Xen_wrap_any_args(g_make_polyshape_w, g_make_polyshape)
  10273. Xen_wrap_3_optional_args(g_polyshape_w, g_polyshape)
  10274. Xen_wrap_1_arg(g_is_polyshape_w, g_is_polyshape)
  10275. Xen_wrap_2_optional_args(g_partials_to_polynomial_w, g_partials_to_polynomial)
  10276. Xen_wrap_1_arg(g_normalize_partials_w, g_normalize_partials)
  10277. Xen_wrap_2_args(g_chebyshev_t_sum_w, g_chebyshev_t_sum)
  10278. Xen_wrap_2_args(g_chebyshev_u_sum_w, g_chebyshev_u_sum)
  10279. Xen_wrap_3_args(g_chebyshev_tu_sum_w, g_chebyshev_tu_sum)
  10280. Xen_wrap_any_args(g_make_polywave_w, g_make_polywave)
  10281. Xen_wrap_2_optional_args(g_polywave_w, g_polywave)
  10282. Xen_wrap_1_arg(g_is_polywave_w, g_is_polywave)
  10283. Xen_wrap_any_args(g_make_nrxysin_w, g_make_nrxysin)
  10284. Xen_wrap_2_optional_args(g_nrxysin_w, g_nrxysin)
  10285. Xen_wrap_1_arg(g_is_nrxysin_w, g_is_nrxysin)
  10286. Xen_wrap_any_args(g_make_nrxycos_w, g_make_nrxycos)
  10287. Xen_wrap_2_optional_args(g_nrxycos_w, g_nrxycos)
  10288. Xen_wrap_1_arg(g_is_nrxycos_w, g_is_nrxycos)
  10289. Xen_wrap_any_args(g_make_rxyksin_w, g_make_rxyksin)
  10290. Xen_wrap_2_optional_args(g_rxyksin_w, g_rxyksin)
  10291. Xen_wrap_1_arg(g_is_rxyksin_w, g_is_rxyksin)
  10292. Xen_wrap_any_args(g_make_rxykcos_w, g_make_rxykcos)
  10293. Xen_wrap_2_optional_args(g_rxykcos_w, g_rxykcos)
  10294. Xen_wrap_1_arg(g_is_rxykcos_w, g_is_rxykcos)
  10295. Xen_wrap_6_optional_args(g_make_filter_w, g_make_filter)
  10296. Xen_wrap_2_optional_args(g_filter_w, g_filter)
  10297. Xen_wrap_1_arg(g_is_filter_w, g_is_filter)
  10298. Xen_wrap_4_optional_args(g_make_fir_filter_w, g_make_fir_filter)
  10299. Xen_wrap_2_args(g_make_fir_coeffs_w, g_make_fir_coeffs)
  10300. Xen_wrap_2_optional_args(g_fir_filter_w, g_fir_filter)
  10301. Xen_wrap_1_arg(g_is_fir_filter_w, g_is_fir_filter)
  10302. Xen_wrap_4_optional_args(g_make_iir_filter_w, g_make_iir_filter)
  10303. Xen_wrap_2_optional_args(g_iir_filter_w, g_iir_filter)
  10304. Xen_wrap_1_arg(g_is_iir_filter_w, g_is_iir_filter)
  10305. Xen_wrap_1_arg(g_mus_xcoeffs_w, g_mus_xcoeffs)
  10306. Xen_wrap_1_arg(g_mus_ycoeffs_w, g_mus_ycoeffs)
  10307. Xen_wrap_2_args(g_mus_xcoeff_w, g_mus_xcoeff)
  10308. Xen_wrap_3_args(g_mus_set_xcoeff_w, g_mus_set_xcoeff)
  10309. Xen_wrap_2_args(g_mus_ycoeff_w, g_mus_ycoeff)
  10310. Xen_wrap_3_args(g_mus_set_ycoeff_w, g_mus_set_ycoeff)
  10311. Xen_wrap_1_arg(g_is_env_w, g_is_env)
  10312. Xen_wrap_1_arg(g_env_w, g_env)
  10313. Xen_wrap_any_args(g_make_env_w, g_make_env)
  10314. Xen_wrap_2_args(g_env_interp_w, g_env_interp)
  10315. Xen_wrap_3_optional_args(g_envelope_interp_w, g_envelope_interp)
  10316. Xen_wrap_2_args(g_env_any_w, g_env_any)
  10317. Xen_wrap_1_arg(g_is_file_to_sample_w, g_is_file_to_sample)
  10318. Xen_wrap_2_optional_args(g_make_file_to_sample_w, g_make_file_to_sample)
  10319. Xen_wrap_3_optional_args(g_file_to_sample_w, g_file_to_sample)
  10320. Xen_wrap_1_arg(g_is_sample_to_file_w, g_is_sample_to_file)
  10321. Xen_wrap_5_optional_args(g_make_sample_to_file_w, g_make_sample_to_file)
  10322. Xen_wrap_1_arg(g_continue_sample_to_file_w, g_continue_sample_to_file)
  10323. Xen_wrap_4_args(g_sample_to_file_w, g_sample_to_file)
  10324. Xen_wrap_2_args(g_sample_to_file_add_w, g_sample_to_file_add)
  10325. Xen_wrap_1_arg(g_is_file_to_frample_w, g_is_file_to_frample)
  10326. Xen_wrap_2_optional_args(g_make_file_to_frample_w, g_make_file_to_frample)
  10327. Xen_wrap_3_optional_args(g_file_to_frample_w, g_file_to_frample)
  10328. Xen_wrap_1_arg(g_continue_frample_to_file_w, g_continue_frample_to_file)
  10329. Xen_wrap_1_arg(g_is_frample_to_file_w, g_is_frample_to_file)
  10330. Xen_wrap_3_args(g_frample_to_file_w, g_frample_to_file)
  10331. Xen_wrap_5_optional_args(g_make_frample_to_file_w, g_make_frample_to_file)
  10332. Xen_wrap_1_arg(g_is_mus_input_w, g_is_mus_input)
  10333. Xen_wrap_1_arg(g_is_mus_output_w, g_is_mus_output)
  10334. Xen_wrap_3_args(g_in_any_w, g_in_any)
  10335. Xen_wrap_2_args(g_ina_w, g_ina)
  10336. Xen_wrap_2_args(g_inb_w, g_inb)
  10337. Xen_wrap_4_optional_args(g_out_any_w, g_out_any)
  10338. Xen_wrap_3_optional_args(g_outa_w, g_outa)
  10339. Xen_wrap_3_optional_args(g_outb_w, g_outb)
  10340. Xen_wrap_3_optional_args(g_outc_w, g_outc)
  10341. Xen_wrap_3_optional_args(g_outd_w, g_outd)
  10342. Xen_wrap_1_arg(g_mus_close_w, g_mus_close)
  10343. Xen_wrap_no_args(g_mus_file_buffer_size_w, g_mus_file_buffer_size)
  10344. Xen_wrap_1_arg(g_mus_set_file_buffer_size_w, g_mus_set_file_buffer_size)
  10345. Xen_wrap_1_arg(g_is_readin_w, g_is_readin)
  10346. Xen_wrap_1_arg(g_readin_w, g_readin)
  10347. Xen_wrap_any_args(g_make_readin_w, g_make_readin)
  10348. Xen_wrap_1_arg(g_mus_channel_w, g_mus_channel)
  10349. Xen_wrap_1_arg(g_mus_interp_type_w, g_mus_interp_type)
  10350. Xen_wrap_1_arg(g_mus_location_w, g_mus_location)
  10351. Xen_wrap_2_args(g_mus_set_location_w, g_mus_set_location)
  10352. Xen_wrap_1_arg(g_mus_increment_w, g_mus_increment)
  10353. Xen_wrap_2_args(g_mus_set_increment_w, g_mus_set_increment)
  10354. Xen_wrap_1_arg(g_mus_feedback_w, g_mus_feedback)
  10355. Xen_wrap_2_args(g_mus_set_feedback_w, g_mus_set_feedback)
  10356. Xen_wrap_1_arg(g_is_locsig_w, g_is_locsig)
  10357. Xen_wrap_3_args(g_locsig_w, g_locsig)
  10358. Xen_wrap_any_args(g_make_locsig_w, g_make_locsig)
  10359. Xen_wrap_3_args(g_move_locsig_w, g_move_locsig)
  10360. Xen_wrap_no_args(g_locsig_type_w, g_locsig_type)
  10361. Xen_wrap_1_arg(g_set_locsig_type_w, g_set_locsig_type)
  10362. Xen_wrap_1_arg(g_mus_channels_w, g_mus_channels)
  10363. Xen_wrap_2_args(g_locsig_ref_w, g_locsig_ref)
  10364. Xen_wrap_2_args(g_locsig_reverb_ref_w, g_locsig_reverb_ref)
  10365. Xen_wrap_3_args(g_locsig_set_w, g_locsig_set)
  10366. Xen_wrap_3_args(g_locsig_reverb_set_w, g_locsig_reverb_set)
  10367. Xen_wrap_1_arg(g_is_move_sound_w, g_is_move_sound)
  10368. Xen_wrap_3_args(g_move_sound_w, g_move_sound)
  10369. Xen_wrap_3_optional_args(g_make_move_sound_w, g_make_move_sound)
  10370. Xen_wrap_no_args(g_mus_clear_sincs_w, g_mus_clear_sincs)
  10371. Xen_wrap_1_arg(g_is_src_w, g_is_src)
  10372. Xen_wrap_3_optional_args(g_src_w, g_src)
  10373. Xen_wrap_6_optional_args(g_make_src_w, g_make_src)
  10374. Xen_wrap_1_arg(g_is_granulate_w, g_is_granulate)
  10375. Xen_wrap_3_optional_args(g_granulate_w, g_granulate)
  10376. Xen_wrap_any_args(g_make_granulate_w, g_make_granulate)
  10377. Xen_wrap_1_arg(g_mus_ramp_w, g_mus_ramp)
  10378. Xen_wrap_2_args(g_mus_set_ramp_w, g_mus_set_ramp)
  10379. Xen_wrap_1_arg(g_is_convolve_w, g_is_convolve)
  10380. Xen_wrap_2_optional_args(g_convolve_w, g_convolve)
  10381. Xen_wrap_any_args(g_make_convolve_w, g_make_convolve)
  10382. Xen_wrap_4_optional_args(g_convolve_files_w, g_convolve_files)
  10383. Xen_wrap_1_arg(g_is_phase_vocoder_w, g_is_phase_vocoder)
  10384. Xen_wrap_5_optional_args(g_phase_vocoder_w, g_phase_vocoder)
  10385. Xen_wrap_any_args(g_make_phase_vocoder_w, g_make_phase_vocoder)
  10386. Xen_wrap_1_arg(g_phase_vocoder_amp_increments_w, g_phase_vocoder_amp_increments)
  10387. Xen_wrap_1_arg(g_phase_vocoder_amps_w, g_phase_vocoder_amps)
  10388. Xen_wrap_1_arg(g_phase_vocoder_freqs_w, g_phase_vocoder_freqs)
  10389. Xen_wrap_1_arg(g_phase_vocoder_phases_w, g_phase_vocoder_phases)
  10390. Xen_wrap_1_arg(g_phase_vocoder_phase_increments_w, g_phase_vocoder_phase_increments)
  10391. Xen_wrap_1_arg(g_mus_hop_w, g_mus_hop)
  10392. Xen_wrap_2_args(g_mus_set_hop_w, g_mus_set_hop)
  10393. Xen_wrap_4_optional_args(g_make_ssb_am_w, g_make_ssb_am)
  10394. Xen_wrap_3_optional_args(g_ssb_am_w, g_ssb_am)
  10395. Xen_wrap_1_arg(g_is_ssb_am_w, g_is_ssb_am)
  10396. Xen_wrap_no_args(g_clm_table_size_w, g_clm_table_size)
  10397. Xen_wrap_1_arg(g_set_clm_table_size_w, g_set_clm_table_size)
  10398. Xen_wrap_no_args(g_clm_default_frequency_w, g_clm_default_frequency)
  10399. Xen_wrap_1_arg(g_set_clm_default_frequency_w, g_set_clm_default_frequency)
  10400. Xen_wrap_1_arg(g_is_mus_generator_w, g_is_mus_generator)
  10401. Xen_wrap_1_arg(g_mus_frandom_w, g_mus_frandom)
  10402. Xen_wrap_1_arg(g_mus_irandom_w, g_mus_irandom)
  10403. Xen_wrap_4_optional_args(g_make_oscil_w, g_make_oscil)
  10404. Xen_wrap_4_optional_args(g_make_ncos_w, g_make_ncos)
  10405. Xen_wrap_4_optional_args(g_make_oscil_bank_w, g_make_oscil_bank)
  10406. Xen_wrap_4_optional_args(g_make_nsin_w, g_make_nsin)
  10407. Xen_wrap_8_optional_args(g_make_asymmetric_fm_w, g_make_asymmetric_fm)
  10408. Xen_wrap_any_args(g_mus_file_mix_w, g_mus_file_mix)
  10409. Xen_wrap_any_args(g_mus_file_mix_with_envs_w, g_mus_file_mix_with_envs)
  10410. Xen_wrap_2_optional_args(g_comb_bank_w, g_comb_bank)
  10411. Xen_wrap_1_arg(g_is_comb_bank_w, g_is_comb_bank)
  10412. Xen_wrap_1_arg(g_make_comb_bank_w, g_make_comb_bank)
  10413. Xen_wrap_2_optional_args(g_filtered_comb_bank_w, g_filtered_comb_bank)
  10414. Xen_wrap_1_arg(g_is_filtered_comb_bank_w, g_is_filtered_comb_bank)
  10415. Xen_wrap_1_arg(g_make_filtered_comb_bank_w, g_make_filtered_comb_bank)
  10416. Xen_wrap_2_optional_args(g_all_pass_bank_w, g_all_pass_bank)
  10417. Xen_wrap_1_arg(g_is_all_pass_bank_w, g_is_all_pass_bank)
  10418. Xen_wrap_1_arg(g_make_all_pass_bank_w, g_make_all_pass_bank)
  10419. Xen_wrap_1_arg(g_pink_noise_w, g_pink_noise)
  10420. Xen_wrap_3_args(g_out_bank_w, g_out_bank)
  10421. #if HAVE_SCHEME
  10422. Xen_wrap_2_args(g_piano_noise_w, g_piano_noise)
  10423. Xen_wrap_6_args(g_singer_filter_w, g_singer_filter)
  10424. Xen_wrap_5_args(g_singer_nose_filter_w, g_singer_nose_filter)
  10425. #endif
  10426. #if HAVE_SCHEME
  10427. static s7_pointer acc_clm_srate(s7_scheme *sc, s7_pointer args) {return(g_mus_set_srate(s7_cadr(args)));}
  10428. static s7_pointer acc_clm_default_frequency(s7_scheme *sc, s7_pointer args) {return(g_set_clm_default_frequency(s7_cadr(args)));}
  10429. static s7_pointer acc_clm_table_size(s7_scheme *sc, s7_pointer args) {return(g_set_clm_table_size(s7_cadr(args)));}
  10430. static s7_pointer acc_mus_file_buffer_size(s7_scheme *sc, s7_pointer args) {return(g_mus_set_file_buffer_size(s7_cadr(args)));}
  10431. static s7_pointer acc_mus_float_equal_fudge_factor(s7_scheme *sc, s7_pointer args) {return(g_mus_set_float_equal_fudge_factor(s7_cadr(args)));}
  10432. static s7_pointer acc_mus_array_print_length(s7_scheme *sc, s7_pointer args) {return(g_mus_set_array_print_length(s7_cadr(args)));}
  10433. #endif
  10434. #if HAVE_SCHEME
  10435. static char *mus_generator_to_readable_string(s7_scheme *sc, void *obj)
  10436. {
  10437. char *str;
  10438. str = (char *)malloc(64 * sizeof(char));
  10439. snprintf(str, 64, "#<%s>", mus_name(((mus_xen *)obj)->gen));
  10440. return(str);
  10441. /* we need a new function to fill this role */
  10442. /* s7_error(sc, s7_make_symbol(sc, "io-error"), s7_list(sc, 1, s7_make_string(sc, "can't write a clm generator readably"))); */
  10443. /* return(NULL); */
  10444. }
  10445. #endif
  10446. static void mus_xen_init(void)
  10447. {
  10448. #if HAVE_SCHEME
  10449. s7_pointer s, i, p, t, r, c, f, v, b, d, j;
  10450. s7_pointer pl_rcr, pl_bt, pl_ir, pl_cc, pl_ccic, pl_ccrr, pl_fc, pl_fcif, pl_cs, pl_ff, pl_tt, pl_fffifi, pl_ffftii, pl_fffi,
  10451. pl_fti, pl_fif, pl_fiir, pl_fttb, pl_ic, pl_rciir, pl_rcir, pl_ririt, pl_rcrr, pl_rirt, pl_riirfff, pl_rirfff, pl_rrpr,
  10452. pl_sc, pl_sssrs, pl_tc, pl_ici, pl_i, pl_fcf, pl_dcr, pl_dr, pl_dffi, pl_dfri, pl_dirfir, pl_dc, pl_dci, pl_dcir, pl_dv,
  10453. pl_dvir, pl_drf, pl_drc, pl_diit, pl_dit, pl_dct, pl_d, pl_djr, pl_it, pl_iti;
  10454. #endif
  10455. mus_initialize();
  10456. current_connect_func = Xen_false;
  10457. #if HAVE_SCHEME
  10458. mus_xen_tag = s7_new_type_x(s7, "<generator>", print_mus_xen, free_mus_xen, s7_equalp_mus_xen, mark_mus_xen,
  10459. mus_xen_apply, NULL, s7_mus_length, s7_mus_copy, NULL, NULL);
  10460. as_needed_arglist = Xen_list_1(Xen_integer_zero);
  10461. Xen_GC_protect(as_needed_arglist);
  10462. s7_set_object_print_readably(mus_xen_tag, mus_generator_to_readable_string);
  10463. s = s7_make_symbol(s7, "string?");
  10464. i = s7_make_symbol(s7, "integer?");
  10465. p = s7_make_symbol(s7, "pair?");
  10466. t = s7_t(s7);
  10467. r = s7_make_symbol(s7, "real?");
  10468. c = s7_t(s7); /* s7_make_symbol(s7, "c-object?"): this should be mus-generator which should match against oscil? etc -- maybe someday... */
  10469. f = s7_make_symbol(s7, "float-vector?");
  10470. j = s7_make_symbol(s7, "int-vector?");
  10471. v = s7_make_symbol(s7, "vector?");
  10472. b = s7_make_symbol(s7, "boolean?");
  10473. d = s7_make_symbol(s7, "float?");
  10474. pl_bt = s7_make_signature(s7, 2, b, t);
  10475. pl_rcr = s7_make_signature(s7, 3, r, c, r);
  10476. pl_d = s7_make_signature(s7, 1, d);
  10477. pl_dcr = s7_make_circular_signature(s7, 2, 3, d, c, r);
  10478. pl_djr = s7_make_circular_signature(s7, 2, 3, d, j, r);
  10479. pl_dct = s7_make_signature(s7, 3, d, c, t);
  10480. pl_dci = s7_make_circular_signature(s7, 2, 3, d, c, i);
  10481. pl_dcir = s7_make_signature(s7, 4, d, c, i, r);
  10482. pl_dr = s7_make_circular_signature(s7, 1, 2, d, r);
  10483. pl_dffi = s7_make_signature(s7, 4, d, f, f, i);
  10484. pl_dfri = s7_make_signature(s7, 4, d, f, r, i);
  10485. pl_dirfir = s7_make_signature(s7, 6, d, i, r, f, i, r);
  10486. pl_dc = s7_make_signature(s7, 2, d, c);
  10487. pl_dv = s7_make_signature(s7, 2, d, v);
  10488. pl_dvir = s7_make_signature(s7, 4, d, v, i, r);
  10489. pl_drf = s7_make_circular_signature(s7, 2, 3, d, r, f);
  10490. pl_drc = s7_make_signature(s7, 3, d, r, c);
  10491. pl_diit = s7_make_signature(s7, 4, d, i, i, t);
  10492. pl_dit = s7_make_signature(s7, 3, d, i, t);
  10493. pl_ir = s7_make_signature(s7, 2, i, r);
  10494. pl_i = s7_make_circular_signature(s7, 0, 1, i);
  10495. pl_cc = s7_make_circular_signature(s7, 1, 2, c, c);
  10496. pl_ici = s7_make_signature(s7, 3, i, c, i);
  10497. pl_iti = s7_make_signature(s7, 3, i, t, i);
  10498. pl_ccic = s7_make_signature(s7, 4, c, c, i, c);
  10499. pl_ccrr = s7_make_signature(s7, 4, c, c, r, r);
  10500. pl_fc = s7_make_signature(s7, 2, s7_make_signature(s7, 2, f, b), c);
  10501. pl_cs = s7_make_signature(s7, 2, c, s);
  10502. pl_ff = s7_make_circular_signature(s7, 1, 2, f, f);
  10503. pl_tt = s7_make_signature(s7, 2, t, t);
  10504. pl_fcf = s7_make_signature(s7, 3, f, c, f);
  10505. pl_fffifi = s7_make_signature(s7, 6, f, f, f, i, f, i);
  10506. pl_ffftii = s7_make_signature(s7, 6, f, f, f, t, i, i);
  10507. pl_fffi = s7_make_circular_signature(s7, 3, 4, f, f, f, i);
  10508. pl_fti = s7_make_signature(s7, 3, f, t, i);
  10509. pl_fif = s7_make_signature(s7, 3, f, i, f);
  10510. pl_fiir = s7_make_circular_signature(s7, 3, 4, f, i, i, r);
  10511. pl_fttb = s7_make_signature(s7, 4, f, t, t, b);
  10512. pl_ic = s7_make_signature(s7, 2, i, c);
  10513. pl_it = s7_make_signature(s7, 2, i, t);
  10514. pl_rciir = s7_make_signature(s7, 5, r, c, i, i, r);
  10515. pl_rcir = s7_make_signature(s7, 4, r, c, i, r);
  10516. pl_ririt = s7_make_signature(s7,5, r, i, r, i, t);
  10517. pl_rcrr = s7_make_signature(s7, 4, r, c, r, r);
  10518. pl_rirt = s7_make_signature(s7, 4, r, i, r, t);
  10519. pl_riirfff = s7_make_signature(s7, 7, r, i, i, r, f, f, f);
  10520. pl_rirfff = s7_make_signature(s7, 6, r, i, r, f, f, f);
  10521. pl_rrpr = s7_make_signature(s7, 4, r, r, p, r);
  10522. pl_sc = s7_make_signature(s7, 2, s, c);
  10523. pl_sssrs = s7_make_signature(s7, 5, s, s, s, r, s);
  10524. pl_tc = s7_make_signature(s7, 2, t, c);
  10525. pl_fcif = s7_make_signature(s7, 4, f, c, i, f);
  10526. #else
  10527. mus_xen_tag = Xen_make_object_type("Mus", sizeof(mus_xen));
  10528. #endif
  10529. xen_one = C_int_to_Xen_integer(1);
  10530. Xen_GC_protect(xen_one);
  10531. xen_minus_one = C_int_to_Xen_integer(-1);
  10532. Xen_GC_protect(xen_minus_one);
  10533. #if HAVE_FORTH
  10534. fth_set_object_inspect(mus_xen_tag, print_mus_xen);
  10535. fth_set_object_equal(mus_xen_tag, equalp_mus_xen);
  10536. fth_set_object_mark(mus_xen_tag, mark_mus_xen);
  10537. fth_set_object_free(mus_xen_tag, free_mus_xen);
  10538. fth_set_object_apply(mus_xen_tag, Xen_procedure_cast mus_xen_apply, 0, 2, 0);
  10539. #endif
  10540. #if HAVE_RUBY
  10541. rb_define_method(mus_xen_tag, "to_s", Xen_procedure_cast mus_xen_to_s, 0);
  10542. rb_define_method(mus_xen_tag, "eql?", Xen_procedure_cast equalp_mus_xen, 1);
  10543. rb_define_method(mus_xen_tag, "frequency", Xen_procedure_cast g_mus_frequency, 0);
  10544. rb_define_method(mus_xen_tag, "frequency=", Xen_procedure_cast g_mus_set_frequency, 1);
  10545. rb_define_method(mus_xen_tag, "phase", Xen_procedure_cast g_mus_phase, 0);
  10546. rb_define_method(mus_xen_tag, "phase=", Xen_procedure_cast g_mus_set_phase, 1);
  10547. rb_define_method(mus_xen_tag, "scaler", Xen_procedure_cast g_mus_scaler, 0);
  10548. rb_define_method(mus_xen_tag, "scaler=", Xen_procedure_cast g_mus_set_scaler, 1);
  10549. rb_define_method(mus_xen_tag, "width", Xen_procedure_cast g_mus_width, 0);
  10550. rb_define_method(mus_xen_tag, "width=", Xen_procedure_cast g_mus_set_width, 1);
  10551. rb_define_method(mus_xen_tag, "offset", Xen_procedure_cast g_mus_offset, 0);
  10552. rb_define_method(mus_xen_tag, "offset=", Xen_procedure_cast g_mus_set_offset, 1);
  10553. rb_define_method(mus_xen_tag, "reset", Xen_procedure_cast g_mus_reset, 0);
  10554. /* rb_define_method(mus_xen_tag, "copy", Xen_procedure_cast g_mus_copy, 0); */
  10555. rb_define_method(mus_xen_tag, "length", Xen_procedure_cast g_mus_length, 0);
  10556. rb_define_method(mus_xen_tag, "length=", Xen_procedure_cast g_mus_set_length, 1);
  10557. rb_define_method(mus_xen_tag, "data", Xen_procedure_cast g_mus_data, 0);
  10558. rb_define_method(mus_xen_tag, "data=", Xen_procedure_cast g_mus_set_data, 1);
  10559. rb_define_method(mus_xen_tag, "feedforward", Xen_procedure_cast g_mus_feedforward, 0);
  10560. rb_define_method(mus_xen_tag, "feedforward=", Xen_procedure_cast g_mus_set_feedforward, 1);
  10561. rb_define_method(mus_xen_tag, "feedback", Xen_procedure_cast g_mus_feedback, 0);
  10562. rb_define_method(mus_xen_tag, "feedback=", Xen_procedure_cast g_mus_set_increment, 1);
  10563. rb_define_method(mus_xen_tag, "order", Xen_procedure_cast g_mus_order, 0);
  10564. rb_define_method(mus_xen_tag, "type", Xen_procedure_cast g_mus_type, 0);
  10565. rb_define_method(mus_xen_tag, "order=", Xen_procedure_cast g_mus_set_length, 1);
  10566. rb_define_method(mus_xen_tag, "call", Xen_procedure_cast mus_xen_apply, 2);
  10567. rb_define_method(mus_xen_tag, "location", Xen_procedure_cast g_mus_location, 0);
  10568. rb_define_method(mus_xen_tag, "location=", Xen_procedure_cast g_mus_set_location, 1);
  10569. rb_define_method(mus_xen_tag, "increment", Xen_procedure_cast g_mus_increment, 0);
  10570. rb_define_method(mus_xen_tag, "increment=", Xen_procedure_cast g_mus_set_increment, 1);
  10571. rb_define_method(mus_xen_tag, "channels", Xen_procedure_cast g_mus_channels, 0);
  10572. rb_define_method(mus_xen_tag, "channel", Xen_procedure_cast g_mus_channel, 0);
  10573. rb_define_method(mus_xen_tag, "interp_type", Xen_procedure_cast g_mus_interp_type, 0);
  10574. rb_define_method(mus_xen_tag, "xcoeffs", Xen_procedure_cast g_mus_xcoeffs, 0);
  10575. rb_define_method(mus_xen_tag, "ycoeffs", Xen_procedure_cast g_mus_ycoeffs, 0);
  10576. rb_define_method(mus_xen_tag, "xcoeff", Xen_procedure_cast g_mus_xcoeff, 1);
  10577. rb_define_method(mus_xen_tag, "ycoeff", Xen_procedure_cast g_mus_ycoeff, 1);
  10578. /*
  10579. rb_define_method(mus_xen_tag, "xcoeff=", Xen_procedure_cast g_mus_set_xcoeff, 1);
  10580. rb_define_method(mus_xen_tag, "ycoeff=", Xen_procedure_cast g_mus_set_ycoeff, 1);
  10581. */
  10582. rb_define_method(mus_xen_tag, "ramp", Xen_procedure_cast g_mus_ramp, 0);
  10583. rb_define_method(mus_xen_tag, "ramp=", Xen_procedure_cast g_mus_set_ramp, 1);
  10584. rb_define_method(mus_xen_tag, "hop", Xen_procedure_cast g_mus_hop, 0);
  10585. rb_define_method(mus_xen_tag, "hop=", Xen_procedure_cast g_mus_set_hop, 1);
  10586. rb_define_method(mus_xen_tag, "name", Xen_procedure_cast g_mus_name, 0);
  10587. rb_define_method(mus_xen_tag, "file_name", Xen_procedure_cast g_mus_file_name, 0);
  10588. #endif
  10589. init_keywords();
  10590. Xen_define_typed_dilambda(S_mus_srate, g_mus_srate_w, H_mus_srate,
  10591. S_set S_mus_srate, g_mus_set_srate_w, 0, 0, 1, 0, pl_d, pl_dr);
  10592. Xen_define_typed_dilambda(S_mus_float_equal_fudge_factor, g_mus_float_equal_fudge_factor_w, H_mus_float_equal_fudge_factor,
  10593. S_set S_mus_float_equal_fudge_factor, g_mus_set_float_equal_fudge_factor_w, 0, 0, 1, 0, pl_d, pl_dr);
  10594. Xen_define_typed_dilambda(S_mus_array_print_length, g_mus_array_print_length_w, H_mus_array_print_length,
  10595. S_set S_mus_array_print_length, g_mus_set_array_print_length_w, 0, 0, 1, 0, pl_i, pl_i);
  10596. Xen_define_typed_dilambda(S_clm_table_size, g_clm_table_size_w, H_clm_table_size,
  10597. S_set S_clm_table_size, g_set_clm_table_size_w, 0, 0, 1, 0, pl_i, pl_i);
  10598. Xen_define_typed_dilambda(S_clm_default_frequency, g_clm_default_frequency_w, H_clm_default_frequency,
  10599. S_set S_clm_default_frequency, g_set_clm_default_frequency_w, 0, 0, 1, 0, pl_d, pl_dr);
  10600. #if HAVE_SCHEME
  10601. clm_srate_symbol = s7_define_variable(s7, "*clm-srate*", s7_make_real(s7, MUS_DEFAULT_SAMPLING_RATE));
  10602. s7_symbol_set_access(s7, clm_srate_symbol, s7_make_function(s7, "[acc-clm-srate]", acc_clm_srate, 2, 0, false, "accessor"));
  10603. clm_default_frequency_symbol = s7_define_variable(s7, "*" S_clm_default_frequency "*", s7_make_real(s7, MUS_CLM_DEFAULT_FREQUENCY));
  10604. s7_symbol_set_documentation(s7, clm_default_frequency_symbol, "*clm-default-frequency*: the default frequency for most generators (0.0)");
  10605. s7_symbol_set_access(s7, clm_default_frequency_symbol, s7_make_function(s7, "[acc-clm-default-frequency]", acc_clm_default_frequency, 2, 0, false, "accessor"));
  10606. clm_table_size_symbol = s7_define_variable(s7, "*" S_clm_table_size "*", s7_make_integer(s7, MUS_CLM_DEFAULT_TABLE_SIZE));
  10607. s7_symbol_set_documentation(s7, clm_table_size_symbol, "*clm-table-size*: the default table size for most generators (512)");
  10608. s7_symbol_set_access(s7, clm_table_size_symbol, s7_make_function(s7, "[acc-clm-table-size]", acc_clm_table_size, 2, 0, false, "accessor"));
  10609. mus_file_buffer_size_symbol = s7_define_variable(s7, "*clm-file-buffer-size*", s7_make_integer(s7, MUS_DEFAULT_FILE_BUFFER_SIZE));
  10610. s7_symbol_set_access(s7, mus_file_buffer_size_symbol, s7_make_function(s7, "[acc-mus-file-buffer-size]", acc_mus_file_buffer_size, 2, 0, false, "accessor"));
  10611. mus_float_equal_fudge_factor_symbol = s7_define_variable(s7, "*" S_mus_float_equal_fudge_factor "*", s7_make_real(s7, 0.0000001)); /* clm.c */
  10612. s7_symbol_set_documentation(s7, mus_float_equal_fudge_factor_symbol, "*mus-float-equal-fudge-factor*: floating point equality fudge factor");
  10613. s7_symbol_set_access(s7, mus_float_equal_fudge_factor_symbol, s7_make_function(s7, "[acc-mus-float-equal-fudge-factor]", acc_mus_float_equal_fudge_factor, 2, 0, false, "accessor"));
  10614. mus_array_print_length_symbol = s7_define_variable(s7, "*" S_mus_array_print_length "*", s7_make_integer(s7, MUS_DEFAULT_ARRAY_PRINT_LENGTH));
  10615. s7_symbol_set_documentation(s7, mus_array_print_length_symbol, "*mus-array-print-length*: current clm array print length (default is 8).");
  10616. s7_symbol_set_access(s7, mus_array_print_length_symbol, s7_make_function(s7, "[acc-mus-array-print-length]", acc_mus_array_print_length, 2, 0, false, "accessor"));
  10617. #endif
  10618. Xen_define_typed_procedure(S_radians_to_hz, g_radians_to_hz_w, 1, 0, 0, H_radians_to_hz, pl_dr);
  10619. Xen_define_typed_procedure(S_hz_to_radians, g_hz_to_radians_w, 1, 0, 0, H_hz_to_radians, pl_dr);
  10620. Xen_define_typed_procedure(S_radians_to_degrees, g_radians_to_degrees_w, 1, 0, 0, H_radians_to_degrees, pl_dr);
  10621. Xen_define_typed_procedure(S_degrees_to_radians, g_degrees_to_radians_w, 1, 0, 0, H_degrees_to_radians, pl_dr);
  10622. Xen_define_typed_procedure(S_db_to_linear, g_db_to_linear_w, 1, 0, 0, H_db_to_linear, pl_dr);
  10623. Xen_define_typed_procedure(S_linear_to_db, g_linear_to_db_w, 1, 0, 0, H_linear_to_db, pl_dr);
  10624. Xen_define_typed_procedure(S_even_weight, g_even_weight_w, 1, 0, 0, H_even_weight, pl_dr);
  10625. Xen_define_typed_procedure(S_odd_weight, g_odd_weight_w, 1, 0, 0, H_odd_weight, pl_dr);
  10626. Xen_define_typed_procedure(S_even_multiple, g_even_multiple_w, 2, 0, 0, H_even_multiple, pl_dr);
  10627. Xen_define_typed_procedure(S_odd_multiple, g_odd_multiple_w, 2, 0, 0, H_odd_multiple, pl_dr);
  10628. Xen_define_typed_procedure(S_seconds_to_samples, g_seconds_to_samples_w, 1, 0, 0, H_seconds_to_samples, pl_ir);
  10629. Xen_define_typed_procedure(S_samples_to_seconds, g_samples_to_seconds_w, 1, 0, 0, H_samples_to_seconds, pl_dr);
  10630. Xen_define_typed_procedure(S_ring_modulate, g_ring_modulate_w, 2, 0, 0, H_ring_modulate, pl_dr);
  10631. Xen_define_typed_procedure(S_amplitude_modulate, g_amplitude_modulate_w, 3, 0, 0, H_amplitude_modulate, pl_dr);
  10632. Xen_define_typed_procedure(S_contrast_enhancement, g_contrast_enhancement_w, 1, 1, 0, H_contrast_enhancement, pl_dr);
  10633. Xen_define_typed_procedure(S_dot_product, g_dot_product_w, 2, 1, 0, H_dot_product, pl_dffi);
  10634. #if HAVE_COMPLEX_TRIG && HAVE_COMPLEX_NUMBERS && (!HAVE_RUBY)
  10635. Xen_define_typed_procedure(S_edot_product, g_edot_product_w, 2, 0, 0, H_edot_product, NULL);
  10636. #endif
  10637. Xen_define_typed_procedure(S_polynomial, g_polynomial_w, 2, 0, 0, H_polynomial, pl_dfri);
  10638. Xen_define_typed_procedure(S_make_fft_window, g_make_fft_window_w, 2, 2, 0, H_make_fft_window, pl_fiir);
  10639. Xen_define_typed_procedure(S_mus_fft, g_mus_fft_w, 2, 2, 0, H_mus_fft, pl_fffi);
  10640. Xen_define_typed_procedure(S_spectrum, g_spectrum_w, 3, 1, 0, H_mus_spectrum, pl_ffftii);
  10641. Xen_define_typed_procedure(S_autocorrelate, g_autocorrelate_w, 1, 0, 0, H_autocorrelate, pl_ff);
  10642. Xen_define_typed_procedure(S_correlate, g_correlate_w, 2, 0, 0, H_correlate, pl_ff);
  10643. Xen_define_typed_procedure(S_convolution, g_convolution_w, 2, 1, 0, H_mus_convolution, pl_fffi);
  10644. Xen_define_typed_procedure(S_rectangular_to_polar, g_rectangular_to_polar_w, 2, 0, 0, H_rectangular_to_polar, pl_ff);
  10645. Xen_define_typed_procedure(S_rectangular_to_magnitudes, g_rectangular_to_magnitudes_w, 2, 0, 0, H_rectangular_to_magnitudes, pl_ff);
  10646. Xen_define_typed_procedure(S_polar_to_rectangular, g_polar_to_rectangular_w, 2, 0, 0, H_polar_to_rectangular, pl_ff);
  10647. Xen_define_typed_procedure(S_array_interp, g_array_interp_w, 2, 1, 0, H_array_interp, pl_dfri);
  10648. Xen_define_typed_procedure(S_mus_interpolate, g_mus_interpolate_w, 3, 2, 0, H_mus_interpolate, pl_dirfir);
  10649. Xen_define_typed_procedure(S_mus_frandom, g_mus_frandom_w, 1, 0, 0, "random reals", pl_dr);
  10650. Xen_define_typed_procedure(S_mus_irandom, g_mus_irandom_w, 1, 0, 0, "random integers", pl_i);
  10651. Xen_define_constant(S_rectangular_window, MUS_RECTANGULAR_WINDOW, "The un-window, so to speak");
  10652. Xen_define_constant(S_hann_window, MUS_HANN_WINDOW, "A simple raised cosine window");
  10653. Xen_define_constant(S_welch_window, MUS_WELCH_WINDOW, "A triangular window squared");
  10654. Xen_define_constant(S_parzen_window, MUS_PARZEN_WINDOW, "A triangular window");
  10655. Xen_define_constant(S_bartlett_window, MUS_BARTLETT_WINDOW, "A triangular window");
  10656. Xen_define_constant(S_bartlett_hann_window, MUS_BARTLETT_HANN_WINDOW, "A combination of the bartlett and hann windows");
  10657. Xen_define_constant(S_bohman_window, MUS_BOHMAN_WINDOW, "A weighted cosine window");
  10658. Xen_define_constant(S_flat_top_window, MUS_FLAT_TOP_WINDOW, "A sum of cosines window");
  10659. Xen_define_constant(S_hamming_window, MUS_HAMMING_WINDOW, "A raised cosine");
  10660. Xen_define_constant(S_blackman2_window, MUS_BLACKMAN2_WINDOW, "second order cosine window");
  10661. Xen_define_constant(S_blackman3_window, MUS_BLACKMAN3_WINDOW, "third order cosine window");
  10662. Xen_define_constant(S_blackman4_window, MUS_BLACKMAN4_WINDOW, "4th order cosine window");
  10663. Xen_define_constant(S_blackman5_window, MUS_BLACKMAN5_WINDOW, "5th order cosine window");
  10664. Xen_define_constant(S_blackman6_window, MUS_BLACKMAN6_WINDOW, "6th order cosine window");
  10665. Xen_define_constant(S_blackman7_window, MUS_BLACKMAN7_WINDOW, "7th order cosine window");
  10666. Xen_define_constant(S_blackman8_window, MUS_BLACKMAN8_WINDOW, "8th order cosine window");
  10667. Xen_define_constant(S_blackman9_window, MUS_BLACKMAN9_WINDOW, "9th order cosine window");
  10668. Xen_define_constant(S_blackman10_window, MUS_BLACKMAN10_WINDOW, "10th order cosine window");
  10669. Xen_define_constant(S_exponential_window, MUS_EXPONENTIAL_WINDOW, "An inverted triangle from exp");
  10670. Xen_define_constant(S_riemann_window, MUS_RIEMANN_WINDOW, "sinc-based window");
  10671. Xen_define_constant(S_kaiser_window, MUS_KAISER_WINDOW, "Bessel I0 based window");
  10672. Xen_define_constant(S_cauchy_window, MUS_CAUCHY_WINDOW, "window based on 1/(1+sqr(angle)");
  10673. Xen_define_constant(S_poisson_window, MUS_POISSON_WINDOW, "window based on exp(-angle)");
  10674. Xen_define_constant(S_gaussian_window, MUS_GAUSSIAN_WINDOW, "window based on exp(-sqr(angle))");
  10675. Xen_define_constant(S_tukey_window, MUS_TUKEY_WINDOW, "window based on truncated cosine");
  10676. Xen_define_constant(S_dolph_chebyshev_window, MUS_DOLPH_CHEBYSHEV_WINDOW, "window from inverse fft (using Chebyshev Tn)");
  10677. Xen_define_constant(S_connes_window, MUS_CONNES_WINDOW, "triangle window squared twice");
  10678. Xen_define_constant(S_hann_poisson_window, MUS_HANN_POISSON_WINDOW, "poisson window * hann window");
  10679. Xen_define_constant(S_samaraki_window, MUS_SAMARAKI_WINDOW, "window from inverse fft (using Chebyshev Un)");
  10680. Xen_define_constant(S_ultraspherical_window, MUS_ULTRASPHERICAL_WINDOW, "window from inverse fft (using Ultraspherical Cn)");
  10681. Xen_define_constant(S_rv2_window, MUS_RV2_WINDOW, "Rife-Vincent second order window (Hann extension)");
  10682. Xen_define_constant(S_rv3_window, MUS_RV3_WINDOW, "Rife-Vincent third order window (Hann extension)");
  10683. Xen_define_constant(S_rv4_window, MUS_RV4_WINDOW, "Rife-Vincent 4th order window (Hann extension)");
  10684. Xen_define_constant(S_mlt_sine_window, MUS_MLT_SINE_WINDOW, "modulated lapped transform sine window");
  10685. Xen_define_constant(S_papoulis_window, MUS_PAPOULIS_WINDOW, "papoulise window");
  10686. Xen_define_constant(S_dpss_window, MUS_DPSS_WINDOW, "proplate spheroidal (slepian) window");
  10687. Xen_define_constant(S_sinc_window, MUS_SINC_WINDOW, "sinc (Lanczos) window");
  10688. Xen_define_constant(S_mus_interp_linear, MUS_INTERP_LINEAR, "locsig/delay linear interpolation");
  10689. Xen_define_constant(S_mus_interp_sinusoidal, MUS_INTERP_SINUSOIDAL, "locsig sinusoidal interpolation");
  10690. Xen_define_constant(S_mus_interp_all_pass, MUS_INTERP_ALL_PASS, "delay interpolation");
  10691. Xen_define_constant(S_mus_interp_lagrange, MUS_INTERP_LAGRANGE, "second order lagrange interpolation");
  10692. Xen_define_constant(S_mus_interp_hermite, MUS_INTERP_HERMITE, "third order hermite interpolation");
  10693. Xen_define_constant(S_mus_interp_none, MUS_INTERP_NONE, "no interpolation -- step func");
  10694. Xen_define_constant(S_mus_interp_bezier, MUS_INTERP_BEZIER, "bezier interpolation");
  10695. Xen_define_constant(S_mus_chebyshev_first_kind, MUS_CHEBYSHEV_FIRST_KIND, "Chebyshev polynomial of first kind, for " S_partials_to_polynomial);
  10696. Xen_define_constant(S_mus_chebyshev_second_kind, MUS_CHEBYSHEV_SECOND_KIND, "Chebyshev polynomial of second kind, for " S_partials_to_polynomial);
  10697. Xen_define_constant(S_mus_chebyshev_both_kinds, MUS_CHEBYSHEV_BOTH_KINDS, "use both Chebyshev polynomials in polywave");
  10698. Xen_define_typed_procedure(S_mus_describe, g_mus_describe_w, 1, 0, 0, H_mus_describe, pl_sc);
  10699. Xen_define_typed_procedure(S_mus_file_name, g_mus_file_name_w, 1, 0, 0, H_mus_file_name, pl_sc);
  10700. Xen_define_typed_procedure(S_mus_reset, g_mus_reset_w, 1, 0, 0, H_mus_reset, pl_tc);
  10701. Xen_define_typed_procedure(S_mus_copy, g_mus_copy_w, 1, 0, 0, H_mus_copy, pl_cc);
  10702. Xen_define_typed_procedure(S_mus_run, g_mus_run_w, 1, 2, 0, H_mus_run, pl_dcr);
  10703. Xen_define_typed_procedure(S_mus_name, g_mus_name_w, 1, 0, 0, H_mus_name, pl_sc);
  10704. Xen_define_typed_dilambda(S_mus_phase, g_mus_phase_w, H_mus_phase, S_set S_mus_phase, g_mus_set_phase_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10705. Xen_define_typed_dilambda(S_mus_scaler, g_mus_scaler_w, H_mus_scaler, S_set S_mus_scaler, g_mus_set_scaler_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10706. Xen_define_typed_dilambda(S_mus_width, g_mus_width_w, H_mus_width, S_set S_mus_width, g_mus_set_width_w, 1, 0, 2, 0, pl_ic, pl_ici);
  10707. Xen_define_typed_dilambda(S_mus_frequency, g_mus_frequency_w, H_mus_frequency, S_set S_mus_frequency, g_mus_set_frequency_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10708. Xen_define_typed_dilambda(S_mus_length, g_mus_length_w, H_mus_length, S_set S_mus_length, g_mus_set_length_w, 1, 0, 2, 0, pl_it, pl_iti);
  10709. Xen_define_typed_dilambda(S_mus_data, g_mus_data_w, H_mus_data, S_set S_mus_data, g_mus_set_data_w, 1, 0, 2, 0, pl_fc, pl_fcf);
  10710. Xen_define_typed_dilambda(S_mus_xcoeff, g_mus_xcoeff_w, H_mus_xcoeff, S_set S_mus_xcoeff, g_mus_set_xcoeff_w, 2, 0, 3, 0, pl_dci, pl_dcir);
  10711. Xen_define_typed_dilambda(S_mus_ycoeff, g_mus_ycoeff_w, H_mus_ycoeff, S_set S_mus_ycoeff, g_mus_set_ycoeff_w, 2, 0, 3, 0, pl_dci, pl_dcir);
  10712. Xen_define_typed_dilambda(S_mus_offset, g_mus_offset_w, H_mus_offset, S_set S_mus_offset, g_mus_set_offset_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10713. Xen_define_typed_procedure(S_mus_xcoeffs, g_mus_xcoeffs_w, 1, 0, 0, H_mus_xcoeffs, pl_fc);
  10714. Xen_define_typed_procedure(S_mus_ycoeffs, g_mus_ycoeffs_w, 1, 0, 0, H_mus_ycoeffs, pl_fc);
  10715. Xen_define_typed_procedure(S_is_oscil, g_is_oscil_w, 1, 0, 0, H_is_oscil, pl_bt);
  10716. Xen_define_typed_procedure(S_oscil, g_oscil_w, 1, 2, 0, H_oscil, Q_oscil);
  10717. Xen_define_typed_procedure(S_is_oscil_bank, g_is_oscil_bank_w, 1, 0, 0, H_is_oscil_bank, pl_bt);
  10718. Xen_define_typed_procedure(S_oscil_bank, g_oscil_bank_w, 1, 0, 0, H_oscil_bank, pl_dc);
  10719. Xen_define_typed_procedure(S_mus_apply, g_mus_apply_w, 0, 0, 1, H_mus_apply, pl_dcr);
  10720. Xen_define_typed_procedure(S_make_delay, g_make_delay_w, 0, 0, 1, H_make_delay,
  10721. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_delay), t));
  10722. Xen_define_typed_procedure(S_make_comb, g_make_comb_w, 0, 0, 1, H_make_comb,
  10723. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_comb), t));
  10724. Xen_define_typed_procedure(S_make_filtered_comb, g_make_filtered_comb_w, 0, 0, 1, H_make_filtered_comb,
  10725. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_filtered_comb), t));
  10726. Xen_define_typed_procedure(S_make_notch, g_make_notch_w, 0, 0, 1, H_make_notch,
  10727. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_notch), t));
  10728. Xen_define_typed_procedure(S_make_all_pass, g_make_all_pass_w, 0, 0, 1, H_make_all_pass,
  10729. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_all_pass), t));
  10730. Xen_define_typed_procedure(S_make_moving_average, g_make_moving_average_w, 0, 0, 1, H_make_moving_average,
  10731. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_moving_average), t));
  10732. Xen_define_typed_procedure(S_make_moving_max, g_make_moving_max_w, 0, 0, 1, H_make_moving_max,
  10733. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_moving_max), t));
  10734. Xen_define_typed_procedure(S_make_moving_norm, g_make_moving_norm_w, 0, 0, 1, H_make_moving_norm,
  10735. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_moving_norm), t));
  10736. Xen_define_typed_procedure(S_delay, g_delay_w, 1, 2, 0, H_delay,
  10737. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_delay), r));
  10738. Xen_define_typed_procedure(S_delay_tick, g_delay_tick_w, 1, 1, 0, H_delay_tick,
  10739. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_delay), r));
  10740. Xen_define_typed_procedure(S_tap, g_tap_w, 1, 1, 0, H_tap,
  10741. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_delay), r));
  10742. Xen_define_typed_procedure(S_notch, g_notch_w, 1, 2, 0, H_notch,
  10743. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_notch), r));
  10744. Xen_define_typed_procedure(S_comb, g_comb_w, 1, 2, 0, H_comb,
  10745. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_comb), r));
  10746. Xen_define_typed_procedure(S_filtered_comb, g_filtered_comb_w, 1, 2, 0, H_filtered_comb,
  10747. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_filtered_comb), r));
  10748. Xen_define_typed_procedure(S_all_pass, g_all_pass_w, 1, 2, 0, H_all_pass,
  10749. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_all_pass), r));
  10750. Xen_define_typed_procedure(S_moving_average, g_moving_average_w, 1, 1, 0, H_moving_average,
  10751. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_moving_average), r));
  10752. Xen_define_typed_procedure(S_moving_max, g_moving_max_w, 1, 1, 0, H_moving_max,
  10753. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_moving_max), r));
  10754. Xen_define_typed_procedure(S_moving_norm, g_moving_norm_w, 1, 1, 0, H_moving_norm,
  10755. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_moving_norm), r));
  10756. Xen_define_typed_procedure(S_is_tap, g_is_tap_w, 1, 0, 0, H_is_tap, pl_bt);
  10757. Xen_define_typed_procedure(S_is_delay, g_is_delay_w, 1, 0, 0, H_is_delay, pl_bt);
  10758. Xen_define_typed_procedure(S_is_notch, g_is_notch_w, 1, 0, 0, H_is_notch, pl_bt);
  10759. Xen_define_typed_procedure(S_is_comb, g_is_comb_w, 1, 0, 0, H_is_comb, pl_bt);
  10760. Xen_define_typed_procedure(S_is_filtered_comb, g_is_filtered_comb_w, 1, 0, 0, H_is_filtered_comb, pl_bt);
  10761. Xen_define_typed_procedure(S_is_all_pass, g_is_all_pass_w, 1, 0, 0, H_is_all_pass, pl_bt);
  10762. Xen_define_typed_procedure(S_is_moving_average, g_is_moving_average_w, 1, 0, 0, H_is_moving_average, pl_bt);
  10763. Xen_define_typed_procedure(S_is_moving_max, g_is_moving_max_w, 1, 0, 0, H_is_moving_max, pl_bt);
  10764. Xen_define_typed_procedure(S_is_moving_norm, g_is_moving_norm_w, 1, 0, 0, H_is_moving_norm, pl_bt);
  10765. Xen_define_typed_procedure(S_comb_bank, g_comb_bank_w, 1, 1, 0, H_comb_bank,
  10766. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_comb_bank), r));
  10767. Xen_define_typed_procedure(S_is_comb_bank, g_is_comb_bank_w, 1, 0, 0, H_is_comb_bank, pl_bt);
  10768. Xen_define_typed_procedure(S_make_comb_bank, g_make_comb_bank_w, 1, 0, 0, H_make_comb_bank,
  10769. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_comb_bank), t));
  10770. Xen_define_typed_procedure(S_filtered_comb_bank, g_filtered_comb_bank_w, 1, 1, 0, H_filtered_comb_bank,
  10771. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_filtered_comb_bank), r));
  10772. Xen_define_typed_procedure(S_is_filtered_comb_bank, g_is_filtered_comb_bank_w, 1, 0, 0, H_is_filtered_comb_bank, pl_bt);
  10773. Xen_define_typed_procedure(S_make_filtered_comb_bank, g_make_filtered_comb_bank_w, 1, 0, 0, H_make_filtered_comb_bank,
  10774. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_filtered_comb_bank), t));
  10775. Xen_define_typed_procedure(S_all_pass_bank, g_all_pass_bank_w, 1, 1, 0, H_all_pass_bank,
  10776. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_all_pass_bank), r));
  10777. Xen_define_typed_procedure(S_is_all_pass_bank, g_is_all_pass_bank_w, 1, 0, 0, H_is_all_pass_bank, pl_bt);
  10778. Xen_define_typed_procedure(S_make_all_pass_bank, g_make_all_pass_bank_w, 1, 0, 0, H_make_all_pass_bank,
  10779. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_all_pass_bank), t));
  10780. Xen_define_typed_procedure(S_pink_noise, g_pink_noise_w, 1, 0, 0, H_pink_noise, pl_dv);
  10781. Xen_define_typed_procedure(S_out_bank, g_out_bank_w, 3, 0, 0, H_out_bank, pl_dvir);
  10782. Xen_define_typed_dilambda(S_mus_feedback, g_mus_feedback_w, H_mus_feedback,
  10783. S_set S_mus_feedback, g_mus_set_feedback_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10784. Xen_define_typed_dilambda(S_mus_feedforward, g_mus_feedforward_w, H_mus_feedforward,
  10785. S_set S_mus_feedforward, g_mus_set_feedforward_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  10786. Xen_define_typed_procedure(S_make_rand, g_make_rand_w, 0, 0, 1, H_make_rand,
  10787. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_rand), t));
  10788. Xen_define_typed_procedure(S_make_rand_interp, g_make_rand_interp_w, 0, 0, 1, H_make_rand_interp,
  10789. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_rand_interp), t));
  10790. #if HAVE_RUBY
  10791. rb_define_alias(rb_mKernel, "kernel_rand", "rand");
  10792. #endif
  10793. Xen_define_typed_procedure(S_rand, g_rand_w, 1, 1, 0, H_rand,
  10794. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_rand), r));
  10795. Xen_define_typed_procedure(S_rand_interp, g_rand_interp_w, 1, 1, 0, H_rand_interp,
  10796. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_rand_interp), r));
  10797. Xen_define_typed_procedure(S_is_rand, g_is_rand_w, 1, 0, 0, H_is_rand, pl_bt);
  10798. Xen_define_typed_procedure(S_is_rand_interp, g_is_rand_interp_w, 1, 0, 0, H_is_rand_interp, pl_bt);
  10799. Xen_define_typed_procedure(S_mus_random, g_mus_random_w, 1, 0, 0, H_mus_random, pl_dr);
  10800. Xen_define_typed_dilambda(S_mus_rand_seed, g_mus_rand_seed_w, H_mus_rand_seed,
  10801. S_set S_mus_rand_seed, g_mus_set_rand_seed_w, 0, 0, 1, 0, pl_i, pl_i);
  10802. Xen_define_typed_procedure(S_ncos, g_ncos_w, 1, 1, 0, H_ncos,
  10803. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_ncos), r));
  10804. Xen_define_typed_procedure(S_is_ncos, g_is_ncos_w, 1, 0, 0, H_is_ncos, pl_bt);
  10805. Xen_define_typed_procedure(S_nsin, g_nsin_w, 1, 1, 0, H_nsin,
  10806. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_nsin), r));
  10807. Xen_define_typed_procedure(S_is_nsin, g_is_nsin_w, 1, 0, 0, H_is_nsin, pl_bt);
  10808. Xen_define_typed_procedure(S_is_table_lookup, g_is_table_lookup_w, 1, 0, 0, H_is_table_lookup, pl_bt);
  10809. Xen_define_typed_procedure(S_make_table_lookup, g_make_table_lookup_w, 0, 0, 1, H_make_table_lookup,
  10810. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_table_lookup), t));
  10811. Xen_define_typed_procedure(S_table_lookup, g_table_lookup_w, 1, 1, 0, H_table_lookup,
  10812. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_table_lookup), r));
  10813. Xen_define_typed_procedure(S_partials_to_wave, g_partials_to_wave_w, 1, 2, 0, H_partials_to_wave, pl_fttb);
  10814. Xen_define_typed_procedure(S_phase_partials_to_wave, g_phase_partials_to_wave_w, 1, 2, 0, H_phase_partials_to_wave, pl_fttb);
  10815. Xen_define_typed_procedure(S_make_sawtooth_wave, g_make_sawtooth_wave_w, 0, 6, 0, H_make_sawtooth_wave,
  10816. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_sawtooth_wave), t));
  10817. Xen_define_typed_procedure(S_sawtooth_wave, g_sawtooth_wave_w, 1, 1, 0, H_sawtooth_wave,
  10818. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_sawtooth_wave), r));
  10819. Xen_define_typed_procedure(S_is_sawtooth_wave, g_is_sawtooth_wave_w, 1, 0, 0, H_is_sawtooth_wave, pl_bt);
  10820. Xen_define_typed_procedure(S_make_triangle_wave, g_make_triangle_wave_w, 0, 6, 0, H_make_triangle_wave,
  10821. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_triangle_wave), t));
  10822. Xen_define_typed_procedure(S_triangle_wave, g_triangle_wave_w, 1, 1, 0, H_triangle_wave,
  10823. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_triangle_wave), r));
  10824. Xen_define_typed_procedure(S_is_triangle_wave, g_is_triangle_wave_w, 1, 0, 0, H_is_triangle_wave, pl_bt);
  10825. Xen_define_typed_procedure(S_make_square_wave, g_make_square_wave_w, 0, 6, 0, H_make_square_wave,
  10826. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_square_wave), t));
  10827. Xen_define_typed_procedure(S_square_wave, g_square_wave_w, 1, 1, 0, H_square_wave,
  10828. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_square_wave), r));
  10829. Xen_define_typed_procedure(S_is_square_wave, g_is_square_wave_w, 1, 0, 0, H_is_square_wave, pl_bt);
  10830. Xen_define_typed_procedure(S_make_pulse_train, g_make_pulse_train_w, 0, 6, 0, H_make_pulse_train,
  10831. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_pulse_train), t));
  10832. Xen_define_typed_procedure(S_pulse_train, g_pulse_train_w, 1, 1, 0, H_pulse_train,
  10833. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_pulse_train), r));
  10834. Xen_define_typed_procedure(S_is_pulse_train, g_is_pulse_train_w, 1, 0, 0, H_is_pulse_train, pl_bt);
  10835. Xen_define_typed_procedure(S_make_pulsed_env, g_make_pulsed_env_w, 3, 0, 0, H_make_pulsed_env,
  10836. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_pulsed_env), t));
  10837. Xen_define_typed_procedure(S_pulsed_env, g_pulsed_env_w, 1, 1, 0, H_pulsed_env,
  10838. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_pulsed_env), r));
  10839. Xen_define_typed_procedure(S_is_pulsed_env, g_is_pulsed_env_w, 1, 0, 0, H_is_pulsed_env, pl_bt);
  10840. Xen_define_typed_procedure(S_asymmetric_fm, g_asymmetric_fm_w, 1, 2, 0, H_asymmetric_fm,
  10841. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_asymmetric_fm), r));
  10842. Xen_define_typed_procedure(S_is_asymmetric_fm, g_is_asymmetric_fm_w, 1, 0, 0, H_is_asymmetric_fm, pl_bt);
  10843. Xen_define_typed_procedure(S_make_one_zero, g_make_one_zero_w, 0, 4, 0, H_make_one_zero,
  10844. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_one_zero), t));
  10845. Xen_define_typed_procedure(S_one_zero, g_one_zero_w, 1, 1, 0, H_one_zero,
  10846. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_one_zero), r));
  10847. Xen_define_typed_procedure(S_is_one_zero, g_is_one_zero_w, 1, 0, 0, H_is_one_zero, pl_bt);
  10848. Xen_define_typed_procedure(S_make_one_pole, g_make_one_pole_w, 0, 4, 0, H_make_one_pole,
  10849. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_one_pole), t));
  10850. Xen_define_typed_procedure(S_one_pole, g_one_pole_w, 1, 1, 0, H_one_pole,
  10851. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_one_pole), r));
  10852. Xen_define_typed_procedure(S_is_one_pole, g_is_one_pole_w, 1, 0, 0, H_is_one_pole, pl_bt);
  10853. Xen_define_typed_procedure(S_make_two_zero, g_make_two_zero_w, 0, 6, 0, H_make_two_zero,
  10854. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_two_zero), t));
  10855. Xen_define_typed_procedure(S_two_zero, g_two_zero_w, 1, 1, 0, H_two_zero,
  10856. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_two_zero), r));
  10857. Xen_define_typed_procedure(S_is_two_zero, g_is_two_zero_w, 1, 0, 0, H_is_two_zero, pl_bt);
  10858. Xen_define_typed_procedure(S_make_two_pole, g_make_two_pole_w, 0, 6, 0, H_make_two_pole,
  10859. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_two_pole), t));
  10860. Xen_define_typed_procedure(S_two_pole, g_two_pole_w, 1, 1, 0, H_two_pole,
  10861. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_two_pole), r));
  10862. Xen_define_typed_procedure(S_is_two_pole, g_is_two_pole_w, 1, 0, 0, H_is_two_pole, pl_bt);
  10863. Xen_define_typed_procedure(S_make_wave_train, g_make_wave_train_w, 0, 0, 1, H_make_wave_train,
  10864. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_wave_train), t));
  10865. Xen_define_typed_procedure(S_wave_train, g_wave_train_w, 1, 1, 0, H_wave_train,
  10866. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_wave_train), r));
  10867. Xen_define_typed_procedure(S_is_wave_train, g_is_wave_train_w, 1, 0, 0, H_is_wave_train, pl_bt);
  10868. Xen_define_typed_procedure(S_is_formant, g_is_formant_w, 1, 0, 0, H_is_formant, pl_bt);
  10869. Xen_define_typed_procedure(S_make_formant, g_make_formant_w, 0, 4, 0, H_make_formant,
  10870. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_formant), t));
  10871. Xen_define_typed_procedure(S_formant, g_formant_w, 1, 2, 0, H_formant,
  10872. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_formant), r));
  10873. Xen_define_typed_procedure(S_formant_bank, g_formant_bank_w, 1, 1, 0, H_formant_bank,
  10874. s7_make_signature(s7, 3, d, s7_make_symbol(s7, S_is_formant_bank), s7_make_signature(s7, 2, r, f)));
  10875. Xen_define_typed_procedure(S_is_formant_bank, g_is_formant_bank_w, 1, 0, 0, H_is_formant_bank, pl_bt);
  10876. Xen_define_typed_procedure(S_make_formant_bank, g_make_formant_bank_w, 1, 1, 0, H_make_formant_bank,
  10877. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_formant_bank), t));
  10878. Xen_define_typed_procedure(S_is_firmant, g_is_firmant_w, 1, 0, 0, H_is_firmant, pl_bt);
  10879. Xen_define_typed_procedure(S_make_firmant, g_make_firmant_w, 0, 4, 0, H_make_firmant,
  10880. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_firmant), t));
  10881. Xen_define_typed_procedure(S_firmant, g_firmant_w, 1, 2, 0, H_firmant,
  10882. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_firmant), r));
  10883. Xen_define_typed_procedure(S_is_one_pole_all_pass, g_is_one_pole_all_pass_w, 1, 0, 0, H_is_one_pole_all_pass, pl_bt);
  10884. Xen_define_typed_procedure(S_make_one_pole_all_pass, g_make_one_pole_all_pass_w, 2, 0, 0, H_make_one_pole_all_pass,
  10885. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_one_pole_all_pass), t));
  10886. Xen_define_typed_procedure(S_one_pole_all_pass, g_one_pole_all_pass_w, 1, 1, 0, H_one_pole_all_pass,
  10887. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_one_pole_all_pass), r));
  10888. Xen_define_typed_procedure(S_mus_set_formant_frequency, g_set_formant_frequency_w, 2, 0, 0, H_mus_set_formant_frequency, pl_rcr);
  10889. Xen_define_typed_procedure(S_mus_set_formant_radius_and_frequency, g_set_formant_radius_and_frequency_w, 3, 0, 0, H_mus_set_formant_radius_and_frequency, pl_rcrr);
  10890. Xen_define_typed_procedure(S_make_polyshape, g_make_polyshape_w, 0, 0, 1, H_make_polyshape,
  10891. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_polyshape), t));
  10892. Xen_define_typed_procedure(S_polyshape, g_polyshape_w, 1, 2, 0, H_polyshape,
  10893. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_polyshape), r));
  10894. Xen_define_typed_procedure(S_is_polyshape, g_is_polyshape_w, 1, 0, 0, H_is_polyshape, pl_bt);
  10895. Xen_define_typed_procedure(S_partials_to_polynomial, g_partials_to_polynomial_w, 1, 1, 0, H_partials_to_polynomial, pl_fti);
  10896. Xen_define_typed_procedure(S_normalize_partials, g_normalize_partials_w, 1, 0, 0, H_normalize_partials, pl_tt);
  10897. Xen_define_typed_procedure(S_mus_chebyshev_t_sum, g_chebyshev_t_sum_w, 2, 0, 0, H_chebyshev_t_sum, pl_drf);
  10898. Xen_define_typed_procedure(S_mus_chebyshev_u_sum, g_chebyshev_u_sum_w, 2, 0, 0, H_chebyshev_u_sum, pl_drf);
  10899. Xen_define_typed_procedure(S_mus_chebyshev_tu_sum, g_chebyshev_tu_sum_w, 3, 0, 0, H_chebyshev_tu_sum, pl_drf);
  10900. Xen_define_typed_procedure(S_make_polywave, g_make_polywave_w, 0, 0, 1, H_make_polywave,
  10901. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_polywave), t));
  10902. Xen_define_typed_procedure(S_polywave, g_polywave_w, 1, 1, 0, H_polywave,
  10903. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_polywave), r));
  10904. Xen_define_typed_procedure(S_is_polywave, g_is_polywave_w, 1, 0, 0, H_is_polywave, pl_bt);
  10905. Xen_define_typed_procedure(S_make_nrxysin, g_make_nrxysin_w, 0, 0, 1, H_make_nrxysin,
  10906. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_nrxysin), t));
  10907. Xen_define_typed_procedure(S_nrxysin, g_nrxysin_w, 1, 1, 0, H_nrxysin,
  10908. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_nrxysin), r));
  10909. Xen_define_typed_procedure(S_is_nrxysin, g_is_nrxysin_w, 1, 0, 0, H_is_nrxysin, pl_bt);
  10910. Xen_define_typed_procedure(S_make_nrxycos, g_make_nrxycos_w, 0, 0, 1, H_make_nrxycos,
  10911. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_nrxycos), t));
  10912. Xen_define_typed_procedure(S_nrxycos, g_nrxycos_w, 1, 1, 0, H_nrxycos,
  10913. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_nrxycos), r));
  10914. Xen_define_typed_procedure(S_is_nrxycos, g_is_nrxycos_w, 1, 0, 0, H_is_nrxycos, pl_bt);
  10915. Xen_define_typed_procedure(S_make_rxyksin, g_make_rxyksin_w, 0, 0, 1, H_make_rxyksin,
  10916. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_rxyksin), t));
  10917. Xen_define_typed_procedure(S_rxyksin, g_rxyksin_w, 1, 1, 0, H_rxyksin,
  10918. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_rxyksin), r));
  10919. Xen_define_typed_procedure(S_is_rxyksin, g_is_rxyksin_w, 1, 0, 0, H_is_rxyksin, pl_bt);
  10920. Xen_define_typed_procedure(S_make_rxykcos, g_make_rxykcos_w, 0, 0, 1, H_make_rxykcos,
  10921. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_rxykcos), t));
  10922. Xen_define_typed_procedure(S_rxykcos, g_rxykcos_w, 1, 1, 0, H_rxykcos,
  10923. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_rxykcos), r));
  10924. Xen_define_typed_procedure(S_is_rxykcos, g_is_rxykcos_w, 1, 0, 0, H_is_rxykcos, pl_bt);
  10925. Xen_define_typed_procedure(S_make_filter, g_make_filter_w, 0, 6, 0, H_make_filter,
  10926. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_filter), t));
  10927. Xen_define_typed_procedure(S_filter, g_filter_w, 1, 1, 0, H_filter,
  10928. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_filter), r));
  10929. Xen_define_typed_procedure(S_is_filter, g_is_filter_w, 1, 0, 0, H_is_filter, pl_bt);
  10930. Xen_define_typed_procedure(S_make_fir_coeffs, g_make_fir_coeffs_w, 2, 0, 0, H_make_fir_coeffs, pl_fif);
  10931. Xen_define_typed_procedure(S_make_fir_filter, g_make_fir_filter_w, 0, 4, 0, H_make_fir_filter,
  10932. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_fir_filter), t));
  10933. Xen_define_typed_procedure(S_fir_filter, g_fir_filter_w, 1, 1, 0, H_fir_filter,
  10934. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_fir_filter), r));
  10935. Xen_define_typed_procedure(S_is_fir_filter, g_is_fir_filter_w, 1, 0, 0, H_is_fir_filter, pl_bt);
  10936. Xen_define_typed_procedure(S_make_iir_filter, g_make_iir_filter_w, 0, 4, 0, H_make_iir_filter,
  10937. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_iir_filter), t));
  10938. Xen_define_typed_procedure(S_iir_filter, g_iir_filter_w, 1, 1, 0, H_iir_filter,
  10939. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_iir_filter), r));
  10940. Xen_define_typed_procedure(S_is_iir_filter, g_is_iir_filter_w, 1, 0, 0, H_is_iir_filter, pl_bt);
  10941. Xen_define_typed_procedure(S_mus_order, g_mus_order_w, 1, 0, 0, H_mus_order, pl_ic);
  10942. Xen_define_typed_procedure(S_mus_type, g_mus_type_w, 1, 0, 0, H_mus_type, pl_ic);
  10943. Xen_define_typed_procedure(S_is_env, g_is_env_w, 1, 0, 0, H_is_env, pl_bt);
  10944. Xen_define_typed_procedure(S_env, g_env_w, 1, 0, 0, H_env,
  10945. s7_make_signature(s7, 2, d, s7_make_symbol(s7, S_is_env)));
  10946. Xen_define_typed_procedure(S_make_env, g_make_env_w, 0, 0, 1, H_make_env,
  10947. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_env), t));
  10948. Xen_define_typed_procedure(S_env_interp, g_env_interp_w, 2, 0, 0, H_env_interp, pl_drc);
  10949. Xen_define_typed_procedure(S_envelope_interp, g_envelope_interp_w, 2, 1, 0, H_envelope_interp, pl_rrpr);
  10950. Xen_define_typed_procedure(S_env_any, g_env_any_w, 2, 0, 0, H_env_any, pl_dct);
  10951. Xen_define_typed_procedure(S_is_locsig, g_is_locsig_w, 1, 0, 0, H_is_locsig, pl_bt);
  10952. Xen_define_typed_procedure(S_locsig, g_locsig_w, 3, 0, 0, H_locsig,
  10953. s7_make_circular_signature(s7, 2, 3, r, s7_make_symbol(s7, S_is_locsig), r));
  10954. Xen_define_typed_procedure(S_make_locsig, g_make_locsig_w, 0, 0, 1, H_make_locsig,
  10955. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_locsig), t));
  10956. Xen_define_typed_procedure(S_move_locsig, g_move_locsig_w, 3, 0, 0, H_move_locsig, pl_ccrr);
  10957. Xen_define_typed_procedure(S_mus_channels, g_mus_channels_w, 1, 0, 0, H_mus_channels, pl_it);
  10958. #if HAVE_RUBY
  10959. Xen_define_procedure(S_locsig_ref, g_locsig_ref_w, 2, 0, 0, H_locsig_ref);
  10960. Xen_define_procedure(S_locsig_reverb_ref, g_locsig_reverb_ref_w, 2, 0, 0, H_locsig_reverb_ref);
  10961. #endif
  10962. Xen_define_typed_procedure(S_locsig_set, g_locsig_set_w, 3, 0, 0, H_locsig_set, pl_rcir);
  10963. #if HAVE_SCHEME || HAVE_FORTH
  10964. Xen_define_typed_dilambda(S_locsig_ref, g_locsig_ref_w, H_locsig_ref,
  10965. S_set S_locsig_ref, g_locsig_set_w, 2, 0, 3, 0, pl_dci, pl_dcir);
  10966. Xen_define_typed_dilambda(S_locsig_reverb_ref, g_locsig_reverb_ref_w, H_locsig_reverb_ref,
  10967. S_locsig_reverb_set, g_locsig_reverb_set_w, 2, 0, 3, 0, pl_dci, pl_dcir);
  10968. #endif
  10969. Xen_define_typed_procedure(S_locsig_reverb_set, g_locsig_reverb_set_w, 3, 0, 0, H_locsig_reverb_set, pl_rcir);
  10970. Xen_define_typed_dilambda(S_locsig_type, g_locsig_type_w, H_locsig_type,
  10971. S_set S_locsig_type, g_set_locsig_type_w, 0, 0, 1, 0, pl_i, pl_i);
  10972. Xen_define_typed_procedure(S_is_move_sound, g_is_move_sound_w, 1, 0, 0, H_is_move_sound, pl_bt);
  10973. Xen_define_typed_procedure(S_move_sound, g_move_sound_w, 3, 0, 0, H_move_sound,
  10974. s7_make_circular_signature(s7, 2, 3, r, s7_make_symbol(s7, S_is_move_sound), r));
  10975. Xen_define_typed_procedure(S_make_move_sound, g_make_move_sound_w, 1, 2, 0, H_make_move_sound,
  10976. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_move_sound), t));
  10977. Xen_define_typed_procedure(S_is_file_to_sample, g_is_file_to_sample_w, 1, 0, 0, H_is_file_to_sample, pl_bt);
  10978. Xen_define_typed_procedure(S_make_file_to_sample, g_make_file_to_sample_w, 1, 1, 0, H_make_file_to_sample,
  10979. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_file_to_sample), t));
  10980. Xen_define_typed_procedure(S_file_to_sample, g_file_to_sample_w, 2, 1, 0, H_file_to_sample,
  10981. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_file_to_sample), i));
  10982. Xen_define_typed_procedure(S_is_sample_to_file, g_is_sample_to_file_w, 1, 0, 0, H_is_sample_to_file, pl_bt);
  10983. Xen_define_typed_procedure(S_make_sample_to_file, g_make_sample_to_file_w, 1, 4, 0, H_make_sample_to_file,
  10984. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_sample_to_file), t));
  10985. Xen_define_typed_procedure(S_continue_sample_to_file, g_continue_sample_to_file_w, 1, 0, 0, H_continue_sample_to_file, pl_cs);
  10986. Xen_define_typed_procedure(S_sample_to_file, g_sample_to_file_w, 4, 0, 0, H_sample_to_file, pl_rciir);
  10987. Xen_define_typed_procedure(S_sample_to_file_add, g_sample_to_file_add_w, 2, 0, 0, H_sample_to_file_add, pl_cc);
  10988. Xen_define_typed_procedure(S_is_file_to_frample, g_is_file_to_frample_w, 1, 0, 0, H_is_file_to_frample, pl_bt);
  10989. Xen_define_typed_procedure(S_make_file_to_frample, g_make_file_to_frample_w, 1, 1, 0, H_make_file_to_frample,
  10990. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_file_to_frample), t));
  10991. Xen_define_typed_procedure(S_file_to_frample, g_file_to_frample_w, 2, 1, 0, H_file_to_frample, pl_ccic);
  10992. Xen_define_typed_procedure(S_continue_frample_to_file, g_continue_frample_to_file_w, 1, 0, 0, H_continue_frample_to_file, pl_cs);
  10993. Xen_define_typed_procedure(S_is_frample_to_file, g_is_frample_to_file_w, 1, 0, 0, H_is_frample_to_file, pl_bt);
  10994. Xen_define_typed_procedure(S_frample_to_file, g_frample_to_file_w, 3, 0, 0, H_frample_to_file, pl_fcif);
  10995. Xen_define_typed_procedure(S_make_frample_to_file, g_make_frample_to_file_w, 1, 4, 0, H_make_frample_to_file,
  10996. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_frample_to_file), t));
  10997. Xen_define_typed_procedure(S_is_mus_input, g_is_mus_input_w, 1, 0, 0, H_is_mus_input, pl_bt);
  10998. Xen_define_typed_procedure(S_is_mus_output, g_is_mus_output_w, 1, 0, 0, H_is_mus_output, pl_bt);
  10999. Xen_define_typed_procedure(S_in_any, g_in_any_w, 3, 0, 0, H_in_any, pl_diit);
  11000. Xen_define_typed_procedure(S_ina, g_ina_w, 2, 0, 0, H_ina, pl_dit);
  11001. Xen_define_typed_procedure(S_inb, g_inb_w, 2, 0, 0, H_inb, pl_dit);
  11002. Xen_define_typed_procedure(S_out_any, g_out_any_w, 3, 1, 0, H_out_any, pl_ririt);
  11003. Xen_define_typed_procedure(S_outa, g_outa_w, 2, 1, 0, H_outa, pl_rirt);
  11004. Xen_define_typed_procedure(S_outb, g_outb_w, 2, 1, 0, H_outb, pl_rirt);
  11005. Xen_define_typed_procedure(S_outc, g_outc_w, 2, 1, 0, H_outc, pl_rirt);
  11006. Xen_define_typed_procedure(S_outd, g_outd_w, 2, 1, 0, H_outd, pl_rirt);
  11007. Xen_define_typed_procedure(S_mus_close, g_mus_close_w, 1, 0, 0, H_mus_close, pl_tc);
  11008. Xen_define_typed_dilambda(S_mus_file_buffer_size, g_mus_file_buffer_size_w, H_mus_file_buffer_size,
  11009. S_set S_mus_file_buffer_size, g_mus_set_file_buffer_size_w, 0, 0, 1, 0, pl_i, pl_i);
  11010. Xen_define_typed_procedure(S_is_readin, g_is_readin_w, 1, 0, 0, H_is_readin, pl_bt);
  11011. Xen_define_typed_procedure(S_readin, g_readin_w, 1, 0, 0, H_readin,
  11012. s7_make_signature(s7, 2, d, s7_make_symbol(s7, S_is_readin)));
  11013. Xen_define_typed_procedure(S_make_readin, g_make_readin_w, 0, 0, 1, H_make_readin,
  11014. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_readin), t));
  11015. Xen_define_typed_procedure(S_mus_channel, g_mus_channel_w, 1, 0, 0, H_mus_channel, pl_ic);
  11016. Xen_define_typed_procedure(S_mus_interp_type, g_mus_interp_type_w, 1, 0, 0, H_mus_interp_type, pl_ic);
  11017. Xen_define_typed_dilambda(S_mus_location, g_mus_location_w, H_mus_location,
  11018. S_set S_mus_location, g_mus_set_location_w, 1, 0, 2, 0, pl_ic, pl_ici);
  11019. Xen_define_typed_dilambda(S_mus_increment, g_mus_increment_w, H_mus_increment,
  11020. S_set S_mus_increment, g_mus_set_increment_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  11021. Xen_define_typed_procedure(S_is_granulate, g_is_granulate_w, 1, 0, 0, H_is_granulate, pl_bt);
  11022. Xen_define_typed_procedure(S_granulate, g_granulate_w, 1, 2, 0, H_granulate,
  11023. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_granulate), t));
  11024. Xen_define_typed_procedure(S_make_granulate, g_make_granulate_w, 0, 0, 1, H_make_granulate,
  11025. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_granulate), t));
  11026. Xen_define_typed_dilambda(S_mus_ramp, g_mus_ramp_w, H_mus_ramp,
  11027. S_set S_mus_ramp, g_mus_set_ramp_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  11028. Xen_define_typed_procedure(S_clear_sincs, g_mus_clear_sincs_w, 0, 0, 0, "clears out any sinc tables", NULL);
  11029. Xen_define_typed_procedure(S_is_src, g_is_src_w, 1, 0, 0, H_is_src, pl_bt);
  11030. Xen_define_typed_procedure(S_src, g_src_w, 1, 2, 0, H_src,
  11031. s7_make_signature(s7, 4, d, s7_make_symbol(s7, S_is_src), r, t));
  11032. Xen_define_typed_procedure(S_make_src, g_make_src_w, 0, 6, 0, H_make_src,
  11033. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_src), t));
  11034. Xen_define_typed_procedure(S_is_convolve, g_is_convolve_w, 1, 0, 0, H_is_convolve, pl_bt);
  11035. Xen_define_typed_procedure(S_convolve, g_convolve_w, 1, 1, 0, H_convolve_gen,
  11036. s7_make_signature(s7, 3, d, s7_make_symbol(s7, S_is_convolve), t));
  11037. Xen_define_typed_procedure(S_make_convolve, g_make_convolve_w, 0, 0, 1, H_make_convolve,
  11038. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_convolve), t));
  11039. Xen_define_typed_procedure(S_convolve_files, g_convolve_files_w, 2, 2, 0, H_convolve_files, pl_sssrs);
  11040. Xen_define_typed_procedure(S_is_phase_vocoder, g_is_phase_vocoder_w, 1, 0, 0, H_is_phase_vocoder, pl_bt);
  11041. Xen_define_typed_procedure(S_phase_vocoder, g_phase_vocoder_w, 1, 4, 0, H_phase_vocoder,
  11042. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_phase_vocoder), t));
  11043. Xen_define_typed_procedure(S_make_phase_vocoder, g_make_phase_vocoder_w, 0, 0, 1, H_make_phase_vocoder,
  11044. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_phase_vocoder), t));
  11045. Xen_define_typed_procedure(S_phase_vocoder_amp_increments, g_phase_vocoder_amp_increments_w, 1, 0, 0, H_phase_vocoder_amp_increments, pl_fc);
  11046. Xen_define_typed_procedure(S_phase_vocoder_amps, g_phase_vocoder_amps_w, 1, 0, 0, H_phase_vocoder_amps, pl_fc);
  11047. Xen_define_typed_procedure(S_phase_vocoder_freqs, g_phase_vocoder_freqs_w, 1, 0, 0, H_phase_vocoder_freqs, pl_fc);
  11048. Xen_define_typed_procedure(S_phase_vocoder_phases, g_phase_vocoder_phases_w, 1, 0, 0, H_phase_vocoder_phases, pl_fc);
  11049. Xen_define_typed_procedure(S_phase_vocoder_phase_increments, g_phase_vocoder_phase_increments_w, 1, 0, 0, H_phase_vocoder_phase_increments, pl_fc);
  11050. Xen_define_typed_dilambda(S_mus_hop, g_mus_hop_w, H_mus_hop,
  11051. S_set S_mus_hop, g_mus_set_hop_w, 1, 0, 2, 0, pl_dc, pl_dcr);
  11052. Xen_define_typed_procedure(S_make_ssb_am, g_make_ssb_am_w, 0, 4, 0, H_make_ssb_am,
  11053. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_ssb_am), t));
  11054. Xen_define_typed_procedure(S_ssb_am, g_ssb_am_w, 1, 2, 0, H_ssb_am,
  11055. s7_make_circular_signature(s7, 2, 3, d, s7_make_symbol(s7, S_is_ssb_am), r));
  11056. Xen_define_typed_procedure(S_is_ssb_am, g_is_ssb_am_w, 1, 0, 0, H_is_ssb_am, pl_bt);
  11057. Xen_define_typed_procedure(S_is_mus_generator, g_is_mus_generator_w, 1, 0, 0, H_is_mus_generator, pl_bt);
  11058. Xen_define_variable(S_output, clm_output, Xen_false);
  11059. Xen_define_variable(S_reverb, clm_reverb, Xen_false);
  11060. #if HAVE_SCHEME
  11061. {
  11062. s7_pointer clm_output_accessor, clm_reverb_accessor;
  11063. /* these are globals in s7, so they aren't going to move */
  11064. clm_output_slot = s7_slot(s7, clm_output);
  11065. clm_reverb_slot = s7_slot(s7, clm_reverb);
  11066. out_any_2 = out_any_2_to_mus_xen;
  11067. /* these can't be safe functions */
  11068. clm_output_accessor = s7_make_function(s7, "(set " S_output ")", g_clm_output_set, 2, 0, false, "called if " S_output " is set");
  11069. s7_symbol_set_access(s7, s7_make_symbol(s7, S_output), clm_output_accessor);
  11070. clm_reverb_accessor = s7_make_function(s7, "(set " S_reverb ")", g_clm_reverb_set, 2, 0, false, "called if " S_reverb " is set");
  11071. s7_symbol_set_access(s7, s7_make_symbol(s7, S_reverb), clm_reverb_accessor);
  11072. }
  11073. #endif
  11074. #if HAVE_SCHEME && (!_MSC_VER)
  11075. Xen_define_typed_procedure(S_get_internal_real_time, g_get_internal_real_time_w, 0, 0, 0, H_get_internal_real_time, NULL);
  11076. Xen_define_constant(S_internal_time_units_per_second, 1, "units used by " S_get_internal_real_time);
  11077. #endif
  11078. #if HAVE_SCHEME
  11079. Xen_define_typed_procedure(S_piano_noise, g_piano_noise_w, 2, 0, 0, H_piano_noise, pl_djr);
  11080. Xen_define_typed_procedure(S_singer_filter, g_singer_filter_w, 6, 0, 0, H_singer_filter, pl_riirfff);
  11081. Xen_define_typed_procedure(S_singer_nose_filter, g_singer_nose_filter_w, 5, 0, 0, H_singer_nose_filter, pl_rirfff);
  11082. #endif
  11083. Xen_define_typed_procedure(S_make_oscil, g_make_oscil_w, 0, 4, 0, H_make_oscil,
  11084. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_oscil), t));
  11085. Xen_define_typed_procedure(S_make_ncos, g_make_ncos_w, 0, 4, 0, H_make_ncos,
  11086. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_ncos), t));
  11087. Xen_define_typed_procedure(S_make_oscil_bank, g_make_oscil_bank_w, 2, 2, 0, H_make_oscil_bank,
  11088. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_oscil_bank), t));
  11089. Xen_define_typed_procedure(S_make_nsin, g_make_nsin_w, 0, 4, 0, H_make_nsin,
  11090. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_nsin), t));
  11091. Xen_define_typed_procedure(S_make_asymmetric_fm, g_make_asymmetric_fm_w, 0, 8, 0, H_make_asymmetric_fm,
  11092. s7_make_circular_signature(s7, 1, 2, s7_make_symbol(s7, S_is_asymmetric_fm), t));
  11093. Xen_define_typed_procedure(S_mus_file_mix, g_mus_file_mix_w, 0, 0, 1, H_mus_file_mix, NULL);
  11094. Xen_define_typed_procedure(S_mus_file_mix_with_envs, g_mus_file_mix_with_envs_w, 0, 0, 1, H_mus_file_mix_with_envs, NULL); /* actually 8 2 0 I think */
  11095. Xen_define_typed_procedure(S_frample_to_frample, g_frample_to_frample_w, 5, 0, 0, H_frample_to_frample, pl_fffifi);
  11096. #if HAVE_SCHEME
  11097. init_choosers(s7);
  11098. #endif
  11099. /* -------- clm-print (see also snd-xen.c) -------- */
  11100. #if (!USE_SND)
  11101. #if HAVE_FORTH
  11102. Xen_eval_C_string("<'> fth-print alias clm-print ( fmt args -- )");
  11103. #endif
  11104. #if HAVE_RUBY
  11105. Xen_eval_C_string("def clm_print(str, *args)\n\
  11106. $stdout.print format(str, *args)\n\
  11107. end");
  11108. #endif
  11109. #endif
  11110. Xen_provide_feature("clm");
  11111. {
  11112. char *clm_version;
  11113. clm_version = mus_format("clm%d", MUS_VERSION);
  11114. Xen_provide_feature(clm_version);
  11115. free(clm_version);
  11116. }
  11117. #if HAVE_SCHEME && (!_MSC_VER)
  11118. {
  11119. struct timezone z0;
  11120. gettimeofday(&overall_start_time, &z0);
  11121. }
  11122. #endif
  11123. }
  11124. void Init_sndlib(void)
  11125. {
  11126. mus_sndlib_xen_initialize();
  11127. mus_vct_init();
  11128. mus_xen_init();
  11129. #if HAVE_SCHEME
  11130. if (sizeof(mus_float_t) != sizeof(s7_double))
  11131. fprintf(stderr, "in s7-clm, s7_double must match mus_float_t. Currently s7_double has %d bytes, but mus_float_t has %d\n",
  11132. (int)sizeof(s7_double),
  11133. (int)sizeof(mus_float_t));
  11134. #endif
  11135. }
  11136. #if HAVE_SCHEME
  11137. void s7_init_sndlib(s7_scheme *sc)
  11138. {
  11139. s7_xen_initialize(sc);
  11140. Init_sndlib();
  11141. }
  11142. #endif