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
94typedef unsigned char muchar;
95typedef unsigned short muint;
96typedef short mint;
97typedef 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
108typedef struct {
109 muchar name[22];
110 muint length;
111 muchar finetune;
112 muchar volume;
113 muint reppnt;
114 muint replen;
115} sample;
116
117typedef struct {
118 muchar sampperiod;
119 muchar period;
120 muchar sampeffect;
121 muchar effect;
122} note;
123
124typedef 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//
139typedef 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
168typedef 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//
203typedef 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
212typedef 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
224typedef struct tracker_state_instrument_
225{
226 char name[22];
227 int active;
228}tracker_state_instrument;
229
230typedef 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
242extern "C" {
243#endif
244
245bool jar_mod_init(jar_mod_context_t * modctx);
246bool jar_mod_setcfg(jar_mod_context_t * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter);
247void jar_mod_fillbuffer(jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf);
248void jar_mod_unload(jar_mod_context_t * modctx);
249mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename);
250mulong jar_mod_current_samples(jar_mod_context_t * modctx);
251mulong jar_mod_max_samples(jar_mod_context_t * modctx);
252void 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
306static 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
322static 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
329typedef struct modtype_
330{
331 unsigned char signature[5];
332 int numberofchannels;
333}modtype;
334
335modtype 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
361static 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
374static 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
386static 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
404static 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
419static 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
899static 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///////////////////////////////////////////////////////////////////////////////////
1057bool 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
1084bool 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
1117static 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
1235void 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
1477static 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
1505void 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
1520mulong 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
1550mulong 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
1559mulong 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
1575void 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