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