1 /***************************************************************************
2 sound.c - sound system for xrally
3 -------------------
4 begin : Sun Jul 23 2000
5 copyright : (C) 2000 by Claudio Matsuoka
6 email : claudio@helllabs.org
7
8 $Id: sound.c,v 1.8 2000/11/25 15:35:19 claudio2 Exp $
9 ***************************************************************************/
10
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19 #include <stdio.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <pthread.h>
27 #include "config.h"
28 #include "global.h"
29 #include "soundplayer.h"
30
31 /***************************************************************************
32 * *
33 * This player is based on the xmp 2.1 development tree, and has a fairly *
34 * good M.K. MOD replaying support. For more information check the libxmp *
35 * draft at http://xmp.helllabs.org/newxmp. *
36 * *
37 ***************************************************************************/
38
39 /* Amiga periods */
40 static int period_amiga[] = {
41 /* 0 1 2 3 4 5 6 7 */
42 0x1c56, 0x1c22, 0x1bee, 0x1bbb, 0x1b87, 0x1b55, 0x1b22, 0x1af0, /* B */
43 0x1abf, 0x1a8e, 0x1a5d, 0x1a2c, 0x19fc, 0x19cc, 0x199c, 0x196d, /* C */
44 0x193e, 0x1910, 0x18e2, 0x18b4, 0x1886, 0x1859, 0x182c, 0x1800, /* C# */
45 0x17d4, 0x17a8, 0x177c, 0x1751, 0x1726, 0x16fb, 0x16d1, 0x16a7, /* D */
46 0x167d, 0x1654, 0x162b, 0x1602, 0x15d9, 0x15b1, 0x1589, 0x1562, /* D# */
47 0x153a, 0x1513, 0x14ec, 0x14c6, 0x149f, 0x1479, 0x1454, 0x142e, /* E */
48 0x1409, 0x13e4, 0x13c0, 0x139b, 0x1377, 0x1353, 0x1330, 0x130c, /* F */
49 0x12e9, 0x12c6, 0x12a4, 0x1282, 0x125f, 0x123e, 0x121c, 0x11fb, /* F# */
50 0x11da, 0x11b9, 0x1198, 0x1178, 0x1157, 0x1137, 0x1118, 0x10f8, /* G */
51 0x10d9, 0x10ba, 0x109b, 0x107d, 0x105e, 0x1040, 0x1022, 0x1004, /* G# */
52 0x0fe7, 0x0fca, 0x0fad, 0x0f90, 0x0f73, 0x0f57, 0x0f3a, 0x0f1e, /* A */
53 0x0f02, 0x0ee7, 0x0ecb, 0x0eb0, 0x0e95, 0x0e7a, 0x0e5f, 0x0e45, /* A# */
54 0x0e2b, 0x0e11, 0x0df7, 0x0ddd, 0x0dc3, 0x0daa, 0x0d91, 0x0d78, /* B */
55 };
56
57 /* Vibrato/tremolo waveform tables */
58 static int waveform[4][64] = {
59 { 0, 24, 49, 74, 97, 120, 141, 161, 180, 197, 212, 224,
60 235, 244, 250, 253, 255, 253, 250, 244, 235, 224, 212, 197,
61 180, 161, 141, 120, 97, 74, 49, 24, 0, -24, -49, -74,
62 -97,-120,-141,-161,-180,-197,-212,-224,-235,-244,-250,-253,
63 -255,-253,-250,-244,-235,-224,-212,-197,-180,-161,-141,-120,
64 -97, -74, -49, -24 }, /* Sine */
65
66 { 0, -8, -16, -24, -32, -40, -48, -56, -64, -72, -80, -88,
67 -96,-104,-112,-120,-128,-136,-144,-152,-160,-168,-176,-184,
68 -192,-200,-208,-216,-224,-232,-240,-248, 255, 248, 240, 232,
69 224, 216, 208, 200, 192, 184, 176, 168, 160, 152, 144, 136,
70 128, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40,
71 32, 24, 16, 8 }, /* Ramp down */
72
73 { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75 255, 255, 255, 255, 255, 255, 255, 255,-255,-255,-255,-255,
76 -255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
77 -255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,-255,
78 -255,-255,-255,-255 }, /* Square */
79
80 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88,
81 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184,
82 192, 200, 208, 216, 224, 232, 240, 248,-255,-248,-240,-232,
83 -224,-216,-208,-200,-192,-184,-176,-168,-160,-152,-144,-136,
84 -128,-120,-112,-104, -96, -88, -80, -72, -64, -56, -48, -40,
85 -32, -24, -16, -8 } /* Ramp up */
86 };
87
88
89 static struct mod_priv _priv, *PRIV = &_priv;
90 static struct mod_state mod[2];
91 static struct mod_channel channel[NUM_CH + 1];
92 static char *mod_ptr[2] = { NULL, NULL };
93 static int slot = 0;
94
95 static pthread_t thread;
96 static pthread_mutex_t frame_mtx = PTHREAD_MUTEX_INITIALIZER;
97
98 struct sound_driver *snddev;
99
100 int16 *snd_buffer;
101
mix_sound(void)102 static int mix_sound (void)
103 {
104 register int i;
105 int c, bsize;
106
107 bsize = BUFFER_SIZE /* * 125 / mod[slot].bpm */;
108
109 memset (snd_buffer, 0, BUFFER_SIZE << 1);
110
111 pthread_mutex_lock (&frame_mtx);
112
113 for (c = 0; c <= NUM_CH; c++) {
114 int siz = mod[slot].header->ins[channel[c].sample].size;
115 int lsz = mod[slot].header->ins[channel[c].sample].loop_size;
116 int lst = mod[slot].header->ins[channel[c].sample].loop_start;
117 int per = channel[c].period;
118 int vol = channel[c].volume;
119 int idx = channel[c].sidx;
120 int8 *src = mod[slot].sample[channel[c].sample];
121 int16 b;
122 //int vib;
123
124 if (!vol || !per || !src)
125 continue;
126
127 if (c < NUM_CH)
128 vol = mod[slot].volume * vol / 100;
129
130 if (lsz <= 2)
131 lsz = 0;
132 else if ((lst + lsz) < siz)
133 siz = lst + lsz;
134
135 for (i = 0; i < bsize; i++) {
136 int hi = idx >> 8;
137 int lo = idx & 0xff;
138
139 if (hi >= siz) {
140 if (lsz) {
141 idx = lst << 8;
142 hi = lst;
143 lo = 0;
144 } else {
145 break;
146 }
147 }
148
149 b = src[hi];
150 /* interpolation */
151 b += ((src[(hi + 1) % siz] - src[hi]) * lo) >> 8;
152 snd_buffer[i] += b * vol;
153
154 idx += 660000 / per;
155 }
156 channel[c].sidx = idx;
157 }
158 pthread_mutex_unlock (&frame_mtx);
159
160 return bsize;
161 }
162
163 /* Get period from note and finetune */
note_to_period(int n,int b)164 static int note_to_period (int n, int b)
165 {
166 int *t = period_amiga;
167 int f = ((b % 100) << 7) / 100;
168
169 if ((n += !((b < 0) && (f += 0x80)) + b / 100) < 0)
170 n = 0;
171 t += ((n % 12) << 3) + (f >> 4);
172 return ((*t << 4) + (*t++ - *t) * (f & 0xf)) >> (n / 12);
173 }
174
175 /* Get note from period using the Amiga frequency table */
period_to_note(int p)176 int period_to_note (int p)
177 {
178 int n, f, *t = period_amiga + MAX_NOTE;
179
180 if (!p)
181 return 0;
182 for (n = NOTE_Bb0; p <= (MAX_PERIOD / 2); n += 12, p <<= 1);
183 for (; p > *t; t -= 8, n--);
184 for (f = 7; f && (*t > p); t++, f--);
185 return n - (f >> 2);
186 }
187
188 /* Get pitchbend from base note and period */
period_to_bend(int p,int n,int f,int g)189 int period_to_bend (int p, int n, int f, int g)
190 {
191 int b, *t = period_amiga + MAX_NOTE;
192
193 if (!n) return 0;
194
195 if (p < MIN_PERIOD_A)
196 p = MIN_PERIOD_A;
197
198 /* Fixup for panic.s3m (from Toru Egashira's NSPmod) */
199 for (n = NOTE_B0 - 1 - n; p <= (MAX_PERIOD / 2); n += 12, p <<= 1);
200
201 for (; p > *t; t -= 8, n--);
202 b = 100 * n + (100 * (*t - p) / (*t - *(t + 8))) +
203 ((f - 128) % 16) * 100 / 128 * (f < 0 ? -1 : 1);
204 return g ? b / 100 * 100 : b;
205 }
206
event_convert(uint8 * e)207 static void event_convert (uint8 *e)
208 {
209 struct mod_event n;
210
211 n.note = period_to_note ((LSN (e[0]) << 8) + e[1]);
212 n.ins = ((MSN (e[0]) << 4) | MSN (e[2]));
213 n.fxt = LSN (e[2]);
214 n.fxp = e[3];
215
216 memcpy (e, &n, 4);
217 }
218
mod_convert(char * p,int slot)219 static void mod_convert (char *p, int slot)
220 {
221 int i, j, k;
222 struct mod_event *e;
223
224 mod[slot].header = (struct mod_header *)p;
225
226 /* convert instrument data */
227 for (i = 0; i < 31; i++) {
228 B_ENDIAN16 (mod[slot].header->ins[i].size);
229 B_ENDIAN16 (mod[slot].header->ins[i].loop_start);
230 B_ENDIAN16 (mod[slot].header->ins[i].loop_size);
231 mod[slot].header->ins[i].size <<= 1;
232 mod[slot].header->ins[i].loop_start <<= 1;
233 mod[slot].header->ins[i].loop_size <<= 1;
234 mod[slot].header->ins[i].finetune =
235 (int8)(mod[slot].header->ins[i].finetune << 4);
236 }
237
238 mod[slot].header->pat = 0;
239 for (i = 0; i < 128; i++) {
240 if (mod[slot].header->order[i] > 0x7f)
241 break;
242 if (mod[slot].header->order[i] > mod[slot].header->pat)
243 mod[slot].header->pat = mod[slot].header->order[i];
244 }
245 mod[slot].header->pat++;
246
247 mod[slot].pattern = (struct mod_event **)malloc
248 (mod[slot].header->pat * sizeof (void *));
249
250 /* convert pattern data */
251 for (i = 0; i < mod[slot].header->pat; i++) {
252 mod[slot].pattern[i] =
253 (struct mod_event *)((char *)mod[slot].header +
254 sizeof (struct mod_header) + 256 * NUM_CH * i);
255 e = mod[slot].pattern[i];
256 for (j = 0; j < 64; j++) {
257 for (k = 0; k < NUM_CH; k++) {
258 event_convert ((char *)e);
259 e++;
260 }
261 }
262 }
263
264 mod[slot].sample[0] =
265 (char *)mod[slot].pattern[mod[slot].header->pat - 1] +
266 256 * NUM_CH;
267
268 for (i = 1; i < 31; i++) {
269 mod[slot].sample[i] = mod[slot].sample[i - 1] +
270 mod[slot].header->ins[i - 1].size;
271 }
272 }
273
mod_play_frame()274 int mod_play_frame ()
275 {
276 int k;
277 struct mod_event *e;
278
279 if (!mod[slot].enabled)
280 return 0;
281
282 //cond_signal (XMP_WAIT_FRAME);
283
284 if (!mod[slot].frame) {
285 //mod[slot].pattern = PRIV->order[mod[slot].order];
286 //mod[slot].nrows = PRIV->rows;
287 PRIV->jmp = 0;
288 PRIV->pbreak = 0;
289 PRIV->pjump = mod[slot].order + 1;
290 }
291
292 /*
293 * Process this frame for all sound channels.
294 */
295
296 for (k = 0; k < NUM_CH /*mod[slot].nchannels*/; k++) {
297 struct mod_channel *ck = &channel[k];
298 //cond_signal (XMP_WAIT_CHN);
299
300 ck->dvolume = ck->dperiod = ck->dpan = 0;
301
302 if (!mod[slot].frame) {
303 int i, fxp;
304
305 /*
306 * In the first frame of a row we collect event data,
307 * parse effects, and process "fine" effects. In the
308 * original Protracker playroutine the effect checks
309 * the frame number, this approach should work better.
310 */
311
312 e = mod[slot].pattern[mod[slot].header->order[mod[slot].order]] +
313 NUM_CH /*mod[slot].nchannels*/ * mod[slot].row + k;
314
315 #if 0
316 /* Update channel data */
317 ck->event.note = e->note;
318 ck->event.ins = e->ins;
319 ck->event.vol = 0; /* FIXME! */
320 ck->event.fxp = e->fxp;
321 ck->event.fxt = e->fxt;
322 #endif
323
324 /*
325 * From the mod replaying notes for PT3.15:
326 *
327 * Instrument -> None Same Valid Inval
328 * New note Switch Play Play Cut
329 * New instr. (no note) - NewVol NewVol Cut
330 * Tone portamento Cont NewVol NewVol Cut
331 *
332 * Play = Play new note with new default volume
333 * Switch = Play new note with current volume
334 * NewVol = Don't play sample, set new default volume
335 * Cont = Continue playing sample
336 * Cut = Stop playing sample
337 */
338
339 if (e->ins) {
340 ck->volume = mod[slot].header->ins[e->ins - 1].volume;
341 ck->fx[finetune].value =
342 mod[slot].header->ins[e->ins - 1].finetune;
343 }
344
345 if (e->note) {
346 ck->note = e->note;
347
348 if (e->fxt != 0x3 && e->fxt != 0x5) {
349 if (e->ins) {
350 ck->instr = e->ins - 1;
351 ck->sample = ck->instr;
352 }
353
354 ck->sidx = 0;
355 ck->period = ck->fx[portamento].target =
356 note_to_period (e->note,
357 ck->fx[finetune].value);
358 }
359 }
360
361 /*
362 * effects
363 */
364
365 for (i = 0; i < fx_last; i++)
366 fx_disable (ck->fx[i]);
367
368 switch (e->fxt) {
369 case 0x0: /* arpeggio */
370 if (!e->fxp)
371 break;
372 fx_enable (ck->fx[arpeggio]);
373 ck->fx[arpeggio].data[0] = 0;
374 ck->fx[arpeggio].data[1] = MSN(e->fxp);
375 ck->fx[arpeggio].data[2] = LSN(e->fxp);
376 ck->fx[arpeggio].value = 0;;
377 break;
378 case 0x1: /* pitchbend up */
379 fx_enable (ck->fx[pitchbend]);
380 ck->fx[pitchbend].value = -e->fxp;
381 break;
382 case 0x2: /* pitchbend down */
383 fx_enable (ck->fx[pitchbend]);
384 ck->fx[pitchbend].value = e->fxp;
385 break;
386 case 0x3: /* tone portamento */
387 fx_enable (ck->fx[portamento]);
388 if (e->note) {
389 ck->fx[portamento].target =
390 note_to_period (e->note,
391 ck->fx[finetune].value);
392 }
393 if (e->fxp)
394 ck->fx[portamento].value = e->fxp;
395 break;
396 case 0x4: /* vibrato */
397 fx_enable (ck->fx[vibrato]);
398 if (e->fxp) {
399 ck->fx[vibrato].vdepth = LSN (e->fxp);
400 ck->fx[vibrato].vspeed = MSN (e->fxp);
401 }
402 break;
403 case 0x5: /* portamento + vslide */
404 fx_enable (ck->fx[portamento]);
405 fx_enable (ck->fx[vslide]);
406 if (e->note) {
407 ck->fx[portamento].target =
408 note_to_period (e->note,
409 ck->fx[finetune].value);
410 }
411 ck->fx[vslide].value = MSN(e->fxp)-LSN(e->fxp);
412 break;
413 case 0x6: /* vibrato + vslide */
414 fx_enable (ck->fx[vibrato]);
415 fx_enable (ck->fx[vslide]);
416 ck->fx[vslide].value = MSN(e->fxp)-LSN(e->fxp);
417 break;
418 case 0x7: /* tremolo */
419 fx_enable (ck->fx[tremolo]);
420 if (e->fxp) {
421 ck->fx[tremolo].vdepth = LSN (e->fxp);
422 ck->fx[tremolo].vspeed = MSN (e->fxp);
423 }
424 break;
425 case 0x8: /* pan setting -- not standard */
426 /* not implemented */
427 break;
428 case 0x9:
429 ck->sidx = e->fxp << 16;
430 break;
431 case 0xa: /* volume slide */
432 fx_enable (ck->fx[vslide]);
433 ck->fx[vslide].value = MSN(e->fxp)-LSN(e->fxp);
434 break;
435 case 0xb: /* pattern jump */
436 PRIV->jmp = 1;
437 PRIV->pjump = e->fxp;
438 break;
439 case 0xc: /* volume set */
440 ck->volume = e->fxp;
441 break;
442 case 0xd: /* pattern break */
443 PRIV->jmp = 1;
444 PRIV->pbreak = (e->fxp >> 4) * 10 +
445 (e->fxp & 0x0f);
446 break;
447 case 0xe: /* extended effect */
448 fx_enable (ck->fx[extended]);
449 break;
450 case 0xf:
451 if (e->fxp == 0)
452 break;
453 if (e->fxp > 0x20)
454 ;//mod[slot].bpm = e->fxp;
455 else
456 mod[slot].speed = e->fxp;
457 break;
458 }
459
460 if (!fx_test (ck->fx[extended]))
461 goto skip_extended;
462
463 /*
464 * extended effects
465 */
466
467 fxp = e->fxp & 0xf;
468
469 switch (e->fxp >> 4) {
470 case 0x0: /* filter on/off */
471 /* not implemented */
472 break;
473 case 0x1: /* fine portamento up */
474 fx_enable (ck->fx[fineporta]);
475 ck->fx[fineporta].value = -fxp;
476 break;
477 case 0x2: /* fine portamento down */
478 fx_enable (ck->fx[fineporta]);
479 ck->fx[fineporta].value = fxp;
480 break;
481 case 0x3: /* glissando */
482 break;
483 case 0x4: /* vibrato waveform */
484 PRIV->vibrato_wf = fxp;
485 break;
486 case 0x5: /* set finetune */
487 ck->fx[finetune].value = (uint8)(fxp << 4);
488 break;
489 case 0x6: /* pattern loop */
490 if (fxp == 0) {
491 ck->fx[loop].data[0] = mod[slot].row;
492 break;
493 }
494
495 if (ck->fx[loop].value == 0) {
496 ck->fx[loop].value = fxp;
497 } else {
498 ck->fx[loop].value--;
499 if (ck->fx[loop].value == 0)
500 break;
501 }
502
503 PRIV->jmp = 1;
504 PRIV->pjump = mod[slot].order;
505 PRIV->pbreak = ck->fx[loop].data[0];
506 break;
507 case 0x7: /* tremolo waveform */
508 PRIV->tremolo_wf = fxp;
509 break;
510 case 0x8: /* */
511 break;
512 case 0x9: /* note retrig */
513 fx_enable (ck->fx[retrig]);
514 ck->fx[retrig].value = fxp;
515 ck->fx[retrig].data[0] = 1;
516 ck->fx[retrig].data[1] = 1;
517 ck->fx[retrig].data[2] = ck->volume;
518 break;
519 case 0xa: /* fine volslide up */
520 fx_enable (ck->fx[finevol]);
521 ck->fx[finevol].value = fxp;
522 break;
523 case 0xb: /* fine volslide down */
524 fx_enable (ck->fx[finevol]);
525 ck->fx[finevol].value = -fxp;
526 break;
527 case 0xc: /* note cut */
528 fx_enable (ck->fx[retrig]);
529 ck->fx[retrig].value = fxp;
530 ck->fx[retrig].data[0] = 1;
531 ck->fx[retrig].data[1] = 0;
532 ck->fx[retrig].data[2] = ck->volume;
533 break;
534 case 0xd: /* note delay */
535 fx_enable (ck->fx[retrig]);
536 ck->fx[retrig].value = fxp;
537 ck->fx[retrig].data[0] = 0;
538 ck->fx[retrig].data[1] = 1;
539 ck->fx[retrig].data[2] = ck->volume;
540 break;
541 case 0xe: /* pattern delay */
542 ck->fx[pdelay].value = fxp;
543 break;
544 case 0xf: /* not defined */
545 break;
546 }
547
548 /*
549 * "fine" effect processing
550 */
551
552 if (fx_test (ck->fx[finevol]))
553 ck->volume += ck->fx[finevol].value;
554
555 if (fx_test (ck->fx[fineporta]))
556 ck->period += ck->fx[fineporta].value;
557
558 /*
559 * Retrig (cut, delay) processing
560 */
561 if (fx_test (ck->fx[retrig])) {
562 ck->volume = ck->fx[retrig].data[0] *
563 ck->fx[retrig].data[2];
564 }
565
566 skip_extended:
567 while (0) {};
568 } else {
569 /*
570 * In the rest of the frames we slide volume, pitch,
571 * etc. as set in the first frame of the row.
572 */
573
574 if (fx_test (ck->fx[vslide]))
575 ck->volume += ck->fx[vslide].value;
576
577 if (fx_test (ck->fx[pitchbend]))
578 ck->period += ck->fx[pitchbend].value;
579
580 if (fx_test (ck->fx[portamento])) {
581 if (abs (ck->fx[portamento].target - ck->period)
582 < abs (ck->fx[portamento].value)) {
583 ck->period = ck->fx[portamento].target;
584 fx_disable (ck->fx[portamento]);
585 } else {
586 ck->period += (ck->fx[portamento].target
587 > ck->period ? 1 : -1) *
588 ck->fx[portamento].value;
589 }
590 }
591 }
592
593 /*
594 * Arpeggio, vibrato and tremolo are processed in all frames.
595 * We also handle retrig events here.
596 */
597
598 if (fx_test (ck->fx[arpeggio])) {
599 ck->period = note_to_period (ck->note +
600 ck->fx[arpeggio].data[ck->fx[arpeggio].value++],
601 ck->fx[finetune].value);
602 ck->fx[arpeggio].value %= 3;
603 }
604
605 if (fx_test (ck->fx[vibrato])) {
606 ck->fx[vibrato].vphase %= 64;
607 ck->dperiod = (waveform[PRIV->vibrato_wf]
608 [ck->fx[vibrato].vphase] *
609 ck->fx[vibrato].vdepth) >> 9;
610 ck->fx[vibrato].vphase += ck->fx[vibrato].vspeed;
611 }
612
613 if (fx_test (ck->fx[tremolo])) {
614 ck->fx[tremolo].vphase %= 64;
615 ck->dvolume = (waveform[PRIV->tremolo_wf]
616 [ck->fx[tremolo].vphase] *
617 ck->fx[tremolo].vdepth) >> 9;
618 ck->fx[tremolo].vphase += ck->fx[tremolo].vspeed;
619 }
620
621 if (fx_test (ck->fx[retrig])) {
622 if (ck->fx[retrig].value == 0) {
623 ck->sidx = 0;
624 ck->volume = ck->fx[retrig].data[1] *
625 ck->fx[retrig].data[2];
626 fx_disable (ck->fx[retrig]);
627 } else {
628 ck->fx[retrig].value--;
629 }
630 }
631
632 /*
633 * Volume and period clipping
634 */
635
636 if (ck->volume > 64)
637 ck->volume = 64;
638 if (ck->volume < 0)
639 ck->volume = 0;
640
641 if (ck->period < MIN_PERIOD_A)
642 ck->period = MIN_PERIOD_A;
643 else if (ck->period > MAX_PERIOD_A)
644 ck->period = MAX_PERIOD_A;
645 }
646
647 /*
648 * Update xmp variables
649 */
650
651 mod[slot].frame++;
652
653 if (mod[slot].frame < mod[slot].speed)
654 return 0;
655
656 mod[slot].frame = 0;
657 mod[slot].row++;
658
659 //cond_signal (XMP_WAIT_ROW);
660
661 if (!PRIV->jmp && mod[slot].row < 64)
662 return 0;
663
664 mod[slot].row = PRIV->pbreak;
665 mod[slot].order = PRIV->pjump;
666
667 //cond_signal (XMP_WAIT_ORD);
668
669 if (mod[slot].order < mod[slot].header->len)
670 return 0;
671
672 //mod[slot].loop++;
673 mod[slot].order = 0;
674 //cond_signal (XMP_WAIT_LOOP);
675
676 return 0;
677 }
678
play_thread(void * arg)679 static void *play_thread (void *arg)
680 {
681 while (mod[slot].playing) {
682 mod_play_frame ();
683 mix_sound ();
684 snddev->dump_buffer ();
685 }
686
687 pthread_exit (NULL);
688 return NULL;
689 }
690
691
sound_switch()692 void sound_switch ()
693 {
694 slot ^= 1;
695 dbg ("Switching to sound slot %d", slot);
696 }
697
sound_select(int s)698 void sound_select (int s)
699 {
700 dbg ("Selecting sound %d (slot %d)", s, slot);
701
702 mod[slot].order = s;
703 mod[slot].row = 0;
704 mod[slot].frame = 0;
705 mod[slot].playing = 1;
706 }
707
sound_start()708 void sound_start ()
709 {
710 dbg ("Starting sound (slot %d)", slot);
711
712 if (!mod[slot].enabled)
713 return;
714
715 if (mod_ptr[slot] == NULL)
716 return;
717
718 dbg ("Creating sound thread");
719 pthread_create (&thread, NULL, play_thread, NULL);
720 pthread_detach (thread);
721 }
722
sound_stop()723 void sound_stop ()
724 {
725 dbg ("Stopping sound (slot %d)", slot);
726 mod[slot].playing = 0;
727 }
728
sound_load(char * m)729 int sound_load (char *m)
730 {
731 FILE *f;
732 struct stat st;
733 int slot2 = slot ^ 1; /* Work on the inactive slot */
734
735 dbg ("Loading %s in slot %d", m, slot2);
736
737 mod[slot2].enabled = 0;
738 if (chdir("sounds") < 0) {
739 fprintf(stderr, "can't go to sounds directory from %s...",
740 getcwd(NULL, -1));
741 return -1;
742 }
743
744 f = fopen (m, "r");
745 if (f == NULL) {
746 chdir("..");
747 fprintf(stderr, "can't load file...");
748 return -1;
749 }
750
751 fstat (fileno (f), &st);
752
753 if (mod_ptr[slot2] != NULL)
754 free (mod_ptr[slot2]);
755 mod_ptr[slot2] = malloc (st.st_size);
756 fread (mod_ptr[slot2], 1, st.st_size, f);
757
758 mod_convert (mod_ptr[slot2], slot2);
759 mod[slot2].speed = 6;
760 mod[slot2].enabled = 1;
761
762 chdir("..");
763 return 0;
764 }
765
sound_play(int s,int n,int v)766 void sound_play (int s, int n, int v)
767 {
768 pthread_mutex_lock (&frame_mtx);
769
770 channel[NUM_CH].note = n;
771 channel[NUM_CH].period = note_to_period (n, 0);
772 channel[NUM_CH].volume = v < 0 ? (mod[slot].header ?
773 mod[slot].header->ins[s].volume : 0) : v;
774 channel[NUM_CH].sample = s;
775 channel[NUM_CH].sidx = 0;
776
777 pthread_mutex_unlock (&frame_mtx);
778 }
779
sound_init()780 int sound_init ()
781 {
782 dbg ("Initializing sound");
783 snd_buffer = malloc (BUFFER_SIZE * sizeof (int16));
784
785 if (sound_oss.init () == 0) {
786 snddev = &sound_oss;
787 return 0;
788 }
789 snddev = &sound_dummy;
790 return 0;
791 }
792
sound_playing()793 int sound_playing ()
794 {
795 return mod[slot].playing;
796 }
797
sound_deinit()798 void sound_deinit ()
799 {
800 dbg ("Deinitializing sound");
801 sound_unload ();
802 snddev->deinit ();
803 free (snd_buffer);
804 }
805
sound_volume(int i)806 void sound_volume (int i)
807 {
808 mod[slot].volume = i;
809 }
810
sound_unload()811 void sound_unload ()
812 {
813 dbg ("Unloading mod in slot %d", slot);
814 mod[slot].enabled = 0;
815 sound_stop ();
816 pthread_join (thread, NULL);
817 free (mod_ptr[slot]);
818 mod_ptr[slot] = NULL;
819 }
820
sound_changevol(int i)821 void sound_changevol (int i)
822 {
823 mod[slot].volume += i;
824 if (mod[slot].volume < 0)
825 mod[slot].volume = 0;
826 if (mod[slot].volume > 64)
827 mod[slot].volume = 64;
828 }
829