1
2 /*
3 * The Real SoundTracker - Basic 32bit integers mixer. Probably the
4 * worst which you can come up with.
5 *
6 * Copyright (C) 1998-2019 Michael Krause
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #include <config.h>
24
25 #include <glib/gi18n.h>
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "mixer.h"
31 #include "tracer.h"
32
33 static int num_channels, mixfreq, amp = 8;
34 static gint32* mixbuf = NULL;
35 static int mixbufsize = 0, clipflag;
36 static int stereo;
37
38 typedef struct integer32_channel {
39 st_mixer_sample_info* sample;
40
41 void* data; /* copy of sample->data */
42 guint32 length; /* length of sample (converted) */
43 guint32 playend; /* for a forced premature end of the sample */
44
45 int running; /* this channel is active */
46 guint32 current; /* current playback position in sample (converted) */
47 guint32 speed; /* sample playback speed (converted) */
48
49 guint32 loopstart; /* loop start (converted) */
50 guint32 loopend; /* loop end (converted) */
51 int loopflags; /* 0 none, 1 forward, 2 pingpong */
52 int direction; /* current pingpong direction (+1 forward, -1 backward) */
53
54 int volume; /* 0..64 */
55 float panning; /* -1.0 .. +1.0 */
56 } integer32_channel;
57
58 static integer32_channel channels[32];
59
60 #define ACCURACY 12 /* accuracy of the fixed point stuff, ALSO HARDCODED in the assembly routines!! */
61
62 #define MAX_SAMPLE_LENGTH ((1 << (32 - ACCURACY)) - 1)
63
64 static void
integer32_setnumch(int n)65 integer32_setnumch(int n)
66 {
67 g_assert(n >= 1 && n <= 32);
68
69 num_channels = n;
70 }
71
72 static void
integer32_updatesample(st_mixer_sample_info * si)73 integer32_updatesample(st_mixer_sample_info* si)
74 {
75 int i;
76 integer32_channel* c;
77
78 for (i = 0; i < 32; i++) {
79 c = &channels[i];
80 if (c->sample != si || !c->running) {
81 continue;
82 }
83
84 if (c->data != si->data
85 || c->length != MIN(si->length, MAX_SAMPLE_LENGTH) << ACCURACY
86 || c->loopflags != si->looptype) {
87 c->running = 0;
88 }
89
90 /* No relevant data has changed. Don't stop the sample, but update
91 our local loop data instead. */
92 c->loopstart = MIN(si->loopstart, MAX_SAMPLE_LENGTH) << ACCURACY;
93 c->loopend = MIN(si->loopend, MAX_SAMPLE_LENGTH) << ACCURACY;
94 c->loopflags = si->looptype;
95 if (c->loopflags != ST_MIXER_SAMPLE_LOOPTYPE_NONE) {
96 // we can be more clever here...
97 c->current = c->loopstart;
98 c->direction = 1;
99 }
100 }
101 }
102
103 static gboolean
integer32_setmixformat(int format)104 integer32_setmixformat(int format)
105 {
106 if (format != 16)
107 return FALSE;
108
109 return TRUE;
110 }
111
112 static gboolean
integer32_setstereo(int on)113 integer32_setstereo(int on)
114 {
115 stereo = on;
116 return TRUE;
117 }
118
119 static void
integer32_setmixfreq(guint32 frequency)120 integer32_setmixfreq(guint32 frequency)
121 {
122 mixfreq = frequency;
123 }
124
125 static void
integer32_setampfactor(float amplification)126 integer32_setampfactor(float amplification)
127 {
128 amp = 8 * amplification;
129 }
130
131 static gboolean
integer32_getclipflag(void)132 integer32_getclipflag(void)
133 {
134 return clipflag;
135 }
136
137 static void
integer32_reset(void)138 integer32_reset(void)
139 {
140 memset(channels, 0, sizeof(channels));
141 }
142
143 static void
integer32_startnote(int channel,st_mixer_sample_info * s)144 integer32_startnote(int channel,
145 st_mixer_sample_info* s)
146 {
147 integer32_channel* c = &channels[channel];
148
149 c->sample = s;
150 c->data = s->data;
151 c->length = MIN(s->length, MAX_SAMPLE_LENGTH) << ACCURACY;
152 c->playend = 0;
153 c->running = 1;
154 c->speed = 1;
155 c->current = 0;
156 c->loopstart = MIN(s->loopstart, MAX_SAMPLE_LENGTH) << ACCURACY;
157 c->loopend = MIN(s->loopend, MAX_SAMPLE_LENGTH) << ACCURACY;
158 c->loopflags = s->looptype;
159 c->direction = 1;
160 }
161
162 static void
integer32_stopnote(int channel)163 integer32_stopnote(int channel)
164 {
165 integer32_channel* c = &channels[channel];
166
167 c->running = 0;
168 }
169
170 static void
integer32_setsmplpos(int channel,guint32 offset)171 integer32_setsmplpos(int channel,
172 guint32 offset)
173 {
174 integer32_channel* c = &channels[channel];
175
176 if (offset<c->length>> ACCURACY) {
177 c->current = offset << ACCURACY;
178 c->direction = 1;
179 } else {
180 c->running = 0;
181 }
182 }
183
184 static void
integer32_setsmplend(int channel,guint32 offset)185 integer32_setsmplend(int channel,
186 guint32 offset)
187 {
188 integer32_channel* c = &channels[channel];
189
190 if (c->current != 0 || offset<c->length>> ACCURACY) {
191 c->playend = MIN(offset, MAX_SAMPLE_LENGTH) << ACCURACY;
192 }
193 }
194
195 static void
integer32_setfreq(int channel,float frequency)196 integer32_setfreq(int channel,
197 float frequency)
198 {
199 integer32_channel* c = &channels[channel];
200
201 if (frequency > (0x7fffffff >> ACCURACY)) {
202 frequency = (0x7fffffff >> ACCURACY);
203 }
204
205 c->speed = frequency * (1 << ACCURACY) / mixfreq;
206 if (c->speed == 0) {
207 c->speed = 1;
208 }
209 }
210
211 static void
integer32_setvolume(int channel,float volume)212 integer32_setvolume(int channel,
213 float volume)
214 {
215 integer32_channel* c = &channels[channel];
216
217 c->volume = 64 * volume;
218 }
219
220 static void
integer32_setpanning(int channel,float panning)221 integer32_setpanning(int channel,
222 float panning)
223 {
224 integer32_channel* c = &channels[channel];
225
226 c->panning = panning;
227 }
228
229 static void*
integer32_mix(void * dest,guint32 count,gint16 * scopebufs[],int scopebuf_offset)230 integer32_mix(void* dest,
231 guint32 count,
232 gint16* scopebufs[],
233 int scopebuf_offset)
234 {
235 int todo;
236 int i, j, t, *m, v;
237 integer32_channel* c;
238 int done;
239 int offs2end, oflcnt, looplen;
240 gint16* sndbuf;
241 gint16* scopedata = NULL;
242 int vl = 0;
243 int vr = 0;
244 gint16* data;
245 int s, val;
246
247 if ((stereo + 1) * count > mixbufsize) {
248 g_free(mixbuf);
249 mixbuf = g_new(gint32, (stereo + 1) * count);
250 mixbufsize = (stereo + 1) * count;
251 }
252 memset(mixbuf, 0, (stereo + 1) * 4 * count);
253
254 for (i = 0; i < num_channels; i++) {
255 c = &channels[i];
256 t = count;
257 m = mixbuf;
258 v = c->volume;
259
260 if (scopebufs)
261 scopedata = scopebufs[i] + scopebuf_offset;
262
263 if (!c->running) {
264 if (scopebufs)
265 memset(scopedata, 0, 2 * count);
266 continue;
267 }
268
269 g_mutex_lock(&c->sample->lock);
270
271 while (t) {
272 /* Check how much of the sample we can fill in one run */
273 if (c->loopflags && c->playend == 0) {
274 looplen = c->loopend - c->loopstart;
275 g_assert(looplen > 0);
276 if (c->loopflags == ST_MIXER_SAMPLE_LOOPTYPE_AMIGA) {
277 offs2end = c->loopend - c->current;
278 if (offs2end <= 0) {
279 oflcnt = -offs2end / looplen;
280 offs2end += oflcnt * looplen;
281 c->current = c->loopstart - offs2end;
282 offs2end = c->loopend - c->current;
283 }
284 } else /* if(c->loopflags == ST_MIXER_SAMPLE_LOOPTYPE_PINGPONG) */ {
285 if (c->direction == 1)
286 offs2end = c->loopend - c->current;
287 else
288 offs2end = c->current - c->loopstart;
289
290 if (offs2end <= 0) {
291 oflcnt = -offs2end / looplen;
292 offs2end += oflcnt * looplen;
293 if ((oflcnt && 1) ^ (c->direction == -1)) {
294 c->current = c->loopstart - offs2end;
295 offs2end = c->loopend - c->current;
296 c->direction = 1;
297 } else {
298 c->current = c->loopend + offs2end;
299 if (c->current == c->loopend)
300 c->current--;
301 offs2end = c->current - c->loopstart;
302 c->direction = -1;
303 }
304 }
305 }
306 g_assert(offs2end >= 0);
307 done = offs2end / c->speed + 1;
308 } else /* if(c->loopflags == LOOP_NO) */ {
309 done = ((c->playend ? c->playend : c->length) - c->current) / c->speed;
310 if (!done) {
311 c->running = 0;
312 break;
313 }
314 }
315
316 g_assert(done > 0);
317
318 if (done > t)
319 done = t;
320 t -= done;
321
322 g_assert(c->current >= 0 && (c->current >> ACCURACY) < c->length);
323
324 if (stereo) {
325 vl = 64 - ((c->panning + 1.0) * 32);
326 vr = (c->panning + 1.0) * 32;
327 }
328
329 /* This one does the actual mixing */
330 data = c->data;
331 if (scopebufs) {
332 if (stereo) {
333 for (j = c->current, s = c->speed * c->direction; done; done--, j += s) {
334 val = v * data[j >> ACCURACY];
335 *m++ += vl * val >> 6;
336 *m++ += vr * val >> 6;
337 *scopedata++ = val >> 6;
338 }
339 } else {
340 for (j = c->current, s = c->speed * c->direction; done; done--, j += s) {
341 val = v * data[j >> ACCURACY];
342 *m++ += val;
343 *scopedata++ = val >> 6;
344 }
345 }
346 } else {
347 if (stereo) {
348 vl *= v;
349 vr *= v;
350 for (j = c->current, s = c->speed * c->direction; done; done--, j += s) {
351 val = data[j >> ACCURACY];
352 *m++ += vl * val >> 6;
353 *m++ += vr * val >> 6;
354 }
355 } else {
356 for (j = c->current, s = c->speed * c->direction; done; done--, j += s) {
357 val = v * data[j >> ACCURACY];
358 *m++ += val;
359 }
360 }
361 }
362
363 c->current = j;
364 }
365
366 g_mutex_unlock(&c->sample->lock);
367 }
368
369 /* modules with many channels get additional amplification here */
370 t = (4 * log(num_channels) / log(4)) * 64 * 8;
371
372 for (sndbuf = dest, clipflag = 0, todo = 0; todo < (stereo + 1) * count; todo++) {
373 gint32 a, b;
374
375 a = mixbuf[todo];
376 a *= amp; /* amplify */
377 a /= t;
378
379 b = CLAMP(a, -32768, 32767);
380 if (a != b) {
381 clipflag = 1;
382 }
383
384 *sndbuf++ = b;
385 }
386
387 return dest + (stereo + 1) * 2 * count;
388 }
389
integer32_dumpstatus(st_mixer_channel_status array[])390 void integer32_dumpstatus(st_mixer_channel_status array[])
391 {
392 int i;
393
394 for (i = 0; i < 32; i++) {
395 if (channels[i].running) {
396 array[i].current_sample = channels[i].sample;
397 array[i].current_position = channels[i].current >> ACCURACY;
398 } else {
399 array[i].current_sample = NULL;
400 }
401 }
402 }
403
404 static void
integer32_loadchsettings(int ch)405 integer32_loadchsettings(int ch)
406 {
407 tracer_channel* tch;
408 integer32_channel* c;
409 guint64 tmp64;
410
411 g_assert(ch < num_channels);
412
413 tch = tracer_return_channel(ch);
414 c = &channels[ch];
415
416 c->sample = tch->sample;
417 c->data = tch->data;
418
419 if (tch->sample) {
420 c->loopflags = tch->sample->looptype;
421 c->loopstart = MIN(tch->sample->loopstart, MAX_SAMPLE_LENGTH) << ACCURACY;
422 c->loopend = MIN(tch->sample->loopend, MAX_SAMPLE_LENGTH) << ACCURACY;
423 }
424 c->length = MIN(tch->length, MAX_SAMPLE_LENGTH) << ACCURACY;
425 c->volume = tch->volume * 64;
426 c->panning = tch->panning;
427 c->direction = tch->direction;
428 c->playend = MIN(tch->playend, MAX_SAMPLE_LENGTH) << ACCURACY;
429 tmp64 = (((guint64)tch->positionw << 32) + tch->positionf) >> (32 - ACCURACY);
430 c->current = MIN(tmp64, MAX_SAMPLE_LENGTH << ACCURACY);
431 tmp64 = (((guint64)tch->freqw << 32) + tch->freqf) >> (32 - ACCURACY);
432 c->speed = MIN(tmp64, MAX_SAMPLE_LENGTH << ACCURACY);
433
434 c->running = tch->flags & TR_FLAG_SAMPLE_RUNNING;
435 }
436
437 st_mixer mixer_integer32 = {
438 "integer32",
439 N_("Integers mixer, no interpolation, no filters, maximum sample length 1M"),
440
441 integer32_setnumch,
442 integer32_updatesample,
443 integer32_setmixformat,
444 integer32_setstereo,
445 integer32_setmixfreq,
446 integer32_setampfactor,
447 integer32_getclipflag,
448 integer32_reset,
449 integer32_startnote,
450 integer32_stopnote,
451 integer32_setsmplpos,
452 integer32_setsmplend,
453 integer32_setfreq,
454 integer32_setvolume,
455 integer32_setpanning,
456 NULL,
457 NULL,
458 integer32_mix,
459 integer32_dumpstatus,
460 integer32_loadchsettings,
461
462 MAX_SAMPLE_LENGTH,
463
464 NULL
465 };
466