compile with -g -Os
[libogc.git] / libmodplay / modplay.c
blobe7f020f89ca9683f85673b0925d8326829f75a38
1 /*
2 Copyright (c) 2002,2003, Christian Nowak <chnowak@web.de>
3 All rights reserved.
5 Modified by Francisco Mu�oz 'Hermes' MAY 2008
7 Redistribution and use in source and binary forms, with or without modification, are
8 permitted provided that the following conditions are met:
10 - Redistributions of source code must retain the above copyright notice, this list of
11 conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright notice, this list
13 of conditions and the following disclaimer in the documentation and/or other
14 materials provided with the distribution.
15 - The names of the contributors may not be used to endorse or promote products derived
16 from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
19 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "defines.h"
33 #include "semitonetab.h"
34 #include "freqtab.h"
35 #include "modplay.h"
36 #include "mixer.h"
37 #ifndef GEKKO
38 #include "bpmtab.h"
39 #include "inctab.h"
40 #endif
42 #ifdef GP32
43 #include "gpstdlib.h"
44 #include "gpstdio.h"
46 volatile long* lcdcon1 = (long*)0x14a00000;
47 #define VLINE ((*lcdcon1 >> 18) & 0x1ff)
48 extern int deltavline;
50 #endif
52 #ifdef GEKKO
53 #include "video.h"
55 static u32 *inc_tabs[2] = {NULL,NULL};
56 static u32 *bpm_tabs[2] = {NULL,NULL};
57 #endif
59 #ifdef GP32
60 #include "gpmem.h"
61 #define MEM_CPY(a,b,c) gm_memcpy(a,b,c)
62 #define MEM_SET(a,b,c) gm_memset(a,b,c)
63 /*#define MEM_CMP(a,b,c) gm_memcmp(a,b,c)*/
64 static s32 MEM_CMP ( void * a, void * b, s32 l )
66 s32 i;
68 for (i=0;i<l;i++)
69 if (((u8*)a)[i]!=((u8*)b)[i])
70 return -1;
71 return 0;
73 #else
74 #define MEM_CPY(a,b,c) memcpy(a,b,c)
75 #define MEM_SET(a,b,c) memset(a,b,c)
76 #define MEM_CMP(a,b,c) memcmp(a,b,c)
77 #endif
79 #ifdef DREAMCAST
80 #include <kos.h>
81 #endif
83 #define MINI(a,b) ((a)<(b)?(a):(b))
84 #define MAXI(a,b) ((a)>(b)?(a):(b))
86 s32 shiftvals[33] =
88 0,8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4,
89 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
92 s16 wavetab[4][64] =
94 { /* Sine */
95 (s16)0, (s16)24, (s16)49, (s16)74, (s16)97, (s16)120, (s16)141, (s16)161,
96 (s16)180, (s16)197, (s16)212, (s16)224, (s16)235, (s16)244, (s16)250, (s16)253,
97 (s16)255, (s16)253, (s16)250, (s16)244, (s16)235, (s16)224, (s16)212, (s16)197,
98 (s16)180, (s16)161, (s16)141, (s16)120, (s16)97, (s16)74, (s16)49, (s16)24,
99 (s16)0, (s16)-24, (s16)-49, (s16)-74, (s16)-97, (s16)-120,(s16)-141,(s16)-161,
100 (s16)-180,(s16)-197,(s16)-212,(s16)-224,(s16)-235,(s16)-244,(s16)-250,(s16)-253,
101 (s16)-255,(s16)-253,(s16)-250,(s16)-244,(s16)-235,(s16)-224,(s16)-212,(s16)-197,
102 (s16)-180,(s16)-161,(s16)-141,(s16)-120,(s16)-97, (s16)-74, (s16)-49, (s16)-24
104 { /* Ramp down */
105 (s16)255, (s16)247, (s16)239, (s16)231, (s16)223, (s16)215, (s16)207, (s16)199,
106 (s16)191, (s16)183, (s16)175, (s16)167, (s16)159, (s16)151, (s16)143, (s16)135,
107 (s16)127, (s16)119, (s16)111, (s16)103, (s16)95, (s16)87, (s16)79, (s16)71,
108 (s16)63, (s16)55, (s16)47, (s16)39, (s16)31, (s16)23, (s16)15, (s16)7,
109 (s16)-1, (s16)-9, (s16)-17, (s16)-25, (s16)-33, (s16)-41, (s16)-49, (s16)-57,
110 (s16)-65, (s16)-73, (s16)-81, (s16)-89, (s16)-97, (s16)-105,(s16)-113,(s16)-121,
111 (s16)-129,(s16)-137,(s16)-145,(s16)-153,(s16)-161,(s16)-169,(s16)-177,(s16)-185,
112 (s16)-193,(s16)-201,(s16)-209,(s16)-217,(s16)-225,(s16)-233,(s16)-241,(s16)-249
114 { /* Square wave */
115 (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255,
116 (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255,
117 (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255,
118 (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255, (s16)255,
119 (s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,
120 (s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,
121 (s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,
122 (s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255,(s16)-255
124 { /* Random */
125 (s16)-26, (s16)-251,(s16)-198,(s16)-46, (s16)-96, (s16)198, (s16)168, (s16)228,
126 (s16)-49, (s16)-153,(s16)-236,(s16)-174,(s16)-37, (s16)61, (s16)187, (s16)120,
127 (s16)56, (s16)-197,(s16)248, (s16)-58, (s16)-204,(s16)172, (s16)58, (s16)253,
128 (s16)-155,(s16)57, (s16)62, (s16)-62, (s16)60, (s16)-137,(s16)-101,(s16)-184,
129 (s16)66, (s16)-160,(s16)160, (s16)-29, (s16)-91, (s16)243, (s16)175, (s16)-175,
130 (s16)149, (s16)97, (s16)3, (s16)-113,(s16)7, (s16)249, (s16)-241,(s16)-247,
131 (s16)110, (s16)-180,(s16)-139,(s16)-20, (s16)246, (s16)-86, (s16)-80, (s16)-134,
132 (s16)219, (s16)117, (s16)-143,(s16)-226,(s16)-166,(s16)120, (s16)-47, (s16)29
136 #if defined(GEKKO)
137 static u32* modplay_getinctab(s32 freq)
139 u32 tv;
140 u32 i,curr_tab,*inc_tab = NULL;
141 f32 rfreq,fval,fdivid;
143 if(freq==32000) curr_tab = 0;
144 else curr_tab = 1;
146 if(inc_tabs[curr_tab]) return inc_tabs[curr_tab];
148 tv = VIDEO_GetCurrentTvMode();
149 if(tv==VI_PAL) fdivid = 7093789.2/2.0F;
150 else fdivid = 7159090.5/2.0F;
152 inc_tab = (u32*)malloc(sizeof(u32)*4096);
153 if(inc_tab) {
154 inc_tabs[curr_tab] = inc_tab;
155 for(i=0;i<4096;i++) {
156 rfreq = (fdivid/(f32)i);
157 fval = (rfreq/(f32)freq)*262144.0F;
158 inc_tab[i] = (u32)fval;
163 return inc_tab;
166 static u32* modplay_getbpmtab(s32 freq)
168 u32 i,curr_tab,*bpm_tab = NULL;
169 f32 fval;
171 if(freq==32000) curr_tab = 0;
172 else curr_tab = 1;
174 if(bpm_tabs[curr_tab]) return bpm_tabs[curr_tab];
176 bpm_tab = (u32*)malloc(sizeof(u32)*224);
177 if(bpm_tab) {
178 bpm_tabs[curr_tab] = bpm_tab;
179 for(i=0;i<224;i++) {
180 fval = ((f32)freq/((f32)(i+32)*0.4F));
181 bpm_tab[i] = (u32)fval;
186 return bpm_tab;
188 #endif
190 #if defined(GP32)
191 static s32 fsize ( s8 * fname )
193 u32 s;
195 if (GpFileGetSize(fname,&s)!=SM_OK)
196 return -1;
197 else
198 return (s32)s;
200 #elif defined(DREAMCAST)
201 static s32 fsize ( s8 * fname )
203 file_t f;
204 s32 s;
206 if ((f=fs_open(fname, O_RDONLY))==0)
207 return -1;
209 fs_seek ( f, 0, SEEK_END );
210 s = fs_tell ( f );
211 fs_close ( f );
213 return s;
215 #elif defined(GAMECUBE)
216 static s32 fsize(s8 *fname)
218 return 0;
220 #else
221 static s32 fsize ( const char * fname )
223 FILE * f;
224 s32 s;
226 f = fopen (fname,"rb");
227 if (f==NULL)
228 return -1;
230 fseek(f, 0, SEEK_END);
231 s=ftell(f);
232 fclose(f);
234 return s;
236 #endif
238 s32 MOD_AllocSFXChannels ( MOD * mod, s32 sfxchans )
240 if (mod->modraw==NULL)
241 return -1;
243 if (mod->num_voices+sfxchans>32)
244 mod->num_channels = mod->num_voices;
245 else
246 mod->num_channels = mod->num_voices+sfxchans;
247 mod->shiftval = shiftvals[mod->num_channels];
249 return (mod->num_voices+sfxchans>32)?-1:0;
252 #ifdef GP32
253 void MOD_Free ( MOD * mod )
255 if (!mod->loaded)
256 return;
258 if (mod->modraw!=NULL)
259 gm_free ( mod->modraw );
261 MEM_SET ( mod, 0, sizeof(MOD) );
263 mod->loaded = FALSE;
265 #else
266 void MOD_Free ( MOD * mod )
268 mod->set = FALSE;
270 if (!mod->loaded)
271 return;
273 if (mod->modraw!=NULL)
274 free ( mod->modraw );
276 MEM_SET ( mod, 0, sizeof(MOD) );
278 mod->loaded = FALSE;
280 #endif
282 s32 MOD_SetMOD ( MOD * mod, u8 * mem )
284 s32 i;
285 s32 ofs = 0;
287 MEM_SET ( mod, 0, sizeof(MOD) );
288 mod->modraw = mem;
289 mod->musicvolume = mod->sfxvolume = 0x40;
291 /* ID */
292 mod->num_instr = 31;
293 MEM_CPY ( mod->id, &mem[1080], 4 );
294 mod->num_instr = 31;
295 if ( (MEM_CMP(mod->id, "M.K.", 4)==0) ||
296 (MEM_CMP(mod->id, "FLT4", 4)==0) )
297 mod->num_voices = 4;
298 else
299 if ( MEM_CMP(mod->id, "2CHN", 4)==0 )
300 mod->num_voices = 2;
301 else
302 if ( MEM_CMP(mod->id, "6CHN", 4)==0 )
303 mod->num_voices = 6;
304 else
305 if ( MEM_CMP(mod->id, "8CHN", 4)==0 )
306 mod->num_voices = 8;
307 else
308 if ( MEM_CMP(mod->id, "10CH", 4)==0 )
309 mod->num_voices = 10;
310 else
311 if ( MEM_CMP(mod->id, "12CH", 4)==0 )
312 mod->num_voices = 12;
313 else
314 if ( MEM_CMP(mod->id, "14CH", 4)==0 )
315 mod->num_voices = 14;
316 else
317 if ( MEM_CMP(mod->id, "16CH", 4)==0 )
318 mod->num_voices = 16;
319 else
320 if ( MEM_CMP(mod->id, "18CH", 4)==0 )
321 mod->num_voices = 18;
322 else
323 if ( MEM_CMP(mod->id, "20CH", 4)==0 )
324 mod->num_voices = 20;
325 else
326 if ( MEM_CMP(mod->id, "22CH", 4)==0 )
327 mod->num_voices = 22;
328 else
329 if ( MEM_CMP(mod->id, "24CH", 4)==0 )
330 mod->num_voices = 24;
331 else
332 if ( MEM_CMP(mod->id, "26CH", 4)==0 )
333 mod->num_voices = 26;
334 else
335 if ( MEM_CMP(mod->id, "28CH", 4)==0 )
336 mod->num_voices = 28;
337 else
338 if ( MEM_CMP(mod->id, "30CH", 4)==0 )
339 mod->num_voices = 30;
340 else
341 if ( MEM_CMP(mod->id, "32CH", 4)==0 )
342 mod->num_voices = 32;
343 else
345 mod->num_instr = 15;
346 mod->num_voices = 4;
349 /* Read song name */
350 MEM_CPY ( mod->name, &mem[ofs], 20 ); ofs+=20;
351 mod->name[20] = '\0';
352 /* Read instruments */
353 for (i=0;i<mod->num_instr;i++)
355 u32 tmp;
356 s32 j;
357 /* Name */
358 MEM_CPY ( &mod->instrument[i].name, &mem[ofs], 22 ); ofs+=22;
359 mod->instrument[i].name[22] = '\0';
360 j=21;
361 while ( mod->instrument[i].name[j]==' ' && j>=0 )
363 mod->instrument[i].name[j] = '\0';
364 --j;
366 /* Length */
367 mod->instrument[i].length = (mem[ofs+1] | (mem[ofs]<<8))<<1; ofs+=2;
368 /* Fine tune */
369 mod->instrument[i].finetune = mem[ofs++];
370 mod->instrument[i].finetune += 8;
371 mod->instrument[i].finetune &= 15;
372 /* Volume */
373 mod->instrument[i].volume = mem[ofs++];
374 if (mod->instrument[i].volume > 0x40)
375 mod->instrument[i].volume = 0x40;
376 /* Loop start */
377 mod->instrument[i].loop_start = (mem[ofs+1] | (mem[ofs]<<8))<<1; ofs+=2;
378 /* Loop end */
379 tmp = (mem[ofs+1] | (mem[ofs]<<8))<<1; ofs+=2;
380 mod->instrument[i].loop_end = tmp + mod->instrument[i].loop_start;
382 /* Is the sample looped ? */
383 mod->instrument[i].looped = TRUE;
384 if (tmp<=2)
385 { /* No ! */
386 mod->instrument[i].looped = FALSE;
387 mod->instrument[i].loop_start = mod->instrument[i].loop_end =
388 mod->instrument[i].length;
390 mod->instrument[i].loop_length = mod->instrument[i].loop_end - mod->instrument[i].loop_start;
392 /* Song length */
393 mod->song_length = mem[ofs++];
394 /* CIAA */
395 mod->ciaa = mem[ofs++];
396 /* Arrangement */
397 MEM_CPY ( mod->song, &mem[ofs], 128 ); ofs+=128;
398 mod->num_patterns = 0;
399 for (i=0;i<128;i++)
401 if ( (mod->song[i] &= 63) > mod->num_patterns )
402 mod->num_patterns = mod->song[i];
404 mod->num_patterns++;
406 if (mod->num_instr!=15)
407 ofs+=4;
409 MOD_AllocSFXChannels ( mod, 0 );
411 /* Patterns */
412 mod->patterndata = &mem[ofs];
413 ofs += 4*64*mod->num_voices*mod->num_patterns;
414 /* Sample data */
415 for (i=0;i<mod->num_instr;i++)
417 mod->instrument[i].data = NULL;
418 if (mod->instrument[i].length!=0)
420 mod->instrument[i].data = (s8*)&mem[ofs];
421 ofs += mod->instrument[i].length;
425 mod->set = TRUE;
427 return 0;
430 s32 MOD_Load ( MOD * mod, const char * fname )
432 #if defined(GP32)
433 F_HANDLE fh;
434 u32 tmp=0;
435 #elif defined(DREAMCAST)
436 file_t fh;
437 #elif defined(GAMECUBE)
438 void *fh;
439 #else
440 FILE *fh;
441 #endif
442 s32 fs;
443 u8 * mem = NULL;
445 fs = fsize(fname);
446 if (fs<1080+1024)
447 return -1;
449 #if defined(GP32)
450 if (GpFileOpen(fname, OPEN_R, &fh)!=SM_OK)
451 return -1;
453 if ((mem=gm_calloc(1,fs))==NULL)
455 GpFileClose(fh);
456 return -1;
459 GpFileRead ( fh, mem, fs, &tmp );
460 GpFileClose(fh);
461 #elif defined(DREAMCAST)
462 if ((fh=fs_open(fname, O_RDONLY))==0)
463 return -1;
465 if ((mem=calloc(1,fs))==NULL)
467 fs_close ( fh );
468 return -1;
471 fs_read ( fh, mem, fs );
472 fs_close ( fh );
473 #elif defined(GAMECUBE)
474 fh = NULL;
475 #else
476 if ((fh=fopen(fname,"rb"))==NULL)
477 return -1;
479 if ((mem=calloc(1,fs))==NULL)
481 fclose ( fh );
482 return -1;
484 fread ( mem, fs, 1, fh );
485 fclose ( fh );
486 #endif
488 if ( MOD_SetMOD ( mod, mem ) < 0 )
490 MOD_Free ( mod );
491 return -1;
493 mod->loaded = TRUE;
495 return 0;
498 u8 * getCurPatternData ( MOD * mod, s32 patternline, s32 channel )
500 return (&mod->patterndata[(((s32)mod->song[mod->songpos])*mod->num_voices*4*64) + ((patternline&63)*4*mod->num_voices) + (channel*4)]);
503 u16 getNote ( MOD * mod, s32 patternline, s32 channel )
505 u8 * data = getCurPatternData(mod, patternline, channel);
506 return (((data[0]&0x0f)<<8) | data[1]);
509 u8 getInstr ( MOD * mod, s32 patternline, s32 channel )
511 u8 * data = getCurPatternData(mod, patternline, channel);
512 return ((data[0]&0xf0) | ((data[2]>>4)&0x0f));
515 u8 getEffect ( MOD * mod, s32 patternline, s32 channel )
517 u8 * data = getCurPatternData(mod, patternline, channel);
518 return (data[2]&0x0f);
521 u8 getEffectOp ( MOD * mod, s32 patternline, s32 channel )
523 u8 * data = getCurPatternData(mod, patternline, channel);
524 return (data[3]);
527 BOOL triggerNote ( MOD * mod, s32 i, u8 instrument, u16 note, u8 effect )
529 BOOL ret = FALSE;
530 if ((instrument!=0) && (note!=0) && (effect!=3) && (effect!=5))
532 mod->playpos[i] = 0;
533 mod->instnum[i] = instrument-1;
534 mod->sintabpos[i] = 0;
535 ret = TRUE;
537 if (note!=0)
539 ret = TRUE;
540 mod->channote[i] = note;
541 if ((effect==3) || (effect==5))
542 mod->portamento_to[i] = note;
543 else
545 if ((effect==4) || (effect==6))
546 mod->vib_basefreq[i] = note;
547 mod->playpos[i] = 0;
548 mod->chanfreq[i] = note;
551 if (instrument != 0)
553 ret = TRUE;
554 mod->volume[i] = mod->instrument[mod->instnum[i]].volume;
556 return ret;
559 /* Handle effect which must be on handled every tick */
560 u32 effect_handler ( MOD * mod )
562 s32 i;
563 u32 retval = 0;
565 if (mod->speedcounter==0)
567 mod->arp_counter = 0;
568 } else
570 mod->arp_counter++;
571 if (mod->arp_counter>3)
572 mod->arp_counter = 1;
575 for (i=0;i<mod->num_voices;i++)
577 if ( mod->effect[i] < 0x10 ) /* Any effect ? */
579 switch ( mod->effect[i] )
581 case 0x00: /* Arpeggio */
582 if (mod->speedcounter!=0)
584 if (mod->effectop[i] != 0)
586 if (mod->arp_counter==1)
588 mod->chanfreq[i] = freqtab[mod->channote[i]]+((mod->effectop[i]>>4)&0x0f);
589 } else
590 if (mod->arp_counter==2)
592 mod->chanfreq[i] = freqtab[mod->channote[i]]+(mod->effectop[i]&0x0f);
593 } else
594 if (mod->arp_counter==3)
596 mod->chanfreq[i] = freqtab[mod->channote[i]];
600 break;
601 case 0x01: /* Slide up */
602 if (mod->speedcounter!=0)
604 mod->chanfreq[i] -= mod->effectop[i];
605 if (mod->chanfreq[i] & 0x8000)
606 mod->chanfreq[i] = 0;
608 break;
609 case 0x02: /* Slide down */
610 if (mod->speedcounter!=0)
612 mod->chanfreq[i] += mod->effectop[i];
613 if (mod->chanfreq[i] > 4095)
614 mod->chanfreq[i] = 4095;
616 break;
617 case 0x03: /* Slide to */
618 if (mod->speedcounter!=0)
620 if ( mod->chanfreq[i] < mod->portamento_to[i] )
622 if ( (mod->portamento_to[i] - mod->chanfreq[i]) > mod->porta_speed[i] )
623 mod->chanfreq[i] += mod->porta_speed[i];
624 else
625 mod->chanfreq[i] = mod->portamento_to[i];
626 } else
627 if ( mod->chanfreq[i] > mod->portamento_to[i] )
629 if ( (mod->chanfreq[i] - mod->portamento_to[i]) > mod->porta_speed[i] )
630 mod->chanfreq[i] -= mod->porta_speed[i];
631 else
632 mod->chanfreq[i] = mod->portamento_to[i];
633 } else
635 mod->channote[i] = mod->chanfreq[i];
638 break;
639 case 0x04: /* Vibrato */
640 if (mod->speedcounter!=0)
642 mod->chanfreq[i] = (((s32)((s32)wavetab[mod->vib_wave[i]&3][mod->sintabpos[i]]*(u32)mod->vib_depth[i]))>>7) + mod->vib_basefreq[i];
643 mod->sintabpos[i] += mod->vib_freq[i];
644 mod->sintabpos[i] &= 63;
646 break;
647 case 0x05: /* Slide to & Volume siding */
648 if (mod->speedcounter!=0)
650 /* Do portamento */
651 if ( mod->chanfreq[i] < mod->portamento_to[i] )
653 if ( (mod->portamento_to[i] - mod->chanfreq[i]) > mod->porta_speed[i] )
654 mod->chanfreq[i] += mod->porta_speed[i];
655 else
656 mod->chanfreq[i] = mod->portamento_to[i];
657 } else
658 if ( mod->chanfreq[i] > mod->portamento_to[i] )
660 if ( (mod->chanfreq[i] - mod->portamento_to[i]) > mod->porta_speed[i] )
661 mod->chanfreq[i] -= mod->porta_speed[i];
662 else
663 mod->chanfreq[i] = mod->portamento_to[i];
664 } else
666 mod->channote[i] = mod->chanfreq[i];
669 /* Do volume sliding */
670 if (mod->effectop[i]&0xf0) /* Increase volume */
672 mod->volume[i] += (mod->effectop[i]>>4)&0x0f;
673 if (mod->volume[i]>64)
674 mod->volume[i] = 64;
675 } else
676 if (mod->effectop[i]&0x0f) /* Decrease volume */
678 mod->volume[i] -= mod->effectop[i]&0x0f;
679 if (mod->volume[i]&0x80) /* <0 ? */
680 mod->volume[i] = 0;
683 break;
684 case 0x06: /* Vibrato & Volume slide */
685 if (mod->speedcounter!=0)
687 mod->chanfreq[i] = (((s32)((s32)wavetab[mod->vib_wave[i]&3][mod->sintabpos[i]]*(u32)mod->vib_depth[i]))>>7) + mod->vib_basefreq[i];
688 mod->sintabpos[i] += mod->vib_freq[i];
689 mod->sintabpos[i] &= 63;
691 if (mod->effectop[i]&0xf0) /* Increase volume */
693 mod->volume[i] += (mod->effectop[i]>>4)&0x0f;
694 if (mod->volume[i]>64)
695 mod->volume[i] = 64;
696 } else
697 if (mod->effectop[i]&0x0f) /* Decrease volume */
699 mod->volume[i] -= mod->effectop[i]&0x0f;
700 if (mod->volume[i]&0x80) /* <0 ? */
701 mod->volume[i] = 0;
704 break;
705 case 0x07: /* Tremolo */
706 if (mod->speedcounter!=0)
708 s16 v = mod->trem_basevol[i];
709 v += ((s32)((s32)wavetab[mod->trem_wave[i]&3][mod->sintabpos[i]]*(s32)mod->trem_depth[i]))>>6;
710 if (v>64)
711 v=64;
712 if (v<0)
713 v=0;
715 mod->sintabpos[i] += mod->trem_freq[i];
716 mod->sintabpos[i] &= 63;
718 mod->volume[i] = v;
720 break;
721 case 0x0a: /* Volume slide */
722 if (mod->speedcounter!=0)
724 if (mod->effectop[i]&0xf0) /* Increase volume */
726 mod->volume[i] += (mod->effectop[i]>>4)&0x0f;
727 if (mod->volume[i]>64)
728 mod->volume[i] = 64;
729 } else
730 if (mod->effectop[i]&0x0f) /* Decrease volume */
732 mod->volume[i] -= mod->effectop[i]&0x0f;
733 if (mod->volume[i]&0x80) /* <0 ? */
734 mod->volume[i] = 0;
737 break;
738 case 0x0e: /* Sub commands */
739 switch ( (mod->effectop[i]>>4)&0x0f )
741 case 0x09: /* Retrigger sample */
742 if (mod->speedcounter!=0)
744 if (++mod->retrigger_counter[i] >= (mod->effectop[i]&0x0f))
746 mod->retrigger_counter[i] = 0;
747 mod->playpos[i] = 0;
748 mod->channel_active[i] = TRUE;
749 retval |= 1<<i;
752 break;
753 case 0x0c: /* Cut note */
754 if (mod->speedcounter!=0)
756 if ( (mod->effectop[i]&0x0f) == mod->speedcounter )
757 mod->volume[i] = 0;
759 break;
760 case 0x0d: /* Delay note */
761 if (mod->speedcounter!=0)
763 if (mod->speedcounter == (mod->effectop[i]&0x0f))
765 triggerNote ( mod, i, mod->nextinstr[i], mod->nextnote[i], mod->effect[i] );
766 mod->channel_active[i] = TRUE;
767 retval |= 1<<i;
771 break;
775 return retval;
778 u32 process ( MOD * mod )
780 s32 i;
781 u32 retval = 0;
782 BOOL doPatternBreak=FALSE;
783 BOOL doPatternLoop=FALSE;
784 u8 * patternData = getCurPatternData ( mod, mod->patternline, 0 );
786 for (i=0;i<mod->num_voices;++i)
788 u16 note = ((patternData[0]<<8)&0x0f00) | patternData[1];
789 u8 instrument = (patternData[0]&0xf0) | ((patternData[2]>>4)&0x0f);
790 u8 effect = patternData[2]&0x0f;
791 u8 effect_operand = patternData[3];
793 patternData+=4;
795 if ( ((mod->last_effect[i]==0x04)||(mod->last_effect[i]==0x06)) &&
796 ((effect!=0x04) && (effect!=0x06)) )
798 mod->chanfreq[i] = mod->vib_basefreq[i];
800 if ( (mod->last_effect[i]==0x07) && (effect!=0x07) )
802 mod->volume[i] = mod->trem_basevol[i];
805 if ( mod->effect[i]==0x00 && mod->effectop[i]!=0)
807 if (effect!=0 || effect_operand==0)
808 mod->chanfreq[i] = mod->channote[i];
811 mod->nextinstr[i] = instrument;
812 mod->nextnote[i] = note;
814 if ( !( (effect==0x0e) && ((effect_operand&0xf0)==0xd0)) )
816 if (triggerNote ( mod, i, mod->nextinstr[i], mod->nextnote[i], effect ))
818 retval |= 1<<i;
819 mod->channel_active[i] = TRUE;
823 mod->effect[i] = 0xff;
825 switch (effect)
827 case 0x03:
828 mod->effect[i] = effect;
829 mod->effectop[i] = effect_operand;
830 if ( mod->effectop[i] != 0 )
831 mod->porta_speed[i] = mod->effectop[i];
832 break;
833 case 0x04:
834 if (!((mod->last_effect[i]==0x04)||(mod->last_effect[i]==0x06)))
835 mod->vib_basefreq[i] = mod->chanfreq[i];
837 if (effect_operand&0xf0)
838 mod->vib_freq[i] = (effect_operand>>4)&0x0f;
839 if (effect_operand&0x0f)
840 mod->vib_depth[i] = effect_operand&0x0f;
841 mod->effect[i] = effect;
842 mod->effectop[i] = effect_operand;
843 break;
844 case 0x05:
845 mod->effect[i] = effect;
846 mod->effectop[i] = effect_operand;
847 if ( mod->effectop[i] != 0 )
848 mod->porta_speed[i] = mod->effectop[i];
849 break;
850 case 0x06:
851 if (!((mod->last_effect[i]==0x04)||(mod->last_effect[i]==0x06)))
852 mod->vib_basefreq[i] = mod->chanfreq[i];
854 mod->effect[i] = effect;
855 mod->effectop[i] = effect_operand;
856 break;
857 case 0x07:
858 if ( mod->last_effect[i]!=0x07 )
859 mod->trem_basevol[i] = mod->volume[i];
861 if (effect_operand&0xf0)
862 mod->trem_freq[i] = (effect_operand>>4)&0x0f;
863 if (effect_operand&0x0f)
864 mod->trem_depth[i] = effect_operand&0x0f;
865 mod->effect[i] = effect;
866 mod->effectop[i] = effect_operand;
867 break;
868 case 0x09:
870 u32 ofs = effect_operand<<8;
871 if (ofs>mod->instrument[mod->instnum[i]].length)
872 mod->playpos[i] = mod->instrument[mod->instnum[i]].length << 16;
873 else
874 mod->playpos[i] = ofs << 16;
876 break;
877 case 0x0b:
878 if (effect_operand<128)
880 if(mod->notify) *mod->notify = TRUE;
881 mod->songpos = effect_operand;
882 mod->patternline = 0;
883 return retval;
885 break;
886 case 0x0c:
887 if (effect_operand>64)
888 effect_operand = 64;
889 mod->volume[i] = effect_operand;
890 break;
891 case 0x0d:
892 doPatternBreak=TRUE;
893 break;
894 case 0x0e:
895 switch ( (effect_operand>>4)&0x0f )
897 case 0x01:
898 mod->chanfreq[i] -= effect_operand&0x0f;
899 if (mod->chanfreq[i]&0x8000)
900 mod->chanfreq[i] = 0;
901 break;
902 case 0x02:
903 mod->chanfreq[i] += effect_operand&0x0f;
904 if (mod->chanfreq[i]>4095)
905 mod->chanfreq[i] = 4095;
906 break;
907 case 0x03:
908 if ( (effect_operand&0x0f) == 0x00 )
909 mod->glissando[i] = FALSE;
910 else
911 if ( (effect_operand&0x0f) == 0x01 )
912 mod->glissando[i] = TRUE;
913 break;
914 case 0x04:
915 if ( (effect_operand&0x0f) < 8 )
916 mod->vib_wave[i] = effect_operand & 0x07;
917 break;
918 case 0x05:
919 mod->instrument[mod->instnum[i]].finetune = (effect_operand+8)&15;
920 break;
921 case 0x06:
922 if ((effect_operand&0x0f)==0)
923 mod->patternline_jumpto = mod->patternline;
924 else
926 doPatternLoop = TRUE;
927 if (mod->patternline_jumpcount==0)
929 mod->patternline_jumpcount = effect_operand&0x0f;
930 } else
932 if (--mod->patternline_jumpcount==0)
933 doPatternLoop = FALSE;
936 break;
937 case 0x07:
938 if ( (effect_operand&0x0f) < 8 )
939 mod->trem_wave[i] = effect_operand & 0x07;
940 break;
941 case 0x09:
942 mod->retrigger_counter[i] = 0;
943 mod->effect[i] = effect;
944 mod->effectop[i] = effect_operand;
945 break;
946 case 0x0a:
947 mod->volume[i] += effect_operand&0x0f;
948 if (mod->volume[i]>64)
949 mod->volume[i] = 64;
950 break;
951 case 0x0b:
952 mod->volume[i] -= effect_operand&0x0f;
953 if (mod->volume[i]&0x80)
954 mod->volume[i] = 0;
955 case 0x0c:
956 case 0x0d:
957 mod->effect[i] = effect;
958 mod->effectop[i] = effect_operand;
959 break;
960 case 0x0e:
961 mod->patterndelay = mod->speed*(effect_operand&0x0f);
962 break;
964 break;
965 case 0x0f:
966 if ( effect_operand<32 )
967 mod->speed = effect_operand;
968 else
970 mod->bpm=effect_operand;
971 mod->samplespertick = mod->bpmtab[effect_operand-32];
974 break;
975 default:
976 mod->effect[i] = effect;
977 mod->effectop[i] = effect_operand;
978 break;
980 mod->last_effect[i] = effect;
983 if (doPatternBreak)
985 mod->songpos++;
986 mod->patternline = 0;
987 if (mod->songpos>=mod->song_length)
989 if(mod->notify) *mod->notify = TRUE;
990 mod->songpos = 0;
991 mod->patternline = 0;
993 mod->patternline_jumpto = 0;
994 mod->patternline_jumpcount = 0;
995 } else
996 if (doPatternLoop)
998 mod->patternline = mod->patternline_jumpto;
999 } else
1001 mod->patternline++;
1002 if (mod->patternline>63)
1004 mod->patternline=0;
1005 mod->songpos++;
1006 mod->patternline_jumpto = 0;
1007 mod->patternline_jumpcount = 0;
1009 if (mod->songpos>=mod->song_length)
1011 if(mod->notify) *mod->notify = TRUE;
1012 mod->songpos = 0;
1013 mod->patternline = 0;
1017 return retval;
1020 void MOD_Start ( MOD * mod )
1022 s32 i;
1024 for (i=MAX_VOICES-1;i>=0;--i)
1026 mod->volume[i] = 0;
1027 mod->playpos[i] = 0;
1028 mod->chanfreq[i] = 0;
1029 mod->instnum[i] = 0;
1030 mod->channote[i] = 0;
1031 mod->sintabpos[i] = 0;
1032 mod->vib_freq[i] = 0;
1033 mod->vib_depth[i] = 0;
1034 mod->last_effect[i] = 0;
1035 mod->glissando[i] = FALSE;
1036 mod->trem_wave[i] = 0;
1037 mod->vib_wave[i] = 0;
1038 mod->channel_active[i] = FALSE;
1041 mod->songpos = 0;
1042 mod->patternline = 0;
1043 mod->speed = 6;
1044 mod->bpm = 125;
1045 mod->speedcounter = 0;
1047 mod->patterndelay = 0;
1048 mod->patternline_jumpto = 0;
1049 mod->patternline_jumpcount = 0;
1050 #ifndef GEKKO
1051 switch(mod->freq) {
1052 case 32000:
1053 mod->bpmtab = bpmtab32KHz;
1054 mod->inctab = inctab32KHz;
1055 break;
1056 case 48000:
1057 mod->bpmtab = bpmtab48KHz;
1058 mod->inctab = inctab48KHz;
1059 break;
1060 default:
1061 mod->bpmtab = bpmtab48KHz;
1062 mod->inctab = inctab48KHz;
1063 break;
1065 #else
1066 if(mod->freq==32000 || mod->freq==48000) {
1067 mod->inctab = modplay_getinctab(mod->freq);
1068 mod->bpmtab = modplay_getbpmtab(mod->freq);
1070 #endif
1072 mod->samplescounter = 0;
1073 mod->samplespertick = mod->bpmtab[125-32];
1076 u32 MOD_Player ( MOD * mod )
1078 s16 * buf = (s16*)mod->mixingbuf;
1079 s32 len = mod->mixingbuflen;
1080 u32 retval = 0;
1082 if (mod->musicvolume>0x40)
1083 mod->musicvolume = 0x40;
1084 if (mod->sfxvolume>0x40)
1085 mod->sfxvolume = 0x40;
1087 if (mod->bits == 16)
1089 len >>= 1;
1090 if (mod->channels==1)
1092 s32 l = 0;
1093 s32 remain = len;
1096 s32 tick_remain = mod->samplespertick - mod->samplescounter;
1097 s32 res;
1099 res = mix_mono_16bit ( mod, &buf[l], tick_remain<=remain ? tick_remain : remain );
1100 l += res;
1101 remain -= res;
1103 mod->samplescounter += res;
1104 if ( mod->samplescounter >= mod->samplespertick )
1106 mod->samplescounter -= mod->samplespertick;
1107 mod->speedcounter++;
1108 if (mod->speedcounter>=(mod->speed+mod->patterndelay))
1110 mod->patterndelay=0;
1111 retval |= process(mod);
1112 mod->speedcounter = 0;
1114 retval |= effect_handler(mod);
1116 } while ( remain>0 );
1117 } else
1118 if (mod->channels==2)
1120 s32 l = 0;
1121 s32 remain;
1122 len >>= 1;
1123 remain = len;
1126 s32 tick_remain = mod->samplespertick - mod->samplescounter;
1127 s32 res;
1129 res = mix_stereo_16bit ( mod, &buf[l<<1], tick_remain<=remain ? tick_remain : remain );
1130 l += res;
1131 remain -= res;
1133 mod->samplescounter += res;
1134 if ( mod->samplescounter >= mod->samplespertick )
1136 mod->samplescounter -= mod->samplespertick;
1137 mod->speedcounter++;
1138 if (mod->speedcounter>=(mod->speed+mod->patterndelay))
1140 mod->patterndelay=0;
1141 retval |= process(mod);
1142 mod->speedcounter = 0;
1144 retval |= effect_handler(mod);
1146 } while ( remain>0 );
1150 mod->notebeats = retval;
1151 if (mod->callback!=NULL)
1152 mod->callback ( mod );
1154 return retval;
1157 s32 MOD_TriggerNote ( MOD * mod, s32 channel, u8 instnum, u16 freq, u8 vol )
1159 if (mod==NULL)
1160 return -1;
1162 channel += mod->num_voices;
1163 if (channel>=mod->num_channels)
1164 return -1;
1165 if (mod->instrument[instnum].data==NULL && instnum!=0xff)
1166 return -1;
1168 if (instnum!=0xff)
1170 mod->channel_active[channel] = TRUE;
1171 mod->playpos[channel] = 0;
1172 mod->instnum[channel] = instnum;
1174 if (freq!=0xffff)
1175 mod->chanfreq[channel] = freq;
1176 if (vol<=0x40)
1177 mod->volume[channel] = vol;
1179 return 0;