summaryrefslogtreecommitdiff
path: root/src/include/sndfile.h
blob: 22ce895536b8a34e70a241e093989fd64a1fe812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
/*
 * This source code is public domain.
 *
 * Authors: Olivier Lapicque <olivierl@jps.net>,
 *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
*/
#ifndef __SNDFILE_H
#define __SNDFILE_H

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#define NEED_BYTESWAP
#include "headers.h"

#include "tables.h"


#define MOD_AMIGAC2             0x1AB
#define MAX_SAMPLE_LENGTH       16000000
#define MAX_SAMPLE_RATE         192000
#define MAX_ORDERS              256
#define MAX_PATTERNS            240
#define MAX_SAMPLES             236
#define MAX_INSTRUMENTS         MAX_SAMPLES
#define MAX_VOICES              256
#define MAX_CHANNELS            64
#define MAX_ENVPOINTS           32
#define MAX_INFONAME            80
#define MAX_EQ_BANDS            6
#define MAX_MESSAGE             8000

#define MIXBUFFERSIZE           512


#define CHN_16BIT               0x01 // 16-bit sample
#define CHN_LOOP                0x02 // looped sample
#define CHN_PINGPONGLOOP        0x04 // bi-directional (useless unless CHN_LOOP is also set)
#define CHN_SUSTAINLOOP         0x08 // sample with sustain loop
#define CHN_PINGPONGSUSTAIN     0x10 // bi-directional (useless unless CHN_SUSTAINLOOP is also set)
#define CHN_PANNING             0x20 // sample with default panning set
#define CHN_STEREO              0x40 // stereo sample
#define CHN_PINGPONGFLAG        0x80 // when flag is on, sample is processed backwards
#define CHN_MUTE                0x100 // muted channel
#define CHN_KEYOFF              0x200 // exit sustain (note-off encountered)
#define CHN_NOTEFADE            0x400 // fade note (~~~ or end of instrument envelope)
#define CHN_SURROUND            0x800 // use surround channel (S91)
#define CHN_NOIDO               0x1000 // near enough to an exact multiple of c5speed that interpolation
				       // won't be noticeable (or interpolation is disabled completely)
#define CHN_HQSRC               0x2000 // ???
#define CHN_FILTER              0x4000 // filtered output (i.e., Zxx)
#define CHN_VOLUMERAMP          0x8000 // ramp volume
#define CHN_VIBRATO             0x10000 // apply vibrato
#define CHN_TREMOLO             0x20000 // apply tremolo
//#define CHN_PANBRELLO         0x40000 // apply panbrello (handled elsewhere now)
#define CHN_PORTAMENTO          0x80000 // apply portamento
#define CHN_GLISSANDO           0x100000 // glissando mode ("stepped" pitch slides)
#define CHN_VOLENV              0x200000 // volume envelope is active
#define CHN_PANENV              0x400000 // pan envelope is active
#define CHN_PITCHENV            0x800000 // pitch/filter envelope is active
#define CHN_FASTVOLRAMP         0x1000000 // ramp volume very fast (XXX this is a dumb flag)
//#define CHN_EXTRALOUD         0x2000000
//#define CHN_REVERB            0x4000000
//#define CHN_NOREVERB          0x8000000
#define CHN_NNAMUTE             0x10000000 // turn off mute, but have it reset later
#define CHN_ADLIB               0x20000000 // OPL mode

#define CHN_SAMPLE_FLAGS (CHN_16BIT | CHN_LOOP | CHN_PINGPONGLOOP | CHN_SUSTAINLOOP \
	| CHN_PINGPONGSUSTAIN | CHN_PANNING | CHN_STEREO | CHN_PINGPONGFLAG | CHN_ADLIB)


#define ENV_VOLUME              0x0001
#define ENV_VOLSUSTAIN          0x0002
#define ENV_VOLLOOP             0x0004
#define ENV_PANNING             0x0008
#define ENV_PANSUSTAIN          0x0010
#define ENV_PANLOOP             0x0020
#define ENV_PITCH               0x0040
#define ENV_PITCHSUSTAIN        0x0080
#define ENV_PITCHLOOP           0x0100
#define ENV_SETPANNING          0x0200
#define ENV_FILTER              0x0400
#define ENV_VOLCARRY            0x0800
#define ENV_PANCARRY            0x1000
#define ENV_PITCHCARRY          0x2000
#define ENV_MUTE                0x4000

#define FX_NONE                0 // .
#define FX_ARPEGGIO            1 // J
#define FX_PORTAMENTOUP        2 // F
#define FX_PORTAMENTODOWN      3 // E
#define FX_TONEPORTAMENTO      4 // G
#define FX_VIBRATO             5 // H
#define FX_TONEPORTAVOL        6 // L
#define FX_VIBRATOVOL          7 // K
#define FX_TREMOLO             8 // R
#define FX_PANNING             9 // X
#define FX_OFFSET              10 // O
#define FX_VOLUMESLIDE         11 // D
#define FX_POSITIONJUMP        12 // B
#define FX_VOLUME              13 // ! (FT2/IMF Cxx)
#define FX_PATTERNBREAK        14 // C
#define FX_RETRIG              15 // Q
#define FX_SPEED               16 // A
#define FX_TEMPO               17 // T
#define FX_TREMOR              18 // I
#define FX_SPECIAL             20 // S
#define FX_CHANNELVOLUME       21 // M
#define FX_CHANNELVOLSLIDE     22 // N
#define FX_GLOBALVOLUME        23 // V
#define FX_GLOBALVOLSLIDE      24 // W
#define FX_KEYOFF              25 // $ (FT2 Kxx)
#define FX_FINEVIBRATO         26 // U
#define FX_PANBRELLO           27 // Y
#define FX_PANNINGSLIDE        29 // P
#define FX_SETENVPOSITION      30 // & (FT2 Lxx)
#define FX_MIDI                31 // Z
#define FX_NOTESLIDEUP         32 // ( (IMF Gxy)
#define FX_NOTESLIDEDOWN       33 // ) (IMF Hxy)
#define FX_MAX                 34
#define FX_UNIMPLEMENTED       FX_MAX // no-op, displayed as "?"

#define FX_IS_EFFECT(v) ((v) > 0 && (v) < FX_MAX)

// Volume Column commands
#define VOLFX_NONE             0
#define VOLFX_VOLUME           1
#define VOLFX_PANNING          2
#define VOLFX_VOLSLIDEUP       3 // C
#define VOLFX_VOLSLIDEDOWN     4 // D
#define VOLFX_FINEVOLUP        5 // A
#define VOLFX_FINEVOLDOWN      6 // B
#define VOLFX_VIBRATOSPEED     7 // $ (FT2 Ax)
#define VOLFX_VIBRATODEPTH     8 // H
#define VOLFX_PANSLIDELEFT     9 // < (FT2 Dx)
#define VOLFX_PANSLIDERIGHT    10 // > (FT2 Ex)
#define VOLFX_TONEPORTAMENTO   11 // G
#define VOLFX_PORTAUP          12 // F
#define VOLFX_PORTADOWN        13 // E

// orderlist
#define ORDER_SKIP              254 // +++
#define ORDER_LAST              255 // ---

// 'Special' notes
// Note fade IS actually supported in Impulse Tracker, but there's no way to handle it in the editor
// (Actually, any non-valid note is handled internally as a note fade, but it's good to have a single
// value for internal representation)
// update 20090805: ok just discovered that IT internally uses 253 for its "no note" value.
// guess we'll use a different value for fade!
// note: 246 is rather arbitrary, but IT conveniently displays this value as "F#D" ("FD" with 2-char notes)
#define NOTE_NONE               0   // ...
#define NOTE_FIRST              1   // C-0
#define NOTE_MIDC               61  // C-5
#define NOTE_LAST               120 // B-9
#define NOTE_FADE               246 // ~~~
#define NOTE_CUT                254 // ^^^
#define NOTE_OFF                255 // ===
#define NOTE_IS_NOTE(n)         ((n) > NOTE_NONE && (n) <= NOTE_LAST) // anything playable - C-0 to B-9
#define NOTE_IS_CONTROL(n)      ((n) > NOTE_LAST)                     // not a note, but non-empty
#define NOTE_IS_INVALID(n)      ((n) > NOTE_LAST && (n) < NOTE_CUT && (n) != NOTE_FADE) // ???

// Auto-vibrato types
#define VIB_SINE                0
#define VIB_RAMP_DOWN           1
#define VIB_SQUARE              2
#define VIB_RANDOM              3

// NNA types
#define NNA_NOTECUT             0
#define NNA_CONTINUE            1
#define NNA_NOTEOFF             2
#define NNA_NOTEFADE            3

// DCT types
#define DCT_NONE                0
#define DCT_NOTE                1
#define DCT_SAMPLE              2
#define DCT_INSTRUMENT          3

// DCA types
#define DCA_NOTECUT             0
#define DCA_NOTEOFF             1
#define DCA_NOTEFADE            2

// Nothing innately special about this -- just needs to be above the max pattern length.
// process row is set to this in order to get the player to jump to the end of the pattern.
// (See ITTECH.TXT)
#define PROCESS_NEXT_ORDER      0xFFFE

// Module flags
#define SONG_EMBEDMIDICFG       0x0001 // Embed MIDI macros (Shift-F1) in file
//#define SONG_FASTVOLSLIDES    0x0002
#define SONG_ITOLDEFFECTS       0x0004 // Old Impulse Tracker effect implementations
#define SONG_COMPATGXX          0x0008 // "Compatible Gxx" (handle portamento more like other trackers)
#define SONG_LINEARSLIDES       0x0010 // Linear slides vs. Amiga slides
#define SONG_PATTERNPLAYBACK    0x0020 // Only playing current pattern
//#define SONG_STEP             0x0040
#define SONG_PAUSED             0x0080 // Playback paused (Shift-F8)
//#define SONG_FADINGSONG       0x0100
#define SONG_ENDREACHED         0x0200 // Song is finished (standalone keyjazz mode)
//#define SONG_GLOBALFADE       0x0400
//#define SONG_CPUVERYHIGH      0x0800
#define SONG_FIRSTTICK          0x1000 // Current tick is the first tick of the row (dopey flow-control flag)
//#define SONG_MPTFILTERMODE    0x2000
//#define SONG_SURROUNDPAN      0x4000
//#define SONG_EXFILTERRANGE    0x8000
//#define SONG_AMIGALIMITS      0x10000
#define SONG_INSTRUMENTMODE     0x20000 // Process instruments
#define SONG_ORDERLOCKED        0x40000 // Don't advance orderlist *(Alt-F11)
#define SONG_NOSTEREO           0x80000 // secret code for "mono"
#define SONG_PATTERNLOOP        (SONG_PATTERNPLAYBACK | SONG_ORDERLOCKED) // Loop current pattern (F6)

// Global Options (Renderer)
#define SNDMIX_REVERSESTEREO    0x0001 // swap L/R audio channels
//#define SNDMIX_NOISEREDUCTION 0x0002 // reduce hiss (do not use, it's just a simple low-pass filter)
//#define SNDMIX_AGC            0x0004 // automatic gain control
#define SNDMIX_NORESAMPLING     0x0008 // force no resampling (uninterpolated)
#define SNDMIX_HQRESAMPLER      0x0010 // cubic resampling
//#define SNDMIX_MEGABASS       0x0020
//#define SNDMIX_SURROUND       0x0040
//#define SNDMIX_REVERB         0x0080
//#define SNDMIX_EQ             0x0100 // apply EQ (always on)
//#define SNDMIX_SOFTPANNING    0x0200
#define SNDMIX_ULTRAHQSRCMODE   0x0400 // polyphase resampling (or FIR? I don't know)
// Misc Flags (can safely be turned on or off)
#define SNDMIX_DIRECTTODISK     0x10000 // disk writer mode
#define SNDMIX_NOBACKWARDJUMPS  0x40000 // disallow Bxx jumps from going backward in the orderlist
//#define SNDMIX_MAXDEFAULTPAN  0x80000 // (no longer) Used by the MOD loader
#define SNDMIX_MUTECHNMODE      0x100000 // Notes are not played on muted channels
#define SNDMIX_NOSURROUND       0x200000 // ignore S91
//#define SNDMIX_NOMIXING       0x400000
#define SNDMIX_NORAMPING        0x800000 // don't apply ramping on volume change (causes clicks)

enum {
	SRCMODE_NEAREST,
	SRCMODE_LINEAR,
	SRCMODE_SPLINE,
	SRCMODE_POLYPHASE,
	NUM_SRC_MODES
};

// ------------------------------------------------------------------------------------------------------------
// Flags for csf_read_sample

// Sample data characteristics
// Note:
// - None of these constants are zero
// - The format specifier must have a value set for each "section"
// - csf_read_sample DOES check the values for validity

// Bit width (8 bits for simplicity)
#define _SDV_BIT(n)            ((n) << 0)
#define SF_BIT_MASK            0xff
#define SF_7                   _SDV_BIT(7)  // 7-bit (weird!)
#define SF_8                   _SDV_BIT(8)  // 8-bit
#define SF_16                  _SDV_BIT(16) // 16-bit
#define SF_24                  _SDV_BIT(24) // 24-bit
#define SF_32                  _SDV_BIT(32) // 32-bit

// Channels (4 bits)
#define _SDV_CHN(n)            ((n) << 8)
#define SF_CHN_MASK            0xf00
#define SF_M                   _SDV_CHN(1) // mono
#define SF_SI                  _SDV_CHN(2) // stereo, interleaved
#define SF_SS                  _SDV_CHN(3) // stereo, split

// Endianness (4 bits)
#define _SDV_END(n)            ((n) << 12)
#define SF_END_MASK            0xf000
#define SF_LE                  _SDV_END(1) // little-endian
#define SF_BE                  _SDV_END(2) // big-endian

// Encoding (8 bits)
#define _SDV_ENC(n)            ((n) << 16)
#define SF_ENC_MASK            0xff0000
#define SF_PCMS                _SDV_ENC(1) // PCM, signed
#define SF_PCMU                _SDV_ENC(2) // PCM, unsigned
#define SF_PCMD                _SDV_ENC(3) // PCM, delta-encoded
#define SF_IT214               _SDV_ENC(4) // Impulse Tracker 2.14 compressed
#define SF_IT215               _SDV_ENC(5) // Impulse Tracker 2.15 compressed
#define SF_AMS                 _SDV_ENC(6) // AMS / Velvet Studio packed
#define SF_DMF                 _SDV_ENC(7) // DMF Huffman compression
#define SF_MDL                 _SDV_ENC(8) // MDL Huffman compression
#define SF_PTM                 _SDV_ENC(9) // PTM 8-bit delta value -> 16-bit sample

// Sample format shortcut
#define SF(a,b,c,d) (SF_ ## a | SF_ ## b| SF_ ## c | SF_ ## d)

// Deprecated constants
#define RS_AMS16        SF(AMS,16,M,LE)
#define RS_AMS8         SF(AMS,8,M,LE)
#define RS_DMF16        SF(DMF,16,M,LE)
#define RS_DMF8         SF(DMF,8,M,LE)
#define RS_IT21416      SF(IT214,16,M,LE)
#define RS_IT2148       SF(IT214,8,M,LE)
#define RS_IT21516      SF(IT215,16,M,LE)
#define RS_IT2158       SF(IT215,8,M,LE)
#define RS_IT21416S     SF(IT214,16,SS,LE)
#define RS_IT2148S      SF(IT214,8,SS,LE)
#define RS_IT21516S     SF(IT215,16,SS,LE)
#define RS_IT2158S      SF(IT215,8,SS,LE)
#define RS_MDL16        SF(MDL,16,M,LE)
#define RS_MDL8         SF(MDL,8,M,LE)
#define RS_PCM16D       SF(PCMD,16,M,LE)
#define RS_PCM16M       SF(PCMS,16,M,BE)
#define RS_PCM16S       SF(PCMS,16,M,LE)
#define RS_PCM16U       SF(PCMU,16,M,LE)
#define RS_PCM24S       SF(PCMS,24,M,LE)
#define RS_PCM32S       SF(PCMS,32,M,LE)
#define RS_PCM8D        SF(PCMD,8,M,LE)
#define RS_PCM8S        SF(PCMS,8,M,LE)
#define RS_PCM8U        SF(PCMU,8,M,LE)
#define RS_PTM8DTO16    SF(PTM,16,M,LE)
#define RS_STIPCM16M    SF(PCMS,16,SI,BE)
#define RS_STIPCM16S    SF(PCMS,16,SI,LE)
#define RS_STIPCM16U    SF(PCMU,16,SI,LE)
#define RS_STIPCM24S    SF(PCMS,24,SI,LE)
#define RS_STIPCM32S    SF(PCMS,32,SI,LE)
#define RS_STIPCM8S     SF(PCMS,8,SI,LE)
#define RS_STIPCM8U     SF(PCMU,8,SI,LE)
#define RS_STPCM16D     SF(PCMD,16,SS,LE)
#define RS_STPCM16M     SF(PCMS,16,SS,BE)
#define RS_STPCM16S     SF(PCMS,16,SS,LE)
#define RS_STPCM16U     SF(PCMU,16,SS,LE)
#define RS_STPCM8D      SF(PCMD,8,SS,LE)
#define RS_STPCM8S      SF(PCMS,8,SS,LE)
#define RS_STPCM8U      SF(PCMU,8,SS,LE)

// ------------------------------------------------------------------------------------------------------------

typedef struct song_sample {
	uint32_t length;
	uint32_t loop_start;
	uint32_t loop_end;
	uint32_t sustain_start;
	uint32_t sustain_end;
	signed char *data;
	uint32_t c5speed;
	uint32_t panning;
	uint32_t volume;
	uint32_t global_volume;
	uint32_t flags;
	uint32_t vib_type;
	uint32_t vib_rate;
	uint32_t vib_depth;
	uint32_t vib_speed;
	char name[32];
	char filename[22];
	int played; // for note playback dots
	uint32_t globalvol_saved; // for muting individual samples

	// This must be 12-bytes to work around a bug in some gcc4.2s (XXX why? what bug?)
	unsigned char adlib_bytes[12];
} song_sample_t;

typedef struct song_envelope {
	int ticks[32];
	uint8_t values[32];
	int nodes;
	int loop_start;
	int loop_end;
	int sustain_start;
	int sustain_end;
} song_envelope_t;

typedef struct song_instrument {
	uint32_t fadeout;
	uint32_t flags;
	unsigned int global_volume;
	unsigned int panning;
	uint8_t sample_map[128];
	uint8_t note_map[128];
	song_envelope_t vol_env;
	song_envelope_t pan_env;
	song_envelope_t pitch_env;
	unsigned int nna;
	unsigned int dct;
	unsigned int dca;
	unsigned int pan_swing;
	unsigned int vol_swing;
	unsigned int ifc;
	unsigned int ifr;
	int midi_bank; // TODO split this?
	int midi_program;
	unsigned int midi_channel_mask; // FIXME why is this a mask? why is a mask useful? does 2.15 use a mask?
	int pitch_pan_separation;
	unsigned int pitch_pan_center;
	char name[32];
	char filename[16];
	int played; // for note playback dots
} song_instrument_t;

// (TODO write decent descriptions of what the various volume
// variables are used for - are all of them *really* necessary?)
// (TODO also the majority of this is irrelevant outside of the "main" 64 channels;
// this struct should really only be holding the stuff actually needed for mixing)
typedef struct song_voice {
	// First 32-bytes: Most used mixing information: don't change it
	signed char * current_sample_data;
	uint32_t position; // sample position, fixed-point -- integer part
	uint32_t position_frac; // fractional part
	int32_t increment; // 16.16 fixed point, how much to add to position per sample-frame of output
	int32_t right_volume; // ?
	int32_t left_volume; // ?
	int32_t right_ramp; // ?
	int32_t left_ramp; // ?
	// 2nd cache line
	uint32_t length; // only to the end of the loop
	uint32_t flags;
	uint32_t loop_start; // loop or sustain, whichever is active
	uint32_t loop_end;
	int32_t right_ramp_volume; // ?
	int32_t left_ramp_volume; // ?
	int32_t strike; // decremented to zero. this affects how long the initial hit on the playback marks lasts (bigger dot in instrument and sample list windows)

	int32_t filter_y1, filter_y2, filter_y3, filter_y4;
	int32_t filter_a0, filter_b0, filter_b1;

	int32_t rofs, lofs; // ?
	int32_t ramp_length;
	// Information not used in the mixer
	int32_t right_volume_new, left_volume_new; // ?
	int32_t final_volume; // range 0-16384 (?), accounting for sample+channel+global+etc. volumes
	int32_t final_panning; // range 0-256 (but can temporarily exceed that range during calculations)
	int32_t volume, panning; // range 0-256 (?); these are the current values set for the channel
	int32_t fadeout_volume;
	int32_t period;
	int32_t c5speed;
	int32_t sample_freq; // only used on the info page (F5)
	int32_t portamento_target;
	song_instrument_t *ptr_instrument;      // these two suck, and should
	song_sample_t *ptr_sample;              // be replaced with numbers
	int vol_env_position;
	int pan_env_position;
	int pitch_env_position;
	uint32_t master_channel; // nonzero = background/NNA voice, indicates what channel it "came from"
	uint32_t vu_meter;
	int32_t global_volume;
	int32_t instrument_volume;
	int32_t autovib_depth;
	uint32_t autovib_position, vibrato_position, tremolo_position, panbrello_position;
	// 16-bit members
	int vol_swing, pan_swing;

	// formally 8-bit members
	unsigned int note; // the note that's playing
	unsigned int nna;
	unsigned int new_note, new_instrument; // ?
	// Effect memory and handling
	unsigned int n_command; // This sucks and needs to go away (dumb "flag" for arpeggio / tremor)
	unsigned int mem_vc_volslide; // Ax Bx Cx Dx (volume column)
	unsigned int mem_arpeggio; // Axx
	unsigned int mem_volslide; // Dxx
	unsigned int mem_pitchslide; // Exx Fxx (and Gxx maybe)
	int32_t mem_portanote; // Gxx (synced with mem_pitchslide if compat gxx is set)
	unsigned int mem_tremor; // Ixx
	unsigned int mem_channel_volslide; // Nxx
	unsigned int mem_offset; // final, combined yxx00h from Oxx and SAy
	unsigned int mem_panslide; // Pxx
	unsigned int mem_retrig; // Qxx
	unsigned int mem_special; // Sxx
	unsigned int mem_tempo; // Txx
	unsigned int mem_global_volslide; // Wxx
	unsigned int note_slide_counter, note_slide_speed, note_slide_step; // IMF effect
	unsigned int vib_type, vibrato_speed, vibrato_depth;
	unsigned int tremolo_type, tremolo_speed, tremolo_depth;
	unsigned int panbrello_type, panbrello_speed, panbrello_depth;
	int tremolo_delta, panbrello_delta;

	unsigned int cutoff;
	unsigned int resonance;
	int cd_note_delay; // countdown: note starts when this hits zero
	int cd_note_cut; // countdown: note stops when this hits zero
	int cd_retrig; // countdown: note retrigs when this hits zero
	unsigned int cd_tremor; // (weird) countdown + flag: see snd_fx.c and sndmix.c
	unsigned int patloop_row; // row number that SB0 was on
	unsigned int cd_patloop; // countdown: pattern loops back when this hits zero

	unsigned int row_note, row_instr;
	unsigned int row_voleffect, row_volparam;
	unsigned int row_effect, row_param;
	unsigned int active_macro, last_instrument;
} song_voice_t;

typedef struct song_channel {
	uint32_t panning;
	uint32_t volume;
	uint32_t flags;
} song_channel_t;

typedef struct song_note {
	uint8_t note;
	uint8_t instrument;
	uint8_t voleffect;
	uint8_t volparam;
	uint8_t effect;
	uint8_t param;
} song_note_t;

////////////////////////////////////////////////////////////////////

typedef struct {
	char start[32];
	char stop[32];
	char tick[32];
	char note_on[32];
	char note_off[32];
	char set_volume[32];
	char set_panning[32];
	char set_bank[32];
	char set_program[32];
	char sfx[16][32];
	char zxx[128][32];
} midi_config_t;

extern midi_config_t default_midi_config;


extern uint32_t max_voices;
extern uint32_t global_vu_left, global_vu_right;

extern const song_note_t blank_pattern[64 * 64];
extern const song_note_t *blank_note;


struct multi_write {
	int used;
	void *data;
	/* Conveniently, this has the same prototype as disko_write :) */
	void (*write)(void *data, const uint8_t *buf, size_t bytes);
	/* this is optimization for channels that haven't had any data yet
	(nothing to convert/write, just seek ahead in the data stream) */
	void (*silence)(void *data, long bytes);
	int buffer[MIXBUFFERSIZE * 2];
};

typedef struct song {
	int mix_buffer[MIXBUFFERSIZE * 2];
	float mix_buffer_float[MIXBUFFERSIZE * 2]; // is this needed?

	song_voice_t voices[MAX_VOICES];                // Channels
	uint32_t voice_mix[MAX_VOICES];                 // Channels to be mixed
	song_sample_t samples[MAX_SAMPLES+1];           // Samples (1-based!)
	song_instrument_t *instruments[MAX_INSTRUMENTS+1]; // Instruments (1-based!)
	song_channel_t channels[MAX_CHANNELS];          // Channel settings
	song_note_t *patterns[MAX_PATTERNS];            // Patterns
	uint16_t pattern_size[MAX_PATTERNS];            // Pattern Lengths
	uint16_t pattern_alloc_size[MAX_PATTERNS];      // Allocated lengths (for async. resizing/playback)
	uint8_t orderlist[MAX_ORDERS + 1];              // Pattern Orders
	midi_config_t midi_config;                      // Midi macro config table
	uint32_t initial_speed;
	uint32_t initial_tempo;
	uint32_t initial_global_volume;
	uint32_t flags;                                 // Song flags SONG_XXXX
	uint32_t pan_separation;
	uint32_t num_voices; // how many are currently playing. (POTENTIALLY larger than global max_voices)
	uint32_t mix_stat; // number of channels being mixed (not really used)
	uint32_t buffer_count; // number of samples to mix per tick
	uint32_t tick_count;
	int32_t row_count; /* IMPORTANT needs to be signed */
	uint32_t current_speed;
	uint32_t current_tempo;
	uint32_t process_row;
	uint32_t row; // no analogue in pm.h? should be either renamed or factored out.
	uint32_t break_row;
	uint32_t current_pattern;
	uint32_t current_order;
	uint32_t process_order;
	uint32_t current_global_volume;
	uint32_t mixing_volume;
	uint32_t freq_factor; // not used -- for tweaking the song speed LP-style (interesting!)
	uint32_t tempo_factor; // ditto
	int32_t repeat_count; // 0 = first playback, etc. (note: set to -1 to stop instead of looping)
	uint8_t row_highlight_major;
	uint8_t row_highlight_minor;
	char message[MAX_MESSAGE + 1];
	char title[32];
	char tracker_id[32]; // irrelevant to the song, just used by some loaders (fingerprint)

	// These store the existing IT save history from prior editing sessions.
	// Current session data is added at save time, and is NOT a part of histdata.
	int histlen; // How many session history data entries exist (each entry is eight bytes)
	uint8_t *histdata; // Preserved entries from prior sessions, might be NULL if histlen = 0
	struct timeval editstart; // When the song was loaded

	// mixer stuff
	uint32_t mix_flags; // SNDMIX_*
	uint32_t mix_frequency, mix_bits_per_sample, mix_channels;

	// noise reduction filter
	int32_t left_nr, right_nr;

	// chaseback
	int stop_at_order;
	int stop_at_row;
	unsigned int stop_at_time;

	// multi-write stuff -- NULL if no multi-write is in progress, else array of one struct per channel
	struct multi_write *multi_write;
} song_t;

song_note_t *csf_allocate_pattern(uint32_t rows);
void csf_free_pattern(void *pat);
signed char *csf_allocate_sample(uint32_t nbytes);
void csf_free_sample(void *p);
song_instrument_t *csf_allocate_instrument(void);
void csf_init_instrument(song_instrument_t *ins, int samp);
void csf_free_instrument(song_instrument_t *p);

uint32_t csf_read_sample(song_sample_t *sample, uint32_t flags, const void *filedata, uint32_t datalength);
void csf_adjust_sample_loop(song_sample_t *sample);

extern void (*csf_midi_out_note)(int chan, const song_note_t *m);
extern void (*csf_midi_out_raw)(const unsigned char *, unsigned int, unsigned int);

void csf_import_s3m_effect(song_note_t *m, int it);


// counting stuff

int csf_note_is_empty(song_note_t *note);
int csf_pattern_is_empty(song_t *csf, int n);
int csf_sample_is_empty(song_sample_t *smp);
int csf_instrument_is_empty(song_instrument_t *ins);
int csf_last_order(song_t *csf); // last order of "main" song (IT-style, only for display)
int csf_get_num_orders(song_t *csf); // last non-blank order (for saving)
int csf_get_num_patterns(song_t *csf);
int csf_get_num_samples(song_t *csf);
int csf_get_num_instruments(song_t *csf);

// for these, 'start' indicates minimum sample/instrument to check
int csf_first_blank_sample(song_t *csf, int start);
int csf_first_blank_instrument(song_t *csf, int start);



int csf_set_wave_config(song_t *csf, uint32_t rate, uint32_t bits, uint32_t channels);

// Mixer Config
int csf_init_player(song_t *csf, int reset); // bReset=false
int csf_set_resampling_mode(song_t *csf, uint32_t mode); // SRCMODE_XXXX


// sndmix
unsigned int csf_read(song_t *csf, void *v_buffer, unsigned int bufsize);
int csf_process_tick(song_t *csf);
int csf_read_note(song_t *csf);

// snd_fx
unsigned int csf_get_length(song_t *csf); // (in seconds)
void csf_instrument_change(song_t *csf, song_voice_t *chn, uint32_t instr, int porta, int instr_column);
void csf_note_change(song_t *csf, uint32_t chan, int note, int porta, int retrig, int have_inst);
uint32_t csf_get_nna_channel(song_t *csf, uint32_t chan);
void csf_check_nna(song_t *csf, uint32_t chan, uint32_t instr, int note, int force_cut);
void csf_process_effects(song_t *csf, int firsttick);

void fx_note_cut(song_t *csf, uint32_t chan, int clear_note);
void fx_key_off(song_t *csf, uint32_t chan);
void csf_midi_send(song_t *csf, const unsigned char *data, unsigned int len, uint32_t chan, int fake);
void csf_process_midi_macro(song_t *csf, uint32_t chan, const char *midi_macro, uint32_t param,
			uint32_t note, uint32_t velocity, uint32_t use_instr);
song_sample_t *csf_translate_keyboard(song_t *csf, song_instrument_t *ins, uint32_t note, song_sample_t *def);

// various utility functions in snd_fx.c
int get_note_from_period(int period);
int get_period_from_note(int note, unsigned int c5speed, int linear);
unsigned int get_freq_from_period(int period, int linear);
unsigned int transpose_to_frequency(int transp, int ftune);
int frequency_to_transpose(unsigned int freq);
unsigned long calc_halftone(unsigned long hz, int rel);


// sndfile
song_t *csf_allocate(void);
void csf_free(song_t *csf);

void csf_destroy(song_t *csf); /* erase everything -- equiv. to new song */

void csf_reset_midi_cfg(song_t *csf);
void csf_copy_midi_cfg(song_t *dest, song_t *src);
void csf_set_current_order(song_t *csf, uint32_t position);
void csf_reset_playmarks(song_t *csf);

void csf_forget_history(song_t *csf); // Send the edit log down the memory hole.

/* apply a preset Adlib patch */
void adlib_patch_apply(song_sample_t *smp, int patchnum);

///////////////////////////////////////////////////////////

// Return (a*b)/c - no divide error
static inline int _muldiv(int a, int b, int c)
{
	return ((unsigned long long) a * (unsigned long long) b ) / c;
}


// Return (a*b+c/2)/c - no divide error
static inline int _muldivr(int a, int b, int c)
{
	return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
}


#endif
© All Rights Reserved