1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // Copyright(C) 1993-1996 Id Software, Inc.
5 // Copyright(C) 2005 Simon Howard
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., 59 Temple Place - Suite 330, Boston, MA
20 // 02111-1307, USA.
21 //
22 // DESCRIPTION:
23 // System interface for music.
24 //
25 //-----------------------------------------------------------------------------
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "config.h"
32
33 #include "doomdef.h"
34
35 #include "m_misc.h"
36 #include "s_sound.h"
37 #include "w_wad.h"
38 #include "z_zone.h"
39
40 #include "opl.h"
41 #include "midifile.h"
42
43 #include "musicplayer.h"
44
45 #include "lprintf.h"
46
47 // #define OPL_MIDI_DEBUG
48
49 #define MAXMIDLENGTH (96 * 1024)
50 #define GENMIDI_NUM_INSTRS 128
51
52 #define GENMIDI_HEADER "#OPL_II#"
53 #define GENMIDI_FLAG_FIXED 0x0001 /* fixed pitch */
54 #define GENMIDI_FLAG_2VOICE 0x0004 /* double voice (OPL3) */
55
56 typedef struct
57 {
58 unsigned char tremolo;
59 unsigned char attack;
60 unsigned char sustain;
61 unsigned char waveform;
62 unsigned char scale;
63 unsigned char level;
64 } PACKEDATTR genmidi_op_t;
65
66 typedef struct
67 {
68 genmidi_op_t modulator;
69 unsigned char feedback;
70 genmidi_op_t carrier;
71 unsigned char unused;
72 short base_note_offset;
73 } PACKEDATTR genmidi_voice_t;
74
75 typedef struct
76 {
77 unsigned short flags;
78 unsigned char fine_tuning;
79 unsigned char fixed_note;
80
81 genmidi_voice_t voices[2];
82 } PACKEDATTR genmidi_instr_t;
83
84 // Data associated with a channel of a track that is currently playing.
85
86 typedef struct
87 {
88 // The instrument currently used for this track.
89
90 const genmidi_instr_t *instrument;
91
92 // Volume level
93
94 int volume;
95
96 // Pitch bend value:
97
98 int bend;
99
100 } opl_channel_data_t;
101
102 // Data associated with a track that is currently playing.
103
104 typedef struct
105 {
106 // Data for each channel.
107
108 opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK];
109
110 // Track iterator used to read new events.
111
112 midi_track_iter_t *iter;
113
114 // Tempo control variables
115
116 unsigned int ticks_per_beat;
117 unsigned int ms_per_beat;
118 } opl_track_data_t;
119
120 typedef struct opl_voice_s opl_voice_t;
121
122 struct opl_voice_s
123 {
124 // Index of this voice:
125 int index;
126
127 // The operators used by this voice:
128 int op1, op2;
129
130 // Currently-loaded instrument data
131 const genmidi_instr_t *current_instr;
132
133 // The voice number in the instrument to use.
134 // This is normally set to zero; if this is a double voice
135 // instrument, it may be one.
136 unsigned int current_instr_voice;
137
138 // The channel currently using this voice.
139 opl_channel_data_t *channel;
140
141 // The midi key that this voice is playing.
142 unsigned int key;
143
144 // The note being played. This is normally the same as
145 // the key, but if the instrument is a fixed pitch
146 // instrument, it is different.
147 unsigned int note;
148
149 // The frequency value being used.
150 unsigned int freq;
151
152 // The volume of the note being played on this channel.
153 unsigned int note_volume;
154
155 // The current volume (register value) that has been set for this channel.
156 unsigned int reg_volume;
157
158 // Next in linked list; a voice is always either in the
159 // free list or the allocated list.
160 opl_voice_t *next;
161 };
162
163 // Operators used by the different voices.
164
165 static const int voice_operators[2][OPL_NUM_VOICES] = {
166 { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12 },
167 { 0x03, 0x04, 0x05, 0x0b, 0x0c, 0x0d, 0x13, 0x14, 0x15 }
168 };
169
170 // Frequency values to use for each note.
171
172 static const unsigned short frequency_curve[] = {
173
174 0x133, 0x133, 0x134, 0x134, 0x135, 0x136, 0x136, 0x137, // -1
175 0x137, 0x138, 0x138, 0x139, 0x139, 0x13a, 0x13b, 0x13b,
176 0x13c, 0x13c, 0x13d, 0x13d, 0x13e, 0x13f, 0x13f, 0x140,
177 0x140, 0x141, 0x142, 0x142, 0x143, 0x143, 0x144, 0x144,
178
179 0x145, 0x146, 0x146, 0x147, 0x147, 0x148, 0x149, 0x149, // -2
180 0x14a, 0x14a, 0x14b, 0x14c, 0x14c, 0x14d, 0x14d, 0x14e,
181 0x14f, 0x14f, 0x150, 0x150, 0x151, 0x152, 0x152, 0x153,
182 0x153, 0x154, 0x155, 0x155, 0x156, 0x157, 0x157, 0x158,
183
184 // These are used for the first seven MIDI note values:
185
186 0x158, 0x159, 0x15a, 0x15a, 0x15b, 0x15b, 0x15c, 0x15d, // 0
187 0x15d, 0x15e, 0x15f, 0x15f, 0x160, 0x161, 0x161, 0x162,
188 0x162, 0x163, 0x164, 0x164, 0x165, 0x166, 0x166, 0x167,
189 0x168, 0x168, 0x169, 0x16a, 0x16a, 0x16b, 0x16c, 0x16c,
190
191 0x16d, 0x16e, 0x16e, 0x16f, 0x170, 0x170, 0x171, 0x172, // 1
192 0x172, 0x173, 0x174, 0x174, 0x175, 0x176, 0x176, 0x177,
193 0x178, 0x178, 0x179, 0x17a, 0x17a, 0x17b, 0x17c, 0x17c,
194 0x17d, 0x17e, 0x17e, 0x17f, 0x180, 0x181, 0x181, 0x182,
195
196 0x183, 0x183, 0x184, 0x185, 0x185, 0x186, 0x187, 0x188, // 2
197 0x188, 0x189, 0x18a, 0x18a, 0x18b, 0x18c, 0x18d, 0x18d,
198 0x18e, 0x18f, 0x18f, 0x190, 0x191, 0x192, 0x192, 0x193,
199 0x194, 0x194, 0x195, 0x196, 0x197, 0x197, 0x198, 0x199,
200
201 0x19a, 0x19a, 0x19b, 0x19c, 0x19d, 0x19d, 0x19e, 0x19f, // 3
202 0x1a0, 0x1a0, 0x1a1, 0x1a2, 0x1a3, 0x1a3, 0x1a4, 0x1a5,
203 0x1a6, 0x1a6, 0x1a7, 0x1a8, 0x1a9, 0x1a9, 0x1aa, 0x1ab,
204 0x1ac, 0x1ad, 0x1ad, 0x1ae, 0x1af, 0x1b0, 0x1b0, 0x1b1,
205
206 0x1b2, 0x1b3, 0x1b4, 0x1b4, 0x1b5, 0x1b6, 0x1b7, 0x1b8, // 4
207 0x1b8, 0x1b9, 0x1ba, 0x1bb, 0x1bc, 0x1bc, 0x1bd, 0x1be,
208 0x1bf, 0x1c0, 0x1c0, 0x1c1, 0x1c2, 0x1c3, 0x1c4, 0x1c4,
209 0x1c5, 0x1c6, 0x1c7, 0x1c8, 0x1c9, 0x1c9, 0x1ca, 0x1cb,
210
211 0x1cc, 0x1cd, 0x1ce, 0x1ce, 0x1cf, 0x1d0, 0x1d1, 0x1d2, // 5
212 0x1d3, 0x1d3, 0x1d4, 0x1d5, 0x1d6, 0x1d7, 0x1d8, 0x1d8,
213 0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df,
214 0x1e0, 0x1e1, 0x1e2, 0x1e3, 0x1e4, 0x1e5, 0x1e5, 0x1e6,
215
216 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed, // 6
217 0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5,
218 0x1f6, 0x1f6, 0x1f7, 0x1f8, 0x1f9, 0x1fa, 0x1fb, 0x1fc,
219 0x1fd, 0x1fe, 0x1ff, 0x200, 0x201, 0x201, 0x202, 0x203,
220
221 // First note of looped range used for all octaves:
222
223 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, // 7
224 0x20c, 0x20d, 0x20e, 0x20f, 0x210, 0x210, 0x211, 0x212,
225 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a,
226 0x21b, 0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222,
227
228 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, // 8
229 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232,
230 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a,
231 0x23b, 0x23c, 0x23d, 0x23e, 0x23f, 0x240, 0x241, 0x242,
232
233 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b, // 9
234 0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253,
235 0x254, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b, 0x25c,
236 0x25d, 0x25e, 0x25f, 0x260, 0x262, 0x263, 0x264, 0x265,
237
238 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, // 10
239 0x26f, 0x270, 0x271, 0x272, 0x273, 0x275, 0x276, 0x277,
240 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280,
241 0x281, 0x282, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289,
242
243 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x292, 0x293, // 11
244 0x294, 0x295, 0x296, 0x298, 0x299, 0x29a, 0x29b, 0x29c,
245 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6,
246 0x2a7, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ae, 0x2af, 0x2b0,
247
248 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba, // 12
249 0x2bb, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c2, 0x2c3, 0x2c4,
250 0x2c5, 0x2c7, 0x2c8, 0x2c9, 0x2cb, 0x2cc, 0x2cd, 0x2ce,
251 0x2d0, 0x2d1, 0x2d2, 0x2d4, 0x2d5, 0x2d6, 0x2d8, 0x2d9,
252
253 0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, // 13
254 0x2e5, 0x2e6, 0x2e8, 0x2e9, 0x2ea, 0x2ec, 0x2ed, 0x2ee,
255 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9,
256 0x2fb, 0x2fc, 0x2fd, 0x2ff, 0x300, 0x302, 0x303, 0x304,
257
258 0x306, 0x307, 0x309, 0x30a, 0x30b, 0x30d, 0x30e, 0x310, // 14
259 0x311, 0x312, 0x314, 0x315, 0x317, 0x318, 0x31a, 0x31b,
260 0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327,
261 0x328, 0x329, 0x32b, 0x32c, 0x32e, 0x32f, 0x331, 0x332,
262
263 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e, // 15
264 0x340, 0x341, 0x343, 0x344, 0x346, 0x347, 0x349, 0x34a,
265 0x34c, 0x34d, 0x34f, 0x350, 0x352, 0x353, 0x355, 0x357,
266 0x358, 0x35a, 0x35b, 0x35d, 0x35e, 0x360, 0x361, 0x363,
267
268 0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, // 16
269 0x371, 0x373, 0x374, 0x376, 0x378, 0x379, 0x37b, 0x37c,
270 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389,
271 0x38b, 0x38d, 0x38e, 0x390, 0x392, 0x393, 0x395, 0x397,
272
273 0x398, 0x39a, 0x39c, 0x39d, 0x39f, 0x3a1, 0x3a2, 0x3a4, // 17
274 0x3a6, 0x3a7, 0x3a9, 0x3ab, 0x3ac, 0x3ae, 0x3b0, 0x3b1,
275 0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf,
276 0x3c1, 0x3c3, 0x3c4, 0x3c6, 0x3c8, 0x3ca, 0x3cb, 0x3cd,
277
278 // The last note has an incomplete range, and loops round back to
279 // the start. Note that the last value is actually a buffer overrun
280 // and does not fit with the other values.
281
282 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db, // 18
283 0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e4, 0x3e6, 0x3e8, 0x3ea,
284 0x3ec, 0x3ed, 0x3ef, 0x3f1, 0x3f3, 0x3f5, 0x3f6, 0x3f8,
285 0x3fa, 0x3fc, 0x3fe, 0x36c,
286 };
287
288 // Mapping from MIDI volume level to OPL level value.
289
290 static const unsigned int volume_mapping_table[] = {
291 0, 1, 3, 5, 6, 8, 10, 11,
292 13, 14, 16, 17, 19, 20, 22, 23,
293 25, 26, 27, 29, 30, 32, 33, 34,
294 36, 37, 39, 41, 43, 45, 47, 49,
295 50, 52, 54, 55, 57, 59, 60, 61,
296 63, 64, 66, 67, 68, 69, 71, 72,
297 73, 74, 75, 76, 77, 79, 80, 81,
298 82, 83, 84, 84, 85, 86, 87, 88,
299 89, 90, 91, 92, 92, 93, 94, 95,
300 96, 96, 97, 98, 99, 99, 100, 101,
301 101, 102, 103, 103, 104, 105, 105, 106,
302 107, 107, 108, 109, 109, 110, 110, 111,
303 112, 112, 113, 113, 114, 114, 115, 115,
304 116, 117, 117, 118, 118, 119, 119, 120,
305 120, 121, 121, 122, 122, 123, 123, 123,
306 124, 124, 125, 125, 126, 126, 127, 127
307 };
308
309 static dbool music_initialized = false;
310
311 //static dbool musicpaused = false;
312 static int current_music_volume;
313
314 // GENMIDI lump instrument data:
315
316 static const genmidi_instr_t *main_instrs;
317 static const genmidi_instr_t *percussion_instrs;
318
319 // Voices:
320
321 static opl_voice_t voices[OPL_NUM_VOICES];
322 static opl_voice_t *voice_free_list;
323 static opl_voice_t *voice_alloced_list;
324
325 // Track data for playing tracks:
326
327 static opl_track_data_t *tracks;
328 static unsigned int num_tracks = 0;
329 static unsigned int running_tracks = 0;
330 static dbool song_looping;
331
332 // Configuration file variable, containing the port number for the
333 // adlib chip.
334
335 int opl_io_port = 0x388;
336
337 // Load instrument table from GENMIDI lump:
338
LoadInstrumentTable(void)339 static dbool LoadInstrumentTable(void)
340 {
341 const unsigned char *lump;
342
343 if (W_CheckNumForName("GENMIDI") == -1)
344 return false;
345
346 lump = W_CacheLumpName("GENMIDI");
347
348 // Check header
349
350 if (strncmp((const char *) lump, GENMIDI_HEADER, strlen(GENMIDI_HEADER)) != 0)
351 {
352 W_UnlockLumpName("GENMIDI");
353
354 return false;
355 }
356
357 main_instrs = (const genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER));
358 percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS;
359
360 return true;
361 }
362
363 // Get the next available voice from the freelist.
364
GetFreeVoice(void)365 static opl_voice_t *GetFreeVoice(void)
366 {
367 opl_voice_t *result;
368
369 // None available?
370
371 if (voice_free_list == NULL)
372 {
373 return NULL;
374 }
375
376 // Remove from free list
377
378 result = voice_free_list;
379 voice_free_list = voice_free_list->next;
380
381 // Add to allocated list
382
383 result->next = voice_alloced_list;
384 voice_alloced_list = result;
385
386 return result;
387 }
388
389 // Remove a voice from the allocated voices list.
390
RemoveVoiceFromAllocedList(opl_voice_t * voice)391 static void RemoveVoiceFromAllocedList(opl_voice_t *voice)
392 {
393 opl_voice_t **rover;
394
395 rover = &voice_alloced_list;
396
397 // Search the list until we find the voice, then remove it.
398
399 while (*rover != NULL)
400 {
401 if (*rover == voice)
402 {
403 *rover = voice->next;
404 voice->next = NULL;
405 break;
406 }
407
408 rover = &(*rover)->next;
409 }
410 }
411
412 // Release a voice back to the freelist.
413
ReleaseVoice(opl_voice_t * voice)414 static void ReleaseVoice(opl_voice_t *voice)
415 {
416 opl_voice_t **rover;
417
418 voice->channel = NULL;
419 voice->note = 0;
420
421 // Remove from alloced list.
422
423 RemoveVoiceFromAllocedList(voice);
424
425 // Search to the end of the freelist (This is how Doom behaves!)
426
427 rover = &voice_free_list;
428
429 while (*rover != NULL)
430 {
431 rover = &(*rover)->next;
432 }
433
434 *rover = voice;
435 voice->next = NULL;
436 }
437
438 // Load data to the specified operator
439
LoadOperatorData(int operator,const genmidi_op_t * data,dbool max_level)440 static void LoadOperatorData(int operator,
441 const genmidi_op_t *data,
442 dbool max_level)
443 {
444 int level;
445
446 // The scale and level fields must be combined for the level register.
447 // For the carrier wave we always set the maximum level.
448
449 level = (data->scale & 0xc0) | (data->level & 0x3f);
450
451 if (max_level)
452 {
453 level |= 0x3f;
454 }
455
456 OPL_WriteRegister(OPL_REGS_LEVEL + operator, level);
457 OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo);
458 OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack);
459 OPL_WriteRegister(OPL_REGS_SUSTAIN + operator, data->sustain);
460 OPL_WriteRegister(OPL_REGS_WAVEFORM + operator, data->waveform);
461 }
462
463 // Set the instrument for a particular voice.
464
SetVoiceInstrument(opl_voice_t * voice,const genmidi_instr_t * instr,unsigned int instr_voice)465 static void SetVoiceInstrument(opl_voice_t *voice,
466 const genmidi_instr_t *instr,
467 unsigned int instr_voice)
468 {
469 const genmidi_voice_t *data;
470 unsigned int modulating;
471
472 // Instrument already set for this channel?
473
474 if (voice->current_instr == instr
475 && voice->current_instr_voice == instr_voice)
476 {
477 return;
478 }
479
480 voice->current_instr = instr;
481 voice->current_instr_voice = instr_voice;
482
483 data = &instr->voices[instr_voice];
484
485 // Are we usind modulated feedback mode?
486
487 modulating = (data->feedback & 0x01) == 0;
488
489 // Doom loads the second operator first, then the first.
490 // The carrier is set to minimum volume until the voice volume
491 // is set in SetVoiceVolume (below). If we are not using
492 // modulating mode, we must set both to minimum volume.
493
494 LoadOperatorData(voice->op2, &data->carrier, true);
495 LoadOperatorData(voice->op1, &data->modulator, !modulating);
496
497 // Set feedback register that control the connection between the
498 // two operators. Turn on bits in the upper nybble; I think this
499 // is for OPL3, where it turns on channel A/B.
500
501 OPL_WriteRegister(OPL_REGS_FEEDBACK + voice->index,
502 data->feedback | 0x30);
503
504 // Hack to force a volume update.
505
506 voice->reg_volume = 999;
507 }
508
SetVoiceVolume(opl_voice_t * voice,unsigned int volume)509 static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume)
510 {
511 const genmidi_voice_t *opl_voice;
512 unsigned int full_volume;
513 unsigned int op_volume;
514 unsigned int reg_volume;
515
516 voice->note_volume = volume;
517
518 opl_voice = &voice->current_instr->voices[voice->current_instr_voice];
519
520 // Multiply note volume and channel volume to get the actual volume.
521
522 full_volume = (volume_mapping_table[voice->note_volume]
523 * volume_mapping_table[voice->channel->volume]
524 * volume_mapping_table[current_music_volume]) / (127 * 127);
525
526 if (full_volume > 0)
527 {
528 // The volume of each instrument can be controlled via GENMIDI:
529 op_volume = 0x3f - opl_voice->carrier.level;
530
531 // The volume value to use in the register:
532
533 reg_volume = (op_volume * full_volume) / 128;
534 reg_volume = (0x3f - reg_volume) | opl_voice->carrier.scale;
535 }
536 else
537 reg_volume = 0xff;
538
539 // Update the volume register(s) if necessary.
540
541 if (reg_volume != voice->reg_volume)
542 {
543 voice->reg_volume = reg_volume;
544
545 OPL_WriteRegister(OPL_REGS_LEVEL + voice->op2, reg_volume);
546
547 // If we are using non-modulated feedback mode, we must set the
548 // volume for both voices.
549 // Note that the same register volume value is written for
550 // both voices, always calculated from the carrier's level
551 // value.
552
553 if ((opl_voice->feedback & 0x01) != 0)
554 {
555 OPL_WriteRegister(OPL_REGS_LEVEL + voice->op1, reg_volume);
556 }
557 }
558 }
559
560 // Initialize the voice table and freelist
561
InitVoices(void)562 static void InitVoices(void)
563 {
564 int i;
565
566 // Start with an empty free list.
567
568 voice_free_list = NULL;
569
570 // Initialize each voice.
571
572 for (i=0; i<OPL_NUM_VOICES; ++i)
573 {
574 voices[i].index = i;
575 voices[i].op1 = voice_operators[0][i];
576 voices[i].op2 = voice_operators[1][i];
577 voices[i].current_instr = NULL;
578
579 // Add this voice to the freelist.
580
581 ReleaseVoice(&voices[i]);
582 }
583 }
584
585 // Set music volume (0 - 15)
586
I_OPL_SetMusicVolume(int volume)587 void I_OPL_SetMusicVolume(int volume)
588 {
589 int opl_vol = volume * 127 / 15; // OPL synth internally uses 0-127
590
591 unsigned int i;
592
593 // Internal state variable.
594
595 current_music_volume = opl_vol;
596
597 // Update the volume of all voices.
598
599 for (i=0; i<OPL_NUM_VOICES; ++i)
600 {
601 if (voices[i].channel != NULL)
602 {
603 SetVoiceVolume(&voices[i], voices[i].note_volume);
604 }
605 }
606 }
607
VoiceKeyOff(opl_voice_t * voice)608 static void VoiceKeyOff(opl_voice_t *voice)
609 {
610 OPL_WriteRegister(OPL_REGS_FREQ_2 + voice->index, voice->freq >> 8);
611 }
612
613 // Get the frequency that we should be using for a voice.
614
KeyOffEvent(opl_track_data_t * track,midi_event_t * event)615 static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event)
616 {
617 opl_channel_data_t *channel;
618 unsigned int key;
619 unsigned int i;
620
621 /*
622 printf("note off: channel %i, %i, %i\n",
623 event->data.channel.channel,
624 event->data.channel.param1,
625 event->data.channel.param2);
626 */
627
628 channel = &track->channels[event->data.channel.channel];
629 key = event->data.channel.param1;
630
631 // Turn off voices being used to play this key.
632 // If it is a double voice instrument there will be two.
633
634 for (i=0; i<OPL_NUM_VOICES; ++i)
635 {
636 if (voices[i].channel == channel && voices[i].key == key)
637 {
638 VoiceKeyOff(&voices[i]);
639
640 // Finished with this voice now.
641
642 ReleaseVoice(&voices[i]);
643 }
644 }
645 }
646
647 // Compare the priorities of channels, returning either -1, 0 or 1.
648
CompareChannelPriorities(opl_channel_data_t * chan1,opl_channel_data_t * chan2)649 static int CompareChannelPriorities(opl_channel_data_t *chan1,
650 opl_channel_data_t *chan2)
651 {
652 // TODO ...
653
654 return 1;
655 }
656
657 // When all voices are in use, we must discard an existing voice to
658 // play a new note. Find and free an existing voice. The channel
659 // passed to the function is the channel for the new note to be
660 // played.
661
ReplaceExistingVoice(opl_channel_data_t * channel)662 static opl_voice_t *ReplaceExistingVoice(opl_channel_data_t *channel)
663 {
664 opl_voice_t *rover;
665 opl_voice_t *result;
666
667 // Check the allocated voices, if we find an instrument that is
668 // of a lower priority to the new instrument, discard it.
669 // If a voice is being used to play the second voice of an instrument,
670 // use that, as second voices are non-essential.
671 // Lower numbered MIDI channels implicitly have a higher priority
672 // than higher-numbered channels, eg. MIDI channel 1 is never
673 // discarded for MIDI channel 2.
674
675 result = NULL;
676
677 for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
678 {
679 if (rover->current_instr_voice != 0
680 || (rover->channel > channel
681 && CompareChannelPriorities(channel, rover->channel) > 0))
682 {
683 result = rover;
684 break;
685 }
686 }
687
688 // If we didn't find a voice, find an existing voice being used to
689 // play a note on the same channel, and use that.
690
691 if (result == NULL)
692 {
693 for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
694 {
695 if (rover->channel == channel)
696 {
697 result = rover;
698 break;
699 }
700 }
701 }
702
703 // Still nothing found? Give up and just use the first voice in
704 // the list.
705
706 if (result == NULL)
707 {
708 result = voice_alloced_list;
709 }
710
711 // Stop playing this voice playing and release it back to the free
712 // list.
713
714 VoiceKeyOff(result);
715 ReleaseVoice(result);
716
717 // Re-allocate the voice again and return it.
718
719 return GetFreeVoice();
720 }
721
722
FrequencyForVoice(opl_voice_t * voice)723 static unsigned int FrequencyForVoice(opl_voice_t *voice)
724 {
725 const genmidi_voice_t *gm_voice;
726 unsigned int freq_index;
727 unsigned int octave;
728 unsigned int sub_index;
729 unsigned int note;
730
731 note = voice->note;
732
733 // Apply note offset.
734 // Don't apply offset if the instrument is a fixed note instrument.
735
736 gm_voice = &voice->current_instr->voices[voice->current_instr_voice];
737
738 if ((voice->current_instr->flags & GENMIDI_FLAG_FIXED) == 0)
739 {
740 note += (signed short) doom_htows(gm_voice->base_note_offset);
741 }
742
743 // Avoid possible overflow due to base note offset:
744
745 if (note > 0x7f)
746 {
747 note = voice->note;
748 }
749
750 freq_index = 64 + 32 * note + voice->channel->bend;
751
752 // If this is the second voice of a double voice instrument, the
753 // frequency index can be adjusted by the fine tuning field.
754
755 if (voice->current_instr_voice != 0)
756 {
757 freq_index += (voice->current_instr->fine_tuning / 2) - 64;
758 }
759
760 // The first 7 notes use the start of the table, while
761 // consecutive notes loop around the latter part.
762
763 if (freq_index < 284)
764 {
765 return frequency_curve[freq_index];
766 }
767
768 sub_index = (freq_index - 284) % (12 * 32);
769 octave = (freq_index - 284) / (12 * 32);
770
771 // Once the seventh octave is reached, things break down.
772 // We can only go up to octave 7 as a maximum anyway (the OPL
773 // register only has three bits for octave number), but for the
774 // notes in octave 7, the first five bits have octave=7, the
775 // following notes have octave=6. This 7/6 pattern repeats in
776 // following octaves (which are technically impossible to
777 // represent anyway).
778
779 if (octave >= 7)
780 {
781 if (sub_index < 5)
782 {
783 octave = 7;
784 }
785 else
786 {
787 octave = 6;
788 }
789 }
790
791 // Calculate the resulting register value to use for the frequency.
792
793 return frequency_curve[sub_index + 284] | (octave << 10);
794 }
795
796 // Update the frequency that a voice is programmed to use.
797
UpdateVoiceFrequency(opl_voice_t * voice)798 static void UpdateVoiceFrequency(opl_voice_t *voice)
799 {
800 unsigned int freq;
801
802 // Calculate the frequency to use for this voice and update it
803 // if neccessary.
804
805 freq = FrequencyForVoice(voice);
806
807 if (voice->freq != freq)
808 {
809 OPL_WriteRegister(OPL_REGS_FREQ_1 + voice->index, freq & 0xff);
810 OPL_WriteRegister(OPL_REGS_FREQ_2 + voice->index, (freq >> 8) | 0x20);
811
812 voice->freq = freq;
813 }
814 }
815
816 // Program a single voice for an instrument. For a double voice
817 // instrument (GENMIDI_FLAG_2VOICE), this is called twice for each
818 // key on event.
819
VoiceKeyOn(opl_channel_data_t * channel,const genmidi_instr_t * instrument,unsigned int instrument_voice,unsigned int key,unsigned int volume)820 static void VoiceKeyOn(opl_channel_data_t *channel,
821 const genmidi_instr_t *instrument,
822 unsigned int instrument_voice,
823 unsigned int key,
824 unsigned int volume)
825 {
826 opl_voice_t *voice;
827
828 // Find a voice to use for this new note.
829
830 voice = GetFreeVoice();
831
832 // If there are no more voices left, we must decide what to do.
833 // If this is the first voice of the instrument, free an existing
834 // voice and use that. Otherwise, if this is the second voice,
835 // it isn't as important; just discard it.
836
837 if (voice == NULL)
838 {
839 if (instrument_voice == 0)
840 {
841 voice = ReplaceExistingVoice(channel);
842 }
843 else
844 {
845 return;
846 }
847 }
848
849 voice->channel = channel;
850 voice->key = key;
851
852 // Work out the note to use. This is normally the same as
853 // the key, unless it is a fixed pitch instrument.
854
855 if ((instrument->flags & GENMIDI_FLAG_FIXED) != 0)
856 {
857 voice->note = instrument->fixed_note;
858 }
859 else
860 {
861 voice->note = key;
862 }
863
864 // Program the voice with the instrument data:
865
866 SetVoiceInstrument(voice, instrument, instrument_voice);
867
868 // Set the volume level.
869
870 SetVoiceVolume(voice, volume);
871
872 // Write the frequency value to turn the note on.
873
874 voice->freq = 0;
875 UpdateVoiceFrequency(voice);
876 }
877
KeyOnEvent(opl_track_data_t * track,midi_event_t * event)878 static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event)
879 {
880 const genmidi_instr_t *instrument;
881 opl_channel_data_t *channel;
882 unsigned int key;
883 unsigned int volume;
884
885 /*
886 printf("note on: channel %i, %i, %i\n",
887 event->data.channel.channel,
888 event->data.channel.param1,
889 event->data.channel.param2);
890 */
891
892 if (event->data.channel.param2 == 0)
893 { // NSM
894 // i have no idea why this is the case, but it is
895 // note that you don't see this in any of the base doom/doom2 music
896 KeyOffEvent (track, event);
897 return;
898 }
899
900 // The channel.
901
902 channel = &track->channels[event->data.channel.channel];
903 key = event->data.channel.param1;
904 volume = event->data.channel.param2;
905
906 // Percussion channel (10) is treated differently.
907
908 if (event->data.channel.channel == 9)
909 {
910 if (key < 35 || key > 81)
911 {
912 return;
913 }
914
915 instrument = &percussion_instrs[key - 35];
916 }
917 else
918 {
919 instrument = channel->instrument;
920 }
921
922 // Find and program a voice for this instrument. If this
923 // is a double voice instrument, we must do this twice.
924
925 VoiceKeyOn(channel, instrument, 0, key, volume);
926
927 if ((instrument->flags & GENMIDI_FLAG_2VOICE) != 0)
928 {
929 VoiceKeyOn(channel, instrument, 1, key, volume);
930 }
931 }
932
ProgramChangeEvent(opl_track_data_t * track,midi_event_t * event)933 static void ProgramChangeEvent(opl_track_data_t *track, midi_event_t *event)
934 {
935 int channel;
936 int instrument;
937
938 // Set the instrument used on this channel.
939
940 channel = event->data.channel.channel;
941 instrument = event->data.channel.param1;
942 track->channels[channel].instrument = &main_instrs[instrument];
943
944 // TODO: Look through existing voices that are turned on on this
945 // channel, and change the instrument.
946 }
947
SetChannelVolume(opl_channel_data_t * channel,unsigned int volume)948 static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume)
949 {
950 unsigned int i;
951
952 channel->volume = volume;
953
954 // Update all voices that this channel is using.
955
956 for (i=0; i<OPL_NUM_VOICES; ++i)
957 {
958 if (voices[i].channel == channel)
959 {
960 SetVoiceVolume(&voices[i], voices[i].note_volume);
961 }
962 }
963 }
964
ControllerEvent(opl_track_data_t * track,midi_event_t * event)965 static void ControllerEvent(opl_track_data_t *track, midi_event_t *event)
966 {
967 unsigned int controller;
968 unsigned int param;
969 opl_channel_data_t *channel;
970
971 /*
972 printf("change controller: channel %i, %i, %i\n",
973 event->data.channel.channel,
974 event->data.channel.param1,
975 event->data.channel.param2);
976 */
977
978 channel = &track->channels[event->data.channel.channel];
979 controller = event->data.channel.param1;
980 param = event->data.channel.param2;
981
982 switch (controller)
983 {
984 case MIDI_CONTROLLER_MAIN_VOLUME:
985 SetChannelVolume(channel, param);
986 break;
987
988 default:
989 #ifdef OPL_MIDI_DEBUG
990 lprintf (LO_WARN, "Unknown MIDI controller type: %i\n", controller);
991 #endif
992 break;
993 }
994 }
995
996 // Process a pitch bend event.
997
PitchBendEvent(opl_track_data_t * track,midi_event_t * event)998 static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event)
999 {
1000 opl_channel_data_t *channel;
1001 unsigned int i;
1002
1003 // Update the channel bend value. Only the MSB of the pitch bend
1004 // value is considered: this is what Doom does.
1005
1006 channel = &track->channels[event->data.channel.channel];
1007 channel->bend = event->data.channel.param2 - 64;
1008
1009 // Update all voices for this channel.
1010
1011 for (i=0; i<OPL_NUM_VOICES; ++i)
1012 {
1013 if (voices[i].channel == channel)
1014 {
1015 UpdateVoiceFrequency(&voices[i]);
1016 }
1017 }
1018 }
1019
1020 // Process a meta event.
1021
MetaEvent(opl_track_data_t * track,midi_event_t * event)1022 static void MetaEvent(opl_track_data_t *track, midi_event_t *event)
1023 {
1024 switch (event->data.meta.type)
1025 {
1026 // Things we can just ignore.
1027
1028 case MIDI_META_SEQUENCE_NUMBER:
1029 case MIDI_META_TEXT:
1030 case MIDI_META_COPYRIGHT:
1031 case MIDI_META_TRACK_NAME:
1032 case MIDI_META_INSTR_NAME:
1033 case MIDI_META_LYRICS:
1034 case MIDI_META_MARKER:
1035 case MIDI_META_CUE_POINT:
1036 case MIDI_META_SEQUENCER_SPECIFIC:
1037 break;
1038
1039 // End of track - actually handled when we run out of events
1040 // in the track, see below.
1041
1042 case MIDI_META_END_OF_TRACK:
1043 break;
1044
1045 default:
1046 #ifdef OPL_MIDI_DEBUG
1047 lprintf (LO_WARN, "Unknown MIDI meta event type: %i\n",
1048 event->data.meta.type);
1049 #endif
1050 break;
1051 }
1052 }
1053
1054 // Process a MIDI event from a track.
1055
ProcessEvent(opl_track_data_t * track,midi_event_t * event)1056 static void ProcessEvent(opl_track_data_t *track, midi_event_t *event)
1057 {
1058 switch (event->event_type)
1059 {
1060 case MIDI_EVENT_NOTE_OFF:
1061 KeyOffEvent(track, event);
1062 break;
1063
1064 case MIDI_EVENT_NOTE_ON:
1065 KeyOnEvent(track, event);
1066 break;
1067
1068 case MIDI_EVENT_CONTROLLER:
1069 ControllerEvent(track, event);
1070 break;
1071
1072 case MIDI_EVENT_PROGRAM_CHANGE:
1073 ProgramChangeEvent(track, event);
1074 break;
1075
1076 case MIDI_EVENT_PITCH_BEND:
1077 PitchBendEvent(track, event);
1078 break;
1079
1080 case MIDI_EVENT_META:
1081 MetaEvent(track, event);
1082 break;
1083
1084 // SysEx events can be ignored.
1085
1086 case MIDI_EVENT_SYSEX:
1087 case MIDI_EVENT_SYSEX_SPLIT:
1088 break;
1089
1090 default:
1091 #ifdef OPL_MIDI_DEBUG
1092 lprintf (LO_WARN, "Unknown MIDI event type %i\n", event->event_type);
1093 #endif
1094 break;
1095 }
1096 }
1097
1098 static void ScheduleTrack(opl_track_data_t *track);
1099
1100 // Restart a song from the beginning.
1101
RestartSong(void)1102 static void RestartSong(void)
1103 {
1104 unsigned int i;
1105
1106 running_tracks = num_tracks;
1107
1108 // fix buggy songs that forget to terminate notes held over loop point
1109 // sdl_mixer does this as well
1110 for (i=0; i<OPL_NUM_VOICES; ++i)
1111 {
1112 if (voices[i].channel != NULL
1113 && voices[i].current_instr < percussion_instrs)
1114 {
1115 VoiceKeyOff(&voices[i]);
1116 }
1117 }
1118
1119
1120 for (i=0; i<num_tracks; ++i)
1121 {
1122 MIDI_RestartIterator(tracks[i].iter);
1123 ScheduleTrack(&tracks[i]);
1124 }
1125 }
1126
1127 // Callback function invoked when another event needs to be read from
1128 // a track.
1129
TrackTimerCallback(void * arg)1130 static void TrackTimerCallback(void *arg)
1131 {
1132 opl_track_data_t *track = arg;
1133 midi_event_t *event;
1134
1135 // Get the next event and process it.
1136
1137 if (!MIDI_GetNextEvent(track->iter, &event))
1138 {
1139 return;
1140 }
1141
1142 ProcessEvent(track, event);
1143
1144 // End of track?
1145
1146 if (event->event_type == MIDI_EVENT_META
1147 && event->data.meta.type == MIDI_META_END_OF_TRACK)
1148 {
1149 --running_tracks;
1150
1151 // When all tracks have finished, restart the song.
1152
1153 if (running_tracks <= 0 && song_looping)
1154 {
1155 RestartSong();
1156 }
1157
1158 return;
1159 }
1160
1161 // Reschedule the callback for the next event in the track.
1162
1163 ScheduleTrack(track);
1164 }
1165
ScheduleTrack(opl_track_data_t * track)1166 static void ScheduleTrack(opl_track_data_t *track)
1167 {
1168 unsigned int nticks;
1169 unsigned int ms;
1170 static int total = 0;
1171
1172 // Get the number of milliseconds until the next event.
1173
1174 nticks = MIDI_GetDeltaTime(track->iter);
1175 ms = (nticks * track->ms_per_beat) / track->ticks_per_beat;
1176 total += ms;
1177
1178 // Set a timer to be invoked when the next event is
1179 // ready to play.
1180
1181 OPL_SetCallback(ms, TrackTimerCallback, track);
1182 }
1183
1184 // Initialize a channel.
1185
InitChannel(opl_track_data_t * track,opl_channel_data_t * channel)1186 static void InitChannel(opl_track_data_t *track, opl_channel_data_t *channel)
1187 {
1188 // TODO: Work out sensible defaults?
1189
1190 channel->instrument = &main_instrs[0];
1191 channel->volume = 127;
1192 channel->bend = 0;
1193 }
1194
1195 // Start a MIDI track playing:
1196
StartTrack(const midi_file_t * file,unsigned int track_num)1197 static void StartTrack(const midi_file_t *file, unsigned int track_num)
1198 {
1199 opl_track_data_t *track;
1200 unsigned int i;
1201
1202 track = &tracks[track_num];
1203 track->iter = MIDI_IterateTrack(file, track_num);
1204 track->ticks_per_beat = MIDI_GetFileTimeDivision(file);
1205
1206 // Default is 120 bpm.
1207 // TODO: this is wrong
1208
1209 track->ms_per_beat = 500;
1210
1211 for (i=0; i<MIDI_CHANNELS_PER_TRACK; ++i)
1212 {
1213 InitChannel(track, &track->channels[i]);
1214 }
1215
1216 // Schedule the first event.
1217
1218 ScheduleTrack(track);
1219 }
1220
1221 // Start playing a mid
1222
I_OPL_PlaySong(const void * handle,int looping)1223 static void I_OPL_PlaySong(const void *handle, int looping)
1224 {
1225 const midi_file_t *file;
1226 unsigned int i;
1227
1228 if (!music_initialized || handle == NULL)
1229 {
1230 return;
1231 }
1232
1233 file = handle;
1234
1235 // Allocate track data.
1236
1237 tracks = malloc(MIDI_NumTracks(file) * sizeof(opl_track_data_t));
1238
1239 num_tracks = MIDI_NumTracks(file);
1240 running_tracks = num_tracks;
1241 song_looping = looping;
1242
1243 for (i=0; i<num_tracks; ++i)
1244 {
1245 StartTrack(file, i);
1246 }
1247 }
1248
I_OPL_PauseSong(void)1249 static void I_OPL_PauseSong(void)
1250 {
1251 unsigned int i;
1252
1253 if (!music_initialized)
1254 {
1255 return;
1256 }
1257
1258 // Pause OPL callbacks.
1259
1260 OPL_SetPaused(1);
1261
1262 // Turn off all main instrument voices (not percussion).
1263 // This is what Vanilla does.
1264
1265 for (i=0; i<OPL_NUM_VOICES; ++i)
1266 {
1267 if (voices[i].channel != NULL
1268 && voices[i].current_instr < percussion_instrs)
1269 {
1270 VoiceKeyOff(&voices[i]);
1271 }
1272 }
1273 }
1274
I_OPL_ResumeSong(void)1275 static void I_OPL_ResumeSong(void)
1276 {
1277 if (!music_initialized)
1278 {
1279 return;
1280 }
1281
1282 OPL_SetPaused(0);
1283 }
1284
I_OPL_StopSong(void)1285 static void I_OPL_StopSong(void)
1286 {
1287 unsigned int i;
1288
1289 if (!music_initialized)
1290 {
1291 return;
1292 }
1293
1294
1295 // Stop all playback.
1296
1297 OPL_ClearCallbacks();
1298
1299 // Free all voices.
1300
1301 for (i=0; i<OPL_NUM_VOICES; ++i)
1302 {
1303 if (voices[i].channel != NULL)
1304 {
1305 VoiceKeyOff(&voices[i]);
1306 ReleaseVoice(&voices[i]);
1307 }
1308 }
1309
1310 // Free all track data.
1311
1312 for (i=0; i<num_tracks; ++i)
1313 {
1314 MIDI_FreeIterator(tracks[i].iter);
1315 }
1316
1317 free(tracks);
1318
1319 tracks = NULL;
1320 num_tracks = 0;
1321
1322 }
1323
I_OPL_UnRegisterSong(const void * handle)1324 static void I_OPL_UnRegisterSong(const void *handle)
1325 {
1326 if (!music_initialized)
1327 {
1328 return;
1329 }
1330
1331 if (handle != NULL)
1332 {
1333 MIDI_FreeFile((void *) handle);
1334 }
1335 }
1336
1337 // Determine whether memory block is a .mid file
1338 /*
1339 static dbool IsMid(unsigned char *mem, int len)
1340 {
1341 return len > 4 && !memcmp(mem, "MThd", 4);
1342 }
1343 */
1344
1345 // now only takes files in MIDI format
I_OPL_RegisterSong(const void * data,unsigned len)1346 static const void *I_OPL_RegisterSong(const void *data, unsigned len)
1347 {
1348 midi_file_t *result;
1349 midimem_t mf;
1350
1351 if (!music_initialized)
1352 {
1353 return NULL;
1354 }
1355 mf.len = len;
1356 mf.pos = 0;
1357 mf.data = data;
1358
1359 // NSM: if a file has a miniscule timecode we have to not load it.
1360 // if it's 0, we'll hang in scheduling and never finish. if it's
1361 // very small but close to 0, there's probably something wrong with it
1362
1363 // this check of course isn't very accurate, but to actually get the
1364 // time numbers we have to traverse the tracks and everything
1365 if (mf.len < 100)
1366 {
1367 lprintf (LO_WARN, "I_OPL_RegisterSong: Very short MIDI (%lu bytes)\n", (long) mf.len);
1368 return NULL;
1369 }
1370
1371 result = MIDI_LoadFileSpecial (&mf);
1372
1373 if (result == NULL)
1374 {
1375 lprintf (LO_WARN, "I_OPL_RegisterSong: Failed to load MID.\n");
1376 }
1377
1378 return result;
1379 }
1380
1381
I_OPL_ShutdownMusic(void)1382 static void I_OPL_ShutdownMusic(void)
1383 {
1384 if (music_initialized)
1385 {
1386 // Stop currently-playing track, if there is one:
1387
1388 I_OPL_StopSong();
1389
1390 OPL_Shutdown();
1391
1392 // Release GENMIDI lump
1393
1394 W_UnlockLumpName("GENMIDI");
1395
1396 music_initialized = false;
1397 }
1398 }
1399
1400 // Initialize music subsystem
1401
I_OPL_InitMusic(int samplerate)1402 int I_OPL_InitMusic(int samplerate)
1403 {
1404
1405 if (!OPL_Init(samplerate))
1406 {
1407 //printf("Dude. The Adlib isn't responding.\n");
1408 return 0;
1409 }
1410
1411 // Load instruments from GENMIDI lump:
1412
1413 if (!LoadInstrumentTable())
1414 {
1415 OPL_Shutdown();
1416 return false;
1417 }
1418
1419 InitVoices();
1420
1421 tracks = NULL;
1422 num_tracks = 0;
1423 music_initialized = true;
1424
1425 return 1;
1426 }
1427
I_OPL_SynthName(void)1428 const char *I_OPL_SynthName (void)
1429 {
1430 return "opl2 synth player";
1431 }
1432
I_OPL_RenderSamples(void * dest,unsigned nsamp)1433 void I_OPL_RenderSamples (void *dest, unsigned nsamp)
1434 {
1435 OPL_Render_Samples (dest, nsamp);
1436 }
1437
1438 const music_player_t opl_synth_player =
1439 {
1440 I_OPL_SynthName,
1441 I_OPL_InitMusic,
1442 I_OPL_ShutdownMusic,
1443 I_OPL_SetMusicVolume,
1444 I_OPL_PauseSong,
1445 I_OPL_ResumeSong,
1446 I_OPL_RegisterSong,
1447 I_OPL_UnRegisterSong,
1448 I_OPL_PlaySong,
1449 I_OPL_StopSong,
1450 I_OPL_RenderSamples
1451 };
1452