1 /*
2 * libInstPatch
3 * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; version 2.1
8 * of the License only.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA or on the web at http://www.gnu.org.
19 */
20 /**
21 * SECTION: IpatchUnit_DLS
22 * @short_description: Unit types and conversions for DLS
23 * @see_also:
24 * @stability: Stable
25 */
26 #include <stdio.h>
27 #include <math.h>
28 #include <glib.h>
29 #include <glib-object.h>
30 #include "IpatchUnit_DLS.h"
31 #include "IpatchUnit.h"
32 #include "i18n.h"
33
34
35 static void
36 ipatch_unit_dls_percent_to_percent_value(const GValue *src_val,
37 GValue *dest_val);
38 static void
39 ipatch_unit_percent_to_dls_percent_value(const GValue *src_val,
40 GValue *dest_val);
41 static void ipatch_unit_dls_gain_to_decibels_value(const GValue *src_val,
42 GValue *dest_val);
43 static void ipatch_unit_decibels_to_dls_gain_value(const GValue *src_val,
44 GValue *dest_val);
45 static void
46 ipatch_unit_dls_abs_time_to_seconds_value(const GValue *src_val,
47 GValue *dest_val);
48 static void
49 ipatch_unit_seconds_to_dls_abs_time_value(const GValue *src_val,
50 GValue *dest_val);
51 static void
52 ipatch_unit_dls_rel_time_to_time_cents_value(const GValue *src_val,
53 GValue *dest_val);
54 static void
55 ipatch_unit_time_cents_to_dls_rel_time_value(const GValue *src_val,
56 GValue *dest_val);
57 static void
58 ipatch_unit_dls_abs_pitch_to_hertz_value(const GValue *src_val,
59 GValue *dest_val);
60 static void
61 ipatch_unit_hertz_to_dls_abs_pitch_value(const GValue *src_val,
62 GValue *dest_val);
63 static void
64 ipatch_unit_dls_rel_pitch_to_cents_value(const GValue *src_val,
65 GValue *dest_val);
66 static void
67 ipatch_unit_cents_to_dls_rel_pitch_value(const GValue *src_val,
68 GValue *dest_val);
69
70 /**
71 * _ipatch_unit_dls_init: (skip)
72 */
73 void
_ipatch_unit_dls_init(void)74 _ipatch_unit_dls_init(void)
75 {
76 IpatchUnitInfo *info;
77
78 info = ipatch_unit_info_new();
79 info->label = NULL;
80 info->descr = NULL;
81 info->value_type = G_TYPE_INT;
82 info->digits = 0;
83
84 info->id = IPATCH_UNIT_TYPE_DLS_PERCENT;
85 info->name = "DLSPercent";
86 ipatch_unit_register(info);
87
88 info->id = IPATCH_UNIT_TYPE_DLS_GAIN;
89 info->name = "DLSGain";
90 ipatch_unit_register(info);
91
92 info->id = IPATCH_UNIT_TYPE_DLS_ABS_TIME;
93 info->name = "DLSAbsTime";
94 ipatch_unit_register(info);
95
96 info->id = IPATCH_UNIT_TYPE_DLS_REL_TIME;
97 info->name = "DLSRelTime";
98 ipatch_unit_register(info);
99
100 info->id = IPATCH_UNIT_TYPE_DLS_ABS_PITCH;
101 info->name = "DLSAbsPitch";
102 ipatch_unit_register(info);
103
104 info->id = IPATCH_UNIT_TYPE_DLS_REL_PITCH;
105 info->name = "DLSRelPitch";
106 ipatch_unit_register(info);
107
108 ipatch_unit_info_free(info); /* done with unit info structure, free it */
109
110 ipatch_unit_conversion_register
111 (IPATCH_UNIT_TYPE_DLS_PERCENT, IPATCH_UNIT_TYPE_PERCENT,
112 ipatch_unit_dls_percent_to_percent_value);
113 ipatch_unit_conversion_register
114 (IPATCH_UNIT_TYPE_PERCENT, IPATCH_UNIT_TYPE_DLS_PERCENT,
115 ipatch_unit_percent_to_dls_percent_value);
116
117 ipatch_unit_conversion_register
118 (IPATCH_UNIT_TYPE_DLS_GAIN, IPATCH_UNIT_TYPE_DECIBELS,
119 ipatch_unit_dls_gain_to_decibels_value);
120 ipatch_unit_conversion_register
121 (IPATCH_UNIT_TYPE_DECIBELS, IPATCH_UNIT_TYPE_DLS_GAIN,
122 ipatch_unit_decibels_to_dls_gain_value);
123
124 ipatch_unit_conversion_register
125 (IPATCH_UNIT_TYPE_DLS_ABS_TIME, IPATCH_UNIT_TYPE_SECONDS,
126 ipatch_unit_dls_abs_time_to_seconds_value);
127 ipatch_unit_conversion_register
128 (IPATCH_UNIT_TYPE_SECONDS, IPATCH_UNIT_TYPE_DLS_ABS_TIME,
129 ipatch_unit_seconds_to_dls_abs_time_value);
130
131 ipatch_unit_conversion_register
132 (IPATCH_UNIT_TYPE_DLS_REL_TIME, IPATCH_UNIT_TYPE_TIME_CENTS,
133 ipatch_unit_dls_rel_time_to_time_cents_value);
134 ipatch_unit_conversion_register
135 (IPATCH_UNIT_TYPE_TIME_CENTS, IPATCH_UNIT_TYPE_DLS_REL_TIME,
136 ipatch_unit_time_cents_to_dls_rel_time_value);
137
138 ipatch_unit_conversion_register
139 (IPATCH_UNIT_TYPE_DLS_ABS_PITCH, IPATCH_UNIT_TYPE_HERTZ,
140 ipatch_unit_dls_abs_pitch_to_hertz_value);
141 ipatch_unit_conversion_register
142 (IPATCH_UNIT_TYPE_HERTZ, IPATCH_UNIT_TYPE_DLS_ABS_PITCH,
143 ipatch_unit_hertz_to_dls_abs_pitch_value);
144
145 ipatch_unit_conversion_register
146 (IPATCH_UNIT_TYPE_DLS_REL_PITCH, IPATCH_UNIT_TYPE_CENTS,
147 ipatch_unit_dls_rel_pitch_to_cents_value);
148 ipatch_unit_conversion_register
149 (IPATCH_UNIT_TYPE_CENTS, IPATCH_UNIT_TYPE_DLS_REL_PITCH,
150 ipatch_unit_cents_to_dls_rel_pitch_value);
151
152
153 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
154 IPATCH_UNIT_TYPE_DLS_PERCENT,
155 IPATCH_UNIT_TYPE_PERCENT);
156 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
157 IPATCH_UNIT_TYPE_DLS_GAIN,
158 IPATCH_UNIT_TYPE_DECIBELS);
159 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
160 IPATCH_UNIT_TYPE_DLS_ABS_TIME,
161 IPATCH_UNIT_TYPE_SECONDS);
162 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
163 IPATCH_UNIT_TYPE_DLS_REL_TIME,
164 IPATCH_UNIT_TYPE_TIME_CENTS);
165 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
166 IPATCH_UNIT_TYPE_DLS_ABS_PITCH,
167 IPATCH_UNIT_TYPE_HERTZ);
168 ipatch_unit_class_register_map(IPATCH_UNIT_CLASS_USER,
169 IPATCH_UNIT_TYPE_DLS_REL_PITCH,
170 IPATCH_UNIT_TYPE_CENTS);
171 }
172
173 /**
174 * ipatch_unit_dls_class_convert:
175 * @src_units: Source unit type ID
176 * @src_val: Source value (type should be compatible with the source unit's
177 * value type)
178 *
179 * Converts a value to "DLS" units. DLS units are unit types that
180 * are used by DLS (Downloadable Sounds) patches. The #IPATCH_UNIT_CLASS_DLS
181 * map is used to lookup the corresponding type to convert to.
182 * Only some types have an associated DLS type. It is an error to pass a
183 * @src_units type that has no DLS mapping (note that this is contrary to the
184 * behavior of ipatch_unit_user_class_convert()).
185 *
186 * Returns: The value converted to DLS units.
187 */
188 int
ipatch_unit_dls_class_convert(guint16 src_units,const GValue * src_val)189 ipatch_unit_dls_class_convert(guint16 src_units, const GValue *src_val)
190 {
191 IpatchUnitInfo *dest_info;
192 GValue v = { 0 };
193 int retval;
194
195 g_return_val_if_fail(src_val != NULL, 0);
196
197 dest_info = ipatch_unit_class_lookup_map(IPATCH_UNIT_CLASS_DLS, src_units);
198 g_return_val_if_fail(dest_info != NULL, 0);
199
200 g_value_init(&v, G_TYPE_INT);
201 ipatch_unit_convert(src_units, dest_info->id, src_val, &v);
202
203 retval = g_value_get_int(&v);
204 g_value_unset(&v); /* probably not needed, for the sake of extra paranoia (TM) */
205
206 return (retval);
207 }
208
209 /**
210 * ipatch_unit_dls_percent_to_percent:
211 * @dls_percent: Value in DLS percent units
212 *
213 * Convert value in DLS percent units to percent.
214 *
215 * percent = dls_percent / (10 * 65536)
216 *
217 * Returns: Value in percent
218 */
219 double
ipatch_unit_dls_percent_to_percent(int dls_percent)220 ipatch_unit_dls_percent_to_percent(int dls_percent)
221 {
222 return ((double)dls_percent / 655360.0);
223 }
224
225 /**
226 * ipatch_unit_percent_to_dls_percent:
227 * @percent: Value in percent
228 *
229 * Convert percent to DLS percent.
230 *
231 * dls_percent = percent * 10 * 65536
232 *
233 * Returns: Converted integer in DLS percent
234 */
235 int
ipatch_unit_percent_to_dls_percent(double percent)236 ipatch_unit_percent_to_dls_percent(double percent)
237 {
238 return (int)(percent * 655360.0 + 0.5); /* +0.5 for rounding */
239 }
240
241 /**
242 * ipatch_unit_dls_gain_to_decibels:
243 * @dls_gain: Value in DLS gain units
244 *
245 * Converts a value from DLS gain to decibels.
246 *
247 * dls_gain = 200 * 65536 * log10 (V / v)
248 * decibels = 20 * log10 (V / v)
249 *
250 * Returns: Value converted to decibels
251 */
252 double
ipatch_unit_dls_gain_to_decibels(int dls_gain)253 ipatch_unit_dls_gain_to_decibels(int dls_gain)
254 {
255 return ((double)dls_gain / 655360.0);
256 }
257
258 /**
259 * ipatch_unit_decibels_to_dls_gain:
260 * @db: Value in decibels
261 *
262 * Converts a value from decibels to DLS gain.
263 * See ipatch_unit_dls_gain_to_decibel()
264 *
265 * Returns: Value converted to DLS gain
266 */
267 int
ipatch_unit_decibels_to_dls_gain(double db)268 ipatch_unit_decibels_to_dls_gain(double db)
269 {
270 return (int)(db * 655360.0 + 0.5);
271 }
272
273 /**
274 * ipatch_unit_dls_abs_time_to_seconds:
275 * @dls_abs_time: Value in DLS absolute time
276 *
277 * Converts a value from DLS absolute time to seconds.
278 * seconds = 2^(dls_abs_time / (1200 * 65536))
279 *
280 * 0x80000000 is used as a 0 value.
281 *
282 * Returns: Value converted to seconds
283 */
284 double
ipatch_unit_dls_abs_time_to_seconds(gint32 dls_abs_time)285 ipatch_unit_dls_abs_time_to_seconds(gint32 dls_abs_time)
286 {
287 if(dls_abs_time == IPATCH_UNIT_DLS_ABS_TIME_0SECS)
288 {
289 return (0.0);
290 }
291
292 return (pow(2.0, (double)dls_abs_time / (1200 * 65536)));
293 }
294
295 /**
296 * ipatch_unit_seconds_to_dls_abs_time:
297 * @seconds: Value in seconds
298 *
299 * Converts a value from seconds to DLS absolute time.
300 * dls_rel_time = 1200 * log2 (seconds) * 65536
301 *
302 * Returns: Value converted to DLS relative time
303 */
304 gint32
ipatch_unit_seconds_to_dls_abs_time(double seconds)305 ipatch_unit_seconds_to_dls_abs_time(double seconds)
306 {
307 if(seconds == 0.0)
308 {
309 return (IPATCH_UNIT_DLS_ABS_TIME_0SECS);
310 }
311
312 return (gint32)((double)1200.0 * (log(seconds) / log(2.0)) * 65536.0 + 0.5);
313 }
314
315 /**
316 * ipatch_unit_dls_rel_time_to_time_cents:
317 * @dls_rel_time: Value in DLS relative time
318 *
319 * Converts a value from DLS relative time to time cents.
320 * time_cents = dls_rel_time / 65536
321 *
322 * Returns: Value converted to time cents
323 */
324 double
ipatch_unit_dls_rel_time_to_time_cents(int dls_rel_time)325 ipatch_unit_dls_rel_time_to_time_cents(int dls_rel_time)
326 {
327 return (dls_rel_time / 65536.0);
328 }
329
330 /**
331 * ipatch_unit_time_cents_to_dls_rel_time:
332 * @time_cents: Value in time cents
333 *
334 * Converts a value from time_cents to DLS relative time.
335 * dls_rel_time = time_cents * 65536
336 *
337 * Returns: Value converted to DLS relative time
338 */
339 int
ipatch_unit_time_cents_to_dls_rel_time(double time_cents)340 ipatch_unit_time_cents_to_dls_rel_time(double time_cents)
341 {
342 return (int)(time_cents * 65536.0 + 0.5);
343 }
344
345 /**
346 * ipatch_unit_dls_abs_pitch_to_hertz:
347 * @dls_abs_pitch: Value in DLS absolute pitch
348 *
349 * Converts a value from DLS absolute pitch to hertz.
350 * hertz = 440 * 2^((dls_abs_pitch / 65536 - 6900) / 1200)
351 *
352 * Returns: Value converted to hertz
353 */
354 double
ipatch_unit_dls_abs_pitch_to_hertz(int dls_abs_pitch)355 ipatch_unit_dls_abs_pitch_to_hertz(int dls_abs_pitch)
356 {
357 return ((double)440.0 * pow(2.0, (dls_abs_pitch / 65536.0 - 6900.0) / 1200.0));
358 }
359
360 /**
361 * ipatch_unit_hertz_to_dls_abs_pitch:
362 * @hertz: Value in hertz
363 *
364 * Converts a value from hertz to DLS absolute pitch.
365 * dls_abs_pitch = (1200 * log2(hertz/440) + 6900) * 65536
366 *
367 * Returns: Value converted to DLS absolute pitch
368 */
369 int
ipatch_unit_hertz_to_dls_abs_pitch(double hertz)370 ipatch_unit_hertz_to_dls_abs_pitch(double hertz)
371 {
372 return (int)(((double)1200.0 * (log(hertz / 440.0) / log(2)) + 6900.0) * 65536.0 + 0.5);
373 }
374
375 /**
376 * ipatch_unit_dls_rel_pitch_to_cents:
377 * @dls_rel_pitch: Value in DLS relative pitch
378 *
379 * Converts a value from DLS relative pitch to cents.
380 * cents = dls_rel_pitch / 65536
381 *
382 * Returns: Value converted to cents
383 */
384 double
ipatch_unit_dls_rel_pitch_to_cents(int dls_rel_pitch)385 ipatch_unit_dls_rel_pitch_to_cents(int dls_rel_pitch)
386 {
387 return ((double)dls_rel_pitch / 65536.0);
388 }
389
390 /**
391 * ipatch_unit_cents_to_dls_rel_pitch:
392 * @cents: Value in cents
393 *
394 * Converts a value from cents to DLS relative pitch.
395 * dls_rel_pitch = cents * 65536
396 *
397 * Returns: Value converted to DLS relative pitch
398 */
399 int
ipatch_unit_cents_to_dls_rel_pitch(double cents)400 ipatch_unit_cents_to_dls_rel_pitch(double cents)
401 {
402 return (int)(cents * 65536.0 + 0.5);
403 }
404
405
406 /* =================================================
407 GValue conversion functions, duplicated for speed
408 ================================================= */
409
410
411 static void
ipatch_unit_dls_percent_to_percent_value(const GValue * src_val,GValue * dest_val)412 ipatch_unit_dls_percent_to_percent_value(const GValue *src_val,
413 GValue *dest_val)
414 {
415 int dls_percent = g_value_get_int(src_val);
416 g_value_set_double(dest_val, (double)dls_percent / 655360.0);
417 }
418
419 static void
ipatch_unit_percent_to_dls_percent_value(const GValue * src_val,GValue * dest_val)420 ipatch_unit_percent_to_dls_percent_value(const GValue *src_val,
421 GValue *dest_val)
422 {
423 double percent = g_value_get_double(src_val);
424 g_value_set_int(dest_val, (gint)(percent * 655360.0 + 0.5));
425 }
426
427 static void
ipatch_unit_dls_gain_to_decibels_value(const GValue * src_val,GValue * dest_val)428 ipatch_unit_dls_gain_to_decibels_value(const GValue *src_val, GValue *dest_val)
429 {
430 int dls_gain = g_value_get_int(src_val);
431 g_value_set_double(dest_val, (double)dls_gain / 655360.0);
432 }
433
434 static void
ipatch_unit_decibels_to_dls_gain_value(const GValue * src_val,GValue * dest_val)435 ipatch_unit_decibels_to_dls_gain_value(const GValue *src_val, GValue *dest_val)
436 {
437 double db = g_value_get_double(src_val);
438 g_value_set_int(dest_val, (gint)(db * 655360.0 + 0.5));
439 }
440
441 static void
ipatch_unit_dls_abs_time_to_seconds_value(const GValue * src_val,GValue * dest_val)442 ipatch_unit_dls_abs_time_to_seconds_value(const GValue *src_val,
443 GValue *dest_val)
444 {
445 int dls_abs_time = g_value_get_int(src_val);
446 double secs;
447
448 if(dls_abs_time != IPATCH_UNIT_DLS_ABS_TIME_0SECS)
449 {
450 secs = pow(2.0, (double)dls_abs_time / (1200 * 65536));
451 }
452 else
453 {
454 secs = 0.0;
455 }
456
457 g_value_set_double(dest_val, secs);
458 }
459
460 static void
ipatch_unit_seconds_to_dls_abs_time_value(const GValue * src_val,GValue * dest_val)461 ipatch_unit_seconds_to_dls_abs_time_value(const GValue *src_val,
462 GValue *dest_val)
463 {
464 double secs = g_value_get_double(src_val);
465 int dls_abs_time;
466
467 if(secs != 0.0)
468 {
469 dls_abs_time = (int)((double)1200.0 * (log(secs) / log(2.0)) * 65536.0 + 0.5);
470 }
471 else
472 {
473 dls_abs_time = IPATCH_UNIT_DLS_ABS_TIME_0SECS;
474 }
475
476 g_value_set_int(dest_val, dls_abs_time);
477 }
478
479 static void
ipatch_unit_dls_rel_time_to_time_cents_value(const GValue * src_val,GValue * dest_val)480 ipatch_unit_dls_rel_time_to_time_cents_value(const GValue *src_val,
481 GValue *dest_val)
482 {
483 int dls_rel_time = g_value_get_int(src_val);
484 g_value_set_double(dest_val, (double)dls_rel_time / 65536.0);
485 }
486
487 static void
ipatch_unit_time_cents_to_dls_rel_time_value(const GValue * src_val,GValue * dest_val)488 ipatch_unit_time_cents_to_dls_rel_time_value(const GValue *src_val,
489 GValue *dest_val)
490 {
491 double time_cents = g_value_get_double(src_val);
492 g_value_set_int(dest_val, (gint)(time_cents * 65536.0 + 0.5));
493 }
494
495 static void
ipatch_unit_dls_abs_pitch_to_hertz_value(const GValue * src_val,GValue * dest_val)496 ipatch_unit_dls_abs_pitch_to_hertz_value(const GValue *src_val,
497 GValue *dest_val)
498 {
499 int dls_abs_pitch = g_value_get_int(src_val);
500 g_value_set_double(dest_val, 440.0 * pow(2.0, ((double)dls_abs_pitch
501 / 65536.0 - 6900.0) / 1200.0));
502 }
503
504 static void
ipatch_unit_hertz_to_dls_abs_pitch_value(const GValue * src_val,GValue * dest_val)505 ipatch_unit_hertz_to_dls_abs_pitch_value(const GValue *src_val,
506 GValue *dest_val)
507 {
508 double hertz = g_value_get_double(src_val);
509 g_value_set_int(dest_val, (gint)(((double)1200.0 * (log(hertz / 440.0) / log(2))
510 + 6900.0) * 65536.0 + 0.5));
511 }
512
513 static void
ipatch_unit_dls_rel_pitch_to_cents_value(const GValue * src_val,GValue * dest_val)514 ipatch_unit_dls_rel_pitch_to_cents_value(const GValue *src_val,
515 GValue *dest_val)
516 {
517 int dls_rel_pitch = g_value_get_int(src_val);
518 g_value_set_double(dest_val, (double)dls_rel_pitch / 65536.0);
519 }
520
521 static void
ipatch_unit_cents_to_dls_rel_pitch_value(const GValue * src_val,GValue * dest_val)522 ipatch_unit_cents_to_dls_rel_pitch_value(const GValue *src_val,
523 GValue *dest_val)
524 {
525 double cents = g_value_get_double(src_val);
526 g_value_set_int(dest_val, (gint)(cents * 65536.0 + 0.5));
527 }
528