1a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 2a4cd9b30SMilanka Ringwald //-------------------------------------------------------------------------------// 3a4cd9b30SMilanka Ringwald //-------------------------------------------------------------------------------// 4a4cd9b30SMilanka Ringwald //-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------// 5a4cd9b30SMilanka Ringwald //----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------// 6a4cd9b30SMilanka Ringwald //---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------// 7a4cd9b30SMilanka Ringwald //--------H----H----X--X----C----------2-------0----0---0----0-----1-------------// 8a4cd9b30SMilanka Ringwald //-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------// 9a4cd9b30SMilanka Ringwald //-------------------------------------------------------------------------------// 10a4cd9b30SMilanka Ringwald //----------------------------------------------------- http://hxc2001.free.fr --// 11a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 12a4cd9b30SMilanka Ringwald // File : hxcmod.c 13a4cd9b30SMilanka Ringwald // Contains: a tiny mod player 14a4cd9b30SMilanka Ringwald // 15a4cd9b30SMilanka Ringwald // Written by: Jean Fran�ois DEL NERO 16a4cd9b30SMilanka Ringwald // 17a4cd9b30SMilanka Ringwald // You are free to do what you want with this code. 18a4cd9b30SMilanka Ringwald // A credit is always appreciated if you include it into your prod :) 19a4cd9b30SMilanka Ringwald // 20a4cd9b30SMilanka Ringwald // This file include some parts of the Noisetracker/Soundtracker/Protracker 21a4cd9b30SMilanka Ringwald // Module Format documentation written by Andrew Scott (Adrenalin Software) 22a4cd9b30SMilanka Ringwald // (modformat.txt) 23a4cd9b30SMilanka Ringwald // 24a4cd9b30SMilanka Ringwald // The core (hxcmod.c/hxcmod.h) is designed to have the least external dependency. 25a4cd9b30SMilanka Ringwald // So it should be usable on almost all OS and systems. 26a4cd9b30SMilanka Ringwald // Please also note that no dynamic allocation is done into the HxCMOD core. 27a4cd9b30SMilanka Ringwald // 28a4cd9b30SMilanka Ringwald // Change History (most recent first): 29a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 30a4cd9b30SMilanka Ringwald // HxCMOD Core API: 31a4cd9b30SMilanka Ringwald // ------------------------------------------- 32a4cd9b30SMilanka Ringwald // int hxcmod_init(modcontext * modctx) 33a4cd9b30SMilanka Ringwald // 34a4cd9b30SMilanka Ringwald // - Initialize the modcontext buffer. Must be called before doing anything else. 35a4cd9b30SMilanka Ringwald // Return 1 if success. 0 in case of error. 36a4cd9b30SMilanka Ringwald // ------------------------------------------- 37a4cd9b30SMilanka Ringwald // int hxcmod_load( modcontext * modctx, void * mod_data, int mod_data_size ) 38a4cd9b30SMilanka Ringwald // 39a4cd9b30SMilanka Ringwald // - "Load" a MOD from memory (from "mod_data" with size "mod_data_size"). 40a4cd9b30SMilanka Ringwald // Return 1 if success. 0 in case of error. 41a4cd9b30SMilanka Ringwald // ------------------------------------------- 42a4cd9b30SMilanka Ringwald // void hxcmod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, tracker_buffer_state * trkbuf ) 43a4cd9b30SMilanka Ringwald // 44a4cd9b30SMilanka Ringwald // - Generate and return the next samples chunk to outbuffer. 45a4cd9b30SMilanka Ringwald // nbsample specify the number of stereo 16bits samples you want. 46a4cd9b30SMilanka Ringwald // The output format is signed 44100Hz 16-bit Stereo PCM samples. 47a4cd9b30SMilanka Ringwald // The output buffer size in byte must be equal to ( nbsample * 2 * 2 ). 48a4cd9b30SMilanka Ringwald // The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 is unused. 49a4cd9b30SMilanka Ringwald // ------------------------------------------- 50a4cd9b30SMilanka Ringwald // void hxcmod_unload( modcontext * modctx ) 51a4cd9b30SMilanka Ringwald // - "Unload" / clear the player status. 52a4cd9b30SMilanka Ringwald // ------------------------------------------- 53a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 54a4cd9b30SMilanka Ringwald 55a4cd9b30SMilanka Ringwald #include "hxcmod.h" 56a4cd9b30SMilanka Ringwald 57a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 58a4cd9b30SMilanka Ringwald 59a4cd9b30SMilanka Ringwald // Effects list 60a4cd9b30SMilanka Ringwald #define EFFECT_ARPEGGIO 0x0 // Supported 61a4cd9b30SMilanka Ringwald #define EFFECT_PORTAMENTO_UP 0x1 // Supported 62a4cd9b30SMilanka Ringwald #define EFFECT_PORTAMENTO_DOWN 0x2 // Supported 63a4cd9b30SMilanka Ringwald #define EFFECT_TONE_PORTAMENTO 0x3 // Supported 64a4cd9b30SMilanka Ringwald #define EFFECT_VIBRATO 0x4 // Supported 65a4cd9b30SMilanka Ringwald #define EFFECT_VOLSLIDE_TONEPORTA 0x5 // Supported 66a4cd9b30SMilanka Ringwald #define EFFECT_VOLSLIDE_VIBRATO 0x6 // Supported 67a4cd9b30SMilanka Ringwald #define EFFECT_VOLSLIDE_TREMOLO 0x7 // - TO BE DONE - 68a4cd9b30SMilanka Ringwald #define EFFECT_SET_PANNING 0x8 // - TO BE DONE - 69a4cd9b30SMilanka Ringwald #define EFFECT_SET_OFFSET 0x9 // Supported 70a4cd9b30SMilanka Ringwald #define EFFECT_VOLUME_SLIDE 0xA // Supported 71a4cd9b30SMilanka Ringwald #define EFFECT_JUMP_POSITION 0xB // Supported 72a4cd9b30SMilanka Ringwald #define EFFECT_SET_VOLUME 0xC // Supported 73a4cd9b30SMilanka Ringwald #define EFFECT_PATTERN_BREAK 0xD // Supported 74a4cd9b30SMilanka Ringwald 75a4cd9b30SMilanka Ringwald #define EFFECT_EXTENDED 0xE 76a4cd9b30SMilanka Ringwald #define EFFECT_E_FINE_PORTA_UP 0x1 // Supported 77a4cd9b30SMilanka Ringwald #define EFFECT_E_FINE_PORTA_DOWN 0x2 // Supported 78a4cd9b30SMilanka Ringwald #define EFFECT_E_GLISSANDO_CTRL 0x3 // - TO BE DONE - 79a4cd9b30SMilanka Ringwald #define EFFECT_E_VIBRATO_WAVEFORM 0x4 // - TO BE DONE - 80a4cd9b30SMilanka Ringwald #define EFFECT_E_SET_FINETUNE 0x5 // - TO BE DONE - 81a4cd9b30SMilanka Ringwald #define EFFECT_E_PATTERN_LOOP 0x6 // Supported 82a4cd9b30SMilanka Ringwald #define EFFECT_E_TREMOLO_WAVEFORM 0x7 // - TO BE DONE - 83a4cd9b30SMilanka Ringwald #define EFFECT_E_SET_PANNING_2 0x8 // - TO BE DONE - 84a4cd9b30SMilanka Ringwald #define EFFECT_E_RETRIGGER_NOTE 0x9 // - TO BE DONE - 85a4cd9b30SMilanka Ringwald #define EFFECT_E_FINE_VOLSLIDE_UP 0xA // Supported 86a4cd9b30SMilanka Ringwald #define EFFECT_E_FINE_VOLSLIDE_DOWN 0xB // Supported 87a4cd9b30SMilanka Ringwald #define EFFECT_E_NOTE_CUT 0xC // Supported 88a4cd9b30SMilanka Ringwald #define EFFECT_E_NOTE_DELAY 0xD // - TO BE DONE - 89a4cd9b30SMilanka Ringwald #define EFFECT_E_PATTERN_DELAY 0xE // Supported 90a4cd9b30SMilanka Ringwald #define EFFECT_E_INVERT_LOOP 0xF // - TO BE DONE - 91a4cd9b30SMilanka Ringwald #define EFFECT_SET_SPEED 0xF0 // Supported 92a4cd9b30SMilanka Ringwald #define EFFECT_SET_TEMPO 0xF2 // Supported 93a4cd9b30SMilanka Ringwald 94a4cd9b30SMilanka Ringwald #define PERIOD_TABLE_LENGTH MAXNOTES 95a4cd9b30SMilanka Ringwald #define FULL_PERIOD_TABLE_LENGTH ( PERIOD_TABLE_LENGTH * 8 ) 96a4cd9b30SMilanka Ringwald 97a4cd9b30SMilanka Ringwald static const short periodtable[]= 98a4cd9b30SMilanka Ringwald { 99a4cd9b30SMilanka Ringwald 27392, 25856, 24384, 23040, 21696, 20480, 19328, 18240, 17216, 16256, 15360, 14496, 100a4cd9b30SMilanka Ringwald 13696, 12928, 12192, 11520, 10848, 10240, 9664, 9120, 8606, 8128, 7680, 7248, 101a4cd9b30SMilanka Ringwald 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624, 102a4cd9b30SMilanka Ringwald 3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2032, 1920, 1812, 103a4cd9b30SMilanka Ringwald 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 906, 104a4cd9b30SMilanka Ringwald 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, 105a4cd9b30SMilanka Ringwald 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, 106a4cd9b30SMilanka Ringwald 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, 107a4cd9b30SMilanka Ringwald 107, 101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56, 108a4cd9b30SMilanka Ringwald 53, 50, 47, 45, 42, 40, 37, 35, 33, 31, 30, 28, 109a4cd9b30SMilanka Ringwald 27, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, 110a4cd9b30SMilanka Ringwald 13, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7 111a4cd9b30SMilanka Ringwald }; 112a4cd9b30SMilanka Ringwald 113a4cd9b30SMilanka Ringwald static const short sintable[]={ 114a4cd9b30SMilanka Ringwald 0, 24, 49, 74, 97, 120, 141,161, 115a4cd9b30SMilanka Ringwald 180, 197, 212, 224, 235, 244, 250,253, 116a4cd9b30SMilanka Ringwald 255, 253, 250, 244, 235, 224, 212,197, 117a4cd9b30SMilanka Ringwald 180, 161, 141, 120, 97, 74, 49, 24 118a4cd9b30SMilanka Ringwald }; 119a4cd9b30SMilanka Ringwald 120a4cd9b30SMilanka Ringwald typedef struct modtype_ 121a4cd9b30SMilanka Ringwald { 122a4cd9b30SMilanka Ringwald unsigned char signature[5]; 123a4cd9b30SMilanka Ringwald int numberofchannels; 124a4cd9b30SMilanka Ringwald }modtype; 125a4cd9b30SMilanka Ringwald 126a4cd9b30SMilanka Ringwald modtype modlist[]= 127a4cd9b30SMilanka Ringwald { 128a4cd9b30SMilanka Ringwald { "M!K!",4}, 129a4cd9b30SMilanka Ringwald { "M.K.",4}, 130a4cd9b30SMilanka Ringwald { "FLT4",4}, 131a4cd9b30SMilanka Ringwald { "FLT8",8}, 132a4cd9b30SMilanka Ringwald { "4CHN",4}, 133a4cd9b30SMilanka Ringwald { "6CHN",6}, 134a4cd9b30SMilanka Ringwald { "8CHN",8}, 135a4cd9b30SMilanka Ringwald { "10CH",10}, 136a4cd9b30SMilanka Ringwald { "12CH",12}, 137a4cd9b30SMilanka Ringwald { "14CH",14}, 138a4cd9b30SMilanka Ringwald { "16CH",16}, 139a4cd9b30SMilanka Ringwald { "18CH",18}, 140a4cd9b30SMilanka Ringwald { "20CH",20}, 141a4cd9b30SMilanka Ringwald { "22CH",22}, 142a4cd9b30SMilanka Ringwald { "24CH",24}, 143a4cd9b30SMilanka Ringwald { "26CH",26}, 144a4cd9b30SMilanka Ringwald { "28CH",28}, 145a4cd9b30SMilanka Ringwald { "30CH",30}, 146a4cd9b30SMilanka Ringwald { "32CH",32}, 147a4cd9b30SMilanka Ringwald { "",0} 148a4cd9b30SMilanka Ringwald }; 149a4cd9b30SMilanka Ringwald 150a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 151a4cd9b30SMilanka Ringwald 152a4cd9b30SMilanka Ringwald static void memcopy( void * dest, void *source, unsigned long size ) 153a4cd9b30SMilanka Ringwald { 154a4cd9b30SMilanka Ringwald unsigned long i; 155a4cd9b30SMilanka Ringwald unsigned char * d,*s; 156a4cd9b30SMilanka Ringwald 157a4cd9b30SMilanka Ringwald d=(unsigned char*)dest; 158a4cd9b30SMilanka Ringwald s=(unsigned char*)source; 159a4cd9b30SMilanka Ringwald for(i=0;i<size;i++) 160a4cd9b30SMilanka Ringwald { 161a4cd9b30SMilanka Ringwald d[i]=s[i]; 162a4cd9b30SMilanka Ringwald } 163a4cd9b30SMilanka Ringwald } 164a4cd9b30SMilanka Ringwald 165a4cd9b30SMilanka Ringwald static void memclear( void * dest, unsigned char value, unsigned long size ) 166a4cd9b30SMilanka Ringwald { 167a4cd9b30SMilanka Ringwald unsigned long i; 168a4cd9b30SMilanka Ringwald unsigned char * d; 169a4cd9b30SMilanka Ringwald 170a4cd9b30SMilanka Ringwald d=(unsigned char*)dest; 171a4cd9b30SMilanka Ringwald for(i=0;i<size;i++) 172a4cd9b30SMilanka Ringwald { 173a4cd9b30SMilanka Ringwald d[i]=value; 174a4cd9b30SMilanka Ringwald } 175a4cd9b30SMilanka Ringwald } 176a4cd9b30SMilanka Ringwald 177a4cd9b30SMilanka Ringwald static int memcompare( unsigned char * buf1, unsigned char * buf2, unsigned int size ) 178a4cd9b30SMilanka Ringwald { 179a4cd9b30SMilanka Ringwald unsigned int i; 180a4cd9b30SMilanka Ringwald 181a4cd9b30SMilanka Ringwald i = 0; 182a4cd9b30SMilanka Ringwald 183a4cd9b30SMilanka Ringwald while(i<size) 184a4cd9b30SMilanka Ringwald { 185a4cd9b30SMilanka Ringwald if(buf1[i] != buf2[i]) 186a4cd9b30SMilanka Ringwald { 187a4cd9b30SMilanka Ringwald return 0; 188a4cd9b30SMilanka Ringwald } 189a4cd9b30SMilanka Ringwald i++; 190a4cd9b30SMilanka Ringwald } 191a4cd9b30SMilanka Ringwald 192a4cd9b30SMilanka Ringwald return 1; 193a4cd9b30SMilanka Ringwald } 194a4cd9b30SMilanka Ringwald 195a4cd9b30SMilanka Ringwald static int getnote( modcontext * mod, unsigned short period, int finetune ) 196a4cd9b30SMilanka Ringwald { 197c5456c21SMilanka Ringwald (void) finetune; 198a4cd9b30SMilanka Ringwald int i; 199a4cd9b30SMilanka Ringwald 200a4cd9b30SMilanka Ringwald for(i = 0; i < FULL_PERIOD_TABLE_LENGTH; i++) 201a4cd9b30SMilanka Ringwald { 202a4cd9b30SMilanka Ringwald if(period >= mod->fullperiod[i]) 203a4cd9b30SMilanka Ringwald { 204a4cd9b30SMilanka Ringwald return i; 205a4cd9b30SMilanka Ringwald } 206a4cd9b30SMilanka Ringwald } 207a4cd9b30SMilanka Ringwald 208a4cd9b30SMilanka Ringwald return MAXNOTES; 209a4cd9b30SMilanka Ringwald } 210a4cd9b30SMilanka Ringwald 211a4cd9b30SMilanka Ringwald static void worknote( note * nptr, channel * cptr,char t,modcontext * mod ) 212a4cd9b30SMilanka Ringwald { 213c5456c21SMilanka Ringwald (void) t; 214*f3198545SMatthias Ringwald muint _sample, period, effect, operiod; 215a4cd9b30SMilanka Ringwald muint curnote, arpnote; 216a4cd9b30SMilanka Ringwald 217*f3198545SMatthias Ringwald _sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4); 218a4cd9b30SMilanka Ringwald period = ((nptr->sampperiod & 0xF) << 8) | nptr->period; 219a4cd9b30SMilanka Ringwald effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect; 220a4cd9b30SMilanka Ringwald 221a4cd9b30SMilanka Ringwald operiod = cptr->period; 222a4cd9b30SMilanka Ringwald 223*f3198545SMatthias Ringwald if ( period || _sample ) 224a4cd9b30SMilanka Ringwald { 225*f3198545SMatthias Ringwald if( _sample && _sample<32 ) 226a4cd9b30SMilanka Ringwald { 227*f3198545SMatthias Ringwald cptr->sampnum = _sample - 1; 228a4cd9b30SMilanka Ringwald } 229a4cd9b30SMilanka Ringwald 230*f3198545SMatthias Ringwald if( period || _sample ) 231a4cd9b30SMilanka Ringwald { 232a4cd9b30SMilanka Ringwald cptr->sampdata =(char *) mod->sampledata[cptr->sampnum]; 233a4cd9b30SMilanka Ringwald cptr->length = mod->song.samples[cptr->sampnum].length; 234a4cd9b30SMilanka Ringwald cptr->reppnt = mod->song.samples[cptr->sampnum].reppnt; 235a4cd9b30SMilanka Ringwald cptr->replen = mod->song.samples[cptr->sampnum].replen; 236a4cd9b30SMilanka Ringwald 237a4cd9b30SMilanka Ringwald cptr->finetune = (mod->song.samples[cptr->sampnum].finetune)&0xF; 238a4cd9b30SMilanka Ringwald 239a4cd9b30SMilanka Ringwald if(effect>>8!=4 && effect>>8!=6) 240a4cd9b30SMilanka Ringwald { 241a4cd9b30SMilanka Ringwald cptr->vibraperiod=0; 242a4cd9b30SMilanka Ringwald cptr->vibrapointeur=0; 243a4cd9b30SMilanka Ringwald } 244a4cd9b30SMilanka Ringwald } 245a4cd9b30SMilanka Ringwald 246*f3198545SMatthias Ringwald if( (_sample != 0) && ( (effect>>8) != EFFECT_VOLSLIDE_TONEPORTA ) ) 247a4cd9b30SMilanka Ringwald { 248a4cd9b30SMilanka Ringwald cptr->volume = mod->song.samples[cptr->sampnum].volume; 249a4cd9b30SMilanka Ringwald cptr->volumeslide = 0; 250a4cd9b30SMilanka Ringwald } 251a4cd9b30SMilanka Ringwald 252a4cd9b30SMilanka Ringwald if( ( (effect>>8) != EFFECT_TONE_PORTAMENTO && (effect>>8)!=EFFECT_VOLSLIDE_TONEPORTA) ) 253a4cd9b30SMilanka Ringwald { 254a4cd9b30SMilanka Ringwald if (period!=0) 255a4cd9b30SMilanka Ringwald cptr->samppos = 0; 256a4cd9b30SMilanka Ringwald } 257a4cd9b30SMilanka Ringwald 258a4cd9b30SMilanka Ringwald cptr->decalperiod=0; 259a4cd9b30SMilanka Ringwald if( period ) 260a4cd9b30SMilanka Ringwald { 261a4cd9b30SMilanka Ringwald if(cptr->finetune) 262a4cd9b30SMilanka Ringwald { 263a4cd9b30SMilanka Ringwald if( cptr->finetune <= 7 ) 264a4cd9b30SMilanka Ringwald { 265a4cd9b30SMilanka Ringwald period = mod->fullperiod[getnote(mod,period,0) + cptr->finetune]; 266a4cd9b30SMilanka Ringwald } 267a4cd9b30SMilanka Ringwald else 268a4cd9b30SMilanka Ringwald { 269a4cd9b30SMilanka Ringwald period = mod->fullperiod[getnote(mod,period,0) - (16 - (cptr->finetune)) ]; 270a4cd9b30SMilanka Ringwald } 271a4cd9b30SMilanka Ringwald } 272a4cd9b30SMilanka Ringwald 273a4cd9b30SMilanka Ringwald cptr->period = period; 274a4cd9b30SMilanka Ringwald } 275a4cd9b30SMilanka Ringwald 276a4cd9b30SMilanka Ringwald } 277a4cd9b30SMilanka Ringwald 278a4cd9b30SMilanka Ringwald cptr->effect = 0; 279a4cd9b30SMilanka Ringwald cptr->parameffect = 0; 280a4cd9b30SMilanka Ringwald cptr->effect_code = effect; 281a4cd9b30SMilanka Ringwald 282a4cd9b30SMilanka Ringwald switch (effect >> 8) 283a4cd9b30SMilanka Ringwald { 284a4cd9b30SMilanka Ringwald case EFFECT_ARPEGGIO: 285a4cd9b30SMilanka Ringwald /* 286a4cd9b30SMilanka Ringwald [0]: Arpeggio 287a4cd9b30SMilanka Ringwald Where [0][x][y] means "play note, note+x semitones, note+y 288a4cd9b30SMilanka Ringwald semitones, then return to original note". The fluctuations are 289a4cd9b30SMilanka Ringwald carried out evenly spaced in one pattern division. They are usually 290a4cd9b30SMilanka Ringwald used to simulate chords, but this doesn't work too well. They are 291a4cd9b30SMilanka Ringwald also used to produce heavy vibrato. A major chord is when x=4, y=7. 292a4cd9b30SMilanka Ringwald A minor chord is when x=3, y=7. 293a4cd9b30SMilanka Ringwald */ 294a4cd9b30SMilanka Ringwald 295a4cd9b30SMilanka Ringwald if(effect&0xff) 296a4cd9b30SMilanka Ringwald { 297a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_ARPEGGIO; 298a4cd9b30SMilanka Ringwald cptr->parameffect = effect&0xff; 299a4cd9b30SMilanka Ringwald 300a4cd9b30SMilanka Ringwald cptr->ArpIndex = 0; 301a4cd9b30SMilanka Ringwald 302a4cd9b30SMilanka Ringwald curnote = getnote(mod,cptr->period,cptr->finetune); 303a4cd9b30SMilanka Ringwald 304a4cd9b30SMilanka Ringwald cptr->Arpperiods[0] = cptr->period; 305a4cd9b30SMilanka Ringwald 306a4cd9b30SMilanka Ringwald arpnote = curnote + (((cptr->parameffect>>4)&0xF)*8); 307a4cd9b30SMilanka Ringwald if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) 308a4cd9b30SMilanka Ringwald arpnote = FULL_PERIOD_TABLE_LENGTH - 1; 309a4cd9b30SMilanka Ringwald 310a4cd9b30SMilanka Ringwald cptr->Arpperiods[1] = mod->fullperiod[arpnote]; 311a4cd9b30SMilanka Ringwald 312a4cd9b30SMilanka Ringwald arpnote = curnote + (((cptr->parameffect)&0xF)*8); 313a4cd9b30SMilanka Ringwald if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) 314a4cd9b30SMilanka Ringwald arpnote = FULL_PERIOD_TABLE_LENGTH - 1; 315a4cd9b30SMilanka Ringwald 316a4cd9b30SMilanka Ringwald cptr->Arpperiods[2] = mod->fullperiod[arpnote]; 317a4cd9b30SMilanka Ringwald } 318a4cd9b30SMilanka Ringwald break; 319a4cd9b30SMilanka Ringwald 320a4cd9b30SMilanka Ringwald case EFFECT_PORTAMENTO_UP: 321a4cd9b30SMilanka Ringwald /* 322a4cd9b30SMilanka Ringwald [1]: Slide up 323a4cd9b30SMilanka Ringwald Where [1][x][y] means "smoothly decrease the period of current 324a4cd9b30SMilanka Ringwald sample by x*16+y after each tick in the division". The 325a4cd9b30SMilanka Ringwald ticks/division are set with the 'set speed' effect (see below). If 326a4cd9b30SMilanka Ringwald the period of the note being played is z, then the final period 327a4cd9b30SMilanka Ringwald will be z - (x*16 + y)*(ticks - 1). As the slide rate depends on 328a4cd9b30SMilanka Ringwald the speed, changing the speed will change the slide. You cannot 329a4cd9b30SMilanka Ringwald slide beyond the note B3 (period 113). 330a4cd9b30SMilanka Ringwald */ 331a4cd9b30SMilanka Ringwald 332a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_PORTAMENTO_UP; 333a4cd9b30SMilanka Ringwald cptr->parameffect = effect&0xff; 334a4cd9b30SMilanka Ringwald break; 335a4cd9b30SMilanka Ringwald 336a4cd9b30SMilanka Ringwald case EFFECT_PORTAMENTO_DOWN: 337a4cd9b30SMilanka Ringwald /* 338a4cd9b30SMilanka Ringwald [2]: Slide down 339a4cd9b30SMilanka Ringwald Where [2][x][y] means "smoothly increase the period of current 340a4cd9b30SMilanka Ringwald sample by x*16+y after each tick in the division". Similar to [1], 341a4cd9b30SMilanka Ringwald but lowers the pitch. You cannot slide beyond the note C1 (period 342a4cd9b30SMilanka Ringwald 856). 343a4cd9b30SMilanka Ringwald */ 344a4cd9b30SMilanka Ringwald 345a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_PORTAMENTO_DOWN; 346a4cd9b30SMilanka Ringwald cptr->parameffect = effect&0xff; 347a4cd9b30SMilanka Ringwald break; 348a4cd9b30SMilanka Ringwald 349a4cd9b30SMilanka Ringwald case EFFECT_TONE_PORTAMENTO: 350a4cd9b30SMilanka Ringwald /* 351a4cd9b30SMilanka Ringwald [3]: Slide to note 352a4cd9b30SMilanka Ringwald Where [3][x][y] means "smoothly change the period of current sample 353a4cd9b30SMilanka Ringwald by x*16+y after each tick in the division, never sliding beyond 354a4cd9b30SMilanka Ringwald current period". The period-length in this channel's division is a 355a4cd9b30SMilanka Ringwald parameter to this effect, and hence is not played. Sliding to a 356a4cd9b30SMilanka Ringwald note is similar to effects [1] and [2], but the slide will not go 357a4cd9b30SMilanka Ringwald beyond the given period, and the direction is implied by that 358a4cd9b30SMilanka Ringwald period. If x and y are both 0, then the old slide will continue. 359a4cd9b30SMilanka Ringwald */ 360a4cd9b30SMilanka Ringwald 361a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_TONE_PORTAMENTO; 362a4cd9b30SMilanka Ringwald if( (effect&0xff) != 0 ) 363a4cd9b30SMilanka Ringwald { 364a4cd9b30SMilanka Ringwald cptr->portaspeed = (short)(effect&0xff); 365a4cd9b30SMilanka Ringwald } 366a4cd9b30SMilanka Ringwald 367a4cd9b30SMilanka Ringwald if(period!=0) 368a4cd9b30SMilanka Ringwald { 369a4cd9b30SMilanka Ringwald cptr->portaperiod = period; 370a4cd9b30SMilanka Ringwald cptr->period = operiod; 371a4cd9b30SMilanka Ringwald } 372a4cd9b30SMilanka Ringwald break; 373a4cd9b30SMilanka Ringwald 374a4cd9b30SMilanka Ringwald case EFFECT_VIBRATO: 375a4cd9b30SMilanka Ringwald /* 376a4cd9b30SMilanka Ringwald [4]: Vibrato 377a4cd9b30SMilanka Ringwald Where [4][x][y] means "oscillate the sample pitch using a 378a4cd9b30SMilanka Ringwald particular waveform with amplitude y/16 semitones, such that (x * 379a4cd9b30SMilanka Ringwald ticks)/64 cycles occur in the division". The waveform is set using 380a4cd9b30SMilanka Ringwald effect [14][4]. By placing vibrato effects on consecutive 381a4cd9b30SMilanka Ringwald divisions, the vibrato effect can be maintained. If either x or y 382a4cd9b30SMilanka Ringwald are 0, then the old vibrato values will be used. 383a4cd9b30SMilanka Ringwald */ 384a4cd9b30SMilanka Ringwald 385a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_VIBRATO; 386a4cd9b30SMilanka Ringwald if( ( effect & 0x0F ) != 0 ) // Depth continue or change ? 387a4cd9b30SMilanka Ringwald cptr->vibraparam = (cptr->vibraparam & 0xF0) | ( effect & 0x0F ); 388a4cd9b30SMilanka Ringwald if( ( effect & 0xF0 ) != 0 ) // Speed continue or change ? 389a4cd9b30SMilanka Ringwald cptr->vibraparam = (cptr->vibraparam & 0x0F) | ( effect & 0xF0 ); 390a4cd9b30SMilanka Ringwald 391a4cd9b30SMilanka Ringwald break; 392a4cd9b30SMilanka Ringwald 393a4cd9b30SMilanka Ringwald case EFFECT_VOLSLIDE_TONEPORTA: 394a4cd9b30SMilanka Ringwald /* 395a4cd9b30SMilanka Ringwald [5]: Continue 'Slide to note', but also do Volume slide 396a4cd9b30SMilanka Ringwald Where [5][x][y] means "either slide the volume up x*(ticks - 1) or 397a4cd9b30SMilanka Ringwald slide the volume down y*(ticks - 1), at the same time as continuing 398a4cd9b30SMilanka Ringwald the last 'Slide to note'". It is illegal for both x and y to be 399a4cd9b30SMilanka Ringwald non-zero. You cannot slide outside the volume range 0..64. The 400a4cd9b30SMilanka Ringwald period-length in this channel's division is a parameter to this 401a4cd9b30SMilanka Ringwald effect, and hence is not played. 402a4cd9b30SMilanka Ringwald */ 403a4cd9b30SMilanka Ringwald 404a4cd9b30SMilanka Ringwald if( period != 0 ) 405a4cd9b30SMilanka Ringwald { 406a4cd9b30SMilanka Ringwald cptr->portaperiod = period; 407a4cd9b30SMilanka Ringwald cptr->period = operiod; 408a4cd9b30SMilanka Ringwald } 409a4cd9b30SMilanka Ringwald 410a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_VOLSLIDE_TONEPORTA; 411a4cd9b30SMilanka Ringwald if( ( effect & 0xFF ) != 0 ) 412a4cd9b30SMilanka Ringwald cptr->volumeslide = ( effect & 0xFF ); 413a4cd9b30SMilanka Ringwald 414a4cd9b30SMilanka Ringwald break; 415a4cd9b30SMilanka Ringwald 416a4cd9b30SMilanka Ringwald case EFFECT_VOLSLIDE_VIBRATO: 417a4cd9b30SMilanka Ringwald /* 418a4cd9b30SMilanka Ringwald [6]: Continue 'Vibrato', but also do Volume slide 419a4cd9b30SMilanka Ringwald Where [6][x][y] means "either slide the volume up x*(ticks - 1) or 420a4cd9b30SMilanka Ringwald slide the volume down y*(ticks - 1), at the same time as continuing 421a4cd9b30SMilanka Ringwald the last 'Vibrato'". It is illegal for both x and y to be non-zero. 422a4cd9b30SMilanka Ringwald You cannot slide outside the volume range 0..64. 423a4cd9b30SMilanka Ringwald */ 424a4cd9b30SMilanka Ringwald 425a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_VOLSLIDE_VIBRATO; 426a4cd9b30SMilanka Ringwald if( (effect & 0xFF) != 0 ) 427a4cd9b30SMilanka Ringwald cptr->volumeslide = (effect & 0xFF); 428a4cd9b30SMilanka Ringwald break; 429a4cd9b30SMilanka Ringwald 430a4cd9b30SMilanka Ringwald case EFFECT_SET_OFFSET: 431a4cd9b30SMilanka Ringwald /* 432a4cd9b30SMilanka Ringwald [9]: Set sample offset 433a4cd9b30SMilanka Ringwald Where [9][x][y] means "play the sample from offset x*4096 + y*256". 434a4cd9b30SMilanka Ringwald The offset is measured in words. If no sample is given, yet one is 435a4cd9b30SMilanka Ringwald still playing on this channel, it should be retriggered to the new 436a4cd9b30SMilanka Ringwald offset using the current volume. 437a4cd9b30SMilanka Ringwald */ 438a4cd9b30SMilanka Ringwald 439a4cd9b30SMilanka Ringwald cptr->samppos = ((effect>>4) * 4096) + ((effect&0xF)*256); 440a4cd9b30SMilanka Ringwald 441a4cd9b30SMilanka Ringwald break; 442a4cd9b30SMilanka Ringwald 443a4cd9b30SMilanka Ringwald case EFFECT_VOLUME_SLIDE: 444a4cd9b30SMilanka Ringwald /* 445a4cd9b30SMilanka Ringwald [10]: Volume slide 446a4cd9b30SMilanka Ringwald Where [10][x][y] means "either slide the volume up x*(ticks - 1) or 447a4cd9b30SMilanka Ringwald slide the volume down y*(ticks - 1)". If both x and y are non-zero, 448a4cd9b30SMilanka Ringwald then the y value is ignored (assumed to be 0). You cannot slide 449a4cd9b30SMilanka Ringwald outside the volume range 0..64. 450a4cd9b30SMilanka Ringwald */ 451a4cd9b30SMilanka Ringwald 452a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_VOLUME_SLIDE; 453a4cd9b30SMilanka Ringwald cptr->volumeslide = (effect & 0xFF); 454a4cd9b30SMilanka Ringwald break; 455a4cd9b30SMilanka Ringwald 456a4cd9b30SMilanka Ringwald case EFFECT_JUMP_POSITION: 457a4cd9b30SMilanka Ringwald /* 458a4cd9b30SMilanka Ringwald [11]: Position Jump 459a4cd9b30SMilanka Ringwald Where [11][x][y] means "stop the pattern after this division, and 460a4cd9b30SMilanka Ringwald continue the song at song-position x*16+y". This shifts the 461a4cd9b30SMilanka Ringwald 'pattern-cursor' in the pattern table (see above). Legal values for 462a4cd9b30SMilanka Ringwald x*16+y are from 0 to 127. 463a4cd9b30SMilanka Ringwald */ 464a4cd9b30SMilanka Ringwald 465a4cd9b30SMilanka Ringwald mod->tablepos = (effect & 0xFF); 466a4cd9b30SMilanka Ringwald if(mod->tablepos >= mod->song.length) 467a4cd9b30SMilanka Ringwald mod->tablepos = 0; 468a4cd9b30SMilanka Ringwald mod->patternpos = 0; 469a4cd9b30SMilanka Ringwald mod->jump_loop_effect = 1; 470a4cd9b30SMilanka Ringwald 471a4cd9b30SMilanka Ringwald break; 472a4cd9b30SMilanka Ringwald 473a4cd9b30SMilanka Ringwald case EFFECT_SET_VOLUME: 474a4cd9b30SMilanka Ringwald /* 475a4cd9b30SMilanka Ringwald [12]: Set volume 476a4cd9b30SMilanka Ringwald Where [12][x][y] means "set current sample's volume to x*16+y". 477a4cd9b30SMilanka Ringwald Legal volumes are 0..64. 478a4cd9b30SMilanka Ringwald */ 479a4cd9b30SMilanka Ringwald 480a4cd9b30SMilanka Ringwald cptr->volume = (effect & 0xFF); 481a4cd9b30SMilanka Ringwald break; 482a4cd9b30SMilanka Ringwald 483a4cd9b30SMilanka Ringwald case EFFECT_PATTERN_BREAK: 484a4cd9b30SMilanka Ringwald /* 485a4cd9b30SMilanka Ringwald [13]: Pattern Break 486a4cd9b30SMilanka Ringwald Where [13][x][y] means "stop the pattern after this division, and 487a4cd9b30SMilanka Ringwald continue the song at the next pattern at division x*10+y" (the 10 488a4cd9b30SMilanka Ringwald is not a typo). Legal divisions are from 0 to 63 (note Protracker 489a4cd9b30SMilanka Ringwald exception above). 490a4cd9b30SMilanka Ringwald */ 491a4cd9b30SMilanka Ringwald 492a4cd9b30SMilanka Ringwald mod->patternpos = ( ((effect>>4)&0xF)*10 + (effect&0xF) ) * mod->number_of_channels; 493a4cd9b30SMilanka Ringwald mod->jump_loop_effect = 1; 494a4cd9b30SMilanka Ringwald mod->tablepos++; 495a4cd9b30SMilanka Ringwald if(mod->tablepos >= mod->song.length) 496a4cd9b30SMilanka Ringwald mod->tablepos = 0; 497a4cd9b30SMilanka Ringwald 498a4cd9b30SMilanka Ringwald break; 499a4cd9b30SMilanka Ringwald 500a4cd9b30SMilanka Ringwald case EFFECT_EXTENDED: 501a4cd9b30SMilanka Ringwald switch( (effect>>4) & 0xF ) 502a4cd9b30SMilanka Ringwald { 503a4cd9b30SMilanka Ringwald case EFFECT_E_FINE_PORTA_UP: 504a4cd9b30SMilanka Ringwald /* 505a4cd9b30SMilanka Ringwald [14][1]: Fineslide up 506a4cd9b30SMilanka Ringwald Where [14][1][x] means "decrement the period of the current sample 507a4cd9b30SMilanka Ringwald by x". The incrementing takes place at the beginning of the 508a4cd9b30SMilanka Ringwald division, and hence there is no actual sliding. You cannot slide 509a4cd9b30SMilanka Ringwald beyond the note B3 (period 113). 510a4cd9b30SMilanka Ringwald */ 511a4cd9b30SMilanka Ringwald 512a4cd9b30SMilanka Ringwald cptr->period -= (effect & 0xF); 513a4cd9b30SMilanka Ringwald if( cptr->period < 113 ) 514a4cd9b30SMilanka Ringwald cptr->period = 113; 515a4cd9b30SMilanka Ringwald break; 516a4cd9b30SMilanka Ringwald 517a4cd9b30SMilanka Ringwald case EFFECT_E_FINE_PORTA_DOWN: 518a4cd9b30SMilanka Ringwald /* 519a4cd9b30SMilanka Ringwald [14][2]: Fineslide down 520a4cd9b30SMilanka Ringwald Where [14][2][x] means "increment the period of the current sample 521a4cd9b30SMilanka Ringwald by x". Similar to [14][1] but shifts the pitch down. You cannot 522a4cd9b30SMilanka Ringwald slide beyond the note C1 (period 856). 523a4cd9b30SMilanka Ringwald */ 524a4cd9b30SMilanka Ringwald 525a4cd9b30SMilanka Ringwald cptr->period += (effect & 0xF); 526a4cd9b30SMilanka Ringwald if( cptr->period > 856 ) 527a4cd9b30SMilanka Ringwald cptr->period = 856; 528a4cd9b30SMilanka Ringwald break; 529a4cd9b30SMilanka Ringwald 530a4cd9b30SMilanka Ringwald case EFFECT_E_FINE_VOLSLIDE_UP: 531a4cd9b30SMilanka Ringwald /* 532a4cd9b30SMilanka Ringwald [14][10]: Fine volume slide up 533a4cd9b30SMilanka Ringwald Where [14][10][x] means "increment the volume of the current sample 534a4cd9b30SMilanka Ringwald by x". The incrementing takes place at the beginning of the 535a4cd9b30SMilanka Ringwald division, and hence there is no sliding. You cannot slide beyond 536a4cd9b30SMilanka Ringwald volume 64. 537a4cd9b30SMilanka Ringwald */ 538a4cd9b30SMilanka Ringwald 539a4cd9b30SMilanka Ringwald cptr->volume += (effect & 0xF); 540a4cd9b30SMilanka Ringwald if( cptr->volume>64 ) 541a4cd9b30SMilanka Ringwald cptr->volume = 64; 542a4cd9b30SMilanka Ringwald break; 543a4cd9b30SMilanka Ringwald 544a4cd9b30SMilanka Ringwald case EFFECT_E_FINE_VOLSLIDE_DOWN: 545a4cd9b30SMilanka Ringwald /* 546a4cd9b30SMilanka Ringwald [14][11]: Fine volume slide down 547a4cd9b30SMilanka Ringwald Where [14][11][x] means "decrement the volume of the current sample 548a4cd9b30SMilanka Ringwald by x". Similar to [14][10] but lowers volume. You cannot slide 549a4cd9b30SMilanka Ringwald beyond volume 0. 550a4cd9b30SMilanka Ringwald */ 551a4cd9b30SMilanka Ringwald 552a4cd9b30SMilanka Ringwald cptr->volume -= (effect & 0xF); 553a4cd9b30SMilanka Ringwald if( cptr->volume > 200 ) 554a4cd9b30SMilanka Ringwald cptr->volume = 0; 555a4cd9b30SMilanka Ringwald break; 556a4cd9b30SMilanka Ringwald 557a4cd9b30SMilanka Ringwald case EFFECT_E_PATTERN_LOOP: 558a4cd9b30SMilanka Ringwald /* 559a4cd9b30SMilanka Ringwald [14][6]: Loop pattern 560a4cd9b30SMilanka Ringwald Where [14][6][x] means "set the start of a loop to this division if 561a4cd9b30SMilanka Ringwald x is 0, otherwise after this division, jump back to the start of a 562a4cd9b30SMilanka Ringwald loop and play it another x times before continuing". If the start 563a4cd9b30SMilanka Ringwald of the loop was not set, it will default to the start of the 564a4cd9b30SMilanka Ringwald current pattern. Hence 'loop pattern' cannot be performed across 565a4cd9b30SMilanka Ringwald multiple patterns. Note that loops do not support nesting, and you 566a4cd9b30SMilanka Ringwald may generate an infinite loop if you try to nest 'loop pattern's. 567a4cd9b30SMilanka Ringwald */ 568a4cd9b30SMilanka Ringwald 569a4cd9b30SMilanka Ringwald if( effect & 0xF ) 570a4cd9b30SMilanka Ringwald { 571a4cd9b30SMilanka Ringwald if( cptr->patternloopcnt ) 572a4cd9b30SMilanka Ringwald { 573a4cd9b30SMilanka Ringwald cptr->patternloopcnt--; 574a4cd9b30SMilanka Ringwald if( cptr->patternloopcnt ) 575a4cd9b30SMilanka Ringwald { 576a4cd9b30SMilanka Ringwald mod->patternpos = cptr->patternloopstartpoint; 577a4cd9b30SMilanka Ringwald mod->jump_loop_effect = 1; 578a4cd9b30SMilanka Ringwald } 579a4cd9b30SMilanka Ringwald else 580a4cd9b30SMilanka Ringwald { 581a4cd9b30SMilanka Ringwald cptr->patternloopstartpoint = mod->patternpos ; 582a4cd9b30SMilanka Ringwald } 583a4cd9b30SMilanka Ringwald } 584a4cd9b30SMilanka Ringwald else 585a4cd9b30SMilanka Ringwald { 586a4cd9b30SMilanka Ringwald cptr->patternloopcnt = (effect & 0xF); 587a4cd9b30SMilanka Ringwald mod->patternpos = cptr->patternloopstartpoint; 588a4cd9b30SMilanka Ringwald mod->jump_loop_effect = 1; 589a4cd9b30SMilanka Ringwald } 590a4cd9b30SMilanka Ringwald } 591a4cd9b30SMilanka Ringwald else // Start point 592a4cd9b30SMilanka Ringwald { 593a4cd9b30SMilanka Ringwald cptr->patternloopstartpoint = mod->patternpos; 594a4cd9b30SMilanka Ringwald } 595a4cd9b30SMilanka Ringwald 596a4cd9b30SMilanka Ringwald break; 597a4cd9b30SMilanka Ringwald 598a4cd9b30SMilanka Ringwald case EFFECT_E_PATTERN_DELAY: 599a4cd9b30SMilanka Ringwald /* 600a4cd9b30SMilanka Ringwald [14][14]: Delay pattern 601a4cd9b30SMilanka Ringwald Where [14][14][x] means "after this division there will be a delay 602a4cd9b30SMilanka Ringwald equivalent to the time taken to play x divisions after which the 603a4cd9b30SMilanka Ringwald pattern will be resumed". The delay only relates to the 604a4cd9b30SMilanka Ringwald interpreting of new divisions, and all effects and previous notes 605a4cd9b30SMilanka Ringwald continue during delay. 606a4cd9b30SMilanka Ringwald */ 607a4cd9b30SMilanka Ringwald 608a4cd9b30SMilanka Ringwald mod->patterndelay = (effect & 0xF); 609a4cd9b30SMilanka Ringwald break; 610a4cd9b30SMilanka Ringwald 611a4cd9b30SMilanka Ringwald case EFFECT_E_NOTE_CUT: 612a4cd9b30SMilanka Ringwald /* 613a4cd9b30SMilanka Ringwald [14][12]: Cut sample 614a4cd9b30SMilanka Ringwald Where [14][12][x] means "after the current sample has been played 615a4cd9b30SMilanka Ringwald for x ticks in this division, its volume will be set to 0". This 616a4cd9b30SMilanka Ringwald implies that if x is 0, then you will not hear any of the sample. 617a4cd9b30SMilanka Ringwald If you wish to insert "silence" in a pattern, it is better to use a 618a4cd9b30SMilanka Ringwald "silence"-sample (see above) due to the lack of proper support for 619a4cd9b30SMilanka Ringwald this effect. 620a4cd9b30SMilanka Ringwald */ 621a4cd9b30SMilanka Ringwald cptr->effect = EFFECT_E_NOTE_CUT; 622a4cd9b30SMilanka Ringwald cptr->cut_param = (effect & 0xF); 623a4cd9b30SMilanka Ringwald if(!cptr->cut_param) 624a4cd9b30SMilanka Ringwald cptr->volume = 0; 625a4cd9b30SMilanka Ringwald break; 626a4cd9b30SMilanka Ringwald 627a4cd9b30SMilanka Ringwald default: 628a4cd9b30SMilanka Ringwald 629a4cd9b30SMilanka Ringwald break; 630a4cd9b30SMilanka Ringwald } 631a4cd9b30SMilanka Ringwald break; 632a4cd9b30SMilanka Ringwald 633a4cd9b30SMilanka Ringwald case 0xF: 634a4cd9b30SMilanka Ringwald /* 635a4cd9b30SMilanka Ringwald [15]: Set speed 636a4cd9b30SMilanka Ringwald Where [15][x][y] means "set speed to x*16+y". Though it is nowhere 637a4cd9b30SMilanka Ringwald near that simple. Let z = x*16+y. Depending on what values z takes, 638a4cd9b30SMilanka Ringwald different units of speed are set, there being two: ticks/division 639a4cd9b30SMilanka Ringwald and beats/minute (though this one is only a label and not strictly 640a4cd9b30SMilanka Ringwald true). If z=0, then what should technically happen is that the 641a4cd9b30SMilanka Ringwald module stops, but in practice it is treated as if z=1, because 642a4cd9b30SMilanka Ringwald there is already a method for stopping the module (running out of 643a4cd9b30SMilanka Ringwald patterns). If z<=32, then it means "set ticks/division to z" 644a4cd9b30SMilanka Ringwald otherwise it means "set beats/minute to z" (convention says that 645a4cd9b30SMilanka Ringwald this should read "If z<32.." but there are some composers out there 646a4cd9b30SMilanka Ringwald that defy conventions). Default values are 6 ticks/division, and 647a4cd9b30SMilanka Ringwald 125 beats/minute (4 divisions = 1 beat). The beats/minute tag is 648a4cd9b30SMilanka Ringwald only meaningful for 6 ticks/division. To get a more accurate view 649a4cd9b30SMilanka Ringwald of how things work, use the following formula: 650a4cd9b30SMilanka Ringwald 24 * beats/minute 651a4cd9b30SMilanka Ringwald divisions/minute = ----------------- 652a4cd9b30SMilanka Ringwald ticks/division 653a4cd9b30SMilanka Ringwald Hence divisions/minute range from 24.75 to 6120, eg. to get a value 654a4cd9b30SMilanka Ringwald of 2000 divisions/minute use 3 ticks/division and 250 beats/minute. 655a4cd9b30SMilanka Ringwald If multiple "set speed" effects are performed in a single division, 656a4cd9b30SMilanka Ringwald the ones on higher-numbered channels take precedence over the ones 657a4cd9b30SMilanka Ringwald on lower-numbered channels. This effect has a large number of 658a4cd9b30SMilanka Ringwald different implementations, but the one described here has the 659a4cd9b30SMilanka Ringwald widest usage. 660a4cd9b30SMilanka Ringwald */ 661a4cd9b30SMilanka Ringwald 662a4cd9b30SMilanka Ringwald if( (effect&0xFF) < 0x21 ) 663a4cd9b30SMilanka Ringwald { 664a4cd9b30SMilanka Ringwald if( effect&0xFF ) 665a4cd9b30SMilanka Ringwald { 666a4cd9b30SMilanka Ringwald mod->song.speed = effect&0xFF; 667a4cd9b30SMilanka Ringwald mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); 668a4cd9b30SMilanka Ringwald } 669a4cd9b30SMilanka Ringwald } 670a4cd9b30SMilanka Ringwald 671a4cd9b30SMilanka Ringwald if( (effect&0xFF) >= 0x21 ) 672a4cd9b30SMilanka Ringwald { 673a4cd9b30SMilanka Ringwald /// HZ = 2 * BPM / 5 674a4cd9b30SMilanka Ringwald mod->bpm = effect&0xFF; 675a4cd9b30SMilanka Ringwald mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); 676a4cd9b30SMilanka Ringwald } 677a4cd9b30SMilanka Ringwald 678a4cd9b30SMilanka Ringwald break; 679a4cd9b30SMilanka Ringwald 680a4cd9b30SMilanka Ringwald default: 681a4cd9b30SMilanka Ringwald // Unsupported effect 682a4cd9b30SMilanka Ringwald break; 683a4cd9b30SMilanka Ringwald 684a4cd9b30SMilanka Ringwald } 685a4cd9b30SMilanka Ringwald 686a4cd9b30SMilanka Ringwald } 687a4cd9b30SMilanka Ringwald 688a4cd9b30SMilanka Ringwald static void workeffect( note * nptr, channel * cptr ) 689a4cd9b30SMilanka Ringwald { 690c5456c21SMilanka Ringwald (void) nptr; 691c5456c21SMilanka Ringwald 692a4cd9b30SMilanka Ringwald switch(cptr->effect) 693a4cd9b30SMilanka Ringwald { 694a4cd9b30SMilanka Ringwald case EFFECT_ARPEGGIO: 695a4cd9b30SMilanka Ringwald 696a4cd9b30SMilanka Ringwald if( cptr->parameffect ) 697a4cd9b30SMilanka Ringwald { 698a4cd9b30SMilanka Ringwald cptr->decalperiod = cptr->period - cptr->Arpperiods[cptr->ArpIndex]; 699a4cd9b30SMilanka Ringwald 700a4cd9b30SMilanka Ringwald cptr->ArpIndex++; 701a4cd9b30SMilanka Ringwald if( cptr->ArpIndex>2 ) 702a4cd9b30SMilanka Ringwald cptr->ArpIndex = 0; 703a4cd9b30SMilanka Ringwald } 704a4cd9b30SMilanka Ringwald break; 705a4cd9b30SMilanka Ringwald 706a4cd9b30SMilanka Ringwald case EFFECT_PORTAMENTO_UP: 707a4cd9b30SMilanka Ringwald 708a4cd9b30SMilanka Ringwald if(cptr->period) 709a4cd9b30SMilanka Ringwald { 710a4cd9b30SMilanka Ringwald cptr->period -= cptr->parameffect; 711a4cd9b30SMilanka Ringwald 712a4cd9b30SMilanka Ringwald if( cptr->period < 113 || cptr->period > 20000 ) 713a4cd9b30SMilanka Ringwald cptr->period = 113; 714a4cd9b30SMilanka Ringwald } 715a4cd9b30SMilanka Ringwald 716a4cd9b30SMilanka Ringwald break; 717a4cd9b30SMilanka Ringwald 718a4cd9b30SMilanka Ringwald case EFFECT_PORTAMENTO_DOWN: 719a4cd9b30SMilanka Ringwald 720a4cd9b30SMilanka Ringwald if(cptr->period) 721a4cd9b30SMilanka Ringwald { 722a4cd9b30SMilanka Ringwald cptr->period += cptr->parameffect; 723a4cd9b30SMilanka Ringwald 724a4cd9b30SMilanka Ringwald if( cptr->period > 20000 ) 725a4cd9b30SMilanka Ringwald cptr->period = 20000; 726a4cd9b30SMilanka Ringwald } 727a4cd9b30SMilanka Ringwald 728a4cd9b30SMilanka Ringwald break; 729a4cd9b30SMilanka Ringwald 730a4cd9b30SMilanka Ringwald case EFFECT_VOLSLIDE_TONEPORTA: 731a4cd9b30SMilanka Ringwald case EFFECT_TONE_PORTAMENTO: 732a4cd9b30SMilanka Ringwald 733a4cd9b30SMilanka Ringwald if( cptr->period && ( cptr->period != cptr->portaperiod ) && cptr->portaperiod ) 734a4cd9b30SMilanka Ringwald { 735a4cd9b30SMilanka Ringwald if( cptr->period > cptr->portaperiod ) 736a4cd9b30SMilanka Ringwald { 737a4cd9b30SMilanka Ringwald if( cptr->period - cptr->portaperiod >= cptr->portaspeed ) 738a4cd9b30SMilanka Ringwald { 739a4cd9b30SMilanka Ringwald cptr->period -= cptr->portaspeed; 740a4cd9b30SMilanka Ringwald } 741a4cd9b30SMilanka Ringwald else 742a4cd9b30SMilanka Ringwald { 743a4cd9b30SMilanka Ringwald cptr->period = cptr->portaperiod; 744a4cd9b30SMilanka Ringwald } 745a4cd9b30SMilanka Ringwald } 746a4cd9b30SMilanka Ringwald else 747a4cd9b30SMilanka Ringwald { 748a4cd9b30SMilanka Ringwald if( cptr->portaperiod - cptr->period >= cptr->portaspeed ) 749a4cd9b30SMilanka Ringwald { 750a4cd9b30SMilanka Ringwald cptr->period += cptr->portaspeed; 751a4cd9b30SMilanka Ringwald } 752a4cd9b30SMilanka Ringwald else 753a4cd9b30SMilanka Ringwald { 754a4cd9b30SMilanka Ringwald cptr->period = cptr->portaperiod; 755a4cd9b30SMilanka Ringwald } 756a4cd9b30SMilanka Ringwald } 757a4cd9b30SMilanka Ringwald 758a4cd9b30SMilanka Ringwald if( cptr->period == cptr->portaperiod ) 759a4cd9b30SMilanka Ringwald { 760a4cd9b30SMilanka Ringwald // If the slide is over, don't let it to be retriggered. 761a4cd9b30SMilanka Ringwald cptr->portaperiod = 0; 762a4cd9b30SMilanka Ringwald } 763a4cd9b30SMilanka Ringwald } 764a4cd9b30SMilanka Ringwald 765a4cd9b30SMilanka Ringwald if( cptr->effect == EFFECT_VOLSLIDE_TONEPORTA ) 766a4cd9b30SMilanka Ringwald { 767a4cd9b30SMilanka Ringwald if( cptr->volumeslide > 0x0F ) 768a4cd9b30SMilanka Ringwald { 769a4cd9b30SMilanka Ringwald cptr->volume = cptr->volume + (cptr->volumeslide>>4); 770a4cd9b30SMilanka Ringwald 771a4cd9b30SMilanka Ringwald if(cptr->volume>63) 772a4cd9b30SMilanka Ringwald cptr->volume = 63; 773a4cd9b30SMilanka Ringwald } 774a4cd9b30SMilanka Ringwald else 775a4cd9b30SMilanka Ringwald { 776a4cd9b30SMilanka Ringwald cptr->volume = cptr->volume - (cptr->volumeslide); 777a4cd9b30SMilanka Ringwald 778a4cd9b30SMilanka Ringwald if(cptr->volume>63) 779a4cd9b30SMilanka Ringwald cptr->volume=0; 780a4cd9b30SMilanka Ringwald } 781a4cd9b30SMilanka Ringwald } 782a4cd9b30SMilanka Ringwald break; 783a4cd9b30SMilanka Ringwald 784a4cd9b30SMilanka Ringwald case EFFECT_VOLSLIDE_VIBRATO: 785a4cd9b30SMilanka Ringwald case EFFECT_VIBRATO: 786a4cd9b30SMilanka Ringwald 787a4cd9b30SMilanka Ringwald cptr->vibraperiod = ( (cptr->vibraparam&0xF) * sintable[cptr->vibrapointeur&0x1F] )>>7; 788a4cd9b30SMilanka Ringwald 789a4cd9b30SMilanka Ringwald if( cptr->vibrapointeur > 31 ) 790a4cd9b30SMilanka Ringwald cptr->vibraperiod = -cptr->vibraperiod; 791a4cd9b30SMilanka Ringwald 792a4cd9b30SMilanka Ringwald cptr->vibrapointeur = (cptr->vibrapointeur+(((cptr->vibraparam>>4))&0xf)) & 0x3F; 793a4cd9b30SMilanka Ringwald 794a4cd9b30SMilanka Ringwald if( cptr->effect == EFFECT_VOLSLIDE_VIBRATO ) 795a4cd9b30SMilanka Ringwald { 796a4cd9b30SMilanka Ringwald if( cptr->volumeslide > 0xF ) 797a4cd9b30SMilanka Ringwald { 798a4cd9b30SMilanka Ringwald cptr->volume = cptr->volume+(cptr->volumeslide>>4); 799a4cd9b30SMilanka Ringwald 800a4cd9b30SMilanka Ringwald if( cptr->volume > 64 ) 801a4cd9b30SMilanka Ringwald cptr->volume = 64; 802a4cd9b30SMilanka Ringwald } 803a4cd9b30SMilanka Ringwald else 804a4cd9b30SMilanka Ringwald { 805a4cd9b30SMilanka Ringwald cptr->volume = cptr->volume - cptr->volumeslide; 806a4cd9b30SMilanka Ringwald 807a4cd9b30SMilanka Ringwald if( cptr->volume > 64 ) 808a4cd9b30SMilanka Ringwald cptr->volume = 0; 809a4cd9b30SMilanka Ringwald } 810a4cd9b30SMilanka Ringwald } 811a4cd9b30SMilanka Ringwald 812a4cd9b30SMilanka Ringwald break; 813a4cd9b30SMilanka Ringwald 814a4cd9b30SMilanka Ringwald case EFFECT_VOLUME_SLIDE: 815a4cd9b30SMilanka Ringwald 816a4cd9b30SMilanka Ringwald if( cptr->volumeslide > 0xF ) 817a4cd9b30SMilanka Ringwald { 818a4cd9b30SMilanka Ringwald cptr->volume += (cptr->volumeslide>>4); 819a4cd9b30SMilanka Ringwald 820a4cd9b30SMilanka Ringwald if( cptr->volume > 64 ) 821a4cd9b30SMilanka Ringwald cptr->volume = 64; 822a4cd9b30SMilanka Ringwald } 823a4cd9b30SMilanka Ringwald else 824a4cd9b30SMilanka Ringwald { 825a4cd9b30SMilanka Ringwald cptr->volume -= (cptr->volumeslide&0xf); 826a4cd9b30SMilanka Ringwald 827a4cd9b30SMilanka Ringwald if( cptr->volume > 64 ) 828a4cd9b30SMilanka Ringwald cptr->volume = 0; 829a4cd9b30SMilanka Ringwald } 830a4cd9b30SMilanka Ringwald break; 831a4cd9b30SMilanka Ringwald 832a4cd9b30SMilanka Ringwald case EFFECT_E_NOTE_CUT: 833a4cd9b30SMilanka Ringwald if(cptr->cut_param) 834a4cd9b30SMilanka Ringwald cptr->cut_param--; 835a4cd9b30SMilanka Ringwald 836a4cd9b30SMilanka Ringwald if(!cptr->cut_param) 837a4cd9b30SMilanka Ringwald cptr->volume = 0; 838a4cd9b30SMilanka Ringwald break; 839a4cd9b30SMilanka Ringwald 840a4cd9b30SMilanka Ringwald default: 841a4cd9b30SMilanka Ringwald break; 842a4cd9b30SMilanka Ringwald 843a4cd9b30SMilanka Ringwald } 844a4cd9b30SMilanka Ringwald 845a4cd9b30SMilanka Ringwald } 846a4cd9b30SMilanka Ringwald 847a4cd9b30SMilanka Ringwald /////////////////////////////////////////////////////////////////////////////////// 848a4cd9b30SMilanka Ringwald int hxcmod_init(modcontext * modctx) 849a4cd9b30SMilanka Ringwald { 850a4cd9b30SMilanka Ringwald muint i,j; 851a4cd9b30SMilanka Ringwald 852a4cd9b30SMilanka Ringwald if( modctx ) 853a4cd9b30SMilanka Ringwald { 854a4cd9b30SMilanka Ringwald memclear(modctx,0,sizeof(modcontext)); 855a4cd9b30SMilanka Ringwald modctx->playrate = 44100; 856a4cd9b30SMilanka Ringwald modctx->stereo = 1; 857a4cd9b30SMilanka Ringwald modctx->stereo_separation = 1; 858a4cd9b30SMilanka Ringwald modctx->bits = 16; 859a4cd9b30SMilanka Ringwald modctx->filter = 1; 860a4cd9b30SMilanka Ringwald 861a4cd9b30SMilanka Ringwald for(i=0;i<PERIOD_TABLE_LENGTH - 1;i++) 862a4cd9b30SMilanka Ringwald { 863a4cd9b30SMilanka Ringwald for(j=0;j<8;j++) 864a4cd9b30SMilanka Ringwald { 865a4cd9b30SMilanka Ringwald modctx->fullperiod[(i*8) + j] = periodtable[i] - ((( periodtable[i] - periodtable[i+1] ) / 8) * j); 866a4cd9b30SMilanka Ringwald } 867a4cd9b30SMilanka Ringwald } 868a4cd9b30SMilanka Ringwald 869a4cd9b30SMilanka Ringwald return 1; 870a4cd9b30SMilanka Ringwald } 871a4cd9b30SMilanka Ringwald 872a4cd9b30SMilanka Ringwald return 0; 873a4cd9b30SMilanka Ringwald } 874a4cd9b30SMilanka Ringwald 875a4cd9b30SMilanka Ringwald int hxcmod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter) 876a4cd9b30SMilanka Ringwald { 877a4cd9b30SMilanka Ringwald if( modctx ) 878a4cd9b30SMilanka Ringwald { 879a4cd9b30SMilanka Ringwald modctx->playrate = samplerate; 880a4cd9b30SMilanka Ringwald 881a4cd9b30SMilanka Ringwald if( stereo ) 882a4cd9b30SMilanka Ringwald modctx->stereo = 1; 883a4cd9b30SMilanka Ringwald else 884a4cd9b30SMilanka Ringwald modctx->stereo = 0; 885a4cd9b30SMilanka Ringwald 886a4cd9b30SMilanka Ringwald if(stereo_separation < 4) 887a4cd9b30SMilanka Ringwald { 888a4cd9b30SMilanka Ringwald modctx->stereo_separation = stereo_separation; 889a4cd9b30SMilanka Ringwald } 890a4cd9b30SMilanka Ringwald 891a4cd9b30SMilanka Ringwald if( bits == 8 || bits == 16 ) 892a4cd9b30SMilanka Ringwald { 893a4cd9b30SMilanka Ringwald modctx->bits = bits; 894a4cd9b30SMilanka Ringwald } 895a4cd9b30SMilanka Ringwald 896a4cd9b30SMilanka Ringwald if( filter ) 897a4cd9b30SMilanka Ringwald modctx->filter = 1; 898a4cd9b30SMilanka Ringwald else 899a4cd9b30SMilanka Ringwald modctx->filter = 0; 900a4cd9b30SMilanka Ringwald 901a4cd9b30SMilanka Ringwald return 1; 902a4cd9b30SMilanka Ringwald } 903a4cd9b30SMilanka Ringwald 904a4cd9b30SMilanka Ringwald return 0; 905a4cd9b30SMilanka Ringwald } 906a4cd9b30SMilanka Ringwald 907a4cd9b30SMilanka Ringwald int hxcmod_load( modcontext * modctx, void * mod_data, int mod_data_size ) 908a4cd9b30SMilanka Ringwald { 909a4cd9b30SMilanka Ringwald muint i, max; 910a4cd9b30SMilanka Ringwald unsigned short t; 911a4cd9b30SMilanka Ringwald sample *sptr; 912a4cd9b30SMilanka Ringwald unsigned char * modmemory,* endmodmemory; 913a4cd9b30SMilanka Ringwald 914a4cd9b30SMilanka Ringwald modmemory = (unsigned char *)mod_data; 915a4cd9b30SMilanka Ringwald endmodmemory = modmemory + mod_data_size; 916a4cd9b30SMilanka Ringwald 917a4cd9b30SMilanka Ringwald if(modmemory) 918a4cd9b30SMilanka Ringwald { 919a4cd9b30SMilanka Ringwald if( modctx ) 920a4cd9b30SMilanka Ringwald { 921a4cd9b30SMilanka Ringwald memcopy(&(modctx->song.title),modmemory,1084); 922a4cd9b30SMilanka Ringwald 923a4cd9b30SMilanka Ringwald i = 0; 924a4cd9b30SMilanka Ringwald modctx->number_of_channels = 0; 925a4cd9b30SMilanka Ringwald while(modlist[i].numberofchannels) 926a4cd9b30SMilanka Ringwald { 927a4cd9b30SMilanka Ringwald if(memcompare(modctx->song.signature,modlist[i].signature,4)) 928a4cd9b30SMilanka Ringwald { 929a4cd9b30SMilanka Ringwald modctx->number_of_channels = modlist[i].numberofchannels; 930a4cd9b30SMilanka Ringwald } 931a4cd9b30SMilanka Ringwald 932a4cd9b30SMilanka Ringwald i++; 933a4cd9b30SMilanka Ringwald } 934a4cd9b30SMilanka Ringwald 935a4cd9b30SMilanka Ringwald if( !modctx->number_of_channels ) 936a4cd9b30SMilanka Ringwald { 937a4cd9b30SMilanka Ringwald // 15 Samples modules support 938a4cd9b30SMilanka Ringwald // Shift the whole datas to make it look likes a standard 4 channels mod. 939a4cd9b30SMilanka Ringwald memcopy(&(modctx->song.signature), "M.K.", 4); 940a4cd9b30SMilanka Ringwald memcopy(&(modctx->song.length), &(modctx->song.samples[15]), 130); 941a4cd9b30SMilanka Ringwald memclear(&(modctx->song.samples[15]), 0, 480); 942a4cd9b30SMilanka Ringwald modmemory += 600; 943a4cd9b30SMilanka Ringwald modctx->number_of_channels = 4; 944a4cd9b30SMilanka Ringwald } 945a4cd9b30SMilanka Ringwald else 946a4cd9b30SMilanka Ringwald { 947a4cd9b30SMilanka Ringwald modmemory += 1084; 948a4cd9b30SMilanka Ringwald } 949a4cd9b30SMilanka Ringwald 950a4cd9b30SMilanka Ringwald if( modmemory >= endmodmemory ) 951a4cd9b30SMilanka Ringwald return 0; // End passed ? - Probably a bad file ! 952a4cd9b30SMilanka Ringwald 953a4cd9b30SMilanka Ringwald // Patterns loading 954a4cd9b30SMilanka Ringwald for (i = max = 0; i < 128; i++) 955a4cd9b30SMilanka Ringwald { 956a4cd9b30SMilanka Ringwald while (max <= modctx->song.patterntable[i]) 957a4cd9b30SMilanka Ringwald { 958a4cd9b30SMilanka Ringwald modctx->patterndata[max] = (note*)modmemory; 959a4cd9b30SMilanka Ringwald modmemory += (256*modctx->number_of_channels); 960a4cd9b30SMilanka Ringwald max++; 961a4cd9b30SMilanka Ringwald 962a4cd9b30SMilanka Ringwald if( modmemory >= endmodmemory ) 963a4cd9b30SMilanka Ringwald return 0; // End passed ? - Probably a bad file ! 964a4cd9b30SMilanka Ringwald } 965a4cd9b30SMilanka Ringwald } 966a4cd9b30SMilanka Ringwald 967a4cd9b30SMilanka Ringwald for (i = 0; i < 31; i++) 968a4cd9b30SMilanka Ringwald modctx->sampledata[i]=0; 969a4cd9b30SMilanka Ringwald 970a4cd9b30SMilanka Ringwald // Samples loading 971a4cd9b30SMilanka Ringwald for (i = 0, sptr = modctx->song.samples; i <31; i++, sptr++) 972a4cd9b30SMilanka Ringwald { 973a4cd9b30SMilanka Ringwald t= (sptr->length &0xFF00)>>8 | (sptr->length &0xFF)<<8; 974a4cd9b30SMilanka Ringwald sptr->length = t*2; 975a4cd9b30SMilanka Ringwald 976a4cd9b30SMilanka Ringwald t= (sptr->reppnt &0xFF00)>>8 | (sptr->reppnt &0xFF)<<8; 977a4cd9b30SMilanka Ringwald sptr->reppnt = t*2; 978a4cd9b30SMilanka Ringwald 979a4cd9b30SMilanka Ringwald t= (sptr->replen &0xFF00)>>8 | (sptr->replen &0xFF)<<8; 980a4cd9b30SMilanka Ringwald sptr->replen = t*2; 981a4cd9b30SMilanka Ringwald 982a4cd9b30SMilanka Ringwald 983a4cd9b30SMilanka Ringwald if (sptr->length == 0) continue; 984a4cd9b30SMilanka Ringwald 985a4cd9b30SMilanka Ringwald modctx->sampledata[i] = (char*)modmemory; 986a4cd9b30SMilanka Ringwald modmemory += sptr->length; 987a4cd9b30SMilanka Ringwald 988a4cd9b30SMilanka Ringwald if (sptr->replen + sptr->reppnt > sptr->length) 989a4cd9b30SMilanka Ringwald sptr->replen = sptr->length - sptr->reppnt; 990a4cd9b30SMilanka Ringwald 991a4cd9b30SMilanka Ringwald if( modmemory > endmodmemory ) 992a4cd9b30SMilanka Ringwald return 0; // End passed ? - Probably a bad file ! 993a4cd9b30SMilanka Ringwald } 994a4cd9b30SMilanka Ringwald 995a4cd9b30SMilanka Ringwald // States init 996a4cd9b30SMilanka Ringwald 997a4cd9b30SMilanka Ringwald modctx->tablepos = 0; 998a4cd9b30SMilanka Ringwald modctx->patternpos = 0; 999a4cd9b30SMilanka Ringwald modctx->song.speed = 6; 1000a4cd9b30SMilanka Ringwald modctx->bpm = 125; 1001a4cd9b30SMilanka Ringwald modctx->samplenb = 0; 1002a4cd9b30SMilanka Ringwald 1003a4cd9b30SMilanka Ringwald modctx->patternticks = (((long)modctx->song.speed * modctx->playrate * 5)/ (2 * modctx->bpm)) + 1; 1004a4cd9b30SMilanka Ringwald modctx->patternticksaim = ((long)modctx->song.speed * modctx->playrate * 5) / (2 * modctx->bpm); 1005a4cd9b30SMilanka Ringwald 1006a4cd9b30SMilanka Ringwald modctx->sampleticksconst = 3546894UL / modctx->playrate; //8448*428/playrate; 1007a4cd9b30SMilanka Ringwald 1008a4cd9b30SMilanka Ringwald for(i=0; i < modctx->number_of_channels; i++) 1009a4cd9b30SMilanka Ringwald { 1010a4cd9b30SMilanka Ringwald modctx->channels[i].volume = 0; 1011a4cd9b30SMilanka Ringwald modctx->channels[i].period = 0; 1012a4cd9b30SMilanka Ringwald } 1013a4cd9b30SMilanka Ringwald 1014a4cd9b30SMilanka Ringwald modctx->mod_loaded = 1; 1015a4cd9b30SMilanka Ringwald 1016a4cd9b30SMilanka Ringwald return 1; 1017a4cd9b30SMilanka Ringwald } 1018a4cd9b30SMilanka Ringwald } 1019a4cd9b30SMilanka Ringwald 1020a4cd9b30SMilanka Ringwald return 0; 1021a4cd9b30SMilanka Ringwald } 1022a4cd9b30SMilanka Ringwald 1023a4cd9b30SMilanka Ringwald void hxcmod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, tracker_buffer_state * trkbuf ) 1024a4cd9b30SMilanka Ringwald { 1025a4cd9b30SMilanka Ringwald unsigned long i, j; 1026a4cd9b30SMilanka Ringwald unsigned long k; 1027a4cd9b30SMilanka Ringwald unsigned char c; 1028a4cd9b30SMilanka Ringwald unsigned int state_remaining_steps; 1029a4cd9b30SMilanka Ringwald int l,r; 1030a4cd9b30SMilanka Ringwald int ll,lr; 1031a4cd9b30SMilanka Ringwald int tl,tr; 1032a4cd9b30SMilanka Ringwald short finalperiod; 1033a4cd9b30SMilanka Ringwald note *nptr; 1034a4cd9b30SMilanka Ringwald channel *cptr; 1035a4cd9b30SMilanka Ringwald 1036a4cd9b30SMilanka Ringwald if( modctx && outbuffer ) 1037a4cd9b30SMilanka Ringwald { 1038a4cd9b30SMilanka Ringwald if(modctx->mod_loaded) 1039a4cd9b30SMilanka Ringwald { 1040a4cd9b30SMilanka Ringwald state_remaining_steps = 0; 1041a4cd9b30SMilanka Ringwald 1042a4cd9b30SMilanka Ringwald if( trkbuf ) 1043a4cd9b30SMilanka Ringwald { 1044a4cd9b30SMilanka Ringwald trkbuf->cur_rd_index = 0; 1045a4cd9b30SMilanka Ringwald 1046a4cd9b30SMilanka Ringwald memcopy(trkbuf->name,modctx->song.title,sizeof(modctx->song.title)); 1047a4cd9b30SMilanka Ringwald 1048a4cd9b30SMilanka Ringwald for(i=0;i<31;i++) 1049a4cd9b30SMilanka Ringwald { 1050a4cd9b30SMilanka Ringwald memcopy(trkbuf->instruments[i].name,modctx->song.samples[i].name,sizeof(trkbuf->instruments[i].name)); 1051a4cd9b30SMilanka Ringwald } 1052a4cd9b30SMilanka Ringwald } 1053a4cd9b30SMilanka Ringwald 1054a4cd9b30SMilanka Ringwald ll = modctx->last_l_sample; 1055a4cd9b30SMilanka Ringwald lr = modctx->last_r_sample; 1056a4cd9b30SMilanka Ringwald 1057a4cd9b30SMilanka Ringwald for (i = 0; i < nbsample; i++) 1058a4cd9b30SMilanka Ringwald { 1059a4cd9b30SMilanka Ringwald //--------------------------------------- 1060a4cd9b30SMilanka Ringwald if( modctx->patternticks++ > modctx->patternticksaim ) 1061a4cd9b30SMilanka Ringwald { 1062a4cd9b30SMilanka Ringwald if( !modctx->patterndelay ) 1063a4cd9b30SMilanka Ringwald { 1064a4cd9b30SMilanka Ringwald nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; 1065a4cd9b30SMilanka Ringwald nptr = nptr + modctx->patternpos; 1066a4cd9b30SMilanka Ringwald cptr = modctx->channels; 1067a4cd9b30SMilanka Ringwald 1068a4cd9b30SMilanka Ringwald modctx->patternticks = 0; 1069a4cd9b30SMilanka Ringwald modctx->patterntickse = 0; 1070a4cd9b30SMilanka Ringwald 1071a4cd9b30SMilanka Ringwald for(c=0;c<modctx->number_of_channels;c++) 1072a4cd9b30SMilanka Ringwald { 1073a4cd9b30SMilanka Ringwald worknote((note*)(nptr+c), (channel*)(cptr+c),(char)(c+1),modctx); 1074a4cd9b30SMilanka Ringwald } 1075a4cd9b30SMilanka Ringwald 1076a4cd9b30SMilanka Ringwald if( !modctx->jump_loop_effect ) 1077a4cd9b30SMilanka Ringwald modctx->patternpos += modctx->number_of_channels; 1078a4cd9b30SMilanka Ringwald else 1079a4cd9b30SMilanka Ringwald modctx->jump_loop_effect = 0; 1080a4cd9b30SMilanka Ringwald 1081a4cd9b30SMilanka Ringwald if( modctx->patternpos == 64*modctx->number_of_channels ) 1082a4cd9b30SMilanka Ringwald { 1083a4cd9b30SMilanka Ringwald modctx->tablepos++; 1084a4cd9b30SMilanka Ringwald modctx->patternpos = 0; 1085a4cd9b30SMilanka Ringwald if(modctx->tablepos >= modctx->song.length) 1086a4cd9b30SMilanka Ringwald modctx->tablepos = 0; 1087a4cd9b30SMilanka Ringwald } 1088a4cd9b30SMilanka Ringwald } 1089a4cd9b30SMilanka Ringwald else 1090a4cd9b30SMilanka Ringwald { 1091a4cd9b30SMilanka Ringwald modctx->patterndelay--; 1092a4cd9b30SMilanka Ringwald modctx->patternticks = 0; 1093a4cd9b30SMilanka Ringwald modctx->patterntickse = 0; 1094a4cd9b30SMilanka Ringwald } 1095a4cd9b30SMilanka Ringwald 1096a4cd9b30SMilanka Ringwald } 1097a4cd9b30SMilanka Ringwald 1098a4cd9b30SMilanka Ringwald if( modctx->patterntickse++ > (modctx->patternticksaim/modctx->song.speed) ) 1099a4cd9b30SMilanka Ringwald { 1100a4cd9b30SMilanka Ringwald nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; 1101a4cd9b30SMilanka Ringwald nptr = nptr + modctx->patternpos; 1102a4cd9b30SMilanka Ringwald cptr = modctx->channels; 1103a4cd9b30SMilanka Ringwald 1104a4cd9b30SMilanka Ringwald for(c=0;c<modctx->number_of_channels;c++) 1105a4cd9b30SMilanka Ringwald { 1106a4cd9b30SMilanka Ringwald workeffect(nptr+c, cptr+c); 1107a4cd9b30SMilanka Ringwald } 1108a4cd9b30SMilanka Ringwald 1109a4cd9b30SMilanka Ringwald modctx->patterntickse = 0; 1110a4cd9b30SMilanka Ringwald } 1111a4cd9b30SMilanka Ringwald 1112a4cd9b30SMilanka Ringwald //--------------------------------------- 1113a4cd9b30SMilanka Ringwald 1114a4cd9b30SMilanka Ringwald if( trkbuf && !state_remaining_steps ) 1115a4cd9b30SMilanka Ringwald { 1116a4cd9b30SMilanka Ringwald if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) 1117a4cd9b30SMilanka Ringwald { 1118a4cd9b30SMilanka Ringwald memclear(&trkbuf->track_state_buf[trkbuf->nb_of_state],0,sizeof(tracker_state)); 1119a4cd9b30SMilanka Ringwald } 1120a4cd9b30SMilanka Ringwald } 1121a4cd9b30SMilanka Ringwald 1122a4cd9b30SMilanka Ringwald l=0; 1123a4cd9b30SMilanka Ringwald r=0; 1124a4cd9b30SMilanka Ringwald 1125a4cd9b30SMilanka Ringwald for(j =0, cptr = modctx->channels; j < modctx->number_of_channels ; j++, cptr++) 1126a4cd9b30SMilanka Ringwald { 1127a4cd9b30SMilanka Ringwald if( cptr->period != 0 ) 1128a4cd9b30SMilanka Ringwald { 1129a4cd9b30SMilanka Ringwald finalperiod = cptr->period - cptr->decalperiod - cptr->vibraperiod; 1130a4cd9b30SMilanka Ringwald if( finalperiod ) 1131a4cd9b30SMilanka Ringwald { 1132a4cd9b30SMilanka Ringwald cptr->samppos += ( (modctx->sampleticksconst<<10) / finalperiod ); 1133a4cd9b30SMilanka Ringwald } 1134a4cd9b30SMilanka Ringwald 1135a4cd9b30SMilanka Ringwald cptr->ticks++; 1136a4cd9b30SMilanka Ringwald 1137a4cd9b30SMilanka Ringwald if( cptr->replen<=2 ) 1138a4cd9b30SMilanka Ringwald { 1139a4cd9b30SMilanka Ringwald if( (cptr->samppos>>10) >= (cptr->length) ) 1140a4cd9b30SMilanka Ringwald { 1141a4cd9b30SMilanka Ringwald cptr->length = 0; 1142a4cd9b30SMilanka Ringwald cptr->reppnt = 0; 1143a4cd9b30SMilanka Ringwald 1144a4cd9b30SMilanka Ringwald if( cptr->length ) 1145a4cd9b30SMilanka Ringwald cptr->samppos = cptr->samppos % (((unsigned long)cptr->length)<<10); 1146a4cd9b30SMilanka Ringwald else 1147a4cd9b30SMilanka Ringwald cptr->samppos = 0; 1148a4cd9b30SMilanka Ringwald } 1149a4cd9b30SMilanka Ringwald } 1150a4cd9b30SMilanka Ringwald else 1151a4cd9b30SMilanka Ringwald { 1152a4cd9b30SMilanka Ringwald if( (cptr->samppos>>10) >= (unsigned long)(cptr->replen+cptr->reppnt) ) 1153a4cd9b30SMilanka Ringwald { 1154a4cd9b30SMilanka Ringwald cptr->samppos = ((unsigned long)(cptr->reppnt)<<10) + (cptr->samppos % ((unsigned long)(cptr->replen+cptr->reppnt)<<10)); 1155a4cd9b30SMilanka Ringwald } 1156a4cd9b30SMilanka Ringwald } 1157a4cd9b30SMilanka Ringwald 1158a4cd9b30SMilanka Ringwald k = cptr->samppos >> 10; 1159a4cd9b30SMilanka Ringwald 1160a4cd9b30SMilanka Ringwald if( cptr->sampdata!=0 && ( ((j&3)==1) || ((j&3)==2) ) ) 1161a4cd9b30SMilanka Ringwald { 1162a4cd9b30SMilanka Ringwald r += ( cptr->sampdata[k] * cptr->volume ); 1163a4cd9b30SMilanka Ringwald } 1164a4cd9b30SMilanka Ringwald 1165a4cd9b30SMilanka Ringwald if( cptr->sampdata!=0 && ( ((j&3)==0) || ((j&3)==3) ) ) 1166a4cd9b30SMilanka Ringwald { 1167a4cd9b30SMilanka Ringwald l += ( cptr->sampdata[k] * cptr->volume ); 1168a4cd9b30SMilanka Ringwald } 1169a4cd9b30SMilanka Ringwald 1170a4cd9b30SMilanka Ringwald if( trkbuf && !state_remaining_steps ) 1171a4cd9b30SMilanka Ringwald { 1172a4cd9b30SMilanka Ringwald if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) 1173a4cd9b30SMilanka Ringwald { 1174a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].number_of_tracks = modctx->number_of_channels; 1175a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].buf_index = i; 1176a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern = modctx->song.patterntable[modctx->tablepos]; 1177a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_pos = modctx->patternpos / modctx->number_of_channels; 1178a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_table_pos = modctx->tablepos; 1179a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].bpm = modctx->bpm; 1180a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].speed = modctx->song.speed; 1181a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_effect = cptr->effect_code; 1182a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_parameffect = cptr->parameffect; 1183a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_period = finalperiod; 1184a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_volume = cptr->volume; 1185a4cd9b30SMilanka Ringwald trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].instrument_number = (unsigned char)cptr->sampnum; 1186a4cd9b30SMilanka Ringwald } 1187a4cd9b30SMilanka Ringwald } 1188a4cd9b30SMilanka Ringwald } 1189a4cd9b30SMilanka Ringwald } 1190a4cd9b30SMilanka Ringwald 1191a4cd9b30SMilanka Ringwald if( trkbuf && !state_remaining_steps ) 1192a4cd9b30SMilanka Ringwald { 1193a4cd9b30SMilanka Ringwald state_remaining_steps = trkbuf->sample_step; 1194a4cd9b30SMilanka Ringwald 1195a4cd9b30SMilanka Ringwald if(trkbuf->nb_of_state < trkbuf->nb_max_of_state) 1196a4cd9b30SMilanka Ringwald trkbuf->nb_of_state++; 1197a4cd9b30SMilanka Ringwald } 1198a4cd9b30SMilanka Ringwald else 1199a4cd9b30SMilanka Ringwald { 1200a4cd9b30SMilanka Ringwald state_remaining_steps--; 1201a4cd9b30SMilanka Ringwald } 1202a4cd9b30SMilanka Ringwald 1203a4cd9b30SMilanka Ringwald tl = (short)l; 1204a4cd9b30SMilanka Ringwald tr = (short)r; 1205a4cd9b30SMilanka Ringwald 1206a4cd9b30SMilanka Ringwald if ( modctx->filter ) 1207a4cd9b30SMilanka Ringwald { 1208a4cd9b30SMilanka Ringwald // Filter 1209a4cd9b30SMilanka Ringwald l = (l+ll)>>1; 1210a4cd9b30SMilanka Ringwald r = (r+lr)>>1; 1211a4cd9b30SMilanka Ringwald } 1212a4cd9b30SMilanka Ringwald 1213a4cd9b30SMilanka Ringwald if ( modctx->stereo_separation == 1 ) 1214a4cd9b30SMilanka Ringwald { 1215a4cd9b30SMilanka Ringwald // Left & Right Stereo panning 1216a4cd9b30SMilanka Ringwald l = (l+(r>>1)); 1217a4cd9b30SMilanka Ringwald r = (r+(l>>1)); 1218a4cd9b30SMilanka Ringwald } 1219a4cd9b30SMilanka Ringwald 1220a4cd9b30SMilanka Ringwald // Level limitation 1221a4cd9b30SMilanka Ringwald if( l > 32767 ) l = 32767; 1222a4cd9b30SMilanka Ringwald if( l < -32768 ) l = -32768; 1223a4cd9b30SMilanka Ringwald if( r > 32767 ) r = 32767; 1224a4cd9b30SMilanka Ringwald if( r < -32768 ) r = -32768; 1225a4cd9b30SMilanka Ringwald 1226a4cd9b30SMilanka Ringwald // Store the final sample. 1227a4cd9b30SMilanka Ringwald outbuffer[(i*2)] = l; 1228a4cd9b30SMilanka Ringwald outbuffer[(i*2)+1] = r; 1229a4cd9b30SMilanka Ringwald 1230a4cd9b30SMilanka Ringwald ll = tl; 1231a4cd9b30SMilanka Ringwald lr = tr; 1232a4cd9b30SMilanka Ringwald 1233a4cd9b30SMilanka Ringwald } 1234a4cd9b30SMilanka Ringwald 1235a4cd9b30SMilanka Ringwald modctx->last_l_sample = ll; 1236a4cd9b30SMilanka Ringwald modctx->last_r_sample = lr; 1237a4cd9b30SMilanka Ringwald 1238a4cd9b30SMilanka Ringwald modctx->samplenb = modctx->samplenb+nbsample; 1239a4cd9b30SMilanka Ringwald } 1240a4cd9b30SMilanka Ringwald else 1241a4cd9b30SMilanka Ringwald { 1242a4cd9b30SMilanka Ringwald for (i = 0; i < nbsample; i++) 1243a4cd9b30SMilanka Ringwald { 1244a4cd9b30SMilanka Ringwald // Mod not loaded. Return blank buffer. 1245a4cd9b30SMilanka Ringwald outbuffer[(i*2)] = 0; 1246a4cd9b30SMilanka Ringwald outbuffer[(i*2)+1] = 0; 1247a4cd9b30SMilanka Ringwald } 1248a4cd9b30SMilanka Ringwald 1249a4cd9b30SMilanka Ringwald if(trkbuf) 1250a4cd9b30SMilanka Ringwald { 1251a4cd9b30SMilanka Ringwald trkbuf->nb_of_state = 0; 1252a4cd9b30SMilanka Ringwald trkbuf->cur_rd_index = 0; 1253a4cd9b30SMilanka Ringwald trkbuf->name[0] = 0; 1254a4cd9b30SMilanka Ringwald memclear(trkbuf->track_state_buf,0,sizeof(tracker_state) * trkbuf->nb_max_of_state); 1255a4cd9b30SMilanka Ringwald memclear(trkbuf->instruments,0,sizeof(trkbuf->instruments)); 1256a4cd9b30SMilanka Ringwald } 1257a4cd9b30SMilanka Ringwald } 1258a4cd9b30SMilanka Ringwald } 1259a4cd9b30SMilanka Ringwald } 1260a4cd9b30SMilanka Ringwald 1261a4cd9b30SMilanka Ringwald void hxcmod_unload( modcontext * modctx ) 1262a4cd9b30SMilanka Ringwald { 1263a4cd9b30SMilanka Ringwald if(modctx) 1264a4cd9b30SMilanka Ringwald { 1265a4cd9b30SMilanka Ringwald memclear(&modctx->song,0,sizeof(modctx->song)); 1266a4cd9b30SMilanka Ringwald memclear(&modctx->sampledata,0,sizeof(modctx->sampledata)); 1267a4cd9b30SMilanka Ringwald memclear(&modctx->patterndata,0,sizeof(modctx->patterndata)); 1268a4cd9b30SMilanka Ringwald modctx->tablepos = 0; 1269a4cd9b30SMilanka Ringwald modctx->patternpos = 0; 1270a4cd9b30SMilanka Ringwald modctx->patterndelay = 0; 1271a4cd9b30SMilanka Ringwald modctx->jump_loop_effect = 0; 1272a4cd9b30SMilanka Ringwald modctx->bpm = 0; 1273a4cd9b30SMilanka Ringwald modctx->patternticks = 0; 1274a4cd9b30SMilanka Ringwald modctx->patterntickse = 0; 1275a4cd9b30SMilanka Ringwald modctx->patternticksaim = 0; 1276a4cd9b30SMilanka Ringwald modctx->sampleticksconst = 0; 1277a4cd9b30SMilanka Ringwald 1278a4cd9b30SMilanka Ringwald modctx->samplenb = 0; 1279a4cd9b30SMilanka Ringwald 1280a4cd9b30SMilanka Ringwald memclear(modctx->channels,0,sizeof(modctx->channels)); 1281a4cd9b30SMilanka Ringwald 1282a4cd9b30SMilanka Ringwald modctx->number_of_channels = 0; 1283a4cd9b30SMilanka Ringwald 1284a4cd9b30SMilanka Ringwald modctx->mod_loaded = 0; 1285a4cd9b30SMilanka Ringwald 1286a4cd9b30SMilanka Ringwald modctx->last_r_sample = 0; 1287a4cd9b30SMilanka Ringwald modctx->last_l_sample = 0; 1288a4cd9b30SMilanka Ringwald } 1289a4cd9b30SMilanka Ringwald } 1290