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 #include "kyra/sound/drivers/midi.h"
24 
25 namespace Kyra {
26 
MidiOutput(OSystem * system,MidiDriver * output,bool isMT32,bool defaultMT32)27 MidiOutput::MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool defaultMT32) : _system(system), _output(output) {
28 	_isMT32 = isMT32;
29 	_defaultMT32 = defaultMT32;
30 
31 	int ret = _output->open();
32 	if (ret != MidiDriver::MERR_ALREADY_OPEN && ret != 0)
33 		error("Couldn't open midi driver");
34 
35 	static const Controller defaultControllers[] = {
36 		{ 0x07, 0x7F }, { 0x01, 0x00 }, { 0x0A, 0x40 },
37 		{ 0x0B, 0x7F }, { 0x40, 0x00 }, { 0x72, 0x00 },
38 		{ 0x6E, 0x00 }, { 0x6F, 0x00 }, { 0x70, 0x00 }
39 	};
40 
41 	static const byte defaultPrograms[] = {
42 		0x44, 0x30, 0x5F, 0x4E, 0x29, 0x03, 0x6E, 0x7A, 0xFF
43 	};
44 
45 	static const byte sysEx1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
46 	static const byte sysEx2[] = { 3, 4, 3, 4, 3, 4, 3, 4, 4 };
47 	static const byte sysEx3[] = { 0, 3, 2 };
48 
49 	if (_isMT32) {
50 		sendSysEx(0x7F, 0x00, 0x00, sysEx1, 1);
51 		sendSysEx(0x10, 0x00, 0x0D, sysEx1, 9);
52 		sendSysEx(0x10, 0x00, 0x04, sysEx2, 9);
53 		sendSysEx(0x10, 0x00, 0x01, sysEx3, 3);
54 	} else {
55 		_output->sendGMReset();
56 	}
57 
58 	memset(_channels, 0, sizeof(_channels));
59 	for (int i = 0; i < 16; ++i) {
60 		for (int j = 0; j < 9; ++j)
61 			_channels[i].controllers[j] = defaultControllers[j];
62 		_channels[i].pitchWheel = -1;
63 		_channels[i].program = 0xFF;
64 	}
65 
66 	for (int i = 0; i < 9; ++i) {
67 		for (int j = 1; j <= 9; ++j)
68 			sendIntern(0xB0, j, defaultControllers[i].controller, defaultControllers[i].value);
69 	}
70 
71 	for (int i = 1; i <= 9; ++i) {
72 		sendIntern(0xE0, i, 0x00, 0x40);
73 		if (defaultPrograms[i - 1] != 0xFF)
74 			sendIntern(0xC0, i, defaultPrograms[i - 1], 0x00);
75 	}
76 
77 	for (int i = 0; i < 4; ++i) {
78 		_sources[i].volume = 256;
79 		initSource(i);
80 	}
81 }
82 
83 
~MidiOutput()84 MidiOutput::~MidiOutput() {
85 	_output->close();
86 	delete _output;
87 }
88 
send(uint32 b)89 void MidiOutput::send(uint32 b) {
90 	const byte event = b & 0xF0;
91 	const byte channel = b & 0x0F;
92 	byte param1 = (b >>  8) & 0xFF;
93 	byte param2 = (b >> 16) & 0xFF;
94 
95 	if (event == 0xE0) {							// Pitch-Wheel
96 		_channels[channel].pitchWheel =
97 		_sources[_curSource].channelPW[channel] = (param2 << 8) | param1;
98 	} else if (event == 0xC0) {						// Program change
99 		_channels[channel].program =
100 		_sources[_curSource].channelProgram[channel] = param1;
101 	} else if (event == 0xB0) {						// Controller change
102 		for (int i = 0; i < 9; ++i) {
103 			Controller &cont = _sources[_curSource].controllers[channel][i];
104 			if (cont.controller == param1) {
105 				cont.value = param2;
106 				break;
107 			}
108 		}
109 
110 		if (param1 == 0x07) {
111 			param2 = (param2 * _sources[_curSource].volume) >> 8;
112 		} else if (param1 == 0x6E) {	// Lock Channel
113 			if (param2 >= 0x40) {	// Lock Channel
114 				int chan = lockChannel();
115 				if (chan < 0)
116 					chan = channel;
117 				_sources[_curSource].channelMap[channel] = chan;
118 			} else {				// Unlock Channel
119 				stopNotesOnChannel(channel);
120 				unlockChannel(_sources[_curSource].channelMap[channel]);
121 				_sources[_curSource].channelMap[channel] = channel;
122 			}
123 		} else if (param1 == 0x6F) {	// Protect Channel
124 			if (param2 >= 0x40) {	// Protect Channel
125 				_channels[channel].flags |= kChannelProtected;
126 			} else {				// Unprotect Channel
127 				_channels[channel].flags &= ~kChannelProtected;
128 			}
129 		} else if (param1 == 0x7B) {	// All notes off
130 			// FIXME: Since the XMIDI parsers sends this
131 			// on track change, we simply ignore it.
132 			return;
133 		}
134 	} else if (event == 0x90 || event == 0x80) {	// Note On/Off
135 		if (!(_channels[channel].flags & kChannelLocked)) {
136 			const bool remove = (event == 0x80) || (param2 == 0x00);
137 			int note = -1;
138 
139 			for (int i = 0; i < 32; ++i) {
140 				if (remove) {
141 					if (_sources[_curSource].notes[i].channel == channel &&
142 						_sources[_curSource].notes[i].note == param1) {
143 						note = i;
144 						break;
145 					}
146 				} else {
147 					if (_sources[_curSource].notes[i].channel == 0xFF) {
148 						note = i;
149 						break;
150 					}
151 				}
152 			}
153 
154 			if (note != -1) {
155 				if (remove) {
156 					_sources[_curSource].notes[note].channel = 0xFF;
157 
158 					--_channels[_sources[_curSource].channelMap[channel]].noteCount;
159 				} else {
160 					_sources[_curSource].notes[note].channel = channel;
161 					_sources[_curSource].notes[note].note = param1;
162 
163 					++_channels[_sources[_curSource].channelMap[channel]].noteCount;
164 				}
165 
166 				sendIntern(event, _sources[_curSource].channelMap[channel], param1, param2);
167 			}
168 		}
169 		return;
170 	}
171 
172 	if (!(_channels[channel].flags & kChannelLocked))
173 		sendIntern(event, _sources[_curSource].channelMap[channel], param1, param2);
174 }
175 
sendIntern(const byte event,const byte channel,byte param1,const byte param2)176 void MidiOutput::sendIntern(const byte event, const byte channel, byte param1, const byte param2) {
177 	if (event == 0xC0) {
178 		// MT32 -> GM conversion
179 		if (!_isMT32 && _defaultMT32)
180 			param1 = MidiDriver::_mt32ToGm[param1];
181 	}
182 
183 	_output->send(event | channel, param1, param2);
184 }
185 
sysEx(const byte * msg,uint16 length)186 void MidiOutput::sysEx(const byte *msg, uint16 length) {
187 	// Wait the time it takes to send the SysEx data
188 	uint32 delay = (length + 2) * 1000 / 3125;
189 
190 	// Plus an additional delay for the MT-32 rev00
191 	if (_isMT32)
192 		delay += 40;
193 
194 	_output->sysEx(msg, length);
195 	_system->delayMillis(delay);
196 }
197 
sendSysEx(const byte p1,const byte p2,const byte p3,const byte * buffer,const int size)198 void MidiOutput::sendSysEx(const byte p1, const byte p2, const byte p3, const byte *buffer, const int size) {
199 	int bufferSize = 8 + size;
200 	byte *outBuffer = new byte[bufferSize];
201 	assert(outBuffer);
202 
203 	outBuffer[0] = 0x41;
204 	outBuffer[1] = 0x10;
205 	outBuffer[2] = 0x16;
206 	outBuffer[3] = 0x12;
207 
208 	outBuffer[4] = p1;
209 	outBuffer[5] = p2;
210 	outBuffer[6] = p3;
211 
212 	memcpy(outBuffer + 7, buffer, size);
213 
214 	uint16 checkSum = p1 + p2 + p3;
215 	for (int i = 0; i < size; ++i)
216 		checkSum += buffer[i];
217 	checkSum &= 0x7F;
218 	checkSum -= 0x80;
219 	checkSum = -checkSum;
220 	checkSum &= 0x7F;
221 
222 	outBuffer[7+size] = checkSum;
223 
224 	sysEx(outBuffer, bufferSize);
225 
226 	delete[] outBuffer;
227 }
228 
metaEvent(byte type,byte * data,uint16 length)229 void MidiOutput::metaEvent(byte type, byte *data, uint16 length) {
230 	if (type == 0x2F) // End of Track
231 		deinitSource(_curSource);
232 
233 	_output->metaEvent(type, data, length);
234 }
235 
setSourceVolume(int source,int volume,bool apply)236 void MidiOutput::setSourceVolume(int source, int volume, bool apply) {
237 	_sources[source].volume = volume;
238 
239 	if (apply) {
240 		for (int i = 0; i < 16; ++i) {
241 			// Controller 0 in the state table should always be '7' aka
242 			// volume control
243 			byte realVol = (_sources[source].controllers[i][0].value * volume) >> 8;
244 			sendIntern(0xB0, i, 0x07, realVol);
245 		}
246 	}
247 }
248 
initSource(int source)249 void MidiOutput::initSource(int source) {
250 	memset(_sources[source].notes, -1, sizeof(_sources[source].notes));
251 
252 	for (int i = 0; i < 16; ++i) {
253 		_sources[source].channelMap[i] = i;
254 		_sources[source].channelProgram[i] = 0xFF;
255 		_sources[source].channelPW[i] = -1;
256 
257 		for (int j = 0; j < 9; ++j)
258 			_sources[source].controllers[i][j] = _channels[i].controllers[j];
259 	}
260 }
261 
deinitSource(int source)262 void MidiOutput::deinitSource(int source) {
263 	for (int i = 0; i < 16; ++i) {
264 		for (int j = 0; j < 9; ++j) {
265 			const Controller &cont = _sources[source].controllers[i][j];
266 
267 			if (cont.controller == 0x40) {
268 				if (cont.value >= 0x40)
269 					sendIntern(0xB0, i, 0x40, 0);
270 			} else if (cont.controller == 0x6E) {
271 				if (cont.value >= 0x40) {
272 					stopNotesOnChannel(i);
273 					unlockChannel(_sources[source].channelMap[i]);
274 					_sources[source].channelMap[i] = i;
275 				}
276 			} else if (cont.controller == 0x6F) {
277 				if (cont.value >= 0x40)
278 					_channels[i].flags &= ~kChannelProtected;
279 			} else if (cont.controller == 0x70) {
280 				if (cont.value >= 0x40)
281 					sendIntern(0xB0, i, 0x70, 0);
282 			}
283 		}
284 	}
285 }
286 
lockChannel()287 int MidiOutput::lockChannel() {
288 	int channel = -1;
289 	int notes = 0xFF;
290 	byte flags = kChannelLocked | kChannelProtected;
291 
292 	while (channel == -1) {
293 		for (int i = _isMT32 ? 8 : 15; i >= 1; --i) {
294 			if (_channels[i].flags & flags)
295 				continue;
296 			if (_channels[i].noteCount < notes) {
297 				channel = i;
298 				notes = _channels[i].noteCount;
299 			}
300 		}
301 
302 		if (channel == -1) {
303 			if (flags & kChannelProtected)
304 				flags &= ~kChannelProtected;
305 			else
306 				break;
307 		}
308 	}
309 
310 	if (channel == -1)
311 		return -1;
312 
313 	sendIntern(0xB0, channel, 0x40, 0);
314 	stopNotesOnChannel(channel);
315 	_channels[channel].noteCount = 0;
316 	_channels[channel].flags |= kChannelLocked;
317 
318 	return channel;
319 }
320 
unlockChannel(int channel)321 void MidiOutput::unlockChannel(int channel) {
322 	if (!(_channels[channel].flags & kChannelLocked))
323 		return;
324 
325 	_channels[channel].flags &= ~kChannelLocked;
326 	_channels[channel].noteCount = 0;
327 	sendIntern(0xB0, channel, 0x40, 0);
328 	sendIntern(0xB0, channel, 0x7B, 0);
329 
330 	for (int i = 0; i < 9; ++i) {
331 		if (_channels[channel].controllers[i].value != 0xFF)
332 			sendIntern(0xB0, channel, _channels[channel].controllers[i].controller, _channels[channel].controllers[i].value);
333 	}
334 
335 	if (_channels[channel].program != 0xFF)
336 		sendIntern(0xC0, channel, _channels[channel].program, 0);
337 
338 	if (_channels[channel].pitchWheel != -1)
339 		sendIntern(0xE0, channel, _channels[channel].pitchWheel & 0xFF, (_channels[channel].pitchWheel >> 8) & 0xFF);
340 }
341 
stopNotesOnChannel(int channel)342 void MidiOutput::stopNotesOnChannel(int channel) {
343 	for (int i = 0; i < 4; ++i) {
344 		SoundSource &sound = _sources[i];
345 		for (int j = 0; j < 32; ++j) {
346 			if (sound.notes[j].channel == channel) {
347 				sound.notes[j].channel = 0xFF;
348 				sendIntern(0x80, sound.channelMap[channel], sound.notes[j].note, 0);
349 				--_channels[sound.channelMap[channel]].noteCount;
350 			}
351 		}
352 	}
353 }
354 
355 } // End of namespace Kyra
356