1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * Wavetable Device: Software Mixer for sample stream output via devp
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * revision history: (please note changes here)
21  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22  *    -first release
23  *  -kb980525   Tammo Hinrichs <kb@nwn.de>
24  *    - restructured volume calculations to avoid those nasty
25  *      rounding errors
26  *    - changed behaviour on loop change a bit (may cause problems with
27  *      some .ULTs but fixes many .ITs instead ;)
28  *    - extended volume table to 256 values, thus consuming more memory,
29  *      but definitely increasing the output quality ;)
30  *    - added _dllinfo record
31  *  -ryg990504  Fabian Giesen  <fabian@jdcs.su.nw.schule.de>
32  *    -fixed sum really stupid memory leak
33  */
34 
35 #include "config.h"
36 #include <string.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 
40 #include <unistd.h>
41 
42 #include <sys/mman.h>
43 
44 #include "types.h"
45 #include "boot/plinkman.h"
46 #include "dev/imsdev.h"
47 #include "dev/mcp.h"
48 #include "stuff/poll.h"
49 #include "dev/mix.h"
50 #include "dev/player.h"
51 #include "devwmix.h"
52 #include "stuff/imsrtns.h"
53 #include "dwmix.h"
54 #include "dwmixa.h"
55 #include "dwmixqa.h"
56 
57 #if defined(__PIC__) && defined(I386_ASM)
58 #warning I386_ASM is disabled in non FPU mixers when compiled PIC
59 #undef I386_ASM
60 #endif
61 
62 
63 #ifdef I386_ASM
64 #include "stuff/pagesize.inc.c"
65 #endif
66 
67 #define MIXBUFLEN 4096
68 #define MAXCHAN 255
69 
70 extern struct sounddevice mcpMixer;
71 
72 static struct mixqpostprocregstruct *postprocs;
73 
74 static int quality;
75 static int resample;
76 
77 static int _pause;
78 static long playsamps;
79 static long pausesamps;
80 
81 static struct sampleinfo *samples;
82 static int samplenum;
83 
84 static int16_t (*amptab)[256]; /* signedness is not fixed here */
85 static unsigned long clipmax;
86 static volatile int clipbusy;
87 #define BARRIER __asm__ __volatile__ ("":);
88 
89 static unsigned long amplify;
90 static unsigned short transform[2][2];
91 static int volopt;
92 static unsigned long relpitch;
93 static int interpolation;
94 static int restricted;
95 
96 static unsigned char stereo;
97 static unsigned char bit16;
98 static unsigned char signedout;
99 static unsigned long samprate;
100 static unsigned char reversestereo;
101 
102 static int channelnum;
103 static struct channel *channels;
104 static int32_t fadedown[2];
105 
106 static int32_t (*voltabsr)[256];
107 static int16_t (*voltabsq)[2][256];
108 
109 static uint8_t (*interpoltabr)[256][2];
110 static int16_t (*interpoltabq)[32][256][2];
111 static int16_t (*interpoltabq2)[16][256][4];
112 
113 static int16_t *scalebuf=0;
114 static int32_t *buf32;
115 static uint32_t bufpos;
116 static uint32_t buflen;
117 static void *plrbuf;
118 
119 static void (*playerproc)(void);
120 static unsigned long tickwidth;
121 static unsigned long tickplayed;
122 static unsigned long orgspeed;
123 static unsigned short relspeed;
124 static unsigned long newtickwidth;
125 static unsigned long cmdtimerpos;
126 
127 static int mastervol;
128 static int masterbal;
129 static int masterpan;
130 static int mastersrnd;
131 static int masterrvb;
132 
calcinterpoltabr(void)133 static void calcinterpoltabr(void)
134 	/* used by OpenPlayer */
135 {
136 	int i,j;
137 	for (i=0; i<16; i++)
138 		for (j=0; j<256; j++)
139 		{
140 			interpoltabr[i][j][1]=(i*(signed char)j)>>4;
141 			interpoltabr[i][j][0]=(signed char)j-interpoltabr[i][j][1];
142 		}
143 }
144 
calcinterpoltabq(void)145 static void calcinterpoltabq(void)
146 	/* used by OpenPlayer */
147 {
148 	int i,j;
149 	for (i=0; i<32; i++)
150 		for (j=0; j<256; j++)
151 		{
152 			interpoltabq[0][i][j][1]=(i*(signed char)j)<<3;
153 			interpoltabq[0][i][j][0]=(((signed char)j)<<8)-interpoltabq[0][i][j][1];
154 			interpoltabq[1][i][j][1]=(i*j)>>5;
155 			interpoltabq[1][i][j][0]=j-interpoltabq[1][i][j][1];
156 		}
157 	for (i=0; i<16; i++)
158 		for (j=0; j<256; j++)
159 		{
160 			interpoltabq2[0][i][j][0]=((16-i)*(16-i)*(signed char)j)>>1;
161 			interpoltabq2[0][i][j][2]=(i*i*(signed char)j)>>1;
162 			interpoltabq2[0][i][j][1]=(((signed char)j)<<8)-interpoltabq2[0][i][j][0]-interpoltabq2[0][i][j][2];
163 			interpoltabq2[1][i][j][0]=((16-i)*(16-i)*j)>>9;
164 			interpoltabq2[1][i][j][2]=(i*i*j)>>9;
165 			interpoltabq2[1][i][j][1]=j-interpoltabq2[1][i][j][0]-interpoltabq2[1][i][j][2];
166 		}
167 }
168 
calcvoltabsr(void)169 static void calcvoltabsr(void)
170 	/* used by OpenPlayer */
171 {
172 	int i,j;
173 	for (i=0; i<=512; i++)
174 		for (j=0; j<256; j++)
175 			voltabsr[i][j]=(i-256)*(signed char)j;
176 }
177 
calcvoltabsq(void)178 static void calcvoltabsq(void)
179 	/* used by OpenPlayer */
180 {
181 	int i,j;
182 	for (j=0; j<=512; j++)
183 	{
184 		long amp=j-256;
185 		for (i=0; i<256; i++)
186 		{
187 			int v=amp*(signed char)i;
188 			voltabsq[j][0][i]=(v==0x8000)?0x7FFF:v;
189 			voltabsq[j][1][i]=(amp*i)>>8;
190 		}
191 	}
192 }
193 
calcamptab(signed long amp)194 static void calcamptab(signed long amp)
195 	/* Used by SET
196 	 *         OpenPlayer
197 	 */
198 {
199 	int i;
200 
201 	clipbusy++;
202 
203 	BARRIER
204 
205 	amp=3*amp/16;
206 
207 	for (i=0; i<256; i++)
208 	{
209 		amptab[0][i]=(amp*i)>>12;
210 		amptab[1][i]=(amp*i)>>4;
211 		amptab[2][i]=(amp*(signed char)i)<<4;
212 	}
213 
214 	if(amp)
215 		clipmax=0x07FFF000/amp;
216 	else
217 		clipmax=0x07FFF000;
218 
219 	if (!signedout)
220 		for (i=0; i<256; i++)
221 			amptab[0][i]^=0x8000;
222 
223 	BARRIER
224 
225 	clipbusy--;
226 }
227 
calcstep(struct channel * c)228 static void calcstep(struct channel *c)
229 	/* Used by calcsteps
230 	 *         SET
231 	 */
232 {
233 	if (!(c->status&MIXRQ_PLAYING))
234 		return;
235 	if (c->orgdiv)
236 		c->step=imuldiv(imuldiv((c->step>=0)?c->orgfrq:-c->orgfrq, c->orgrate, c->orgdiv)<<8, relpitch, samprate);
237 	else
238 		c->step=0;
239 	c->status&=~MIXRQ_INTERPOLATE;
240 	if (!quality)
241 	{
242 		if (interpolation>1)
243 			c->status|=MIXRQ_INTERPOLATE;
244 		if (interpolation==1)
245 			if (abs(c->step)<=(3<<15))
246 		c->status|=MIXRQ_INTERPOLATE;
247 	} else {
248 		if (interpolation>1)
249 			c->status|=MIXRQ_INTERPOLATEMAX|MIXRQ_INTERPOLATE;
250 		if (interpolation==1)
251 		{
252 			c->status|=MIXRQ_INTERPOLATE;
253 			c->status&=~MIXRQ_INTERPOLATEMAX;
254 		}
255 	}
256 }
257 
calcsteps(void)258 static void calcsteps(void)
259 	/* Used by SET */
260 {
261 	int i;
262 	for (i=0; i<channelnum; i++)
263 		calcstep(&channels[i]);
264 }
265 
calcspeed(void)266 static void calcspeed(void)
267 {
268 	/* Used by SET
269 	 *         OpenPlayer
270 	 */
271 	if (channelnum)
272 		newtickwidth=imuldiv(256*256*256, samprate, orgspeed*relspeed);
273 }
274 
transformvol(struct channel * ch)275 static void transformvol(struct channel *ch)
276 	/* Used by calcvol
277 	 *         calcvols
278 	 *         SET
279 	 */
280 {
281 	int32_t v;
282 
283 	v=transform[0][0]*ch->orgvol[0]+transform[0][1]*ch->orgvol[1];
284 	ch->vol[0]=(v>0x10000)?256:(v<-0x10000)?-256:((v+192)>>8);
285 
286 	v=transform[1][0]*ch->orgvol[0]+transform[1][1]*ch->orgvol[1];
287 	if (volopt^ch->volopt)
288 		v=-v;
289 	ch->vol[1]=(v>0x10000)?256:(v<-0x10000)?-256:((v+192)>>8);
290 
291 	if (ch->status&MIXRQ_MUTE)
292 	{
293 		ch->dstvols[0]=ch->dstvols[1]=0;
294 		return;
295 	}
296 	if (!stereo)
297 	{
298 		ch->dstvols[0]=(abs(ch->vol[0])+abs(ch->vol[1])+1)>>1;
299 		ch->dstvols[1]=0;
300 	} else if (reversestereo)
301 	{
302 		ch->dstvols[0]=ch->vol[1];
303 		ch->dstvols[1]=ch->vol[0];
304 	} else {
305 		ch->dstvols[0]=ch->vol[0];
306 		ch->dstvols[1]=ch->vol[1];
307 	}
308 }
309 
calcvol(struct channel * chn)310 static void calcvol(struct channel *chn)
311 	/* Used by calcvols
312 	 *         SET
313 	 */
314 {
315 	chn->orgvol[1]=((int32_t)chn->orgvolx*(0x80L+chn->orgpan))>>8;
316 	chn->orgvol[0]=((int32_t)chn->orgvolx*(0x80L-chn->orgpan))>>8;
317 	/* werte: 0-0x100; */
318 	transformvol(chn);
319 }
320 
321 
calcvols(void)322 static void calcvols(void)
323 	/* Used by SET
324 	 *         OpenPlayer
325 	 */
326 {
327 	int16_t vols[2][2];
328 	int i;
329 
330 	vols[0][0]=vols[1][1]=(mastervol*(0x40+masterpan))>>6;
331 	vols[0][1]=vols[1][0]=(mastervol*(0x40-masterpan))>>6;
332 	/* werte: 0-0x100 */
333 
334 	if (masterbal>0)
335 	{
336 		vols[0][0]=(vols[0][0]*(0x40-masterbal))>>6;
337 		vols[0][1]=(vols[0][1]*(0x40-masterbal))>>6;
338 	} else if (masterbal<0)
339 	{
340 		vols[1][0]=(vols[1][0]*(0x40+masterbal))>>6;
341 		vols[1][1]=(vols[1][1]*(0x40+masterbal))>>6;
342 	}
343 
344 	volopt=mastersrnd;
345 	transform[0][0]=vols[0][0];
346 	transform[0][1]=vols[0][1];
347 	transform[1][0]=vols[1][0];
348 	transform[1][1]=vols[1][1];
349 	for (i=0; i<channelnum; i++)
350 		transformvol(&channels[i]);
351 }
352 
fadechanq(int * fade,struct channel * c)353 static void fadechanq(int *fade, struct channel *c)
354 	/* Used by stopchan
355 	 *         playchannelq
356 	 */
357 {
358 	int s;
359 	if (c->status&MIXRQ_PLAY16BIT)
360 		s=((short*)((unsigned long)c->samp*2))[c->pos];
361 	else
362 		s=(((signed char*)c->samp)[c->pos])<<8;
363 	fade[0]+=(c->curvols[0]*s)>>8;
364 	fade[1]+=(c->curvols[1]*s)>>8;
365 	c->curvols[0]=c->curvols[1]=0;
366 }
367 
stopchan(struct channel * c)368 static void stopchan(struct channel *c)
369 {
370 	/* Used by SET
371 	 */
372 	if (!(c->status&MIXRQ_PLAYING))
373 		return;
374 	if (!quality)
375 		mixrFadeChannel(fadedown, c);
376 	else
377 		fadechanq(fadedown, c);
378 	c->status&=~MIXRQ_PLAYING;
379 }
380 
amplifyfadeq(uint32_t pos,uint32_t cl,int32_t * curvol,int32_t dstvol)381 static void amplifyfadeq(uint32_t pos, uint32_t cl, int32_t *curvol, int32_t dstvol)
382 	/* Used by playchannelq
383 	 */
384 {
385 	uint32_t l=abs(dstvol-*curvol);
386 
387 	if (l>cl)
388 		l=cl;
389 	if (dstvol<*curvol)
390 	{
391 		mixqAmplifyChannelDown(buf32+pos, scalebuf, l, *curvol, 4<<stereo);
392 		*curvol-=l;
393 	} else if (dstvol>*curvol)
394 	{
395 		mixqAmplifyChannelUp(buf32+pos, scalebuf, l, *curvol, 4<<stereo);
396 		*curvol+=l;
397 	}
398 	cl-=l;
399 	if (*curvol&&cl)
400 		mixqAmplifyChannel(buf32+pos+(l<<stereo), scalebuf+l, cl, *curvol, 4<<stereo);
401 }
402 
playchannelq(int ch,uint32_t len)403 static void playchannelq(int ch, uint32_t len)
404 {
405 	/* Used by mixer
406 	 */
407 	struct channel *c=&channels[ch];
408 	if (c->status&MIXRQ_PLAYING)
409 	{
410 		int quiet=!c->curvols[0]&&!c->curvols[1]&&!c->dstvols[0]&&!c->dstvols[1];
411 		mixqPlayChannel(scalebuf, len, c, quiet);
412 		if (quiet)
413 			return;
414 
415 		if (stereo)
416 		{
417 			amplifyfadeq(0, len, &c->curvols[0], c->dstvols[0]);
418 			amplifyfadeq(1, len, &c->curvols[1], c->dstvols[1]);
419 		} else
420 			amplifyfadeq(0, len, &c->curvols[0], c->dstvols[0]);
421 
422 		if (!(c->status&MIXRQ_PLAYING))
423 			fadechanq(fadedown, c);
424 	}
425 }
426 
427 
428 
mixer(void)429 static void mixer(void)
430 {
431 	/* mixer used by timerproc
432 	 *               Idle
433 	 */
434 	int i;
435 	int bufdeltatot;
436 	struct mixqpostprocregstruct *mode;
437 
438 	if (!channelnum)
439 		return;
440 
441 	BARRIER
442 
443 	if (clipbusy++)
444 	{
445 		clipbusy--;
446 		return;
447 	}
448 
449 	BARRIER
450 
451 	bufdeltatot=((buflen+(plrGetBufPos()>>(stereo+bit16))-bufpos)%buflen);
452 	if (_pause)
453 	{
454 		uint32_t pass2=((bufpos+bufdeltatot)>buflen)?(bufpos+bufdeltatot-buflen):0;
455 
456 		if (bit16)
457 		{
458 			memsetw((short*)plrbuf+(bufpos<<stereo), signedout?0:0x8000, (bufdeltatot-pass2)<<stereo);
459 			if (pass2)
460 				memsetw((short*)plrbuf, signedout?0:0x8000, pass2<<stereo);
461 		} else {
462 			memsetb((char*)plrbuf+(bufpos<<stereo), signedout?0:0x80, (bufdeltatot-pass2)<<stereo);
463 			if (pass2)
464 				memsetb((char*)plrbuf, signedout?0:0x80, pass2<<stereo);
465 		}
466 
467 		bufpos+=bufdeltatot;
468 		if (bufpos>=buflen)
469 		bufpos-=buflen;
470 
471 		plrAdvanceTo(bufpos<<(stereo+bit16));
472 		pausesamps+=bufdeltatot;
473 	} else while (bufdeltatot>0)
474 	{
475 		uint32_t bufdelta=(bufdeltatot>MIXBUFLEN)?MIXBUFLEN:bufdeltatot;
476 
477 		if (bufdelta>(buflen-bufpos))
478 			bufdelta=buflen-bufpos;
479 		if (bufdelta>((tickwidth-tickplayed)>>8))
480 			bufdelta=(tickwidth-tickplayed)>>8;
481 
482 		mixrFade(buf32, fadedown, bufdelta, stereo);
483 		if (!quality)
484 		{
485 			for (i=0; i<channelnum; i++)
486 				mixrPlayChannel(buf32, fadedown, bufdelta, &channels[i], stereo);
487 		} else {
488 			for (i=0; i<channelnum; i++)
489 				playchannelq(i, bufdelta);
490 		}
491 
492 		for (mode=postprocs; mode; mode=mode->next)
493 			mode->Process(buf32, bufdelta, samprate, stereo);
494 
495 		mixrClip((char*)plrbuf+(bufpos<<(stereo+bit16)), buf32, bufdelta<<stereo, amptab, clipmax, bit16);
496 
497 		tickplayed+=bufdelta<<8;
498 		if (!((tickwidth-tickplayed)>>8))
499 		{
500 			tickplayed-=tickwidth;
501 			playerproc();
502 			cmdtimerpos+=tickwidth;
503 			tickwidth=newtickwidth;
504 		}
505 		bufpos+=bufdelta;
506 		if (bufpos>=buflen)
507 			bufpos-=buflen;
508 
509 		plrAdvanceTo(bufpos<<(stereo+bit16));
510 		bufdeltatot-=bufdelta;
511 		playsamps+=bufdelta;
512 	}
513 
514 	BARRIER
515 
516 	clipbusy--;
517 }
518 
timerproc(void)519 static void timerproc(void)
520 {
521 	/* Referred by OpenPlayer
522 	 */
523 #ifndef NO_BACKGROUND_MIXER
524 	mixer();
525 #endif
526 	if (plrIdle)
527 		plrIdle();
528 }
529 
530 
531 
532 
533 
534 
535 
536 
537 
538 #ifdef __STRANGE_BUG__
539 void *GetReturnAddress12();
540 #pragma aux GetReturnAddress12="mov eax, [esp+12]" value [eax];
541 
sbDumpRetAddr(void * ptr)542 void sbDumpRetAddr(void *ptr)
543 {
544   linkaddressinfostruct a;
545   lnkGetAddressInfo(a, ptr);
546   printf("--> called from %s.%s+0x%x, %s.%d+0x%x\n", a.module, a.sym,
547 	 a.symoff, a.source, a.line, a.lineoff);
548   fflush(stdout);
549 }
550 #endif
551 
552 
SET(int ch,int opt,int val)553 static void SET(int ch, int opt, int val)
554 {
555 	/* Refered by OpenPlayer
556 	 */
557 	struct channel *chn;
558 
559 #ifdef __STRANGE_BUG__
560   if ((opt==mcpMasterBalance)&&(val<-64 || val>64))  /* got that damn bug. */
561     {
562       sbDumpRetAddr(GetReturnAddress12());
563       printf("mcpSet(%d, %d, %d);\n", ch, opt, val);
564     }
565 #endif
566 
567 	if (ch>=channelnum)
568 		ch=channelnum-1;
569 	if (ch<0)
570 		ch=0;
571 	chn=&channels[ch];
572 	switch (opt)
573 	{
574 		case mcpCReset:
575 			{
576 				int reswasmute;
577 				stopchan(chn);
578 				reswasmute=chn->status&MIXRQ_MUTE;
579 				memset(chn, 0, sizeof(struct channel));
580 				chn->status=reswasmute;
581 				break;
582 			}
583 		case mcpCInstrument:
584 			stopchan(chn);
585 			if ((val<0)||(val>=samplenum))
586 				break;
587 			{
588 				struct sampleinfo *samp=&samples[val];
589 				chn->samptype=samp->type;
590 				chn->length=samp->length;
591 				chn->orgrate=samp->samprate;
592 				chn->samp=samp->ptr;
593 				chn->realsamp.bit8=chn->samp;
594 				chn->orgloopstart=samp->loopstart;
595 				chn->orgloopend=samp->loopend;
596 				chn->orgsloopstart=samp->sloopstart;
597 				chn->orgsloopend=samp->sloopend;
598 
599 				chn->status&=~(MIXRQ_PLAYING|MIXRQ_LOOPED|MIXRQ_PINGPONGLOOP|MIXRQ_PLAY16BIT|MIXRQ_PLAYSTEREO);
600 			}
601 			if (chn->samptype&mcpSamp16Bit)
602 			{
603 				chn->status|=MIXRQ_PLAY16BIT;
604 				chn->samp=(void*)((unsigned long)chn->samp>>1);
605 			}
606 			if (chn->samptype&mcpSampStereo)
607 			{
608 				chn->status|=MIXRQ_PLAYSTEREO;
609 				chn->samp=(void*)((unsigned long)chn->samp>>1);
610 			}
611 			if (chn->samptype&mcpSampSLoop)
612 			{
613 				chn->status|=MIXRQ_LOOPED;
614 				chn->loopstart=chn->orgsloopstart;
615 				chn->loopend=chn->orgsloopend;
616 				if (chn->samptype&mcpSampSBiDi)
617 					chn->status|=MIXRQ_PINGPONGLOOP;
618 			} else if (chn->samptype&mcpSampLoop)
619 			{
620 				chn->status|=MIXRQ_LOOPED;
621 				chn->loopstart=chn->orgloopstart;
622 				chn->loopend=chn->orgloopend;
623 				if (chn->samptype&mcpSampBiDi)
624 					chn->status|=MIXRQ_PINGPONGLOOP;
625 			}
626 			chn->replen=(chn->status&MIXRQ_LOOPED)?(chn->loopend-chn->loopstart):0;
627 			chn->step=0;
628 			chn->pos=0;
629 			chn->fpos=0;
630 			break;
631 		case mcpCStatus:
632 			if (!val)
633 				stopchan(chn);
634 			else {
635 				if (chn->pos>=chn->length)
636 					break;
637 				chn->status|=MIXRQ_PLAYING;
638 				calcstep(chn);
639 			}
640 			break;
641 		case mcpCMute:
642 			if (val)
643 				chn->status|=MIXRQ_MUTE;
644 			else
645 				chn->status&=~MIXRQ_MUTE;
646 			transformvol(chn);
647 				break;
648 		case mcpCVolume:
649 			chn->orgvolx=(val>0x100)?0x100:(val<0)?0:val;
650 			calcvol(chn);
651 			break;
652 		case mcpCPanning:
653 			chn->orgpan=(val>0x80)?0x80:(val<-0x80)?-0x80:val;
654 			calcvol(chn);
655 			break;
656 		case mcpCSurround:
657 			chn->volopt=val?1:0;
658 			transformvol(chn);
659 			break;
660 		case mcpCDirect:
661 			if (val==0)
662 				chn->step=abs(chn->step);
663 			else
664 				if (val==1)
665 					chn->step=-abs(chn->step);
666 				else
667 					chn->step=-chn->step;
668 			break;
669 		case mcpCLoop:
670 			chn->status&=~(MIXRQ_LOOPED|MIXRQ_PINGPONGLOOP);
671 			if ((val==1)&&!(chn->samptype&mcpSampSLoop))
672 				val=2;
673 			if ((val==2)&&!(chn->samptype&mcpSampLoop))
674 				val=0;
675 			if (val==1)
676 			{
677 				chn->status|=MIXRQ_LOOPED;
678 				chn->loopstart=chn->orgsloopstart;
679 				chn->loopend=chn->orgsloopend;
680 				if (chn->samptype&mcpSampSBiDi)
681 					chn->status|=MIXRQ_PINGPONGLOOP;
682 			}
683 			if (val==2)
684 			{
685 				chn->status|=MIXRQ_LOOPED;
686 				chn->loopstart=chn->orgloopstart;
687 				chn->loopend=chn->orgloopend;
688 				if (chn->samptype&mcpSampBiDi)
689 					chn->status|=MIXRQ_PINGPONGLOOP;
690 			}
691 			chn->replen=(chn->status&MIXRQ_LOOPED)?(chn->loopend-chn->loopstart):0;
692 			if (chn->replen)
693 			{
694 				if (((chn->pos<chn->loopstart)&&(chn->step<0))||((chn->pos>=chn->loopend)&&(chn->step>0)))
695 					chn->step=-chn->step;
696 			} else if (chn->step<0)
697 				chn->step=-chn->step;
698 			break;
699 
700 		case mcpCPosition:
701 			{
702 				int poswasplaying;
703 				poswasplaying=chn->status&MIXRQ_PLAYING;
704 				stopchan(chn);
705 				if (val<0)
706 					val=0;
707 				if ((unsigned)val>=chn->length)
708 				val=chn->length-1;
709 				chn->pos=val;
710 				chn->fpos=0;
711 				chn->status|=poswasplaying;
712 				break;
713 			}
714 		case mcpCPitch:
715 			chn->orgfrq=8363;
716 			chn->orgdiv=mcpGetFreq8363(-val);
717 			calcstep(chn);
718 			break;
719 		case mcpCPitchFix:
720 			chn->orgfrq=val;
721 			chn->orgdiv=0x10000;
722 			calcstep(chn);
723 			break;
724 		case mcpCPitch6848:
725 			chn->orgfrq=6848;
726 			chn->orgdiv=val;
727 			calcstep(chn);
728 			break;
729 
730 		case mcpGSpeed:
731 			orgspeed=val;
732 			calcspeed();
733 			break;
734 
735 		case mcpMasterVolume:
736 			if (val>=0 && val<=64)
737 				mastervol=(val<0)?0:(val>63)?63:val;
738 			calcvols();
739 			break;
740 
741 		case mcpMasterPanning:
742 #ifndef __STRANGE_BUG__
743 			if (val>=-64 && val<=64)
744 #endif
745 				masterpan=(val<-64)?-64:(val>64)?64:val;
746 			calcvols();
747 			break;
748 		case mcpMasterBalance:
749 			if (val>=-64 && val<=64)
750 				masterbal=(val<-64)?-64:(val>64)?64:val;
751 			calcvols();
752 			break;
753 		case mcpMasterSurround:
754 			mastersrnd=val?1:0;
755 			calcvols();
756 			break;
757 		case mcpMasterReverb:
758 			masterrvb=(val>=64)?63:(val<-64)?-64:val;
759 			break;
760 		case mcpMasterSpeed:
761 			relspeed=(val<16)?16:val;
762 			calcspeed();
763 			break;
764 		case mcpMasterPitch:
765 			relpitch=val;
766 			calcsteps();
767 			break;
768 		case mcpMasterFilter:
769 			interpolation=val;
770 			break;
771 		case mcpMasterAmplify:
772 			amplify=val;
773 			if (channelnum)
774 			{
775 				calcamptab(amplify);
776 				mixSetAmplify(amplify);
777 			}
778 			break;
779 		case mcpMasterPause:
780 			_pause=val;
781 			break;
782 		case mcpGRestrict:
783 			restricted=val;
784 		break;
785 	}
786 }
787 
GET(int ch,int opt)788 static int GET(int ch, int opt)
789 {
790 	/* Refered by OpenPlayer
791 	 */
792 	struct channel *chn;
793 
794 	if (ch>=channelnum)
795 		ch=channelnum-1;
796 	if (ch<0)
797 		ch=0;
798 	chn=&channels[ch];
799 	switch (opt)
800 	{
801 		case mcpCStatus:
802 			return !!(chn->status&MIXRQ_PLAYING);
803 		case mcpCMute:
804 			return !!(chn->status&MIXRQ_MUTE);
805 		case mcpGTimer:
806 			if (_pause)
807 				return imuldiv(playsamps, 65536, samprate);
808 			else
809 				return plrGetTimer()-imuldiv(pausesamps, 65536, samprate);
810 		case mcpGCmdTimer:
811 			return umuldiv(cmdtimerpos, 256, samprate);
812 		case mcpMasterReverb:
813 			return masterrvb;
814 	}
815 	return 0;
816 }
817 
Idle(void)818 static void Idle(void)
819 {
820 	mixer();
821 	if (plrIdle)
822 		plrIdle();
823 }
824 
825 
826 
GetMixChannel(unsigned int ch,struct mixchannel * chn,uint32_t rate)827 static void GetMixChannel(unsigned int ch, struct mixchannel *chn, uint32_t rate)
828 	/* Refered to by OpenPlayer to mixInit */
829 {
830 	struct channel *c=&channels[ch];
831 
832 	if (c->status&MIXRQ_PLAY16BIT)
833 		chn->samp=(void*)((unsigned long)c->samp<<1);
834 	else
835 		chn->samp=c->samp;
836 	chn->realsamp.fmt=chn->samp; /* at this point, they match */
837 	chn->length=c->length;
838 	chn->loopstart=c->loopstart;
839 	chn->loopend=c->loopend;
840 	chn->fpos=c->fpos;
841 	chn->pos=c->pos;
842 	chn->vol.vols[0]=abs(c->vol[0]);
843 	chn->vol.vols[1]=abs(c->vol[1]);
844 	chn->step=imuldiv(c->step, samprate, (signed)rate);
845 	chn->status=0;
846 	if (c->status&MIXRQ_MUTE)
847 		chn->status|=MIX_MUTE;
848 	if (c->status&MIXRQ_PLAY16BIT)
849 		chn->status|=MIX_PLAY16BIT;
850 	if (c->status&MIXRQ_LOOPED)
851 		chn->status|=MIX_LOOPED;
852 	if (c->status&MIXRQ_PINGPONGLOOP)
853 		chn->status|=MIX_PINGPONGLOOP;
854 	if (c->status&MIXRQ_PLAYING)
855 		chn->status|=MIX_PLAYING;
856 	if (c->status&MIXRQ_INTERPOLATE)
857 		chn->status|=MIX_INTERPOLATE;
858 }
859 
LoadSamples(struct sampleinfo * sil,int n)860 static int LoadSamples(struct sampleinfo *sil, int n)
861 {
862 #if 0
863 	int i;
864 	if (!mcpReduceSamples(sil, n, 0x40000000, mcpRedToMono))
865 		return 0;
866 
867 	samples=malloc(sizeof(*sil)*n);
868 	memcpy(samples, sil, sizeof(*sil)*n);
869 
870 	for (i=0;i<n;i++)
871 	{
872 		samples[i].ptr=malloc(samples[i].length+pagesize()*10);
873 		samples[i].ptr= (char *)(((int) samples[i].ptr + pagesize()*4) & ~(pagesize()-1) );
874 		memcpy(samples[i].ptr, sil[i].ptr, samples[i].length);
875 		mprotect((void *)((int)(samples[i].ptr) & ~(pagesize()-1)), samples[i].length, PROT_READ);
876 	}
877 	samplenum=n;
878 
879 #else
880 	if (!mcpReduceSamples(sil, n, 0x40000000, mcpRedToMono))
881 		return 0;
882 
883 	samples=sil;
884 	samplenum=n;
885 #endif
886 	return 1;
887 }
888 
OpenPlayer(int chan,void (* proc)(),struct ocpfilehandle_t * source_file)889 static int OpenPlayer(int chan, void (*proc)(), struct ocpfilehandle_t *source_file)
890 {
891 	uint32_t currentrate;
892 	uint16_t mixrate;
893 	struct mixqpostprocregstruct *mode;
894 
895 	fadedown[0]=fadedown[1]=0;
896 	playsamps=pausesamps=0;
897 	if (chan>MAXCHAN)
898 		chan=MAXCHAN;
899 
900 	if (!plrPlay)
901 		return 0;
902 
903 	currentrate=mcpMixProcRate/chan;
904 	mixrate=(currentrate>mcpMixMaxRate)?mcpMixMaxRate:currentrate;
905 	plrSetOptions(mixrate, mcpMixOpt|(restricted?PLR_RESTRICTED:0));
906 
907 	playerproc=proc;
908 
909 	if (!quality)
910 	{
911 		scalebuf=0;
912 		voltabsq=0;
913 		interpoltabq=0;
914 		interpoltabq2=0;
915 		if (!(voltabsr=malloc(sizeof(uint32_t)*513*256))) /*new long [513][256];*/
916 			return 0;
917 		if (!(interpoltabr=malloc(sizeof(uint8_t)*16*256*2))) /*new unsigned char [16][256][2];*/
918 		{
919 			free(voltabsr);
920 			return 0;
921 		}
922 	} else {
923 		voltabsr=0;
924 		interpoltabr=0;
925 		if (!(scalebuf=malloc(sizeof(int16_t)*MIXBUFLEN))) /* new short [MIXBUFLEN];*/
926 			return 0;
927 
928 		if (!(voltabsq=malloc(sizeof(uint16_t)*513*2*256))) /*new short [513][2][256];*/
929 		{
930 			free(scalebuf);
931 			scalebuf=0;
932 			return 0;
933 		}
934 		if (!(interpoltabq=malloc(sizeof(uint16_t)*2*32*256*2))) /*new unsigned short [2][32][256][2];*/
935 		{
936 			free(scalebuf);
937 			free(voltabsq);
938 			scalebuf=0;
939 			return 0;
940 		}
941 		if (!(interpoltabq2=malloc(sizeof(uint16_t)*2*16*256*4))) /*new unsigned short [2][16][256][4];*/
942 		{
943 			free(scalebuf);
944 			free(voltabsq);
945 			free(interpoltabq);
946 			scalebuf=0;
947 			return 0;
948 		}
949 	}
950 	if (!(buf32=malloc(sizeof(uint32_t)*(MIXBUFLEN<<1)))) /*new long [MIXBUFLEN<<1];*/
951 	{
952 		if (voltabsr) free(voltabsr);
953 		if (interpoltabr) free(interpoltabr);
954 		if (scalebuf) free(scalebuf);
955 		if (voltabsq) free(voltabsq);
956 		if (interpoltabq) free(interpoltabq);
957 		if (interpoltabq2) free(interpoltabq2);
958 		scalebuf=0;
959 		return 0;
960 	}
961 	if (!(amptab=malloc(sizeof(int16_t)*3*256+sizeof(int32_t)))) /* PADDING since assembler indexes some bytes beyond tab and ignores upper bits */ /*new short [3][256];*/
962 	{
963 		if (voltabsr) free(voltabsr);
964 		if (interpoltabr) free(interpoltabr);
965 		if (scalebuf) free(scalebuf);
966 		if (voltabsq) free(voltabsq);
967 		if (interpoltabq) free(interpoltabq);
968 		if (interpoltabq2) free(interpoltabq2);
969 		free(buf32);
970 		scalebuf=0;
971 		return 0;
972 	}
973 
974 	if (!(channels=malloc(sizeof(struct channel)*chan))) /*new channel[chan];*/
975 	{
976 		if (voltabsr) free(voltabsr);
977 		if (interpoltabr) free(interpoltabr);
978 		if (scalebuf) free(scalebuf);
979 		if (voltabsq) free(voltabsq);
980 		if (interpoltabq) free(interpoltabq);
981 		if (interpoltabq2) free(interpoltabq2);
982 		free(buf32);
983 		free(channels);
984 		scalebuf=0;
985 		return 0;
986 	}
987 
988 	mcpGetMasterSample=plrGetMasterSample;
989 	mcpGetRealMasterVolume=plrGetRealMasterVolume;
990 	if (!mixInit(GetMixChannel, resample, chan, amplify))
991 		return 0;
992 
993 	memset(channels, 0, sizeof(struct channel)*chan);
994 	calcvols();
995 
996 	if (!quality)
997 	{
998 		mixrSetupAddresses(&voltabsr[256], interpoltabr);
999 		calcinterpoltabr();
1000 		calcvoltabsr();
1001 	} else {
1002 		mixqSetupAddresses(&voltabsq[256], interpoltabq, interpoltabq2);
1003 		calcinterpoltabq();
1004 		calcvoltabsq();
1005 	}
1006 
1007 	if (!plrOpenPlayer(&plrbuf, &buflen, mcpMixBufSize * plrRate / 1000, source_file))
1008 	{
1009 		mixClose();
1010 		return 0;
1011 	}
1012 
1013 	stereo=(plrOpt&PLR_STEREO)?1:0;
1014 	bit16=(plrOpt&PLR_16BIT)?1:0;
1015 	signedout=!!(plrOpt&PLR_SIGNEDOUT);
1016 	reversestereo=!!(plrOpt&PLR_REVERSESTEREO);
1017 
1018 	samprate=plrRate;
1019 	bufpos=0;
1020 	_pause=0;
1021 	orgspeed=12800;
1022 
1023 	channelnum=chan;
1024 	mcpNChan=chan;
1025 	mcpIdle=Idle;
1026 
1027 	calcamptab(amplify);
1028 	calcspeed();
1029 	/* playerproc();*/  /* some timing is wrong here!*/
1030 	tickwidth=newtickwidth;
1031 	tickplayed=0;
1032 	cmdtimerpos=0;
1033 	if (!pollInit(timerproc))
1034 	{
1035 		mcpNChan=0;
1036 		mcpIdle=0;
1037 		plrClosePlayer();
1038 		mixClose();
1039 		return 0;
1040 	}
1041 
1042 	for (mode=postprocs; mode; mode=mode->next)
1043 		if (mode->Init)
1044 			mode->Init(samprate, stereo);
1045 
1046 	return 1;
1047 }
1048 
ClosePlayer()1049 static void ClosePlayer()
1050 {
1051 	struct mixqpostprocregstruct *mode;
1052 
1053 	mcpNChan=0;
1054 	mcpIdle=0;
1055 
1056 	pollClose();
1057 
1058 	plrClosePlayer();
1059 
1060 	channelnum=0;
1061 	restricted=0;
1062 
1063 	mixClose();
1064 
1065 	for (mode=postprocs; mode; mode=mode->next)
1066 		if (mode->Close)
1067 			mode->Close();
1068 
1069 	if (voltabsr) free(voltabsr);
1070 	if (interpoltabr) free(interpoltabr);
1071 	if (scalebuf) free(scalebuf);
1072 	if (voltabsq) free(voltabsq);
1073 	if (interpoltabq) free(interpoltabq);
1074 	if (interpoltabq2) free(interpoltabq2);
1075 
1076 	free(channels);
1077 	free(amptab);
1078 	free(buf32);
1079 	scalebuf=0;
1080 
1081 	voltabsr=NULL;
1082 	interpoltabr=NULL;
1083 	scalebuf=NULL;
1084 	voltabsq=NULL;
1085 	interpoltabq=NULL;
1086 	interpoltabq2=NULL;
1087 }
1088 
wmixInit(const struct deviceinfo * dev)1089 static int wmixInit(const struct deviceinfo *dev)
1090 {
1091 	resample=!!(dev->opt&MIXRQ_RESAMPLE);
1092 	quality=!!dev->subtype;
1093 
1094 	restricted=0;
1095 	amplify=65535;
1096 	relspeed=256;
1097 	relpitch=256;
1098 	interpolation=0;
1099 	mastervol=64;
1100 	masterbal=0;
1101 	masterpan=0;
1102 	mastersrnd=0;
1103 	channelnum=0;
1104 
1105 	mcpLoadSamples=LoadSamples;
1106 	mcpOpenPlayer=OpenPlayer;
1107 	mcpClosePlayer=ClosePlayer;
1108 	mcpGet=GET;
1109 	mcpSet=SET;
1110 
1111 #ifdef I386_ASM
1112 
1113 	/* Self-modifying code needs access to modify it self */
1114 	{
1115 		int fd;
1116 		char *file=strdup("/tmp/ocpXXXXXX");
1117 		char *start1, *stop1, *start2, *stop2;
1118 		int len1, len2;
1119 		fd=mkstemp(file);
1120 
1121 		start1=(void *)remap_range1_start;
1122 		stop1=(void *)remap_range1_stop;
1123 		start2=(void *)remap_range2_start;
1124 		stop2=(void *)remap_range2_stop;
1125 #ifdef MIXER_DEBUG
1126 		fprintf(stderr, "range1: %p - %p\n", start1, stop1);
1127 		fprintf(stderr, "range2: %p - %p\n", start2, stop2);
1128 #endif
1129 
1130 		start1=(char *)(((int)start1)&~(pagesize()-1));
1131 		start2=(char *)(((int)start2)&~(pagesize()-1));
1132 		len1=((stop1-start1)+pagesize()-1)& ~(pagesize()-1);
1133 		len2=((stop2-start2)+pagesize()-1)& ~(pagesize()-1);
1134 #ifdef MIXER_DEBUG
1135 		fprintf(stderr, "mprot: %p + %08x\n", start1, len1);
1136 		fprintf(stderr, "mprot: %p + %08x\n", start2, len2);
1137 #endif
1138 		if (write(fd, start1, len1)!=len1)
1139 		{
1140 #ifdef MIXER_DEBUG
1141 			fprintf(stderr, "write 1 failed\n");
1142 #endif
1143 			return 0;
1144 		}
1145 		if (write(fd, start2, len2)!=len2)
1146 		{
1147 #ifdef MIXER_DEBUG
1148 			fprintf(stderr, "write 2 failed\n");
1149 #endif
1150 			return 0;
1151 		}
1152 
1153 		if (mmap(start1, len1, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, 0)==MAP_FAILED)
1154 		{
1155 			perror("mmap()");
1156 			return 0;
1157 		}
1158 
1159 		if (mmap(start2, len2, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, len1)==MAP_FAILED)
1160 		{
1161 			perror("mmap()");
1162 			return 0;
1163 		}
1164 
1165 /*
1166 		if (mprotect((char *)(((int)remap_range1_start)&~(pagesize()-1)), (((char *)remap_range1_stop-(char *)remap_range1_start)+pagesize()-1)& ~(pagesize()-1), PROT_READ|PROT_WRITE|PROT_EXEC) ||
1167 		    mprotect((char *)(((int)remap_range2_start)&~(pagesize()-1)), (((char *)remap_range2_stop-(char *)remap_range2_start)+pagesize()-1)& ~(pagesize()-1), PROT_READ|PROT_WRITE|PROT_EXEC) )
1168 	    {
1169 			perror("Couldn't mprotect");
1170 			return 0;
1171 		}*/
1172 #ifdef MIXER_DEBUG
1173 		fprintf(stderr, "Done ?\n");
1174 #endif
1175 		close(fd);
1176 		unlink(file);
1177 		free(file);
1178 	}
1179 #endif
1180 
1181 	return 1;
1182 }
1183 
wmixClose(void)1184 static void wmixClose(void)
1185 {
1186 	mcpOpenPlayer=0;
1187 }
1188 
1189 
wmixDetect(struct deviceinfo * c)1190 static int wmixDetect(struct deviceinfo *c)
1191 {
1192 	c->devtype=&mcpMixer;
1193 	c->port=-1;
1194 	c->port2=-1;
1195 /*
1196 	c->irq=-1;
1197 	c->irq2=-1;
1198 	c->dma=-1;
1199 	c->dma2=-1;
1200 */
1201 	if (c->subtype==-1)
1202 		c->subtype=0;
1203 	c->chan=/*(MAXCHAN>99)?99:MAXCHAN;*/MAXCHAN;
1204 	c->mem=0;
1205 	return 1;
1206 }
1207 
mixrRegisterPostProc(struct mixqpostprocregstruct * mode)1208 void mixrRegisterPostProc(struct mixqpostprocregstruct *mode)
1209 {
1210 	mode->next=postprocs;
1211 	postprocs=mode;
1212 }
1213 
1214 #include "dev/devigen.h"
1215 #include "boot/psetting.h"
1216 #include "dev/deviplay.h"
1217 #include "boot/plinkman.h"
1218 
1219 static struct mixqpostprocaddregstruct *postprocadds;
1220 
mixGetOpt(const char * sec)1221 static uint32_t mixGetOpt(const char *sec)
1222 {
1223 	uint32_t opt=0;
1224 	if (cfGetProfileBool(sec, "mixresample", 0, 0))
1225 		opt|=MIXRQ_RESAMPLE;
1226 	return opt;
1227 }
1228 
mixrInit(const char * sec)1229 static void mixrInit(const char *sec)
1230 {
1231 	char regname[50];
1232 	const char *regs;
1233 
1234 
1235 	fprintf(stderr, "[devwmix] INIT, ");
1236 	if (!quality)
1237 	{
1238 #ifdef I386_ASM
1239 		fprintf(stderr, "using dwmixa.c x86-asm version\n");
1240 #else
1241 #ifdef I386_ASM_EMU
1242 		fprintf(stderr, "using dwmixa.c x86-emu-asm version\n");
1243 #else
1244 		fprintf(stderr, "using dwmixa.c C version\n");
1245 #endif
1246 #endif
1247 	} else {
1248 #ifdef I386_ASM
1249 		fprintf(stderr, "using dwmixaq.c x86-asm version\n");
1250 #else
1251 		fprintf(stderr, "using dwmixaq.c C version\n");
1252 #endif
1253 	}
1254 
1255 	postprocs=0;
1256 	regs=cfGetProfileString(sec, "postprocs", "");
1257 
1258 	while (cfGetSpaceListEntry(regname, &regs, 49))
1259 	{
1260 		void *reg=_lnkGetSymbol(regname);
1261 		fprintf(stderr, "[%s] registering %s: %p\n", sec, regname, reg);
1262 		if (reg)
1263 			mixrRegisterPostProc((struct mixqpostprocregstruct*)reg);
1264 	}
1265 
1266 	postprocadds=0;
1267 	regs=cfGetProfileString(sec, "postprocadds", "");
1268 	while (cfGetSpaceListEntry(regname, &regs, 49))
1269 	{
1270 		void *reg=_lnkGetSymbol(regname);
1271 		if (reg)
1272 		{
1273 			((struct mixqpostprocaddregstruct*)reg)->next=postprocadds;
1274 			postprocadds=(struct mixqpostprocaddregstruct*)reg;
1275 		}
1276 	}
1277 }
1278 
mixProcKey(unsigned short key)1279 static int mixProcKey(unsigned short key)
1280 {
1281 	struct mixqpostprocaddregstruct *mode;
1282 	for (mode=postprocadds; mode; mode=mode->next)
1283 	{
1284 		int r=mode->ProcessKey(key);
1285 		if (r)
1286 			return r;
1287 	}
1288 
1289 	if (plrProcessKey)
1290 		return plrProcessKey(key);
1291 	return 0;
1292 }
1293 
1294 struct devaddstruct mcpMixAdd = {mixGetOpt, mixrInit, 0, mixProcKey};
1295 struct sounddevice mcpMixer={SS_WAVETABLE|SS_NEEDPLAYER, 0, "Mixer", wmixDetect, wmixInit, wmixClose, &mcpMixAdd};
1296 char *dllinfo="driver mcpMixer";
1297 
1298 struct linkinfostruct dllextinfo = {.name = "devwmix", .desc = "OpenCP Wavetable Device: Mixer (c) 1994-10 Niklas Beisert, Tammo Hinrichs, Stian Skjelstad", .ver = DLLVERSION, .size = 0};
1299