1
2 /*
3 * The Real SoundTracker - Cubically interpolating mixing routines
4 * with IT style filter support
5 *
6 * Copyright (C) 2001-2019 Michael Krause
7 * Copyright (C) 1999-2000 Tammo Hinrichs
8
9 * Despite its name, this mixer can run on every platform.
10
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include <config.h>
27
28 #include <glib/gi18n.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "kbfloat-core.h"
35 #include "mixer.h"
36 #include "tracer.h"
37 #include "st-subs.h"
38
39 static int num_channels, mixfreq;
40 static float fmixfreq;
41 static int clipflag;
42
43 static float* kb_x86_tempbuf = NULL;
44 static int kb_x86_tempbufsize = 0;
45
46 static float kb_x86_amplification = 0.25;
47
48 float kb_x86_ct0[256];
49 float kb_x86_ct1[256];
50 float kb_x86_ct2[256];
51 float kb_x86_ct3[256];
52
53 typedef struct kb_x86_channel {
54 st_mixer_sample_info* sample;
55
56 void* data; // for updatesample() to see if sample has changed
57 int looptype;
58 guint32 length;
59
60 guint32 flags; // see below
61 float volume; // 0.0 ... 1.0
62 float panning; // 0.0 ... 1.0
63 int direction; // +1 for forward, -1 for backward
64 guint32 playend; // for a forced premature end of the sample
65
66 float volleft; // left volume (1.0 = no change)
67 float volright; // rite volume (1.0 = no change)
68
69 guint32 ramp_num_samples; // number of mixer output samples during which ramping is active
70 float rampleft; // left volramp (delta_vol per sample)
71 float rampright; // rite volramp (delta_vol per sample)
72 float rampdestleft; // ramp destination volume left
73 float rampdestright; // ramp destination volume right
74
75 guint32 positionw; // current sample position (whole part of 32.32)
76 guint32 positionf; // current sample position (fractional part of 32.32)
77 guint32 freqw; // frequency (whole part of 32.32)
78 guint32 freqf; // frequency (fractional part of 32.32)
79
80 float ffreq; // filter frequency (0<=x<=1)
81 float freso; // filter resonance (0<=x<1)
82 float fl1; // filter lp buffer
83 float fb1; // filter bp buffer
84 gboolean filter_on;
85 } kb_x86_channel;
86
87 #define KB_FLAG_LOOP_UNIDIRECTIONAL 1
88 #define KB_FLAG_LOOP_BIDIRECTIONAL 2
89 #define KB_FLAG_SAMPLE_RUNNING 4
90 #define KB_FLAG_JUST_STARTED 8
91 #define KB_FLAG_UPPER_ACTIVE 16
92 #define KB_FLAG_STOP_AFTER_VOLRAMP 32
93 #define KB_FLAG_DO_SAMPLE_START_DECLICK 64
94
95 // This is an artificial limit. The code can do more channels.
96 static kb_x86_channel channels[2 * 32];
97
98 // Number of samples the mixer needs in advance
99 #define KB_X86_SAMPLE_PADDING 3
100
101 // A ramp from 32768 to 0 should take RAMP_MAX_DURATION seconds
102 #define RAMP_MAX_DURATION 0.001
103
104 static void
kb_x86_setnumch(int n)105 kb_x86_setnumch(int n)
106 {
107 g_assert(n >= 1 && n <= 32);
108
109 num_channels = n;
110 }
111
112 /* This is just a quick hack to implement sample-change declicking
113 without coding full virtual channel support. But this will come
114 sooner or later so that hack is only temporary.
115
116 It works like this: When a sample is stopped and a new one is
117 immediately started, there usually results a little click. In order
118 to avoid it, we let the old sample continue, but start a quick
119 volume downramp on it towards 0 (so that the click gets a linear
120 ramp and it's not that disturbing). It's obvious that for the time
121 of the volume ramp, we need to store the kb_x86_channel data blocks
122 of both the old channel and the new channel. Because of this, our
123 channels[] array is twice as large, and in the lower copy, the
124 KB_FLAG_UPPER_ACTIVE flag is active when the upper copy is the
125 one with the currently running main sample and the lower copy is
126 only the fading out old sample.
127
128 Alle Klarheiten beseitigt? :-) As I said before, full
129 virtual-channel support will make this superfluous.
130 */
131 static kb_x86_channel*
kb_x86_get_channel_struct(int channel)132 kb_x86_get_channel_struct(int channel)
133 {
134 kb_x86_channel* c = &channels[channel];
135
136 if (c->flags & KB_FLAG_UPPER_ACTIVE) {
137 c = &channels[channel + 32];
138 }
139
140 return c;
141 }
142
143 static void
kb_x86_updatesample(st_mixer_sample_info * si)144 kb_x86_updatesample(st_mixer_sample_info* si)
145 {
146 int i;
147 kb_x86_channel* c;
148
149 for (i = 0; i < 2 * 32; i++) {
150 c = &channels[i];
151
152 if (c->sample != si || !(c->flags & KB_FLAG_SAMPLE_RUNNING)) {
153 continue;
154 }
155
156 if (c->data != si->data
157 || c->length != si->length
158 || c->looptype != si->looptype) {
159 c->flags &= ~KB_FLAG_SAMPLE_RUNNING;
160 continue;
161 }
162
163 /* No relevant data has changed. Don't stop the sample, but update
164 our local loop data instead. */
165 c->looptype = si->looptype;
166 if (c->looptype != ST_MIXER_SAMPLE_LOOPTYPE_NONE) {
167 if (c->positionw < si->loopstart) {
168 c->positionw = si->loopstart;
169 c->positionf = 0x7fffffff;
170 } else if (c->positionw >= si->loopend) {
171 c->positionw = si->loopend - 1;
172 c->positionf = 0x7fffffff;
173 }
174 }
175 }
176 }
177
178 static gboolean
kb_x86_setmixformat(int format)179 kb_x86_setmixformat(int format)
180 {
181 if (format != 16)
182 return FALSE;
183
184 return TRUE;
185 }
186
187 static gboolean
kb_x86_setstereo(int on)188 kb_x86_setstereo(int on)
189 {
190 if (!on)
191 return FALSE;
192
193 return TRUE;
194 }
195
196 static void
kb_x86_setmixfreq(guint32 frequency)197 kb_x86_setmixfreq(guint32 frequency)
198 {
199 mixfreq = frequency;
200 fmixfreq = 48000.0 / (float)mixfreq;
201 }
202
203 static void
kb_x86_setampfactor(float amplification)204 kb_x86_setampfactor(float amplification)
205 {
206 kb_x86_amplification = 0.25 * amplification;
207 }
208
209 static gboolean
kb_x86_getclipflag(void)210 kb_x86_getclipflag(void)
211 {
212 return clipflag;
213 }
214
215 static void
kb_x86_reset(void)216 kb_x86_reset(void)
217 {
218 int i;
219
220 memset(channels, 0, sizeof(channels));
221 clipflag = 0;
222
223 for (i = 0; i < 256; i++) {
224 float x1 = i / 256.0;
225 float x2 = x1 * x1;
226 float x3 = x1 * x1 * x1;
227 kb_x86_ct0[i] = -0.5 * x3 + x2 - 0.5 * x1;
228 kb_x86_ct1[i] = 1.5 * x3 - 2.5 * x2 + 1;
229 kb_x86_ct2[i] = -1.5 * x3 + 2 * x2 + 0.5 * x1;
230 kb_x86_ct3[i] = 0.5 * x3 - 0.5 * x2;
231 }
232 }
233
234 static void
kb_x86_startnote(int channel,st_mixer_sample_info * s)235 kb_x86_startnote(int channel,
236 st_mixer_sample_info* s)
237 {
238 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
239
240 c->flags &= KB_FLAG_UPPER_ACTIVE;
241
242 c->sample = s;
243
244 // The following three for update_sample()
245 c->data = s->data;
246 c->length = s->length;
247 c->looptype = s->looptype;
248
249 c->positionw = 0;
250 c->positionf = 0;
251 c->playend = 0;
252 if (s->looptype == ST_MIXER_SAMPLE_LOOPTYPE_AMIGA) {
253 c->flags |= KB_FLAG_LOOP_UNIDIRECTIONAL;
254 } else if (s->looptype == ST_MIXER_SAMPLE_LOOPTYPE_PINGPONG) {
255 c->flags |= KB_FLAG_LOOP_BIDIRECTIONAL;
256 }
257 c->direction = 1;
258 c->ramp_num_samples = 0;
259 c->freso = 0.0;
260 c->ffreq = fmixfreq;
261 c->filter_on = FALSE;
262 c->fl1 = 0.0;
263 c->fb1 = 0.0;
264 c->flags |= KB_FLAG_SAMPLE_RUNNING | KB_FLAG_JUST_STARTED;
265 }
266
267 static void
kb_x86_stopnote(int channel)268 kb_x86_stopnote(int channel)
269 {
270 kb_x86_channel* c = &channels[channel];
271 kb_x86_channel* current_used_chan = kb_x86_get_channel_struct(channel);
272
273 if (current_used_chan->flags & KB_FLAG_SAMPLE_RUNNING) {
274 if (current_used_chan != c) {
275 c->flags &= ~KB_FLAG_UPPER_ACTIVE;
276 } else {
277 c->flags |= KB_FLAG_UPPER_ACTIVE;
278 }
279
280 c = current_used_chan;
281
282 c->flags |= KB_FLAG_STOP_AFTER_VOLRAMP;
283
284 c->ramp_num_samples = RAMP_MAX_DURATION * mixfreq;
285 if (c->ramp_num_samples == 0) {
286 c->ramp_num_samples = 1;
287 }
288 c->rampdestleft = 0;
289 c->rampdestright = 0;
290 c->rampleft = (c->rampdestleft - c->volleft) / c->ramp_num_samples;
291 c->rampright = (c->rampdestright - c->volright) / c->ramp_num_samples;
292 }
293 }
294
295 static void
kb_x86_setsmplpos(int channel,guint32 offset)296 kb_x86_setsmplpos(int channel,
297 guint32 offset)
298 {
299 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
300
301 if (c->sample && c->flags != 0) {
302 if (offset < c->sample->length) {
303 c->positionw = offset;
304 c->positionf = 0;
305 c->direction = 1;
306
307 if (c->flags & KB_FLAG_JUST_STARTED && offset > 0) {
308 /* User has used 9xx command - declick sample start */
309 c->flags |= KB_FLAG_DO_SAMPLE_START_DECLICK;
310 }
311 } else {
312 c->flags &= KB_FLAG_UPPER_ACTIVE;
313 }
314 }
315 }
316
317 static void
kb_x86_setsmplend(int channel,guint32 offset)318 kb_x86_setsmplend(int channel,
319 guint32 offset)
320 {
321 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
322
323 if (c->sample && c->flags != 0) {
324 if (c->positionw != 0 || offset < c->sample->length) {
325 // only end if the selection is not the whole sample
326 c->playend = offset;
327 }
328 }
329 }
330
331 static void
kb_x86_setfreq(int channel,float frequency)332 kb_x86_setfreq(int channel,
333 float frequency)
334 {
335 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
336
337 frequency /= mixfreq;
338
339 c->freqw = (guint32)floor(frequency);
340 c->freqf = (guint32)((frequency - c->freqw) * 4294967296.0 /* this is pow(2,32) */);
341 }
342
343 static void
kb_x86_redo_vol_fields(kb_x86_channel * c)344 kb_x86_redo_vol_fields(kb_x86_channel* c)
345 {
346 c->rampdestleft = c->volume * (1.0 - c->panning);
347 c->rampdestright = c->volume * c->panning;
348 g_assert(c->rampdestleft >= 0.0 && c->rampdestleft <= 1.0);
349 g_assert(c->rampdestright >= 0.0 && c->rampdestright <= 1.0);
350
351 if (c->flags & KB_FLAG_JUST_STARTED) {
352 c->volleft = c->rampdestleft;
353 c->volright = c->rampdestright;
354 } else {
355 c->ramp_num_samples = RAMP_MAX_DURATION * mixfreq;
356 if (c->ramp_num_samples == 0) {
357 c->ramp_num_samples = 1;
358 }
359 c->rampleft = (c->rampdestleft - c->volleft) / c->ramp_num_samples;
360 c->rampright = (c->rampdestright - c->volright) / c->ramp_num_samples;
361 }
362 }
363
364 static void
kb_x86_setvolume(int channel,float volume)365 kb_x86_setvolume(int channel,
366 float volume)
367 {
368 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
369
370 c->volume = volume;
371 kb_x86_redo_vol_fields(c);
372 }
373
374 static void
kb_x86_setpanning(int channel,float panning)375 kb_x86_setpanning(int channel,
376 float panning)
377 {
378 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
379
380 c->panning = 0.5 * (panning + 1.0);
381 kb_x86_redo_vol_fields(c);
382 }
383
384 static void
kb_x86_setchcutoff(int channel,float freq)385 kb_x86_setchcutoff(int channel,
386 float freq)
387 {
388 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
389
390 if (freq < 0.0) {
391 c->ffreq = fmixfreq;
392 c->freso = 0.0;
393 c->filter_on = FALSE;
394 } else {
395 g_assert(0.0 <= freq);
396 g_assert(freq <= 1.0);
397 c->ffreq = freq * fmixfreq;
398 c->filter_on = TRUE;
399 }
400 }
401
402 static void
kb_x86_setchreso(int channel,float reso)403 kb_x86_setchreso(int channel,
404 float reso)
405 {
406 kb_x86_channel* c = kb_x86_get_channel_struct(channel);
407
408 g_assert(0.0 <= reso);
409 g_assert(reso <= 1.0);
410 c->freso = reso;
411 }
412
413 #if defined(DEBUG_BUFFER)
414 static void
kb_x86_debug_dump_buffer(gint16 * buffer,int count)415 kb_x86_debug_dump_buffer(gint16* buffer,
416 int count)
417 {
418 int i;
419
420 printf("{ ");
421 for (i = 0; i < count; i++) {
422 if (i > 0) {
423 printf(", ");
424 }
425 printf("%d", buffer[i]);
426 }
427 printf(" }\n");
428 }
429 #endif
430
431 static void
kb_x86_call_mixer(kb_x86_channel * ch,kb_x86_mixer_data * md,gboolean forward)432 kb_x86_call_mixer(kb_x86_channel* ch,
433 kb_x86_mixer_data* md,
434 gboolean forward)
435 {
436 if (!forward) {
437 md->flags |= KB_X86_MIXER_FLAGS_BACKWARD;
438 }
439 kbasm_mix(md);
440 ch->volleft = md->volleft;
441 ch->volright = md->volright;
442 }
443
444 static guint32
kb_x86_mix_sub(kb_x86_channel * ch,guint32 num_samples_left,gboolean volramping,float * mixbuf,gint16 * scopebuf)445 kb_x86_mix_sub(kb_x86_channel* ch,
446 guint32 num_samples_left,
447 gboolean volramping,
448 float* mixbuf,
449 gint16* scopebuf)
450 {
451 kb_x86_mixer_data md;
452
453 const gboolean loopit = (ch->playend == 0) && (ch->flags & (KB_FLAG_LOOP_UNIDIRECTIONAL | KB_FLAG_LOOP_BIDIRECTIONAL));
454 const gboolean gonnapingpong = loopit && (ch->flags & KB_FLAG_LOOP_BIDIRECTIONAL);
455
456 const gint64 lstart64 = ((guint64)ch->sample->loopstart) << 32;
457 const gint32 pos = ch->positionw;
458 const gint64 freq64 = (((guint64)ch->freqw) << 32) + (guint64)ch->freqf;
459 const gint64 pos64 = ((guint64)(ch->positionw) << 32) + (guint64)ch->positionf;
460 const gint32 ende = (ch->playend != 0) ? (ch->playend) : (loopit ? ch->sample->loopend : ch->length);
461 const gint64 ende64 = (guint64)ende << 32;
462
463 int num_samples;
464
465 /* Initalize the data array for the assembly subroutines. */
466 md.volleft = ch->volleft;
467 md.volright = ch->volright;
468 if (!volramping) {
469 md.volrampl = 0;
470 md.volrampr = 0;
471 } else {
472 md.volrampl = ch->rampleft;
473 md.volrampr = ch->rampright;
474 }
475 md.positionf = ch->positionf;
476 if (ch->direction == 1) {
477 md.freqi = ch->freqw;
478 md.freqf = ch->freqf;
479 } else {
480 gint64 freq64_ = -freq64;
481 md.freqi = freq64_ >> 32;
482 md.freqf = freq64_ & 0xffffffff;
483 }
484 md.mixbuffer = mixbuf;
485 md.scopebuf = scopebuf;
486 md.freso = ch->freso;
487 md.ffreq = ch->ffreq;
488 md.fl1 = ch->fl1;
489 md.fb1 = ch->fb1;
490 md.flags = (ch->filter_on) ? KB_X86_MIXER_FLAGS_FILTERED : 0;
491
492 if (md.scopebuf) {
493 md.flags |= KB_X86_MIXER_FLAGS_SCOPES;
494 }
495 if (volramping) {
496 md.flags |= KB_X86_MIXER_FLAGS_VOLRAMP;
497 }
498
499 if ((ch->direction == 1 && pos >= ende - KB_X86_SAMPLE_PADDING)
500 || (ch->direction == -1 && pos < (gint32)(ch->sample->loopstart + KB_X86_SAMPLE_PADDING))) {
501 /* This is the dangerous case. We are near one of the ends of
502 a loop or sample (we might even have crossed it
503 already!). We have to take care of handling the looping and
504 perhaps we also have to prepare a mirror copy of the sample
505 values located around the loop incontinuity so that the
506 assembly routines don't use illegal values when
507 interpolating. */
508 gint16 buffer[KB_X86_SAMPLE_PADDING + 1];
509 unsigned int i;
510 gint32 j;
511 gint16* bufferpt;
512
513 /* First check if we're completely out of bounds, that means
514 for example: not just slightly before the end of the loop,
515 but way behind it. */
516 if (gonnapingpong) {
517 /* The pingpong loop case. Care is taken to take into
518 account extremely short loops with extremly high
519 frequencies. */
520 gboolean touched = FALSE;
521 gint64 mypos64 = ((guint64)(ch->positionw) << 32) + (guint64)ch->positionf;
522 gint64 lend64 = (((guint64)ch->sample->loopend) << 32) - 1;
523
524 while (1) {
525 if (ch->direction == 1 && mypos64 >= lend64) {
526 ch->direction = -1;
527 mypos64 -= lend64;
528 mypos64 *= -1;
529 mypos64 += lend64;
530 touched = TRUE;
531 } else if (ch->direction == -1 && mypos64 < lstart64) {
532 ch->direction = +1;
533 mypos64 -= lstart64;
534 mypos64 *= -1;
535 mypos64 += lstart64;
536 touched = TRUE;
537 } else {
538 break;
539 }
540 }
541
542 if (touched) {
543 /* We've been really out of bounds. Start all over. */
544 ch->positionf = (guint32)(mypos64 & 0xffffffff); /* just the lower 32 bits */
545 ch->positionw = (guint32)(mypos64 >> 32); /* just the upper 32 bits */
546 return 0;
547 }
548 } else if (loopit) {
549 /* The unidirectional ("Amiga") loop case. */
550 gboolean touched = FALSE;
551 guint32 looplen = ch->sample->loopend - ch->sample->loopstart;
552
553 while (ch->positionw >= ch->sample->loopend) {
554 ch->positionw -= looplen;
555 touched = TRUE;
556 }
557
558 if (touched) {
559 /* We've been out of bounds. Start all over. */
560 return 0;
561 }
562 } else {
563 if (ch->positionw >= ende) {
564 /* A sample without loop has just ended. */
565 ch->flags &= KB_FLAG_UPPER_ACTIVE;
566 return num_samples_left;
567 }
568 }
569
570 /* The following code is concerned with doing the fake sample
571 stuff for correct handling of the loop incontinuities. */
572 if (loopit || gonnapingpong) {
573 g_assert(pos < ch->sample->loopend);
574 }
575
576 if (gonnapingpong) {
577 int dir, bufferfilldir;
578
579 dir = bufferfilldir = ch->direction;
580 bufferpt = buffer;
581 if (ch->direction == -1) {
582 bufferpt += ARRAY_SIZE(buffer) - 1;
583 }
584 for (i = 0, j = pos; i < ARRAY_SIZE(buffer); i++) {
585 *bufferpt = ((gint16*)ch->sample->data)[j];
586 if (dir == +1) {
587 if (++j >= ch->sample->loopend) {
588 dir = -1;
589 j--;
590 }
591 } else {
592 if (--j < (gint32)ch->sample->loopstart) {
593 j++;
594 dir = +1;
595 }
596 }
597 bufferpt += bufferfilldir;
598 }
599 } else {
600 for (i = 0, j = pos; i < ARRAY_SIZE(buffer); i++) {
601 buffer[i] = ((gint16*)ch->sample->data)[j];
602 if (++j >= ende) {
603 if (loopit) {
604 j -= (ch->sample->loopend - ch->sample->loopstart);
605 } else {
606 j--;
607 }
608 }
609 }
610 }
611
612 num_samples = 1;
613 md.numsamples = 1;
614 if (ch->direction == 1) {
615 md.positioni = buffer;
616 kb_x86_call_mixer(ch, &md, TRUE);
617 ch->positionw = md.positioni - buffer + pos;
618 } else {
619 md.positioni = buffer + (ARRAY_SIZE(buffer) - 1);
620 kb_x86_call_mixer(ch, &md, FALSE);
621 ch->positionw = md.positioni - (buffer + (ARRAY_SIZE(buffer) - 1)) + pos;
622 }
623
624 ch->positionf = md.positionf;
625 ch->volleft = md.volleft;
626 ch->volright = md.volright;
627 ch->fl1 = md.fl1;
628 ch->fb1 = md.fb1;
629
630 return num_samples;
631 } else {
632 /* That we've reached this point means that the current sample
633 position is in an area of the sample that's not near the
634 start nor the end, which in turn means that we don't have
635 to create auxiliary arrays to prevent the mixer routine
636 from accessing invalid data beyond the end of the sample.
637
638 Now calculate how far we can go on like this until we hit a
639 dangerous area. */
640 if (ch->direction == 1) {
641 const guint64 wieweit64 = pos64 + freq64 * num_samples_left;
642 const guint32 wieweit = wieweit64 >> 32;
643
644 if (wieweit >= ende - KB_X86_SAMPLE_PADDING) {
645 /* oh, sorry - we need to truncate mixing length this
646 time. calculate exactly how many samples we can
647 still render in one run until we hit a dangerous
648 area. */
649 num_samples = (ende64 - ((guint64)KB_X86_SAMPLE_PADDING << 32) - pos64 + (freq64 - 1)) / freq64;
650 g_assert(num_samples > 0);
651 g_assert(pos64 + freq64 * num_samples >= ende64 - ((guint64)KB_X86_SAMPLE_PADDING << 32));
652 g_assert(pos64 + freq64 * (num_samples - 1) < ende64 - ((guint64)KB_X86_SAMPLE_PADDING << 32));
653 num_samples = MIN(num_samples_left, num_samples);
654 } else {
655 /* no problem, we can render the full buffer without
656 problems in one run. */
657 num_samples = num_samples_left;
658 }
659
660 md.positioni = (gint16*)ch->sample->data + pos;
661 md.numsamples = num_samples;
662 kb_x86_call_mixer(ch, &md, TRUE);
663 } else {
664 /* The same stuff, only for backwards direction */
665 const gint64 wieweit64 = pos64 - freq64 * num_samples_left;
666 const gint32 wieweit = wieweit64 >> 32;
667
668 if (wieweit < (gint32)(ch->sample->loopstart + KB_X86_SAMPLE_PADDING)) {
669 num_samples = 1 + (pos64 - (((guint64)KB_X86_SAMPLE_PADDING + ch->sample->loopstart) << 32)) / freq64;
670 g_assert(num_samples > 0);
671 g_assert(pos64 - freq64 * (gint64)(num_samples) < ((gint64)(ch->sample->loopstart + KB_X86_SAMPLE_PADDING) << 32));
672 g_assert(pos64 - freq64 * (gint64)(num_samples - 1) >= ((gint64)(ch->sample->loopstart + KB_X86_SAMPLE_PADDING) << 32));
673 num_samples = MIN(num_samples_left, num_samples);
674 } else {
675 num_samples = num_samples_left;
676 }
677
678 md.positioni = (gint16*)ch->sample->data + pos;
679 md.numsamples = num_samples;
680 kb_x86_call_mixer(ch, &md, FALSE);
681 }
682
683 ch->positionw = md.positioni - (gint16*)ch->sample->data;
684 ch->positionf = md.positionf;
685 ch->volleft = md.volleft;
686 ch->volright = md.volright;
687 ch->fl1 = md.fl1;
688 ch->fb1 = md.fb1;
689
690 return num_samples;
691 }
692 }
693
694 static void*
kb_x86_mix(void * dest,guint32 count,gint16 * scopebufs[],int scopebuf_offset)695 kb_x86_mix(void* dest,
696 guint32 count,
697 gint16* scopebufs[],
698 int scopebuf_offset)
699 {
700 int chnr;
701
702 if (count > kb_x86_tempbufsize) {
703 free(kb_x86_tempbuf);
704 kb_x86_tempbufsize = count;
705 kb_x86_tempbuf = malloc(2 * sizeof(float) * kb_x86_tempbufsize);
706 }
707
708 memset(kb_x86_tempbuf, 0, 2 * sizeof(float) * count);
709
710 for (chnr = 0; chnr < 2 * 32; chnr++) {
711 kb_x86_channel* ch = channels + chnr;
712 float* tempbuf = kb_x86_tempbuf;
713 int num_samples_left = count;
714 gint16* scopedata = NULL;
715
716 if ((chnr & 31) >= num_channels)
717 continue;
718
719 if (scopebufs && (chnr < 32 || (channels[chnr - 32].flags & KB_FLAG_UPPER_ACTIVE))) {
720 scopedata = scopebufs[chnr & 31] + scopebuf_offset;
721 }
722
723 if (!(ch->flags & KB_FLAG_SAMPLE_RUNNING)) {
724 if (scopedata) {
725 memset(scopedata, 0, 2 * num_samples_left);
726 }
727 continue;
728 }
729
730 if (ch->flags & KB_FLAG_JUST_STARTED) {
731 if (ch->flags & KB_FLAG_DO_SAMPLE_START_DECLICK) {
732 ch->ramp_num_samples = RAMP_MAX_DURATION * mixfreq;
733 if (ch->ramp_num_samples == 0) {
734 ch->ramp_num_samples = 1;
735 }
736 ch->volleft = 0.0;
737 ch->volright = 0.0;
738 ch->rampleft = (ch->rampdestleft - ch->volleft) / ch->ramp_num_samples;
739 ch->rampright = (ch->rampdestright - ch->volright) / ch->ramp_num_samples;
740 }
741
742 ch->flags &= ~KB_FLAG_JUST_STARTED;
743 }
744
745 g_mutex_lock(&ch->sample->lock);
746
747 while (num_samples_left && (ch->flags & KB_FLAG_SAMPLE_RUNNING)) {
748 int num_samples = 0;
749 gboolean vol_ramping = (ch->ramp_num_samples != 0);
750 int max_samples_this_time = vol_ramping ? MIN(ch->ramp_num_samples, num_samples_left) : num_samples_left;
751
752 num_samples = kb_x86_mix_sub(ch,
753 max_samples_this_time, vol_ramping,
754 tempbuf, scopedata);
755
756 if (vol_ramping) {
757 ch->ramp_num_samples -= num_samples;
758 if (ch->ramp_num_samples == 0) {
759 /* Volume ramping finished. */
760 ch->volleft = ch->rampdestleft;
761 ch->volright = ch->rampdestright;
762 if (ch->flags & KB_FLAG_STOP_AFTER_VOLRAMP) {
763 /* This was only a declicking channel. Stop sample. */
764 ch->flags &= KB_FLAG_UPPER_ACTIVE;
765 }
766 }
767 }
768
769 num_samples_left -= num_samples;
770 tempbuf += (num_samples * 2);
771 if (scopedata) {
772 scopedata += num_samples;
773 }
774 }
775
776 g_mutex_unlock(&ch->sample->lock);
777 }
778
779 clipflag = kbasm_post_mixing(kb_x86_tempbuf, (gint16*)dest, count, kb_x86_amplification);
780
781 return dest + count * 2 * 2;
782 }
783
kb_x86_dumpstatus(st_mixer_channel_status array[])784 void kb_x86_dumpstatus(st_mixer_channel_status array[])
785 {
786 int i;
787 gint32 pos;
788
789 for (i = 0; i < 32; i++) {
790 kb_x86_channel* c = kb_x86_get_channel_struct(i);
791
792 if (c->flags & KB_FLAG_SAMPLE_RUNNING) {
793 array[i].current_sample = c->sample;
794 pos = c->positionw;
795 if (pos < 0) {
796 pos = 0;
797 } else if (pos >= c->sample->length) {
798 pos = c->sample->length - 1;
799 }
800 array[i].current_position = pos;
801 } else {
802 array[i].current_sample = NULL;
803 }
804 }
805 }
806
807 static void
kb_x86_loadchsettings(int ch)808 kb_x86_loadchsettings(int ch)
809 {
810 tracer_channel* tch;
811 kb_x86_channel* kbch;
812
813 g_assert(ch < num_channels);
814
815 tch = tracer_return_channel(ch);
816 kbch = kb_x86_get_channel_struct(ch);
817
818 kbch->sample = tch->sample;
819 kbch->data = tch->data;
820 kbch->looptype = tch->looptype;
821 kbch->length = tch->length;
822 kbch->volume = tch->volume;
823 kbch->panning = tch->panning;
824 kbch->direction = tch->direction;
825 kbch->playend = tch->playend;
826 kbch->positionw = tch->positionw;
827 kbch->positionf = tch->positionf;
828 kbch->freqw = tch->freqw;
829 kbch->freqf = tch->freqf;
830 kbch->ffreq = tch->ffreq;
831 kbch->freso = tch->freso;
832 kbch->filter_on = tch->filter_on;
833
834 kbch->flags = (kbch->flags & KB_FLAG_UPPER_ACTIVE) | KB_FLAG_JUST_STARTED | ((tch->flags & TR_FLAG_LOOP_UNIDIRECTIONAL) ? KB_FLAG_LOOP_UNIDIRECTIONAL : 0) | ((tch->flags & TR_FLAG_LOOP_BIDIRECTIONAL) ? KB_FLAG_LOOP_BIDIRECTIONAL : 0) | ((tch->flags & TR_FLAG_SAMPLE_RUNNING) ? KB_FLAG_SAMPLE_RUNNING : 0);
835
836 kb_x86_redo_vol_fields(kbch);
837 }
838
839 st_mixer mixer_kbfloat = {
840 "kbfloat",
841 N_("High-quality FPU mixer, cubic interpolation, IT filters, unlimited length samples"),
842
843 kb_x86_setnumch,
844 kb_x86_updatesample,
845 kb_x86_setmixformat,
846 kb_x86_setstereo,
847 kb_x86_setmixfreq,
848 kb_x86_setampfactor,
849 kb_x86_getclipflag,
850 kb_x86_reset,
851 kb_x86_startnote,
852 kb_x86_stopnote,
853 kb_x86_setsmplpos,
854 kb_x86_setsmplend,
855 kb_x86_setfreq,
856 kb_x86_setvolume,
857 kb_x86_setpanning,
858 kb_x86_setchcutoff,
859 kb_x86_setchreso,
860 kb_x86_mix,
861 kb_x86_dumpstatus,
862 kb_x86_loadchsettings,
863
864 0x7fffffff,
865
866 NULL
867 };
868