Wise&mystical  1.0
Project about Europe
Loading...
Searching...
No Matches
jar_xm.h
Go to the documentation of this file.
1// jar_xm.h
2//
3// ORIGINAL LICENSE - FOR LIBXM:
4//
5// Author: Romain "Artefact2" Dalmaso <artefact2@gmail.com>
6// Contributor: Dan Spencer <dan@atomicpotato.net>
7// Repackaged into jar_xm.h By: Joshua Adam Reisenauer <kd7tck@gmail.com>
8// This program is free software. It comes without any warranty, to the
9// extent permitted by applicable law. You can redistribute it and/or
10// modify it under the terms of the Do What The Fuck You Want To Public
11// License, Version 2, as published by Sam Hocevar. See
12// http://sam.zoy.org/wtfpl/COPYING for more details.
13//
14// HISTORY:
15// v0.1.0 2016-02-22 jar_xm.h - development by Joshua Reisenauer, MAR 2016
16// v0.2.1 2021-03-07 m4ntr0n1c: Fix clipping noise for "bad" xm's (they will always clip), avoid clip noise and just put a ceiling)
17// v0.2.2 2021-03-09 m4ntr0n1c: Add complete debug solution (raylib.h must be included)
18// v0.2.3 2021-03-11 m4ntr0n1c: Fix tempo, bpm and volume on song stop / start / restart / loop
19// v0.2.4 2021-03-17 m4ntr0n1c: Sanitize code for readability
20// v0.2.5 2021-03-22 m4ntr0n1c: Minor adjustments
21// v0.2.6 2021-04-01 m4ntr0n1c: Minor fixes and optimisation
22// v0.3.0 2021-04-03 m4ntr0n1c: Addition of Stereo sample support, Linear Interpolation and Ramping now addressable options in code
23// v0.3.1 2021-04-04 m4ntr0n1c: Volume effects column adjustments, sample offset handling adjustments
24//
25// USAGE:
26//
27// In ONE source file, put:
28//
29// #define JAR_XM_IMPLEMENTATION
30// #include "jar_xm.h"
31//
32// Other source files should just include jar_xm.h
33//
34// SAMPLE CODE:
35//
36// jar_xm_context_t *musicptr;
37// float musicBuffer[48000 / 60];
38// int intro_load(void)
39// {
40// jar_xm_create_context_from_file(&musicptr, 48000, "Song.XM");
41// return 1;
42// }
43// int intro_unload(void)
44// {
45// jar_xm_free_context(musicptr);
46// return 1;
47// }
48// int intro_tick(long counter)
49// {
50// jar_xm_generate_samples(musicptr, musicBuffer, (48000 / 60) / 2);
51// if(IsKeyDown(KEY_ENTER))
52// return 1;
53// return 0;
54// }
55//
56#ifndef INCLUDE_JAR_XM_H
57#define INCLUDE_JAR_XM_H
58
59#include <stdint.h>
60
61#define JAR_XM_DEBUG 0
62#define JAR_XM_DEFENSIVE 1
63//#define JAR_XM_RAYLIB 0 // set to 0 to disable the RayLib visualizer extension
64
65// Allow custom memory allocators
66#ifndef JARXM_MALLOC
67 #define JARXM_MALLOC(sz) malloc(sz)
68#endif
69#ifndef JARXM_FREE
70 #define JARXM_FREE(p) free(p)
71#endif
72
73//-------------------------------------------------------------------------------
74struct jar_xm_context_s;
75typedef struct jar_xm_context_s jar_xm_context_t;
76
77#ifdef __cplusplus
78extern "C" {
79#endif
80
81//** Create a XM context.
82// * @param moddata the contents of the module
83// * @param rate play rate in Hz, recommended value of 48000
84// * @returns 0 on success
85// * @returns 1 if module data is not sane
86// * @returns 2 if memory allocation failed
87// * @returns 3 unable to open input file
88// * @returns 4 fseek() failed
89// * @returns 5 fread() failed
90// * @returns 6 unkown error
91// * @deprecated This function is unsafe!
92// * @see jar_xm_create_context_safe()
93int jar_xm_create_context_from_file(jar_xm_context_t** ctx, uint32_t rate, const char* filename);
94
95//** Create a XM context.
96// * @param moddata the contents of the module
97// * @param rate play rate in Hz, recommended value of 48000
98// * @returns 0 on success
99// * @returns 1 if module data is not sane
100// * @returns 2 if memory allocation failed
101// * @deprecated This function is unsafe!
102// * @see jar_xm_create_context_safe()
103int jar_xm_create_context(jar_xm_context_t** ctx, const char* moddata, uint32_t rate);
104
105//** Create a XM context.
106// * @param moddata the contents of the module
107// * @param moddata_length the length of the contents of the module, in bytes
108// * @param rate play rate in Hz, recommended value of 48000
109// * @returns 0 on success
110// * @returns 1 if module data is not sane
111// * @returns 2 if memory allocation failed
112int jar_xm_create_context_safe(jar_xm_context_t** ctx, const char* moddata, size_t moddata_length, uint32_t rate);
113
114//** Free a XM context created by jar_xm_create_context(). */
116
117//** Play the module and put the sound samples in an output buffer.
118// * @param output buffer of 2*numsamples elements (A left and right value for each sample)
119// * @param numsamples number of samples to generate
120void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsamples);
121
122//** Play the module, resample from float to 16 bit, and put the sound samples in an output buffer.
123// * @param output buffer of 2*numsamples elements (A left and right value for each sample)
124// * @param numsamples number of samples to generate
125void jar_xm_generate_samples_16bit(jar_xm_context_t* ctx, short* output, size_t numsamples) {
126 float* musicBuffer = JARXM_MALLOC((2*numsamples)*sizeof(float));
127 jar_xm_generate_samples(ctx, musicBuffer, numsamples);
128
129 if(output){
130 for(int x=0;x<2*numsamples;x++) output[x] = (musicBuffer[x] * 32767.0f); // scale sample to signed small int
131 }
132 JARXM_FREE(musicBuffer);
133}
134
135//** Play the module, resample from float to 8 bit, and put the sound samples in an output buffer.
136// * @param output buffer of 2*numsamples elements (A left and right value for each sample)
137// * @param numsamples number of samples to generate
138void jar_xm_generate_samples_8bit(jar_xm_context_t* ctx, char* output, size_t numsamples) {
139 float* musicBuffer = JARXM_MALLOC((2*numsamples)*sizeof(float));
140 jar_xm_generate_samples(ctx, musicBuffer, numsamples);
141
142 if(output){
143 for(int x=0;x<2*numsamples;x++) output[x] = (musicBuffer[x] * 127.0f); // scale sample to signed 8 bit
144 }
145 JARXM_FREE(musicBuffer);
146}
147
148//** Set the maximum number of times a module can loop. After the specified number of loops, calls to jar_xm_generate_samples will only generate silence. You can control the current number of loops with jar_xm_get_loop_count().
149// * @param loopcnt maximum number of loops. Use 0 to loop indefinitely.
151
152//** Get the loop count of the currently playing module. This value is 0 when the module is still playing, 1 when the module has looped once, etc.
154
155//** Mute or unmute a channel.
156// * @note Channel numbers go from 1 to jar_xm_get_number_of_channels(...).
157// * @return whether the channel was muted.
159
160//** Mute or unmute an instrument.
161// * @note Instrument numbers go from 1 to jar_xm_get_number_of_instruments(...).
162// * @return whether the instrument was muted.
164
165//** Get the module name as a NUL-terminated string.
167
168//** Get the tracker name as a NUL-terminated string.
170
171//** Get the number of channels.
173
174//** Get the module length (in patterns).
176
177//** Get the number of patterns.
179
180//** Get the number of rows of a pattern.
181// * @note Pattern numbers go from 0 to jar_xm_get_number_of_patterns(...)-1.
183
184//** Get the number of instruments.
186
187//** Get the number of samples of an instrument.
188// * @note Instrument numbers go from 1 to jar_xm_get_number_of_instruments(...).
190
191//** Get the current module speed.
192// * @param bpm will receive the current BPM
193// * @param tempo will receive the current tempo (ticks per line)
195
196//** Get the current position in the module being played.
197// * @param pattern_index if not NULL, will receive the current pattern index in the POT (pattern order table)
198// * @param pattern if not NULL, will receive the current pattern number
199// * @param row if not NULL, will receive the current row
200// * @param samples if not NULL, will receive the total number of
201// * generated samples (divide by sample rate to get seconds of generated audio)
202void jar_xm_get_position(jar_xm_context_t* ctx, uint8_t* pattern_index, uint8_t* pattern, uint8_t* row, uint64_t* samples);
203
204//** Get the latest time (in number of generated samples) when a particular instrument was triggered in any channel.
205// * @note Instrument numbers go from 1 to jar_xm_get_number_of_instruments(...).
207
208//** Get the latest time (in number of generated samples) when a particular sample was triggered in any channel.
209// * @note Instrument numbers go from 1 to jar_xm_get_number_of_instruments(...).
210// * @note Sample numbers go from 0 to jar_xm_get_nubmer_of_samples(...,instr)-1.
212
213//** Get the latest time (in number of generated samples) when any instrument was triggered in a given channel.
214// * @note Channel numbers go from 1 to jar_xm_get_number_of_channels(...).
216
217//** Get the number of remaining samples. Divide by 2 to get the number of individual LR data samples.
218// * @note This is the remaining number of samples before the loop starts module again, or halts if on last pass.
219// * @note This function is very slow and should only be run once, if at all.
221
222#ifdef __cplusplus
223}
224#endif
225//-------------------------------------------------------------------------------
226
227#ifdef JAR_XM_IMPLEMENTATION
228
229#include <math.h>
230#include <stdio.h>
231#include <stdlib.h>
232#include <limits.h>
233#include <string.h>
234
235#if JAR_XM_DEBUG //JAR_XM_DEBUG defined as 0
236#include <stdio.h>
237#define DEBUG(fmt, ...) do { \
238 fprintf(stderr, "%s(): " fmt "\n", __func__, __VA_ARGS__); \
239 fflush(stderr); \
240 } while(0)
241#else
242#define DEBUG(...)
243#endif
244
245#if jar_xm_BIG_ENDIAN
246#error "Big endian platforms are not yet supported, sorry"
247/* Make sure the compiler stops, even if #error is ignored */
248extern int __fail[-1];
249#endif
250
251/* ----- XM constants ----- */
252#define SAMPLE_NAME_LENGTH 22
253#define INSTRUMENT_NAME_LENGTH 22
254#define MODULE_NAME_LENGTH 20
255#define TRACKER_NAME_LENGTH 20
256#define PATTERN_ORDER_TABLE_LENGTH 256
257#define NUM_NOTES 96 // from 1 to 96, where 1 = C-0
258#define NUM_ENVELOPE_POINTS 12 // to be verified if 12 is the max
259#define MAX_NUM_ROWS 256
260
261#define jar_xm_SAMPLE_RAMPING_POINTS 8
262
263/* ----- Data types ----- */
264
265enum jar_xm_waveform_type_e {
266 jar_xm_SINE_WAVEFORM = 0,
267 jar_xm_RAMP_DOWN_WAVEFORM = 1,
268 jar_xm_SQUARE_WAVEFORM = 2,
269 jar_xm_RANDOM_WAVEFORM = 3,
270 jar_xm_RAMP_UP_WAVEFORM = 4,
271};
272typedef enum jar_xm_waveform_type_e jar_xm_waveform_type_t;
273
274enum jar_xm_loop_type_e {
275 jar_xm_NO_LOOP,
276 jar_xm_FORWARD_LOOP,
277 jar_xm_PING_PONG_LOOP,
278};
279typedef enum jar_xm_loop_type_e jar_xm_loop_type_t;
280
281enum jar_xm_frequency_type_e {
282 jar_xm_LINEAR_FREQUENCIES,
283 jar_xm_AMIGA_FREQUENCIES,
284};
285typedef enum jar_xm_frequency_type_e jar_xm_frequency_type_t;
286
287struct jar_xm_envelope_point_s {
288 uint16_t frame;
289 uint16_t value;
290};
291typedef struct jar_xm_envelope_point_s jar_xm_envelope_point_t;
292
293struct jar_xm_envelope_s {
294 jar_xm_envelope_point_t points[NUM_ENVELOPE_POINTS];
295 uint8_t num_points;
296 uint8_t sustain_point;
297 uint8_t loop_start_point;
298 uint8_t loop_end_point;
299 bool enabled;
300 bool sustain_enabled;
301 bool loop_enabled;
302};
303typedef struct jar_xm_envelope_s jar_xm_envelope_t;
304
305struct jar_xm_sample_s {
306 char name[SAMPLE_NAME_LENGTH + 1];
307 int8_t bits; /* Either 8 or 16 */
308 int8_t stereo;
309 uint32_t length;
310 uint32_t loop_start;
311 uint32_t loop_length;
312 uint32_t loop_end;
313 float volume;
314 int8_t finetune;
315 jar_xm_loop_type_t loop_type;
316 float panning;
317 int8_t relative_note;
318 uint64_t latest_trigger;
319
320 float* data;
321 };
322 typedef struct jar_xm_sample_s jar_xm_sample_t;
323
324 struct jar_xm_instrument_s {
325 char name[INSTRUMENT_NAME_LENGTH + 1];
326 uint16_t num_samples;
327 uint8_t sample_of_notes[NUM_NOTES];
328 jar_xm_envelope_t volume_envelope;
329 jar_xm_envelope_t panning_envelope;
330 jar_xm_waveform_type_t vibrato_type;
331 uint8_t vibrato_sweep;
332 uint8_t vibrato_depth;
333 uint8_t vibrato_rate;
334 uint16_t volume_fadeout;
335 uint64_t latest_trigger;
336 bool muted;
337
338 jar_xm_sample_t* samples;
339 };
340 typedef struct jar_xm_instrument_s jar_xm_instrument_t;
341
342 struct jar_xm_pattern_slot_s {
343 uint8_t note; /* 1-96, 97 = Key Off note */
344 uint8_t instrument; /* 1-128 */
345 uint8_t volume_column;
346 uint8_t effect_type;
347 uint8_t effect_param;
348 };
349 typedef struct jar_xm_pattern_slot_s jar_xm_pattern_slot_t;
350
351 struct jar_xm_pattern_s {
352 uint16_t num_rows;
353 jar_xm_pattern_slot_t* slots; /* Array of size num_rows * num_channels */
354 };
355 typedef struct jar_xm_pattern_s jar_xm_pattern_t;
356
357 struct jar_xm_module_s {
358 char name[MODULE_NAME_LENGTH + 1];
359 char trackername[TRACKER_NAME_LENGTH + 1];
360 uint16_t length;
361 uint16_t restart_position;
362 uint16_t num_channels;
363 uint16_t num_patterns;
364 uint16_t num_instruments;
365 uint16_t linear_interpolation;
366 uint16_t ramping;
367 jar_xm_frequency_type_t frequency_type;
368 uint8_t pattern_table[PATTERN_ORDER_TABLE_LENGTH];
369
370 jar_xm_pattern_t* patterns;
371 jar_xm_instrument_t* instruments; /* Instrument 1 has index 0, instrument 2 has index 1, etc. */
372 };
373 typedef struct jar_xm_module_s jar_xm_module_t;
374
375 struct jar_xm_channel_context_s {
376 float note;
377 float orig_note; /* The original note before effect modifications, as read in the pattern. */
378 jar_xm_instrument_t* instrument; /* Could be NULL */
379 jar_xm_sample_t* sample; /* Could be NULL */
380 jar_xm_pattern_slot_t* current;
381
382 float sample_position;
383 float period;
384 float frequency;
385 float step;
386 bool ping; /* For ping-pong samples: true is -->, false is <-- */
387
388 float volume; /* Ideally between 0 (muted) and 1 (loudest) */
389 float panning; /* Between 0 (left) and 1 (right); 0.5 is centered */
390
391 uint16_t autovibrato_ticks;
392
393 bool sustained;
394 float fadeout_volume;
395 float volume_envelope_volume;
396 float panning_envelope_panning;
397 uint16_t volume_envelope_frame_count;
398 uint16_t panning_envelope_frame_count;
399
400 float autovibrato_note_offset;
401
402 bool arp_in_progress;
403 uint8_t arp_note_offset;
404 uint8_t volume_slide_param;
405 uint8_t fine_volume_slide_param;
406 uint8_t global_volume_slide_param;
407 uint8_t panning_slide_param;
408 uint8_t portamento_up_param;
409 uint8_t portamento_down_param;
410 uint8_t fine_portamento_up_param;
411 uint8_t fine_portamento_down_param;
412 uint8_t extra_fine_portamento_up_param;
413 uint8_t extra_fine_portamento_down_param;
414 uint8_t tone_portamento_param;
415 float tone_portamento_target_period;
416 uint8_t multi_retrig_param;
417 uint8_t note_delay_param;
418 uint8_t pattern_loop_origin; /* Where to restart a E6y loop */
419 uint8_t pattern_loop_count; /* How many loop passes have been done */
420 bool vibrato_in_progress;
421 jar_xm_waveform_type_t vibrato_waveform;
422 bool vibrato_waveform_retrigger; /* True if a new note retriggers the waveform */
423 uint8_t vibrato_param;
424 uint16_t vibrato_ticks; /* Position in the waveform */
425 float vibrato_note_offset;
426 jar_xm_waveform_type_t tremolo_waveform;
427 bool tremolo_waveform_retrigger;
428 uint8_t tremolo_param;
429 uint8_t tremolo_ticks;
430 float tremolo_volume;
431 uint8_t tremor_param;
432 bool tremor_on;
433
434 uint64_t latest_trigger;
435 bool muted;
436
437 //* These values are updated at the end of each tick, to save a couple of float operations on every generated sample.
438 float target_panning;
439 float target_volume;
440
441 unsigned long frame_count;
442 float end_of_previous_sample_left[jar_xm_SAMPLE_RAMPING_POINTS];
443 float end_of_previous_sample_right[jar_xm_SAMPLE_RAMPING_POINTS];
444 float curr_left;
445 float curr_right;
446
447 float actual_panning;
448 float actual_volume;
449 };
450 typedef struct jar_xm_channel_context_s jar_xm_channel_context_t;
451
452 struct jar_xm_context_s {
453 void* allocated_memory;
454 jar_xm_module_t module;
455 uint32_t rate;
456
457 uint16_t default_tempo; // Number of ticks per row
458 uint16_t default_bpm;
459 float default_global_volume;
460
461 uint16_t tempo; // Number of ticks per row
462 uint16_t bpm;
463 float global_volume;
464
465 float volume_ramp; /* How much is a channel final volume allowed to change per sample; this is used to avoid abrubt volume changes which manifest as "clicks" in the generated sound. */
466 float panning_ramp; /* Same for panning. */
467
468 uint8_t current_table_index;
469 uint8_t current_row;
470 uint16_t current_tick; /* Can go below 255, with high tempo and a pattern delay */
471 float remaining_samples_in_tick;
472 uint64_t generated_samples;
473
474 bool position_jump;
475 bool pattern_break;
476 uint8_t jump_dest;
477 uint8_t jump_row;
478
479 uint16_t extra_ticks; /* Extra ticks to be played before going to the next row - Used for EEy effect */
480
481 uint8_t* row_loop_count; /* Array of size MAX_NUM_ROWS * module_length */
482 uint8_t loop_count;
483 uint8_t max_loop_count;
484
485 jar_xm_channel_context_t* channels;
486};
487
488#if JAR_XM_DEFENSIVE
489
490//** Check the module data for errors/inconsistencies.
491// * @returns 0 if everything looks OK. Module should be safe to load.
492int jar_xm_check_sanity_preload(const char*, size_t);
493
494//** Check a loaded module for errors/inconsistencies.
495// * @returns 0 if everything looks OK.
496int jar_xm_check_sanity_postload(jar_xm_context_t*);
497
498#endif
499
500//** Get the number of bytes needed to store the module data in a dynamically allocated blank context.
501// * Things that are dynamically allocated:
502// * - sample data
503// * - sample structures in instruments
504// * - pattern data
505// * - row loop count arrays
506// * - pattern structures in module
507// * - instrument structures in module
508// * - channel contexts
509// * - context structure itself
510// * @returns 0 if everything looks OK.
511size_t jar_xm_get_memory_needed_for_context(const char*, size_t);
512
513//** Populate the context from module data.
514// * @returns pointer to the memory pool
515char* jar_xm_load_module(jar_xm_context_t*, const char*, size_t, char*);
516
517int jar_xm_create_context(jar_xm_context_t** ctxp, const char* moddata, uint32_t rate) {
518 return jar_xm_create_context_safe(ctxp, moddata, SIZE_MAX, rate);
519}
520
521#define ALIGN(x, b) (((x) + ((b) - 1)) & ~((b) - 1))
522#define ALIGN_PTR(x, b) (void*)(((uintptr_t)(x) + ((b) - 1)) & ~((b) - 1))
523int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) {
524#if JAR_XM_DEFENSIVE
525 int ret;
526#endif
527 size_t bytes_needed;
528 char* mempool;
529 jar_xm_context_t* ctx;
530
531#if JAR_XM_DEFENSIVE
532 if((ret = jar_xm_check_sanity_preload(moddata, moddata_length))) {
533 DEBUG("jar_xm_check_sanity_preload() returned %i, module is not safe to load", ret);
534 return 1;
535 }
536#endif
537
538 bytes_needed = jar_xm_get_memory_needed_for_context(moddata, moddata_length);
539 mempool = JARXM_MALLOC(bytes_needed);
540 if(mempool == NULL && bytes_needed > 0) { /* JARXM_MALLOC() failed, trouble ahead */
541 DEBUG("call to JARXM_MALLOC() failed, returned %p", (void*)mempool);
542 return 2;
543 }
544
545 /* Initialize most of the fields to 0, 0.f, NULL or false depending on type */
546 memset(mempool, 0, bytes_needed);
547
548 ctx = (*ctxp = (jar_xm_context_t *)mempool);
549 ctx->allocated_memory = mempool; /* Keep original pointer for JARXM_FREE() */
550 mempool += sizeof(jar_xm_context_t);
551
552 ctx->rate = rate;
553 mempool = jar_xm_load_module(ctx, moddata, moddata_length, mempool);
554 mempool = ALIGN_PTR(mempool, 16);
555
556 ctx->channels = (jar_xm_channel_context_t*)mempool;
557 mempool += ctx->module.num_channels * sizeof(jar_xm_channel_context_t);
558 mempool = ALIGN_PTR(mempool, 16);
559
560 ctx->default_global_volume = 1.f;
561 ctx->global_volume = ctx->default_global_volume;
562
563 ctx->volume_ramp = (1.f / 128.f);
564 ctx->panning_ramp = (1.f / 128.f);
565
566 for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
567 jar_xm_channel_context_t *ch = ctx->channels + i;
568 ch->ping = true;
569 ch->vibrato_waveform = jar_xm_SINE_WAVEFORM;
570 ch->vibrato_waveform_retrigger = true;
571 ch->tremolo_waveform = jar_xm_SINE_WAVEFORM;
572 ch->tremolo_waveform_retrigger = true;
573 ch->volume = ch->volume_envelope_volume = ch->fadeout_volume = 1.0f;
574 ch->panning = ch->panning_envelope_panning = .5f;
575 ch->actual_volume = .0f;
576 ch->actual_panning = .5f;
577 }
578
579 mempool = ALIGN_PTR(mempool, 16);
580 ctx->row_loop_count = (uint8_t *)mempool;
581 mempool += MAX_NUM_ROWS * sizeof(uint8_t);
582
583#if JAR_XM_DEFENSIVE
584 if((ret = jar_xm_check_sanity_postload(ctx))) { DEBUG("jar_xm_check_sanity_postload() returned %i, module is not safe to play", ret);
586 return 1;
587 }
588#endif
589
590 return 0;
591}
592
594 if (ctx != NULL) { JARXM_FREE(ctx->allocated_memory); }
595}
596
598 ctx->max_loop_count = loopcnt;
599}
600
602 return ctx->loop_count;
603}
604
606 bool old = ctx->channels[channel - 1].muted;
607 ctx->channels[channel - 1].muted = mute;
608 return old;
609}
610
611bool jar_xm_mute_instrument(jar_xm_context_t *ctx, uint16_t instr, bool mute) {
612 bool old = ctx->module.instruments[instr - 1].muted;
613 ctx->module.instruments[instr - 1].muted = mute;
614 return old;
615}
616
618 return ctx->module.name;
619}
620
622 return ctx->module.trackername;
623}
624
626 return ctx->module.num_channels;
627}
628
630 return ctx->module.length;
631}
632
634 return ctx->module.num_patterns;
635}
636
638 return ctx->module.patterns[pattern].num_rows;
639}
640
642 return ctx->module.num_instruments;
643}
644
646 return ctx->module.instruments[instrument - 1].num_samples;
647}
648
650 if(bpm) *bpm = ctx->bpm;
651 if(tempo) *tempo = ctx->tempo;
652}
653
654void jar_xm_get_position(jar_xm_context_t *ctx, uint8_t *pattern_index, uint8_t *pattern, uint8_t *row, uint64_t *samples) {
655 if(pattern_index) *pattern_index = ctx->current_table_index;
656 if(pattern) *pattern = ctx->module.pattern_table[ctx->current_table_index];
657 if(row) *row = ctx->current_row;
658 if(samples) *samples = ctx->generated_samples;
659}
660
662 return ctx->module.instruments[instr - 1].latest_trigger;
663}
664
666 return ctx->module.instruments[instr - 1].samples[sample].latest_trigger;
667}
668
670 return ctx->channels[chn - 1].latest_trigger;
671}
672
673//* .xm files are little-endian. (XXX: Are they really?)
674
675//* Bound reader macros.
676//* If we attempt to read the buffer out-of-bounds, pretend that the buffer is infinitely padded with zeroes.
677#define READ_U8(offset) (((offset) < moddata_length) ? (*(uint8_t*)(moddata + (offset))) : 0)
678#define READ_U16(offset) ((uint16_t)READ_U8(offset) | ((uint16_t)READ_U8((offset) + 1) << 8))
679#define READ_U32(offset) ((uint32_t)READ_U16(offset) | ((uint32_t)READ_U16((offset) + 2) << 16))
680#define READ_MEMCPY(ptr, offset, length) memcpy_pad(ptr, length, moddata, moddata_length, offset)
681
682static void memcpy_pad(void *dst, size_t dst_len, const void *src, size_t src_len, size_t offset) {
683 uint8_t *dst_c = dst;
684 const uint8_t *src_c = src;
685
686 /* how many bytes can be copied without overrunning `src` */
687 size_t copy_bytes = (src_len >= offset) ? (src_len - offset) : 0;
688 copy_bytes = copy_bytes > dst_len ? dst_len : copy_bytes;
689
690 memcpy(dst_c, src_c + offset, copy_bytes);
691 /* padded bytes */
692 memset(dst_c + copy_bytes, 0, dst_len - copy_bytes);
693}
694
695#if JAR_XM_DEFENSIVE
696
697int jar_xm_check_sanity_preload(const char* module, size_t module_length) {
698 if(module_length < 60) { return 4; }
699 if(memcmp("Extended Module: ", module, 17) != 0) { return 1; }
700 if(module[37] != 0x1A) { return 2; }
701 if(module[59] != 0x01 || module[58] != 0x04) { return 3; } /* Not XM 1.04 */
702 return 0;
703}
704
705int jar_xm_check_sanity_postload(jar_xm_context_t* ctx) {
706 /* Check the POT */
707 for(uint8_t i = 0; i < ctx->module.length; ++i) {
708 if(ctx->module.pattern_table[i] >= ctx->module.num_patterns) {
709 if(i+1 == ctx->module.length && ctx->module.length > 1) {
710 DEBUG("trimming invalid POT at pos %X", i);
711 --ctx->module.length;
712 } else {
713 DEBUG("module has invalid POT, pos %X references nonexistent pattern %X", i, ctx->module.pattern_table[i]);
714 return 1;
715 }
716 }
717 }
718
719 return 0;
720}
721
722#endif
723
724size_t jar_xm_get_memory_needed_for_context(const char* moddata, size_t moddata_length) {
725 size_t memory_needed = 0;
726 size_t offset = 60; /* 60 = Skip the first header */
727 uint16_t num_channels;
728 uint16_t num_patterns;
729 uint16_t num_instruments;
730
731 /* Read the module header */
732 num_channels = READ_U16(offset + 8);
733 num_patterns = READ_U16(offset + 10);
734 memory_needed += num_patterns * sizeof(jar_xm_pattern_t);
735 memory_needed = ALIGN(memory_needed, 16);
736 num_instruments = READ_U16(offset + 12);
737 memory_needed += num_instruments * sizeof(jar_xm_instrument_t);
738 memory_needed = ALIGN(memory_needed, 16);
739 memory_needed += MAX_NUM_ROWS * READ_U16(offset + 4) * sizeof(uint8_t); /* Module length */
740
741 offset += READ_U32(offset); /* Header size */
742
743 /* Read pattern headers */
744 for(uint16_t i = 0; i < num_patterns; ++i) {
745 uint16_t num_rows;
746 num_rows = READ_U16(offset + 5);
747 memory_needed += num_rows * num_channels * sizeof(jar_xm_pattern_slot_t);
748 offset += READ_U32(offset) + READ_U16(offset + 7); /* Pattern header length + packed pattern data size */
749 }
750 memory_needed = ALIGN(memory_needed, 16);
751
752 /* Read instrument headers */
753 for(uint16_t i = 0; i < num_instruments; ++i) {
754 uint16_t num_samples;
755 uint32_t sample_header_size = 0;
756 uint32_t sample_size_aggregate = 0;
757 num_samples = READ_U16(offset + 27);
758 memory_needed += num_samples * sizeof(jar_xm_sample_t);
759 if(num_samples > 0) { sample_header_size = READ_U32(offset + 29); }
760
761 offset += READ_U32(offset); /* Instrument header size */
762 for(uint16_t j = 0; j < num_samples; ++j) {
763 uint32_t sample_size;
764 uint8_t flags;
765 sample_size = READ_U32(offset);
766 flags = READ_U8(offset + 14);
767 sample_size_aggregate += sample_size;
768
769 if(flags & (1 << 4)) { /* 16 bit sample */
770 memory_needed += sample_size * (sizeof(float) >> 1);
771 } else { /* 8 bit sample */
772 memory_needed += sample_size * sizeof(float);
773 }
774 offset += sample_header_size;
775 }
776 offset += sample_size_aggregate;
777 }
778
779 memory_needed += num_channels * sizeof(jar_xm_channel_context_t);
780 memory_needed += sizeof(jar_xm_context_t);
781 return memory_needed;
782}
783
784char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t moddata_length, char* mempool) {
785 size_t offset = 0;
786 jar_xm_module_t* mod = &(ctx->module);
787
788 /* Read XM header */
789 READ_MEMCPY(mod->name, offset + 17, MODULE_NAME_LENGTH);
790 READ_MEMCPY(mod->trackername, offset + 38, TRACKER_NAME_LENGTH);
791 offset += 60;
792
793 /* Read module header */
794 uint32_t header_size = READ_U32(offset);
795 mod->length = READ_U16(offset + 4);
796 mod->restart_position = READ_U16(offset + 6);
797 mod->num_channels = READ_U16(offset + 8);
798 mod->num_patterns = READ_U16(offset + 10);
799 mod->num_instruments = READ_U16(offset + 12);
800 mod->patterns = (jar_xm_pattern_t*)mempool;
801 mod->linear_interpolation = 1; // Linear interpolation can be set after loading
802 mod->ramping = 1; // ramping can be set after loading
803 mempool += mod->num_patterns * sizeof(jar_xm_pattern_t);
804 mempool = ALIGN_PTR(mempool, 16);
805 mod->instruments = (jar_xm_instrument_t*)mempool;
806 mempool += mod->num_instruments * sizeof(jar_xm_instrument_t);
807 mempool = ALIGN_PTR(mempool, 16);
808 uint16_t flags = READ_U32(offset + 14);
809 mod->frequency_type = (flags & (1 << 0)) ? jar_xm_LINEAR_FREQUENCIES : jar_xm_AMIGA_FREQUENCIES;
810 ctx->default_tempo = READ_U16(offset + 16);
811 ctx->default_bpm = READ_U16(offset + 18);
812 ctx->tempo =ctx->default_tempo;
813 ctx->bpm = ctx->default_bpm;
814
815 READ_MEMCPY(mod->pattern_table, offset + 20, PATTERN_ORDER_TABLE_LENGTH);
816 offset += header_size;
817
818 /* Read patterns */
819 for(uint16_t i = 0; i < mod->num_patterns; ++i) {
820 uint16_t packed_patterndata_size = READ_U16(offset + 7);
821 jar_xm_pattern_t* pat = mod->patterns + i;
822 pat->num_rows = READ_U16(offset + 5);
823 pat->slots = (jar_xm_pattern_slot_t*)mempool;
824 mempool += mod->num_channels * pat->num_rows * sizeof(jar_xm_pattern_slot_t);
825 offset += READ_U32(offset); /* Pattern header length */
826
827 if(packed_patterndata_size == 0) { /* No pattern data is present */
828 memset(pat->slots, 0, sizeof(jar_xm_pattern_slot_t) * pat->num_rows * mod->num_channels);
829 } else {
830 /* This isn't your typical for loop */
831 for(uint16_t j = 0, k = 0; j < packed_patterndata_size; ++k) {
832 uint8_t note = READ_U8(offset + j);
833 jar_xm_pattern_slot_t* slot = pat->slots + k;
834 if(note & (1 << 7)) {
835 /* MSB is set, this is a compressed packet */
836 ++j;
837 if(note & (1 << 0)) { /* Note follows */
838 slot->note = READ_U8(offset + j);
839 ++j;
840 } else {
841 slot->note = 0;
842 }
843 if(note & (1 << 1)) { /* Instrument follows */
844 slot->instrument = READ_U8(offset + j);
845 ++j;
846 } else {
847 slot->instrument = 0;
848 }
849 if(note & (1 << 2)) { /* Volume column follows */
850 slot->volume_column = READ_U8(offset + j);
851 ++j;
852 } else {
853 slot->volume_column = 0;
854 }
855 if(note & (1 << 3)) { /* Effect follows */
856 slot->effect_type = READ_U8(offset + j);
857 ++j;
858 } else {
859 slot->effect_type = 0;
860 }
861 if(note & (1 << 4)) { /* Effect parameter follows */
862 slot->effect_param = READ_U8(offset + j);
863 ++j;
864 } else {
865 slot->effect_param = 0;
866 }
867 } else { /* Uncompressed packet */
868 slot->note = note;
869 slot->instrument = READ_U8(offset + j + 1);
870 slot->volume_column = READ_U8(offset + j + 2);
871 slot->effect_type = READ_U8(offset + j + 3);
872 slot->effect_param = READ_U8(offset + j + 4);
873 j += 5;
874 }
875 }
876 }
877
878 offset += packed_patterndata_size;
879 }
880 mempool = ALIGN_PTR(mempool, 16);
881
882 /* Read instruments */
883 for(uint16_t i = 0; i < ctx->module.num_instruments; ++i) {
884 uint32_t sample_header_size = 0;
885 jar_xm_instrument_t* instr = mod->instruments + i;
886
887 READ_MEMCPY(instr->name, offset + 4, INSTRUMENT_NAME_LENGTH);
888 instr->num_samples = READ_U16(offset + 27);
889
890 if(instr->num_samples > 0) {
891 /* Read extra header properties */
892 sample_header_size = READ_U32(offset + 29);
893 READ_MEMCPY(instr->sample_of_notes, offset + 33, NUM_NOTES);
894
895 instr->volume_envelope.num_points = READ_U8(offset + 225);
896 instr->panning_envelope.num_points = READ_U8(offset + 226);
897
898 for(uint8_t j = 0; j < instr->volume_envelope.num_points; ++j) {
899 instr->volume_envelope.points[j].frame = READ_U16(offset + 129 + 4 * j);
900 instr->volume_envelope.points[j].value = READ_U16(offset + 129 + 4 * j + 2);
901 }
902
903 for(uint8_t j = 0; j < instr->panning_envelope.num_points; ++j) {
904 instr->panning_envelope.points[j].frame = READ_U16(offset + 177 + 4 * j);
905 instr->panning_envelope.points[j].value = READ_U16(offset + 177 + 4 * j + 2);
906 }
907
908 instr->volume_envelope.sustain_point = READ_U8(offset + 227);
909 instr->volume_envelope.loop_start_point = READ_U8(offset + 228);
910 instr->volume_envelope.loop_end_point = READ_U8(offset + 229);
911 instr->panning_envelope.sustain_point = READ_U8(offset + 230);
912 instr->panning_envelope.loop_start_point = READ_U8(offset + 231);
913 instr->panning_envelope.loop_end_point = READ_U8(offset + 232);
914
915 uint8_t flags = READ_U8(offset + 233);
916 instr->volume_envelope.enabled = flags & (1 << 0);
917 instr->volume_envelope.sustain_enabled = flags & (1 << 1);
918 instr->volume_envelope.loop_enabled = flags & (1 << 2);
919
920 flags = READ_U8(offset + 234);
921 instr->panning_envelope.enabled = flags & (1 << 0);
922 instr->panning_envelope.sustain_enabled = flags & (1 << 1);
923 instr->panning_envelope.loop_enabled = flags & (1 << 2);
924 instr->vibrato_type = READ_U8(offset + 235);
925 if(instr->vibrato_type == 2) {
926 instr->vibrato_type = 1;
927 } else if(instr->vibrato_type == 1) {
928 instr->vibrato_type = 2;
929 }
930 instr->vibrato_sweep = READ_U8(offset + 236);
931 instr->vibrato_depth = READ_U8(offset + 237);
932 instr->vibrato_rate = READ_U8(offset + 238);
933 instr->volume_fadeout = READ_U16(offset + 239);
934 instr->samples = (jar_xm_sample_t*)mempool;
935 mempool += instr->num_samples * sizeof(jar_xm_sample_t);
936 } else {
937 instr->samples = NULL;
938 }
939
940 /* Instrument header size */
941 offset += READ_U32(offset);
942
943 for(int j = 0; j < instr->num_samples; ++j) {
944 /* Read sample header */
945 jar_xm_sample_t* sample = instr->samples + j;
946
947 sample->length = READ_U32(offset);
948 sample->loop_start = READ_U32(offset + 4);
949 sample->loop_length = READ_U32(offset + 8);
950 sample->loop_end = sample->loop_start + sample->loop_length;
951 sample->volume = (float)(READ_U8(offset + 12) << 2) / 256.f;
952 if (sample->volume > 1.0f) {sample->volume = 1.f;};
953 sample->finetune = (int8_t)READ_U8(offset + 13);
954
955 uint8_t flags = READ_U8(offset + 14);
956 switch (flags & 3) {
957 case 2:
958 case 3:
959 sample->loop_type = jar_xm_PING_PONG_LOOP;
960 case 1:
961 sample->loop_type = jar_xm_FORWARD_LOOP;
962 break;
963 default:
964 sample->loop_type = jar_xm_NO_LOOP;
965 break;
966 };
967 sample->bits = (flags & 0x10) ? 16 : 8;
968 sample->stereo = (flags & 0x20) ? 1 : 0;
969 sample->panning = (float)READ_U8(offset + 15) / 255.f;
970 sample->relative_note = (int8_t)READ_U8(offset + 16);
971 READ_MEMCPY(sample->name, 18, SAMPLE_NAME_LENGTH);
972 sample->data = (float*)mempool;
973 if(sample->bits == 16) {
974 /* 16 bit sample */
975 mempool += sample->length * (sizeof(float) >> 1);
976 sample->loop_start >>= 1;
977 sample->loop_length >>= 1;
978 sample->loop_end >>= 1;
979 sample->length >>= 1;
980 } else {
981 /* 8 bit sample */
982 mempool += sample->length * sizeof(float);
983 }
984 // Adjust loop points to reflect half of the reported length (stereo)
985 if (sample->stereo && sample->loop_type != jar_xm_NO_LOOP) {
986 div_t lstart = div(READ_U32(offset + 4), 2);
987 sample->loop_start = lstart.quot;
988 div_t llength = div(READ_U32(offset + 8), 2);
989 sample->loop_length = llength.quot;
990 sample->loop_end = sample->loop_start + sample->loop_length;
991 };
992
993 offset += sample_header_size;
994 }
995
996 // Read all samples and convert them to float values
997 for(int j = 0; j < instr->num_samples; ++j) {
998 /* Read sample data */
999 jar_xm_sample_t* sample = instr->samples + j;
1000 int length = sample->length;
1001 if (sample->stereo) {
1002 // Since it is stereo, we cut the sample in half (treated as single channel)
1003 div_t result = div(sample->length, 2);
1004 if(sample->bits == 16) {
1005 int16_t v = 0;
1006 for(int k = 0; k < length; ++k) {
1007 if (k == result.quot) { v = 0;};
1008 v = v + (int16_t)READ_U16(offset + (k << 1));
1009 sample->data[k] = (float) v / 32768.f ;//* sign;
1010 if(sample->data[k] < -1.0) {sample->data[k] = -1.0;} else if(sample->data[k] > 1.0) {sample->data[k] = 1.0;};
1011 }
1012 offset += sample->length << 1;
1013 } else {
1014 int8_t v = 0;
1015 for(int k = 0; k < length; ++k) {
1016 if (k == result.quot) { v = 0;};
1017 v = v + (int8_t)READ_U8(offset + k);
1018 sample->data[k] = (float)v / 128.f ;//* sign;
1019 if(sample->data[k] < -1.0) {sample->data[k] = -1.0;} else if(sample->data[k] > 1.0) {sample->data[k] = 1.0;};
1020 }
1021 offset += sample->length;
1022 };
1023 sample->length = result.quot;
1024 } else {
1025 if(sample->bits == 16) {
1026 int16_t v = 0;
1027 for(int k = 0; k < length; ++k) {
1028 v = v + (int16_t)READ_U16(offset + (k << 1));
1029 sample->data[k] = (float) v / 32768.f ;//* sign;
1030 if(sample->data[k] < -1.0) {sample->data[k] = -1.0;} else if(sample->data[k] > 1.0) {sample->data[k] = 1.0;};
1031 }
1032 offset += sample->length << 1;
1033 } else {
1034 int8_t v = 0;
1035 for(int k = 0; k < length; ++k) {
1036 v = v + (int8_t)READ_U8(offset + k);
1037 sample->data[k] = (float)v / 128.f ;//* sign;
1038 if(sample->data[k] < -1.0) {sample->data[k] = -1.0;} else if(sample->data[k] > 1.0) {sample->data[k] = 1.0;};
1039 }
1040 offset += sample->length;
1041 }
1042 }
1043 };
1044 };
1045 return mempool;
1046};
1047
1048//-------------------------------------------------------------------------------
1049//THE FOLLOWING IS FOR PLAYING
1050static float jar_xm_waveform(jar_xm_waveform_type_t, uint8_t);
1051static void jar_xm_autovibrato(jar_xm_context_t*, jar_xm_channel_context_t*);
1052static void jar_xm_vibrato(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
1053static void jar_xm_tremolo(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
1054static void jar_xm_arpeggio(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
1055static void jar_xm_tone_portamento(jar_xm_context_t*, jar_xm_channel_context_t*);
1056static void jar_xm_pitch_slide(jar_xm_context_t*, jar_xm_channel_context_t*, float);
1057static void jar_xm_panning_slide(jar_xm_channel_context_t*, uint8_t);
1058static void jar_xm_volume_slide(jar_xm_channel_context_t*, uint8_t);
1059
1060static float jar_xm_envelope_lerp(jar_xm_envelope_point_t*, jar_xm_envelope_point_t*, uint16_t);
1061static void jar_xm_envelope_tick(jar_xm_channel_context_t*, jar_xm_envelope_t*, uint16_t*, float*);
1062static void jar_xm_envelopes(jar_xm_channel_context_t*);
1063
1064static float jar_xm_linear_period(float);
1065static float jar_xm_linear_frequency(float);
1066static float jar_xm_amiga_period(float);
1067static float jar_xm_amiga_frequency(float);
1068static float jar_xm_period(jar_xm_context_t*, float);
1069static float jar_xm_frequency(jar_xm_context_t*, float, float);
1070static void jar_xm_update_frequency(jar_xm_context_t*, jar_xm_channel_context_t*);
1071
1072static void jar_xm_handle_note_and_instrument(jar_xm_context_t*, jar_xm_channel_context_t*, jar_xm_pattern_slot_t*);
1073static void jar_xm_trigger_note(jar_xm_context_t*, jar_xm_channel_context_t*, unsigned int flags);
1074static void jar_xm_cut_note(jar_xm_channel_context_t*);
1075static void jar_xm_key_off(jar_xm_channel_context_t*);
1076
1077static void jar_xm_post_pattern_change(jar_xm_context_t*);
1078static void jar_xm_row(jar_xm_context_t*);
1079static void jar_xm_tick(jar_xm_context_t*);
1080
1081static void jar_xm_next_of_sample(jar_xm_context_t*, jar_xm_channel_context_t*, int);
1082static void jar_xm_mixdown(jar_xm_context_t*, float*, float*);
1083
1084#define jar_xm_TRIGGER_KEEP_VOLUME (1 << 0)
1085#define jar_xm_TRIGGER_KEEP_PERIOD (1 << 1)
1086#define jar_xm_TRIGGER_KEEP_SAMPLE_POSITION (1 << 2)
1087
1088 // C-2, C#2, D-2, D#2, E-2, F-2, F#2, G-2, G#2, A-2, A#2, B-2, C-3
1089static const uint16_t amiga_frequencies[] = { 1712, 1616, 1525, 1440, 1357, 1281, 1209, 1141, 1077, 1017, 961, 907, 856 };
1090
1091 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
1092static const float multi_retrig_add[] = { 0.f, -1.f, -2.f, -4.f, -8.f, -16.f, 0.f, 0.f, 0.f, 1.f, 2.f, 4.f, 8.f, 16.f, 0.f, 0.f };
1093
1094 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
1095static const float multi_retrig_multiply[] = { 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, .6666667f, .5f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.5f, 2.f };
1096
1097#define jar_xm_CLAMP_UP1F(vol, limit) do { \
1098 if((vol) > (limit)) (vol) = (limit); \
1099 } while(0)
1100#define jar_xm_CLAMP_UP(vol) jar_xm_CLAMP_UP1F((vol), 1.f)
1101
1102#define jar_xm_CLAMP_DOWN1F(vol, limit) do { \
1103 if((vol) < (limit)) (vol) = (limit); \
1104 } while(0)
1105#define jar_xm_CLAMP_DOWN(vol) jar_xm_CLAMP_DOWN1F((vol), .0f)
1106
1107#define jar_xm_CLAMP2F(vol, up, down) do { \
1108 if((vol) > (up)) (vol) = (up); \
1109 else if((vol) < (down)) (vol) = (down); \
1110 } while(0)
1111#define jar_xm_CLAMP(vol) jar_xm_CLAMP2F((vol), 1.f, .0f)
1112
1113#define jar_xm_SLIDE_TOWARDS(val, goal, incr) do { \
1114 if((val) > (goal)) { \
1115 (val) -= (incr); \
1116 jar_xm_CLAMP_DOWN1F((val), (goal)); \
1117 } else if((val) < (goal)) { \
1118 (val) += (incr); \
1119 jar_xm_CLAMP_UP1F((val), (goal)); \
1120 } \
1121 } while(0)
1122
1123#define jar_xm_LERP(u, v, t) ((u) + (t) * ((v) - (u)))
1124#define jar_xm_INVERSE_LERP(u, v, lerp) (((lerp) - (u)) / ((v) - (u)))
1125
1126#define HAS_TONE_PORTAMENTO(s) ((s)->effect_type == 3 \
1127 || (s)->effect_type == 5 \
1128 || ((s)->volume_column >> 4) == 0xF)
1129#define HAS_ARPEGGIO(s) ((s)->effect_type == 0 \
1130 && (s)->effect_param != 0)
1131#define HAS_VIBRATO(s) ((s)->effect_type == 4 \
1132 || (s)->effect_param == 6 \
1133 || ((s)->volume_column >> 4) == 0xB)
1134#define NOTE_IS_VALID(n) ((n) > 0 && (n) < 97)
1135#define NOTE_OFF 97
1136
1137static float jar_xm_waveform(jar_xm_waveform_type_t waveform, uint8_t step) {
1138 static unsigned int next_rand = 24492;
1139 step %= 0x40;
1140 switch(waveform) {
1141 case jar_xm_SINE_WAVEFORM: /* No SIN() table used, direct calculation. */
1142 return -sinf(2.f * 3.141592f * (float)step / (float)0x40);
1143 case jar_xm_RAMP_DOWN_WAVEFORM: /* Ramp down: 1.0f when step = 0; -1.0f when step = 0x40 */
1144 return (float)(0x20 - step) / 0x20;
1145 case jar_xm_SQUARE_WAVEFORM: /* Square with a 50% duty */
1146 return (step >= 0x20) ? 1.f : -1.f;
1147 case jar_xm_RANDOM_WAVEFORM: /* Use the POSIX.1-2001 example, just to be deterministic across different machines */
1148 next_rand = next_rand * 1103515245 + 12345;
1149 return (float)((next_rand >> 16) & 0x7FFF) / (float)0x4000 - 1.f;
1150 case jar_xm_RAMP_UP_WAVEFORM: /* Ramp up: -1.f when step = 0; 1.f when step = 0x40 */
1151 return (float)(step - 0x20) / 0x20;
1152 default:
1153 break;
1154 }
1155 return .0f;
1156}
1157
1158static void jar_xm_autovibrato(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch) {
1159 if(ch->instrument == NULL || ch->instrument->vibrato_depth == 0) return;
1160 jar_xm_instrument_t* instr = ch->instrument;
1161 float sweep = 1.f;
1162 if(ch->autovibrato_ticks < instr->vibrato_sweep) { sweep = jar_xm_LERP(0.f, 1.f, (float)ch->autovibrato_ticks / (float)instr->vibrato_sweep); }
1163 unsigned int step = ((ch->autovibrato_ticks++) * instr->vibrato_rate) >> 2;
1164 ch->autovibrato_note_offset = .25f * jar_xm_waveform(instr->vibrato_type, step) * (float)instr->vibrato_depth / (float)0xF * sweep;
1165 jar_xm_update_frequency(ctx, ch);
1166}
1167
1168static void jar_xm_vibrato(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, uint8_t param, uint16_t pos) {
1169 unsigned int step = pos * (param >> 4);
1170 ch->vibrato_note_offset = 2.f * jar_xm_waveform(ch->vibrato_waveform, step) * (float)(param & 0x0F) / (float)0xF;
1171 jar_xm_update_frequency(ctx, ch);
1172}
1173
1174static void jar_xm_tremolo(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, uint8_t param, uint16_t pos) {
1175 unsigned int step = pos * (param >> 4);
1176 ch->tremolo_volume = -1.f * jar_xm_waveform(ch->tremolo_waveform, step) * (float)(param & 0x0F) / (float)0xF;
1177}
1178
1179static void jar_xm_arpeggio(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, uint8_t param, uint16_t tick) {
1180 switch(tick % 3) {
1181 case 0:
1182 ch->arp_in_progress = false;
1183 ch->arp_note_offset = 0;
1184 break;
1185 case 2:
1186 ch->arp_in_progress = true;
1187 ch->arp_note_offset = param >> 4;
1188 break;
1189 case 1:
1190 ch->arp_in_progress = true;
1191 ch->arp_note_offset = param & 0x0F;
1192 break;
1193 }
1194 jar_xm_update_frequency(ctx, ch);
1195}
1196
1197static void jar_xm_tone_portamento(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch) {
1198 /* 3xx called without a note, wait until we get an actual target note. */
1199 if(ch->tone_portamento_target_period == 0.f) return; /* no value, exit */
1200 if(ch->period != ch->tone_portamento_target_period) {
1201 jar_xm_SLIDE_TOWARDS(ch->period, ch->tone_portamento_target_period, (ctx->module.frequency_type == jar_xm_LINEAR_FREQUENCIES ? 4.f : 1.f) * ch->tone_portamento_param);
1202 jar_xm_update_frequency(ctx, ch);
1203 }
1204}
1205
1206static void jar_xm_pitch_slide(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, float period_offset) {
1207 /* Don't ask about the 4.f coefficient. I found mention of it nowhere. Found by earâ„¢. */
1208 if(ctx->module.frequency_type == jar_xm_LINEAR_FREQUENCIES) {period_offset *= 4.f; }
1209 ch->period += period_offset;
1210 jar_xm_CLAMP_DOWN(ch->period);
1211 /* XXX: upper bound of period ? */
1212 jar_xm_update_frequency(ctx, ch);
1213}
1214
1215static void jar_xm_panning_slide(jar_xm_channel_context_t* ch, uint8_t rawval) {
1216 if (rawval & 0xF0) {ch->panning += (float)((rawval & 0xF0 )>> 4) / (float)0xFF;};
1217 if (rawval & 0x0F) {ch->panning -= (float)(rawval & 0x0F) / (float)0xFF;};
1218};
1219
1220static void jar_xm_volume_slide(jar_xm_channel_context_t* ch, uint8_t rawval) {
1221 if (rawval & 0xF0) {ch->volume += (float)((rawval & 0xF0) >> 4) / (float)0x40;};
1222 if (rawval & 0x0F) {ch->volume -= (float)(rawval & 0x0F) / (float)0x40;};
1223};
1224
1225static float jar_xm_envelope_lerp(jar_xm_envelope_point_t* a, jar_xm_envelope_point_t* b, uint16_t pos) {
1226 /* Linear interpolation between two envelope points */
1227 if(pos <= a->frame) return a->value;
1228 else if(pos >= b->frame) return b->value;
1229 else {
1230 float p = (float)(pos - a->frame) / (float)(b->frame - a->frame);
1231 return a->value * (1 - p) + b->value * p;
1232 }
1233}
1234
1235static void jar_xm_post_pattern_change(jar_xm_context_t* ctx) {
1236 /* Loop if necessary */
1237 if(ctx->current_table_index >= ctx->module.length) {
1238 ctx->current_table_index = ctx->module.restart_position;
1239 ctx->tempo =ctx->default_tempo; // reset to file default value
1240 ctx->bpm = ctx->default_bpm; // reset to file default value
1241 ctx->global_volume = ctx->default_global_volume; // reset to file default value
1242 }
1243}
1244
1245static float jar_xm_linear_period(float note) {
1246 return 7680.f - note * 64.f;
1247}
1248
1249static float jar_xm_linear_frequency(float period) {
1250 return 8363.f * powf(2.f, (4608.f - period) / 768.f);
1251}
1252
1253static float jar_xm_amiga_period(float note) {
1254 unsigned int intnote = note;
1255 uint8_t a = intnote % 12;
1256 int8_t octave = note / 12.f - 2;
1257 uint16_t p1 = amiga_frequencies[a], p2 = amiga_frequencies[a + 1];
1258 if(octave > 0) {
1259 p1 >>= octave;
1260 p2 >>= octave;
1261 } else if(octave < 0) {
1262 p1 <<= -octave;
1263 p2 <<= -octave;
1264 }
1265 return jar_xm_LERP(p1, p2, note - intnote);
1266}
1267
1268static float jar_xm_amiga_frequency(float period) {
1269 if(period == .0f) return .0f;
1270 return 7093789.2f / (period * 2.f); /* This is the PAL value. (we could use the NTSC value also) */
1271}
1272
1273static float jar_xm_period(jar_xm_context_t* ctx, float note) {
1274 switch(ctx->module.frequency_type) {
1275 case jar_xm_LINEAR_FREQUENCIES:
1276 return jar_xm_linear_period(note);
1277 case jar_xm_AMIGA_FREQUENCIES:
1278 return jar_xm_amiga_period(note);
1279 }
1280 return .0f;
1281}
1282
1283static float jar_xm_frequency(jar_xm_context_t* ctx, float period, float note_offset) {
1284 switch(ctx->module.frequency_type) {
1285 case jar_xm_LINEAR_FREQUENCIES:
1286 return jar_xm_linear_frequency(period - 64.f * note_offset);
1287 case jar_xm_AMIGA_FREQUENCIES:
1288 if(note_offset == 0) { return jar_xm_amiga_frequency(period); };
1289 int8_t octave;
1290 float note;
1291 uint16_t p1, p2;
1292 uint8_t a = octave = 0;
1293
1294 /* Find the octave of the current period */
1295 if(period > amiga_frequencies[0]) {
1296 --octave;
1297 while(period > (amiga_frequencies[0] << -octave)) --octave;
1298 } else if(period < amiga_frequencies[12]) {
1299 ++octave;
1300 while(period < (amiga_frequencies[12] >> octave)) ++octave;
1301 }
1302
1303 /* Find the smallest note closest to the current period */
1304 for(uint8_t i = 0; i < 12; ++i) {
1305 p1 = amiga_frequencies[i], p2 = amiga_frequencies[i + 1];
1306 if(octave > 0) {
1307 p1 >>= octave;
1308 p2 >>= octave;
1309 } else if(octave < 0) {
1310 p1 <<= (-octave);
1311 p2 <<= (-octave);
1312 }
1313 if(p2 <= period && period <= p1) {
1314 a = i;
1315 break;
1316 }
1317 }
1318 if(JAR_XM_DEBUG && (p1 < period || p2 > period)) { DEBUG("%i <= %f <= %i should hold but doesn't, this is a bug", p2, period, p1); }
1319 note = 12.f * (octave + 2) + a + jar_xm_INVERSE_LERP(p1, p2, period);
1320 return jar_xm_amiga_frequency(jar_xm_amiga_period(note + note_offset));
1321 }
1322
1323 return .0f;
1324}
1325
1326static void jar_xm_update_frequency(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch) {
1327 ch->frequency = jar_xm_frequency( ctx, ch->period, (ch->arp_note_offset > 0 ? ch->arp_note_offset : ( ch->vibrato_note_offset + ch->autovibrato_note_offset )) );
1328 ch->step = ch->frequency / ctx->rate;
1329}
1330
1331static void jar_xm_handle_note_and_instrument(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, jar_xm_pattern_slot_t* s) {
1332 jar_xm_module_t* mod = &(ctx->module);
1333 if(s->instrument > 0) {
1334 if(HAS_TONE_PORTAMENTO(ch->current) && ch->instrument != NULL && ch->sample != NULL) { /* Tone portamento in effect */
1335 jar_xm_trigger_note(ctx, ch, jar_xm_TRIGGER_KEEP_PERIOD | jar_xm_TRIGGER_KEEP_SAMPLE_POSITION);
1336 } else if(s->instrument > ctx->module.num_instruments) { /* Invalid instrument, Cut current note */
1337 jar_xm_cut_note(ch);
1338 ch->instrument = NULL;
1339 ch->sample = NULL;
1340 } else {
1341 ch->instrument = ctx->module.instruments + (s->instrument - 1);
1342 if(s->note == 0 && ch->sample != NULL) { /* Ghost instrument, trigger note */
1343 /* Sample position is kept, but envelopes are reset */
1344 jar_xm_trigger_note(ctx, ch, jar_xm_TRIGGER_KEEP_SAMPLE_POSITION);
1345 }
1346 }
1347 }
1348
1349 if(NOTE_IS_VALID(s->note)) {
1350 // note value is s->note -1
1351 jar_xm_instrument_t* instr = ch->instrument;
1352 if(HAS_TONE_PORTAMENTO(ch->current) && instr != NULL && ch->sample != NULL) {
1353 /* Tone portamento in effect */
1354 ch->note = s->note + ch->sample->relative_note + ch->sample->finetune / 128.f - 1.f;
1355 ch->tone_portamento_target_period = jar_xm_period(ctx, ch->note);
1356 } else if(instr == NULL || ch->instrument->num_samples == 0) { /* Issue on instrument */
1357 jar_xm_cut_note(ch);
1358 } else {
1359 if(instr->sample_of_notes[s->note - 1] < instr->num_samples) {
1360 if (mod->ramping) {
1361 for(int i = 0; i < jar_xm_SAMPLE_RAMPING_POINTS; ++i) {
1362 jar_xm_next_of_sample(ctx, ch, i);
1363 }
1364 ch->frame_count = 0;
1365 };
1366 ch->sample = instr->samples + instr->sample_of_notes[s->note - 1];
1367 ch->orig_note = ch->note = s->note + ch->sample->relative_note + ch->sample->finetune / 128.f - 1.f;
1368 if(s->instrument > 0) {
1369 jar_xm_trigger_note(ctx, ch, 0);
1370 } else { /* Ghost note: keep old volume */
1371 jar_xm_trigger_note(ctx, ch, jar_xm_TRIGGER_KEEP_VOLUME);
1372 }
1373 } else {
1374 jar_xm_cut_note(ch);
1375 }
1376 }
1377 } else if(s->note == NOTE_OFF) {
1378 jar_xm_key_off(ch);
1379 }
1380
1381 // Interpret Effect column
1382 switch(s->effect_type) {
1383 case 1: /* 1xx: Portamento up */
1384 if(s->effect_param > 0) { ch->portamento_up_param = s->effect_param; }
1385 break;
1386 case 2: /* 2xx: Portamento down */
1387 if(s->effect_param > 0) { ch->portamento_down_param = s->effect_param; }
1388 break;
1389 case 3: /* 3xx: Tone portamento */
1390 if(s->effect_param > 0) { ch->tone_portamento_param = s->effect_param; }
1391 break;
1392 case 4: /* 4xy: Vibrato */
1393 if(s->effect_param & 0x0F) { ch->vibrato_param = (ch->vibrato_param & 0xF0) | (s->effect_param & 0x0F); } /* Set vibrato depth */
1394 if(s->effect_param >> 4) { ch->vibrato_param = (s->effect_param & 0xF0) | (ch->vibrato_param & 0x0F); } /* Set vibrato speed */
1395 break;
1396 case 5: /* 5xy: Tone portamento + Volume slide */
1397 if(s->effect_param > 0) { ch->volume_slide_param = s->effect_param; }
1398 break;
1399 case 6: /* 6xy: Vibrato + Volume slide */
1400 if(s->effect_param > 0) { ch->volume_slide_param = s->effect_param; }
1401 break;
1402 case 7: /* 7xy: Tremolo */
1403 if(s->effect_param & 0x0F) { ch->tremolo_param = (ch->tremolo_param & 0xF0) | (s->effect_param & 0x0F); } /* Set tremolo depth */
1404 if(s->effect_param >> 4) { ch->tremolo_param = (s->effect_param & 0xF0) | (ch->tremolo_param & 0x0F); } /* Set tremolo speed */
1405 break;
1406 case 8: /* 8xx: Set panning */
1407 ch->panning = (float)s->effect_param / 255.f;
1408 break;
1409 case 9: /* 9xx: Sample offset */
1410 if(ch->sample != 0) { //&& NOTE_IS_VALID(s->note)) {
1411 uint32_t final_offset = s->effect_param << (ch->sample->bits == 16 ? 7 : 8);
1412 switch (ch->sample->loop_type) {
1413 case jar_xm_NO_LOOP:
1414 if(final_offset >= ch->sample->length) { /* Pretend the sample dosen't loop and is done playing */
1415 ch->sample_position = -1;
1416 } else {
1417 ch->sample_position = final_offset;
1418 }
1419 break;
1420 case jar_xm_FORWARD_LOOP:
1421 if (final_offset >= ch->sample->loop_end) {
1422 ch->sample_position -= ch->sample->loop_length;
1423 } else if(final_offset >= ch->sample->length) {
1424 ch->sample_position = ch->sample->loop_start;
1425 } else {
1426 ch->sample_position = final_offset;
1427 }
1428 break;
1429 case jar_xm_PING_PONG_LOOP:
1430 if(final_offset >= ch->sample->loop_end) {
1431 ch->ping = false;
1432 ch->sample_position = (ch->sample->loop_end << 1) - ch->sample_position;
1433 } else if(final_offset >= ch->sample->length) {
1434 ch->ping = false;
1435 ch->sample_position -= ch->sample->length - 1;
1436 } else {
1437 ch->sample_position = final_offset;
1438 };
1439 break;
1440 }
1441 }
1442 break;
1443 case 0xA: /* Axy: Volume slide */
1444 if(s->effect_param > 0) { ch->volume_slide_param = s->effect_param; }
1445 break;
1446 case 0xB: /* Bxx: Position jump */
1447 if(s->effect_param < ctx->module.length) {
1448 ctx->position_jump = true;
1449 ctx->jump_dest = s->effect_param;
1450 }
1451 break;
1452 case 0xC: /* Cxx: Set volume */
1453 ch->volume = (float)((s->effect_param > 0x40) ? 0x40 : s->effect_param) / (float)0x40;
1454 break;
1455 case 0xD: /* Dxx: Pattern break */
1456 /* Jump after playing this line */
1457 ctx->pattern_break = true;
1458 ctx->jump_row = (s->effect_param >> 4) * 10 + (s->effect_param & 0x0F);
1459 break;
1460 case 0xE: /* EXy: Extended command */
1461 switch(s->effect_param >> 4) {
1462 case 1: /* E1y: Fine portamento up */
1463 if(s->effect_param & 0x0F) { ch->fine_portamento_up_param = s->effect_param & 0x0F; }
1464 jar_xm_pitch_slide(ctx, ch, -ch->fine_portamento_up_param);
1465 break;
1466 case 2: /* E2y: Fine portamento down */
1467 if(s->effect_param & 0x0F) { ch->fine_portamento_down_param = s->effect_param & 0x0F; }
1468 jar_xm_pitch_slide(ctx, ch, ch->fine_portamento_down_param);
1469 break;
1470 case 4: /* E4y: Set vibrato control */
1471 ch->vibrato_waveform = s->effect_param & 3;
1472 ch->vibrato_waveform_retrigger = !((s->effect_param >> 2) & 1);
1473 break;
1474 case 5: /* E5y: Set finetune */
1475 if(NOTE_IS_VALID(ch->current->note) && ch->sample != NULL) {
1476 ch->note = ch->current->note + ch->sample->relative_note + (float)(((s->effect_param & 0x0F) - 8) << 4) / 128.f - 1.f;
1477 ch->period = jar_xm_period(ctx, ch->note);
1478 jar_xm_update_frequency(ctx, ch);
1479 }
1480 break;
1481 case 6: /* E6y: Pattern loop */
1482 if(s->effect_param & 0x0F) {
1483 if((s->effect_param & 0x0F) == ch->pattern_loop_count) { /* Loop is over */
1484 ch->pattern_loop_count = 0;
1485 ctx->position_jump = false;
1486 } else { /* Jump to the beginning of the loop */
1487 ch->pattern_loop_count++;
1488 ctx->position_jump = true;
1489 ctx->jump_row = ch->pattern_loop_origin;
1490 ctx->jump_dest = ctx->current_table_index;
1491 }
1492 } else {
1493 ch->pattern_loop_origin = ctx->current_row; /* Set loop start point */
1494 ctx->jump_row = ch->pattern_loop_origin; /* Replicate FT2 E60 bug */
1495 }
1496 break;
1497 case 7: /* E7y: Set tremolo control */
1498 ch->tremolo_waveform = s->effect_param & 3;
1499 ch->tremolo_waveform_retrigger = !((s->effect_param >> 2) & 1);
1500 break;
1501 case 0xA: /* EAy: Fine volume slide up */
1502 if(s->effect_param & 0x0F) { ch->fine_volume_slide_param = s->effect_param & 0x0F; }
1503 jar_xm_volume_slide(ch, ch->fine_volume_slide_param << 4);
1504 break;
1505 case 0xB: /* EBy: Fine volume slide down */
1506 if(s->effect_param & 0x0F) { ch->fine_volume_slide_param = s->effect_param & 0x0F; }
1507 jar_xm_volume_slide(ch, ch->fine_volume_slide_param);
1508 break;
1509 case 0xD: /* EDy: Note delay */
1510 /* XXX: figure this out better. EDx triggers the note even when there no note and no instrument. But ED0 acts like like a ghost note, EDx (x ≠ 0) does not. */
1511 if(s->note == 0 && s->instrument == 0) {
1512 unsigned int flags = jar_xm_TRIGGER_KEEP_VOLUME;
1513 if(ch->current->effect_param & 0x0F) {
1514 ch->note = ch->orig_note;
1515 jar_xm_trigger_note(ctx, ch, flags);
1516 } else {
1517 jar_xm_trigger_note(ctx, ch, flags | jar_xm_TRIGGER_KEEP_PERIOD | jar_xm_TRIGGER_KEEP_SAMPLE_POSITION );
1518 }
1519 }
1520 break;
1521
1522 case 0xE: /* EEy: Pattern delay */
1523 ctx->extra_ticks = (ch->current->effect_param & 0x0F) * ctx->tempo;
1524 break;
1525 default:
1526 break;
1527 }
1528 break;
1529
1530 case 0xF: /* Fxx: Set tempo/BPM */
1531 if(s->effect_param > 0) {
1532 if(s->effect_param <= 0x1F) { // First 32 possible values adjust the ticks (goes into tempo)
1533 ctx->tempo = s->effect_param;
1534 } else { //32 and greater values adjust the BPM
1535 ctx->bpm = s->effect_param;
1536 }
1537 }
1538 break;
1539
1540 case 16: /* Gxx: Set global volume */
1541 ctx->global_volume = (float)((s->effect_param > 0x40) ? 0x40 : s->effect_param) / (float)0x40;
1542 break;
1543 case 17: /* Hxy: Global volume slide */
1544 if(s->effect_param > 0) { ch->global_volume_slide_param = s->effect_param; }
1545 break;
1546 case 21: /* Lxx: Set envelope position */
1547 ch->volume_envelope_frame_count = s->effect_param;
1548 ch->panning_envelope_frame_count = s->effect_param;
1549 break;
1550 case 25: /* Pxy: Panning slide */
1551 if(s->effect_param > 0) { ch->panning_slide_param = s->effect_param; }
1552 break;
1553 case 27: /* Rxy: Multi retrig note */
1554 if(s->effect_param > 0) {
1555 if((s->effect_param >> 4) == 0) { /* Keep previous x value */
1556 ch->multi_retrig_param = (ch->multi_retrig_param & 0xF0) | (s->effect_param & 0x0F);
1557 } else {
1558 ch->multi_retrig_param = s->effect_param;
1559 }
1560 }
1561 break;
1562 case 29: /* Txy: Tremor */
1563 if(s->effect_param > 0) { ch->tremor_param = s->effect_param; } /* Tremor x and y params are not separately kept in memory, unlike Rxy */
1564 break;
1565 case 33: /* Xxy: Extra stuff */
1566 switch(s->effect_param >> 4) {
1567 case 1: /* X1y: Extra fine portamento up */
1568 if(s->effect_param & 0x0F) { ch->extra_fine_portamento_up_param = s->effect_param & 0x0F; }
1569 jar_xm_pitch_slide(ctx, ch, -1.0f * ch->extra_fine_portamento_up_param);
1570 break;
1571 case 2: /* X2y: Extra fine portamento down */
1572 if(s->effect_param & 0x0F) { ch->extra_fine_portamento_down_param = s->effect_param & 0x0F; }
1573 jar_xm_pitch_slide(ctx, ch, ch->extra_fine_portamento_down_param);
1574 break;
1575 default:
1576 break;
1577 }
1578 break;
1579 default:
1580 break;
1581 }
1582}
1583
1584static void jar_xm_trigger_note(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, unsigned int flags) {
1585 if (!(flags & jar_xm_TRIGGER_KEEP_SAMPLE_POSITION)) {
1586 ch->sample_position = 0.f;
1587 ch->ping = true;
1588 };
1589
1590 if (!(flags & jar_xm_TRIGGER_KEEP_VOLUME)) {
1591 if(ch->sample != NULL) {
1592 ch->volume = ch->sample->volume;
1593 };
1594 };
1595 ch->panning = ch->sample->panning;
1596 ch->sustained = true;
1597 ch->fadeout_volume = ch->volume_envelope_volume = 1.0f;
1598 ch->panning_envelope_panning = .5f;
1599 ch->volume_envelope_frame_count = ch->panning_envelope_frame_count = 0;
1600 ch->vibrato_note_offset = 0.f;
1601 ch->tremolo_volume = 0.f;
1602 ch->tremor_on = false;
1603 ch->autovibrato_ticks = 0;
1604
1605 if(ch->vibrato_waveform_retrigger) { ch->vibrato_ticks = 0; } /* XXX: should the waveform itself also be reset to sine? */
1606 if(ch->tremolo_waveform_retrigger) { ch->tremolo_ticks = 0; }
1607 if(!(flags & jar_xm_TRIGGER_KEEP_PERIOD)) {
1608 ch->period = jar_xm_period(ctx, ch->note);
1609 jar_xm_update_frequency(ctx, ch);
1610 }
1611 ch->latest_trigger = ctx->generated_samples;
1612 if(ch->instrument != NULL) { ch->instrument->latest_trigger = ctx->generated_samples; }
1613 if(ch->sample != NULL) { ch->sample->latest_trigger = ctx->generated_samples; }
1614}
1615
1616static void jar_xm_cut_note(jar_xm_channel_context_t* ch) {
1617 ch->volume = .0f; /* NB: this is not the same as Key Off */
1618// ch->curr_left = .0f;
1619// ch->curr_right = .0f;
1620}
1621
1622static void jar_xm_key_off(jar_xm_channel_context_t* ch) {
1623 ch->sustained = false; /* Key Off */
1624 if(ch->instrument == NULL || !ch->instrument->volume_envelope.enabled) { jar_xm_cut_note(ch); } /* If no volume envelope is used, also cut the note */
1625}
1626
1627static void jar_xm_row(jar_xm_context_t* ctx) {
1628 if(ctx->position_jump) {
1629 ctx->current_table_index = ctx->jump_dest;
1630 ctx->current_row = ctx->jump_row;
1631 ctx->position_jump = false;
1632 ctx->pattern_break = false;
1633 ctx->jump_row = 0;
1634 jar_xm_post_pattern_change(ctx);
1635 } else if(ctx->pattern_break) {
1636 ctx->current_table_index++;
1637 ctx->current_row = ctx->jump_row;
1638 ctx->pattern_break = false;
1639 ctx->jump_row = 0;
1640 jar_xm_post_pattern_change(ctx);
1641 }
1642 jar_xm_pattern_t* cur = ctx->module.patterns + ctx->module.pattern_table[ctx->current_table_index];
1643 bool in_a_loop = false;
1644
1645 /* Read notes information for all channels into temporary pattern slot */
1646 for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
1647 jar_xm_pattern_slot_t* s = cur->slots + ctx->current_row * ctx->module.num_channels + i;
1648 jar_xm_channel_context_t* ch = ctx->channels + i;
1649 ch->current = s;
1650 // If there is no note delay effect (0xED) then...
1651 if(s->effect_type != 0xE || s->effect_param >> 4 != 0xD) {
1652 //********** Process the channel slot information **********
1653 jar_xm_handle_note_and_instrument(ctx, ch, s);
1654 } else {
1655 // read the note delay information
1656 ch->note_delay_param = s->effect_param & 0x0F;
1657 }
1658 if(!in_a_loop && ch->pattern_loop_count > 0) {
1659 // clarify if in a loop or not
1660 in_a_loop = true;
1661 }
1662 }
1663
1664 if(!in_a_loop) {
1665 /* No E6y loop is in effect (or we are in the first pass) */
1666 ctx->loop_count = (ctx->row_loop_count[MAX_NUM_ROWS * ctx->current_table_index + ctx->current_row]++);
1667 }
1668
1670 ctx->current_row++; /* uint8 warning: can increment from 255 to 0, in which case it is still necessary to go the next pattern. */
1671 if (!ctx->position_jump && !ctx->pattern_break && (ctx->current_row >= cur->num_rows || ctx->current_row == 0)) {
1672 ctx->current_table_index++;
1673 ctx->current_row = ctx->jump_row; /* This will be 0 most of the time, except when E60 is used */
1674 ctx->jump_row = 0;
1675 jar_xm_post_pattern_change(ctx);
1676 }
1677}
1678
1679static void jar_xm_envelope_tick(jar_xm_channel_context_t *ch, jar_xm_envelope_t *env, uint16_t *counter, float *outval) {
1680 if(env->num_points < 2) {
1681 if(env->num_points == 1) {
1682 *outval = (float)env->points[0].value / (float)0x40;
1683 if(*outval > 1) { *outval = 1; };
1684 } else {;
1685 return;
1686 };
1687 } else {
1688 if(env->loop_enabled) {
1689 uint16_t loop_start = env->points[env->loop_start_point].frame;
1690 uint16_t loop_end = env->points[env->loop_end_point].frame;
1691 uint16_t loop_length = loop_end - loop_start;
1692 if(*counter >= loop_end) { *counter -= loop_length; };
1693 };
1694 for(uint8_t j = 0; j < (env->num_points - 1); ++j) {
1695 if(env->points[j].frame <= *counter && env->points[j+1].frame >= *counter) {
1696 *outval = jar_xm_envelope_lerp(env->points + j, env->points + j + 1, *counter) / (float)0x40;
1697 break;
1698 };
1699 };
1700 /* Make sure it is safe to increment frame count */
1701 if(!ch->sustained || !env->sustain_enabled || *counter != env->points[env->sustain_point].frame) { (*counter)++; };
1702 };
1703};
1704
1705static void jar_xm_envelopes(jar_xm_channel_context_t *ch) {
1706 if(ch->instrument != NULL) {
1707 if(ch->instrument->volume_envelope.enabled) {
1708 if(!ch->sustained) {
1709 ch->fadeout_volume -= (float)ch->instrument->volume_fadeout / 65536.f;
1710 jar_xm_CLAMP_DOWN(ch->fadeout_volume);
1711 };
1712 jar_xm_envelope_tick(ch, &(ch->instrument->volume_envelope), &(ch->volume_envelope_frame_count), &(ch->volume_envelope_volume));
1713 };
1714 if(ch->instrument->panning_envelope.enabled) {
1715 jar_xm_envelope_tick(ch, &(ch->instrument->panning_envelope), &(ch->panning_envelope_frame_count), &(ch->panning_envelope_panning));
1716 };
1717 };
1718};
1719
1720static void jar_xm_tick(jar_xm_context_t* ctx) {
1721 if(ctx->current_tick == 0) {
1722 jar_xm_row(ctx); // We have processed all ticks and we run the row
1723 }
1724
1725 jar_xm_module_t* mod = &(ctx->module);
1726 for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
1727 jar_xm_channel_context_t* ch = ctx->channels + i;
1728 jar_xm_envelopes(ch);
1729 jar_xm_autovibrato(ctx, ch);
1730 if(ch->arp_in_progress && !HAS_ARPEGGIO(ch->current)) {
1731 ch->arp_in_progress = false;
1732 ch->arp_note_offset = 0;
1733 jar_xm_update_frequency(ctx, ch);
1734 }
1735 if(ch->vibrato_in_progress && !HAS_VIBRATO(ch->current)) {
1736 ch->vibrato_in_progress = false;
1737 ch->vibrato_note_offset = 0.f;
1738 jar_xm_update_frequency(ctx, ch);
1739 }
1740
1741 // Effects in volumne column mostly handled on a per tick basis
1742 switch(ch->current->volume_column & 0xF0) {
1743 case 0x50: // Checks for volume = 64
1744 if(ch->current->volume_column != 0x50) break;
1745 case 0x10: // Set volume 0-15
1746 case 0x20: // Set volume 16-32
1747 case 0x30: // Set volume 32-48
1748 case 0x40: // Set volume 48-64
1749 ch->volume = (float)(ch->current->volume_column - 16) / 64.0f;
1750 break;
1751 case 0x60: // Volume slide down
1752 jar_xm_volume_slide(ch, ch->current->volume_column & 0x0F);
1753 break;
1754 case 0x70: // Volume slide up
1755 jar_xm_volume_slide(ch, ch->current->volume_column << 4);
1756 break;
1757 case 0x80: // Fine volume slide down
1758 jar_xm_volume_slide(ch, ch->current->volume_column & 0x0F);
1759 break;
1760 case 0x90: // Fine volume slide up
1761 jar_xm_volume_slide(ch, ch->current->volume_column << 4);
1762 break;
1763 case 0xA0: // Set vibrato speed
1764 ch->vibrato_param = (ch->vibrato_param & 0x0F) | ((ch->current->volume_column & 0x0F) << 4);
1765 break;
1766 case 0xB0: // Vibrato
1767 ch->vibrato_in_progress = false;
1768 jar_xm_vibrato(ctx, ch, ch->vibrato_param, ch->vibrato_ticks++);
1769 break;
1770 case 0xC0: // Set panning
1771 if(!ctx->current_tick ) {
1772 ch->panning = (float)(ch->current->volume_column & 0x0F) / 15.0f;
1773 }
1774 break;
1775 case 0xD0: // Panning slide left
1776 jar_xm_panning_slide(ch, ch->current->volume_column & 0x0F);
1777 break;
1778 case 0xE0: // Panning slide right
1779 jar_xm_panning_slide(ch, ch->current->volume_column << 4);
1780 break;
1781 case 0xF0: // Tone portamento
1782 if(!ctx->current_tick ) {
1783 if(ch->current->volume_column & 0x0F) { ch->tone_portamento_param = ((ch->current->volume_column & 0x0F) << 4) | (ch->current->volume_column & 0x0F); }
1784 };
1785 jar_xm_tone_portamento(ctx, ch);
1786 break;
1787 default:
1788 break;
1789 }
1790
1791 // Only some standard effects handled on a per tick basis
1792 // see jar_xm_handle_note_and_instrument for all effects handling on a per row basis
1793 switch(ch->current->effect_type) {
1794 case 0: /* 0xy: Arpeggio */
1795 if(ch->current->effect_param > 0) {
1796 char arp_offset = ctx->tempo % 3;
1797 switch(arp_offset) {
1798 case 2: /* 0 -> x -> 0 -> y -> x -> … */
1799 if(ctx->current_tick == 1) {
1800 ch->arp_in_progress = true;
1801 ch->arp_note_offset = ch->current->effect_param >> 4;
1802 jar_xm_update_frequency(ctx, ch);
1803 break;
1804 }
1805 /* No break here, this is intended */
1806 case 1: /* 0 -> 0 -> y -> x -> … */
1807 if(ctx->current_tick == 0) {
1808 ch->arp_in_progress = false;
1809 ch->arp_note_offset = 0;
1810 jar_xm_update_frequency(ctx, ch);
1811 break;
1812 }
1813 /* No break here, this is intended */
1814 case 0: /* 0 -> y -> x -> … */
1815 jar_xm_arpeggio(ctx, ch, ch->current->effect_param, ctx->current_tick - arp_offset);
1816 default:
1817 break;
1818 }
1819 }
1820 break;
1821
1822 case 1: /* 1xx: Portamento up */
1823 if(ctx->current_tick == 0) break;
1824 jar_xm_pitch_slide(ctx, ch, -ch->portamento_up_param);
1825 break;
1826 case 2: /* 2xx: Portamento down */
1827 if(ctx->current_tick == 0) break;
1828 jar_xm_pitch_slide(ctx, ch, ch->portamento_down_param);
1829 break;
1830 case 3: /* 3xx: Tone portamento */
1831 if(ctx->current_tick == 0) break;
1832 jar_xm_tone_portamento(ctx, ch);
1833 break;
1834 case 4: /* 4xy: Vibrato */
1835 if(ctx->current_tick == 0) break;
1836 ch->vibrato_in_progress = true;
1837 jar_xm_vibrato(ctx, ch, ch->vibrato_param, ch->vibrato_ticks++);
1838 break;
1839 case 5: /* 5xy: Tone portamento + Volume slide */
1840 if(ctx->current_tick == 0) break;
1841 jar_xm_tone_portamento(ctx, ch);
1842 jar_xm_volume_slide(ch, ch->volume_slide_param);
1843 break;
1844 case 6: /* 6xy: Vibrato + Volume slide */
1845 if(ctx->current_tick == 0) break;
1846 ch->vibrato_in_progress = true;
1847 jar_xm_vibrato(ctx, ch, ch->vibrato_param, ch->vibrato_ticks++);
1848 jar_xm_volume_slide(ch, ch->volume_slide_param);
1849 break;
1850 case 7: /* 7xy: Tremolo */
1851 if(ctx->current_tick == 0) break;
1852 jar_xm_tremolo(ctx, ch, ch->tremolo_param, ch->tremolo_ticks++);
1853 break;
1854 case 8: /* 8xy: Set panning */
1855 break;
1856 case 9: /* 9xy: Sample offset */
1857 break;
1858 case 0xA: /* Axy: Volume slide */
1859 if(ctx->current_tick == 0) break;
1860 jar_xm_volume_slide(ch, ch->volume_slide_param);
1861 break;
1862 case 0xE: /* EXy: Extended command */
1863 switch(ch->current->effect_param >> 4) {
1864 case 0x9: /* E9y: Retrigger note */
1865 if(ctx->current_tick != 0 && ch->current->effect_param & 0x0F) {
1866 if(!(ctx->current_tick % (ch->current->effect_param & 0x0F))) {
1867 jar_xm_trigger_note(ctx, ch, 0);
1868 jar_xm_envelopes(ch);
1869 }
1870 }
1871 break;
1872 case 0xC: /* ECy: Note cut */
1873 if((ch->current->effect_param & 0x0F) == ctx->current_tick) {
1874 jar_xm_cut_note(ch);
1875 }
1876 break;
1877 case 0xD: /* EDy: Note delay */
1878 if(ch->note_delay_param == ctx->current_tick) {
1879 jar_xm_handle_note_and_instrument(ctx, ch, ch->current);
1880 jar_xm_envelopes(ch);
1881 }
1882 break;
1883 default:
1884 break;
1885 }
1886 break;
1887 case 16: /* Fxy: Set tempo/BPM */
1888 break;
1889 case 17: /* Hxy: Global volume slide */
1890 if(ctx->current_tick == 0) break;
1891 if((ch->global_volume_slide_param & 0xF0) && (ch->global_volume_slide_param & 0x0F)) { break; }; /* Invalid state */
1892 if(ch->global_volume_slide_param & 0xF0) { /* Global slide up */
1893 float f = (float)(ch->global_volume_slide_param >> 4) / (float)0x40;
1894 ctx->global_volume += f;
1895 jar_xm_CLAMP_UP(ctx->global_volume);
1896 } else { /* Global slide down */
1897 float f = (float)(ch->global_volume_slide_param & 0x0F) / (float)0x40;
1898 ctx->global_volume -= f;
1899 jar_xm_CLAMP_DOWN(ctx->global_volume);
1900 };
1901 break;
1902
1903 case 20: /* Kxx: Key off */
1904 if(ctx->current_tick == ch->current->effect_param) { jar_xm_key_off(ch); };
1905 break;
1906 case 21: /* Lxx: Set envelope position */
1907 break;
1908 case 25: /* Pxy: Panning slide */
1909 if(ctx->current_tick == 0) break;
1910 jar_xm_panning_slide(ch, ch->panning_slide_param);
1911 break;
1912 case 27: /* Rxy: Multi retrig note */
1913 if(ctx->current_tick == 0) break;
1914 if(((ch->multi_retrig_param) & 0x0F) == 0) break;
1915 if((ctx->current_tick % (ch->multi_retrig_param & 0x0F)) == 0) {
1916 float v = ch->volume * multi_retrig_multiply[ch->multi_retrig_param >> 4]
1917 + multi_retrig_add[ch->multi_retrig_param >> 4];
1918 jar_xm_CLAMP(v);
1919 jar_xm_trigger_note(ctx, ch, 0);
1920 ch->volume = v;
1921 };
1922 break;
1923
1924 case 29: /* Txy: Tremor */
1925 if(ctx->current_tick == 0) break;
1926 ch->tremor_on = ( (ctx->current_tick - 1) % ((ch->tremor_param >> 4) + (ch->tremor_param & 0x0F) + 2) > (ch->tremor_param >> 4) );
1927 break;
1928 default:
1929 break;
1930 };
1931
1932 float panning, volume;
1933 panning = ch->panning + (ch->panning_envelope_panning - .5f) * (.5f - fabs(ch->panning - .5f)) * 2.0f;
1934 if(ch->tremor_on) {
1935 volume = .0f;
1936 } else {
1937 volume = ch->volume + ch->tremolo_volume;
1938 jar_xm_CLAMP(volume);
1939 volume *= ch->fadeout_volume * ch->volume_envelope_volume;
1940 };
1941
1942 if (mod->ramping) {
1943 ch->target_panning = panning;
1944 ch->target_volume = volume;
1945 } else {
1946 ch->actual_panning = panning;
1947 ch->actual_volume = volume;
1948 };
1949 };
1950
1951 ctx->current_tick++; // ok so we understand that ticks increment within the row
1952 if(ctx->current_tick >= ctx->tempo + ctx->extra_ticks) {
1953 // This means it reached the end of the row and we reset
1954 ctx->current_tick = 0;
1955 ctx->extra_ticks = 0;
1956 };
1957
1958 // Number of ticks / second = BPM * 0.4
1959 ctx->remaining_samples_in_tick += (float)ctx->rate / ((float)ctx->bpm * 0.4f);
1960};
1961
1962static void jar_xm_next_of_sample(jar_xm_context_t* ctx, jar_xm_channel_context_t* ch, int previous) {
1963 jar_xm_module_t* mod = &(ctx->module);
1964
1965// ch->curr_left = 0.f;
1966// ch->curr_right = 0.f;
1967 if(ch->instrument == NULL || ch->sample == NULL || ch->sample_position < 0) {
1968 ch->curr_left = 0.f;
1969 ch->curr_right = 0.f;
1970 if (mod->ramping) {
1971 if (ch->frame_count < jar_xm_SAMPLE_RAMPING_POINTS) {
1972 if (previous > -1) {
1973 ch->end_of_previous_sample_left[previous] = jar_xm_LERP(ch->end_of_previous_sample_left[ch->frame_count], ch->curr_left, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
1974 ch->end_of_previous_sample_right[previous] = jar_xm_LERP(ch->end_of_previous_sample_right[ch->frame_count], ch->curr_right, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
1975 } else {
1976 ch->curr_left = jar_xm_LERP(ch->end_of_previous_sample_left[ch->frame_count], ch->curr_left, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
1977 ch->curr_right = jar_xm_LERP(ch->end_of_previous_sample_right[ch->frame_count], ch->curr_right, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
1978 };
1979 };
1980 };
1981 return;
1982 };
1983 if(ch->sample->length == 0) {
1984 return;
1985 };
1986
1987 float t = 0.f;
1988 uint32_t b = 0;
1989 if(mod->linear_interpolation) {
1990 b = ch->sample_position + 1;
1991 t = ch->sample_position - (uint32_t)ch->sample_position; /* Cheaper than fmodf(., 1.f) */
1992 };
1993
1994 float u_left, u_right;
1995 u_left = ch->sample->data[(uint32_t)ch->sample_position];
1996 if (ch->sample->stereo) {
1997 u_right = ch->sample->data[(uint32_t)ch->sample_position + ch->sample->length];
1998 } else {
1999 u_right = u_left;
2000 };
2001 float v_left = 0.f, v_right = 0.f;
2002 switch(ch->sample->loop_type) {
2003 case jar_xm_NO_LOOP:
2004 if(mod->linear_interpolation) {
2005 v_left = (b < ch->sample->length) ? ch->sample->data[b] : .0f;
2006 if (ch->sample->stereo) {
2007 v_right = (b < ch->sample->length) ? ch->sample->data[b + ch->sample->length] : .0f;
2008 } else {
2009 v_right = v_left;
2010 };
2011 };
2012 ch->sample_position += ch->step;
2013 if(ch->sample_position >= ch->sample->length) { ch->sample_position = -1; } // stop playing this sample
2014 break;
2015 case jar_xm_FORWARD_LOOP:
2016 if(mod->linear_interpolation) {
2017 v_left = ch->sample->data[ (b == ch->sample->loop_end) ? ch->sample->loop_start : b ];
2018 if (ch->sample->stereo) {
2019 v_right = ch->sample->data[ (b == ch->sample->loop_end) ? ch->sample->loop_start + ch->sample->length : b + ch->sample->length];
2020 } else {
2021 v_right = v_left;
2022 };
2023 };
2024 ch->sample_position += ch->step;
2025 if (ch->sample_position >= ch->sample->loop_end) {
2026 ch->sample_position -= ch->sample->loop_length;
2027 };
2028 if(ch->sample_position >= ch->sample->length) {
2029 ch->sample_position = ch->sample->loop_start;
2030 };
2031 break;
2032 case jar_xm_PING_PONG_LOOP:
2033 if(ch->ping) {
2034 if(mod->linear_interpolation) {
2035 v_left = (b >= ch->sample->loop_end) ? ch->sample->data[(uint32_t)ch->sample_position] : ch->sample->data[b];
2036 if (ch->sample->stereo) {
2037 v_right = (b >= ch->sample->loop_end) ? ch->sample->data[(uint32_t)ch->sample_position + ch->sample->length] : ch->sample->data[b + ch->sample->length];
2038 } else {
2039 v_right = v_left;
2040 };
2041 };
2042 ch->sample_position += ch->step;
2043 if(ch->sample_position >= ch->sample->loop_end) {
2044 ch->ping = false;
2045 ch->sample_position = (ch->sample->loop_end << 1) - ch->sample_position;
2046 };
2047 if(ch->sample_position >= ch->sample->length) {
2048 ch->ping = false;
2049 ch->sample_position -= ch->sample->length - 1;
2050 };
2051 } else {
2052 if(mod->linear_interpolation) {
2053 v_left = u_left;
2054 v_right = u_right;
2055 u_left = (b == 1 || b - 2 <= ch->sample->loop_start) ? ch->sample->data[(uint32_t)ch->sample_position] : ch->sample->data[b - 2];
2056 if (ch->sample->stereo) {
2057 u_right = (b == 1 || b - 2 <= ch->sample->loop_start) ? ch->sample->data[(uint32_t)ch->sample_position + ch->sample->length] : ch->sample->data[b + ch->sample->length - 2];
2058 } else {
2059 u_right = u_left;
2060 };
2061 };
2062 ch->sample_position -= ch->step;
2063 if(ch->sample_position <= ch->sample->loop_start) {
2064 ch->ping = true;
2065 ch->sample_position = (ch->sample->loop_start << 1) - ch->sample_position;
2066 };
2067 if (ch->sample_position <= .0f) {
2068 ch->ping = true;
2069 ch->sample_position = .0f;
2070 };
2071 };
2072 break;
2073
2074 default:
2075 v_left = .0f;
2076 v_right = .0f;
2077 break;
2078 };
2079
2080 float endval_left = mod->linear_interpolation ? jar_xm_LERP(u_left, v_left, t) : u_left;
2081 float endval_right = mod->linear_interpolation ? jar_xm_LERP(u_right, v_right, t) : u_right;
2082
2083 if (mod->ramping) {
2084 if(ch->frame_count < jar_xm_SAMPLE_RAMPING_POINTS) {
2085 /* Smoothly transition between old and new sample. */
2086 if (previous > -1) {
2087 ch->end_of_previous_sample_left[previous] = jar_xm_LERP(ch->end_of_previous_sample_left[ch->frame_count], endval_left, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
2088 ch->end_of_previous_sample_right[previous] = jar_xm_LERP(ch->end_of_previous_sample_right[ch->frame_count], endval_right, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
2089 } else {
2090 ch->curr_left = jar_xm_LERP(ch->end_of_previous_sample_left[ch->frame_count], endval_left, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
2091 ch->curr_right = jar_xm_LERP(ch->end_of_previous_sample_right[ch->frame_count], endval_right, (float)ch->frame_count / (float)jar_xm_SAMPLE_RAMPING_POINTS);
2092 };
2093 };
2094 };
2095
2096 if (previous > -1) {
2097 ch->end_of_previous_sample_left[previous] = endval_left;
2098 ch->end_of_previous_sample_right[previous] = endval_right;
2099 } else {
2100 ch->curr_left = endval_left;
2101 ch->curr_right = endval_right;
2102 };
2103};
2104
2105// gather all channel audio into stereo float
2106static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) {
2107 jar_xm_module_t* mod = &(ctx->module);
2108
2109 if(ctx->remaining_samples_in_tick <= 0) {
2110 jar_xm_tick(ctx);
2111 };
2112 ctx->remaining_samples_in_tick--;
2113 *left = 0.f;
2114 *right = 0.f;
2115 if(ctx->max_loop_count > 0 && ctx->loop_count > ctx->max_loop_count) { return; }
2116
2117 for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
2118 jar_xm_channel_context_t* ch = ctx->channels + i;
2119 if(ch->instrument != NULL && ch->sample != NULL && ch->sample_position >= 0) {
2120 jar_xm_next_of_sample(ctx, ch, -1);
2121 if(!ch->muted && !ch->instrument->muted) {
2122 *left += ch->curr_left * ch->actual_volume * (1.f - ch->actual_panning);
2123 *right += ch->curr_right * ch->actual_volume * ch->actual_panning;
2124 };
2125
2126 if (mod->ramping) {
2127 ch->frame_count++;
2128 jar_xm_SLIDE_TOWARDS(ch->actual_volume, ch->target_volume, ctx->volume_ramp);
2129 jar_xm_SLIDE_TOWARDS(ch->actual_panning, ch->target_panning, ctx->panning_ramp);
2130 };
2131 };
2132 };
2133 if (ctx->global_volume != 1.0f) {
2134 *left *= ctx->global_volume;
2135 *right *= ctx->global_volume;
2136 };
2137
2138 // experimental
2139// float counter = (float)ctx->generated_samples * 0.0001f
2140// *left = tan(&left + sin(counter));
2141// *right = tan(&right + cos(counter));
2142
2143 // apply brick wall limiter when audio goes beyond bounderies
2144 if(*left < -1.0) {*left = -1.0;} else if(*left > 1.0) {*left = 1.0;};
2145 if(*right < -1.0) {*right = -1.0;} else if(*right > 1.0) {*right = 1.0;};
2146};
2147
2148void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsamples) {
2149 if(ctx && output) {
2150 ctx->generated_samples += numsamples;
2151 for(size_t i = 0; i < numsamples; i++) {
2152 jar_xm_mixdown(ctx, output + (2 * i), output + (2 * i + 1));
2153 };
2154 };
2155};
2156
2158 uint64_t total = 0;
2159 uint8_t currentLoopCount = jar_xm_get_loop_count(ctx);
2161 while(jar_xm_get_loop_count(ctx) == currentLoopCount) {
2162 total += ctx->remaining_samples_in_tick;
2163 ctx->remaining_samples_in_tick = 0;
2164 jar_xm_tick(ctx);
2165 }
2166 ctx->loop_count = currentLoopCount;
2167 return total;
2168}
2169
2170//--------------------------------------------
2171//FILE LOADER - TODO - NEEDS TO BE CLEANED UP
2172//--------------------------------------------
2173#undef DEBUG
2174#define DEBUG(...) do { \
2175 fprintf(stderr, __VA_ARGS__); \
2176 fflush(stderr); \
2177 } while(0)
2178
2179#define DEBUG_ERR(...) do { \
2180 fprintf(stderr, __VA_ARGS__); \
2181 fflush(stderr); \
2182 } while(0)
2183
2184#define FATAL(...) do { \
2185 fprintf(stderr, __VA_ARGS__); \
2186 fflush(stderr); \
2187 exit(1); \
2188 } while(0)
2189
2190#define FATAL_ERR(...) do { \
2191 fprintf(stderr, __VA_ARGS__); \
2192 fflush(stderr); \
2193 exit(1); \
2194 } while(0)
2195
2196
2197int jar_xm_create_context_from_file(jar_xm_context_t** ctx, uint32_t rate, const char* filename) {
2198 FILE* xmf;
2199 int size;
2200 int ret;
2201
2202 xmf = fopen(filename, "rb");
2203 if(xmf == NULL) {
2204 DEBUG_ERR("Could not open input file");
2205 *ctx = NULL;
2206 return 3;
2207 }
2208
2209 fseek(xmf, 0, SEEK_END);
2210 size = ftell(xmf);
2211 rewind(xmf);
2212 if(size == -1) {
2213 fclose(xmf);
2214 DEBUG_ERR("fseek() failed");
2215 *ctx = NULL;
2216 return 4;
2217 }
2218
2219 char* data = JARXM_MALLOC(size + 1);
2220 if(!data || fread(data, 1, size, xmf) < size) {
2221 fclose(xmf);
2222 DEBUG_ERR(data ? "fread() failed" : "JARXM_MALLOC() failed");
2223 JARXM_FREE(data);
2224 *ctx = NULL;
2225 return 5;
2226 }
2227
2228 fclose(xmf);
2229
2230 ret = jar_xm_create_context_safe(ctx, data, size, rate);
2231 JARXM_FREE(data);
2232
2233 switch(ret) {
2234 case 0:
2235 break;
2236 case 1: DEBUG("could not create context: module is not sane\n");
2237 *ctx = NULL;
2238 return 1;
2239 break;
2240 case 2: FATAL("could not create context: malloc failed\n");
2241 return 2;
2242 break;
2243 default: FATAL("could not create context: unknown error\n");
2244 return 6;
2245 break;
2246 }
2247
2248 return 0;
2249}
2250
2251// not part of the original library
2252void jar_xm_reset(jar_xm_context_t* ctx) {
2253 for (uint16_t i = 0; i < jar_xm_get_number_of_channels(ctx); i++) {
2254 jar_xm_cut_note(&ctx->channels[i]);
2255 }
2256 ctx->generated_samples = 0;
2257 ctx->current_row = 0;
2258 ctx->current_table_index = 0;
2259 ctx->current_tick = 0;
2260 ctx->tempo =ctx->default_tempo; // reset to file default value
2261 ctx->bpm = ctx->default_bpm; // reset to file default value
2262 ctx->global_volume = ctx->default_global_volume; // reset to file default value
2263}
2264
2265
2266void jar_xm_flip_linear_interpolation(jar_xm_context_t* ctx) {
2267 if (ctx->module.linear_interpolation) {
2268 ctx->module.linear_interpolation = 0;
2269 } else {
2270 ctx->module.linear_interpolation = 1;
2271 }
2272}
2273
2274void jar_xm_table_jump(jar_xm_context_t* ctx, int table_ptr) {
2275 for (uint16_t i = 0; i < jar_xm_get_number_of_channels(ctx); i++) {
2276 jar_xm_cut_note(&ctx->channels[i]);
2277 }
2278 ctx->current_row = 0;
2279 ctx->current_tick = 0;
2280 if(table_ptr > 0 && table_ptr < ctx->module.length) {
2281 ctx->current_table_index = table_ptr;
2282 ctx->module.restart_position = table_ptr; // The reason to jump is to start a new loop or track
2283 } else {
2284 ctx->current_table_index = 0;
2285 ctx->module.restart_position = 0; // The reason to jump is to start a new loop or track
2286 ctx->tempo =ctx->default_tempo; // reset to file default value
2287 ctx->bpm = ctx->default_bpm; // reset to file default value
2288 ctx->global_volume = ctx->default_global_volume; // reset to file default value
2289 };
2290}
2291
2292
2293// TRANSLATE NOTE NUMBER INTO USER VALUE (ie. 1 = C-1, 2 = C#1, 3 = D-1 ... )
2294const char* xm_note_chr(int number) {
2295 if (number == NOTE_OFF) {
2296 return "==";
2297 };
2298 number = number % 12;
2299 switch(number) {
2300 case 1: return "C-";
2301 case 2: return "C#";
2302 case 3: return "D-";
2303 case 4: return "D#";
2304 case 5: return "E-";
2305 case 6: return "F-";
2306 case 7: return "F#";
2307 case 8: return "G-";
2308 case 9: return "G#";
2309 case 10: return "A-";
2310 case 11: return "A#";
2311 case 12: return "B-";
2312 };
2313 return "??";
2314};
2315
2316const char* xm_octave_chr(int number) {
2317 if (number == NOTE_OFF) {
2318 return "=";
2319 };
2320
2321 int number2 = number - number % 12;
2322 int result = floor(number2 / 12) + 1;
2323 switch(result) {
2324 case 1: return "1";
2325 case 2: return "2";
2326 case 3: return "3";
2327 case 4: return "4";
2328 case 5: return "5";
2329 case 6: return "6";
2330 case 7: return "7";
2331 case 8: return "8";
2332 default: return "?"; /* UNKNOWN */
2333 };
2334
2335};
2336
2337// TRANSLATE NOTE EFFECT CODE INTO USER VALUE
2338const char* xm_effect_chr(int fx) {
2339 switch(fx) {
2340 case 0: return "0"; /* ZERO = NO EFFECT */
2341 case 1: return "1"; /* 1xx: Portamento up */
2342 case 2: return "2"; /* 2xx: Portamento down */
2343 case 3: return "3"; /* 3xx: Tone portamento */
2344 case 4: return "4"; /* 4xy: Vibrato */
2345 case 5: return "5"; /* 5xy: Tone portamento + Volume slide */
2346 case 6: return "6"; /* 6xy: Vibrato + Volume slide */
2347 case 7: return "7"; /* 7xy: Tremolo */
2348 case 8: return "8"; /* 8xx: Set panning */
2349 case 9: return "9"; /* 9xx: Sample offset */
2350 case 0xA: return "A";/* Axy: Volume slide */
2351 case 0xB: return "B";/* Bxx: Position jump */
2352 case 0xC: return "C";/* Cxx: Set volume */
2353 case 0xD: return "D";/* Dxx: Pattern break */
2354 case 0xE: return "E";/* EXy: Extended command */
2355 case 0xF: return "F";/* Fxx: Set tempo/BPM */
2356 case 16: return "G"; /* Gxx: Set global volume */
2357 case 17: return "H"; /* Hxy: Global volume slide */
2358 case 21: return "L"; /* Lxx: Set envelope position */
2359 case 25: return "P"; /* Pxy: Panning slide */
2360 case 27: return "R"; /* Rxy: Multi retrig note */
2361 case 29: return "T"; /* Txy: Tremor */
2362 case 33: return "X"; /* Xxy: Extra stuff */
2363 default: return "?"; /* UNKNOWN */
2364 };
2365}
2366
2367#ifdef JAR_XM_RAYLIB
2368
2369#include "raylib.h" // Need RayLib API calls for the DEBUG display
2370
2371void jar_xm_debug(jar_xm_context_t *ctx) {
2372 int size=40;
2373 int x = 0, y = 0;
2374
2375 // DEBUG VARIABLES
2376 y += size; DrawText(TextFormat("CUR TBL = %i", ctx->current_table_index), x, y, size, WHITE);
2377 y += size; DrawText(TextFormat("CUR PAT = %i", ctx->module.pattern_table[ctx->current_table_index]), x, y, size, WHITE);
2378 y += size; DrawText(TextFormat("POS JMP = %d", ctx->position_jump), x, y, size, WHITE);
2379 y += size; DrawText(TextFormat("JMP DST = %i", ctx->jump_dest), x, y, size, WHITE);
2380 y += size; DrawText(TextFormat("PTN BRK = %d", ctx->pattern_break), x, y, size, WHITE);
2381 y += size; DrawText(TextFormat("CUR ROW = %i", ctx->current_row), x, y, size, WHITE);
2382 y += size; DrawText(TextFormat("JMP ROW = %i", ctx->jump_row), x, y, size, WHITE);
2383 y += size; DrawText(TextFormat("ROW LCT = %i", ctx->row_loop_count), x, y, size, WHITE);
2384 y += size; DrawText(TextFormat("LCT = %i", ctx->loop_count), x, y, size, WHITE);
2385 y += size; DrawText(TextFormat("MAX LCT = %i", ctx->max_loop_count), x, y, size, WHITE);
2386 x = size * 12; y = 0;
2387
2388 y += size; DrawText(TextFormat("CUR TCK = %i", ctx->current_tick), x, y, size, WHITE);
2389 y += size; DrawText(TextFormat("XTR TCK = %i", ctx->extra_ticks), x, y, size, WHITE);
2390 y += size; DrawText(TextFormat("TCK/ROW = %i", ctx->tempo), x, y, size, ORANGE);
2391 y += size; DrawText(TextFormat("SPL TCK = %f", ctx->remaining_samples_in_tick), x, y, size, WHITE);
2392 y += size; DrawText(TextFormat("GEN SPL = %i", ctx->generated_samples), x, y, size, WHITE);
2393 y += size * 7;
2394
2395 x = 0;
2396 size=16;
2397 // TIMELINE OF MODULE
2398 for (int i=0; i < ctx->module.length; i++) {
2399 if (i == ctx->jump_dest) {
2400 if (ctx->position_jump) {
2401 DrawRectangle(i * size * 2, y - size, size * 2, size, GOLD);
2402 } else {
2403 DrawRectangle(i * size * 2, y - size, size * 2, size, BROWN);
2404 };
2405 };
2406 if (i == ctx->current_table_index) {
2407// DrawText(TextFormat("%02X", ctx->current_tick), i * size * 2, y - size, size, WHITE);
2408 DrawRectangle(i * size * 2, y, size * 2, size, RED);
2409 DrawText(TextFormat("%02X", ctx->current_row), i * size * 2, y - size, size, YELLOW);
2410 } else {
2411 DrawRectangle(i * size * 2, y, size * 2, size, ORANGE);
2412 };
2413 DrawText(TextFormat("%02X", ctx->module.pattern_table[i]), i * size * 2, y, size, WHITE);
2414 };
2415 y += size;
2416
2417 jar_xm_pattern_t* cur = ctx->module.patterns + ctx->module.pattern_table[ctx->current_table_index];
2418
2419 /* DISPLAY CURRENTLY PLAYING PATTERN */
2420
2421 x += 2 * size;
2422 for(uint8_t i = 0; i < ctx->module.num_channels; i++) {
2423 DrawRectangle(x, y, 8 * size, size, PURPLE);
2424 DrawText("N", x, y, size, YELLOW);
2425 DrawText("I", x + size * 2, y, size, YELLOW);
2426 DrawText("V", x + size * 4, y, size, YELLOW);
2427 DrawText("FX", x + size * 6, y, size, YELLOW);
2428 x += 9 * size;
2429 };
2430 x += size;
2431 for (int j=(ctx->current_row - 14); j<(ctx->current_row + 15); j++) {
2432 y += size;
2433 x = 0;
2434 if (j >=0 && j < (cur->num_rows)) {
2435 DrawRectangle(x, y, size * 2, size, BROWN);
2436 DrawText(TextFormat("%02X",j), x, y, size, WHITE);
2437 x += 2 * size;
2438 for(uint8_t i = 0; i < ctx->module.num_channels; i++) {
2439 if (j==(ctx->current_row)) {
2440 DrawRectangle(x, y, 8 * size, size, DARKGREEN);
2441 } else {
2442 DrawRectangle(x, y, 8 * size, size, DARKGRAY);
2443 };
2444 jar_xm_pattern_slot_t *s = cur->slots + j * ctx->module.num_channels + i;
2445 // jar_xm_channel_context_t *ch = ctx->channels + i;
2446 if (s->note > 0) {DrawText(TextFormat("%s%s", xm_note_chr(s->note), xm_octave_chr(s->note) ), x, y, size, WHITE);} else {DrawText("...", x, y, size, GRAY);};
2447 if (s->instrument > 0) {
2448 DrawText(TextFormat("%02X", s->instrument), x + size * 2, y, size, WHITE);
2449 if (s->volume_column == 0) {
2450 DrawText(TextFormat("%02X", 64), x + size * 4, y, size, YELLOW);
2451 };
2452 } else {
2453 DrawText("..", x + size * 2, y, size, GRAY);
2454 if (s->volume_column == 0) {
2455 DrawText("..", x + size * 4, y, size, GRAY);
2456 };
2457 };
2458 if (s->volume_column > 0) {DrawText(TextFormat("%02X", (s->volume_column - 16)), x + size * 4, y, size, WHITE);};
2459 if (s->effect_type > 0 || s->effect_param > 0) {DrawText(TextFormat("%s%02X", xm_effect_chr(s->effect_type), s->effect_param), x + size * 6, y, size, WHITE);};
2460 x += 9 * size;
2461 };
2462 };
2463 };
2464
2465}
2466#endif // RayLib extension
2467
2468#endif//end of JAR_XM_IMPLEMENTATION
2469//-------------------------------------------------------------------------------
2470
2471#endif//end of INCLUDE_JAR_XM_H
uint16_t jar_xm_get_module_length(jar_xm_context_t *)
uint16_t jar_xm_get_number_of_rows(jar_xm_context_t *ctx, uint16_t)
uint64_t jar_xm_get_latest_trigger_of_instrument(jar_xm_context_t *ctx, uint16_t)
void jar_xm_set_max_loop_count(jar_xm_context_t *ctx, uint8_t loopcnt)
uint16_t jar_xm_get_number_of_samples(jar_xm_context_t *ctx, uint16_t)
uint16_t jar_xm_get_number_of_instruments(jar_xm_context_t *ctx)
#define JARXM_MALLOC(sz)
Definition: jar_xm.h:67
void jar_xm_free_context(jar_xm_context_t *ctx)
void jar_xm_get_position(jar_xm_context_t *ctx, uint8_t *pattern_index, uint8_t *pattern, uint8_t *row, uint64_t *samples)
int jar_xm_create_context(jar_xm_context_t **ctx, const char *moddata, uint32_t rate)
const char * jar_xm_get_module_name(jar_xm_context_t *ctx)
#define JARXM_FREE(p)
Definition: jar_xm.h:70
void jar_xm_generate_samples(jar_xm_context_t *ctx, float *output, size_t numsamples)
bool jar_xm_mute_channel(jar_xm_context_t *ctx, uint16_t, bool)
uint16_t jar_xm_get_number_of_patterns(jar_xm_context_t *ctx)
bool jar_xm_mute_instrument(jar_xm_context_t *ctx, uint16_t, bool)
uint8_t jar_xm_get_loop_count(jar_xm_context_t *ctx)
void jar_xm_generate_samples_16bit(jar_xm_context_t *ctx, short *output, size_t numsamples)
Definition: jar_xm.h:125
uint64_t jar_xm_get_latest_trigger_of_sample(jar_xm_context_t *ctx, uint16_t instr, uint16_t sample)
const char * jar_xm_get_tracker_name(jar_xm_context_t *ctx)
void jar_xm_get_playing_speed(jar_xm_context_t *ctx, uint16_t *bpm, uint16_t *tempo)
int jar_xm_create_context_safe(jar_xm_context_t **ctx, const char *moddata, size_t moddata_length, uint32_t rate)
void jar_xm_generate_samples_8bit(jar_xm_context_t *ctx, char *output, size_t numsamples)
Definition: jar_xm.h:138
#define JAR_XM_DEBUG
Definition: jar_xm.h:61
uint64_t jar_xm_get_latest_trigger_of_channel(jar_xm_context_t *ctx, uint16_t)
uint16_t jar_xm_get_number_of_channels(jar_xm_context_t *ctx)
uint64_t jar_xm_get_remaining_samples(jar_xm_context_t *ctx)
struct jar_xm_context_s jar_xm_context_t
Definition: jar_xm.h:75
int jar_xm_create_context_from_file(jar_xm_context_t **ctx, uint32_t rate, const char *filename)
#define NULL
Definition: miniaudio.h:3718
RLAPI const char * TextFormat(const char *text,...)
Definition: rtext.c:1278
#define PURPLE
Definition: raylib.h:163
#define DARKGREEN
Definition: raylib.h:159
#define DARKGRAY
Definition: raylib.h:150
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
Definition: rtext.c:1007
#define WHITE
Definition: raylib.h:170
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color)
Definition: rshapes.c:664
#define RED
Definition: raylib.h:155
#define BROWN
Definition: raylib.h:167
#define YELLOW
Definition: raylib.h:151
#define ORANGE
Definition: raylib.h:153
#define GRAY
Definition: raylib.h:149
#define GOLD
Definition: raylib.h:152
signed short int16_t
Definition: stdint.h:76
unsigned short uint16_t
Definition: stdint.h:79
#define SIZE_MAX
Definition: stdint.h:206
unsigned int uint32_t
Definition: stdint.h:80
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90
signed char int8_t
Definition: stdint.h:75
muchar length
Definition: jar_mod.h:127
Definition: jar_mod.h:117
muchar name[22]
Definition: jar_mod.h:109
muchar finetune
Definition: jar_mod.h:111
muint length
Definition: jar_mod.h:110
muchar volume
Definition: jar_mod.h:112