1 /* OpenCP Module Player
2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3 * copyright (c) '04-'21 Stian Skjelstad <stian.skjelstad@gmail.com>
4 *
5 * WAVPlay interface routines
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * revision history: (please note changes here)
22 * -nb980510 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
23 * -first release
24 * -ryg981219 Fabian Giesen <fabian@jdcs.su.nw.schule.de>
25 * -made max amplification 793% (as in module players)
26 */
27
28 #include "config.h"
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include "types.h"
35 #include "boot/plinkman.h"
36 #include "boot/psetting.h"
37 #include "cpiface/cpiface.h"
38 #include "dev/deviplay.h"
39 #include "dev/player.h"
40 #include "filesel/filesystem.h"
41 #include "filesel/mdb.h"
42 #include "filesel/pfilesel.h"
43 #include "stuff/compat.h"
44 #include "stuff/err.h"
45 #include "stuff/poutput.h"
46 #include "stuff/sets.h"
47 #include "wave.h"
48
49 #define _MAX_FNAME 8
50 #define _MAX_EXT 4
51
52 extern char plPause;
53
54 static unsigned long wavelen;
55 static unsigned long waverate;
56
57 static time_t starttime;
58 static time_t pausetime;
59 static char currentmodname[_MAX_FNAME+1];
60 static char currentmodext[_MAX_EXT+1];
61 static char *modname;
62 static char *composer;
63 static short vol;
64 static short bal;
65 static short pan;
66 static char srnd;
67 static long amp;
68 static short speed;
69 static short reverb;
70 static short chorus;
71 static char finespeed=8;
72 static time_t pausefadestart;
73 static uint8_t pausefaderelspeed;
74 static int8_t pausefadedirect;
75
startpausefade(void)76 static void startpausefade(void)
77 {
78 if (plPause)
79 starttime=starttime+dos_clock()-pausetime;
80
81 if (pausefadedirect)
82 {
83 if (pausefadedirect<0)
84 plPause=1;
85 pausefadestart=2*dos_clock()-DOS_CLK_TCK-pausefadestart;
86 } else
87 pausefadestart=dos_clock();
88
89 if (plPause)
90 {
91 plChanChanged=1;
92 wpPause(plPause=0);
93 pausefadedirect=1;
94 } else
95 pausefadedirect=-1;
96 }
97
dopausefade(void)98 static void dopausefade(void)
99 {
100 int16_t i;
101 if (pausefadedirect>0)
102 {
103 i=(dos_clock()-pausefadestart)*64/DOS_CLK_TCK;
104 if (i<0)
105 i=0;
106 if (i>=64)
107 {
108 i=64;
109 pausefadedirect=0;
110 }
111 } else {
112 i=64-(dos_clock()-pausefadestart)*64/DOS_CLK_TCK;
113 if (i>=64)
114 i=64;
115 if (i<=0)
116 {
117 i=0;
118 pausefadedirect=0;
119 pausetime=dos_clock();
120 wpPause(plPause=1);
121 plChanChanged=1;
122 wpSetSpeed(speed);
123 return;
124 }
125 }
126 pausefaderelspeed=i;
127 wpSetSpeed(speed*i/64);
128 }
wavDrawGStrings(unsigned short (* buf)[CONSOLE_MAX_X])129 static void wavDrawGStrings(unsigned short (*buf)[CONSOLE_MAX_X])
130 {
131 struct waveinfo inf;
132 long tim;
133 int l;
134 int p;
135
136 wpGetInfo(&inf);
137 tim=inf.len/inf.rate;
138
139 if (plScrWidth<128)
140 {
141 memset(buf[0]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
142 memset(buf[1]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
143 memset(buf[2]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
144
145 writestring(buf[0], 0, 0x09, " vol: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 15);
146 writestring(buf[0], 15, 0x09, " srnd: \xfa pan: l\xfa\xfa\xfam\xfa\xfa\xfar bal: l\xfa\xfa\xfam\xfa\xfa\xfar ", 41);
147 writestring(buf[0], 56, 0x09, " spd: ---% \x1D ptch: ---% ", 24);
148 writestring(buf[0], 6, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+4)>>3);
149 writestring(buf[0], 22, 0x0F, srnd?"x":"o", 1);
150 if (((pan+70)>>4)==4)
151 writestring(buf[0], 34, 0x0F, "m", 1);
152 else {
153 writestring(buf[0], 30+((pan+70)>>4), 0x0F, "r", 1);
154 writestring(buf[0], 38-((pan+70)>>4), 0x0F, "l", 1);
155 }
156 writestring(buf[0], 46+((bal+70)>>4), 0x0F, "I", 1);
157 _writenum(buf[0], 62, 0x0F, speed*100/256, 10, 3);
158 _writenum(buf[0], 75, 0x0F, speed*100/256, 10, 3);
159
160 writestring(buf[1], 57, 0x09, "amp: ...% filter: ... ", 23);
161 _writenum(buf[1], 62, 0x0F, amp*100/64, 10, 3);
162 writestring(buf[1], 75, 0x0F, "off", 3);
163
164 l=(inf.len>>(10-inf.stereo-inf.bit16));
165 p=(inf.pos>>(10-inf.stereo-inf.bit16));
166 writestring(buf[1], 0, 0x09, " pos: ...% / ......k size: ......k len: ..:..", 57);
167 _writenum(buf[1], 7, 0x0F, p*100/l, 10, 3);
168 writenum(buf[1], 43, 0x0F, (tim/60)%60, 10, 2, 1);
169 writestring(buf[1], 45, 0x0F, ":", 1);
170 writenum(buf[1], 46, 0x0F, tim%60, 10, 2, 0);
171 writenum(buf[1], 29, 0x0F, l, 10, 6, 1);
172 writenum(buf[1], 14, 0x0F, p, 10, 6, 1);
173
174 if (plPause)
175 tim=(pausetime-starttime);
176 else
177 tim=(time(NULL)-starttime);
178
179 writestring(buf[2], 0, 0x09, " wave \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... time: ..:.. ", 80);
180 writestring(buf[2], 8, 0x0F, currentmodname, _MAX_FNAME);
181 writestring(buf[2], 16, 0x0F, currentmodext, _MAX_EXT);
182 writestring(buf[2], 22, 0x0F, modname, 31);
183 if (plPause)
184 writestring(buf[2], 58, 0x0C, "paused", 6);
185 writenum(buf[2], 74, 0x0F, (tim/60)%60, 10, 2, 1);
186 writestring(buf[2], 76, 0x0F, ":", 1);
187 writenum(buf[2], 77, 0x0F, tim%60, 10, 2, 0);
188 } else {
189 memset(buf[0]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
190 memset(buf[1]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
191 memset(buf[2]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
192
193 writestring(buf[0], 0, 0x09, " volume: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 30);
194 writestring(buf[0], 30, 0x09, " surround: \xfa panning: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar balance: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar ", 72);
195 writestring(buf[0], 102, 0x09, " speed: ---% \x1D pitch: ---% ", 30);
196 writestring(buf[0], 12, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+2)>>2);
197 writestring(buf[0], 41, 0x0F, srnd?"x":"o", 1);
198 if (((pan+68)>>3)==8)
199 writestring(buf[0], 62, 0x0F, "m", 1);
200 else {
201 writestring(buf[0], 54+((pan+68)>>3), 0x0F, "r", 1);
202 writestring(buf[0], 70-((pan+68)>>3), 0x0F, "l", 1);
203 }
204 writestring(buf[0], 83+((bal+68)>>3), 0x0F, "I", 1);
205 _writenum(buf[0], 110, 0x0F, speed*100/256, 10, 3);
206 _writenum(buf[0], 124, 0x0F, speed*100/256, 10, 3);
207
208 l=(inf.len>>(10-inf.stereo-inf.bit16));
209 p=(inf.pos>>(10-inf.stereo-inf.bit16));
210 writestring(buf[1], 0, 0x09, " position: ...% / ......k size: ......k length: ..:.. opt: .....Hz, .. bit, ......", 92);
211 _writenum(buf[1], 14, 0x0F, p*100/l, 10, 3);
212 writenum(buf[1], 53, 0x0F, (tim/60)%60, 10, 2, 1);
213 writestring(buf[1], 55, 0x0F, ":", 1);
214 writenum(buf[1], 56, 0x0F, tim%60, 10, 2, 0);
215 writenum(buf[1], 36, 0x0F, l, 10, 6, 1);
216 writenum(buf[1], 21, 0x0F, p, 10, 6, 1);
217 writenum(buf[1], 65, 0x0F, inf.rate, 10, 5, 1);
218 writenum(buf[1], 74, 0x0F, 8<<inf.bit16, 10, 2, 1);
219 writestring(buf[1], 82, 0x0F, inf.stereo?"stereo":"mono", 6);
220
221 writestring(buf[1], 92, 0x09, " amplification: ...% filter: ... ", 40);
222 _writenum(buf[1], 110, 0x0F, amp*100/64, 10, 3);
223 writestring(buf[1], 124, 0x0F, "off", 3);
224
225 if (plPause)
226 tim=(pausetime-starttime);
227 else
228 tim=(time(NULL)-starttime);
229
230 writestring(buf[2], 0, 0x09, " wave \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... composer: ............................... time: ..:.. ", 132);
231 writestring(buf[2], 11, 0x0F, currentmodname, _MAX_FNAME);
232 writestring(buf[2], 19, 0x0F, currentmodext, _MAX_EXT);
233 writestring(buf[2], 25, 0x0F, modname, 31);
234 writestring(buf[2], 68, 0x0F, composer, 31);
235 if (plPause)
236 writestring(buf[2], 100, 0x0C, "playback paused", 15);
237 writenum(buf[2], 123, 0x0F, (tim/60)%60, 10, 2, 1);
238 writestring(buf[2], 125, 0x0F, ":", 1);
239 writenum(buf[2], 126, 0x0F, tim%60, 10, 2, 0);
240 }
241 }
242
normalize(void)243 static void normalize(void)
244 {
245 mcpNormalize(0);
246 speed=set.speed;
247 pan=set.pan;
248 bal=set.bal;
249 vol=set.vol;
250 amp=set.amp;
251 srnd=set.srnd;
252 reverb=set.reverb;
253 chorus=set.chorus;
254 wpSetAmplify(1024*amp);
255 wpSetVolume(vol, bal, pan, srnd);
256 wpSetSpeed(speed);
257 /*
258 wpSetMasterReverbChorus(reverb, chorus);
259 */
260 }
261
wavCloseFile()262 static void wavCloseFile()
263 {
264 wpClosePlayer();
265 }
266
wavProcessKey(unsigned short key)267 static int wavProcessKey(unsigned short key)
268 {
269 switch (key)
270 {
271 case KEY_ALT_K:
272 cpiKeyHelp('p', "Start/stop pause with fade");
273 cpiKeyHelp('P', "Start/stop pause with fade");
274 cpiKeyHelp(KEY_CTRL_P, "Start/stop pause");
275 cpiKeyHelp('<', "Jump back (big)");
276 cpiKeyHelp(KEY_CTRL_LEFT, "Jump back (big)");
277 cpiKeyHelp('>', "Jump forward (big)");
278 cpiKeyHelp(KEY_CTRL_RIGHT, "Jump forward (big)");
279 cpiKeyHelp(KEY_CTRL_UP, "Jump back (small)");
280 cpiKeyHelp(KEY_CTRL_DOWN, "Jump forward (small)");
281 cpiKeyHelp('-', "Decrease volume (small)");
282 cpiKeyHelp('+', "Increase volume (small)");
283 cpiKeyHelp('/', "Move balance left (small)");
284 cpiKeyHelp('*', "Move balance right (small)");
285 cpiKeyHelp(',', "Move panning against normal (small)");
286 cpiKeyHelp('.', "Move panning against reverse (small)");
287 cpiKeyHelp(KEY_F(2), "Decrease volume");
288 cpiKeyHelp(KEY_F(3), "Increase volume");
289 cpiKeyHelp(KEY_F(4), "Toggle surround on/off");
290 cpiKeyHelp(KEY_F(5), "Move panning against normal");
291 cpiKeyHelp(KEY_F(6), "Move panning against reverse");
292 cpiKeyHelp(KEY_F(7), "Move balance left");
293 cpiKeyHelp(KEY_F(8), "Move balance right");
294 cpiKeyHelp(KEY_F(9), "Decrease pitch speed");
295 cpiKeyHelp(KEY_F(11), "Decrease pitch speed");
296 cpiKeyHelp(KEY_F(10), "Increase pitch speed");
297 cpiKeyHelp(KEY_F(12), "Increase pitch speed");
298 if (plrProcessKey)
299 plrProcessKey(key);
300 return 0;
301
302 case 'p': case 'P':
303 startpausefade();
304 break;
305 case KEY_CTRL_P:
306 pausefadedirect=0;
307 if (plPause)
308 starttime=starttime+time(NULL)-pausetime;
309 else
310 pausetime=time(NULL);
311 plPause=!plPause;
312 wpPause(plPause);
313 break;
314 case KEY_CTRL_UP:
315 /* case 0x8D00: //ctrl-up */
316 wpSetPos(wpGetPos()-waverate);
317 break;
318 case KEY_CTRL_DOWN:
319 /* case 0x9100: //ctrl-down */
320 wpSetPos(wpGetPos()+waverate);
321 break;
322 case '<':
323 case KEY_CTRL_LEFT:
324 /* case 0x7300: //ctrl-left */
325 {
326 uint32_t pos = wpGetPos();
327 uint32_t newpos = pos -(wavelen>>5);
328 if (newpos > pos)
329 {
330 newpos = 0;
331 }
332 wpSetPos(newpos);
333 }
334 break;
335 case '>':
336 case KEY_CTRL_RIGHT:
337 /* case 0x7400: //ctrl-right */
338 {
339 uint32_t pos = wpGetPos();
340 uint32_t newpos = pos + (wavelen>>5);
341 if ((newpos < pos) || (newpos > wavelen)) /* catch both wrap around (not likely), and overshots */
342 {
343 newpos = wavelen - 4;
344 }
345 wpSetPos(newpos);
346 }
347 break;
348 /*
349 case 0x7700: //ctrl-home TODO keys
350 wpSetPos(0);
351 break;
352 */
353 case '-':
354 if (vol>=2)
355 vol-=2;
356 wpSetVolume(vol, bal, pan, srnd);
357 break;
358 case '+':
359 if (vol<=62)
360 vol+=2;
361 wpSetVolume(vol, bal, pan, srnd);
362 break;
363 case '/':
364 if ((bal-=4)<-64)
365 bal=-64;
366 wpSetVolume(vol, bal, pan, srnd);
367 break;
368 case '*':
369 if ((bal+=4)>64)
370 bal=64;
371 wpSetVolume(vol, bal, pan, srnd);
372 break;
373 case ',':
374 if ((pan-=4)<-64)
375 pan=-64;
376 wpSetVolume(vol, bal, pan, srnd);
377 break;
378 case '.':
379 if ((pan+=4)>64)
380 pan=64;
381 wpSetVolume(vol, bal, pan, srnd);
382 break;
383 case KEY_F(2): /*f2*/
384 if ((vol-=8)<0)
385 vol=0;
386 wpSetVolume(vol, bal, pan, srnd);
387 break;
388 case KEY_F(3): /*f3*/
389 if ((vol+=8)>64)
390 vol=64;
391 wpSetVolume(vol, bal, pan, srnd);
392 break;
393 case KEY_F(4): /*f4*/
394 wpSetVolume(vol, bal, pan, srnd=srnd?0:2);
395 break;
396 case KEY_F(5): /*f5*/
397 if ((pan-=16)<-64)
398 pan=-64;
399 wpSetVolume(vol, bal, pan, srnd);
400 break;
401 case KEY_F(6): /*f6*/
402 if ((pan+=16)>64)
403 pan=64;
404 wpSetVolume(vol, bal, pan, srnd);
405 break;
406 case KEY_F(7): /*f7*/
407 if ((bal-=16)<-64)
408 bal=-64;
409 wpSetVolume(vol, bal, pan, srnd);
410 break;
411 case KEY_F(8): /*f8*/
412 if ((bal+=16)>64)
413 bal=64;
414 wpSetVolume(vol, bal, pan, srnd);
415 break;
416 case KEY_F(9): /*f9*/
417 case KEY_F(11): /*f11*/
418 if ((speed-=finespeed)<16)
419 speed=16;
420 wpSetSpeed(speed);
421 break;
422 case KEY_F(10): /*f10*/
423 case KEY_F(12): /*f12*/
424 if ((speed+=finespeed)>2048)
425 speed=2048;
426 wpSetSpeed(speed);
427 break;
428 /*
429 case 0x5f00: // ctrl f2 TODO keys
430 if ((amp-=4)<4)
431 amp=4;
432 wpSetAmplify(1024*amp);
433 break;
434 case 0x6000: // ctrl f3 TODO keys
435 if ((amp+=4)>508)
436 amp=508;
437 wpSetAmplify(1024*amp);
438 break;
439 case 0x8900: // ctrl f11 TODO keys
440 finespeed=(finespeed==8)?1:8;
441 break;
442 case 0x6a00: // alt-f3 TODO keys
443 normalize();
444 break;
445 case 0x6900: // alt-f2 TODO keys
446 set.pan=pan;
447 set.bal=bal;
448 set.vol=vol;
449 set.speed=speed;
450 set.amp=amp;
451 set.srnd=srnd;
452 break;
453 case 0x6b00: // alt-f4 TODO keys
454 pan=64;
455 bal=0;
456 vol=64;
457
458 speed=256;
459 amp=64;
460 wpSetVolume(vol, bal, pan, srnd);
461 wpSetSpeed(speed);
462 wpSetAmplify(1024*amp);
463 break;*/
464 default:
465 if (plrProcessKey)
466 {
467 int ret=plrProcessKey(key);
468 if (ret==2)
469 cpiResetScreen();
470 if (ret)
471 return 1;
472 }
473 return 0;
474 }
475 return 1;
476 }
477
478
wavLooped(void)479 static int wavLooped(void)
480 {
481 if (pausefadedirect)
482 dopausefade();
483 wpSetLoop(fsLoopMods);
484 wpIdle();
485 if (plrIdle)
486 plrIdle();
487 return !fsLoopMods&&wpLooped();
488 }
489
490
wavOpenFile(struct moduleinfostruct * info,struct ocpfilehandle_t * wavf)491 static int wavOpenFile(struct moduleinfostruct *info, struct ocpfilehandle_t *wavf)
492 {
493 struct waveinfo inf;
494
495 if (!wavf)
496 return -1;
497
498 strncpy(currentmodname, info->name, _MAX_FNAME);
499 strncpy(currentmodext, info->name + _MAX_FNAME, _MAX_EXT);
500
501 modname=info->modname;
502 composer=info->composer;
503
504 fprintf(stderr, "preloading %s%s...\n", currentmodname, currentmodext);
505
506 plIsEnd=wavLooped;
507 plProcessKey=wavProcessKey;
508 plDrawGStrings=wavDrawGStrings;
509 plGetMasterSample=plrGetMasterSample;
510 plGetRealMasterVolume=plrGetRealMasterVolume;
511
512 if (!wpOpenPlayer(wavf))
513 {
514 #ifdef INITCLOSE_DEBUG
515 fprintf(stderr, "wpOpenPlayer FAILED\n");
516 #endif
517 return -1;
518 }
519
520 starttime=time(NULL);
521 plPause=0;
522 normalize();
523 pausefadedirect=0;
524
525 wpGetInfo(&inf);
526 wavelen=inf.len;
527 waverate=inf.rate;
528
529 return errOk;
530 }
531
532 struct cpifaceplayerstruct wavPlayer = {wavOpenFile, wavCloseFile};
533 struct linkinfostruct dllextinfo = {.name = "playwav", .desc = "OpenCP Wave Player (c) 1994-'21 Niklas Beisert, Tammo Hinrichs, Stian Skjelstad", .ver = DLLVERSION, .size = 0};
534