1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef AUDIO_MIDIDRV_H
24 #define AUDIO_MIDIDRV_H
25 
26 #include "common/scummsys.h"
27 #include "common/str.h"
28 #include "common/stream.h"
29 #include "common/timer.h"
30 #include "common/array.h"
31 
32 class MidiChannel;
33 
34 /**
35  * @defgroup audio_mididrv MIDI drivers
36  * @ingroup audio
37  *
38  * @brief API for managing MIDI drivers.
39  * @{
40  */
41 
42 /**
43  * Music types that music drivers can implement and engines can rely on.
44  */
45 enum MusicType {
46 	MT_INVALID = -1,	// Invalid output
47 	MT_AUTO = 0,		// Auto
48 	MT_NULL,			// Null
49 	MT_PCSPK,			// PC Speaker
50 	MT_PCJR,			// PCjr
51 	MT_CMS,				// CMS
52 	MT_ADLIB,			// AdLib
53 	MT_C64,				// C64
54 	MT_AMIGA,			// Amiga
55 	MT_APPLEIIGS,		// Apple IIGS
56 	MT_TOWNS,			// FM-TOWNS
57 	MT_PC98,			// PC98
58 	MT_SEGACD,			// SegaCD
59 	MT_GM,				// General MIDI
60 	MT_MT32,			// MT-32
61 	MT_GS				// Roland GS
62 };
63 
64 /**
65  * A set of flags to be passed to detectDevice() which can be used to
66  * specify what kind of music driver is preferred / accepted.
67  *
68  * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a
69  * given driver type is acceptable. E.g. the TOWNS music driver could be
70  * returned by detectDevice if and only if MDT_TOWNS is specified.
71  *
72  * MDT_PREFER_MT32 and MDT_PREFER_GM indicate the MIDI device type to use when
73  * no device is selected in the music options, or when the MIDI device selected
74  * does not match the requirements of a game engine. With these flags, more
75  * priority is given to an MT-32 device, or a GM device respectively.
76  *
77  * @todo Rename MidiDriverFlags to MusicDriverFlags
78  */
79 enum MidiDriverFlags {
80 	MDT_NONE        = 0,
81 	MDT_PCSPK       = 1 << 0,		// PC Speaker: Maps to MT_PCSPK and MT_PCJR
82 	MDT_CMS         = 1 << 1,		// Creative Music System / Gameblaster: Maps to MT_CMS
83 	MDT_PCJR        = 1 << 2,		// Tandy/PC Junior driver
84 	MDT_ADLIB       = 1 << 3,		// AdLib: Maps to MT_ADLIB
85 	MDT_C64         = 1 << 4,
86 	MDT_AMIGA       = 1 << 5,
87 	MDT_APPLEIIGS   = 1 << 6,
88 	MDT_TOWNS       = 1 << 7,		// FM-TOWNS: Maps to MT_TOWNS
89 	MDT_PC98        = 1 << 8,		// PC-98: Maps to MT_PC98
90 	MDT_SEGACD		= 1 << 9,
91 	MDT_MIDI        = 1 << 10,		// Real MIDI
92 	MDT_PREFER_MT32 = 1 << 11,		// MT-32 output is preferred
93 	MDT_PREFER_GM   = 1 << 12,		// GM output is preferred
94 	MDT_PREFER_FLUID= 1 << 13		// FluidSynth driver is preferred
95 };
96 
97 /**
98  * TODO: Document this, give it a better name.
99  */
100 class MidiDriver_BASE {
101 public:
102 	static const uint8 MIDI_CHANNEL_COUNT = 16;
103 	static const uint8 MIDI_RHYTHM_CHANNEL = 9;
104 
105 	static const byte MIDI_COMMAND_NOTE_OFF = 0x80;
106 	static const byte MIDI_COMMAND_NOTE_ON = 0x90;
107 	static const byte MIDI_COMMAND_POLYPHONIC_AFTERTOUCH = 0xA0;
108 	static const byte MIDI_COMMAND_CONTROL_CHANGE = 0xB0;
109 	static const byte MIDI_COMMAND_PROGRAM_CHANGE = 0xC0;
110 	static const byte MIDI_COMMAND_CHANNEL_AFTERTOUCH = 0xD0;
111 	static const byte MIDI_COMMAND_PITCH_BEND = 0xE0;
112 	static const byte MIDI_COMMAND_SYSTEM = 0xF0;
113 
114 	static const byte MIDI_CONTROLLER_BANK_SELECT_MSB = 0x00;
115 	static const byte MIDI_CONTROLLER_MODULATION = 0x01;
116 	static const byte MIDI_CONTROLLER_DATA_ENTRY_MSB = 0x06;
117 	static const byte MIDI_CONTROLLER_VOLUME = 0x07;
118 	static const byte MIDI_CONTROLLER_PANNING = 0x0A;
119 	static const byte MIDI_CONTROLLER_EXPRESSION = 0x0B;
120 	static const byte MIDI_CONTROLLER_BANK_SELECT_LSB = 0x20;
121 	static const byte MIDI_CONTROLLER_DATA_ENTRY_LSB = 0x26;
122 	static const byte MIDI_CONTROLLER_SUSTAIN = 0x40;
123 	static const byte MIDI_CONTROLLER_REVERB = 0x5B;
124 	static const byte MIDI_CONTROLLER_CHORUS = 0x5D;
125 	static const byte MIDI_CONTROLLER_RPN_LSB = 0x64;
126 	static const byte MIDI_CONTROLLER_RPN_MSB = 0x65;
127 	static const byte MIDI_CONTROLLER_ALL_SOUND_OFF = 0x78;
128 	static const byte MIDI_CONTROLLER_RESET_ALL_CONTROLLERS = 0x79;
129 	static const byte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B;
130 	static const byte MIDI_CONTROLLER_OMNI_ON = 0x7C;
131 	static const byte MIDI_CONTROLLER_OMNI_OFF = 0x7D;
132 	static const byte MIDI_CONTROLLER_MONO_ON = 0x7E;
133 	static const byte MIDI_CONTROLLER_POLY_ON = 0x7F;
134 
135 	static const uint16 MIDI_RPN_PITCH_BEND_SENSITIVITY = 0x0000;
136 	static const uint16 MIDI_RPN_MASTER_TUNING_FINE = 0x0001;
137 	static const uint16 MIDI_RPN_MASTER_TUNING_COARSE = 0x0002;
138 	static const uint16 MIDI_RPN_NULL = 0x7F7F;
139 
140 	static const uint8 MIDI_META_END_OF_TRACK = 0x2F;
141 	static const uint8 MIDI_META_SEQUENCER = 0x7F;
142 
143 	static const uint16 MIDI_PITCH_BEND_DEFAULT = 0x2000;
144 	static const uint8 MIDI_PANNING_DEFAULT = 0x40;
145 	static const uint8 MIDI_EXPRESSION_DEFAULT = 0x7F;
146 	static const uint16 MIDI_MASTER_TUNING_FINE_DEFAULT = 0x2000;
147 	static const uint8 MIDI_MASTER_TUNING_COARSE_DEFAULT = 0x40;
148 
149 	static const uint8 GM_PITCH_BEND_SENSITIVITY_DEFAULT = 0x02;
150 
151 	static const uint8 GS_RHYTHM_FIRST_NOTE = 0x1B;
152 	static const uint8 GS_RHYTHM_LAST_NOTE = 0x58;
153 
154 	MidiDriver_BASE();
155 
156 	virtual ~MidiDriver_BASE();
157 
158 	/**
159 	 * Output a packed midi command to the midi stream.
160 	 * The 'lowest' byte (i.e. b & 0xFF) is the status
161 	 * code, then come (if used) the first and second
162 	 * opcode.
163 	 */
164 	virtual void send(uint32 b) = 0;
165 
166 	/**
167 	 * Send a MIDI command from a specific source. If the MIDI driver
168 	 * does not support multiple sources, the source parameter is
169 	 * ignored.
170 	 */
send(int8 source,uint32 b)171 	virtual void send(int8 source, uint32 b) { send(b); }
172 
173 	/**
174 	 * Output a midi command to the midi stream. Convenience wrapper
175 	 * around the usual 'packed' send method.
176 	 *
177 	 * Do NOT use this for sysEx transmission; instead, use the sysEx()
178 	 * method below.
179 	 */
180 	void send(byte status, byte firstOp, byte secondOp);
181 
182 	/**
183 	 * Send a MIDI command from a specific source. If the MIDI driver
184 	 * does not support multiple sources, the source parameter is
185 	 * ignored.
186 	 */
187 	void send(int8 source, byte status, byte firstOp, byte secondOp);
188 
189 	/**
190 	 * Transmit a SysEx to the MIDI device.
191 	 *
192 	 * The given msg MUST NOT contain the usual SysEx frame, i.e.
193 	 * do NOT include the leading 0xF0 and the trailing 0xF7.
194 	 *
195 	 * Furthermore, the maximal supported length of a SysEx
196 	 * is 264 bytes. Passing longer buffers can lead to
197 	 * undefined behavior (most likely, a crash).
198 	 */
sysEx(const byte * msg,uint16 length)199 	virtual void sysEx(const byte *msg, uint16 length) { }
200 
201 	/**
202 	 * Transmit a SysEx to the MIDI device and return the necessary
203 	 * delay until the next SysEx event in milliseconds.
204 	 *
205 	 * This can be used to implement an alternate delay method than the
206 	 * OSystem::delayMillis function used by most sysEx implementations.
207 	 * Note that not every driver needs a delay, or supports this method.
208 	 * In this case, 0 is returned and the driver itself will do a delay
209 	 * if necessary.
210 	 *
211 	 * For information on the SysEx data requirements, see the sysEx method.
212 	 */
sysExNoDelay(const byte * msg,uint16 length)213 	virtual uint16 sysExNoDelay(const byte *msg, uint16 length) { sysEx(msg, length); return 0; }
214 
215 	// TODO: Document this.
metaEvent(byte type,byte * data,uint16 length)216 	virtual void metaEvent(byte type, byte *data, uint16 length) { }
217 
218 	/**
219 	 * Send a meta event from a specific source. If the MIDI driver
220 	 * does not support multiple sources, the source parameter is
221 	 * ignored.
222 	 */
metaEvent(int8 source,byte type,byte * data,uint16 length)223 	virtual void metaEvent(int8 source, byte type, byte *data, uint16 length) { metaEvent(type, data, length); }
224 
225 	/**
226 	 * Stops all currently active notes. Specify stopSustainedNotes if
227 	 * the MIDI data makes use of the sustain controller to make sure
228 	 * sustained notes are also stopped.
229 	 *
230 	 * Usually, the MIDI parser tracks active notes and terminates them
231 	 * when playback is stopped. This method should be used as a backup
232 	 * to silence the MIDI output in case the MIDI parser makes a
233 	 * mistake when tracking acive notes. It can also be used when
234 	 * quitting or pausing a game.
235 	 *
236 	 * By default, this method sends an All Notes Off message and, if
237 	 * stopSustainedNotes is true, a Sustain off message on all MIDI
238 	 * channels. Driver implementations can override this if they want
239 	 * to implement this functionality in a different way.
240 	 */
241 	virtual void stopAllNotes(bool stopSustainedNotes = false);
242 
243 	/**
244 	 * A driver implementation might need time to prepare playback of
245 	 * a track. Use this function to check if the driver is ready to
246 	 * receive MIDI events.
247 	 */
isReady()248 	virtual bool isReady() { return true; }
249 
250 protected:
251 
252 	/**
253 	 * Enables midi dumping to a 'dump.mid' file and to debug messages on screen
254 	 * It's set by '--dump-midi' command line parameter
255 	 */
256 	bool _midiDumpEnable;
257 
258 	/** Used for MIDI dumping delta calculation */
259 	uint32 _prevMillis;
260 
261 	/** Stores all MIDI events, will be written to disk after an engine quits */
262 	Common::Array<byte> _midiDumpCache;
263 
264 	/** Initialize midi dumping mechanism, called only if enabled */
265 	void midiDumpInit();
266 
267 	/** Handles MIDI file variable length dumping */
268 	int midiDumpVarLength(const uint32 &delta);
269 
270 	/** Handles MIDI file time delta dumping */
271 	void midiDumpDelta();
272 
273 	/** Performs dumping of MIDI commands, called only if enabled */
274 	void midiDumpDo(uint32 b);
275 
276 	/** Performs dumping of MIDI SysEx commands, called only if enabled */
277 	void midiDumpSysEx(const byte *msg, uint16 length);
278 
279 	/** Writes the captured MIDI events to disk, called only if enabled */
280 	void midiDumpFinish();
281 
282 };
283 
284 /**
285  * Abstract MIDI Driver Class
286  *
287  * @todo Rename MidiDriver to MusicDriver
288  */
289 class MidiDriver : public MidiDriver_BASE {
290 public:
291 	/**
292 	 * The device handle.
293 	 *
294 	 * The value 0 is reserved for an invalid device for now.
295 	 * TODO: Maybe we should use -1 (i.e. 0xFFFFFFFF) as
296 	 * invalid device?
297 	 */
298 	typedef uint32 DeviceHandle;
299 
300 	enum DeviceStringType {
301 		kDriverName,
302 		kDriverId,
303 		kDeviceName,
304 		kDeviceId
305 	};
306 
307 	static Common::String musicType2GUIO(uint32 musicType);
308 
309 	/** Create music driver matching the given device handle, or NULL if there is no match. */
310 	static MidiDriver *createMidi(DeviceHandle handle);
311 
312 	/** Returns device handle based on the present devices and the flags parameter. */
313 	static DeviceHandle detectDevice(int flags);
314 
315 	/** Find the music driver matching the given driver name/description. */
316 	static DeviceHandle getDeviceHandle(const Common::String &identifier);
317 
318 	/** Check whether the device with the given handle is available. */
319 	static bool checkDevice(DeviceHandle handle);
320 
321 	/** Get the music type matching the given device handle, or MT_AUTO if there is no match. */
322 	static MusicType getMusicType(DeviceHandle handle);
323 
324 	/** Get the device description string matching the given device handle and the given type. */
325 	static Common::String getDeviceString(DeviceHandle handle, DeviceStringType type);
326 
327 	/** Common operations to be done by all drivers on start of send */
328 	void midiDriverCommonSend(uint32 b);
329 
330 	/** Common operations to be done by all drivers on start of sysEx */
331 	void midiDriverCommonSysEx(const byte *msg, uint16 length);
332 
333 private:
334 	// If detectDevice() detects MT32 and we have a preferred MT32 device
335 	// we use this to force getMusicType() to return MT_MT32 so that we don't
336 	// have to rely on the 'True Roland MT-32' config manager setting (since nobody
337 	// would possibly think about activating 'True Roland MT-32' when he has set
338 	// 'Music Driver' to '<default>')
339 	static bool _forceTypeMT32;
340 
341 public:
~MidiDriver()342 	virtual ~MidiDriver() { }
343 
344 	static const byte _mt32ToGm[128];
345 	static const byte _gmToMt32[128];
346 
347 	/**
348 	 * Error codes returned by open.
349 	 * Can be converted to a string with getErrorName().
350 	 */
351 	enum {
352 		MERR_CANNOT_CONNECT = 1,
353 //		MERR_STREAMING_NOT_AVAILABLE = 2,
354 		MERR_DEVICE_NOT_AVAILABLE = 3,
355 		MERR_ALREADY_OPEN = 4
356 	};
357 
358 	enum {
359 		//		PROP_TIMEDIV = 1,
360 		PROP_OLD_ADLIB = 2,
361 		PROP_CHANNEL_MASK = 3,
362 		// HACK: Not so nice, but our SCUMM AdLib code is in audio/
363 		PROP_SCUMM_OPL3 = 4,
364 		/**
365 		 * Set this to enable or disable scaling of the MIDI channel
366 		 * volume with the user volume settings (including setting it
367 		 * to 0 when Mute All is selected). This is currently
368 		 * implemented in the MT-32/GM drivers (regular and Miles AIL)
369 		 * and the regular AdLib driver.
370 		 *
371 		 * Default is disabled.
372 		 */
373 		PROP_USER_VOLUME_SCALING = 5,
374 		/**
375 		 * Set this property to indicate that the MIDI data used by the
376 		 * game has reversed stereo panning compared to its intended
377 		 * device. The MT-32 has reversed stereo panning compared to
378 		 * the MIDI specification and some game developers chose to
379 		 * stick to the MIDI specification.
380 		 *
381 		 * Do not confuse this with the _midiDeviceReversePanning flag,
382 		 * which indicates that the output MIDI device has reversed
383 		 * stereo panning compared to the intended MIDI device targeted
384 		 * by the MIDI data. This is set by the MT-32/GM driver when
385 		 * MT-32 data is played on a GM device or the other way around.
386 		 * Both flags can be set, which results in no change to the
387 		 * panning.
388 		 *
389 		 * Set this property before opening the driver, to make sure
390 		 * that the default panning is set correctly.
391 		 */
392 		PROP_MIDI_DATA_REVERSE_PANNING = 6,
393 		/**
394 		 * Set this property to specify the behavior of the AdLib driver
395 		 * for note frequency and volume calculation.
396 		 *
397 		 * ACCURACY_MODE_SB16_WIN95: volume and frequency calculation is
398 		 * identical to the Windows 95 SB16 driver. This is the default.
399 		 * ACCURACY_MODE_GM: volume and frequency calculation is closer
400 		 * to the General MIDI and MIDI specifications. Volume is more
401 		 * dynamic and frequencies are closer to actual note frequencies.
402 		 * Calculations are more CPU intensive in this mode.
403 		 */
404 		PROP_OPL_ACCURACY_MODE = 7,
405 		/**
406 		 * Set this property to specify the OPL channel allocation
407 		 * behavior of the AdLib driver.
408 		 *
409 		 * ALLOCATION_MODE_DYNAMIC: behavior is identical to the Windows
410 		 * 95 SB16 driver. Whenever a note is played, an OPL channel is
411 		 * allocated to play this note if:
412 		 * 1. the channel is not playing a note, or
413 		 * 2. the channel is playing a note of the same instrument, or
414 		 * 3. the channel is playing the least recently started note.
415 		 * This mode is the default.
416 		 * ALLOCATION_MODE_STATIC: when a note is played, an OPL channel
417 		 * is exclusively allocated to the MIDI channel and source
418 		 * playing the note. All notes on this MIDI channel are played
419 		 * using this OPL channel. If no OPL channels are unallocated,
420 		 * allocation will fail and the note will not play. This mode
421 		 * requires MIDI channels to be monophonic (i.e. only play one
422 		 * note at a time).
423 		 */
424 		PROP_OPL_CHANNEL_ALLOCATION_MODE = 8,
425 		/**
426 		 * Set this property to specify the Miles AIL/MSS version that the
427 		 * Miles drivers should emulate.
428 		 *
429 		 * MILES_VERSION_2: behavior matches Miles AIL versions 1 and 2.
430 		 * Specifically, GM devices are initialized like the MT-32 because
431 		 * these versions do not yet support GM.
432 		 * MILES_VERSION_3: behavior matches Miles Sound System version 3 and
433 		 * higher. GM devices are initialized according to the GM standard.
434 		 */
435 		PROP_MILES_VERSION = 9
436 	};
437 
438 	/**
439 	 * Open the midi driver.
440 	 * @return 0 if successful, otherwise an error code.
441 	 */
442 	virtual int open() = 0;
443 
444 	/**
445 	 * Check whether the midi driver has already been opened.
446 	 */
447 	virtual bool isOpen() const = 0;
448 
449 	/** Close the midi driver. */
450 	virtual void close() = 0;
451 
452 	/** Get or set a property. */
property(int prop,uint32 param)453 	virtual uint32 property(int prop, uint32 param) { return 0; }
454 
455 	/** Retrieve a string representation of an error code. */
456 	static const char *getErrorName(int error_code);
457 
458 	// HIGH-LEVEL SEMANTIC METHODS
setPitchBendRange(byte channel,uint range)459 	virtual void setPitchBendRange(byte channel, uint range) {
460 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_RPN_MSB, MIDI_RPN_PITCH_BEND_SENSITIVITY >> 8);
461 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_RPN_LSB, MIDI_RPN_PITCH_BEND_SENSITIVITY & 0xFF);
462 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_DATA_ENTRY_MSB, range); // Semi-tones
463 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_DATA_ENTRY_LSB, 0); // Cents
464 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_RPN_MSB, MIDI_RPN_NULL >> 8);
465 		send(MIDI_COMMAND_CONTROL_CHANGE | channel, MIDI_CONTROLLER_RPN_LSB, MIDI_RPN_NULL & 0xFF);
466 	}
467 
468 	/**
469 	 * Send a Roland MT-32 reset sysEx to the midi device.
470 	 */
471 	void sendMT32Reset();
472 
473 	/**
474 	 * Send a General MIDI reset sysEx to the midi device.
475 	 */
476 	void sendGMReset();
477 
sysEx_customInstrument(byte channel,uint32 type,const byte * instr)478 	virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
479 
480 	// Timing functions - MidiDriver now operates timers
481 	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;
482 
483 	/** The time in microseconds between invocations of the timer callback. */
484 	virtual uint32 getBaseTempo() = 0;
485 
486 	// Channel allocation functions
487 	virtual MidiChannel *allocateChannel() = 0;
488 	virtual MidiChannel *getPercussionChannel() = 0;
489 
490 	// Allow an engine to supply its own soundFont data. This stream will be destroyed after use.
setEngineSoundFont(Common::SeekableReadStream * soundFontData)491 	virtual void setEngineSoundFont(Common::SeekableReadStream *soundFontData) { }
492 
493 	// Does this driver accept soundFont data?
acceptsSoundFontData()494 	virtual bool acceptsSoundFontData() { return false; }
495 };
496 
497 class MidiChannel {
498 public:
~MidiChannel()499 	virtual ~MidiChannel() {}
500 
501 	virtual MidiDriver *device() = 0;
502 	virtual byte getNumber() = 0;
503 	virtual void release() = 0;
504 
505 	virtual void send(uint32 b) = 0; // 4-bit channel portion is ignored
506 
507 	// Regular messages
508 	virtual void noteOff(byte note) = 0;
509 	virtual void noteOn(byte note, byte velocity) = 0;
510 	virtual void programChange(byte program) = 0;
511 	virtual void pitchBend(int16 bend) = 0; // -0x2000 to +0x1FFF
512 
513 	// Control Change messages
514 	virtual void controlChange(byte control, byte value) = 0;
modulationWheel(byte value)515 	virtual void modulationWheel(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_MODULATION, value); }
volume(byte value)516 	virtual void volume(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_VOLUME, value); }
panPosition(byte value)517 	virtual void panPosition(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_PANNING, value); }
518 	virtual void pitchBendFactor(byte value) = 0;
transpose(int8 value)519 	virtual void transpose(int8 value) {}
detune(byte value)520 	virtual void detune(byte value) { controlChange(17, value); }
priority(byte value)521 	virtual void priority(byte value) { }
sustain(bool value)522 	virtual void sustain(bool value) { controlChange(MidiDriver::MIDI_CONTROLLER_SUSTAIN, value ? 1 : 0); }
effectLevel(byte value)523 	virtual void effectLevel(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_REVERB, value); }
chorusLevel(byte value)524 	virtual void chorusLevel(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_CHORUS, value); }
allNotesOff()525 	virtual void allNotesOff() { controlChange(MidiDriver::MIDI_CONTROLLER_ALL_NOTES_OFF, 0); }
526 
527 	// SysEx messages
528 	virtual void sysEx_customInstrument(uint32 type, const byte *instr) = 0;
529 };
530 /** @} */
531 #endif
532