diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-21 11:09:56 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-04-21 11:09:56 +0200 |
| commit | 123144c93bfc77883c8fb517828b47bbe13b8671 (patch) | |
| tree | 762739afedb5f3f168051367515cb9b9a06ec68d /raylib/src/external/jar_mod.h | |
| download | minesweeper-123144c93bfc77883c8fb517828b47bbe13b8671.tar.gz minesweeper-123144c93bfc77883c8fb517828b47bbe13b8671.zip | |
Diffstat (limited to 'raylib/src/external/jar_mod.h')
| -rw-r--r-- | raylib/src/external/jar_mod.h | 1596 |
1 files changed, 1596 insertions, 0 deletions
diff --git a/raylib/src/external/jar_mod.h b/raylib/src/external/jar_mod.h new file mode 100644 index 0000000..eacd3b7 --- /dev/null +++ b/raylib/src/external/jar_mod.h | |||
| @@ -0,0 +1,1596 @@ | |||
| 1 | // jar_mod.h - v0.01 - public domain C0 - Joshua Reisenauer | ||
| 2 | // | ||
| 3 | // HISTORY: | ||
| 4 | // | ||
| 5 | // v0.01 2016-03-12 Setup | ||
| 6 | // | ||
| 7 | // | ||
| 8 | // USAGE: | ||
| 9 | // | ||
| 10 | // In ONE source file, put: | ||
| 11 | // | ||
| 12 | // #define JAR_MOD_IMPLEMENTATION | ||
| 13 | // #include "jar_mod.h" | ||
| 14 | // | ||
| 15 | // Other source files should just include jar_mod.h | ||
| 16 | // | ||
| 17 | // SAMPLE CODE: | ||
| 18 | // jar_mod_context_t modctx; | ||
| 19 | // short samplebuff[4096]; | ||
| 20 | // bool bufferFull = false; | ||
| 21 | // int intro_load(void) | ||
| 22 | // { | ||
| 23 | // jar_mod_init(&modctx); | ||
| 24 | // jar_mod_load_file(&modctx, "file.mod"); | ||
| 25 | // return 1; | ||
| 26 | // } | ||
| 27 | // int intro_unload(void) | ||
| 28 | // { | ||
| 29 | // jar_mod_unload(&modctx); | ||
| 30 | // return 1; | ||
| 31 | // } | ||
| 32 | // int intro_tick(long counter) | ||
| 33 | // { | ||
| 34 | // if(!bufferFull) | ||
| 35 | // { | ||
| 36 | // jar_mod_fillbuffer(&modctx, samplebuff, 4096, 0); | ||
| 37 | // bufferFull=true; | ||
| 38 | // } | ||
| 39 | // if(IsKeyDown(KEY_ENTER)) | ||
| 40 | // return 1; | ||
| 41 | // return 0; | ||
| 42 | // } | ||
| 43 | // | ||
| 44 | // | ||
| 45 | // LISCENSE: | ||
| 46 | // | ||
| 47 | // Written by: Jean-François DEL NERO (http://hxc2001.com/) <Email : jeanfrancoisdelnero <> free.fr> | ||
| 48 | // Adapted to jar_mod by: Joshua Adam Reisenauer <kd7tck@gmail.com> | ||
| 49 | // This program is free software. It comes without any warranty, to the | ||
| 50 | // extent permitted by applicable law. You can redistribute it and/or | ||
| 51 | // modify it under the terms of the Do What The Fuck You Want To Public | ||
| 52 | // License, Version 2, as published by Sam Hocevar. See | ||
| 53 | // http://sam.zoy.org/wtfpl/COPYING for more details. | ||
| 54 | /////////////////////////////////////////////////////////////////////////////////// | ||
| 55 | // HxCMOD Core API: | ||
| 56 | // ------------------------------------------- | ||
| 57 | // int jar_mod_init(jar_mod_context_t * modctx) | ||
| 58 | // | ||
| 59 | // - Initialize the jar_mod_context_t buffer. Must be called before doing anything else. | ||
| 60 | // Return 1 if success. 0 in case of error. | ||
| 61 | // ------------------------------------------- | ||
| 62 | // mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename) | ||
| 63 | // | ||
| 64 | // - "Load" a MOD from file, context must already be initialized. | ||
| 65 | // Return size of file in bytes. | ||
| 66 | // ------------------------------------------- | ||
| 67 | // void jar_mod_fillbuffer( jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) | ||
| 68 | // | ||
| 69 | // - Generate and return the next samples chunk to outbuffer. | ||
| 70 | // nbsample specify the number of stereo 16bits samples you want. | ||
| 71 | // The output format is by default signed 48000Hz 16-bit Stereo PCM samples, otherwise it is changed with jar_mod_setcfg(). | ||
| 72 | // The output buffer size in bytes must be equal to ( nbsample * 2 * channels ). | ||
| 73 | // The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 is unused. | ||
| 74 | // ------------------------------------------- | ||
| 75 | // void jar_mod_unload( jar_mod_context_t * modctx ) | ||
| 76 | // - "Unload" / clear the player status. | ||
| 77 | // ------------------------------------------- | ||
| 78 | /////////////////////////////////////////////////////////////////////////////////// | ||
| 79 | |||
| 80 | |||
| 81 | #ifndef INCLUDE_JAR_MOD_H | ||
| 82 | #define INCLUDE_JAR_MOD_H | ||
| 83 | |||
| 84 | // Allow custom memory allocators | ||
| 85 | #ifndef JARMOD_MALLOC | ||
| 86 | #define JARMOD_MALLOC(sz) malloc(sz) | ||
| 87 | #endif | ||
| 88 | #ifndef JARMOD_FREE | ||
| 89 | #define JARMOD_FREE(p) free(p) | ||
| 90 | #endif | ||
| 91 | |||
| 92 | |||
| 93 | // Basic type | ||
| 94 | typedef unsigned char muchar; | ||
| 95 | typedef unsigned short muint; | ||
| 96 | typedef short mint; | ||
| 97 | typedef unsigned long mulong; | ||
| 98 | |||
| 99 | #define NUMMAXCHANNELS 32 | ||
| 100 | #define MAXNOTES 12*12 | ||
| 101 | #define DEFAULT_SAMPLE_RATE 48000 | ||
| 102 | // | ||
| 103 | // MOD file structures | ||
| 104 | // | ||
| 105 | |||
| 106 | #pragma pack(1) | ||
| 107 | |||
| 108 | typedef struct { | ||
| 109 | muchar name[22]; | ||
| 110 | muint length; | ||
| 111 | muchar finetune; | ||
| 112 | muchar volume; | ||
| 113 | muint reppnt; | ||
| 114 | muint replen; | ||
| 115 | } sample; | ||
| 116 | |||
| 117 | typedef struct { | ||
| 118 | muchar sampperiod; | ||
| 119 | muchar period; | ||
| 120 | muchar sampeffect; | ||
| 121 | muchar effect; | ||
| 122 | } note; | ||
| 123 | |||
| 124 | typedef struct { | ||
| 125 | muchar title[20]; | ||
| 126 | sample samples[31]; | ||
| 127 | muchar length; // length of tablepos | ||
| 128 | muchar protracker; | ||
| 129 | muchar patterntable[128]; | ||
| 130 | muchar signature[4]; | ||
| 131 | muchar speed; | ||
| 132 | } module; | ||
| 133 | |||
| 134 | #pragma pack() | ||
| 135 | |||
| 136 | // | ||
| 137 | // HxCMod Internal structures | ||
| 138 | // | ||
| 139 | typedef struct { | ||
| 140 | char* sampdata; | ||
| 141 | muint sampnum; | ||
| 142 | muint length; | ||
| 143 | muint reppnt; | ||
| 144 | muint replen; | ||
| 145 | mulong samppos; | ||
| 146 | muint period; | ||
| 147 | muchar volume; | ||
| 148 | mulong ticks; | ||
| 149 | muchar effect; | ||
| 150 | muchar parameffect; | ||
| 151 | muint effect_code; | ||
| 152 | mint decalperiod; | ||
| 153 | mint portaspeed; | ||
| 154 | mint portaperiod; | ||
| 155 | mint vibraperiod; | ||
| 156 | mint Arpperiods[3]; | ||
| 157 | muchar ArpIndex; | ||
| 158 | mint oldk; | ||
| 159 | muchar volumeslide; | ||
| 160 | muchar vibraparam; | ||
| 161 | muchar vibrapointeur; | ||
| 162 | muchar finetune; | ||
| 163 | muchar cut_param; | ||
| 164 | muint patternloopcnt; | ||
| 165 | muint patternloopstartpoint; | ||
| 166 | } channel; | ||
| 167 | |||
| 168 | typedef struct { | ||
| 169 | module song; | ||
| 170 | char* sampledata[31]; | ||
| 171 | note* patterndata[128]; | ||
| 172 | |||
| 173 | mulong playrate; | ||
| 174 | muint tablepos; | ||
| 175 | muint patternpos; | ||
| 176 | muint patterndelay; | ||
| 177 | muint jump_loop_effect; | ||
| 178 | muchar bpm; | ||
| 179 | mulong patternticks; | ||
| 180 | mulong patterntickse; | ||
| 181 | mulong patternticksaim; | ||
| 182 | mulong sampleticksconst; | ||
| 183 | mulong samplenb; | ||
| 184 | channel channels[NUMMAXCHANNELS]; | ||
| 185 | muint number_of_channels; | ||
| 186 | muint fullperiod[MAXNOTES * 8]; | ||
| 187 | muint mod_loaded; | ||
| 188 | mint last_r_sample; | ||
| 189 | mint last_l_sample; | ||
| 190 | mint stereo; | ||
| 191 | mint stereo_separation; | ||
| 192 | mint bits; | ||
| 193 | mint filter; | ||
| 194 | |||
| 195 | muchar *modfile; // the raw mod file | ||
| 196 | mulong modfilesize; | ||
| 197 | muint loopcount; | ||
| 198 | } jar_mod_context_t; | ||
| 199 | |||
| 200 | // | ||
| 201 | // Player states structures | ||
| 202 | // | ||
| 203 | typedef struct track_state_ | ||
| 204 | { | ||
| 205 | unsigned char instrument_number; | ||
| 206 | unsigned short cur_period; | ||
| 207 | unsigned char cur_volume; | ||
| 208 | unsigned short cur_effect; | ||
| 209 | unsigned short cur_parameffect; | ||
| 210 | }track_state; | ||
| 211 | |||
| 212 | typedef struct tracker_state_ | ||
| 213 | { | ||
| 214 | int number_of_tracks; | ||
| 215 | int bpm; | ||
| 216 | int speed; | ||
| 217 | int cur_pattern; | ||
| 218 | int cur_pattern_pos; | ||
| 219 | int cur_pattern_table_pos; | ||
| 220 | unsigned int buf_index; | ||
| 221 | track_state tracks[32]; | ||
| 222 | }tracker_state; | ||
| 223 | |||
| 224 | typedef struct tracker_state_instrument_ | ||
| 225 | { | ||
| 226 | char name[22]; | ||
| 227 | int active; | ||
| 228 | }tracker_state_instrument; | ||
| 229 | |||
| 230 | typedef struct jar_mod_tracker_buffer_state_ | ||
| 231 | { | ||
| 232 | int nb_max_of_state; | ||
| 233 | int nb_of_state; | ||
| 234 | int cur_rd_index; | ||
| 235 | int sample_step; | ||
| 236 | char name[64]; | ||
| 237 | tracker_state_instrument instruments[31]; | ||
| 238 | tracker_state * track_state_buf; | ||
| 239 | }jar_mod_tracker_buffer_state; | ||
| 240 | |||
| 241 | #ifdef __cplusplus | ||
| 242 | extern "C" { | ||
| 243 | #endif | ||
| 244 | |||
| 245 | bool jar_mod_init(jar_mod_context_t * modctx); | ||
| 246 | bool jar_mod_setcfg(jar_mod_context_t * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter); | ||
| 247 | void jar_mod_fillbuffer(jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf); | ||
| 248 | void jar_mod_unload(jar_mod_context_t * modctx); | ||
| 249 | mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename); | ||
| 250 | mulong jar_mod_current_samples(jar_mod_context_t * modctx); | ||
| 251 | mulong jar_mod_max_samples(jar_mod_context_t * modctx); | ||
| 252 | void jar_mod_seek_start(jar_mod_context_t * ctx); | ||
| 253 | |||
| 254 | #ifdef __cplusplus | ||
| 255 | } | ||
| 256 | #endif | ||
| 257 | //-------------------------------------------------------------------- | ||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | //------------------------------------------------------------------------------- | ||
| 262 | #ifdef JAR_MOD_IMPLEMENTATION | ||
| 263 | |||
| 264 | #include <stdio.h> | ||
| 265 | #include <stdlib.h> | ||
| 266 | //#include <stdbool.h> | ||
| 267 | |||
| 268 | // Effects list | ||
| 269 | #define EFFECT_ARPEGGIO 0x0 // Supported | ||
| 270 | #define EFFECT_PORTAMENTO_UP 0x1 // Supported | ||
| 271 | #define EFFECT_PORTAMENTO_DOWN 0x2 // Supported | ||
| 272 | #define EFFECT_TONE_PORTAMENTO 0x3 // Supported | ||
| 273 | #define EFFECT_VIBRATO 0x4 // Supported | ||
| 274 | #define EFFECT_VOLSLIDE_TONEPORTA 0x5 // Supported | ||
| 275 | #define EFFECT_VOLSLIDE_VIBRATO 0x6 // Supported | ||
| 276 | #define EFFECT_VOLSLIDE_TREMOLO 0x7 // - TO BE DONE - | ||
| 277 | #define EFFECT_SET_PANNING 0x8 // - TO BE DONE - | ||
| 278 | #define EFFECT_SET_OFFSET 0x9 // Supported | ||
| 279 | #define EFFECT_VOLUME_SLIDE 0xA // Supported | ||
| 280 | #define EFFECT_JUMP_POSITION 0xB // Supported | ||
| 281 | #define EFFECT_SET_VOLUME 0xC // Supported | ||
| 282 | #define EFFECT_PATTERN_BREAK 0xD // Supported | ||
| 283 | |||
| 284 | #define EFFECT_EXTENDED 0xE | ||
| 285 | #define EFFECT_E_FINE_PORTA_UP 0x1 // Supported | ||
| 286 | #define EFFECT_E_FINE_PORTA_DOWN 0x2 // Supported | ||
| 287 | #define EFFECT_E_GLISSANDO_CTRL 0x3 // - TO BE DONE - | ||
| 288 | #define EFFECT_E_VIBRATO_WAVEFORM 0x4 // - TO BE DONE - | ||
| 289 | #define EFFECT_E_SET_FINETUNE 0x5 // - TO BE DONE - | ||
| 290 | #define EFFECT_E_PATTERN_LOOP 0x6 // Supported | ||
| 291 | #define EFFECT_E_TREMOLO_WAVEFORM 0x7 // - TO BE DONE - | ||
| 292 | #define EFFECT_E_SET_PANNING_2 0x8 // - TO BE DONE - | ||
| 293 | #define EFFECT_E_RETRIGGER_NOTE 0x9 // - TO BE DONE - | ||
| 294 | #define EFFECT_E_FINE_VOLSLIDE_UP 0xA // Supported | ||
| 295 | #define EFFECT_E_FINE_VOLSLIDE_DOWN 0xB // Supported | ||
| 296 | #define EFFECT_E_NOTE_CUT 0xC // Supported | ||
| 297 | #define EFFECT_E_NOTE_DELAY 0xD // - TO BE DONE - | ||
| 298 | #define EFFECT_E_PATTERN_DELAY 0xE // Supported | ||
| 299 | #define EFFECT_E_INVERT_LOOP 0xF // - TO BE DONE - | ||
| 300 | #define EFFECT_SET_SPEED 0xF0 // Supported | ||
| 301 | #define EFFECT_SET_TEMPO 0xF2 // Supported | ||
| 302 | |||
| 303 | #define PERIOD_TABLE_LENGTH MAXNOTES | ||
| 304 | #define FULL_PERIOD_TABLE_LENGTH ( PERIOD_TABLE_LENGTH * 8 ) | ||
| 305 | |||
| 306 | static const short periodtable[]= | ||
| 307 | { | ||
| 308 | 27392, 25856, 24384, 23040, 21696, 20480, 19328, 18240, 17216, 16256, 15360, 14496, | ||
| 309 | 13696, 12928, 12192, 11520, 10848, 10240, 9664, 9120, 8606, 8128, 7680, 7248, | ||
| 310 | 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624, | ||
| 311 | 3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2032, 1920, 1812, | ||
| 312 | 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 906, | ||
| 313 | 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, | ||
| 314 | 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, | ||
| 315 | 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, | ||
| 316 | 107, 101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56, | ||
| 317 | 53, 50, 47, 45, 42, 40, 37, 35, 33, 31, 30, 28, | ||
| 318 | 27, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, | ||
| 319 | 13, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7 | ||
| 320 | }; | ||
| 321 | |||
| 322 | static const short sintable[]={ | ||
| 323 | 0, 24, 49, 74, 97, 120, 141,161, | ||
| 324 | 180, 197, 212, 224, 235, 244, 250,253, | ||
| 325 | 255, 253, 250, 244, 235, 224, 212,197, | ||
| 326 | 180, 161, 141, 120, 97, 74, 49, 24 | ||
| 327 | }; | ||
| 328 | |||
| 329 | typedef struct modtype_ | ||
| 330 | { | ||
| 331 | unsigned char signature[5]; | ||
| 332 | int numberofchannels; | ||
| 333 | }modtype; | ||
| 334 | |||
| 335 | modtype modlist[]= | ||
| 336 | { | ||
| 337 | { "M!K!",4}, | ||
| 338 | { "M.K.",4}, | ||
| 339 | { "FLT4",4}, | ||
| 340 | { "FLT8",8}, | ||
| 341 | { "4CHN",4}, | ||
| 342 | { "6CHN",6}, | ||
| 343 | { "8CHN",8}, | ||
| 344 | { "10CH",10}, | ||
| 345 | { "12CH",12}, | ||
| 346 | { "14CH",14}, | ||
| 347 | { "16CH",16}, | ||
| 348 | { "18CH",18}, | ||
| 349 | { "20CH",20}, | ||
| 350 | { "22CH",22}, | ||
| 351 | { "24CH",24}, | ||
| 352 | { "26CH",26}, | ||
| 353 | { "28CH",28}, | ||
| 354 | { "30CH",30}, | ||
| 355 | { "32CH",32}, | ||
| 356 | { "",0} | ||
| 357 | }; | ||
| 358 | |||
| 359 | /////////////////////////////////////////////////////////////////////////////////// | ||
| 360 | |||
| 361 | static void memcopy( void * dest, void *source, unsigned long size ) | ||
| 362 | { | ||
| 363 | unsigned long i; | ||
| 364 | unsigned char * d,*s; | ||
| 365 | |||
| 366 | d=(unsigned char*)dest; | ||
| 367 | s=(unsigned char*)source; | ||
| 368 | for(i=0;i<size;i++) | ||
| 369 | { | ||
| 370 | d[i]=s[i]; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | static void memclear( void * dest, unsigned char value, unsigned long size ) | ||
| 375 | { | ||
| 376 | unsigned long i; | ||
| 377 | unsigned char * d; | ||
| 378 | |||
| 379 | d=(unsigned char*)dest; | ||
| 380 | for(i=0;i<size;i++) | ||
| 381 | { | ||
| 382 | d[i]=value; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | static int memcompare( unsigned char * buf1, unsigned char * buf2, unsigned int size ) | ||
| 387 | { | ||
| 388 | unsigned int i; | ||
| 389 | |||
| 390 | i = 0; | ||
| 391 | |||
| 392 | while(i<size) | ||
| 393 | { | ||
| 394 | if(buf1[i] != buf2[i]) | ||
| 395 | { | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | i++; | ||
| 399 | } | ||
| 400 | |||
| 401 | return 1; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int getnote( jar_mod_context_t * mod, unsigned short period, int finetune ) | ||
| 405 | { | ||
| 406 | int i; | ||
| 407 | |||
| 408 | for(i = 0; i < FULL_PERIOD_TABLE_LENGTH; i++) | ||
| 409 | { | ||
| 410 | if(period >= mod->fullperiod[i]) | ||
| 411 | { | ||
| 412 | return i; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | return MAXNOTES; | ||
| 417 | } | ||
| 418 | |||
| 419 | static void worknote( note * nptr, channel * cptr, char t, jar_mod_context_t * mod ) | ||
| 420 | { | ||
| 421 | muint sample, period, effect, operiod; | ||
| 422 | muint curnote, arpnote; | ||
| 423 | |||
| 424 | sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4); | ||
| 425 | period = ((nptr->sampperiod & 0xF) << 8) | nptr->period; | ||
| 426 | effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect; | ||
| 427 | |||
| 428 | operiod = cptr->period; | ||
| 429 | |||
| 430 | if ( period || sample ) | ||
| 431 | { | ||
| 432 | if( sample && sample < 32 ) | ||
| 433 | { | ||
| 434 | cptr->sampnum = sample - 1; | ||
| 435 | } | ||
| 436 | |||
| 437 | if( period || sample ) | ||
| 438 | { | ||
| 439 | cptr->sampdata = (char *) mod->sampledata[cptr->sampnum]; | ||
| 440 | cptr->length = mod->song.samples[cptr->sampnum].length; | ||
| 441 | cptr->reppnt = mod->song.samples[cptr->sampnum].reppnt; | ||
| 442 | cptr->replen = mod->song.samples[cptr->sampnum].replen; | ||
| 443 | |||
| 444 | cptr->finetune = (mod->song.samples[cptr->sampnum].finetune)&0xF; | ||
| 445 | |||
| 446 | if(effect>>8!=4 && effect>>8!=6) | ||
| 447 | { | ||
| 448 | cptr->vibraperiod=0; | ||
| 449 | cptr->vibrapointeur=0; | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | if( (sample != 0) && ( (effect>>8) != EFFECT_VOLSLIDE_TONEPORTA ) ) | ||
| 454 | { | ||
| 455 | cptr->volume = mod->song.samples[cptr->sampnum].volume; | ||
| 456 | cptr->volumeslide = 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | if( ( (effect>>8) != EFFECT_TONE_PORTAMENTO && (effect>>8)!=EFFECT_VOLSLIDE_TONEPORTA) ) | ||
| 460 | { | ||
| 461 | if (period!=0) | ||
| 462 | cptr->samppos = 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | cptr->decalperiod = 0; | ||
| 466 | if( period ) | ||
| 467 | { | ||
| 468 | if(cptr->finetune) | ||
| 469 | { | ||
| 470 | if( cptr->finetune <= 7 ) | ||
| 471 | { | ||
| 472 | period = mod->fullperiod[getnote(mod,period,0) + cptr->finetune]; | ||
| 473 | } | ||
| 474 | else | ||
| 475 | { | ||
| 476 | period = mod->fullperiod[getnote(mod,period,0) - (16 - (cptr->finetune)) ]; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | cptr->period = period; | ||
| 481 | } | ||
| 482 | |||
| 483 | } | ||
| 484 | |||
| 485 | cptr->effect = 0; | ||
| 486 | cptr->parameffect = 0; | ||
| 487 | cptr->effect_code = effect; | ||
| 488 | |||
| 489 | switch (effect >> 8) | ||
| 490 | { | ||
| 491 | case EFFECT_ARPEGGIO: | ||
| 492 | /* | ||
| 493 | [0]: Arpeggio | ||
| 494 | Where [0][x][y] means "play note, note+x semitones, note+y | ||
| 495 | semitones, then return to original note". The fluctuations are | ||
| 496 | carried out evenly spaced in one pattern division. They are usually | ||
| 497 | used to simulate chords, but this doesn't work too well. They are | ||
| 498 | also used to produce heavy vibrato. A major chord is when x=4, y=7. | ||
| 499 | A minor chord is when x=3, y=7. | ||
| 500 | */ | ||
| 501 | |||
| 502 | if(effect&0xff) | ||
| 503 | { | ||
| 504 | cptr->effect = EFFECT_ARPEGGIO; | ||
| 505 | cptr->parameffect = effect&0xff; | ||
| 506 | |||
| 507 | cptr->ArpIndex = 0; | ||
| 508 | |||
| 509 | curnote = getnote(mod,cptr->period,cptr->finetune); | ||
| 510 | |||
| 511 | cptr->Arpperiods[0] = cptr->period; | ||
| 512 | |||
| 513 | arpnote = curnote + (((cptr->parameffect>>4)&0xF)*8); | ||
| 514 | if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) | ||
| 515 | arpnote = FULL_PERIOD_TABLE_LENGTH - 1; | ||
| 516 | |||
| 517 | cptr->Arpperiods[1] = mod->fullperiod[arpnote]; | ||
| 518 | |||
| 519 | arpnote = curnote + (((cptr->parameffect)&0xF)*8); | ||
| 520 | if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) | ||
| 521 | arpnote = FULL_PERIOD_TABLE_LENGTH - 1; | ||
| 522 | |||
| 523 | cptr->Arpperiods[2] = mod->fullperiod[arpnote]; | ||
| 524 | } | ||
| 525 | break; | ||
| 526 | |||
| 527 | case EFFECT_PORTAMENTO_UP: | ||
| 528 | /* | ||
| 529 | [1]: Slide up | ||
| 530 | Where [1][x][y] means "smoothly decrease the period of current | ||
| 531 | sample by x*16+y after each tick in the division". The | ||
| 532 | ticks/division are set with the 'set speed' effect (see below). If | ||
| 533 | the period of the note being played is z, then the final period | ||
| 534 | will be z - (x*16 + y)*(ticks - 1). As the slide rate depends on | ||
| 535 | the speed, changing the speed will change the slide. You cannot | ||
| 536 | slide beyond the note B3 (period 113). | ||
| 537 | */ | ||
| 538 | |||
| 539 | cptr->effect = EFFECT_PORTAMENTO_UP; | ||
| 540 | cptr->parameffect = effect&0xff; | ||
| 541 | break; | ||
| 542 | |||
| 543 | case EFFECT_PORTAMENTO_DOWN: | ||
| 544 | /* | ||
| 545 | [2]: Slide down | ||
| 546 | Where [2][x][y] means "smoothly increase the period of current | ||
| 547 | sample by x*16+y after each tick in the division". Similar to [1], | ||
| 548 | but lowers the pitch. You cannot slide beyond the note C1 (period | ||
| 549 | 856). | ||
| 550 | */ | ||
| 551 | |||
| 552 | cptr->effect = EFFECT_PORTAMENTO_DOWN; | ||
| 553 | cptr->parameffect = effect&0xff; | ||
| 554 | break; | ||
| 555 | |||
| 556 | case EFFECT_TONE_PORTAMENTO: | ||
| 557 | /* | ||
| 558 | [3]: Slide to note | ||
| 559 | Where [3][x][y] means "smoothly change the period of current sample | ||
| 560 | by x*16+y after each tick in the division, never sliding beyond | ||
| 561 | current period". The period-length in this channel's division is a | ||
| 562 | parameter to this effect, and hence is not played. Sliding to a | ||
| 563 | note is similar to effects [1] and [2], but the slide will not go | ||
| 564 | beyond the given period, and the direction is implied by that | ||
| 565 | period. If x and y are both 0, then the old slide will continue. | ||
| 566 | */ | ||
| 567 | |||
| 568 | cptr->effect = EFFECT_TONE_PORTAMENTO; | ||
| 569 | if( (effect&0xff) != 0 ) | ||
| 570 | { | ||
| 571 | cptr->portaspeed = (short)(effect&0xff); | ||
| 572 | } | ||
| 573 | |||
| 574 | if(period!=0) | ||
| 575 | { | ||
| 576 | cptr->portaperiod = period; | ||
| 577 | cptr->period = operiod; | ||
| 578 | } | ||
| 579 | break; | ||
| 580 | |||
| 581 | case EFFECT_VIBRATO: | ||
| 582 | /* | ||
| 583 | [4]: Vibrato | ||
| 584 | Where [4][x][y] means "oscillate the sample pitch using a | ||
| 585 | particular waveform with amplitude y/16 semitones, such that (x * | ||
| 586 | ticks)/64 cycles occur in the division". The waveform is set using | ||
| 587 | effect [14][4]. By placing vibrato effects on consecutive | ||
| 588 | divisions, the vibrato effect can be maintained. If either x or y | ||
| 589 | are 0, then the old vibrato values will be used. | ||
| 590 | */ | ||
| 591 | |||
| 592 | cptr->effect = EFFECT_VIBRATO; | ||
| 593 | if( ( effect & 0x0F ) != 0 ) // Depth continue or change ? | ||
| 594 | cptr->vibraparam = (cptr->vibraparam & 0xF0) | ( effect & 0x0F ); | ||
| 595 | if( ( effect & 0xF0 ) != 0 ) // Speed continue or change ? | ||
| 596 | cptr->vibraparam = (cptr->vibraparam & 0x0F) | ( effect & 0xF0 ); | ||
| 597 | |||
| 598 | break; | ||
| 599 | |||
| 600 | case EFFECT_VOLSLIDE_TONEPORTA: | ||
| 601 | /* | ||
| 602 | [5]: Continue 'Slide to note', but also do Volume slide | ||
| 603 | Where [5][x][y] means "either slide the volume up x*(ticks - 1) or | ||
| 604 | slide the volume down y*(ticks - 1), at the same time as continuing | ||
| 605 | the last 'Slide to note'". It is illegal for both x and y to be | ||
| 606 | non-zero. You cannot slide outside the volume range 0..64. The | ||
| 607 | period-length in this channel's division is a parameter to this | ||
| 608 | effect, and hence is not played. | ||
| 609 | */ | ||
| 610 | |||
| 611 | if( period != 0 ) | ||
| 612 | { | ||
| 613 | cptr->portaperiod = period; | ||
| 614 | cptr->period = operiod; | ||
| 615 | } | ||
| 616 | |||
| 617 | cptr->effect = EFFECT_VOLSLIDE_TONEPORTA; | ||
| 618 | if( ( effect & 0xFF ) != 0 ) | ||
| 619 | cptr->volumeslide = ( effect & 0xFF ); | ||
| 620 | |||
| 621 | break; | ||
| 622 | |||
| 623 | case EFFECT_VOLSLIDE_VIBRATO: | ||
| 624 | /* | ||
| 625 | [6]: Continue 'Vibrato', but also do Volume slide | ||
| 626 | Where [6][x][y] means "either slide the volume up x*(ticks - 1) or | ||
| 627 | slide the volume down y*(ticks - 1), at the same time as continuing | ||
| 628 | the last 'Vibrato'". It is illegal for both x and y to be non-zero. | ||
| 629 | You cannot slide outside the volume range 0..64. | ||
| 630 | */ | ||
| 631 | |||
| 632 | cptr->effect = EFFECT_VOLSLIDE_VIBRATO; | ||
| 633 | if( (effect & 0xFF) != 0 ) | ||
| 634 | cptr->volumeslide = (effect & 0xFF); | ||
| 635 | break; | ||
| 636 | |||
| 637 | case EFFECT_SET_OFFSET: | ||
| 638 | /* | ||
| 639 | [9]: Set sample offset | ||
| 640 | Where [9][x][y] means "play the sample from offset x*4096 + y*256". | ||
| 641 | The offset is measured in words. If no sample is given, yet one is | ||
| 642 | still playing on this channel, it should be retriggered to the new | ||
| 643 | offset using the current volume. | ||
| 644 | */ | ||
| 645 | |||
| 646 | cptr->samppos = ((effect>>4) * 4096) + ((effect&0xF)*256); | ||
| 647 | |||
| 648 | break; | ||
| 649 | |||
| 650 | case EFFECT_VOLUME_SLIDE: | ||
| 651 | /* | ||
| 652 | [10]: Volume slide | ||
| 653 | Where [10][x][y] means "either slide the volume up x*(ticks - 1) or | ||
| 654 | slide the volume down y*(ticks - 1)". If both x and y are non-zero, | ||
| 655 | then the y value is ignored (assumed to be 0). You cannot slide | ||
| 656 | outside the volume range 0..64. | ||
| 657 | */ | ||
| 658 | |||
| 659 | cptr->effect = EFFECT_VOLUME_SLIDE; | ||
| 660 | cptr->volumeslide = (effect & 0xFF); | ||
| 661 | break; | ||
| 662 | |||
| 663 | case EFFECT_JUMP_POSITION: | ||
| 664 | /* | ||
| 665 | [11]: Position Jump | ||
| 666 | Where [11][x][y] means "stop the pattern after this division, and | ||
| 667 | continue the song at song-position x*16+y". This shifts the | ||
| 668 | 'pattern-cursor' in the pattern table (see above). Legal values for | ||
| 669 | x*16+y are from 0 to 127. | ||
| 670 | */ | ||
| 671 | |||
| 672 | mod->tablepos = (effect & 0xFF); | ||
| 673 | if(mod->tablepos >= mod->song.length) | ||
| 674 | { | ||
| 675 | mod->tablepos = 0; | ||
| 676 | } | ||
| 677 | mod->patternpos = 0; | ||
| 678 | mod->jump_loop_effect = 1; | ||
| 679 | |||
| 680 | break; | ||
| 681 | |||
| 682 | case EFFECT_SET_VOLUME: | ||
| 683 | /* | ||
| 684 | [12]: Set volume | ||
| 685 | Where [12][x][y] means "set current sample's volume to x*16+y". | ||
| 686 | Legal volumes are 0..64. | ||
| 687 | */ | ||
| 688 | |||
| 689 | cptr->volume = (effect & 0xFF); | ||
| 690 | break; | ||
| 691 | |||
| 692 | case EFFECT_PATTERN_BREAK: | ||
| 693 | /* | ||
| 694 | [13]: Pattern Break | ||
| 695 | Where [13][x][y] means "stop the pattern after this division, and | ||
| 696 | continue the song at the next pattern at division x*10+y" (the 10 | ||
| 697 | is not a typo). Legal divisions are from 0 to 63 (note Protracker | ||
| 698 | exception above). | ||
| 699 | */ | ||
| 700 | |||
| 701 | mod->patternpos = ( ((effect>>4)&0xF)*10 + (effect&0xF) ) * mod->number_of_channels; | ||
| 702 | mod->jump_loop_effect = 1; | ||
| 703 | mod->tablepos++; | ||
| 704 | if(mod->tablepos >= mod->song.length) | ||
| 705 | { | ||
| 706 | mod->tablepos = 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | break; | ||
| 710 | |||
| 711 | case EFFECT_EXTENDED: | ||
| 712 | switch( (effect>>4) & 0xF ) | ||
| 713 | { | ||
| 714 | case EFFECT_E_FINE_PORTA_UP: | ||
| 715 | /* | ||
| 716 | [14][1]: Fineslide up | ||
| 717 | Where [14][1][x] means "decrement the period of the current sample | ||
| 718 | by x". The incrementing takes place at the beginning of the | ||
| 719 | division, and hence there is no actual sliding. You cannot slide | ||
| 720 | beyond the note B3 (period 113). | ||
| 721 | */ | ||
| 722 | |||
| 723 | cptr->period -= (effect & 0xF); | ||
| 724 | if( cptr->period < 113 ) | ||
| 725 | cptr->period = 113; | ||
| 726 | break; | ||
| 727 | |||
| 728 | case EFFECT_E_FINE_PORTA_DOWN: | ||
| 729 | /* | ||
| 730 | [14][2]: Fineslide down | ||
| 731 | Where [14][2][x] means "increment the period of the current sample | ||
| 732 | by x". Similar to [14][1] but shifts the pitch down. You cannot | ||
| 733 | slide beyond the note C1 (period 856). | ||
| 734 | */ | ||
| 735 | |||
| 736 | cptr->period += (effect & 0xF); | ||
| 737 | if( cptr->period > 856 ) | ||
| 738 | cptr->period = 856; | ||
| 739 | break; | ||
| 740 | |||
| 741 | case EFFECT_E_FINE_VOLSLIDE_UP: | ||
| 742 | /* | ||
| 743 | [14][10]: Fine volume slide up | ||
| 744 | Where [14][10][x] means "increment the volume of the current sample | ||
| 745 | by x". The incrementing takes place at the beginning of the | ||
| 746 | division, and hence there is no sliding. You cannot slide beyond | ||
| 747 | volume 64. | ||
| 748 | */ | ||
| 749 | |||
| 750 | cptr->volume += (effect & 0xF); | ||
| 751 | if( cptr->volume>64 ) | ||
| 752 | cptr->volume = 64; | ||
| 753 | break; | ||
| 754 | |||
| 755 | case EFFECT_E_FINE_VOLSLIDE_DOWN: | ||
| 756 | /* | ||
| 757 | [14][11]: Fine volume slide down | ||
| 758 | Where [14][11][x] means "decrement the volume of the current sample | ||
| 759 | by x". Similar to [14][10] but lowers volume. You cannot slide | ||
| 760 | beyond volume 0. | ||
| 761 | */ | ||
| 762 | |||
| 763 | cptr->volume -= (effect & 0xF); | ||
| 764 | if( cptr->volume > 200 ) | ||
| 765 | cptr->volume = 0; | ||
| 766 | break; | ||
| 767 | |||
| 768 | case EFFECT_E_PATTERN_LOOP: | ||
| 769 | /* | ||
| 770 | [14][6]: Loop pattern | ||
| 771 | Where [14][6][x] means "set the start of a loop to this division if | ||
| 772 | x is 0, otherwise after this division, jump back to the start of a | ||
| 773 | loop and play it another x times before continuing". If the start | ||
| 774 | of the loop was not set, it will default to the start of the | ||
| 775 | current pattern. Hence 'loop pattern' cannot be performed across | ||
| 776 | multiple patterns. Note that loops do not support nesting, and you | ||
| 777 | may generate an infinite loop if you try to nest 'loop pattern's. | ||
| 778 | */ | ||
| 779 | |||
| 780 | if( effect & 0xF ) | ||
| 781 | { | ||
| 782 | if( cptr->patternloopcnt ) | ||
| 783 | { | ||
| 784 | cptr->patternloopcnt--; | ||
| 785 | if( cptr->patternloopcnt ) | ||
| 786 | { | ||
| 787 | mod->patternpos = cptr->patternloopstartpoint; | ||
| 788 | mod->jump_loop_effect = 1; | ||
| 789 | } | ||
| 790 | else | ||
| 791 | { | ||
| 792 | cptr->patternloopstartpoint = mod->patternpos ; | ||
| 793 | } | ||
| 794 | } | ||
| 795 | else | ||
| 796 | { | ||
| 797 | cptr->patternloopcnt = (effect & 0xF); | ||
| 798 | mod->patternpos = cptr->patternloopstartpoint; | ||
| 799 | mod->jump_loop_effect = 1; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | else // Start point | ||
| 803 | { | ||
| 804 | cptr->patternloopstartpoint = mod->patternpos; | ||
| 805 | } | ||
| 806 | |||
| 807 | break; | ||
| 808 | |||
| 809 | case EFFECT_E_PATTERN_DELAY: | ||
| 810 | /* | ||
| 811 | [14][14]: Delay pattern | ||
| 812 | Where [14][14][x] means "after this division there will be a delay | ||
| 813 | equivalent to the time taken to play x divisions after which the | ||
| 814 | pattern will be resumed". The delay only relates to the | ||
| 815 | interpreting of new divisions, and all effects and previous notes | ||
| 816 | continue during delay. | ||
| 817 | */ | ||
| 818 | |||
| 819 | mod->patterndelay = (effect & 0xF); | ||
| 820 | break; | ||
| 821 | |||
| 822 | case EFFECT_E_NOTE_CUT: | ||
| 823 | /* | ||
| 824 | [14][12]: Cut sample | ||
| 825 | Where [14][12][x] means "after the current sample has been played | ||
| 826 | for x ticks in this division, its volume will be set to 0". This | ||
| 827 | implies that if x is 0, then you will not hear any of the sample. | ||
| 828 | If you wish to insert "silence" in a pattern, it is better to use a | ||
| 829 | "silence"-sample (see above) due to the lack of proper support for | ||
| 830 | this effect. | ||
| 831 | */ | ||
| 832 | cptr->effect = EFFECT_E_NOTE_CUT; | ||
| 833 | cptr->cut_param = (effect & 0xF); | ||
| 834 | if(!cptr->cut_param) | ||
| 835 | cptr->volume = 0; | ||
| 836 | break; | ||
| 837 | |||
| 838 | default: | ||
| 839 | |||
| 840 | break; | ||
| 841 | } | ||
| 842 | break; | ||
| 843 | |||
| 844 | case 0xF: | ||
| 845 | /* | ||
| 846 | [15]: Set speed | ||
| 847 | Where [15][x][y] means "set speed to x*16+y". Though it is nowhere | ||
| 848 | near that simple. Let z = x*16+y. Depending on what values z takes, | ||
| 849 | different units of speed are set, there being two: ticks/division | ||
| 850 | and beats/minute (though this one is only a label and not strictly | ||
| 851 | true). If z=0, then what should technically happen is that the | ||
| 852 | module stops, but in practice it is treated as if z=1, because | ||
| 853 | there is already a method for stopping the module (running out of | ||
| 854 | patterns). If z<=32, then it means "set ticks/division to z" | ||
| 855 | otherwise it means "set beats/minute to z" (convention says that | ||
| 856 | this should read "If z<32.." but there are some composers out there | ||
| 857 | that defy conventions). Default values are 6 ticks/division, and | ||
| 858 | 125 beats/minute (4 divisions = 1 beat). The beats/minute tag is | ||
| 859 | only meaningful for 6 ticks/division. To get a more accurate view | ||
| 860 | of how things work, use the following formula: | ||
| 861 | 24 * beats/minute | ||
| 862 | divisions/minute = ----------------- | ||
| 863 | ticks/division | ||
| 864 | Hence divisions/minute range from 24.75 to 6120, eg. to get a value | ||
| 865 | of 2000 divisions/minute use 3 ticks/division and 250 beats/minute. | ||
| 866 | If multiple "set speed" effects are performed in a single division, | ||
| 867 | the ones on higher-numbered channels take precedence over the ones | ||
| 868 | on lower-numbered channels. This effect has a large number of | ||
| 869 | different implementations, but the one described here has the | ||
| 870 | widest usage. | ||
| 871 | */ | ||
| 872 | |||
| 873 | if( (effect&0xFF) < 0x21 ) | ||
| 874 | { | ||
| 875 | if( effect&0xFF ) | ||
| 876 | { | ||
| 877 | mod->song.speed = effect&0xFF; | ||
| 878 | mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 882 | if( (effect&0xFF) >= 0x21 ) | ||
| 883 | { | ||
| 884 | /// HZ = 2 * BPM / 5 | ||
| 885 | mod->bpm = effect&0xFF; | ||
| 886 | mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); | ||
| 887 | } | ||
| 888 | |||
| 889 | break; | ||
| 890 | |||
| 891 | default: | ||
| 892 | // Unsupported effect | ||
| 893 | break; | ||
| 894 | |||
| 895 | } | ||
| 896 | |||
| 897 | } | ||
| 898 | |||
| 899 | static void workeffect( note * nptr, channel * cptr ) | ||
| 900 | { | ||
| 901 | switch(cptr->effect) | ||
| 902 | { | ||
| 903 | case EFFECT_ARPEGGIO: | ||
| 904 | |||
| 905 | if( cptr->parameffect ) | ||
| 906 | { | ||
| 907 | cptr->decalperiod = cptr->period - cptr->Arpperiods[cptr->ArpIndex]; | ||
| 908 | |||
| 909 | cptr->ArpIndex++; | ||
| 910 | if( cptr->ArpIndex>2 ) | ||
| 911 | cptr->ArpIndex = 0; | ||
| 912 | } | ||
| 913 | break; | ||
| 914 | |||
| 915 | case EFFECT_PORTAMENTO_UP: | ||
| 916 | |||
| 917 | if(cptr->period) | ||
| 918 | { | ||
| 919 | cptr->period -= cptr->parameffect; | ||
| 920 | |||
| 921 | if( cptr->period < 113 || cptr->period > 20000 ) | ||
| 922 | cptr->period = 113; | ||
| 923 | } | ||
| 924 | |||
| 925 | break; | ||
| 926 | |||
| 927 | case EFFECT_PORTAMENTO_DOWN: | ||
| 928 | |||
| 929 | if(cptr->period) | ||
| 930 | { | ||
| 931 | cptr->period += cptr->parameffect; | ||
| 932 | |||
| 933 | if( cptr->period > 20000 ) | ||
| 934 | cptr->period = 20000; | ||
| 935 | } | ||
| 936 | |||
| 937 | break; | ||
| 938 | |||
| 939 | case EFFECT_VOLSLIDE_TONEPORTA: | ||
| 940 | case EFFECT_TONE_PORTAMENTO: | ||
| 941 | |||
| 942 | if( cptr->period && ( cptr->period != cptr->portaperiod ) && cptr->portaperiod ) | ||
| 943 | { | ||
| 944 | if( cptr->period > cptr->portaperiod ) | ||
| 945 | { | ||
| 946 | if( cptr->period - cptr->portaperiod >= cptr->portaspeed ) | ||
| 947 | { | ||
| 948 | cptr->period -= cptr->portaspeed; | ||
| 949 | } | ||
| 950 | else | ||
| 951 | { | ||
| 952 | cptr->period = cptr->portaperiod; | ||
| 953 | } | ||
| 954 | } | ||
| 955 | else | ||
| 956 | { | ||
| 957 | if( cptr->portaperiod - cptr->period >= cptr->portaspeed ) | ||
| 958 | { | ||
| 959 | cptr->period += cptr->portaspeed; | ||
| 960 | } | ||
| 961 | else | ||
| 962 | { | ||
| 963 | cptr->period = cptr->portaperiod; | ||
| 964 | } | ||
| 965 | } | ||
| 966 | |||
| 967 | if( cptr->period == cptr->portaperiod ) | ||
| 968 | { | ||
| 969 | // If the slide is over, don't let it to be retriggered. | ||
| 970 | cptr->portaperiod = 0; | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | if( cptr->effect == EFFECT_VOLSLIDE_TONEPORTA ) | ||
| 975 | { | ||
| 976 | if( cptr->volumeslide > 0x0F ) | ||
| 977 | { | ||
| 978 | cptr->volume = cptr->volume + (cptr->volumeslide>>4); | ||
| 979 | |||
| 980 | if(cptr->volume>63) | ||
| 981 | cptr->volume = 63; | ||
| 982 | } | ||
| 983 | else | ||
| 984 | { | ||
| 985 | cptr->volume = cptr->volume - (cptr->volumeslide); | ||
| 986 | |||
| 987 | if(cptr->volume>63) | ||
| 988 | cptr->volume=0; | ||
| 989 | } | ||
| 990 | } | ||
| 991 | break; | ||
| 992 | |||
| 993 | case EFFECT_VOLSLIDE_VIBRATO: | ||
| 994 | case EFFECT_VIBRATO: | ||
| 995 | |||
| 996 | cptr->vibraperiod = ( (cptr->vibraparam&0xF) * sintable[cptr->vibrapointeur&0x1F] )>>7; | ||
| 997 | |||
| 998 | if( cptr->vibrapointeur > 31 ) | ||
| 999 | cptr->vibraperiod = -cptr->vibraperiod; | ||
| 1000 | |||
| 1001 | cptr->vibrapointeur = (cptr->vibrapointeur+(((cptr->vibraparam>>4))&0xf)) & 0x3F; | ||
| 1002 | |||
| 1003 | if( cptr->effect == EFFECT_VOLSLIDE_VIBRATO ) | ||
| 1004 | { | ||
| 1005 | if( cptr->volumeslide > 0xF ) | ||
| 1006 | { | ||
| 1007 | cptr->volume = cptr->volume+(cptr->volumeslide>>4); | ||
| 1008 | |||
| 1009 | if( cptr->volume > 64 ) | ||
| 1010 | cptr->volume = 64; | ||
| 1011 | } | ||
| 1012 | else | ||
| 1013 | { | ||
| 1014 | cptr->volume = cptr->volume - cptr->volumeslide; | ||
| 1015 | |||
| 1016 | if( cptr->volume > 64 ) | ||
| 1017 | cptr->volume = 0; | ||
| 1018 | } | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | break; | ||
| 1022 | |||
| 1023 | case EFFECT_VOLUME_SLIDE: | ||
| 1024 | |||
| 1025 | if( cptr->volumeslide > 0xF ) | ||
| 1026 | { | ||
| 1027 | cptr->volume += (cptr->volumeslide>>4); | ||
| 1028 | |||
| 1029 | if( cptr->volume > 64 ) | ||
| 1030 | cptr->volume = 64; | ||
| 1031 | } | ||
| 1032 | else | ||
| 1033 | { | ||
| 1034 | cptr->volume -= (cptr->volumeslide&0xf); | ||
| 1035 | |||
| 1036 | if( cptr->volume > 64 ) | ||
| 1037 | cptr->volume = 0; | ||
| 1038 | } | ||
| 1039 | break; | ||
| 1040 | |||
| 1041 | case EFFECT_E_NOTE_CUT: | ||
| 1042 | if(cptr->cut_param) | ||
| 1043 | cptr->cut_param--; | ||
| 1044 | |||
| 1045 | if(!cptr->cut_param) | ||
| 1046 | cptr->volume = 0; | ||
| 1047 | break; | ||
| 1048 | |||
| 1049 | default: | ||
| 1050 | break; | ||
| 1051 | |||
| 1052 | } | ||
| 1053 | |||
| 1054 | } | ||
| 1055 | |||
| 1056 | /////////////////////////////////////////////////////////////////////////////////// | ||
| 1057 | bool jar_mod_init(jar_mod_context_t * modctx) | ||
| 1058 | { | ||
| 1059 | muint i,j; | ||
| 1060 | |||
| 1061 | if( modctx ) | ||
| 1062 | { | ||
| 1063 | memclear(modctx, 0, sizeof(jar_mod_context_t)); | ||
| 1064 | modctx->playrate = DEFAULT_SAMPLE_RATE; | ||
| 1065 | modctx->stereo = 1; | ||
| 1066 | modctx->stereo_separation = 1; | ||
| 1067 | modctx->bits = 16; | ||
| 1068 | modctx->filter = 1; | ||
| 1069 | |||
| 1070 | for(i=0; i < PERIOD_TABLE_LENGTH - 1; i++) | ||
| 1071 | { | ||
| 1072 | for(j=0; j < 8; j++) | ||
| 1073 | { | ||
| 1074 | modctx->fullperiod[(i*8) + j] = periodtable[i] - ((( periodtable[i] - periodtable[i+1] ) / 8) * j); | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | return 1; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | return 0; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | bool jar_mod_setcfg(jar_mod_context_t * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter) | ||
| 1085 | { | ||
| 1086 | if( modctx ) | ||
| 1087 | { | ||
| 1088 | modctx->playrate = samplerate; | ||
| 1089 | |||
| 1090 | if( stereo ) | ||
| 1091 | modctx->stereo = 1; | ||
| 1092 | else | ||
| 1093 | modctx->stereo = 0; | ||
| 1094 | |||
| 1095 | if(stereo_separation < 4) | ||
| 1096 | { | ||
| 1097 | modctx->stereo_separation = stereo_separation; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | if( bits == 8 || bits == 16 ) | ||
| 1101 | modctx->bits = bits; | ||
| 1102 | else | ||
| 1103 | modctx->bits = 16; | ||
| 1104 | |||
| 1105 | if( filter ) | ||
| 1106 | modctx->filter = 1; | ||
| 1107 | else | ||
| 1108 | modctx->filter = 0; | ||
| 1109 | |||
| 1110 | return 1; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | return 0; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | // make certain that mod_data stays in memory while playing | ||
| 1117 | static bool jar_mod_load( jar_mod_context_t * modctx, void * mod_data, int mod_data_size ) | ||
| 1118 | { | ||
| 1119 | muint i, max; | ||
| 1120 | unsigned short t; | ||
| 1121 | sample *sptr; | ||
| 1122 | unsigned char * modmemory,* endmodmemory; | ||
| 1123 | |||
| 1124 | modmemory = (unsigned char *)mod_data; | ||
| 1125 | endmodmemory = modmemory + mod_data_size; | ||
| 1126 | |||
| 1127 | |||
| 1128 | |||
| 1129 | if(modmemory) | ||
| 1130 | { | ||
| 1131 | if( modctx ) | ||
| 1132 | { | ||
| 1133 | memcopy(&(modctx->song.title),modmemory,1084); | ||
| 1134 | |||
| 1135 | i = 0; | ||
| 1136 | modctx->number_of_channels = 0; | ||
| 1137 | while(modlist[i].numberofchannels) | ||
| 1138 | { | ||
| 1139 | if(memcompare(modctx->song.signature,modlist[i].signature,4)) | ||
| 1140 | { | ||
| 1141 | modctx->number_of_channels = modlist[i].numberofchannels; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | i++; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | if( !modctx->number_of_channels ) | ||
| 1148 | { | ||
| 1149 | // 15 Samples modules support | ||
| 1150 | // Shift the whole datas to make it look likes a standard 4 channels mod. | ||
| 1151 | memcopy(&(modctx->song.signature), "M.K.", 4); | ||
| 1152 | memcopy(&(modctx->song.length), &(modctx->song.samples[15]), 130); | ||
| 1153 | memclear(&(modctx->song.samples[15]), 0, 480); | ||
| 1154 | modmemory += 600; | ||
| 1155 | modctx->number_of_channels = 4; | ||
| 1156 | } | ||
| 1157 | else | ||
| 1158 | { | ||
| 1159 | modmemory += 1084; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | if( modmemory >= endmodmemory ) | ||
| 1163 | return 0; // End passed ? - Probably a bad file ! | ||
| 1164 | |||
| 1165 | // Patterns loading | ||
| 1166 | for (i = max = 0; i < 128; i++) | ||
| 1167 | { | ||
| 1168 | while (max <= modctx->song.patterntable[i]) | ||
| 1169 | { | ||
| 1170 | modctx->patterndata[max] = (note*)modmemory; | ||
| 1171 | modmemory += (256*modctx->number_of_channels); | ||
| 1172 | max++; | ||
| 1173 | |||
| 1174 | if( modmemory >= endmodmemory ) | ||
| 1175 | return 0; // End passed ? - Probably a bad file ! | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | for (i = 0; i < 31; i++) | ||
| 1180 | modctx->sampledata[i]=0; | ||
| 1181 | |||
| 1182 | // Samples loading | ||
| 1183 | for (i = 0, sptr = modctx->song.samples; i <31; i++, sptr++) | ||
| 1184 | { | ||
| 1185 | t= (sptr->length &0xFF00)>>8 | (sptr->length &0xFF)<<8; | ||
| 1186 | sptr->length = t*2; | ||
| 1187 | |||
| 1188 | t= (sptr->reppnt &0xFF00)>>8 | (sptr->reppnt &0xFF)<<8; | ||
| 1189 | sptr->reppnt = t*2; | ||
| 1190 | |||
| 1191 | t= (sptr->replen &0xFF00)>>8 | (sptr->replen &0xFF)<<8; | ||
| 1192 | sptr->replen = t*2; | ||
| 1193 | |||
| 1194 | |||
| 1195 | if (sptr->length == 0) continue; | ||
| 1196 | |||
| 1197 | modctx->sampledata[i] = (char*)modmemory; | ||
| 1198 | modmemory += sptr->length; | ||
| 1199 | |||
| 1200 | if (sptr->replen + sptr->reppnt > sptr->length) | ||
| 1201 | sptr->replen = sptr->length - sptr->reppnt; | ||
| 1202 | |||
| 1203 | if( modmemory > endmodmemory ) | ||
| 1204 | return 0; // End passed ? - Probably a bad file ! | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | // States init | ||
| 1208 | |||
| 1209 | modctx->tablepos = 0; | ||
| 1210 | modctx->patternpos = 0; | ||
| 1211 | modctx->song.speed = 6; | ||
| 1212 | modctx->bpm = 125; | ||
| 1213 | modctx->samplenb = 0; | ||
| 1214 | |||
| 1215 | modctx->patternticks = (((long)modctx->song.speed * modctx->playrate * 5)/ (2 * modctx->bpm)) + 1; | ||
| 1216 | modctx->patternticksaim = ((long)modctx->song.speed * modctx->playrate * 5) / (2 * modctx->bpm); | ||
| 1217 | |||
| 1218 | modctx->sampleticksconst = 3546894UL / modctx->playrate; //8448*428/playrate; | ||
| 1219 | |||
| 1220 | for(i=0; i < modctx->number_of_channels; i++) | ||
| 1221 | { | ||
| 1222 | modctx->channels[i].volume = 0; | ||
| 1223 | modctx->channels[i].period = 0; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | modctx->mod_loaded = 1; | ||
| 1227 | |||
| 1228 | return 1; | ||
| 1229 | } | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | return 0; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | void jar_mod_fillbuffer( jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) | ||
| 1236 | { | ||
| 1237 | unsigned long i, j; | ||
| 1238 | unsigned long k; | ||
| 1239 | unsigned char c; | ||
| 1240 | unsigned int state_remaining_steps; | ||
| 1241 | int l,r; | ||
| 1242 | int ll,lr; | ||
| 1243 | int tl,tr; | ||
| 1244 | short finalperiod; | ||
| 1245 | note *nptr; | ||
| 1246 | channel *cptr; | ||
| 1247 | |||
| 1248 | if( modctx && outbuffer ) | ||
| 1249 | { | ||
| 1250 | if(modctx->mod_loaded) | ||
| 1251 | { | ||
| 1252 | state_remaining_steps = 0; | ||
| 1253 | |||
| 1254 | if( trkbuf ) | ||
| 1255 | { | ||
| 1256 | trkbuf->cur_rd_index = 0; | ||
| 1257 | |||
| 1258 | memcopy(trkbuf->name,modctx->song.title,sizeof(modctx->song.title)); | ||
| 1259 | |||
| 1260 | for(i=0;i<31;i++) | ||
| 1261 | { | ||
| 1262 | memcopy(trkbuf->instruments[i].name,modctx->song.samples[i].name,sizeof(trkbuf->instruments[i].name)); | ||
| 1263 | } | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | ll = modctx->last_l_sample; | ||
| 1267 | lr = modctx->last_r_sample; | ||
| 1268 | |||
| 1269 | for (i = 0; i < nbsample; i++) | ||
| 1270 | { | ||
| 1271 | //--------------------------------------- | ||
| 1272 | if( modctx->patternticks++ > modctx->patternticksaim ) | ||
| 1273 | { | ||
| 1274 | if( !modctx->patterndelay ) | ||
| 1275 | { | ||
| 1276 | nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; | ||
| 1277 | nptr = nptr + modctx->patternpos; | ||
| 1278 | cptr = modctx->channels; | ||
| 1279 | |||
| 1280 | modctx->patternticks = 0; | ||
| 1281 | modctx->patterntickse = 0; | ||
| 1282 | |||
| 1283 | for(c=0;c<modctx->number_of_channels;c++) | ||
| 1284 | { | ||
| 1285 | worknote((note*)(nptr+c), (channel*)(cptr+c),(char)(c+1),modctx); | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | if( !modctx->jump_loop_effect ) | ||
| 1289 | modctx->patternpos += modctx->number_of_channels; | ||
| 1290 | else | ||
| 1291 | modctx->jump_loop_effect = 0; | ||
| 1292 | |||
| 1293 | if( modctx->patternpos == 64*modctx->number_of_channels ) | ||
| 1294 | { | ||
| 1295 | modctx->tablepos++; | ||
| 1296 | modctx->patternpos = 0; | ||
| 1297 | if(modctx->tablepos >= modctx->song.length) | ||
| 1298 | { | ||
| 1299 | modctx->tablepos = 0; | ||
| 1300 | modctx->loopcount++; // count next loop | ||
| 1301 | } | ||
| 1302 | } | ||
| 1303 | } | ||
| 1304 | else | ||
| 1305 | { | ||
| 1306 | modctx->patterndelay--; | ||
| 1307 | modctx->patternticks = 0; | ||
| 1308 | modctx->patterntickse = 0; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | } | ||
| 1312 | |||
| 1313 | if( modctx->patterntickse++ > (modctx->patternticksaim/modctx->song.speed) ) | ||
| 1314 | { | ||
| 1315 | nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; | ||
| 1316 | nptr = nptr + modctx->patternpos; | ||
| 1317 | cptr = modctx->channels; | ||
| 1318 | |||
| 1319 | for(c=0;c<modctx->number_of_channels;c++) | ||
| 1320 | { | ||
| 1321 | workeffect(nptr+c, cptr+c); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | modctx->patterntickse = 0; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | //--------------------------------------- | ||
| 1328 | |||
| 1329 | if( trkbuf && !state_remaining_steps ) | ||
| 1330 | { | ||
| 1331 | if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) | ||
| 1332 | { | ||
| 1333 | memclear(&trkbuf->track_state_buf[trkbuf->nb_of_state], 0, sizeof(tracker_state)); | ||
| 1334 | } | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | l=0; | ||
| 1338 | r=0; | ||
| 1339 | |||
| 1340 | for(j =0, cptr = modctx->channels; j < modctx->number_of_channels ; j++, cptr++) | ||
| 1341 | { | ||
| 1342 | if( cptr->period != 0 ) | ||
| 1343 | { | ||
| 1344 | finalperiod = cptr->period - cptr->decalperiod - cptr->vibraperiod; | ||
| 1345 | if( finalperiod ) | ||
| 1346 | { | ||
| 1347 | cptr->samppos += ( (modctx->sampleticksconst<<10) / finalperiod ); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | cptr->ticks++; | ||
| 1351 | |||
| 1352 | if( cptr->replen<=2 ) | ||
| 1353 | { | ||
| 1354 | if( (cptr->samppos>>10) >= (cptr->length) ) | ||
| 1355 | { | ||
| 1356 | cptr->length = 0; | ||
| 1357 | cptr->reppnt = 0; | ||
| 1358 | |||
| 1359 | if( cptr->length ) | ||
| 1360 | cptr->samppos = cptr->samppos % (((unsigned long)cptr->length)<<10); | ||
| 1361 | else | ||
| 1362 | cptr->samppos = 0; | ||
| 1363 | } | ||
| 1364 | } | ||
| 1365 | else | ||
| 1366 | { | ||
| 1367 | if( (cptr->samppos>>10) >= (unsigned long)(cptr->replen+cptr->reppnt) ) | ||
| 1368 | { | ||
| 1369 | cptr->samppos = ((unsigned long)(cptr->reppnt)<<10) + (cptr->samppos % ((unsigned long)(cptr->replen+cptr->reppnt)<<10)); | ||
| 1370 | } | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | k = cptr->samppos >> 10; | ||
| 1374 | |||
| 1375 | if( cptr->sampdata!=0 && ( ((j&3)==1) || ((j&3)==2) ) ) | ||
| 1376 | { | ||
| 1377 | r += ( cptr->sampdata[k] * cptr->volume ); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | if( cptr->sampdata!=0 && ( ((j&3)==0) || ((j&3)==3) ) ) | ||
| 1381 | { | ||
| 1382 | l += ( cptr->sampdata[k] * cptr->volume ); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | if( trkbuf && !state_remaining_steps ) | ||
| 1386 | { | ||
| 1387 | if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) | ||
| 1388 | { | ||
| 1389 | trkbuf->track_state_buf[trkbuf->nb_of_state].number_of_tracks = modctx->number_of_channels; | ||
| 1390 | trkbuf->track_state_buf[trkbuf->nb_of_state].buf_index = i; | ||
| 1391 | trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern = modctx->song.patterntable[modctx->tablepos]; | ||
| 1392 | trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_pos = modctx->patternpos / modctx->number_of_channels; | ||
| 1393 | trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_table_pos = modctx->tablepos; | ||
| 1394 | trkbuf->track_state_buf[trkbuf->nb_of_state].bpm = modctx->bpm; | ||
| 1395 | trkbuf->track_state_buf[trkbuf->nb_of_state].speed = modctx->song.speed; | ||
| 1396 | trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_effect = cptr->effect_code; | ||
| 1397 | trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_parameffect = cptr->parameffect; | ||
| 1398 | trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_period = finalperiod; | ||
| 1399 | trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_volume = cptr->volume; | ||
| 1400 | trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].instrument_number = (unsigned char)cptr->sampnum; | ||
| 1401 | } | ||
| 1402 | } | ||
| 1403 | } | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | if( trkbuf && !state_remaining_steps ) | ||
| 1407 | { | ||
| 1408 | state_remaining_steps = trkbuf->sample_step; | ||
| 1409 | |||
| 1410 | if(trkbuf->nb_of_state < trkbuf->nb_max_of_state) | ||
| 1411 | trkbuf->nb_of_state++; | ||
| 1412 | } | ||
| 1413 | else | ||
| 1414 | { | ||
| 1415 | state_remaining_steps--; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | tl = (short)l; | ||
| 1419 | tr = (short)r; | ||
| 1420 | |||
| 1421 | if ( modctx->filter ) | ||
| 1422 | { | ||
| 1423 | // Filter | ||
| 1424 | l = (l+ll)>>1; | ||
| 1425 | r = (r+lr)>>1; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | if ( modctx->stereo_separation == 1 ) | ||
| 1429 | { | ||
| 1430 | // Left & Right Stereo panning | ||
| 1431 | l = (l+(r>>1)); | ||
| 1432 | r = (r+(l>>1)); | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | // Level limitation | ||
| 1436 | if( l > 32767 ) l = 32767; | ||
| 1437 | if( l < -32768 ) l = -32768; | ||
| 1438 | if( r > 32767 ) r = 32767; | ||
| 1439 | if( r < -32768 ) r = -32768; | ||
| 1440 | |||
| 1441 | // Store the final sample. | ||
| 1442 | outbuffer[(i*2)] = l; | ||
| 1443 | outbuffer[(i*2)+1] = r; | ||
| 1444 | |||
| 1445 | ll = tl; | ||
| 1446 | lr = tr; | ||
| 1447 | |||
| 1448 | } | ||
| 1449 | |||
| 1450 | modctx->last_l_sample = ll; | ||
| 1451 | modctx->last_r_sample = lr; | ||
| 1452 | |||
| 1453 | modctx->samplenb = modctx->samplenb+nbsample; | ||
| 1454 | } | ||
| 1455 | else | ||
| 1456 | { | ||
| 1457 | for (i = 0; i < nbsample; i++) | ||
| 1458 | { | ||
| 1459 | // Mod not loaded. Return blank buffer. | ||
| 1460 | outbuffer[(i*2)] = 0; | ||
| 1461 | outbuffer[(i*2)+1] = 0; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | if(trkbuf) | ||
| 1465 | { | ||
| 1466 | trkbuf->nb_of_state = 0; | ||
| 1467 | trkbuf->cur_rd_index = 0; | ||
| 1468 | trkbuf->name[0] = 0; | ||
| 1469 | memclear(trkbuf->track_state_buf, 0, sizeof(tracker_state) * trkbuf->nb_max_of_state); | ||
| 1470 | memclear(trkbuf->instruments, 0, sizeof(trkbuf->instruments)); | ||
| 1471 | } | ||
| 1472 | } | ||
| 1473 | } | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | //resets internals for mod context | ||
| 1477 | static bool jar_mod_reset( jar_mod_context_t * modctx) | ||
| 1478 | { | ||
| 1479 | if(modctx) | ||
| 1480 | { | ||
| 1481 | memclear(&modctx->song, 0, sizeof(modctx->song)); | ||
| 1482 | memclear(&modctx->sampledata, 0, sizeof(modctx->sampledata)); | ||
| 1483 | memclear(&modctx->patterndata, 0, sizeof(modctx->patterndata)); | ||
| 1484 | modctx->tablepos = 0; | ||
| 1485 | modctx->patternpos = 0; | ||
| 1486 | modctx->patterndelay = 0; | ||
| 1487 | modctx->jump_loop_effect = 0; | ||
| 1488 | modctx->bpm = 0; | ||
| 1489 | modctx->patternticks = 0; | ||
| 1490 | modctx->patterntickse = 0; | ||
| 1491 | modctx->patternticksaim = 0; | ||
| 1492 | modctx->sampleticksconst = 0; | ||
| 1493 | modctx->samplenb = 0; | ||
| 1494 | memclear(modctx->channels, 0, sizeof(modctx->channels)); | ||
| 1495 | modctx->number_of_channels = 0; | ||
| 1496 | modctx->mod_loaded = 0; | ||
| 1497 | modctx->last_r_sample = 0; | ||
| 1498 | modctx->last_l_sample = 0; | ||
| 1499 | |||
| 1500 | return jar_mod_init(modctx); | ||
| 1501 | } | ||
| 1502 | return 0; | ||
| 1503 | } | ||
| 1504 | |||
| 1505 | void jar_mod_unload( jar_mod_context_t * modctx) | ||
| 1506 | { | ||
| 1507 | if(modctx) | ||
| 1508 | { | ||
| 1509 | if(modctx->modfile) | ||
| 1510 | { | ||
| 1511 | JARMOD_FREE(modctx->modfile); | ||
| 1512 | modctx->modfile = 0; | ||
| 1513 | modctx->modfilesize = 0; | ||
| 1514 | modctx->loopcount = 0; | ||
| 1515 | } | ||
| 1516 | jar_mod_reset(modctx); | ||
| 1517 | } | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename) | ||
| 1521 | { | ||
| 1522 | mulong fsize = 0; | ||
| 1523 | if(modctx->modfile) | ||
| 1524 | { | ||
| 1525 | JARMOD_FREE(modctx->modfile); | ||
| 1526 | modctx->modfile = 0; | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | FILE *f = fopen(filename, "rb"); | ||
| 1530 | if(f) | ||
| 1531 | { | ||
| 1532 | fseek(f,0,SEEK_END); | ||
| 1533 | fsize = ftell(f); | ||
| 1534 | fseek(f,0,SEEK_SET); | ||
| 1535 | |||
| 1536 | if(fsize && fsize < 32*1024*1024) | ||
| 1537 | { | ||
| 1538 | modctx->modfile = JARMOD_MALLOC(fsize); | ||
| 1539 | modctx->modfilesize = fsize; | ||
| 1540 | memset(modctx->modfile, 0, fsize); | ||
| 1541 | fread(modctx->modfile, fsize, 1, f); | ||
| 1542 | fclose(f); | ||
| 1543 | |||
| 1544 | if(!jar_mod_load(modctx, (void*)modctx->modfile, fsize)) fsize = 0; | ||
| 1545 | } else fsize = 0; | ||
| 1546 | } | ||
| 1547 | return fsize; | ||
| 1548 | } | ||
| 1549 | |||
| 1550 | mulong jar_mod_current_samples(jar_mod_context_t * modctx) | ||
| 1551 | { | ||
| 1552 | if(modctx) | ||
| 1553 | return modctx->samplenb; | ||
| 1554 | |||
| 1555 | return 0; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | // Works, however it is very slow, this data should be cached to ensure it is run only once per file | ||
| 1559 | mulong jar_mod_max_samples(jar_mod_context_t * ctx) | ||
| 1560 | { | ||
| 1561 | mint buff[2]; | ||
| 1562 | mulong len; | ||
| 1563 | mulong lastcount = ctx->loopcount; | ||
| 1564 | |||
| 1565 | while(ctx->loopcount <= lastcount) | ||
| 1566 | jar_mod_fillbuffer(ctx, buff, 1, 0); | ||
| 1567 | |||
| 1568 | len = ctx->samplenb; | ||
| 1569 | jar_mod_seek_start(ctx); | ||
| 1570 | |||
| 1571 | return len; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | // move seek_val to sample index, 0 -> jar_mod_max_samples is the range | ||
| 1575 | void jar_mod_seek_start(jar_mod_context_t * ctx) | ||
| 1576 | { | ||
| 1577 | if(ctx && ctx->modfile) | ||
| 1578 | { | ||
| 1579 | muchar* ftmp = ctx->modfile; | ||
| 1580 | mulong stmp = ctx->modfilesize; | ||
| 1581 | muint lcnt = ctx->loopcount; | ||
| 1582 | |||
| 1583 | if(jar_mod_reset(ctx)){ | ||
| 1584 | jar_mod_load(ctx, ftmp, stmp); | ||
| 1585 | ctx->modfile = ftmp; | ||
| 1586 | ctx->modfilesize = stmp; | ||
| 1587 | ctx->loopcount = lcnt; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | #endif // end of JAR_MOD_IMPLEMENTATION | ||
| 1593 | //------------------------------------------------------------------------------- | ||
| 1594 | |||
| 1595 | |||
| 1596 | #endif //end of header file \ No newline at end of file | ||
