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