aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/mt32/Structures.h
blob: d116aaeb46a5273dc9a0db85572645e3a5b45643 (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
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
 * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 2.1 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef MT32EMU_STRUCTURES_H
#define MT32EMU_STRUCTURES_H

#include "globals.h"
#include "Types.h"

namespace MT32Emu {

// MT32EMU_MEMADDR() converts from sysex-padded, MT32EMU_SYSEXMEMADDR converts to it
// Roland provides documentation using the sysex-padded addresses, so we tend to use that in code and output
#define MT32EMU_MEMADDR(x) ((((x) & 0x7f0000) >> 2) | (((x) & 0x7f00) >> 1) | ((x) & 0x7f))
#define MT32EMU_SYSEXMEMADDR(x) ((((x) & 0x1FC000) << 2) | (((x) & 0x3F80) << 1) | ((x) & 0x7f))

#ifdef _MSC_VER
#define  MT32EMU_ALIGN_PACKED __declspec(align(1))
#else
#define MT32EMU_ALIGN_PACKED __attribute__((packed))
#endif

// The following structures represent the MT-32's memory
// Since sysex allows this memory to be written to in blocks of bytes,
// we keep this packed so that we can copy data into the various
// banks directly
#if defined(_MSC_VER) || defined(__MINGW32__)
#pragma pack(push, 1)
#else
#pragma pack(1)
#endif

struct TimbreParam {
	struct CommonParam {
		char name[10];
		Bit8u partialStructure12;  // 1 & 2  0-12 (1-13)
		Bit8u partialStructure34;  // 3 & 4  0-12 (1-13)
		Bit8u partialMute;  // 0-15 (0000-1111)
		Bit8u noSustain; // ENV MODE 0-1 (Normal, No sustain)
	} MT32EMU_ALIGN_PACKED common;

	struct PartialParam {
		struct WGParam {
			Bit8u pitchCoarse;  // 0-96 (C1,C#1-C9)
			Bit8u pitchFine;  // 0-100 (-50 to +50 (cents - confirmed by Mok))
			Bit8u pitchKeyfollow;  // 0-16 (-1, -1/2, -1/4, 0, 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 1, 5/4, 3/2, 2, s1, s2)
			Bit8u pitchBenderEnabled;  // 0-1 (OFF, ON)
			Bit8u waveform; // MT-32: 0-1 (SQU/SAW); LAPC-I: WG WAVEFORM/PCM BANK 0 - 3 (SQU/1, SAW/1, SQU/2, SAW/2)
			Bit8u pcmWave; // 0-127 (1-128)
			Bit8u pulseWidth; // 0-100
			Bit8u pulseWidthVeloSensitivity; // 0-14 (-7 - +7)
		} MT32EMU_ALIGN_PACKED wg;

		struct PitchEnvParam {
			Bit8u depth; // 0-10
			Bit8u veloSensitivity; // 0-100
			Bit8u timeKeyfollow; // 0-4
			Bit8u time[4]; // 0-100
			Bit8u level[5]; // 0-100 (-50 - +50) // [3]: SUSTAIN LEVEL, [4]: END LEVEL
		} MT32EMU_ALIGN_PACKED pitchEnv;

		struct PitchLFOParam {
			Bit8u rate; // 0-100
			Bit8u depth; // 0-100
			Bit8u modSensitivity; // 0-100
		} MT32EMU_ALIGN_PACKED pitchLFO;

		struct TVFParam {
			Bit8u cutoff; // 0-100
			Bit8u resonance; // 0-30
			Bit8u keyfollow; // -1, -1/2, -1/4, 0, 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 1, 5/4, 3/2, 2
			Bit8u biasPoint; // 0-127 (<1A-<7C >1A-7C)
			Bit8u biasLevel; // 0-14 (-7 - +7)
			Bit8u envDepth; // 0-100
			Bit8u envVeloSensitivity; // 0-100
			Bit8u envDepthKeyfollow; // DEPTH KEY FOLL0W 0-4
			Bit8u envTimeKeyfollow; // TIME KEY FOLLOW 0-4
			Bit8u envTime[5]; // 0-100
			Bit8u envLevel[4]; // 0-100 // [3]: SUSTAIN LEVEL
		} MT32EMU_ALIGN_PACKED tvf;

		struct TVAParam {
			Bit8u level; // 0-100
			Bit8u veloSensitivity; // 0-100
			Bit8u biasPoint1; // 0-127 (<1A-<7C >1A-7C)
			Bit8u biasLevel1; // 0-12 (-12 - 0)
			Bit8u biasPoint2; // 0-127 (<1A-<7C >1A-7C)
			Bit8u biasLevel2; // 0-12 (-12 - 0)
			Bit8u envTimeKeyfollow; // TIME KEY FOLLOW 0-4
			Bit8u envTimeVeloSensitivity; // VELOS KEY FOLL0W 0-4
			Bit8u envTime[5]; // 0-100
			Bit8u envLevel[4]; // 0-100 // [3]: SUSTAIN LEVEL
		} MT32EMU_ALIGN_PACKED tva;
	} MT32EMU_ALIGN_PACKED partial[4]; // struct PartialParam
} MT32EMU_ALIGN_PACKED; // struct TimbreParam

struct PatchParam {
	Bit8u timbreGroup; // TIMBRE GROUP  0-3 (group A, group B, Memory, Rhythm)
	Bit8u timbreNum; // TIMBRE NUMBER 0-63
	Bit8u keyShift; // KEY SHIFT 0-48 (-24 - +24 semitones)
	Bit8u fineTune; // FINE TUNE 0-100 (-50 - +50 cents)
	Bit8u benderRange; // BENDER RANGE 0-24
	Bit8u assignMode;  // ASSIGN MODE 0-3 (POLY1, POLY2, POLY3, POLY4)
	Bit8u reverbSwitch;  // REVERB SWITCH 0-1 (OFF,ON)
	Bit8u dummy; // (DUMMY)
} MT32EMU_ALIGN_PACKED;

const unsigned int SYSTEM_MASTER_TUNE_OFF = 0;
const unsigned int SYSTEM_REVERB_MODE_OFF = 1;
const unsigned int SYSTEM_REVERB_TIME_OFF = 2;
const unsigned int SYSTEM_REVERB_LEVEL_OFF = 3;
const unsigned int SYSTEM_RESERVE_SETTINGS_START_OFF = 4;
const unsigned int SYSTEM_RESERVE_SETTINGS_END_OFF = 12;
const unsigned int SYSTEM_CHAN_ASSIGN_START_OFF = 13;
const unsigned int SYSTEM_CHAN_ASSIGN_END_OFF = 21;
const unsigned int SYSTEM_MASTER_VOL_OFF = 22;

struct MemParams {
	// NOTE: The MT-32 documentation only specifies PatchTemp areas for parts 1-8.
	// The LAPC-I documentation specified an additional area for rhythm at the end,
	// where all parameters but fine tune, assign mode and output level are ignored
	struct PatchTemp {
		PatchParam patch;
		Bit8u outputLevel; // OUTPUT LEVEL 0-100
		Bit8u panpot; // PANPOT 0-14 (R-L)
		Bit8u dummyv[6];
	} MT32EMU_ALIGN_PACKED patchTemp[9];

	struct RhythmTemp {
		Bit8u timbre; // TIMBRE  0-94 (M1-M64,R1-30,OFF); LAPC-I: 0-127 (M01-M64,R01-R63)
		Bit8u outputLevel; // OUTPUT LEVEL 0-100
		Bit8u panpot; // PANPOT 0-14 (R-L)
		Bit8u reverbSwitch;  // REVERB SWITCH 0-1 (OFF,ON)
	} MT32EMU_ALIGN_PACKED rhythmTemp[85];

	TimbreParam timbreTemp[8];

	PatchParam patches[128];

	// NOTE: There are only 30 timbres in the "rhythm" bank for MT-32; the additional 34 are for LAPC-I and above
	struct PaddedTimbre {
		TimbreParam timbre;
		Bit8u padding[10];
	} MT32EMU_ALIGN_PACKED timbres[64 + 64 + 64 + 64]; // Group A, Group B, Memory, Rhythm

	struct System {
		Bit8u masterTune; // MASTER TUNE 0-127 432.1-457.6Hz
		Bit8u reverbMode; // REVERB MODE 0-3 (room, hall, plate, tap delay)
		Bit8u reverbTime; // REVERB TIME 0-7 (1-8)
		Bit8u reverbLevel; // REVERB LEVEL 0-7 (1-8)
		Bit8u reserveSettings[9]; // PARTIAL RESERVE (PART 1) 0-32
		Bit8u chanAssign[9]; // MIDI CHANNEL (PART1) 0-16 (1-16,OFF)
		Bit8u masterVol; // MASTER VOLUME 0-100
	} MT32EMU_ALIGN_PACKED system;
}; // struct MemParams

struct SoundGroup {
	Bit8u timbreNumberTableAddrLow;
	Bit8u timbreNumberTableAddrHigh;
	Bit8u displayPosition;
	Bit8u name[9];
	Bit8u timbreCount;
	Bit8u pad;
} MT32EMU_ALIGN_PACKED;

#if defined(_MSC_VER) || defined(__MINGW32__)
#pragma pack(pop)
#else
#pragma pack()
#endif

struct ControlROMFeatureSet {
	unsigned int quirkBasePitchOverflow : 1;
	unsigned int quirkPitchEnvelopeOverflow : 1;
	unsigned int quirkRingModulationNoMix : 1;
	unsigned int quirkTVAZeroEnvLevels : 1;
	unsigned int quirkPanMult : 1;
	unsigned int quirkKeyShift : 1;
	unsigned int quirkTVFBaseCutoffLimit : 1;

	// Features below don't actually depend on control ROM version, which is used to identify hardware model
	unsigned int defaultReverbMT32Compatible : 1;
	unsigned int oldMT32AnalogLPF : 1;
};

struct ControlROMMap {
	const char *shortName;
	const ControlROMFeatureSet &featureSet;
	Bit16u pcmTable; // 4 * pcmCount bytes
	Bit16u pcmCount;
	Bit16u timbreAMap; // 128 bytes
	Bit16u timbreAOffset;
	bool timbreACompressed;
	Bit16u timbreBMap; // 128 bytes
	Bit16u timbreBOffset;
	bool timbreBCompressed;
	Bit16u timbreRMap; // 2 * timbreRCount bytes
	Bit16u timbreRCount;
	Bit16u rhythmSettings; // 4 * rhythmSettingsCount bytes
	Bit16u rhythmSettingsCount;
	Bit16u reserveSettings; // 9 bytes
	Bit16u panSettings; // 8 bytes
	Bit16u programSettings; // 8 bytes
	Bit16u rhythmMaxTable; // 4 bytes
	Bit16u patchMaxTable; // 16 bytes
	Bit16u systemMaxTable; // 23 bytes
	Bit16u timbreMaxTable; // 72 bytes
	Bit16u soundGroupsTable; // 14 bytes each entry
	Bit16u soundGroupsCount;
};

struct ControlROMPCMStruct {
	Bit8u pos;
	Bit8u len;
	Bit8u pitchLSB;
	Bit8u pitchMSB;
};

struct PCMWaveEntry {
	Bit32u addr;
	Bit32u len;
	bool loop;
	ControlROMPCMStruct *controlROMPCMStruct;
};

// This is basically a per-partial, pre-processed combination of timbre and patch/rhythm settings
struct PatchCache {
	bool playPartial;
	bool PCMPartial;
	int pcm;
	Bit8u waveform;

	Bit32u structureMix;
	int structurePosition;
	int structurePair;

	// The following fields are actually common to all partials in the timbre
	bool dirty;
	Bit32u partialCount;
	bool sustain;
	bool reverb;

	TimbreParam::PartialParam srcPartial;

	// The following directly points into live sysex-addressable memory
	const TimbreParam::PartialParam *partialParam;
};

} // namespace MT32Emu

#endif // #ifndef MT32EMU_STRUCTURES_H