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