github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/jar_xm.h (about)

     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  //-------------------------------------------------------------------------------
    74  struct jar_xm_context_s;
    75  typedef struct jar_xm_context_s jar_xm_context_t;
    76  
    77  #ifdef __cplusplus
    78  extern "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()
    93  int 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()
   103  int 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
   112  int 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(). */
   115  void jar_xm_free_context(jar_xm_context_t* ctx);
   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
   120  void 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
   125  void 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
   138  void 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.
   150  void jar_xm_set_max_loop_count(jar_xm_context_t* ctx, uint8_t loopcnt);
   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.
   153  uint8_t jar_xm_get_loop_count(jar_xm_context_t* ctx);
   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.
   158  bool jar_xm_mute_channel(jar_xm_context_t* ctx, uint16_t, bool);
   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.
   163  bool jar_xm_mute_instrument(jar_xm_context_t* ctx, uint16_t, bool);
   164  
   165  //** Get the module name as a NUL-terminated string.
   166  const char* jar_xm_get_module_name(jar_xm_context_t* ctx);
   167  
   168  //** Get the tracker name as a NUL-terminated string.
   169  const char* jar_xm_get_tracker_name(jar_xm_context_t* ctx);
   170  
   171  //** Get the number of channels.
   172  uint16_t jar_xm_get_number_of_channels(jar_xm_context_t* ctx);
   173  
   174  //** Get the module length (in patterns).
   175  uint16_t jar_xm_get_module_length(jar_xm_context_t*);
   176  
   177  //** Get the number of patterns.
   178  uint16_t jar_xm_get_number_of_patterns(jar_xm_context_t* ctx);
   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.
   182  uint16_t jar_xm_get_number_of_rows(jar_xm_context_t* ctx, uint16_t);
   183  
   184  //** Get the number of instruments.
   185  uint16_t jar_xm_get_number_of_instruments(jar_xm_context_t* ctx);
   186  
   187  //** Get the number of samples of an instrument.
   188  // * @note Instrument numbers go from 1 to jar_xm_get_number_of_instruments(...).
   189  uint16_t jar_xm_get_number_of_samples(jar_xm_context_t* ctx, uint16_t);
   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)
   194  void jar_xm_get_playing_speed(jar_xm_context_t* ctx, uint16_t* bpm, uint16_t* tempo);
   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)
   202  void 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(...).
   206  uint64_t jar_xm_get_latest_trigger_of_instrument(jar_xm_context_t* ctx, uint16_t);
   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.
   211  uint64_t jar_xm_get_latest_trigger_of_sample(jar_xm_context_t* ctx, uint16_t instr, uint16_t sample);
   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(...).
   215  uint64_t jar_xm_get_latest_trigger_of_channel(jar_xm_context_t* ctx, uint16_t);
   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.
   220  uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx);
   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 */
   248  extern 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  
   265  enum 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  };
   272  typedef enum jar_xm_waveform_type_e jar_xm_waveform_type_t;
   273  
   274  enum jar_xm_loop_type_e {
   275      jar_xm_NO_LOOP,
   276      jar_xm_FORWARD_LOOP,
   277      jar_xm_PING_PONG_LOOP,
   278  };
   279  typedef enum jar_xm_loop_type_e jar_xm_loop_type_t;
   280  
   281  enum jar_xm_frequency_type_e {
   282      jar_xm_LINEAR_FREQUENCIES,
   283      jar_xm_AMIGA_FREQUENCIES,
   284  };
   285  typedef enum jar_xm_frequency_type_e jar_xm_frequency_type_t;
   286  
   287  struct jar_xm_envelope_point_s {
   288      uint16_t frame;
   289      uint16_t value;
   290  };
   291  typedef struct jar_xm_envelope_point_s jar_xm_envelope_point_t;
   292  
   293  struct 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  };
   303  typedef struct jar_xm_envelope_s jar_xm_envelope_t;
   304  
   305  struct 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.
   492  int 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.
   496  int 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.
   511  size_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
   515  char* jar_xm_load_module(jar_xm_context_t*, const char*, size_t, char*);
   516  
   517  int 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))
   523  int 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);
   585          jar_xm_free_context(ctx);
   586          return 1;
   587      }
   588  #endif
   589  
   590      return 0;
   591  }
   592  
   593  void jar_xm_free_context(jar_xm_context_t *ctx) {
   594      if (ctx != NULL) {   JARXM_FREE(ctx->allocated_memory); }
   595  }
   596  
   597  void jar_xm_set_max_loop_count(jar_xm_context_t *ctx, uint8_t loopcnt) {
   598      ctx->max_loop_count = loopcnt;
   599  }
   600  
   601  uint8_t jar_xm_get_loop_count(jar_xm_context_t *ctx) {
   602      return ctx->loop_count;
   603  }
   604  
   605  bool jar_xm_mute_channel(jar_xm_context_t *ctx, uint16_t channel, bool mute) {
   606      bool old = ctx->channels[channel - 1].muted;
   607      ctx->channels[channel - 1].muted = mute;
   608      return old;
   609  }
   610  
   611  bool 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  
   617  const char* jar_xm_get_module_name(jar_xm_context_t *ctx) {
   618      return ctx->module.name;
   619  }
   620  
   621  const char* jar_xm_get_tracker_name(jar_xm_context_t *ctx) {
   622      return ctx->module.trackername;
   623  }
   624  
   625  uint16_t jar_xm_get_number_of_channels(jar_xm_context_t *ctx) {
   626      return ctx->module.num_channels;
   627  }
   628  
   629  uint16_t jar_xm_get_module_length(jar_xm_context_t *ctx) {
   630      return ctx->module.length;
   631  }
   632  
   633  uint16_t jar_xm_get_number_of_patterns(jar_xm_context_t *ctx) {
   634      return ctx->module.num_patterns;
   635  }
   636  
   637  uint16_t jar_xm_get_number_of_rows(jar_xm_context_t *ctx, uint16_t pattern) {
   638      return ctx->module.patterns[pattern].num_rows;
   639  }
   640  
   641  uint16_t jar_xm_get_number_of_instruments(jar_xm_context_t *ctx) {
   642      return ctx->module.num_instruments;
   643  }
   644  
   645  uint16_t jar_xm_get_number_of_samples(jar_xm_context_t *ctx, uint16_t instrument) {
   646      return ctx->module.instruments[instrument - 1].num_samples;
   647  }
   648  
   649  void jar_xm_get_playing_speed(jar_xm_context_t *ctx, uint16_t *bpm, uint16_t *tempo) {
   650      if(bpm) *bpm = ctx->bpm;
   651      if(tempo) *tempo = ctx->tempo;
   652  }
   653  
   654  void 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  
   661  uint64_t jar_xm_get_latest_trigger_of_instrument(jar_xm_context_t *ctx, uint16_t instr) {
   662      return ctx->module.instruments[instr - 1].latest_trigger;
   663  }
   664  
   665  uint64_t jar_xm_get_latest_trigger_of_sample(jar_xm_context_t *ctx, uint16_t instr, uint16_t sample) {
   666      return ctx->module.instruments[instr - 1].samples[sample].latest_trigger;
   667  }
   668  
   669  uint64_t jar_xm_get_latest_trigger_of_channel(jar_xm_context_t *ctx, uint16_t chn) {
   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  
   682  static 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  
   697  int 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  
   705  int 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  
   724  size_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  
   784  char* 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
  1050  static float jar_xm_waveform(jar_xm_waveform_type_t, uint8_t);
  1051  static void jar_xm_autovibrato(jar_xm_context_t*, jar_xm_channel_context_t*);
  1052  static void jar_xm_vibrato(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
  1053  static void jar_xm_tremolo(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
  1054  static void jar_xm_arpeggio(jar_xm_context_t*, jar_xm_channel_context_t*, uint8_t, uint16_t);
  1055  static void jar_xm_tone_portamento(jar_xm_context_t*, jar_xm_channel_context_t*);
  1056  static void jar_xm_pitch_slide(jar_xm_context_t*, jar_xm_channel_context_t*, float);
  1057  static void jar_xm_panning_slide(jar_xm_channel_context_t*, uint8_t);
  1058  static void jar_xm_volume_slide(jar_xm_channel_context_t*, uint8_t);
  1059  
  1060  static float jar_xm_envelope_lerp(jar_xm_envelope_point_t*, jar_xm_envelope_point_t*, uint16_t);
  1061  static void jar_xm_envelope_tick(jar_xm_channel_context_t*, jar_xm_envelope_t*, uint16_t*, float*);
  1062  static void jar_xm_envelopes(jar_xm_channel_context_t*);
  1063  
  1064  static float jar_xm_linear_period(float);
  1065  static float jar_xm_linear_frequency(float);
  1066  static float jar_xm_amiga_period(float);
  1067  static float jar_xm_amiga_frequency(float);
  1068  static float jar_xm_period(jar_xm_context_t*, float);
  1069  static float jar_xm_frequency(jar_xm_context_t*, float, float);
  1070  static void jar_xm_update_frequency(jar_xm_context_t*, jar_xm_channel_context_t*);
  1071  
  1072  static void jar_xm_handle_note_and_instrument(jar_xm_context_t*, jar_xm_channel_context_t*, jar_xm_pattern_slot_t*);
  1073  static void jar_xm_trigger_note(jar_xm_context_t*, jar_xm_channel_context_t*, unsigned int flags);
  1074  static void jar_xm_cut_note(jar_xm_channel_context_t*);
  1075  static void jar_xm_key_off(jar_xm_channel_context_t*);
  1076  
  1077  static void jar_xm_post_pattern_change(jar_xm_context_t*);
  1078  static void jar_xm_row(jar_xm_context_t*);
  1079  static void jar_xm_tick(jar_xm_context_t*);
  1080  
  1081  static void jar_xm_next_of_sample(jar_xm_context_t*, jar_xm_channel_context_t*, int);
  1082  static 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
  1089  static 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
  1092  static 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
  1095  static 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  
  1137  static 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  
  1158  static 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  
  1168  static 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  
  1174  static 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  
  1179  static 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  
  1197  static 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  
  1206  static 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  
  1215  static 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  
  1220  static 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  
  1225  static 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  
  1235  static 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  
  1245  static float jar_xm_linear_period(float note) {
  1246      return 7680.f - note * 64.f;
  1247  }
  1248  
  1249  static float jar_xm_linear_frequency(float period) {
  1250      return 8363.f * powf(2.f, (4608.f - period) / 768.f);
  1251  }
  1252  
  1253  static 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  
  1268  static 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  
  1273  static 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  
  1283  static 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  
  1326  static 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  
  1331  static 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  
  1584  static 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  
  1616  static 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  
  1622  static 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  
  1627  static 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  
  1669      /// Move to next row
  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  
  1679  static 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  
  1705  static 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  
  1720  static 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  
  1962  static 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
  2106  static 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  
  2148  void 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  
  2157  uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx) {
  2158      uint64_t total = 0;
  2159      uint8_t currentLoopCount = jar_xm_get_loop_count(ctx);
  2160      jar_xm_set_max_loop_count(ctx, 0);
  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  
  2197  int 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
  2252  void 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  
  2266  void 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  
  2274  void 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 ... )
  2294  const 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  
  2316  const 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
  2338  const 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  
  2371  void 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