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