1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * Wavetable Device: No Sound
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * revision history: (please note changes here)
20  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
21  *    -first release
22  *  -kb980717   Tammo Hinrichs <opencp@gmx.net>
23  *    -added _dllinfo record
24  */
25 
26 #define NO_CURSES
27 #include "config.h"
28 #include <string.h>
29 #include <stdlib.h>
30 #include "types.h"
31 #include "boot/plinkman.h"
32 #include "dev/imsdev.h"
33 #include "dev/mcp.h"
34 #include "stuff/timer.h"
35 #include "dev/mix.h"
36 #include "stuff/imsrtns.h"
37 
38 #define TIMERRATE 17100
39 #define MAXCHAN 256
40 
41 #define NONE_PLAYING 1
42 #define NONE_MUTE 2
43 #define NONE_LOOPED 4
44 #define NONE_PINGPONGLOOP 8
45 #define NONE_PLAY16BIT 16
46 
47 static const unsigned long samprate=44100;
48 
49 extern struct sounddevice mcpNone;
50 
51 struct channel
52 {
53 	void *samp;
54 	uint32_t length;
55 	uint32_t loopstart;
56 	uint32_t loopend;
57 	uint32_t replen;
58 	int32_t step;
59 	uint32_t pos;
60 	uint16_t fpos;
61 	uint8_t status;
62 	int8_t vol[2];
63 	uint8_t orgvol[2];
64 	uint16_t orgrate;
65 	int32_t orgfrq;
66 	int32_t orgdiv;
67 	uint8_t direct;
68 	uint8_t volopt;
69 	uint8_t orgloop;
70 	int orgvolx;
71 	int orgpan;
72 };
73 
74 static int pause;
75 
76 static struct sampleinfo *samples;
77 static int samplenum;
78 
79 static unsigned long amplify;
80 static unsigned char transform[2][2];
81 static unsigned long relpitch;
82 static int filter;
83 
84 static int channelnum;
85 static struct channel *channels;
86 
87 static void (*playerproc)(void);
88 static unsigned long tickwidth;
89 static unsigned long tickplayed;
90 static unsigned long orgspeed;
91 static unsigned short relspeed;
92 static unsigned long newtickwidth;
93 static unsigned long cmdtimerpos;
94 
95 static int mastervol;
96 static int masterpan;
97 static int masterbal;
98 
99 #include "dwnone_asminc.c"
100 
calcstep(struct channel * c)101 static void calcstep(struct channel *c)
102 {
103 	if (!(c->status&NONE_PLAYING))
104 		return;
105 	c->step=imuldiv(imuldiv(c->orgrate, ((c->step>=0)^c->direct)?c->orgfrq:-c->orgfrq, c->orgdiv)<<8, relpitch, samprate);
106 	c->direct=(c->orgfrq<0)^(c->orgdiv<0);
107 }
108 
calcspeed(void)109 static void calcspeed(void)
110 {
111 	if (channelnum)
112 		newtickwidth=imuldiv(256*256, samprate, orgspeed*relspeed);
113 }
114 
transformvol(struct channel * ch)115 static void transformvol(struct channel *ch)
116 {
117 	int v;
118 	v=transform[0][0]*ch->orgvol[0]+transform[0][1]*ch->orgvol[1];
119 	ch->vol[0]=(v>4096)?64:(v<-4096)?-64:((v+32)>>6);
120 
121 	v=transform[1][0]*ch->orgvol[0]+transform[1][1]*ch->orgvol[1];
122 	ch->vol[1]=(v>4096)?64:(v<-4096)?-64:((v+32)>>6);
123 }
124 
calcvol(struct channel * chn)125 static void calcvol(struct channel *chn)
126 {
127 	if (chn->orgpan<0)
128 	{
129 		chn->orgvol[1]=(chn->orgvolx*(0x80+chn->orgpan))>>10;
130 		chn->orgvol[0]=(chn->orgvolx>>2)-chn->orgvol[1];
131 	} else {
132 		chn->orgvol[0]=(chn->orgvolx*(0x80-chn->orgpan))>>10;
133 		chn->orgvol[1]=(chn->orgvolx>>2)-chn->orgvol[0];
134 	}
135 	transformvol(chn);
136 }
137 
playchannels(unsigned short len)138 static void playchannels(unsigned short len)
139 {
140 	int i;
141 
142 	if (!len)
143 		return;
144 	for (i=0; i<channelnum; i++)
145 	{
146 		struct channel *c=&channels[i];
147 		if (c->status&NONE_PLAYING)
148 			nonePlayChannel(len, c);
149 	}
150 }
151 
152 
timerproc(void)153 static void timerproc(void)
154 {
155 	unsigned int bufdelta=samprate*TIMERRATE/1193046;
156 
157 	if (channelnum&&!pause)
158 	{
159 		while ((tickwidth-tickplayed)<=bufdelta)
160 		{
161 			playchannels(tickwidth-tickplayed);
162 			bufdelta-=tickwidth-tickplayed;
163 			tickplayed=0;
164 			playerproc();
165 			cmdtimerpos+=tickwidth;
166 			tickwidth=newtickwidth;
167 		}
168 		playchannels(bufdelta);
169 		tickplayed+=bufdelta;
170 	}
171 }
172 
173 
calcvols(void)174 static void calcvols(void)
175 {
176 	signed char vols[2][2];
177 	int i;
178 
179 	vols[0][0]=0x20+(masterpan>>1);
180 	vols[0][1]=0x20-(masterpan>>1);
181 	vols[1][0]=0x20-(masterpan>>1);
182 	vols[1][1]=0x20+(masterpan>>1);
183 
184 	if (masterbal>0)
185 	{
186 		vols[0][0]=((signed short)vols[0][0]*(0x40-masterbal))>>6;
187 		vols[0][1]=((signed short)vols[0][1]*(0x40-masterbal))>>6;
188 	} else {
189 		vols[1][0]=((signed short)vols[1][0]*(0x40+masterbal))>>6;
190 		vols[1][1]=((signed short)vols[1][1]*(0x40+masterbal))>>6;
191 	}
192 
193 	vols[0][0]=((signed short)vols[0][0]*mastervol)>>6;
194 	vols[0][1]=((signed short)vols[0][1]*mastervol)>>6;
195 	vols[1][0]=((signed short)vols[1][0]*mastervol)>>6;
196 	vols[1][1]=((signed short)vols[1][1]*mastervol)>>6;
197 
198 	memcpy(transform, vols, 4);
199 	for (i=0; i<channelnum; i++)
200 		transformvol(&channels[i]);
201 }
202 
calcsteps(void)203 static void calcsteps(void)
204 {
205 	int i;
206 	for (i=0; i<channelnum; i++)
207 		calcstep(&channels[i]);
208 }
209 
SetInstr(struct channel * chn,unsigned short samp)210 static void SetInstr(struct channel *chn, unsigned short samp)
211 {
212 	struct sampleinfo *s=&samples[samp];
213 	chn->status&=~(NONE_PLAYING|NONE_LOOPED|NONE_PINGPONGLOOP|NONE_PLAY16BIT);
214 	chn->samp=s->ptr;
215 	if (s->type&mcpSamp16Bit)
216 		chn->status|=NONE_PLAY16BIT;
217 	if (s->type&mcpSampLoop)
218 		chn->status|=NONE_LOOPED;
219 	if (s->type&mcpSampBiDi)
220 		chn->status|=NONE_PINGPONGLOOP;
221 	chn->length=s->length;
222 	chn->loopstart=s->loopstart;
223 	chn->loopend=s->loopend;
224 	chn->replen=(chn->status&NONE_LOOPED)?(s->loopend-s->loopstart):0;
225 	chn->orgloop=chn->status&NONE_LOOPED;
226 	chn->orgrate=s->samprate;
227 	chn->step=0;
228 	chn->pos=0;
229 	chn->fpos=0;
230 	chn->orgvol[0]=0;
231 	chn->orgvol[1]=0;
232 	chn->vol[0]=0;
233 	chn->vol[1]=0;
234 }
235 
SET(int ch,int opt,int val)236 static void SET(int ch, int opt, int val)
237 {
238 	int tmp;
239 	switch (opt)
240 	{
241 		case mcpGSpeed:
242 			orgspeed=val;
243 			calcspeed();
244 			break;
245 		case mcpCInstrument:
246 			SetInstr(&channels[ch], val);
247 			break;
248 		case mcpCMute:
249 			if (val)
250 				channels[ch].status|=NONE_MUTE;
251 			else
252 				channels[ch].status&=~NONE_MUTE;
253 			break;
254 		case mcpCStatus:
255 			if (!val)
256 				channels[ch].status&=~NONE_PLAYING;
257 			break;
258 		case mcpCReset:
259 			tmp=channels[ch].status&NONE_MUTE;
260 			memset(&channels[ch], 0, sizeof(struct channel));
261 			channels[ch].status=tmp;
262 			break;
263 		case mcpCVolume:
264 			channels[ch].orgvolx=(val>0xF8)?0x100:(val<0)?0:(val+3);
265 			calcvol(&channels[ch]);
266 			break;
267 		case mcpCPanning:
268 			channels[ch].orgpan=(val>0x78)?0x80:(val<-0x78)?-0x80:val;
269 			calcvol(&channels[ch]);
270 			break;
271 		case mcpMasterAmplify:
272 			amplify=val;
273 			if (channelnum)
274 				mixSetAmplify(amplify);
275 			break;
276 		case mcpMasterPause:
277 			pause=val;
278 			break;
279 		case mcpCPosition:
280 			channels[ch].status&=~NONE_PLAYING;
281 			if ((unsigned)val>=channels[ch].length)
282 			{
283 				if (channels[ch].status&NONE_LOOPED)
284 					val=channels[ch].loopstart;
285 				else
286 					break;
287 			}
288 
289 			channels[ch].step=0;
290 			channels[ch].direct=0;
291 			calcstep(&channels[ch]);
292 			channels[ch].pos=val;
293 			channels[ch].fpos=0;
294 			channels[ch].status|=NONE_PLAYING;
295 			break;
296 		case mcpCPitch:
297 			channels[ch].orgfrq=8363;
298 			channels[ch].orgdiv=mcpGetFreq8363(-val);calcstep(&channels[ch]);
299 			break;
300 		case mcpCPitchFix:
301 			channels[ch].orgfrq=val;
302 			channels[ch].orgdiv=0x10000;
303 			calcstep(&channels[ch]);
304 			break;
305 		case mcpCPitch6848:
306 			channels[ch].orgfrq=6848;
307 			channels[ch].orgdiv=val;
308 			calcstep(&channels[ch]);
309 			break;
310 		case mcpMasterVolume:
311 			mastervol=val;
312 			calcvols();
313 			break;
314 		case mcpMasterPanning:
315 			masterpan=val;
316 			calcvols();
317 			break;
318 		case mcpMasterBalance:
319 			masterbal=val;
320 			calcvols();
321 			break;
322 		case mcpMasterSpeed:
323 			relspeed=(val<16)?16:val;
324 			calcspeed();
325 			break;
326 		case mcpMasterPitch:
327 			relpitch=val;
328 			calcsteps();
329 			break;
330 		case mcpMasterFilter:
331 			filter=val;
332 			break;
333 	}
334 }
335 
GET(int ch,int opt)336 static int GET(int ch, int opt)
337 {
338 	switch (opt)
339 	{
340 		case mcpCStatus:
341 			return !!(channels[ch].status&NONE_PLAYING);
342 		case mcpCMute:
343 			return !!(channels[ch].status&NONE_MUTE);
344 		case mcpGTimer:
345 			return tmGetTimer();
346 		case mcpGCmdTimer:
347 			return umuldiv(cmdtimerpos, 65536, samprate);
348 	}
349 	return 0;
350 }
351 
352 
GetMixChannel(unsigned int ch,struct mixchannel * chn,uint32_t rate)353 static void GetMixChannel(unsigned int ch, struct mixchannel *chn, uint32_t rate)
354 {
355 	struct channel *c=&channels[ch];
356 	chn->samp=c->samp;
357 	chn->realsamp.fmt=c->samp;
358 	chn->length=c->length;
359 	chn->loopstart=c->loopstart;
360 	chn->loopend=c->loopend;
361 	chn->fpos=c->fpos;
362 	chn->pos=c->pos;
363 	chn->vol.vols[0]=abs(c->vol[0]);
364 	chn->vol.vols[1]=abs(c->vol[1]);
365 	chn->step=imuldiv(c->step, samprate, (signed)rate);
366 	chn->status=0;
367 	if (c->status&NONE_MUTE)
368 		chn->status|=MIX_MUTE;
369 	if (c->status&NONE_PLAY16BIT)
370 		chn->status|=MIX_PLAY16BIT;
371 	if (c->status&NONE_LOOPED)
372 		chn->status|=MIX_LOOPED;
373 	if (c->status&NONE_PINGPONGLOOP)
374 		chn->status|=MIX_PINGPONGLOOP;
375 	if (c->status&NONE_PLAYING)
376 		chn->status|=MIX_PLAYING;
377 	if (filter)
378 		chn->status|=MIX_INTERPOLATE;
379 }
380 
381 
382 
LoadSamples(struct sampleinfo * sil,int n)383 static int LoadSamples(struct sampleinfo *sil, int n)
384 {
385 	if (!mcpReduceSamples(sil, n, 0x40000000, mcpRedToMono))
386 		return 0;
387 
388 	samples=sil;
389 	samplenum=n;
390 
391 	return 1;
392 }
393 
394 
OpenPlayer(int chan,void (* proc)(void),struct ocpfilehandle_t * source_file)395 static int OpenPlayer(int chan, void (*proc)(void), struct ocpfilehandle_t *source_file)
396 {
397 	if (chan>MAXCHAN)
398 		chan=MAXCHAN;
399 
400 	if (!(channels=malloc(sizeof(struct channel)*chan)))
401 	{
402 		return 0;
403 	}
404 
405 
406 	playerproc=proc;
407 
408 	if (!mixInit(GetMixChannel, 1, chan, amplify))
409 	{
410 		free(channels);
411 		channels=0;
412 		return 0;
413 	}
414 
415 	memset(channels, 0, sizeof(struct channel)*chan);
416 
417 	calcvols();
418 	pause=0;
419 	orgspeed=12800;
420 	calcspeed();
421 	tickwidth=newtickwidth;
422 	tickplayed=0;
423 	cmdtimerpos=0;
424 
425 	channelnum=chan;
426 	tmInit(timerproc, TIMERRATE);
427 
428 	mcpNChan=chan;
429 
430 	return 1;
431 }
432 
ClosePlayer(void)433 static void ClosePlayer(void)
434 {
435 	mcpNChan=0;
436 	tmClose();
437 	channelnum=0;
438 	mixClose();
439 	free(channels);
440 	channels=0;
441 }
442 
Init(const struct deviceinfo * c)443 static int Init(const struct deviceinfo *c)
444 {
445 	amplify=65535;
446 	relspeed=256;
447 	relpitch=256;
448 	filter=0;
449 	mastervol=64;
450 	masterpan=64;
451 	masterbal=0;
452 
453 	channelnum=0;
454 
455 	mcpLoadSamples=LoadSamples;
456 	mcpOpenPlayer=OpenPlayer;
457 	mcpClosePlayer=ClosePlayer;
458 	mcpSet=SET;
459 	mcpGet=GET;
460 
461 	return 1;
462 }
463 
Close(void)464 static void Close(void)
465 {
466 	mcpOpenPlayer=0;
467 }
468 
469 
Detect(struct deviceinfo * c)470 static int Detect(struct deviceinfo *c)
471 {
472 	c->devtype=&mcpNone;
473 	c->port=-1;
474 	c->port2=-1;
475 /*
476 	c->irq=-1;
477 	c->irq2=-1;
478 	c->dma=-1;
479 	c->dma2=-1;
480 */
481 	c->subtype=-1;
482 	c->chan=(MAXCHAN>99)?99:MAXCHAN;
483 	c->mem=0;
484 	return 1;
485 }
486 
487 struct sounddevice mcpNone={SS_WAVETABLE, 0, "None", Detect, Init, Close, 0};
488 char *dllinfo = "driver mcpNone";
489 
490 struct linkinfostruct dllextinfo = {.name = "devwnone", .desc = "OpenCP Wavetable Device: None (c) 1994-09 Niklas Beisert, Tammo Hinrichs", .ver = DLLVERSION, .size = 0};
491