1 /* Author: Romain "Artefact2" Dalmaso <artefact2@gmail.com> */
2 
3 /* This program is free software. It comes without any warranty, to the
4  * extent permitted by applicable law. You can redistribute it and/or
5  * modify it under the terms of the Do What The Fuck You Want To Public
6  * License, Version 2, as published by Sam Hocevar. See
7  * http://sam.zoy.org/wtfpl/COPYING for more details. */
8 module audioformats.libxm;
9 
10 import core.stdc.config: c_ulong;
11 import core.stdc.stdlib: malloc, free;
12 import core.stdc.string: memcpy, memcmp, memset;
13 
14 import dplug.core.math;
15 
16 nothrow:
17 @nogc:
18 
19 private alias int8_t = byte;
20 private alias int16_t = short;
21 private alias int32_t = int;
22 private alias uint8_t = ubyte;
23 private alias uint16_t = ushort;
24 private alias uint32_t = uint;
25 private alias uint64_t = ulong;
26 
27 // xm_internal.h
28 
29 version(BigEndian)
30 {
31     static assert(false, "Big endian platforms are not yet supported, sorry");
32 }
33 
34 /* ----- XM constants ----- */
35 
36 enum SAMPLE_NAME_LENGTH = 22;
37 enum INSTRUMENT_HEADER_LENGTH = 263;
38 enum INSTRUMENT_NAME_LENGTH = 22;
39 enum MODULE_NAME_LENGTH = 20;
40 enum TRACKER_NAME_LENGTH = 20;
41 enum PATTERN_ORDER_TABLE_LENGTH = 256;
42 enum NUM_NOTES = 96;
43 enum NUM_ENVELOPE_POINTS = 12;
44 enum MAX_NUM_ROWS = 256;
45 
46 
47 // Options
48 version = XM_RAMPING; // sounds better to me when on
49 //version = XM_STRINGS;
50 enum XM_DEFENSIVE = true;
51 enum XM_LINEAR_INTERPOLATION = false; // sounds better/digital to me when off
52 enum XM_DEBUG = false;
53 
54 version(XM_RAMPING)
55 {
56     enum XM_SAMPLE_RAMPING_POINTS = 0x20;
57 }
58 
59 /* ----- Data types ----- */
60 
61 alias xm_waveform_type_t = int;
62 enum : xm_waveform_type_t {
63     XM_SINE_WAVEFORM = 0,
64     XM_RAMP_DOWN_WAVEFORM = 1,
65     XM_SQUARE_WAVEFORM = 2,
66     XM_RANDOM_WAVEFORM = 3,
67     XM_RAMP_UP_WAVEFORM = 4,
68 }
69 
70 alias xm_loop_type_t = int;
71 enum : xm_loop_type_t
72 {
73     XM_NO_LOOP,
74     XM_FORWARD_LOOP,
75     XM_PING_PONG_LOOP,
76 }
77 
78 alias xm_frequency_type_t = int;
79 enum : xm_frequency_type_t 
80 {
81     XM_LINEAR_FREQUENCIES,
82     XM_AMIGA_FREQUENCIES,
83 }
84 
85 struct xm_envelope_point_t 
86 {
87     uint16_t frame;
88     uint16_t value;
89 }
90 
91 struct xm_envelope_t
92 {
93     xm_envelope_point_t[NUM_ENVELOPE_POINTS] points;
94     uint8_t num_points;
95     uint8_t sustain_point;
96     uint8_t loop_start_point;
97     uint8_t loop_end_point;
98     bool enabled;
99     bool sustain_enabled;
100     bool loop_enabled;
101 }
102 
103 struct xm_sample_t 
104 {
105     version(XM_STRINGS)
106     {
107         char[SAMPLE_NAME_LENGTH + 1] name;
108     }
109 
110     uint8_t bits; /* Either 8 or 16 */
111 
112     uint32_t length;
113     uint32_t loop_start;
114     uint32_t loop_length;
115     uint32_t loop_end;
116     float volume;
117     int8_t finetune;
118     xm_loop_type_t loop_type;
119     float panning;
120     int8_t relative_note;
121     uint64_t latest_trigger;
122 
123     union {
124         int8_t* data8;
125         int16_t* data16;
126     };
127 }
128 
129 struct xm_instrument_t
130 {
131     version(XM_STRINGS)
132     {
133          char[INSTRUMENT_NAME_LENGTH + 1] name;
134     }
135     uint16_t num_samples;
136     uint8_t[NUM_NOTES] sample_of_notes;
137     xm_envelope_t volume_envelope;
138     xm_envelope_t panning_envelope;
139     xm_waveform_type_t vibrato_type;
140     uint8_t vibrato_sweep;
141     uint8_t vibrato_depth;
142     uint8_t vibrato_rate;
143     uint16_t volume_fadeout;
144     uint64_t latest_trigger;
145     bool muted;
146 
147     xm_sample_t* samples;
148 }
149 
150 struct xm_pattern_slot_t 
151 {
152     uint8_t note; /* 1-96, 97 = Key Off note */
153     uint8_t instrument; /* 1-128 */
154     uint8_t volume_column;
155     uint8_t effect_type;
156     uint8_t effect_param;
157 
158     nothrow:
159     @nogc:
160 
161     bool HAS_TONE_PORTAMENTO()
162     {
163         return effect_type == 3  || effect_type == 5 || ((volume_column >> 4) == 0xF);
164     }
165 
166     bool HAS_ARPEGGIO()
167     {
168         return effect_param != 0;
169     }
170 
171     bool HAS_VIBRATO()
172     {
173         return effect_type == 4 || effect_type == 6 || (volume_column >> 4) == 0xB;
174     }
175 }
176 
177 struct xm_pattern_t
178 {
179     uint16_t num_rows;
180     xm_pattern_slot_t* slots; /* Array of size num_rows * num_channels */
181 }
182 
183 struct xm_module_t 
184 {
185     version(XM_STRINGS)
186     {
187         char[MODULE_NAME_LENGTH + 1] name;
188         char[TRACKER_NAME_LENGTH + 1] trackername;
189     }
190 
191     uint16_t length;
192     uint16_t restart_position;
193     uint16_t num_channels;
194     uint16_t num_patterns;
195     uint16_t num_instruments;
196     xm_frequency_type_t frequency_type;
197     uint8_t[PATTERN_ORDER_TABLE_LENGTH] pattern_table;
198 
199     xm_pattern_t* patterns;
200     xm_instrument_t* instruments; /* Instrument 1 has index 0,
201                                    * instrument 2 has index 1, etc. */
202 }
203 
204 struct xm_channel_context_t 
205 {
206     float note;
207     float orig_note; /* The original note before effect modifications, as read in the pattern. */
208     xm_instrument_t* instrument; /* Could be null */
209     xm_sample_t* sample; /* Could be null */
210     xm_pattern_slot_t* current;
211 
212     float sample_position;
213     float period;
214     float frequency;
215     float step;
216     bool ping; /* For ping-pong samples: true is -., false is <-- */
217 
218     float volume; /* Ideally between 0 (muted) and 1 (loudest) */
219     float panning; /* Between 0 (left) and 1 (right); 0.5 is centered */
220 
221     uint16_t autovibrato_ticks;
222 
223     bool sustained;
224     float fadeout_volume;
225     float volume_envelope_volume;
226     float panning_envelope_panning;
227     uint16_t volume_envelope_frame_count;
228     uint16_t panning_envelope_frame_count;
229 
230     float autovibrato_note_offset;
231 
232     bool arp_in_progress;
233     uint8_t arp_note_offset;
234     uint8_t volume_slide_param;
235     uint8_t fine_volume_slide_param;
236     uint8_t global_volume_slide_param;
237     uint8_t panning_slide_param;
238     uint8_t portamento_up_param;
239     uint8_t portamento_down_param;
240     uint8_t fine_portamento_up_param;
241     uint8_t fine_portamento_down_param;
242     uint8_t extra_fine_portamento_up_param;
243     uint8_t extra_fine_portamento_down_param;
244     uint8_t tone_portamento_param;
245     float tone_portamento_target_period;
246     uint8_t multi_retrig_param;
247     uint8_t note_delay_param;
248     uint8_t pattern_loop_origin; /* Where to restart a E6y loop */
249     uint8_t pattern_loop_count; /* How many loop passes have been done */
250     bool vibrato_in_progress;
251     xm_waveform_type_t vibrato_waveform;
252     bool vibrato_waveform_retrigger; /* True if a new note retriggers the waveform */
253     uint8_t vibrato_param;
254     uint16_t vibrato_ticks; /* Position in the waveform */
255     float vibrato_note_offset;
256     xm_waveform_type_t tremolo_waveform;
257     bool tremolo_waveform_retrigger;
258     uint8_t tremolo_param;
259     uint8_t tremolo_ticks;
260     float tremolo_volume;
261     uint8_t tremor_param;
262     bool tremor_on;
263 
264     uint64_t latest_trigger;
265     bool muted;
266 
267     version(XM_RAMPING)
268     {
269         /* These values are updated at the end of each tick, to save
270          * a couple of float operations on every generated sample. */
271         float[2] target_volume;
272 
273         c_ulong frame_count;
274         float[XM_SAMPLE_RAMPING_POINTS] end_of_previous_sample;
275     }
276 
277     float[2] actual_volume;
278 }
279 
280 struct xm_context_t
281 {
282     size_t ctx_size; /* Must be first, see xm_create_context_from_libxmize() */
283     xm_module_t module_;
284     uint32_t rate;
285 
286     uint16_t tempo;
287     uint16_t bpm;
288     float global_volume;
289     float amplification;
290 
291     version(XM_RAMPING)
292     {
293         /* How much is a channel final volume allowed to change per
294          * sample; this is used to avoid abrubt volume changes which
295          * manifest as "clicks" in the generated sound. */
296         float volume_ramp;
297     }
298 
299     uint next_rand;
300 
301     uint8_t current_table_index;
302     uint8_t current_row;
303     uint16_t current_tick; /* Can go below 255, with high tempo and a pattern delay */
304     float remaining_samples_in_tick;
305     uint64_t generated_samples;
306 
307     bool position_jump;
308     bool pattern_break;
309     uint8_t jump_dest;
310     uint8_t jump_row;
311 
312 
313     /* Extra ticks to be played before going to the next row -
314      * Used for EEy effect */
315     uint16_t extra_ticks;
316 
317     uint8_t* row_loop_count; /* Array of size MAX_NUM_ROWS * module_length */
318     uint8_t loop_count;
319     uint8_t max_loop_count;
320 
321     xm_channel_context_t* channels;
322 }
323 
324 // xm.c
325 
326 /* .xm files are little-endian. */
327 
328 /* Bounded reader macros.
329 * If we attempt to read the buffer out-of-bounds, pretend that the buffer is
330 * infinitely padded with zeroes.
331 */
332 /*
333 #define READ_U8_BOUND(offset, bound) (((offset) < bound) ? (*(uint8_t*)(moddata + (offset))) : 0)
334 #define READ_U16_BOUND(offset, bound) ((uint16_t)READ_U8(offset) | ((uint16_t)READ_U8((offset) + 1) << 8))
335 #define READ_U32_BOUND(offset, bound) ((uint32_t)READ_U16(offset) | ((uint32_t)READ_U16((offset) + 2) << 16))
336 #define READ_MEMCPY_BOUND(ptr, offset, length, bound) memcpy_pad(ptr, length, moddata, bound, offset)
337 
338 #define READ_U8(offset) READ_U8_BOUND(offset, moddata_length)
339 #define READ_U16(offset) READ_U16_BOUND(offset, moddata_length)
340 #define READ_U32(offset) READ_U32_BOUND(offset, moddata_length)
341 #define READ_MEMCPY(ptr, offset, length) READ_MEMCPY_BOUND(ptr, offset, length, moddata_length)
342 */
343 void memcpy_pad(void* dst, size_t dst_len, const(void)* src, size_t src_len, size_t offset) 
344 {
345     uint8_t* dst_c = cast(uint8_t*)dst;
346     const(uint8_t)* src_c = cast(const(uint8_t)*)src;
347 
348     /* how many bytes can be copied without overrunning `src` */
349     size_t copy_bytes = (src_len >= offset) ? (src_len - offset) : 0;
350     copy_bytes = copy_bytes > dst_len ? dst_len : copy_bytes;
351 
352     memcpy(dst_c, src_c + offset, copy_bytes);
353     /* padded bytes */
354     memset(dst_c + copy_bytes, 0, dst_len - copy_bytes);
355 }
356 
357 /** Check the module data for errors/inconsistencies.
358  *
359  * @returns 0 if everything looks OK. Module should be safe to load.
360  */
361 int xm_check_sanity_preload(const(char)* module_, size_t module_length) 
362 {
363     if(module_length < 60) {
364         return 4;
365     }
366 
367     if(memcmp("Extended Module: ".ptr, module_, 17) != 0) {
368         return 1;
369     }
370 
371     if(module_[37] != 0x1A) {
372         return 2;
373     }
374 
375     if(module_[59] != 0x01 || module_[58] != 0x04) {
376         /* Not XM 1.04 */
377         return 3;
378     }
379 
380     return 0;
381 }
382 
383 /** Check a loaded module for errors/inconsistencies.
384  *
385  * @returns 0 if everything looks OK.
386  */
387 
388 int xm_check_sanity_postload(xm_context_t* ctx) 
389 {   
390     /* @todo: plenty of stuff to do here */
391 
392     /* Check the POT */
393     for(uint8_t i = 0; i < ctx.module_.length; ++i) {
394         if(ctx.module_.pattern_table[i] >= ctx.module_.num_patterns) {
395             if(i+1 == ctx.module_.length && ctx.module_.length > 1) {
396                 /* Cheap fix */
397                 --ctx.module_.length;
398                 // DEBUG("trimming invalid POT at pos %X", i);
399             } 
400             else 
401             {
402                 import core.stdc.stdio;
403                 printf("module has invalid POT, pos %X references nonexistent pattern %X", i, ctx.module_.pattern_table[i]);
404                 
405                 return 1;
406             }
407         }
408     }
409 
410     return 0;
411 }
412 
413 /** Get the number of bytes needed to store the module data in a
414  * dynamically allocated blank context.
415  *
416  * Things that are dynamically allocated:
417  * - sample data
418  * - sample structures in instruments
419  * - pattern data
420  * - row loop count arrays
421  * - pattern structures in module
422  * - instrument structures in module
423  * - channel contexts
424  * - context structure itself
425 
426  * @returns 0 if everything looks OK.
427  */
428 size_t xm_get_memory_needed_for_context(const char* moddata, size_t moddata_length) 
429 {
430     size_t memory_needed = 0;
431     size_t offset = 60; /* Skip the first header */
432     uint16_t num_channels;
433     uint16_t num_patterns;
434     uint16_t num_instruments;
435 
436     /* Read the module header */
437 
438     ubyte READ_U8_BOUND(size_t offset, size_t bound)
439     {
440         return (offset < bound) ? *cast(uint8_t*)(moddata + offset) : 0;
441     }
442 
443     ubyte READ_U8(size_t offset)
444     {
445         return READ_U8_BOUND(offset, moddata_length);
446     }
447 
448     ushort READ_U16_BOUND(size_t offset, size_t bound)
449     {
450         return (cast(uint16_t)READ_U8(offset) | (cast(uint16_t)READ_U8((offset) + 1) << 8));
451     }
452 
453     ushort READ_U16(size_t offset)
454     {
455         return READ_U16_BOUND(offset, moddata_length);
456     }
457 
458     uint READ_U32_BOUND(size_t offset, size_t bound)
459     {
460         return (cast(uint32_t)READ_U16(offset) | (cast(uint32_t)READ_U16((offset) + 2) << 16));
461     }
462 
463     uint READ_U32(size_t offset)
464     {
465         return READ_U32_BOUND(offset, moddata_length);
466     }
467 
468     void READ_MEMCPY_BOUND(void* ptr, size_t offset, size_t length, size_t bound)
469     {
470         memcpy_pad(ptr, length, moddata, bound, offset);
471     }
472 
473     void READ_MEMCPY(void* ptr, size_t ffset, size_t length) 
474     {
475         return READ_MEMCPY_BOUND(ptr, offset, length, moddata_length);
476     }
477 
478 
479     num_channels = READ_U16(offset + 8);
480     num_channels = READ_U16(offset + 8);
481 
482     num_patterns = READ_U16(offset + 10);
483     memory_needed += num_patterns * xm_pattern_t.sizeof;
484 
485     num_instruments = READ_U16(offset + 12);
486     memory_needed += num_instruments * xm_instrument_t.sizeof;
487 
488     memory_needed += MAX_NUM_ROWS * READ_U16(offset + 4) * uint8_t.sizeof; /* Module length */
489 
490     /* Header size */
491     offset += READ_U32(offset);
492 
493     /* Read pattern headers */
494     for(uint16_t i = 0; i < num_patterns; ++i) {
495         uint16_t num_rows;
496 
497         num_rows = READ_U16(offset + 5);
498         memory_needed += num_rows * num_channels * xm_pattern_slot_t.sizeof;
499 
500         /* Pattern header length + packed pattern data size */
501         offset += READ_U32(offset) + READ_U16(offset + 7);
502     }
503 
504     /* Read instrument headers */
505     for(uint16_t i = 0; i < num_instruments; ++i) {
506         uint16_t num_samples;
507         uint32_t sample_size_aggregate = 0;
508 
509         num_samples = READ_U16(offset + 27);
510         memory_needed += num_samples * xm_sample_t.sizeof;
511 
512         /* Instrument header size */
513         uint32_t ins_header_size = READ_U32(offset);
514         if (ins_header_size == 0 || ins_header_size > INSTRUMENT_HEADER_LENGTH)
515             ins_header_size = INSTRUMENT_HEADER_LENGTH;
516         offset += ins_header_size;
517 
518         for(uint16_t j = 0; j < num_samples; ++j) {
519             uint32_t sample_size;
520 
521             sample_size = READ_U32(offset);
522             sample_size_aggregate += sample_size;
523             memory_needed += sample_size;
524             offset += 40; /* See comment in xm_load_module() */
525         }
526 
527         offset += sample_size_aggregate;
528     }
529 
530     memory_needed += num_channels * xm_channel_context_t.sizeof;
531     memory_needed += xm_context_t.sizeof;
532 
533     return memory_needed;
534 }
535 
536 /** Populate the context from module data.
537  *
538  * @returns pointer to the memory pool
539  */
540 char* xm_load_module(xm_context_t* ctx, const char* moddata, size_t moddata_length, char* mempool) {
541     size_t offset = 0;
542     xm_module_t* mod = &(ctx.module_);
543 
544     ubyte READ_U8_BOUND(size_t offset, size_t bound)
545     {
546         return (offset < bound) ? *cast(uint8_t*)(moddata + offset) : 0;
547     }
548 
549     ubyte READ_U8(size_t offset)
550     {
551         return READ_U8_BOUND(offset, moddata_length);
552     }
553 
554     ushort READ_U16_BOUND(size_t offset, size_t bound)
555     {
556         return (cast(uint16_t)READ_U8(offset) | (cast(uint16_t)READ_U8((offset) + 1) << 8));
557     }
558 
559     ushort READ_U16(size_t offset)
560     {
561         return READ_U16_BOUND(offset, moddata_length);
562     }
563 
564     uint READ_U32_BOUND(size_t offset, size_t bound)
565     {
566         return (cast(uint32_t)READ_U16(offset) | (cast(uint32_t)READ_U16((offset) + 2) << 16));
567     }
568 
569     uint READ_U32(size_t offset)
570     {
571         return READ_U32_BOUND(offset, moddata_length);
572     }
573 
574     void READ_MEMCPY_BOUND(void* ptr, size_t offset, size_t length, size_t bound)
575     {
576         memcpy_pad(ptr, length, moddata, bound, offset);
577     }
578 
579     void READ_MEMCPY(void* ptr, size_t offset, size_t length) 
580     {
581         return READ_MEMCPY_BOUND(ptr, offset, length, moddata_length);
582     }
583 
584     /* Read XM header */
585     version(XM_STRINGS)
586     {
587         READ_MEMCPY(mod.name.ptr, offset + 17, MODULE_NAME_LENGTH);
588         READ_MEMCPY(mod.trackername.ptr, offset + 38, TRACKER_NAME_LENGTH);
589     }
590     offset += 60;
591 
592     /* Read module header */
593     uint32_t header_size = READ_U32(offset);
594 
595     mod.length = READ_U16(offset + 4);
596     mod.restart_position = READ_U16(offset + 6);
597     mod.num_channels = READ_U16(offset + 8);
598     mod.num_patterns = READ_U16(offset + 10);
599     mod.num_instruments = READ_U16(offset + 12);
600 
601     mod.patterns = cast(xm_pattern_t*)mempool;
602     mempool += mod.num_patterns * xm_pattern_t.sizeof;
603 
604     mod.instruments = cast(xm_instrument_t*)mempool;
605     mempool += mod.num_instruments * xm_instrument_t.sizeof;
606 
607     uint16_t flags = cast(ushort) READ_U32(offset + 14);
608     mod.frequency_type = (flags & (1 << 0)) ? XM_LINEAR_FREQUENCIES : XM_AMIGA_FREQUENCIES;
609 
610     ctx.tempo = READ_U16(offset + 16);
611     ctx.bpm = READ_U16(offset + 18);
612 
613     READ_MEMCPY(mod.pattern_table.ptr, offset + 20, PATTERN_ORDER_TABLE_LENGTH);
614     offset += header_size;
615 
616     /* Read patterns */
617     for(uint16_t i = 0; i < mod.num_patterns; ++i) {
618         uint16_t packed_patterndata_size = READ_U16(offset + 7);
619         xm_pattern_t* pat = mod.patterns + i;
620 
621         pat.num_rows = READ_U16(offset + 5);
622 
623         pat.slots = cast(xm_pattern_slot_t*)mempool;
624         mempool += mod.num_channels * pat.num_rows * xm_pattern_slot_t.sizeof;
625 
626         /* Pattern header length */
627         offset += READ_U32(offset);
628 
629         if(packed_patterndata_size == 0) {
630             /* No pattern data is present */
631             memset(pat.slots, 0, xm_pattern_slot_t.sizeof * pat.num_rows * mod.num_channels);
632         } else {
633             /* This isn't your typical for loop */
634             for(uint16_t j = 0, k = 0; j < packed_patterndata_size; ++k) {
635                 uint8_t note = READ_U8(offset + j);
636                 xm_pattern_slot_t* slot = pat.slots + k;
637 
638                 if(note & (1 << 7)) {
639                     /* MSB is set, this is a compressed packet */
640                     ++j;
641 
642                     if(note & (1 << 0)) {
643                         /* Note follows */
644                         slot.note = READ_U8(offset + j);
645                         ++j;
646                     } else {
647                         slot.note = 0;
648                     }
649 
650                     if(note & (1 << 1)) {
651                         /* Instrument follows */
652                         slot.instrument = READ_U8(offset + j);
653                         ++j;
654                     } else {
655                         slot.instrument = 0;
656                     }
657 
658                     if(note & (1 << 2)) {
659                         /* Volume column follows */
660                         slot.volume_column = READ_U8(offset + j);
661                         ++j;
662                     } else {
663                         slot.volume_column = 0;
664                     }
665 
666                     if(note & (1 << 3)) {
667                         /* Effect follows */
668                         slot.effect_type = READ_U8(offset + j);
669                         ++j;
670                     } else {
671                         slot.effect_type = 0;
672                     }
673 
674                     if(note & (1 << 4)) {
675                         /* Effect parameter follows */
676                         slot.effect_param = READ_U8(offset + j);
677                         ++j;
678                     } else {
679                         slot.effect_param = 0;
680                     }
681                 } else {
682                     /* Uncompressed packet */
683                     slot.note = note;
684                     slot.instrument = READ_U8(offset + j + 1);
685                     slot.volume_column = READ_U8(offset + j + 2);
686                     slot.effect_type = READ_U8(offset + j + 3);
687                     slot.effect_param = READ_U8(offset + j + 4);
688                     j += 5;
689                 }
690             }
691         }
692 
693         offset += packed_patterndata_size;
694     }
695 
696     /* Read instruments */
697     for(uint16_t i = 0; i < ctx.module_.num_instruments; ++i) {
698         xm_instrument_t* instr = mod.instruments + i;
699 
700         /* Original FT2 would load instruments with a direct read into the
701         instrument data structure that was previously zeroed. This means
702         that if the declared length was less than INSTRUMENT_HEADER_LENGTH,
703         all excess data would be zeroed. This is used by the XM compressor
704         BoobieSqueezer. To implement this, bound all reads to the header size. */
705         uint32_t ins_header_size = READ_U32(offset);
706         if (ins_header_size == 0 || ins_header_size > INSTRUMENT_HEADER_LENGTH)
707             ins_header_size = INSTRUMENT_HEADER_LENGTH;
708 
709         version(XM_STRINGS)
710         {
711             READ_MEMCPY_BOUND(instr.name.ptr, offset + 4, INSTRUMENT_NAME_LENGTH, offset + ins_header_size);
712             instr.name[INSTRUMENT_NAME_LENGTH] = 0;
713         }
714         instr.num_samples = READ_U16_BOUND(offset + 27, offset + ins_header_size);
715 
716         if(instr.num_samples > 0) {
717             /* Read extra header properties */
718             READ_MEMCPY_BOUND(instr.sample_of_notes.ptr, offset + 33, NUM_NOTES, offset + ins_header_size);
719 
720             instr.volume_envelope.num_points = READ_U8_BOUND(offset + 225, offset + ins_header_size);
721             if (instr.volume_envelope.num_points > NUM_ENVELOPE_POINTS)
722                 instr.volume_envelope.num_points = NUM_ENVELOPE_POINTS;
723 
724             instr.panning_envelope.num_points = READ_U8_BOUND(offset + 226, offset + ins_header_size);
725             if (instr.panning_envelope.num_points > NUM_ENVELOPE_POINTS)
726                 instr.panning_envelope.num_points = NUM_ENVELOPE_POINTS;
727 
728             for(uint8_t j = 0; j < instr.volume_envelope.num_points; ++j) {
729                 instr.volume_envelope.points[j].frame = READ_U16_BOUND(offset + 129 + 4 * j, offset + ins_header_size);
730                 instr.volume_envelope.points[j].value = READ_U16_BOUND(offset + 129 + 4 * j + 2, offset + ins_header_size);
731             }
732 
733             for(uint8_t j = 0; j < instr.panning_envelope.num_points; ++j) {
734                 instr.panning_envelope.points[j].frame = READ_U16_BOUND(offset + 177 + 4 * j, offset + ins_header_size);
735                 instr.panning_envelope.points[j].value = READ_U16_BOUND(offset + 177 + 4 * j + 2, offset + ins_header_size);
736             }
737 
738             instr.volume_envelope.sustain_point = READ_U8_BOUND(offset + 227, offset + ins_header_size);
739             instr.volume_envelope.loop_start_point = READ_U8_BOUND(offset + 228, offset + ins_header_size);
740             instr.volume_envelope.loop_end_point = READ_U8_BOUND(offset + 229, offset + ins_header_size);
741 
742             instr.panning_envelope.sustain_point = READ_U8_BOUND(offset + 230, offset + ins_header_size);
743             instr.panning_envelope.loop_start_point = READ_U8_BOUND(offset + 231, offset + ins_header_size);
744             instr.panning_envelope.loop_end_point = READ_U8_BOUND(offset + 232, offset + ins_header_size);
745 
746             uint8_t flags_ = READ_U8_BOUND(offset + 233, offset + ins_header_size);
747             instr.volume_envelope.enabled = ( flags_ & (1 << 0) ) != 0;
748             instr.volume_envelope.sustain_enabled = (flags_ & (1 << 1) ) != 0;
749             instr.volume_envelope.loop_enabled = ( flags_ & (1 << 2)  ) != 0;
750 
751             flags_ = READ_U8_BOUND(offset + 234, offset + ins_header_size);
752             instr.panning_envelope.enabled = flags_ & (1 << 0);
753             instr.panning_envelope.sustain_enabled = (flags_ & (1 << 1)) != 0;
754             instr.panning_envelope.loop_enabled =    (flags_ & (1 << 2)) != 0;
755 
756             instr.vibrato_type = READ_U8_BOUND(offset + 235, offset + ins_header_size);
757             if(instr.vibrato_type == 2) {
758                 instr.vibrato_type = 1;
759             } else if(instr.vibrato_type == 1) {
760                 instr.vibrato_type = 2;
761             }
762             instr.vibrato_sweep = READ_U8_BOUND(offset + 236, offset + ins_header_size);
763             instr.vibrato_depth = READ_U8_BOUND(offset + 237, offset + ins_header_size);
764             instr.vibrato_rate = READ_U8_BOUND(offset + 238, offset + ins_header_size);
765             instr.volume_fadeout = READ_U16_BOUND(offset + 239, offset + ins_header_size);
766 
767             instr.samples = cast(xm_sample_t*)mempool;
768             mempool += instr.num_samples * xm_sample_t.sizeof;
769         } else {
770             instr.samples = null;
771         }
772 
773         /* Instrument header size */
774         offset += ins_header_size;
775 
776         for(uint16_t j = 0; j < instr.num_samples; ++j) {
777             /* Read sample header */
778             xm_sample_t* sample = instr.samples + j;
779 
780             sample.length = READ_U32(offset);
781             sample.loop_start = READ_U32(offset + 4);
782             sample.loop_length = READ_U32(offset + 8);
783             sample.loop_end = sample.loop_start + sample.loop_length;
784             sample.volume = cast(float)READ_U8(offset + 12) / cast(float)0x40;
785             sample.finetune = cast(int8_t)READ_U8(offset + 13);
786 
787             /* Fix invalid loop definitions */
788             if (sample.loop_start > sample.length)
789                 sample.loop_start = sample.length;
790             if (sample.loop_end > sample.length)
791                 sample.loop_end = sample.length;
792             sample.loop_length = sample.loop_end - sample.loop_start;
793 
794             uint8_t flags2 = READ_U8(offset + 14);
795             if((flags2 & 3) == 0 || sample.loop_length == 0) {
796                 sample.loop_type = XM_NO_LOOP;
797             } else if((flags2 & 3) == 1) {
798                 sample.loop_type = XM_FORWARD_LOOP;
799             } else {
800                 sample.loop_type = XM_PING_PONG_LOOP;
801             }
802 
803             sample.bits = (flags2 & (1 << 4)) ? 16 : 8;
804 
805             sample.panning = cast(float)READ_U8(offset + 15) / cast(float)0xFF;
806             sample.relative_note = cast(int8_t)READ_U8(offset + 16);
807             version( XM_STRINGS)
808             {
809                 READ_MEMCPY(sample.name.ptr, 18, SAMPLE_NAME_LENGTH);
810             }
811             sample.data8 = cast(int8_t*)mempool;
812             mempool += sample.length;
813 
814             if(sample.bits == 16) {
815                 sample.loop_start >>= 1;
816                 sample.loop_length >>= 1;
817                 sample.loop_end >>= 1;
818                 sample.length >>= 1;
819             }
820 
821             /* Notice that, even if there's a "sample header size" in the
822             instrument header, that value seems ignored, and might even
823             be wrong in some corrupted modules. */
824             offset += 40;
825         }
826 
827         for(uint16_t j = 0; j < instr.num_samples; ++j) {
828             /* Read sample data */
829             xm_sample_t* sample = instr.samples + j;
830             uint32_t length = sample.length;
831 
832             if(sample.bits == 16) {
833                 int16_t v = 0;
834                 for(uint32_t k = 0; k < length; ++k) {
835                     v = cast(short)( v + cast(int16_t)READ_U16(offset + (k << 1)) );
836                     sample.data16[k] = v;
837                 }
838                 offset += sample.length << 1;
839             } else {
840                 int8_t v = 0;
841                 for(uint32_t k = 0; k < length; ++k) {
842                     v = cast(byte)( v + cast(int8_t)READ_U8(offset + k) );
843                     sample.data8[k] = v;
844                 }
845                 offset += sample.length;
846             }
847         }
848     }
849 
850     return mempool;
851 }
852 
853 
854 
855 // context.c -- public API
856 
857 int xm_create_context_safe(xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) 
858 {
859 	size_t bytes_needed;
860 	char* mempool;
861 	xm_context_t* ctx;
862 
863 	if(XM_DEFENSIVE) 
864     {
865 		int ret = xm_check_sanity_preload(moddata, moddata_length);
866 		if (ret != 0) 
867         {
868 			//("xm_check_sanity_preload() returned %i, module is not safe to load", ret);
869 			return 1;
870 		}
871 	}
872 
873 	bytes_needed = xm_get_memory_needed_for_context(moddata, moddata_length);
874 	mempool = cast(char*) malloc(bytes_needed);
875 	if(mempool == null && bytes_needed > 0) {
876 		/* malloc() failed, trouble ahead */
877 		//DEBUG("call to malloc() failed, returned %p", (void*)mempool);
878 		return 2;
879 	}
880 
881 	/* Initialize most of the fields to 0, 0.0f, null or false depending on type */
882 	memset(mempool, 0, bytes_needed);
883 
884 	ctx = (*ctxp = cast(xm_context_t*)mempool);
885 	ctx.ctx_size = bytes_needed; /* Keep original requested size for xmconvert */
886     mempool += xm_context_t.sizeof;
887 
888 	ctx.rate = rate;
889 	mempool = xm_load_module(ctx, moddata, moddata_length, mempool);
890 
891 	ctx.channels = cast(xm_channel_context_t*)mempool;
892 	mempool += ctx.module_.num_channels * (xm_channel_context_t).sizeof;
893 
894 	ctx.global_volume = 1.0f;
895 	ctx.amplification = 0.25f; /* XXX: some bad modules may still clip. Find out something better. */
896     ctx.next_rand = 24492; // see rng
897 
898     version(XM_RAMPING)
899     {
900 	    ctx.volume_ramp = (1.0f / 128.0f);
901     }
902 
903 	for(uint8_t i = 0; i < ctx.module_.num_channels; ++i) {
904 		xm_channel_context_t* ch = ctx.channels + i;
905 
906 		ch.ping = true;
907 		ch.vibrato_waveform = XM_SINE_WAVEFORM;
908 		ch.vibrato_waveform_retrigger = true;
909 		ch.tremolo_waveform = XM_SINE_WAVEFORM;
910 		ch.tremolo_waveform_retrigger = true;
911 
912 		ch.volume = ch.volume_envelope_volume = ch.fadeout_volume = 1.0f;
913 		ch.panning = ch.panning_envelope_panning = .5f;
914 		ch.actual_volume[0] = .0f;
915 		ch.actual_volume[1] = .0f;
916 	}
917 
918 	ctx.row_loop_count = cast(uint8_t*)mempool;
919 	mempool += ctx.module_.length * MAX_NUM_ROWS * uint8_t.sizeof;
920 
921 	if(XM_DEFENSIVE) {
922 		int ret = xm_check_sanity_postload(ctx);
923 		if(ret != 0) 
924         {
925 			//DEBUG("xm_check_sanity_postload() returned %i, module is not safe to play", ret);
926 			xm_free_context(ctx);
927             *ctxp = null;
928 			return 1;
929 		}
930 	}
931 
932 	return 0;
933 }
934 
935 int xm_count_remaining_samples(xm_context_t* context) {
936     // TODO: implement
937     return 0;
938 }
939 
940 void xm_free_context(xm_context_t* context) {
941 	free(context);
942 }
943 
944 void xm_set_max_loop_count(xm_context_t* context, uint8_t loopcnt) {
945 	context.max_loop_count = loopcnt;
946 }
947 
948 uint8_t xm_get_loop_count(xm_context_t* context) {
949 	return context.loop_count;
950 }
951 
952 bool xm_seek(xm_context_t* ctx, int pot, int row, int tick) 
953 {
954     // TODO: check validity of position, return false otherwise.
955 	ctx.current_table_index = cast(uint8_t)pot;
956 	ctx.current_row = cast(uint8_t) row;
957 	ctx.current_tick = cast(uint16_t) tick;
958 	ctx.remaining_samples_in_tick = 0;
959     return true;
960 }
961 
962 bool xm_mute_channel(xm_context_t* ctx, uint16_t channel, bool mute) {
963 	bool old = ctx.channels[channel - 1].muted;
964 	ctx.channels[channel - 1].muted = mute;
965 	return old;
966 }
967 
968 bool xm_mute_instrument(xm_context_t* ctx, uint16_t instr, bool mute) {
969 	bool old = ctx.module_.instruments[instr - 1].muted;
970 	ctx.module_.instruments[instr - 1].muted = mute;
971 	return old;
972 }
973 
974 
975 
976 version(XM_STRINGS)
977 {
978     const(char)* xm_get_module_name(xm_context_t* ctx) 
979     {
980 	    return ctx.module_.name.ptr;
981     }
982 
983     const(char)* xm_get_tracker_name(xm_context_t* ctx) 
984     {
985 	    return ctx.module_.trackername.ptr;
986     }
987 }
988 else
989 {
990     const(char)* xm_get_module_name(xm_context_t* ctx) 
991     {
992 	    return null;
993     }
994 
995     const(char)* xm_get_tracker_name(xm_context_t* ctx) 
996     {
997 	    return null;
998     }
999 }
1000 
1001 uint16_t xm_get_number_of_channels(xm_context_t* ctx) {
1002 	return ctx.module_.num_channels;
1003 }
1004 
1005 uint16_t xm_get_module_length(xm_context_t* ctx) {
1006 	return ctx.module_.length;
1007 }
1008 
1009 uint16_t xm_get_number_of_patterns(xm_context_t* ctx) {
1010 	return ctx.module_.num_patterns;
1011 }
1012 
1013 uint16_t xm_get_number_of_rows(xm_context_t* ctx, uint16_t pattern) {
1014 	return ctx.module_.patterns[pattern].num_rows;
1015 }
1016 
1017 uint16_t xm_get_number_of_instruments(xm_context_t* ctx) {
1018 	return ctx.module_.num_instruments;
1019 }
1020 
1021 uint16_t xm_get_number_of_samples(xm_context_t* ctx, uint16_t instrument) {
1022 	return ctx.module_.instruments[instrument - 1].num_samples;
1023 }
1024 
1025 void* xm_get_sample_waveform(xm_context_t* ctx, uint16_t i, uint16_t s, size_t* size, uint8_t* bits) {
1026 	*size = ctx.module_.instruments[i - 1].samples[s].length;
1027 	*bits = ctx.module_.instruments[i - 1].samples[s].bits;
1028 	return ctx.module_.instruments[i - 1].samples[s].data8;
1029 }
1030 
1031 void xm_get_playing_speed(xm_context_t* ctx, uint16_t* bpm, uint16_t* tempo) {
1032 	if(bpm) *bpm = ctx.bpm;
1033 	if(tempo) *tempo = ctx.tempo;
1034 }
1035 
1036 void xm_get_position(xm_context_t* ctx, uint8_t* pattern_index, uint8_t* pattern, uint8_t* row, uint64_t* samples) {
1037 	if(pattern_index) *pattern_index = ctx.current_table_index;
1038 	if(pattern) *pattern = ctx.module_.pattern_table[ctx.current_table_index];
1039 	if(row) *row = ctx.current_row;
1040 	if(samples) *samples = ctx.generated_samples;
1041 }
1042 
1043 uint64_t xm_get_latest_trigger_of_instrument(xm_context_t* ctx, uint16_t instr) {
1044 	return ctx.module_.instruments[instr - 1].latest_trigger;
1045 }
1046 
1047 uint64_t xm_get_latest_trigger_of_sample(xm_context_t* ctx, uint16_t instr, uint16_t sample) {
1048 	return ctx.module_.instruments[instr - 1].samples[sample].latest_trigger;
1049 }
1050 
1051 uint64_t xm_get_latest_trigger_of_channel(xm_context_t* ctx, uint16_t chn) {
1052 	return ctx.channels[chn - 1].latest_trigger;
1053 }
1054 
1055 bool xm_is_channel_active(xm_context_t* ctx, uint16_t chn) {
1056 	xm_channel_context_t* ch = ctx.channels + (chn - 1);
1057 	return ch.instrument != null && ch.sample != null && ch.sample_position >= 0;
1058 }
1059 
1060 float xm_get_frequency_of_channel(xm_context_t* ctx, uint16_t chn) {
1061 	return ctx.channels[chn - 1].frequency;
1062 }
1063 
1064 float xm_get_volume_of_channel(xm_context_t* ctx, uint16_t chn) {
1065 	return ctx.channels[chn - 1].volume * ctx.global_volume;
1066 }
1067 
1068 float xm_get_panning_of_channel(xm_context_t* ctx, uint16_t chn) {
1069 	return ctx.channels[chn - 1].panning;
1070 }
1071 
1072 uint16_t xm_get_instrument_of_channel(xm_context_t* ctx, uint16_t chn) 
1073 {
1074 	xm_channel_context_t* ch = ctx.channels + (chn - 1);
1075 	if(ch.instrument == null) return 0;
1076 	return cast(ushort)( 1 + (ch.instrument - ctx.module_.instruments) );
1077 }
1078 
1079 
1080 // play.c
1081 
1082 /* Author: Romain "Artefact2" Dalmaso <artefact2@gmail.com> */
1083 /* Contributor: Daniel Oaks <daniel@danieloaks.net> */
1084 
1085 /* This program is free software. It comes without any warranty, to the
1086 * extent permitted by applicable law. You can redistribute it and/or
1087 * modify it under the terms of the Do What The Fuck You Want To Public
1088 * License, Version 2, as published by Sam Hocevar. See
1089 * http://sam.zoy.org/wtfpl/COPYING for more details. */
1090 
1091 /* ----- Other oddities ----- */
1092 
1093 enum XM_TRIGGER_KEEP_VOLUME = (1 << 0);
1094 enum  XM_TRIGGER_KEEP_PERIOD = (1 << 1);
1095 enum  XM_TRIGGER_KEEP_SAMPLE_POSITION = (1 << 2);
1096 enum  XM_TRIGGER_KEEP_ENVELOPE = (1 << 3);
1097 
1098 enum AMIGA_FREQ_SCALE = 1024;
1099 
1100 static immutable uint32_t[13] amiga_frequencies =
1101 [
1102 	1712*AMIGA_FREQ_SCALE, 1616*AMIGA_FREQ_SCALE, 1525*AMIGA_FREQ_SCALE, 1440*AMIGA_FREQ_SCALE, /* C-2, C#2, D-2, D#2 */
1103 	1357*AMIGA_FREQ_SCALE, 1281*AMIGA_FREQ_SCALE, 1209*AMIGA_FREQ_SCALE, 1141*AMIGA_FREQ_SCALE, /* E-2, F-2, F#2, G-2 */
1104 	1077*AMIGA_FREQ_SCALE, 1017*AMIGA_FREQ_SCALE,  961*AMIGA_FREQ_SCALE,  907*AMIGA_FREQ_SCALE, /* G#2, A-2, A#2, B-2 */
1105 	856*AMIGA_FREQ_SCALE,                                                                       /* C-3 */
1106 ];
1107 
1108 static immutable float[16] multi_retrig_add = 
1109 [
1110     0.0f,  -1.0f,  -2.0f,  -4.0f,  /* 0, 1, 2, 3 */
1111 	-8.0f, -16.0f,   0.0f,   0.0f,  /* 4, 5, 6, 7 */
1112     0.0f,   1.0f,   2.0f,   4.0f,  /* 8, 9, A, B */
1113     8.0f,  16.0f,   0.0f,   0.0f   /* C, D, E, F */
1114 ];
1115 
1116 static const float[16] multi_retrig_multiply =
1117 [
1118 	1.0f,   1.0f,  1.0f,        1.0f,  /* 0, 1, 2, 3 */
1119 	1.0f,   1.0f,   .6666667f,  .5f, /* 4, 5, 6, 7 */
1120 	1.0f,   1.0f,  1.0f,        1.0f,  /* 8, 9, A, B */
1121 	1.0f,   1.0f,  1.5f,       2.0f   /* C, D, E, F */
1122 ];
1123 
1124 void XM_SLIDE_TOWARDS(ref float val, float goal, float incr)
1125 {
1126     if (val > goal)
1127     {
1128         val -= incr;
1129         if (val < goal) val = goal;
1130     }
1131     else if (val < goal)
1132     {
1133         val += incr;
1134         if (val > goal) val = goal;
1135     }
1136 }
1137 
1138 float XM_LERP(float u, float v, float t)
1139 {
1140     return u + t * (v - u);
1141 }
1142 
1143 float XM_INVERSE_LERP(float u, float v, float lerp)
1144 {
1145     return  (lerp - u) / (v - u);
1146 }
1147 
1148 bool NOTE_IS_VALID(int n)
1149 {
1150     return (n > 0) && (n < 97);
1151 }
1152 
1153 /* ----- Function definitions ----- */
1154 
1155 float xm_waveform(xm_context_t* context, xm_waveform_type_t waveform, uint8_t step) {
1156 	step %= 0x40;
1157 	switch(waveform) 
1158     {
1159 
1160         case XM_SINE_WAVEFORM:
1161             /* Why not use a table? For saving space, and because there's
1162             * very very little actual performance gain. */
1163             return -fast_sin(2.0f * 3.141592f * cast(float)step / cast(float)0x40);
1164 
1165         case XM_RAMP_DOWN_WAVEFORM:
1166             /* Ramp down: 1.0f when step = 0; -1.0f when step = 0x40 */
1167             return cast(float)(0x20 - step) / 0x20;
1168 
1169         case XM_SQUARE_WAVEFORM:
1170             /* Square with a 50% duty */
1171             return (step >= 0x20) ? 1.0f : -1.0f;
1172 
1173         case XM_RANDOM_WAVEFORM:
1174             /* Use the POSIX.1-2001 example, just to be deterministic
1175             * across different machines */
1176             context.next_rand = context.next_rand * 1103515245 + 12345;
1177             return cast(float)((context.next_rand >> 16) & 0x7FFF) / cast(float)0x4000 - 1.0f;
1178 
1179         case XM_RAMP_UP_WAVEFORM:
1180             /* Ramp up: -1.0f when step = 0; 1.0f when step = 0x40 */
1181             return cast(float)(step - 0x20) / 0x20;
1182 
1183         default:
1184             break;
1185 
1186 	}
1187 
1188 	return .0f;
1189 }
1190 
1191 void xm_autovibrato(xm_context_t* ctx, xm_channel_context_t* ch) {
1192 	if(ch.instrument == null || ch.instrument.vibrato_depth == 0){
1193 		if (ch.autovibrato_note_offset){
1194 			ch.autovibrato_note_offset = 0.0f;
1195 			xm_update_frequency(ctx, ch);
1196 		}
1197 		return;
1198 	}
1199 	xm_instrument_t* instr = ch.instrument;
1200 	float sweep = 1.0f;
1201 
1202 	if(ch.autovibrato_ticks < instr.vibrato_sweep) {
1203 		/* No idea if this is correct, but it sounds close enough… */
1204 		sweep = XM_LERP(0.0f, 1.0f, cast(float)ch.autovibrato_ticks / cast(float)instr.vibrato_sweep);
1205 	}
1206 
1207 	uint step = ((ch.autovibrato_ticks++) * instr.vibrato_rate) >> 2;
1208 	ch.autovibrato_note_offset = .25f * xm_waveform(ctx, instr.vibrato_type, cast(ubyte)step)
1209 		* cast(float)instr.vibrato_depth / cast(float)0xF * sweep;
1210 	xm_update_frequency(ctx, ch);
1211 }
1212 
1213 void xm_vibrato(xm_context_t* ctx, xm_channel_context_t* ch, uint8_t param) {
1214 	ch.vibrato_ticks += (param >> 4);
1215 	ch.vibrato_note_offset =
1216 		-2.0f
1217 		* xm_waveform(ctx, ch.vibrato_waveform, cast(ubyte)ch.vibrato_ticks)
1218 		* cast(float)(param & 0x0F) / cast(float)0xF;
1219 	xm_update_frequency(ctx, ch);
1220 }
1221 
1222 void xm_tremolo(xm_context_t* ctx, xm_channel_context_t* ch, uint8_t param, uint16_t pos) {
1223 	uint step = pos * (param >> 4);
1224 	/* Not so sure about this, it sounds correct by ear compared with
1225     * MilkyTracker, but it could come from other bugs */
1226 	ch.tremolo_volume = -1.0f * xm_waveform(ctx, ch.tremolo_waveform, cast(ubyte)step)
1227 		* cast(float)(param & 0x0F) / cast(float)0xF;
1228 }
1229 
1230 void xm_arpeggio(xm_context_t* ctx, xm_channel_context_t* ch, uint8_t param, uint16_t tick) {
1231 	switch(tick % 3) {
1232         case 0:
1233             ch.arp_in_progress = false;
1234             ch.arp_note_offset = 0;
1235             break;
1236         case 2:
1237             ch.arp_in_progress = true;
1238             ch.arp_note_offset = param >> 4;
1239             break;
1240         case 1:
1241             ch.arp_in_progress = true;
1242             ch.arp_note_offset = param & 0x0F;
1243             break;
1244 
1245         default:
1246             assert(false);
1247 	}
1248 
1249 	xm_update_frequency(ctx, ch);
1250 }
1251 
1252 void xm_tone_portamento(xm_context_t* ctx, xm_channel_context_t* ch) 
1253 {
1254 	/* 3xx called without a note, wait until we get an actual
1255     * target note. */
1256 	if(ch.tone_portamento_target_period == 0.0f) 
1257         return;
1258 
1259 	if(ch.period != ch.tone_portamento_target_period) 
1260     {
1261 		XM_SLIDE_TOWARDS(ch.period,
1262 		                 ch.tone_portamento_target_period,
1263 		                 (ctx.module_.frequency_type == XM_LINEAR_FREQUENCIES ? 4.0f : 1.0f) * ch.tone_portamento_param);
1264 		xm_update_frequency(ctx, ch);
1265 	}
1266 }
1267 
1268 void xm_pitch_slide(xm_context_t* ctx, xm_channel_context_t* ch, float period_offset) {
1269 	/* Don't ask about the 4.0f coefficient. I found mention of it
1270     * nowhere. Found by ear™. */
1271 	if(ctx.module_.frequency_type == XM_LINEAR_FREQUENCIES) {
1272 		period_offset *= 4.0f;
1273 	}
1274 
1275 	ch.period += period_offset;
1276     if (ch.period < 0) ch.period = 0;
1277 	/* XXX: upper bound of period ? */
1278 
1279 	xm_update_frequency(ctx, ch);
1280 }
1281 
1282 void xm_panning_slide(xm_channel_context_t* ch, uint8_t rawval) {
1283 	float f;
1284 
1285 	if((rawval & 0xF0) && (rawval & 0x0F)) {
1286 		/* Illegal state */
1287 		return;
1288 	}
1289 
1290 	if(rawval & 0xF0) {
1291 		/* Slide right */
1292 		f = cast(float)(rawval >> 4) / cast(float)0xFF;
1293 		ch.panning += f;
1294         if (ch.panning > 1) 
1295             ch.panning = 1;
1296 	} else {
1297 		/* Slide left */
1298 		f = cast(float)(rawval & 0x0F) / cast(float)0xFF;
1299 		ch.panning -= f;
1300         if (ch.panning < 0)
1301             ch.panning = 0;
1302 	}
1303 }
1304 
1305 void xm_volume_slide(xm_channel_context_t* ch, uint8_t rawval) {
1306 	float f;
1307 
1308 	if((rawval & 0xF0) && (rawval & 0x0F)) {
1309 		/* Illegal state */
1310 		return;
1311 	}
1312 
1313 	if(rawval & 0xF0) {
1314 		/* Slide up */
1315 		f = cast(float)(rawval >> 4) / cast(float)0x40;
1316 		ch.volume += f;
1317         if (ch.volume > 1)
1318             ch.volume = 1;
1319 	} else {
1320 		/* Slide down */
1321 		f = cast(float)(rawval & 0x0F) / cast(float)0x40;
1322 		ch.volume -= f;
1323         if (ch.volume < 0)
1324             ch.volume = 0;
1325 	}
1326 }
1327 
1328 float xm_envelope_lerp(xm_envelope_point_t* a, xm_envelope_point_t* b, uint16_t pos) {
1329 	/* Linear interpolation between two envelope points */
1330 	if(pos <= a.frame) return a.value;
1331 	else if(pos >= b.frame) return b.value;
1332 	else {
1333 		float p = cast(float)(pos - a.frame) / cast(float)(b.frame - a.frame);
1334 		return a.value * (1 - p) + b.value * p;
1335 	}
1336 }
1337 
1338 void xm_post_pattern_change(xm_context_t* ctx) {
1339 	/* Loop if necessary */
1340 	if(ctx.current_table_index >= ctx.module_.length) 
1341     {
1342 		ctx.current_table_index = cast(ubyte)(ctx.module_.restart_position);
1343 	}
1344 }
1345 
1346 float xm_linear_period(float note) {
1347 	return 7680.0f - note * 64.0f;
1348 }
1349 
1350 float xm_linear_frequency(float period) {
1351 	return 8363.0f * fast_pow(2.0f, (4608.0f - period) / 768.0f);
1352 }
1353 
1354 float xm_amiga_period(float note) {
1355 	uint intnote = cast(uint)note;
1356 	uint8_t a = intnote % 12;
1357 	int8_t octave = cast(int8_t)(note / 12.0f - 2);
1358 	int32_t p1 = amiga_frequencies[a], p2 = amiga_frequencies[a + 1];
1359 
1360 	if(octave > 0) {
1361 		p1 >>= octave;
1362 		p2 >>= octave;
1363 	} else if(octave < 0) {
1364 		p1 <<= (-cast(int)octave);
1365 		p2 <<= (-cast(int)octave);
1366 	}
1367 
1368 	return XM_LERP(p1, p2, note - intnote) / AMIGA_FREQ_SCALE;
1369 }
1370 
1371 float xm_amiga_frequency(float period) {
1372 	if(period == .0f) return .0f;
1373 
1374 	/* This is the PAL value. No reason to choose this one over the
1375     * NTSC value. */
1376 	return 7093789.2f / (period * 2.0f);
1377 }
1378 
1379 float xm_period(xm_context_t* ctx, float note) 
1380 {
1381 	switch(ctx.module_.frequency_type) 
1382     {
1383         case XM_LINEAR_FREQUENCIES:
1384             return xm_linear_period(note);
1385         case XM_AMIGA_FREQUENCIES:
1386             return xm_amiga_period(note);
1387         default:
1388 	}
1389 	return .0f;
1390 }
1391 
1392 float xm_frequency(xm_context_t* ctx, float period, float note_offset, float period_offset) {
1393 	uint8_t a;
1394 	int8_t octave;
1395 	float note;
1396 	int32_t p1, p2;
1397 
1398 	switch(ctx.module_.frequency_type) 
1399     {
1400 
1401         case XM_LINEAR_FREQUENCIES:
1402             return xm_linear_frequency(period - 64.0f * note_offset - 16.0f * period_offset);
1403 
1404         case XM_AMIGA_FREQUENCIES:
1405             if(note_offset == 0) {
1406                 /* A chance to escape from insanity */
1407                 return xm_amiga_frequency(period + 16.0f * period_offset);
1408             }
1409 
1410             /* FIXME: this is very crappy at best */
1411             a = octave = 0;
1412 
1413             /* Find the octave of the current period */
1414             period *= AMIGA_FREQ_SCALE;
1415             if(period > amiga_frequencies[0]) {
1416                 --octave;
1417                 while(period > (amiga_frequencies[0] << (-cast(int)octave))) --octave;
1418             } else if(period < amiga_frequencies[12]) {
1419                 ++octave;
1420                 while(period < (amiga_frequencies[12] >> octave)) ++octave;
1421             }
1422 
1423             /* Find the smallest note closest to the current period */
1424             for(uint8_t i = 0; i < 12; ++i) {
1425                 p1 = amiga_frequencies[i], p2 = amiga_frequencies[i + 1];
1426 
1427                 if(octave > 0) {
1428                     p1 >>= octave;
1429                     p2 >>= octave;
1430                 } else if(octave < 0) {
1431                     p1 <<= (-cast(int)octave);
1432                     p2 <<= (-cast(int)octave);
1433                 }
1434 
1435                 if(p2 <= period && period <= p1) {
1436                     a = i;
1437                     break;
1438                 }
1439             }
1440 
1441             /*if(XM_DEBUG && (p1 < period || p2 > period)) 
1442             {
1443                 //DEBUG("%" PRId32 " <= %f <= %" PRId32 " should hold but doesn't, this is a bug", p2, period, p1);
1444                 assert(false);
1445             }*/
1446 
1447             note = 12.0f * (octave + 2) + a + XM_INVERSE_LERP(p1, p2, period);
1448 
1449             return xm_amiga_frequency(xm_amiga_period(note + note_offset) + 16.0f * period_offset);
1450 
1451         default:
1452 	}
1453 
1454 	return .0f;
1455 }
1456 
1457 void xm_update_frequency(xm_context_t* ctx, xm_channel_context_t* ch) {
1458 	ch.frequency = xm_frequency(
1459                                  ctx, ch.period,
1460                                  ch.arp_note_offset,
1461                                  ch.vibrato_note_offset + ch.autovibrato_note_offset
1462                                  );
1463 	ch.step = ch.frequency / ctx.rate;
1464 }
1465 
1466 void xm_handle_note_and_instrument(xm_context_t* ctx, xm_channel_context_t* ch,
1467 										  xm_pattern_slot_t* s) {
1468                                             if(s.instrument > 0) {
1469                                                 if(ch.current.HAS_TONE_PORTAMENTO() && ch.instrument != null && ch.sample != null) {
1470                                                     /* Tone portamento in effect, unclear stuff happens */
1471                                                     xm_trigger_note(ctx, ch, XM_TRIGGER_KEEP_PERIOD | XM_TRIGGER_KEEP_SAMPLE_POSITION);
1472                                                 } else if(s.note == 0 && ch.sample != null) {
1473                                                     /* Ghost instrument, trigger note */
1474                                                     /* Sample position is kept, but envelopes are reset */
1475                                                     xm_trigger_note(ctx, ch, XM_TRIGGER_KEEP_SAMPLE_POSITION);
1476                                                 } else if(s.instrument > ctx.module_.num_instruments) {
1477                                                     /* Invalid instrument, Cut current note */
1478                                                     xm_cut_note(ch);
1479                                                     ch.instrument = null;
1480                                                     ch.sample = null;
1481                                                 } else {
1482                                                     ch.instrument = ctx.module_.instruments + (s.instrument - 1);
1483                                                 }
1484                                             }
1485 
1486                                             if(NOTE_IS_VALID(s.note)) {
1487                                                 /* Yes, the real note number is s.note -1. Try finding
1488                                                 * THAT in any of the specs! :-) */
1489 
1490                                                 xm_instrument_t* instr = ch.instrument;
1491 
1492                                                 if(ch.current.HAS_TONE_PORTAMENTO() && instr != null && ch.sample != null) {
1493                                                     /* Tone portamento in effect */
1494                                                     ch.note = s.note + ch.sample.relative_note + ch.sample.finetune / 128.0f - 1.0f;
1495                                                     ch.tone_portamento_target_period = xm_period(ctx, ch.note);
1496                                                 } else if(instr == null || ch.instrument.num_samples == 0) {
1497                                                     /* Bad instrument */
1498                                                     xm_cut_note(ch);
1499                                                 } else {
1500                                                     if(instr.sample_of_notes[s.note - 1] < instr.num_samples) {
1501                                                         version(XM_RAMPING)
1502                                                         {
1503                                                             for(uint z = 0; z < XM_SAMPLE_RAMPING_POINTS; ++z) {
1504                                                                 ch.end_of_previous_sample[z] = xm_next_of_sample(ch);
1505                                                             }
1506                                                             ch.frame_count = 0;
1507                                                         }
1508                                                         ch.sample = instr.samples + instr.sample_of_notes[s.note - 1];
1509                                                         ch.orig_note = ch.note = s.note + ch.sample.relative_note
1510                                                             + ch.sample.finetune / 128.0f - 1.0f;
1511                                                         if(s.instrument > 0) {
1512                                                             xm_trigger_note(ctx, ch, 0);
1513                                                         } else {
1514                                                             /* Ghost note: keep old volume */
1515                                                             xm_trigger_note(ctx, ch, XM_TRIGGER_KEEP_VOLUME);
1516                                                         }
1517                                                     } else {
1518                                                         /* Bad sample */
1519                                                         xm_cut_note(ch);
1520                                                     }
1521                                                 }
1522                                             } else if(s.note == 97) {
1523                                                 /* Key Off */
1524                                                 xm_key_off(ch);
1525                                             }
1526 
1527                                             switch(s.volume_column >> 4) {
1528 
1529                                                 case 0x5:
1530                                                     if(s.volume_column > 0x50) break;
1531                                                     goto case 0x1;
1532 
1533                                                 case 0x1:
1534                                                 case 0x2:
1535                                                 case 0x3:
1536                                                 case 0x4:
1537                                                     /* Set volume */
1538                                                     ch.volume = cast(float)(s.volume_column - 0x10) / cast(float)0x40;
1539                                                     break;
1540 
1541                                                 case 0x8: /* Fine volume slide down */
1542                                                     xm_volume_slide(ch, s.volume_column & 0x0F);
1543                                                     break;
1544 
1545                                                 case 0x9: /* Fine volume slide up */
1546                                                     xm_volume_slide(ch, cast(ubyte)(s.volume_column << 4));
1547                                                     break;
1548 
1549                                                 case 0xA: /* Set vibrato speed */
1550                                                     ch.vibrato_param = (ch.vibrato_param & 0x0F) | ((s.volume_column & 0x0F) << 4);
1551                                                     break;
1552 
1553                                                 case 0xC: /* Set panning */
1554                                                     ch.panning = cast(float)(
1555                                                                           ((s.volume_column & 0x0F) << 4) | (s.volume_column & 0x0F)
1556                                                                           ) / cast(float)0xFF;
1557                                                     break;
1558 
1559                                                 case 0xF: /* Tone portamento */
1560                                                     if(s.volume_column & 0x0F) {
1561                                                         ch.tone_portamento_param = ((s.volume_column & 0x0F) << 4)
1562                                                             | (s.volume_column & 0x0F);
1563                                                     }
1564                                                     break;
1565 
1566                                                 default:
1567                                                     break;
1568 
1569                                             }
1570 
1571                                             switch(s.effect_type) {
1572 
1573                                                 case 1: /* 1xx: Portamento up */
1574                                                     if(s.effect_param > 0) {
1575                                                         ch.portamento_up_param = s.effect_param;
1576                                                     }
1577                                                     break;
1578 
1579                                                 case 2: /* 2xx: Portamento down */
1580                                                     if(s.effect_param > 0) {
1581                                                         ch.portamento_down_param = s.effect_param;
1582                                                     }
1583                                                     break;
1584 
1585                                                 case 3: /* 3xx: Tone portamento */
1586                                                     if(s.effect_param > 0) {
1587                                                         ch.tone_portamento_param = s.effect_param;
1588                                                     }
1589                                                     break;
1590 
1591                                                 case 4: /* 4xy: Vibrato */
1592                                                     if(s.effect_param & 0x0F) {
1593                                                         /* Set vibrato depth */
1594                                                         ch.vibrato_param = (ch.vibrato_param & 0xF0) | (s.effect_param & 0x0F);
1595                                                     }
1596                                                     if(s.effect_param >> 4) {
1597                                                         /* Set vibrato speed */
1598                                                         ch.vibrato_param = (s.effect_param & 0xF0) | (ch.vibrato_param & 0x0F);
1599                                                     }
1600                                                     break;
1601 
1602                                                 case 5: /* 5xy: Tone portamento + Volume slide */
1603                                                     if(s.effect_param > 0) {
1604                                                         ch.volume_slide_param = s.effect_param;
1605                                                     }
1606                                                     break;
1607 
1608                                                 case 6: /* 6xy: Vibrato + Volume slide */
1609                                                     if(s.effect_param > 0) {
1610                                                         ch.volume_slide_param = s.effect_param;
1611                                                     }
1612                                                     break;
1613 
1614                                                 case 7: /* 7xy: Tremolo */
1615                                                     if(s.effect_param & 0x0F) {
1616                                                         /* Set tremolo depth */
1617                                                         ch.tremolo_param = (ch.tremolo_param & 0xF0) | (s.effect_param & 0x0F);
1618                                                     }
1619                                                     if(s.effect_param >> 4) {
1620                                                         /* Set tremolo speed */
1621                                                         ch.tremolo_param = (s.effect_param & 0xF0) | (ch.tremolo_param & 0x0F);
1622                                                     }
1623                                                     break;
1624 
1625                                                 case 8: /* 8xx: Set panning */
1626                                                     ch.panning = cast(float)s.effect_param / cast(float)0xFF;
1627                                                     break;
1628 
1629                                                 case 9: /* 9xx: Sample offset */
1630                                                     if(ch.sample != null && NOTE_IS_VALID(s.note)) {
1631                                                         uint32_t final_offset = s.effect_param << (ch.sample.bits == 16 ? 7 : 8);
1632                                                         if(final_offset >= ch.sample.length) {
1633                                                             /* Pretend the sample dosen't loop and is done playing */
1634                                                             ch.sample_position = -1;
1635                                                             break;
1636                                                         }
1637                                                         ch.sample_position = final_offset;
1638                                                     }
1639                                                     break;
1640 
1641                                                 case 0xA: /* Axy: Volume slide */
1642                                                     if(s.effect_param > 0) {
1643                                                         ch.volume_slide_param = s.effect_param;
1644                                                     }
1645                                                     break;
1646 
1647                                                 case 0xB: /* Bxx: Position jump */
1648                                                     if(s.effect_param < ctx.module_.length) {
1649                                                         ctx.position_jump = true;
1650                                                         ctx.jump_dest = s.effect_param;
1651                                                         ctx.jump_row = 0;
1652                                                     }
1653                                                     break;
1654 
1655                                                 case 0xC: /* Cxx: Set volume */
1656                                                     ch.volume = cast(float)((s.effect_param > 0x40)
1657                                                                          ? 0x40 : s.effect_param) / cast(float)0x40;
1658                                                     break;
1659 
1660                                                 case 0xD: /* Dxx: Pattern break */
1661                                                     /* Jump after playing this line */
1662                                                     ctx.pattern_break = true;
1663                                                     ctx.jump_row = (s.effect_param >> 4) * 10 + (s.effect_param & 0x0F);
1664                                                     break;
1665 
1666                                                 case 0xE: /* EXy: Extended command */
1667                                                     switch(s.effect_param >> 4) {
1668 
1669                                                         case 1: /* E1y: Fine portamento up */
1670                                                             if(s.effect_param & 0x0F) {
1671                                                                 ch.fine_portamento_up_param = s.effect_param & 0x0F;
1672                                                             }
1673                                                             xm_pitch_slide(ctx, ch, -cast(int)(ch.fine_portamento_up_param));
1674                                                             break;
1675 
1676                                                         case 2: /* E2y: Fine portamento down */
1677                                                             if(s.effect_param & 0x0F) {
1678                                                                 ch.fine_portamento_down_param = s.effect_param & 0x0F;
1679                                                             }
1680                                                             xm_pitch_slide(ctx, ch, ch.fine_portamento_down_param);
1681                                                             break;
1682 
1683                                                         case 4: /* E4y: Set vibrato control */
1684                                                             ch.vibrato_waveform = s.effect_param & 3;
1685                                                             ch.vibrato_waveform_retrigger = !((s.effect_param >> 2) & 1);
1686                                                             break;
1687 
1688                                                         case 5: /* E5y: Set finetune */
1689                                                             if(NOTE_IS_VALID(ch.current.note) && ch.sample != null) {
1690                                                                 ch.note = ch.current.note + ch.sample.relative_note +
1691                                                                     cast(float)(((s.effect_param & 0x0F) - 8) << 4) / 128.0f - 1.0f;
1692                                                                 ch.period = xm_period(ctx, ch.note);
1693                                                                 xm_update_frequency(ctx, ch);
1694                                                             }
1695                                                             break;
1696 
1697                                                         case 6: /* E6y: Pattern loop */
1698                                                             if(s.effect_param & 0x0F) {
1699                                                                 if((s.effect_param & 0x0F) == ch.pattern_loop_count) {
1700                                                                     /* Loop is over */
1701                                                                     ch.pattern_loop_count = 0;
1702                                                                     break;
1703                                                                 }
1704 
1705                                                                 /* Jump to the beginning of the loop */
1706                                                                 ch.pattern_loop_count++;
1707                                                                 ctx.position_jump = true;
1708                                                                 ctx.jump_row = ch.pattern_loop_origin;
1709                                                                 ctx.jump_dest = ctx.current_table_index;
1710                                                             } else {
1711                                                                 /* Set loop start point */
1712                                                                 ch.pattern_loop_origin = ctx.current_row;
1713                                                                 /* Replicate FT2 E60 bug */
1714                                                                 ctx.jump_row = ch.pattern_loop_origin;
1715                                                             }
1716                                                             break;
1717 
1718                                                         case 7: /* E7y: Set tremolo control */
1719                                                             ch.tremolo_waveform = s.effect_param & 3;
1720                                                             ch.tremolo_waveform_retrigger = !((s.effect_param >> 2) & 1);
1721                                                             break;
1722 
1723                                                         case 0xA: /* EAy: Fine volume slide up */
1724                                                             if(s.effect_param & 0x0F) {
1725                                                                 ch.fine_volume_slide_param = s.effect_param & 0x0F;
1726                                                             }
1727                                                             xm_volume_slide(ch, cast(ubyte)(ch.fine_volume_slide_param << 4));
1728                                                             break;
1729 
1730                                                         case 0xB: /* EBy: Fine volume slide down */
1731                                                             if(s.effect_param & 0x0F) {
1732                                                                 ch.fine_volume_slide_param = s.effect_param & 0x0F;
1733                                                             }
1734                                                             xm_volume_slide(ch, ch.fine_volume_slide_param);
1735                                                             break;
1736 
1737                                                         case 0xD: /* EDy: Note delay */
1738                                                             /* XXX: figure this out better. EDx triggers
1739                                                             * the note even when there no note and no
1740                                                             * instrument. But ED0 acts like like a ghost
1741                                                             * note, EDx (x ≠ 0) does not. */
1742                                                             if(s.note == 0 && s.instrument == 0) {
1743                                                                 uint flags = XM_TRIGGER_KEEP_VOLUME;
1744 
1745                                                                 if(ch.current.effect_param & 0x0F) {
1746                                                                     ch.note = ch.orig_note;
1747                                                                     xm_trigger_note(ctx, ch, flags);
1748                                                                 } else {
1749                                                                     xm_trigger_note(
1750                                                                                     ctx, ch,
1751                                                                                     flags
1752                                                                                     | XM_TRIGGER_KEEP_PERIOD
1753                                                                                     | XM_TRIGGER_KEEP_SAMPLE_POSITION
1754                                                                                     );
1755                                                                 }
1756                                                             }
1757                                                             break;
1758 
1759                                                         case 0xE: /* EEy: Pattern delay */
1760                                                             ctx.extra_ticks = cast(ushort)( (ch.current.effect_param & 0x0F) * ctx.tempo );
1761                                                             break;
1762 
1763                                                         default:
1764                                                             break;
1765 
1766                                                     }
1767                                                     break;
1768 
1769                                                 case 0xF: /* Fxx: Set tempo/BPM */
1770                                                     if(s.effect_param > 0) {
1771                                                         if(s.effect_param <= 0x1F) {
1772                                                             ctx.tempo = s.effect_param;
1773                                                         } else {
1774                                                             ctx.bpm = s.effect_param;
1775                                                         }
1776                                                     }
1777                                                     break;
1778 
1779                                                 case 16: /* Gxx: Set global volume */
1780                                                     ctx.global_volume = cast(float)((s.effect_param > 0x40)
1781                                                                                  ? 0x40 : s.effect_param) / cast(float)0x40;
1782                                                     break;
1783 
1784                                                 case 17: /* Hxy: Global volume slide */
1785                                                     if(s.effect_param > 0) {
1786                                                         ch.global_volume_slide_param = s.effect_param;
1787                                                     }
1788                                                     break;
1789 
1790                                                 case 21: /* Lxx: Set envelope position */
1791                                                     ch.volume_envelope_frame_count = s.effect_param;
1792                                                     ch.panning_envelope_frame_count = s.effect_param;
1793                                                     break;
1794 
1795                                                 case 25: /* Pxy: Panning slide */
1796                                                     if(s.effect_param > 0) {
1797                                                         ch.panning_slide_param = s.effect_param;
1798                                                     }
1799                                                     break;
1800 
1801                                                 case 27: /* Rxy: Multi retrig note */
1802                                                     if(s.effect_param > 0) {
1803                                                         if((s.effect_param >> 4) == 0) {
1804                                                             /* Keep previous x value */
1805                                                             ch.multi_retrig_param = (ch.multi_retrig_param & 0xF0) | (s.effect_param & 0x0F);
1806                                                         } else {
1807                                                             ch.multi_retrig_param = s.effect_param;
1808                                                         }
1809                                                     }
1810                                                     break;
1811 
1812                                                 case 29: /* Txy: Tremor */
1813                                                     if(s.effect_param > 0) {
1814                                                         /* Tremor x and y params do not appear to be separately
1815                                                         * kept in memory, unlike Rxy */
1816                                                         ch.tremor_param = s.effect_param;
1817                                                     }
1818                                                     break;
1819 
1820                                                 case 33: /* Xxy: Extra stuff */
1821                                                     switch(s.effect_param >> 4) {
1822 
1823                                                         case 1: /* X1y: Extra fine portamento up */
1824                                                             if(s.effect_param & 0x0F) {
1825                                                                 ch.extra_fine_portamento_up_param = s.effect_param & 0x0F;
1826                                                             }
1827                                                             xm_pitch_slide(ctx, ch, -1.0f * ch.extra_fine_portamento_up_param);
1828                                                             break;
1829 
1830                                                         case 2: /* X2y: Extra fine portamento down */
1831                                                             if(s.effect_param & 0x0F) {
1832                                                                 ch.extra_fine_portamento_down_param = s.effect_param & 0x0F;
1833                                                             }
1834                                                             xm_pitch_slide(ctx, ch, ch.extra_fine_portamento_down_param);
1835                                                             break;
1836 
1837                                                         default:
1838                                                             break;
1839 
1840                                                     }
1841                                                     break;
1842 
1843                                                 default:
1844                                                     break;
1845 
1846                                             }
1847                                           }
1848 
1849 void xm_trigger_note(xm_context_t* ctx, xm_channel_context_t* ch, uint flags) {
1850 	if(!(flags & XM_TRIGGER_KEEP_SAMPLE_POSITION)) {
1851 		ch.sample_position = 0.0f;
1852 		ch.ping = true;
1853 	}
1854 
1855 	if(ch.sample != null) {
1856 		if(!(flags & XM_TRIGGER_KEEP_VOLUME)) {
1857 			ch.volume = ch.sample.volume;
1858 		}
1859 
1860 		ch.panning = ch.sample.panning;
1861 	}
1862 
1863 	if(!(flags & XM_TRIGGER_KEEP_ENVELOPE)) {
1864 		ch.sustained = true;
1865 		ch.fadeout_volume = ch.volume_envelope_volume = 1.0f;
1866 		ch.panning_envelope_panning = .5f;
1867 		ch.volume_envelope_frame_count = ch.panning_envelope_frame_count = 0;
1868 	}
1869 	ch.vibrato_note_offset = 0.0f;
1870 	ch.tremolo_volume = 0.0f;
1871 	ch.tremor_on = false;
1872 
1873 	ch.autovibrato_ticks = 0;
1874 
1875 	if(ch.vibrato_waveform_retrigger) {
1876 		ch.vibrato_ticks = 0; /* XXX: should the waveform itself also
1877         * be reset to sine? */
1878 	}
1879 	if(ch.tremolo_waveform_retrigger) {
1880 		ch.tremolo_ticks = 0;
1881 	}
1882 
1883 	if(!(flags & XM_TRIGGER_KEEP_PERIOD)) {
1884 		ch.period = xm_period(ctx, ch.note);
1885 		xm_update_frequency(ctx, ch);
1886 	}
1887 
1888 	ch.latest_trigger = ctx.generated_samples;
1889 	if(ch.instrument != null) {
1890 		ch.instrument.latest_trigger = ctx.generated_samples;
1891 	}
1892 	if(ch.sample != null) {
1893 		ch.sample.latest_trigger = ctx.generated_samples;
1894 	}
1895 }
1896 
1897 void xm_cut_note(xm_channel_context_t* ch) {
1898 	/* NB: this is not the same as Key Off */
1899 	ch.volume = .0f;
1900 }
1901 
1902 void xm_key_off(xm_channel_context_t* ch) {
1903 	/* Key Off */
1904 	ch.sustained = false;
1905 
1906 	/* If no volume envelope is used, also cut the note */
1907 	if(ch.instrument == null || !ch.instrument.volume_envelope.enabled) {
1908 		xm_cut_note(ch);
1909 	}
1910 }
1911 
1912 void xm_row(xm_context_t* ctx) {
1913 	if(ctx.position_jump) {
1914 		ctx.current_table_index = ctx.jump_dest;
1915 		ctx.current_row = ctx.jump_row;
1916 		ctx.position_jump = false;
1917 		ctx.pattern_break = false;
1918 		ctx.jump_row = 0;
1919 		xm_post_pattern_change(ctx);
1920 	} else if(ctx.pattern_break) {
1921 		ctx.current_table_index++;
1922 		ctx.current_row = ctx.jump_row;
1923 		ctx.pattern_break = false;
1924 		ctx.jump_row = 0;
1925 		xm_post_pattern_change(ctx);
1926 	}
1927 
1928 	xm_pattern_t* cur = ctx.module_.patterns + ctx.module_.pattern_table[ctx.current_table_index];
1929 	bool in_a_loop = false;
1930 
1931 	/* Read notes… */
1932 	for(uint8_t i = 0; i < ctx.module_.num_channels; ++i) {
1933 		xm_pattern_slot_t* s = cur.slots + ctx.current_row * ctx.module_.num_channels + i;
1934 		xm_channel_context_t* ch = ctx.channels + i;
1935 
1936 		ch.current = s;
1937 
1938 		if(s.effect_type != 0xE || s.effect_param >> 4 != 0xD) {
1939 			xm_handle_note_and_instrument(ctx, ch, s);
1940 		} else {
1941 			ch.note_delay_param = s.effect_param & 0x0F;
1942 		}
1943 
1944 		if(!in_a_loop && ch.pattern_loop_count > 0) {
1945 			in_a_loop = true;
1946 		}
1947 	}
1948 
1949 	if(!in_a_loop) {
1950 		/* No E6y loop is in effect (or we are in the first pass) */
1951 		ctx.loop_count = (ctx.row_loop_count[MAX_NUM_ROWS * ctx.current_table_index + ctx.current_row]++);
1952 	}
1953 
1954 	ctx.current_row++; /* Since this is an uint8, this line can
1955     * increment from 255 to 0, in which case it
1956     * is still necessary to go the next
1957     * pattern. */
1958 	if(!ctx.position_jump && !ctx.pattern_break &&
1959 	   (ctx.current_row >= cur.num_rows || ctx.current_row == 0)) {
1960 		ctx.current_table_index++;
1961 		ctx.current_row = ctx.jump_row; /* This will be 0 most of
1962         * the time, except when E60
1963         * is used */
1964 		ctx.jump_row = 0;
1965 		xm_post_pattern_change(ctx);
1966        }
1967 }
1968 
1969 void xm_envelope_tick(xm_channel_context_t* ch,
1970 							 xm_envelope_t* env,
1971 							 uint16_t* counter,
1972 							 float* outval) {
1973                                 if(env.num_points < 2) {
1974                                     /* Don't really know what to do… */
1975                                     if(env.num_points == 1) {
1976                                         /* XXX I am pulling this out of my ass */
1977                                         *outval = cast(float)env.points[0].value / cast(float)0x40;
1978                                         if(*outval > 1) {
1979                                             *outval = 1;
1980                                         }
1981                                     }
1982 
1983                                     return;
1984                                 } else {
1985                                     uint8_t j;
1986 
1987                                     if(env.loop_enabled) {
1988                                         uint16_t loop_start = env.points[env.loop_start_point].frame;
1989                                         uint16_t loop_end = env.points[env.loop_end_point].frame;
1990                                         uint16_t loop_length = cast(ushort)(loop_end - loop_start);
1991 
1992                                         if(*counter >= loop_end) {
1993                                             *counter -= loop_length;
1994                                         }
1995                                     }
1996 
1997                                     for(j = 0; j < (env.num_points - 2); ++j) {
1998                                         if(env.points[j].frame <= *counter &&
1999                                            env.points[j+1].frame >= *counter) {
2000                                             break;
2001                                            }
2002                                     }
2003 
2004                                     *outval = xm_envelope_lerp(env.points.ptr + j, env.points.ptr + j + 1, *counter) / cast(float)0x40;
2005 
2006                                     /* Make sure it is safe to increment frame count */
2007                                     if(!ch.sustained || !env.sustain_enabled ||
2008                                        *counter != env.points[env.sustain_point].frame) {
2009                                         (*counter)++;
2010                                        }
2011                                 }
2012                              }
2013 
2014 void xm_envelopes(xm_channel_context_t* ch) {
2015 	if(ch.instrument != null) {
2016 		if(ch.instrument.volume_envelope.enabled) {
2017 			if(!ch.sustained) {
2018 				ch.fadeout_volume -= ch.instrument.volume_fadeout / 32768.0f;
2019 				if(ch.fadeout_volume < 0) ch.fadeout_volume = 0;
2020 			}
2021 
2022 			xm_envelope_tick(ch,
2023 							 &(ch.instrument.volume_envelope),
2024 							 &(ch.volume_envelope_frame_count),
2025 							 &(ch.volume_envelope_volume));
2026 		}
2027 
2028 		if(ch.instrument.panning_envelope.enabled) {
2029 			xm_envelope_tick(ch,
2030 							 &(ch.instrument.panning_envelope),
2031 							 &(ch.panning_envelope_frame_count),
2032 							 &(ch.panning_envelope_panning));
2033 		}
2034 	}
2035 }
2036 
2037 void xm_tick(xm_context_t* ctx) {
2038 	if(ctx.current_tick == 0) {
2039 		xm_row(ctx);
2040 	}
2041 
2042 	for(uint8_t i = 0; i < ctx.module_.num_channels; ++i) {
2043 		xm_channel_context_t* ch = ctx.channels + i;
2044 
2045 		xm_envelopes(ch);
2046 		xm_autovibrato(ctx, ch);
2047 
2048 		if(ch.arp_in_progress && !ch.current.HAS_ARPEGGIO()) {
2049 			ch.arp_in_progress = false;
2050 			ch.arp_note_offset = 0;
2051 			xm_update_frequency(ctx, ch);
2052 		}
2053 		if(ch.vibrato_in_progress && !ch.current.HAS_VIBRATO()) {
2054 			ch.vibrato_in_progress = false;
2055 			ch.vibrato_note_offset = 0.0f;
2056 			xm_update_frequency(ctx, ch);
2057 		}
2058 
2059 		switch(ch.current.volume_column >> 4) {
2060 
2061             case 0x6: /* Volume slide down */
2062                 if(ctx.current_tick == 0) break;
2063                 xm_volume_slide(ch, ch.current.volume_column & 0x0F);
2064                 break;
2065 
2066             case 0x7: /* Volume slide up */
2067                 if(ctx.current_tick == 0) break;
2068                 xm_volume_slide(ch, cast(ubyte)(ch.current.volume_column << 4));
2069                 break;
2070 
2071             case 0xB: /* Vibrato */
2072                 if(ctx.current_tick == 0) break;
2073                 ch.vibrato_in_progress = false;
2074                 xm_vibrato(ctx, ch, ch.vibrato_param);
2075                 break;
2076 
2077             case 0xD: /* Panning slide left */
2078                 if(ctx.current_tick == 0) break;
2079                 xm_panning_slide(ch, ch.current.volume_column & 0x0F);
2080                 break;
2081 
2082             case 0xE: /* Panning slide right */
2083                 if(ctx.current_tick == 0) break;
2084                 xm_panning_slide(ch, cast(ubyte)(ch.current.volume_column << 4));
2085                 break;
2086 
2087             case 0xF: /* Tone portamento */
2088                 if(ctx.current_tick == 0) break;
2089                 xm_tone_portamento(ctx, ch);
2090                 break;
2091 
2092             default:
2093                 break;
2094 
2095 		}
2096 
2097 		switch(ch.current.effect_type) {
2098 
2099             case 0: /* 0xy: Arpeggio */
2100                 if(ch.current.effect_param > 0) {
2101                     char arp_offset = ctx.tempo % 3;
2102                     switch(arp_offset) {
2103                         case 2: /* 0 . x . 0 . y . x . … */
2104                             if(ctx.current_tick == 1) {
2105                                 ch.arp_in_progress = true;
2106                                 ch.arp_note_offset = ch.current.effect_param >> 4;
2107                                 xm_update_frequency(ctx, ch);
2108                                 break;
2109                             }
2110                             /* No break here, this is intended */
2111                             goto case 1;
2112 
2113                         case 1: /* 0 . 0 . y . x . … */
2114                             if(ctx.current_tick == 0) 
2115                             {
2116                                 ch.arp_in_progress = false;
2117                                 ch.arp_note_offset = 0;
2118                                 xm_update_frequency(ctx, ch);
2119                                 break;
2120                             }
2121                             /* No break here, this is intended */
2122                             goto case 0;
2123 
2124                         case 0: /* 0 . y . x . … */
2125                             xm_arpeggio(ctx, ch, ch.current.effect_param, cast(ushort)(ctx.current_tick - arp_offset));
2126                             break;
2127 
2128                         default:
2129                             break;
2130                     }
2131                 }
2132                 break;
2133 
2134             case 1: /* 1xx: Portamento up */
2135                 if(ctx.current_tick == 0) break;
2136                 xm_pitch_slide(ctx, ch, -cast(int)ch.portamento_up_param);
2137                 break;
2138 
2139             case 2: /* 2xx: Portamento down */
2140                 if(ctx.current_tick == 0) break;
2141                 xm_pitch_slide(ctx, ch, ch.portamento_down_param);
2142                 break;
2143 
2144             case 3: /* 3xx: Tone portamento */
2145                 if(ctx.current_tick == 0) break;
2146                 xm_tone_portamento(ctx, ch);
2147                 break;
2148 
2149             case 4: /* 4xy: Vibrato */
2150                 if(ctx.current_tick == 0) break;
2151                 ch.vibrato_in_progress = true;
2152                 xm_vibrato(ctx, ch, ch.vibrato_param);
2153                 break;
2154 
2155             case 5: /* 5xy: Tone portamento + Volume slide */
2156                 if(ctx.current_tick == 0) break;
2157                 xm_tone_portamento(ctx, ch);
2158                 xm_volume_slide(ch, ch.volume_slide_param);
2159                 break;
2160 
2161             case 6: /* 6xy: Vibrato + Volume slide */
2162                 if(ctx.current_tick == 0) break;
2163                 ch.vibrato_in_progress = true;
2164                 xm_vibrato(ctx, ch, ch.vibrato_param);
2165                 xm_volume_slide(ch, ch.volume_slide_param);
2166                 break;
2167 
2168             case 7: /* 7xy: Tremolo */
2169                 if(ctx.current_tick == 0) break;
2170                 xm_tremolo(ctx, ch, ch.tremolo_param, ch.tremolo_ticks++);
2171                 break;
2172 
2173             case 0xA: /* Axy: Volume slide */
2174                 if(ctx.current_tick == 0) break;
2175                 xm_volume_slide(ch, ch.volume_slide_param);
2176                 break;
2177 
2178             case 0xE: /* EXy: Extended command */
2179                 switch(ch.current.effect_param >> 4) {
2180 
2181                     case 0x9: /* E9y: Retrigger note */
2182                         if(ctx.current_tick != 0 && ch.current.effect_param & 0x0F) {
2183                             if(!(ctx.current_tick % (ch.current.effect_param & 0x0F))) {
2184                                 xm_trigger_note(ctx, ch, XM_TRIGGER_KEEP_VOLUME);
2185                                 xm_envelopes(ch);
2186                             }
2187                         }
2188                         break;
2189 
2190                     case 0xC: /* ECy: Note cut */
2191                         if((ch.current.effect_param & 0x0F) == ctx.current_tick) {
2192                             xm_cut_note(ch);
2193                         }
2194                         break;
2195 
2196                     case 0xD: /* EDy: Note delay */
2197                         if(ch.note_delay_param == ctx.current_tick) {
2198                             xm_handle_note_and_instrument(ctx, ch, ch.current);
2199                             xm_envelopes(ch);
2200                         }
2201                         break;
2202 
2203                     default:
2204                         break;
2205 
2206                 }
2207                 break;
2208 
2209             case 17: /* Hxy: Global volume slide */
2210                 if(ctx.current_tick == 0) break;
2211                 if((ch.global_volume_slide_param & 0xF0) &&
2212                    (ch.global_volume_slide_param & 0x0F)) {
2213                     /* Illegal state */
2214                     break;
2215                    }
2216                 if(ch.global_volume_slide_param & 0xF0) {
2217                     /* Global slide up */
2218                     float f = cast(float)(ch.global_volume_slide_param >> 4) / cast(float)0x40;
2219                     ctx.global_volume += f;
2220                     if(ctx.global_volume > 1)
2221                         ctx.global_volume = 1;
2222                 } else {
2223                     /* Global slide down */
2224                     float f = cast(float)(ch.global_volume_slide_param & 0x0F) / cast(float)0x40;
2225                     ctx.global_volume -= f;
2226                     if (ctx.global_volume < 0)
2227                         ctx.global_volume = 0;
2228                 }
2229                 break;
2230 
2231             case 20: /* Kxx: Key off */
2232                 /* Most documentations will tell you the parameter has no
2233                 * use. Don't be fooled. */
2234                 if(ctx.current_tick == ch.current.effect_param) {
2235                     xm_key_off(ch);
2236                 }
2237                 break;
2238 
2239             case 25: /* Pxy: Panning slide */
2240                 if(ctx.current_tick == 0) break;
2241                 xm_panning_slide(ch, ch.panning_slide_param);
2242                 break;
2243 
2244             case 27: /* Rxy: Multi retrig note */
2245                 if(ctx.current_tick == 0) break;
2246                 if(((ch.multi_retrig_param) & 0x0F) == 0) break;
2247                 if((ctx.current_tick % (ch.multi_retrig_param & 0x0F)) == 0) {
2248                     xm_trigger_note(ctx, ch, XM_TRIGGER_KEEP_VOLUME | XM_TRIGGER_KEEP_ENVELOPE);
2249 
2250                     /* Rxy doesn't affect volume if there's a command in the volume
2251                     column, or if the instrument has a volume envelope. */
2252                     if (!ch.current.volume_column && !ch.instrument.volume_envelope.enabled){
2253                         float v = ch.volume * multi_retrig_multiply[ch.multi_retrig_param >> 4]
2254                             + multi_retrig_add[ch.multi_retrig_param >> 4] / cast(float)0x40;
2255                         if (v < 0) v = 0;
2256                         if (v > 1) v = 1;
2257                         ch.volume = v;
2258                     }
2259                 }
2260                 break;
2261 
2262             case 29: /* Txy: Tremor */
2263                 if(ctx.current_tick == 0) break;
2264                 ch.tremor_on = (
2265                                  (ctx.current_tick - 1) % ((ch.tremor_param >> 4) + (ch.tremor_param & 0x0F) + 2)
2266                                  >
2267                                  (ch.tremor_param >> 4)
2268                                  );
2269                 break;
2270 
2271             default:
2272                 break;
2273 
2274 		}
2275 
2276 		float panning, volume;
2277 
2278 		panning = ch.panning +
2279 			(ch.panning_envelope_panning - .5f) * (.5f - fast_fabs(ch.panning - .5f)) * 2.0f;
2280 
2281 		if(ch.tremor_on) {
2282             volume = .0f;
2283 		} else {
2284 			volume = ch.volume + ch.tremolo_volume;
2285 			if (volume < 0) volume = 0;
2286             if (volume > 1) volume = 1;
2287 			volume *= ch.fadeout_volume * ch.volume_envelope_volume;
2288 		}
2289 
2290         version(XM_RAMPING)
2291         {
2292 		    /* See https://modarchive.org/forums/index.php?topic=3517.0
2293             * and https://github.com/Artefact2/libxm/pull/16 */
2294 		    ch.target_volume[0] = volume * fast_sqrt(1.0f - panning);
2295 		    ch.target_volume[1] = volume * fast_sqrt(panning);
2296         }
2297         else
2298         {
2299 		    ch.actual_volume[0] = volume * fast_sqrt(1.0f - panning);
2300 		    ch.actual_volume[1] = volume * fast_sqrt(panning);
2301         }
2302 	}
2303 
2304 	ctx.current_tick++;
2305 	if(ctx.current_tick >= ctx.tempo + ctx.extra_ticks) {
2306 		ctx.current_tick = 0;
2307 		ctx.extra_ticks = 0;
2308 	}
2309 
2310 	/* FT2 manual says number of ticks / second = BPM * 0.4 */
2311 	ctx.remaining_samples_in_tick += cast(float)ctx.rate / (cast(float)ctx.bpm * 0.4f);
2312 }
2313 
2314 float xm_sample_at(xm_sample_t* sample, size_t k) {
2315 	return sample.bits == 8 ? (sample.data8[k] / 128.0f) : (sample.data16[k] / 32768.0f);
2316 }
2317 
2318 float xm_next_of_sample(xm_channel_context_t* ch) {
2319 	if(ch.instrument == null || ch.sample == null || ch.sample_position < 0) {
2320         version(XM_RAMPING)
2321         {
2322 		    if(ch.frame_count < XM_SAMPLE_RAMPING_POINTS) {
2323 			    return XM_LERP(ch.end_of_previous_sample[ch.frame_count], .0f,
2324 			                   cast(float)ch.frame_count / cast(float)XM_SAMPLE_RAMPING_POINTS);
2325 		    }
2326         }
2327 		return .0f;
2328 	}
2329 	if(ch.sample.length == 0) {
2330 		return .0f;
2331 	}
2332 
2333 	float u, v, t;
2334 	uint32_t a, b;
2335 	a = cast(uint32_t)ch.sample_position; /* This cast is fine,
2336     * sample_position will not
2337     * go above integer
2338     * ranges */
2339 	if(XM_LINEAR_INTERPOLATION) {
2340 		b = a + 1;
2341 		t = ch.sample_position - a;
2342 	}
2343 	u = xm_sample_at(ch.sample, a);
2344 
2345 	switch(ch.sample.loop_type) {
2346 
2347         case XM_NO_LOOP:
2348             if(XM_LINEAR_INTERPOLATION) {
2349                 v = (b < ch.sample.length) ? xm_sample_at(ch.sample, b) : .0f;
2350             }
2351             ch.sample_position += ch.step;
2352             if(ch.sample_position >= ch.sample.length) {
2353                 ch.sample_position = -1;
2354             }
2355             break;
2356 
2357         case XM_FORWARD_LOOP:
2358             if(XM_LINEAR_INTERPOLATION) {
2359                 v = xm_sample_at(
2360                                  ch.sample,
2361                                  (b == ch.sample.loop_end) ? ch.sample.loop_start : b
2362                                  );
2363             }
2364             ch.sample_position += ch.step;
2365             while(ch.sample_position >= ch.sample.loop_end) {
2366                 ch.sample_position -= ch.sample.loop_length;
2367             }
2368             break;
2369 
2370         case XM_PING_PONG_LOOP:
2371             if(ch.ping) {
2372                 ch.sample_position += ch.step;
2373             } else {
2374                 ch.sample_position -= ch.step;
2375             }
2376             /* XXX: this may not work for very tight ping-pong loops
2377             * (ie switches direction more than once per sample */
2378             if(ch.ping) {
2379                 if(XM_LINEAR_INTERPOLATION) {
2380                     v = xm_sample_at(ch.sample, (b >= ch.sample.loop_end) ? a : b);
2381                 }
2382                 if(ch.sample_position >= ch.sample.loop_end) {
2383                     ch.ping = false;
2384                     ch.sample_position = (ch.sample.loop_end << 1) - ch.sample_position;
2385                 }
2386                 /* sanity checking */
2387                 if(ch.sample_position >= ch.sample.length) {
2388                     ch.ping = false;
2389                     ch.sample_position -= ch.sample.length - 1;
2390                 }
2391             } else {
2392                 if(XM_LINEAR_INTERPOLATION) {
2393                     v = u;
2394                     u = xm_sample_at(
2395                                      ch.sample,
2396                                      (b == 1 || b - 2 <= ch.sample.loop_start) ? a : (b - 2)
2397                                      );
2398                 }
2399                 if(ch.sample_position <= ch.sample.loop_start) {
2400                     ch.ping = true;
2401                     ch.sample_position = (ch.sample.loop_start << 1) - ch.sample_position;
2402                 }
2403                 /* sanity checking */
2404                 if(ch.sample_position <= .0f) {
2405                     ch.ping = true;
2406                     ch.sample_position = .0f;
2407                 }
2408             }
2409             break;
2410 
2411         default:
2412             v = .0f;
2413             break;
2414 	}
2415 
2416 	float endval = (XM_LINEAR_INTERPOLATION ? XM_LERP(u, v, t) : u);
2417 
2418     version(XM_RAMPING)
2419     {
2420 	    if(ch.frame_count < XM_SAMPLE_RAMPING_POINTS) {
2421 		    /* Smoothly transition between old and new sample. */
2422 		    return XM_LERP(ch.end_of_previous_sample[ch.frame_count], endval,
2423 		                   cast(float)ch.frame_count / cast(float)XM_SAMPLE_RAMPING_POINTS);
2424 	    }
2425     }
2426 
2427 	return endval;
2428 }
2429 
2430 void xm_sample(xm_context_t* ctx, float* left, float* right) {
2431 	if(ctx.remaining_samples_in_tick <= 0) {
2432 		xm_tick(ctx);
2433 	}
2434 	ctx.remaining_samples_in_tick--;
2435 
2436 	*left = 0.0f;
2437 	*right = 0.0f;
2438 
2439 	if(ctx.max_loop_count > 0 && ctx.loop_count >= ctx.max_loop_count) {
2440 		return;
2441 	}
2442 
2443 	for(uint8_t i = 0; i < ctx.module_.num_channels; ++i) {
2444 		xm_channel_context_t* ch = ctx.channels + i;
2445 
2446 		if(ch.instrument == null || ch.sample == null || ch.sample_position < 0) {
2447 			continue;
2448 		}
2449 
2450 		const float fval = xm_next_of_sample(ch);
2451 
2452 		if(!ch.muted && !ch.instrument.muted) {
2453 			*left += fval * ch.actual_volume[0];
2454 			*right += fval * ch.actual_volume[1];
2455 		}
2456 
2457         version(XM_RAMPING)
2458         {
2459 		    ch.frame_count++;
2460 		    XM_SLIDE_TOWARDS(ch.actual_volume[0], ch.target_volume[0], ctx.volume_ramp);
2461 		    XM_SLIDE_TOWARDS(ch.actual_volume[1], ch.target_volume[1], ctx.volume_ramp);
2462         }
2463 	}
2464 
2465 	const float fgvol = ctx.global_volume * ctx.amplification;
2466 	*left *= fgvol;
2467 	*right *= fgvol;
2468 
2469 	/*if(XM_DEBUG) {
2470 		if(fast_fabs(*left) > 1 || fast_fabs(*right) > 1) 
2471         {
2472             assert(false);
2473 			//DEBUG("clipping frame: %f %f, this is a bad module or a libxm bug", *left, *right);
2474 		}
2475 	}*/
2476 }
2477 
2478 void xm_generate_samples(xm_context_t* ctx, float* output, size_t numsamples) {
2479 	ctx.generated_samples += numsamples;
2480 
2481 	for(size_t i = 0; i < numsamples; i++) {
2482 		xm_sample(ctx, output + (2 * i), output + (2 * i + 1));
2483 	}
2484 }