1 /*
2  * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
3  *
4  * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
5  * ADLMIDI Library API:   Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
6  *
7  * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
8  * http://iki.fi/bisqwit/source/adlmidi.html
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "adlmidi_private.hpp"
25 
26 #ifdef ADLMIDI_HW_OPL
27 static const unsigned OPLBase = 0x388;
28 #else
29 #   if defined(ADLMIDI_DISABLE_NUKED_EMULATOR) && defined(ADLMIDI_DISABLE_DOSBOX_EMULATOR)
30 #       error "No emulators enabled. You must enable at least one emulator to use this library!"
31 #   endif
32 
33 // Nuked OPL3 emulator, Most accurate, but requires the powerful CPU
34 #   ifndef ADLMIDI_DISABLE_NUKED_EMULATOR
35 #       include "chips/nuked_opl3.h"
36 #       include "chips/nuked_opl3_v174.h"
37 #   endif
38 
39 // DosBox 0.74 OPL3 emulator, Well-accurate and fast
40 #   ifndef ADLMIDI_DISABLE_DOSBOX_EMULATOR
41 #       include "chips/dosbox_opl3.h"
42 #   endif
43 #endif
44 
45 //! Per-channel and per-operator registers map
46 static const uint16_t g_operatorsMap[23 * 2] =
47 {
48     // Channels 0-2
49     0x000, 0x003, 0x001, 0x004, 0x002, 0x005, // operators  0, 3,  1, 4,  2, 5
50     // Channels 3-5
51     0x008, 0x00B, 0x009, 0x00C, 0x00A, 0x00D, // operators  6, 9,  7,10,  8,11
52     // Channels 6-8
53     0x010, 0x013, 0x011, 0x014, 0x012, 0x015, // operators 12,15, 13,16, 14,17
54     // Same for second card
55     0x100, 0x103, 0x101, 0x104, 0x102, 0x105, // operators 18,21, 19,22, 20,23
56     0x108, 0x10B, 0x109, 0x10C, 0x10A, 0x10D, // operators 24,27, 25,28, 26,29
57     0x110, 0x113, 0x111, 0x114, 0x112, 0x115, // operators 30,33, 31,34, 32,35
58     // Channel 18
59     0x010, 0x013,  // operators 12,15
60     // Channel 19
61     0x014, 0xFFF,  // operator 16
62     // Channel 19
63     0x012, 0xFFF,  // operator 14
64     // Channel 19
65     0x015, 0xFFF,  // operator 17
66     // Channel 19
67     0x011, 0xFFF
68 }; // operator 13
69 
70 //! Channel map to regoster offsets
71 static const uint16_t g_channelsMap[23] =
72 {
73     0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, // 0..8
74     0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, // 9..17 (secondary set)
75     0x006, 0x007, 0x008, 0xFFF, 0xFFF
76 }; // <- hw percussions, 0xFFF = no support for pitch/pan
77 
78 /*
79     In OPL3 mode:
80          0    1    2    6    7    8     9   10   11    16   17   18
81        op0  op1  op2 op12 op13 op14  op18 op19 op20  op30 op31 op32
82        op3  op4  op5 op15 op16 op17  op21 op22 op23  op33 op34 op35
83          3    4    5                   13   14   15
84        op6  op7  op8                 op24 op25 op26
85        op9 op10 op11                 op27 op28 op29
86     Ports:
87         +0   +1   +2  +10  +11  +12  +100 +101 +102  +110 +111 +112
88         +3   +4   +5  +13  +14  +15  +103 +104 +105  +113 +114 +115
89         +8   +9   +A                 +108 +109 +10A
90         +B   +C   +D                 +10B +10C +10D
91 
92     Percussion:
93       bassdrum = op(0): 0xBD bit 0x10, operators 12 (0x10) and 15 (0x13) / channels 6, 6b
94       snare    = op(3): 0xBD bit 0x08, operators 16 (0x14)               / channels 7b
95       tomtom   = op(4): 0xBD bit 0x04, operators 14 (0x12)               / channels 8
96       cym      = op(5): 0xBD bit 0x02, operators 17 (0x17)               / channels 8b
97       hihat    = op(2): 0xBD bit 0x01, operators 13 (0x11)               / channels 7
98 
99 
100     In OPTi mode ("extended FM" in 82C924, 82C925, 82C931 chips):
101          0   1   2    3    4    5    6    7     8    9   10   11   12   13   14   15   16   17
102        op0 op4 op6 op10 op12 op16 op18 op22  op24 op28 op30 op34 op36 op38 op40 op42 op44 op46
103        op1 op5 op7 op11 op13 op17 op19 op23  op25 op29 op31 op35 op37 op39 op41 op43 op45 op47
104        op2     op8      op14      op20       op26      op32
105        op3     op9      op15      op21       op27      op33    for a total of 6 quad + 12 dual
106     Ports: ???
107 */
108 
makeEmptyInstrument()109 static adlinsdata2 makeEmptyInstrument()
110 {
111     adlinsdata2 ins;
112     memset(&ins, 0, sizeof(adlinsdata2));
113     ins.flags = adlinsdata::Flag_NoSound;
114     return ins;
115 }
116 
117 const adlinsdata2 OPL3::m_emptyInstrument = makeEmptyInstrument();
118 
OPL3()119 OPL3::OPL3() :
120     m_numChips(1),
121     m_numFourOps(0),
122     m_deepTremoloMode(false),
123     m_deepVibratoMode(false),
124     m_rhythmMode(false),
125     m_musicMode(MODE_MIDI),
126     m_volumeScale(VOLUME_Generic)
127 {
128 #ifdef DISABLE_EMBEDDED_BANKS
129     m_embeddedBank = CustomBankTag;
130 #else
131     setEmbeddedBank(0);
132 #endif
133 }
134 
setEmbeddedBank(uint32_t bank)135 void OPL3::setEmbeddedBank(uint32_t bank)
136 {
137 #ifndef DISABLE_EMBEDDED_BANKS
138     m_embeddedBank = bank;
139     //Embedded banks are supports 128:128 GM set only
140     m_insBanks.clear();
141 
142     if(bank >= static_cast<unsigned int>(maxAdlBanks()))
143         return;
144 
145     Bank *bank_pair[2] =
146     {
147         &m_insBanks[0],
148         &m_insBanks[PercussionTag]
149     };
150 
151     for(unsigned i = 0; i < 256; ++i)
152     {
153         size_t meta = banks[bank][i];
154         adlinsdata2 &ins = bank_pair[i / 128]->ins[i % 128];
155         ins = adlinsdata2(adlins[meta]);
156     }
157 #else
158     ADL_UNUSED(bank);
159 #endif
160 }
161 
writeReg(size_t chip,uint16_t address,uint8_t value)162 void OPL3::writeReg(size_t chip, uint16_t address, uint8_t value)
163 {
164 #ifdef ADLMIDI_HW_OPL
165     ADL_UNUSED(chip);
166     unsigned o = address >> 8;
167     unsigned port = OPLBase + o * 2;
168 
169     #ifdef __DJGPP__
170     outportb(port, address);
171     for(unsigned c = 0; c < 6; ++c) inportb(port);
172     outportb(port + 1, value);
173     for(unsigned c = 0; c < 35; ++c) inportb(port);
174     #endif
175 
176     #ifdef __WATCOMC__
177     outp(port, address);
178     for(uint16_t c = 0; c < 6; ++c)  inp(port);
179     outp(port + 1, value);
180     for(uint16_t c = 0; c < 35; ++c) inp(port);
181     #endif//__WATCOMC__
182 
183 #else//ADLMIDI_HW_OPL
184     m_chips[chip]->writeReg(address, value);
185 #endif
186 }
187 
writeRegI(size_t chip,uint32_t address,uint32_t value)188 void OPL3::writeRegI(size_t chip, uint32_t address, uint32_t value)
189 {
190 #ifdef ADLMIDI_HW_OPL
191     writeReg(chip, static_cast<uint16_t>(address), static_cast<uint8_t>(value));
192 #else//ADLMIDI_HW_OPL
193     m_chips[chip]->writeReg(static_cast<uint16_t>(address), static_cast<uint8_t>(value));
194 #endif
195 }
196 
197 
noteOff(size_t c)198 void OPL3::noteOff(size_t c)
199 {
200     size_t chip = c / 23, cc = c % 23;
201 
202     if(cc >= 18)
203     {
204         m_regBD[chip] &= ~(0x10 >> (cc - 18));
205         writeRegI(chip, 0xBD, m_regBD[chip]);
206         return;
207     }
208 
209     writeRegI(chip, 0xB0 + g_channelsMap[cc], m_keyBlockFNumCache[c] & 0xDF);
210 }
211 
noteOn(size_t c,double hertz)212 void OPL3::noteOn(size_t c, double hertz) // Hertz range: 0..131071
213 {
214     size_t chip = c / 23, cc = c % 23;
215     uint32_t x = 0x2000;
216 
217     if(hertz < 0 || hertz > 131071) // Avoid infinite loop
218         return;
219 
220     while(hertz >= 1023.5)
221     {
222         hertz /= 2.0;    // Calculate octave
223         x += 0x400;
224     }
225 
226     x += static_cast<uint32_t>(hertz + 0.5);
227     uint32_t chn = g_channelsMap[cc];
228 
229     if(cc >= 18)
230     {
231         m_regBD[chip ] |= (0x10 >> (cc - 18));
232         writeRegI(chip , 0x0BD, m_regBD[chip ]);
233         x &= ~0x2000u;
234         //x |= 0x800; // for test
235     }
236 
237     if(chn != 0xFFF)
238     {
239         writeRegI(chip , 0xA0 + chn, (x & 0xFF));
240         writeRegI(chip , 0xB0 + chn, (x >> 8));
241         m_keyBlockFNumCache[c] = (x >> 8);
242     }
243 }
244 
touchNote(size_t c,uint8_t volume,uint8_t brightness)245 void OPL3::touchNote(size_t c, uint8_t volume, uint8_t brightness)
246 {
247     if(volume > 63)
248         volume = 63;
249 
250     size_t chip = c / 23, cc = c % 23;
251     const adldata &adli = m_insCache[c];
252     uint16_t o1 = g_operatorsMap[cc * 2 + 0];
253     uint16_t o2 = g_operatorsMap[cc * 2 + 1];
254     uint8_t  x = adli.modulator_40, y = adli.carrier_40;
255     uint32_t mode = 1; // 2-op AM
256 
257     if(m_channelCategory[c] == 0 || m_channelCategory[c] == 3)
258     {
259         mode = adli.feedconn & 1; // 2-op FM or 2-op AM
260     }
261     else if(m_channelCategory[c] == 1 || m_channelCategory[c] == 2)
262     {
263         const adldata *i0, *i1;
264 
265         if(m_channelCategory[c] == 1)
266         {
267             i0 = &adli;
268             i1 = &m_insCache[c + 3];
269             mode = 2; // 4-op xx-xx ops 1&2
270         }
271         else
272         {
273             i0 = &m_insCache[c - 3];
274             i1 = &adli;
275             mode = 6; // 4-op xx-xx ops 3&4
276         }
277 
278         mode += (i0->feedconn & 1) + (i1->feedconn & 1) * 2;
279     }
280 
281     static const bool do_ops[10][2] =
282     {
283         { false, true },  /* 2 op FM */
284         { true,  true },  /* 2 op AM */
285         { false, false }, /* 4 op FM-FM ops 1&2 */
286         { true,  false }, /* 4 op AM-FM ops 1&2 */
287         { false, true  }, /* 4 op FM-AM ops 1&2 */
288         { true,  false }, /* 4 op AM-AM ops 1&2 */
289         { false, true  }, /* 4 op FM-FM ops 3&4 */
290         { false, true  }, /* 4 op AM-FM ops 3&4 */
291         { false, true  }, /* 4 op FM-AM ops 3&4 */
292         { true,  true  }  /* 4 op AM-AM ops 3&4 */
293     };
294 
295     if(m_musicMode == MODE_RSXX)
296     {
297         writeRegI(chip, 0x40 + o1, x);
298         if(o2 != 0xFFF)
299             writeRegI(chip, 0x40 + o2, y - volume / 2);
300     }
301     else
302     {
303         bool do_modulator = do_ops[ mode ][ 0 ] || m_scaleModulators;
304         bool do_carrier   = do_ops[ mode ][ 1 ] || m_scaleModulators;
305 
306         uint32_t modulator = do_modulator ? (x | 63) - volume + volume * (x & 63) / 63 : x;
307         uint32_t carrier   = do_carrier   ? (y | 63) - volume + volume * (y & 63) / 63 : y;
308 
309         if(brightness != 127)
310         {
311             brightness = static_cast<uint8_t>(::round(127.0 * ::sqrt((static_cast<double>(brightness)) * (1.0 / 127.0))) / 2.0);
312             if(!do_modulator)
313                 modulator = (modulator | 63) - brightness + brightness * (modulator & 63) / 63;
314             if(!do_carrier)
315                 carrier = (carrier | 63) - brightness + brightness * (carrier & 63) / 63;
316         }
317 
318         writeRegI(chip, 0x40 + o1, modulator);
319         if(o2 != 0xFFF)
320             writeRegI(chip, 0x40 + o2, carrier);
321     }
322 
323     // Correct formula (ST3, AdPlug):
324     //   63-((63-(instrvol))/63)*chanvol
325     // Reduces to (tested identical):
326     //   63 - chanvol + chanvol*instrvol/63
327     // Also (slower, floats):
328     //   63 + chanvol * (instrvol / 63.0 - 1)
329 }
330 
331 /*
332 void OPL3::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127
333 {
334     if(LogarithmicVolumes)
335         Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2);
336     else
337     {
338         // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A)
339         Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log(volume) * 11.541561 + (0.5 - 104.22845)) : 0);
340         // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A)
341         //Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0);
342     }
343 }*/
344 
setPatch(size_t c,const adldata & instrument)345 void OPL3::setPatch(size_t c, const adldata &instrument)
346 {
347     size_t chip = c / 23, cc = c % 23;
348     static const uint8_t data[4] = {0x20, 0x60, 0x80, 0xE0};
349     m_insCache[c] = instrument;
350     uint16_t o1 = g_operatorsMap[cc * 2 + 0];
351     uint16_t o2 = g_operatorsMap[cc * 2 + 1];
352     unsigned x = instrument.modulator_E862, y = instrument.carrier_E862;
353 
354     for(size_t a = 0; a < 4; ++a, x >>= 8, y >>= 8)
355     {
356         writeRegI(chip, data[a] + o1, x & 0xFF);
357         if(o2 != 0xFFF)
358             writeRegI(chip, data[a] + o2, y & 0xFF);
359     }
360 }
361 
setPan(size_t c,uint8_t value)362 void OPL3::setPan(size_t c, uint8_t value)
363 {
364     size_t chip = c / 23, cc = c % 23;
365     if(g_channelsMap[cc] != 0xFFF)
366         writeRegI(chip, 0xC0 + g_channelsMap[cc], m_insCache[c].feedconn | value);
367 }
368 
silenceAll()369 void OPL3::silenceAll() // Silence all OPL channels.
370 {
371     for(size_t c = 0; c < m_numChannels; ++c)
372     {
373         noteOff(c);
374         touchNote(c, 0);
375     }
376 }
377 
updateChannelCategories()378 void OPL3::updateChannelCategories()
379 {
380     uint32_t fours = m_numFourOps;
381 
382     for(size_t chip = 0; chip < m_numChips; ++chip)
383     {
384         m_regBD[chip] = (m_deepTremoloMode * 0x80 + m_deepVibratoMode * 0x40 + m_rhythmMode * 0x20);
385         writeRegI(chip, 0x0BD, m_regBD[chip]);
386         uint32_t fours_this_chip = std::min(fours, static_cast<uint32_t>(6u));
387         writeRegI(chip, 0x104, (1 << fours_this_chip) - 1);
388         fours -= fours_this_chip;
389     }
390 
391     // Mark all channels that are reserved for four-operator function
392     if(m_rhythmMode == 1)
393     {
394         for(size_t a = 0; a < m_numChips; ++a)
395         {
396             for(size_t b = 0; b < 5; ++b)
397                 m_channelCategory[a * 23 + 18 + b] = static_cast<char>(b + 3);
398             for(size_t b = 0; b < 3; ++b)
399                 m_channelCategory[a * 23 + 6  + b] = ChanCat_Rhythm_Slave;
400         }
401     }
402 
403     size_t nextfour = 0;
404     for(size_t a = 0; a < m_numFourOps; ++a)
405     {
406         m_channelCategory[nextfour] = ChanCat_4op_Master;
407         m_channelCategory[nextfour + 3] = ChanCat_4op_Slave;
408 
409         switch(a % 6)
410         {
411         case 0:
412         case 1:
413             nextfour += 1;
414             break;
415         case 2:
416             nextfour += 9 - 2;
417             break;
418         case 3:
419         case 4:
420             nextfour += 1;
421             break;
422         case 5:
423             nextfour += 23 - 9 - 2;
424             break;
425         }
426     }
427 
428 /**/
429 /*
430     In two-op mode, channels 0..8 go as follows:
431                   Op1[port]  Op2[port]
432       Channel 0:  00  00     03  03
433       Channel 1:  01  01     04  04
434       Channel 2:  02  02     05  05
435       Channel 3:  06  08     09  0B
436       Channel 4:  07  09     10  0C
437       Channel 5:  08  0A     11  0D
438       Channel 6:  12  10     15  13
439       Channel 7:  13  11     16  14
440       Channel 8:  14  12     17  15
441     In four-op mode, channels 0..8 go as follows:
442                   Op1[port]  Op2[port]  Op3[port]  Op4[port]
443       Channel 0:  00  00     03  03     06  08     09  0B
444       Channel 1:  01  01     04  04     07  09     10  0C
445       Channel 2:  02  02     05  05     08  0A     11  0D
446       Channel 3:  CHANNEL 0 SLAVE
447       Channel 4:  CHANNEL 1 SLAVE
448       Channel 5:  CHANNEL 2 SLAVE
449       Channel 6:  12  10     15  13
450       Channel 7:  13  11     16  14
451       Channel 8:  14  12     17  15
452      Same goes principally for channels 9-17 respectively.
453     */
454 }
455 
commitDeepFlags()456 void OPL3::commitDeepFlags()
457 {
458     for(size_t chip = 0; chip < m_numChips; ++chip)
459     {
460         m_regBD[chip] = (m_deepTremoloMode * 0x80 + m_deepVibratoMode * 0x40 + m_rhythmMode * 0x20);
461         writeRegI(chip, 0x0BD, m_regBD[chip]);
462     }
463 }
464 
setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel)465 void OPL3::setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel)
466 {
467     switch(volumeModel)
468     {
469     case ADLMIDI_VolumeModel_AUTO://Do nothing until restart playing
470         break;
471 
472     case ADLMIDI_VolumeModel_Generic:
473         m_volumeScale = OPL3::VOLUME_Generic;
474         break;
475 
476     case ADLMIDI_VolumeModel_NativeOPL3:
477         m_volumeScale = OPL3::VOLUME_NATIVE;
478         break;
479 
480     case ADLMIDI_VolumeModel_DMX:
481         m_volumeScale = OPL3::VOLUME_DMX;
482         break;
483 
484     case ADLMIDI_VolumeModel_APOGEE:
485         m_volumeScale = OPL3::VOLUME_APOGEE;
486         break;
487 
488     case ADLMIDI_VolumeModel_9X:
489         m_volumeScale = OPL3::VOLUME_9X;
490         break;
491     }
492 }
493 
494 #ifndef ADLMIDI_HW_OPL
clearChips()495 void OPL3::clearChips()
496 {
497     for(size_t i = 0; i < m_chips.size(); i++)
498         m_chips[i].reset(NULL);
499     m_chips.clear();
500 }
501 #endif
502 
reset(int emulator,unsigned long PCM_RATE,void * audioTickHandler)503 void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
504 {
505 #ifndef ADLMIDI_HW_OPL
506     clearChips();
507 #else
508     (void)emulator;
509     (void)PCM_RATE;
510 #endif
511 #if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
512     (void)audioTickHandler;
513 #endif
514     m_insCache.clear();
515     m_keyBlockFNumCache.clear();
516     m_regBD.clear();
517 
518 #ifndef ADLMIDI_HW_OPL
519     m_chips.resize(m_numChips, AdlMIDI_SPtr<OPLChipBase>());
520 #endif
521 
522     const struct adldata defaultInsCache = { 0x1557403,0x005B381, 0x49,0x80, 0x4, +0 };
523     m_numChannels = m_numChips * 23;
524     m_insCache.resize(m_numChannels, defaultInsCache);
525     m_keyBlockFNumCache.resize(m_numChannels,   0);
526     m_regBD.resize(m_numChips,    0);
527     m_channelCategory.resize(m_numChannels, 0);
528 
529     for(size_t p = 0, a = 0; a < m_numChips; ++a)
530     {
531         for(size_t b = 0; b < 18; ++b)
532             m_channelCategory[p++] = 0;
533         for(size_t b = 0; b < 5; ++b)
534             m_channelCategory[p++] = ChanCat_Rhythm_Slave;
535     }
536 
537     static const uint16_t data[] =
538     {
539         0x004, 96, 0x004, 128,        // Pulse timer
540         0x105, 0, 0x105, 1, 0x105, 0, // Pulse OPL3 enable
541         0x001, 32, 0x105, 1           // Enable wave, OPL3 extensions
542     };
543 //    size_t fours = m_numFourOps;
544 
545     for(size_t i = 0; i < m_numChips; ++i)
546     {
547 #ifndef ADLMIDI_HW_OPL
548         OPLChipBase *chip;
549         switch(emulator)
550         {
551         default:
552 #ifndef ADLMIDI_DISABLE_NUKED_EMULATOR
553         case ADLMIDI_EMU_NUKED: /* Latest Nuked OPL3 */
554             chip = new NukedOPL3;
555             break;
556         case ADLMIDI_EMU_NUKED_174: /* Old Nuked OPL3 1.4.7 modified and optimized */
557             chip = new NukedOPL3v174;
558             break;
559 #endif
560 #ifndef ADLMIDI_DISABLE_DOSBOX_EMULATOR
561         case ADLMIDI_EMU_DOSBOX:
562             chip = new DosBoxOPL3;
563             break;
564 #endif
565         }
566         m_chips[i].reset(chip);
567         chip->setChipId((uint32_t)i);
568         chip->setRate((uint32_t)PCM_RATE);
569         if(m_runAtPcmRate)
570             chip->setRunningAtPcmRate(true);
571 #   if defined(ADLMIDI_AUDIO_TICK_HANDLER)
572         chip->setAudioTickHandlerInstance(audioTickHandler);
573 #   endif
574 #endif // ADLMIDI_HW_OPL
575 
576         /* Clean-up channels from any playing junk sounds */
577         for(size_t a = 0; a < 18; ++a)
578             writeRegI(i, 0xB0 + g_channelsMap[a], 0x00);
579         for(size_t a = 0; a < sizeof(data) / sizeof(*data); a += 2)
580             writeRegI(i, data[a], (data[a + 1]));
581     }
582 
583     updateChannelCategories();
584     silenceAll();
585 }
586