The OpenD Programming Language

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