1 /* Extended Module Player
2 * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include "common.h"
27 #include "virtual.h"
28 #include "mixer.h"
29 #include "period.h"
30 #include "player.h" /* for set_sample_end() */
31
32 #ifdef LIBXMP_PAULA_SIMULATOR
33 #include "paula.h"
34 #endif
35
36
37 #define FLAG_16_BITS 0x01
38 #define FLAG_STEREO 0x02
39 #define FLAG_FILTER 0x04
40 #define FLAG_ACTIVE 0x10
41 /* #define FLAG_SYNTH 0x20 */
42 #define FIDX_FLAGMASK (FLAG_16_BITS | FLAG_STEREO | FLAG_FILTER)
43
44 #define DOWNMIX_SHIFT 12
45 #define LIM8_HI 127
46 #define LIM8_LO -128
47 #define LIM16_HI 32767
48 #define LIM16_LO -32768
49
50 #define MIX_FN(x) void libxmp_mix_##x(struct mixer_voice *, int32 *, int, int, int, int, int, int, int)
51
52 MIX_FN(mono_8bit_nearest);
53 MIX_FN(mono_8bit_linear);
54 MIX_FN(mono_16bit_nearest);
55 MIX_FN(mono_16bit_linear);
56 MIX_FN(stereo_8bit_nearest);
57 MIX_FN(stereo_8bit_linear);
58 MIX_FN(stereo_16bit_nearest);
59 MIX_FN(stereo_16bit_linear);
60 MIX_FN(mono_8bit_spline);
61 MIX_FN(mono_16bit_spline);
62 MIX_FN(stereo_8bit_spline);
63 MIX_FN(stereo_16bit_spline);
64
65 #ifndef LIBXMP_CORE_DISABLE_IT
66 MIX_FN(mono_8bit_linear_filter);
67 MIX_FN(mono_16bit_linear_filter);
68 MIX_FN(stereo_8bit_linear_filter);
69 MIX_FN(stereo_16bit_linear_filter);
70 MIX_FN(mono_8bit_spline_filter);
71 MIX_FN(mono_16bit_spline_filter);
72 MIX_FN(stereo_8bit_spline_filter);
73 MIX_FN(stereo_16bit_spline_filter);
74 #endif
75
76 #ifdef LIBXMP_PAULA_SIMULATOR
77 MIX_FN(mono_a500);
78 MIX_FN(mono_a500_filter);
79 MIX_FN(stereo_a500);
80 MIX_FN(stereo_a500_filter);
81 #endif
82
83 /* Mixers array index:
84 *
85 * bit 0: 0=8 bit sample, 1=16 bit sample
86 * bit 1: 0=mono output, 1=stereo output
87 * bit 2: 0=unfiltered, 1=filtered
88 */
89
90 typedef void (*mixer_set[])(struct mixer_voice *, int32 *, int, int, int, int, int, int, int);
91
92 static mixer_set nearest_mixers = {
93 libxmp_mix_mono_8bit_nearest,
94 libxmp_mix_mono_16bit_nearest,
95 libxmp_mix_stereo_8bit_nearest,
96 libxmp_mix_stereo_16bit_nearest,
97
98 #ifndef LIBXMP_CORE_DISABLE_IT
99 libxmp_mix_mono_8bit_nearest,
100 libxmp_mix_mono_16bit_nearest,
101 libxmp_mix_stereo_8bit_nearest,
102 libxmp_mix_stereo_16bit_nearest,
103 #endif
104 };
105
106 static mixer_set linear_mixers = {
107 libxmp_mix_mono_8bit_linear,
108 libxmp_mix_mono_16bit_linear,
109 libxmp_mix_stereo_8bit_linear,
110 libxmp_mix_stereo_16bit_linear,
111
112 #ifndef LIBXMP_CORE_DISABLE_IT
113 libxmp_mix_mono_8bit_linear_filter,
114 libxmp_mix_mono_16bit_linear_filter,
115 libxmp_mix_stereo_8bit_linear_filter,
116 libxmp_mix_stereo_16bit_linear_filter
117 #endif
118 };
119
120 static mixer_set spline_mixers = {
121 libxmp_mix_mono_8bit_spline,
122 libxmp_mix_mono_16bit_spline,
123 libxmp_mix_stereo_8bit_spline,
124 libxmp_mix_stereo_16bit_spline,
125
126 #ifndef LIBXMP_CORE_DISABLE_IT
127 libxmp_mix_mono_8bit_spline_filter,
128 libxmp_mix_mono_16bit_spline_filter,
129 libxmp_mix_stereo_8bit_spline_filter,
130 libxmp_mix_stereo_16bit_spline_filter
131 #endif
132 };
133
134 #ifdef LIBXMP_PAULA_SIMULATOR
135 static mixer_set a500_mixers = {
136 libxmp_mix_mono_a500,
137 NULL,
138 libxmp_mix_stereo_a500,
139 NULL,
140 NULL,
141 NULL,
142 NULL,
143 NULL
144 };
145
146
147 static mixer_set a500led_mixers = {
148 libxmp_mix_mono_a500_filter,
149 NULL,
150 libxmp_mix_stereo_a500_filter,
151 NULL,
152 NULL,
153 NULL,
154 NULL,
155 NULL
156 };
157 #endif
158
159
160 /* Downmix 32bit samples to 8bit, signed or unsigned, mono or stereo output */
downmix_int_8bit(int8 * dest,int32 * src,int num,int amp,int offs)161 static void downmix_int_8bit(int8 *dest, int32 *src, int num, int amp, int offs)
162 {
163 int smp;
164 int shift = DOWNMIX_SHIFT + 8 - amp;
165
166 for (; num--; src++, dest++) {
167 smp = *src >> shift;
168 if (smp > LIM8_HI) {
169 *dest = LIM8_HI;
170 } else if (smp < LIM8_LO) {
171 *dest = LIM8_LO;
172 } else {
173 *dest = smp;
174 }
175
176 if (offs) *dest += offs;
177 }
178 }
179
180
181 /* Downmix 32bit samples to 16bit, signed or unsigned, mono or stereo output */
downmix_int_16bit(int16 * dest,int32 * src,int num,int amp,int offs)182 static void downmix_int_16bit(int16 *dest, int32 *src, int num, int amp, int offs)
183 {
184 int smp;
185 int shift = DOWNMIX_SHIFT - amp;
186
187 for (; num--; src++, dest++) {
188 smp = *src >> shift;
189 if (smp > LIM16_HI) {
190 *dest = LIM16_HI;
191 } else if (smp < LIM16_LO) {
192 *dest = LIM16_LO;
193 } else {
194 *dest = smp;
195 }
196
197 if (offs) *dest += offs;
198 }
199 }
200
anticlick(struct mixer_voice * vi)201 static void anticlick(struct mixer_voice *vi)
202 {
203 vi->flags |= ANTICLICK;
204 vi->old_vl = 0;
205 vi->old_vr = 0;
206 }
207
208 /* Ok, it's messy, but it works :-) Hipolito */
do_anticlick(struct context_data * ctx,int voc,int32 * buf,int count)209 static void do_anticlick(struct context_data *ctx, int voc, int32 *buf, int count)
210 {
211 struct player_data *p = &ctx->p;
212 struct mixer_data *s = &ctx->s;
213 struct mixer_voice *vi = &p->virt.voice_array[voc];
214 int smp_l, smp_r, max_x2;
215 int discharge = s->ticksize >> ANTICLICK_SHIFT;
216
217 smp_r = vi->sright;
218 smp_l = vi->sleft;
219 vi->sright = vi->sleft = 0;
220
221 if (smp_l == 0 && smp_r == 0) {
222 return;
223 }
224
225 if (buf == NULL) {
226 buf = s->buf32;
227 count = discharge;
228 } else if (count > discharge) {
229 count = discharge;
230 }
231
232 if (count <= 0) {
233 return;
234 }
235
236 max_x2 = count * count;
237
238 while (count--) {
239 if (~s->format & XMP_FORMAT_MONO) {
240 *buf++ += (count * (smp_r >> 10) / max_x2 * count) << 10;
241 }
242
243 *buf++ += (count * (smp_l >> 10) / max_x2 * count) << 10;
244 }
245 }
246
set_sample_end(struct context_data * ctx,int voc,int end)247 static void set_sample_end(struct context_data *ctx, int voc, int end)
248 {
249 struct player_data *p = &ctx->p;
250 struct module_data *m = &ctx->m;
251 struct mixer_voice *vi = &p->virt.voice_array[voc];
252 struct channel_data *xc;
253
254 if ((uint32)voc >= p->virt.maxvoc)
255 return;
256
257 xc = &p->xc_data[vi->chn];
258
259 if (end) {
260 SET_NOTE(NOTE_SAMPLE_END);
261 if (HAS_QUIRK(QUIRK_RSTCHN)) {
262 libxmp_virt_resetvoice(ctx, voc, 0);
263 }
264 } else {
265 RESET_NOTE(NOTE_SAMPLE_END);
266 }
267 }
268
adjust_voice_end(struct mixer_voice * vi,struct xmp_sample * xxs)269 static void adjust_voice_end(struct mixer_voice *vi, struct xmp_sample *xxs)
270 {
271 if (xxs->flg & XMP_SAMPLE_LOOP) {
272 if ((xxs->flg & XMP_SAMPLE_LOOP_FULL) && (~vi->flags & SAMPLE_LOOP)) {
273 vi->end = xxs->len;
274 } else {
275 vi->end = xxs->lpe;
276 }
277 } else {
278 vi->end = xxs->len;
279 }
280 }
281
loop_reposition(struct context_data * ctx,struct mixer_voice * vi,struct xmp_sample * xxs)282 static void loop_reposition(struct context_data *ctx, struct mixer_voice *vi, struct xmp_sample *xxs)
283 {
284 #ifndef LIBXMP_CORE_DISABLE_IT
285 struct module_data *m = &ctx->m;
286 #endif
287 int loop_size = xxs->lpe - xxs->lps;
288
289 /* Reposition for next loop */
290 vi->pos -= loop_size; /* forward loop */
291 vi->end = xxs->lpe;
292 vi->flags |= SAMPLE_LOOP;
293
294 if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
295 vi->end += loop_size; /* unrolled loop */
296 vi->pos -= loop_size; /* forward loop */
297
298 #ifndef LIBXMP_CORE_DISABLE_IT
299 /* OpenMPT Bidi-Loops.it: "In Impulse Tracker’s software mixer,
300 * ping-pong loops are shortened by one sample.
301 */
302 if (IS_PLAYER_MODE_IT()) {
303 vi->end--;
304 vi->pos++;
305 }
306 #endif
307 }
308 }
309
310
311 /* Prepare the mixer for the next tick */
libxmp_mixer_prepare(struct context_data * ctx)312 void libxmp_mixer_prepare(struct context_data *ctx)
313 {
314 struct player_data *p = &ctx->p;
315 struct module_data *m = &ctx->m;
316 struct mixer_data *s = &ctx->s;
317 int bytelen;
318
319 s->ticksize = (int)(s->freq * m->time_factor * m->rrate / p->bpm / 1000);
320
321 bytelen = s->ticksize * sizeof(int);
322 if (~s->format & XMP_FORMAT_MONO) {
323 bytelen *= 2;
324 }
325 memset(s->buf32, 0, bytelen);
326 }
327 /* Fill the output buffer calling one of the handlers. The buffer contains
328 * sound for one tick (a PAL frame or 1/50s for standard vblank-timed mods)
329 */
libxmp_mixer_softmixer(struct context_data * ctx)330 void libxmp_mixer_softmixer(struct context_data *ctx)
331 {
332 struct player_data *p = &ctx->p;
333 struct mixer_data *s = &ctx->s;
334 struct module_data *m = &ctx->m;
335 struct xmp_module *mod = &m->mod;
336 struct xmp_sample *xxs;
337 struct mixer_voice *vi;
338 double step;
339 int samples, size;
340 int vol_l, vol_r, voc, usmp;
341 int prev_l, prev_r = 0;
342 int lps, lpe;
343 int32 *buf_pos;
344 void (*mix_fn)(struct mixer_voice *, int32 *, int, int, int, int, int, int, int);
345 mixer_set *mixers;
346
347 switch (s->interp) {
348 case XMP_INTERP_NEAREST:
349 mixers = (mixer_set *)&nearest_mixers;
350 break;
351 case XMP_INTERP_LINEAR:
352 mixers = (mixer_set *)&linear_mixers;
353 break;
354 case XMP_INTERP_SPLINE:
355 mixers = (mixer_set *)&spline_mixers;
356 break;
357 default:
358 mixers = (mixer_set *)&linear_mixers;
359 }
360
361 #ifdef LIBXMP_PAULA_SIMULATOR
362 if (p->flags & XMP_FLAGS_A500) {
363 if (IS_AMIGA_MOD()) {
364 if (p->filter) {
365 mixers = (mixer_set *)&a500led_mixers;
366 } else {
367 mixers = (mixer_set *)&a500_mixers;
368 }
369 }
370 }
371 #endif
372
373 libxmp_mixer_prepare(ctx);
374
375 for (voc = 0; voc < p->virt.maxvoc; voc++) {
376 int c5spd, rampsize, delta_l, delta_r;
377
378 vi = &p->virt.voice_array[voc];
379
380 if (vi->flags & ANTICLICK) {
381 if (s->interp > XMP_INTERP_NEAREST) {
382 do_anticlick(ctx, voc, NULL, 0);
383 }
384 vi->flags &= ~ANTICLICK;
385 }
386
387 if (vi->chn < 0) {
388 continue;
389 }
390
391 if (vi->period < 1) {
392 libxmp_virt_resetvoice(ctx, voc, 1);
393 continue;
394 }
395
396 vi->pos0 = (int)vi->pos;
397
398 buf_pos = s->buf32;
399 if (vi->pan == PAN_SURROUND) {
400 vol_r = vi->vol * 0x80;
401 vol_l = -vi->vol * 0x80;
402 } else {
403 vol_r = vi->vol * (0x80 - vi->pan);
404 vol_l = vi->vol * (0x80 + vi->pan);
405 }
406
407 if (vi->smp < mod->smp) {
408 xxs = &mod->xxs[vi->smp];
409 c5spd = (int) m->xtra[vi->smp].c5spd;
410 } else {
411 xxs = &ctx->smix.xxs[vi->smp - mod->smp];
412 c5spd = m->c4rate;
413 }
414
415 step = C4_PERIOD * c5spd / s->freq / vi->period;
416
417 if (step < 0.001) { /* otherwise m5v-nwlf.it crashes */
418 continue;
419 }
420
421 #ifndef LIBXMP_CORE_DISABLE_IT
422 if (xxs->flg & XMP_SAMPLE_SLOOP && vi->smp < mod->smp) {
423 if (~vi->flags & VOICE_RELEASE) {
424 if (vi->pos < m->xsmp[vi->smp].lpe) {
425 xxs = &m->xsmp[vi->smp];
426 }
427 }
428 }
429
430 adjust_voice_end(vi, xxs);
431 #endif
432
433 lps = xxs->lps;
434 lpe = xxs->lpe;
435
436 if (p->flags & XMP_FLAGS_FIXLOOP) {
437 lps >>= 1;
438 }
439
440 if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
441 vi->end += lpe - lps;
442
443 #ifndef LIBXMP_CORE_DISABLE_IT
444 if (IS_PLAYER_MODE_IT()) {
445 vi->end--;
446 }
447 #endif
448 }
449
450 rampsize = s->ticksize >> ANTICLICK_SHIFT;
451 delta_l = (vol_l - vi->old_vl) / rampsize;
452 delta_r = (vol_r - vi->old_vr) / rampsize;
453
454 usmp = 0;
455 for (size = s->ticksize; size > 0; ) {
456 int split_noloop = 0;
457
458 if (p->xc_data[vi->chn].split) {
459 split_noloop = 1;
460 }
461
462 /* How many samples we can write before the loop break
463 * or sample end... */
464 if (vi->pos >= vi->end) {
465 samples = 0;
466 usmp = 1;
467 } else {
468 int s = (int) ceil(((double)vi->end - vi->pos) / step);
469 /* ...inside the tick boundaries */
470 if (s > size) {
471 s = size;
472 }
473
474 samples = s;
475 if (samples > 0) {
476 usmp = 0;
477 }
478 }
479
480 if (vi->vol) {
481 int mix_size = samples;
482 int mixer = vi->fidx & FIDX_FLAGMASK;
483
484 if (~s->format & XMP_FORMAT_MONO) {
485 mix_size *= 2;
486 }
487
488 /* For Hipolito's anticlick routine */
489 if (samples > 0) {
490 if (~s->format & XMP_FORMAT_MONO) {
491 prev_r = buf_pos[mix_size - 2];
492 }
493 prev_l = buf_pos[mix_size - 1];
494 } else {
495 prev_r = prev_l = 0;
496 }
497
498 #ifndef LIBXMP_CORE_DISABLE_IT
499 /* See OpenMPT env-flt-max.it */
500 if (vi->filter.cutoff >= 0xfe &&
501 vi->filter.resonance == 0) {
502 mixer &= ~FLAG_FILTER;
503 }
504 #endif
505
506 mix_fn = (*mixers)[mixer];
507
508 /* Call the output handler */
509 if (samples > 0 && vi->sptr != NULL) {
510 int rsize = 0;
511
512 if (rampsize > samples) {
513 rampsize -= samples;
514 } else {
515 rsize = samples - rampsize;
516 rampsize = 0;
517 }
518
519 if (delta_l == 0 && delta_r == 0) {
520 /* no need to ramp */
521 rsize = samples;
522 }
523
524 if (mix_fn != NULL) {
525 mix_fn(vi, buf_pos, samples,
526 vol_l >> 8, vol_r >> 8, (int) (step * (1 << SMIX_SHIFT)), rsize, delta_l, delta_r);
527 }
528
529 buf_pos += mix_size;
530 vi->old_vl += samples * delta_l;
531 vi->old_vr += samples * delta_r;
532
533
534 /* For Hipolito's anticlick routine */
535 if (~s->format & XMP_FORMAT_MONO) {
536 vi->sright = buf_pos[-2] - prev_r;
537 }
538 vi->sleft = buf_pos[-1] - prev_l;
539 }
540 }
541
542 vi->pos += step * samples;
543
544 /* No more samples in this tick */
545 size -= samples + usmp;
546 if (size <= 0) {
547 if (xxs->flg & XMP_SAMPLE_LOOP) {
548 if (vi->pos + step > vi->end) {
549 vi->pos += step;
550 loop_reposition(ctx, vi, xxs);
551 }
552 }
553 continue;
554 }
555
556 /* First sample loop run */
557 if ((~xxs->flg & XMP_SAMPLE_LOOP) || split_noloop) {
558 do_anticlick(ctx, voc, buf_pos, size);
559 set_sample_end(ctx, voc, 1);
560 size = 0;
561 continue;
562 }
563
564 loop_reposition(ctx, vi, xxs);
565 }
566
567 vi->old_vl = vol_l;
568 vi->old_vr = vol_r;
569 }
570
571 /* Render final frame */
572
573 size = s->ticksize;
574 if (~s->format & XMP_FORMAT_MONO) {
575 size *= 2;
576 }
577
578 if (size > XMP_MAX_FRAMESIZE) {
579 size = XMP_MAX_FRAMESIZE;
580 }
581
582 if (s->format & XMP_FORMAT_8BIT) {
583 downmix_int_8bit((int8 *)s->buffer, s->buf32, size, s->amplify,
584 s->format & XMP_FORMAT_UNSIGNED ? 0x80 : 0);
585 } else {
586 downmix_int_16bit((int16 *)s->buffer, s->buf32, size,s->amplify,
587 s->format & XMP_FORMAT_UNSIGNED ? 0x8000 : 0);
588 }
589
590 s->dtright = s->dtleft = 0;
591 }
592
libxmp_mixer_voicepos(struct context_data * ctx,int voc,double pos,int ac)593 void libxmp_mixer_voicepos(struct context_data *ctx, int voc, double pos, int ac)
594 {
595 struct player_data *p = &ctx->p;
596 struct module_data *m = &ctx->m;
597 struct mixer_voice *vi = &p->virt.voice_array[voc];
598 struct xmp_sample *xxs;
599 int lps;
600
601 if (vi->smp < m->mod.smp) {
602 xxs = &m->mod.xxs[vi->smp];
603 } else {
604 xxs = &ctx->smix.xxs[vi->smp - m->mod.smp];
605 }
606
607 if (xxs->flg & XMP_SAMPLE_SYNTH) {
608 return;
609 }
610
611 vi->pos = pos;
612
613 adjust_voice_end(vi, xxs);
614
615 if (vi->pos >= vi->end) {
616 if (xxs->flg & XMP_SAMPLE_LOOP) {
617 vi->pos = xxs->lps;
618 } else {
619 vi->pos = xxs->len;
620 }
621 }
622
623 lps = xxs->lps;
624 if (p->flags & XMP_FLAGS_FIXLOOP) {
625 lps >>= 1;
626 }
627
628 if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
629 vi->end += (xxs->lpe - lps);
630
631 #ifndef LIBXMP_CORE_DISABLE_IT
632 if (IS_PLAYER_MODE_IT()) {
633 vi->end--;
634 }
635 #endif
636 }
637
638 if (ac) {
639 anticlick(vi);
640 }
641 }
642
libxmp_mixer_getvoicepos(struct context_data * ctx,int voc)643 double libxmp_mixer_getvoicepos(struct context_data *ctx, int voc)
644 {
645 struct player_data *p = &ctx->p;
646 struct mixer_voice *vi = &p->virt.voice_array[voc];
647 struct xmp_sample *xxs;
648
649 xxs = libxmp_get_sample(ctx, vi->smp);
650
651 if (xxs->flg & XMP_SAMPLE_SYNTH) {
652 return 0;
653 }
654
655 if (xxs->flg & XMP_SAMPLE_LOOP_BIDIR) {
656 if (vi->pos >= xxs->lpe) {
657 return xxs->lpe - (vi->pos - xxs->lpe) - 1;
658 }
659 }
660
661 return vi->pos;
662 }
663
libxmp_mixer_setpatch(struct context_data * ctx,int voc,int smp,int ac)664 void libxmp_mixer_setpatch(struct context_data *ctx, int voc, int smp, int ac)
665 {
666 struct player_data *p = &ctx->p;
667 #ifndef LIBXMP_CORE_DISABLE_IT
668 struct module_data *m = &ctx->m;
669 #endif
670 struct mixer_data *s = &ctx->s;
671 struct mixer_voice *vi = &p->virt.voice_array[voc];
672 struct xmp_sample *xxs;
673
674 xxs = libxmp_get_sample(ctx, smp);
675
676 vi->smp = smp;
677 vi->vol = 0;
678 vi->pan = 0;
679 vi->flags &= ~SAMPLE_LOOP;
680
681 vi->fidx = 0;
682
683 if (~s->format & XMP_FORMAT_MONO) {
684 vi->fidx |= FLAG_STEREO;
685 }
686
687 set_sample_end(ctx, voc, 0);
688
689 /*mixer_setvol(ctx, voc, 0);*/
690
691 vi->sptr = xxs->data;
692 vi->fidx |= FLAG_ACTIVE;
693
694 #ifndef LIBXMP_CORE_DISABLE_IT
695 if (HAS_QUIRK(QUIRK_FILTER) && s->dsp & XMP_DSP_LOWPASS) {
696 vi->fidx |= FLAG_FILTER;
697 }
698 #endif
699
700 if (xxs->flg & XMP_SAMPLE_16BIT) {
701 vi->fidx |= FLAG_16_BITS;
702 }
703
704 libxmp_mixer_voicepos(ctx, voc, 0, ac);
705 }
706
libxmp_mixer_setnote(struct context_data * ctx,int voc,int note)707 void libxmp_mixer_setnote(struct context_data *ctx, int voc, int note)
708 {
709 struct player_data *p = &ctx->p;
710 struct mixer_voice *vi = &p->virt.voice_array[voc];
711
712 /* FIXME: Workaround for crash on notes that are too high
713 * see 6nations.it (+114 transposition on instrument 16)
714 */
715 if (note > 149) {
716 note = 149;
717 }
718
719 vi->note = note;
720 vi->period = libxmp_note_to_period_mix(note, 0);
721
722 anticlick(vi);
723 }
724
libxmp_mixer_setperiod(struct context_data * ctx,int voc,double period)725 void libxmp_mixer_setperiod(struct context_data *ctx, int voc, double period)
726 {
727 struct player_data *p = &ctx->p;
728 struct mixer_voice *vi = &p->virt.voice_array[voc];
729
730 vi->period = period;
731 }
732
libxmp_mixer_setvol(struct context_data * ctx,int voc,int vol)733 void libxmp_mixer_setvol(struct context_data *ctx, int voc, int vol)
734 {
735 struct player_data *p = &ctx->p;
736 struct mixer_voice *vi = &p->virt.voice_array[voc];
737
738 if (vol == 0) {
739 anticlick(vi);
740 }
741
742 vi->vol = vol;
743 }
744
libxmp_mixer_release(struct context_data * ctx,int voc,int rel)745 void libxmp_mixer_release(struct context_data *ctx, int voc, int rel)
746 {
747 struct player_data *p = &ctx->p;
748 struct mixer_voice *vi = &p->virt.voice_array[voc];
749
750 if (rel) {
751 vi->flags |= VOICE_RELEASE;
752 } else {
753 vi->flags &= ~VOICE_RELEASE;
754 }
755 }
756
libxmp_mixer_seteffect(struct context_data * ctx,int voc,int type,int val)757 void libxmp_mixer_seteffect(struct context_data *ctx, int voc, int type, int val)
758 {
759 #ifndef LIBXMP_CORE_DISABLE_IT
760 struct player_data *p = &ctx->p;
761 struct mixer_voice *vi = &p->virt.voice_array[voc];
762
763 switch (type) {
764 case DSP_EFFECT_CUTOFF:
765 vi->filter.cutoff = val;
766 break;
767 case DSP_EFFECT_RESONANCE:
768 vi->filter.resonance = val;
769 break;
770 case DSP_EFFECT_FILTER_A0:
771 vi->filter.a0 = val;
772 break;
773 case DSP_EFFECT_FILTER_B0:
774 vi->filter.b0 = val;
775 break;
776 case DSP_EFFECT_FILTER_B1:
777 vi->filter.b1 = val;
778 break;
779 }
780 #endif
781 }
782
libxmp_mixer_setpan(struct context_data * ctx,int voc,int pan)783 void libxmp_mixer_setpan(struct context_data *ctx, int voc, int pan)
784 {
785 struct player_data *p = &ctx->p;
786 struct mixer_voice *vi = &p->virt.voice_array[voc];
787
788 vi->pan = pan;
789 }
790
libxmp_mixer_numvoices(struct context_data * ctx,int num)791 int libxmp_mixer_numvoices(struct context_data *ctx, int num)
792 {
793 struct mixer_data *s = &ctx->s;
794
795 if (num > s->numvoc || num < 0) {
796 return s->numvoc;
797 } else {
798 return num;
799 }
800 }
801
libxmp_mixer_on(struct context_data * ctx,int rate,int format,int c4rate)802 int libxmp_mixer_on(struct context_data *ctx, int rate, int format, int c4rate)
803 {
804 struct mixer_data *s = &ctx->s;
805
806 s->buffer = (char *)calloc(2, XMP_MAX_FRAMESIZE);
807 if (s->buffer == NULL)
808 goto err;
809
810 s->buf32 = (int32 *)calloc(sizeof(int32), XMP_MAX_FRAMESIZE);
811 if (s->buf32 == NULL)
812 goto err1;
813
814 s->freq = rate;
815 s->format = format;
816 s->amplify = DEFAULT_AMPLIFY;
817 s->mix = DEFAULT_MIX;
818 /* s->pbase = C4_PERIOD * c4rate / s->freq; */
819 s->interp = XMP_INTERP_LINEAR; /* default interpolation type */
820 s->dsp = XMP_DSP_LOWPASS; /* enable filters by default */
821 /* s->numvoc = SMIX_NUMVOC; */
822 s->dtright = s->dtleft = 0;
823
824 return 0;
825
826 err1:
827 free(s->buffer);
828 err:
829 return -1;
830 }
831
libxmp_mixer_off(struct context_data * ctx)832 void libxmp_mixer_off(struct context_data *ctx)
833 {
834 struct mixer_data *s = &ctx->s;
835
836 free(s->buffer);
837 free(s->buf32);
838 s->buf32 = NULL;
839 s->buffer = NULL;
840 }
841