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