From 03e7b666ae30d6051f7a33f280661b3111bea601 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Sun, 19 Jun 2016 13:05:30 -0700 Subject: [PATCH] Added support for DMX and MSOPL true stereo extension. --- Plugins/MIDI/MIDI/MIDIDecoder.mm | 11 ++- Plugins/MIDI/MIDI/MSPlayer.cpp | 8 ++- Plugins/MIDI/MIDI/MSPlayer.h | 2 + Plugins/MIDI/MIDI/fmopl3lib/opl3.cpp | 46 +++++++++++- Plugins/MIDI/MIDI/fmopl3lib/opl3.h | 2 + Plugins/MIDI/MIDI/interface.h | 2 +- .../MIDI/MIDI/synthlib_doom/i_oplmusic.cpp | 72 ++++++++++++++----- Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.h | 6 +- Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.cpp | 41 ++++++++--- Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.h | 5 +- 10 files changed, 163 insertions(+), 32 deletions(-) diff --git a/Plugins/MIDI/MIDI/MIDIDecoder.mm b/Plugins/MIDI/MIDI/MIDIDecoder.mm index 935f28642..126d8b2b2 100755 --- a/Plugins/MIDI/MIDI/MIDIDecoder.mm +++ b/Plugins/MIDI/MIDI/MIDIDecoder.mm @@ -149,6 +149,8 @@ static OSType getOSType(const char * in_) msplayer->set_synth(0); msplayer->set_bank([[plugin substringFromIndex:4] intValue]); + + msplayer->set_extp(1); msplayer->setSampleRate( 44100 ); } @@ -160,7 +162,9 @@ static OSType getOSType(const char * in_) msplayer->set_synth(1); msplayer->set_bank([[plugin substringFromIndex:5] intValue]); - + + msplayer->set_extp(1); + msplayer->setSampleRate( 44100 ); } else @@ -318,6 +322,11 @@ static OSType getOSType(const char * in_) player = NULL; } +- (void)dealloc +{ + [self close]; +} + + (NSArray *)fileTypes { return [NSArray arrayWithObjects:@"mid", @"midi", @"kar", @"rmi", @"mids", @"mds", @"hmi", @"hmp", @"mus", @"xmi", @"lds", nil]; diff --git a/Plugins/MIDI/MIDI/MSPlayer.cpp b/Plugins/MIDI/MIDI/MSPlayer.cpp index c2aea8208..9b5bc8ad4 100644 --- a/Plugins/MIDI/MIDI/MSPlayer.cpp +++ b/Plugins/MIDI/MIDI/MSPlayer.cpp @@ -25,6 +25,12 @@ void MSPlayer::set_bank(unsigned int bank_id) this->bank_id = bank_id; } +void MSPlayer::set_extp(unsigned int extp) +{ + shutdown(); + this->extp = extp; +} + void MSPlayer::send_event(uint32_t b) { if (!(b & 0x80000000)) @@ -74,7 +80,7 @@ bool MSPlayer::startup() if (!synth) return false; - if (!synth->midi_init((unsigned int)uSampleRate, bank_id)) + if (!synth->midi_init((unsigned int)uSampleRate, bank_id, extp)) return false; return true; diff --git a/Plugins/MIDI/MIDI/MSPlayer.h b/Plugins/MIDI/MIDI/MSPlayer.h index eaa391e6a..3a51e2a34 100644 --- a/Plugins/MIDI/MIDI/MSPlayer.h +++ b/Plugins/MIDI/MIDI/MSPlayer.h @@ -18,6 +18,7 @@ public: void set_synth(unsigned int synth); void set_bank(unsigned int bank); + void set_extp(unsigned int extp); typedef void (*enum_callback)(unsigned int synth, unsigned int bank, const char * name); @@ -33,6 +34,7 @@ protected: private: unsigned int synth_id; unsigned int bank_id; + unsigned int extp; midisynth * synth; }; diff --git a/Plugins/MIDI/MIDI/fmopl3lib/opl3.cpp b/Plugins/MIDI/MIDI/fmopl3lib/opl3.cpp index 6ee92b3f0..c074d7c8c 100755 --- a/Plugins/MIDI/MIDI/fmopl3lib/opl3.cpp +++ b/Plugins/MIDI/MIDI/fmopl3lib/opl3.cpp @@ -29,6 +29,10 @@ #include #include "opl3.h" +// Extended panning mode +#define _USE_MATH_DEFINES +#include + #define RSM_FRAC 10 // Channel types @@ -933,7 +937,10 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) { OPL3_ChannelSetupAlg(channel); } - if (channel->chip->newm) + if (channel->chip->extp) + { + } + else if (channel->chip->newm) { channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; @@ -1120,6 +1127,17 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) } chip->mixbuff[0] = 0; + if (chip->extp) + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[0] += (Bit16s)(accm * chip->channel[ii].cha / 65535); + } + else for (ii = 0; ii < 18; ii++) { accm = 0; @@ -1159,6 +1177,17 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) } chip->mixbuff[1] = 0; + if (chip->extp) + for (ii = 0; ii < 18; ii++) + { + accm = 0; + for (jj = 0; jj < 4; jj++) + { + accm += *chip->channel[ii].out[jj]; + } + chip->mixbuff[1] += (Bit16s)(accm * chip->channel[ii].chb / 65535); + } + else for (ii = 0; ii < 18; ii++) { accm = 0; @@ -1276,6 +1305,21 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) case 0x05: chip->newm = v & 0x01; break; + + case 0x06: + chip->extp = v == 0x17; + break; + case 0x07: + if (chip->extp) + chip->panch = v; + break; + case 0x08: + if (chip->extp && chip->panch < 18) + { + chip->channel[chip->panch].cha = (Bit16u)(cos((float)v * (M_PI / 2.0f / 255.0f)) * 65535.0f); + chip->channel[chip->panch].chb = (Bit16u)(sin((float)v * (M_PI / 2.0f / 255.0f)) * 65535.0f); + } + break; } } else diff --git a/Plugins/MIDI/MIDI/fmopl3lib/opl3.h b/Plugins/MIDI/MIDI/fmopl3lib/opl3.h index c100e659f..d263798ea 100755 --- a/Plugins/MIDI/MIDI/fmopl3lib/opl3.h +++ b/Plugins/MIDI/MIDI/fmopl3lib/opl3.h @@ -89,6 +89,8 @@ struct _opl3_chip { opl3_slot slot[36]; Bit16u timer; Bit8u newm; + Bit8u extp; + Bit8u panch; Bit8u nts; Bit8u rhy; Bit8u vibpos; diff --git a/Plugins/MIDI/MIDI/interface.h b/Plugins/MIDI/MIDI/interface.h index 9ee89df01..701dc5ee1 100755 --- a/Plugins/MIDI/MIDI/interface.h +++ b/Plugins/MIDI/MIDI/interface.h @@ -25,7 +25,7 @@ public: virtual const char * midi_synth_name(void) = 0; virtual unsigned int midi_bank_count(void) = 0; virtual const char * midi_bank_name(unsigned int bank) = 0; - virtual int midi_init(unsigned int rate, unsigned int bank) = 0; + virtual int midi_init(unsigned int rate, unsigned int bank, unsigned int extp) = 0; virtual void midi_write(unsigned int data) = 0; virtual void midi_generate(signed short *buffer, unsigned int length) = 0; }; diff --git a/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.cpp b/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.cpp index cf365dc79..1c083740d 100755 --- a/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.cpp +++ b/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.cpp @@ -93,6 +93,11 @@ void DoomOPL::OPL_InitRegisters(bool opl_new) { OPL_WriteRegister(OPL_REG_NEW_MODE, 0x01); } + + if (opl_extp) + { + OPL_WriteRegister(0x106, 0x17); + } } // Load instrument table from GENMIDI lump: @@ -307,6 +312,16 @@ void DoomOPL::SetVoicePan(opl_voice_t *voice, unsigned int pan) opl_voice->feedback | pan); } +void DoomOPL::SetVoicePanEx(opl_voice_t *voice, unsigned int pan) +{ + const genmidi_voice_t *opl_voice; + + opl_voice = &voice->current_instr->voices[voice->current_instr_voice]; + + OPL_WriteRegister(0x107, voice->index + (voice->array * 9 / 256)); + OPL_WriteRegister(0x108, pan * 2); +} + // Initialize the voice table and freelist void DoomOPL::InitVoices(void) @@ -583,6 +598,11 @@ void DoomOPL::VoiceKeyOn(opl_channel_data_t *channel, // Set the volume level. SetVoiceVolume(voice, volume); + + // Set the extended panning, if necessary + + if (opl_extp) + SetVoicePanEx(voice, channel->panex); // Write the frequency value to turn the note on. @@ -712,26 +732,43 @@ void DoomOPL::SetChannelPan(opl_channel_data_t *channel, unsigned int pan) if (opl_new) { - if (pan >= 96) + if (opl_extp) { - reg_pan = 0x10; - } - else if (pan <= 48) - { - reg_pan = 0x20; + if (channel->panex != pan) + { + channel->panex = pan; + for (i = 0; i < voice_alloced_num; i++) + { + if (voice_alloced_list[i]->channel == channel) + { + SetVoicePanEx(voice_alloced_list[i], pan); + } + } + } } else { - reg_pan = 0x30; - } - if (channel->pan != reg_pan) - { - channel->pan = reg_pan; - for (i = 0; i < voice_alloced_num; i++) + if (pan >= 96) { - if (voice_alloced_list[i]->channel == channel) + reg_pan = 0x10; + } + else if (pan <= 48) + { + reg_pan = 0x20; + } + else + { + reg_pan = 0x30; + } + if (channel->pan != reg_pan) + { + channel->pan = reg_pan; + for (i = 0; i < voice_alloced_num; i++) { - SetVoicePan(voice_alloced_list[i], reg_pan); + if (voice_alloced_list[i]->channel == channel) + { + SetVoicePan(voice_alloced_list[i], reg_pan); + } } } } @@ -881,10 +918,11 @@ void DoomOPL::InitChannel(opl_channel_data_t *channel) channel->instrument = &main_instrs[0]; channel->volume = 127; channel->pan = 0x30; + channel->panex = 64; channel->bend = 0; } -int DoomOPL::midi_init(unsigned int rate, unsigned int bank) +int DoomOPL::midi_init(unsigned int rate, unsigned int bank, unsigned int extp) { /*char *env;*/ unsigned int i; @@ -894,7 +932,9 @@ int DoomOPL::midi_init(unsigned int rate, unsigned int bank) { return 0; } - + + opl_extp = !!extp; + memset(channels, 0, sizeof(channels)); main_instrs = NULL; percussion_instrs = NULL; diff --git a/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.h b/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.h index df82f67a4..065ec110a 100755 --- a/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.h +++ b/Plugins/MIDI/MIDI/synthlib_doom/i_oplmusic.h @@ -116,7 +116,7 @@ typedef struct // Pan value - int pan; + int pan, panex; // Pitch bend value: @@ -347,6 +347,7 @@ private: unsigned int voice_alloced_num = 0; bool opl_new; + bool opl_extp; unsigned int opl_voices; void OPL_WriteRegister(unsigned int reg, unsigned char data); @@ -357,6 +358,7 @@ private: void SetVoiceInstrument(opl_voice_t *voice, const genmidi_instr_t *instr, unsigned int instr_voice); void SetVoiceVolume(opl_voice_t *voice, unsigned int volume); void SetVoicePan(opl_voice_t *voice, unsigned int pan); + void SetVoicePanEx(opl_voice_t *voice, unsigned int pan); void InitVoices(void); void VoiceKeyOff(opl_voice_t *voice); opl_channel_data_t *TrackChannelForEvent(unsigned char channel_num); @@ -379,7 +381,7 @@ public: const char * midi_synth_name(void); unsigned int midi_bank_count(void); const char * midi_bank_name(unsigned int bank); - int midi_init(unsigned int rate, unsigned int bank); + int midi_init(unsigned int rate, unsigned int bank, unsigned int extp); void midi_write(unsigned int data); void midi_generate(signed short *buffer, unsigned int length); }; diff --git a/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.cpp b/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.cpp index 5742e8c65..85d18fe67 100755 --- a/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.cpp +++ b/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.cpp @@ -223,6 +223,12 @@ void OPL3MIDI::opl_midikeyon(opl_channel *channel, byte note, opl_timbre *timbre opl_writereg(OPL_FNUM + voice->num, freqpitched & 0xff); opl_writereg(OPL_FEEDBACK + voice->num, fb); opl_writereg(OPL_BLOCK + voice->num, (freqpitched >> 8) | 0x20); + + if (opl_extp) + { + opl_writereg(0x107, (voice->num & 0xFF) + ((voice->num / 256) * 9)); + opl_writereg(0x108, channel->panex * 2); + } voice->freq = freq; voice->freqpitched = freqpitched; @@ -305,6 +311,12 @@ void OPL3MIDI::opl_updatevolpan(opl_channel *channel) opl_writereg(OPL_TL + opl_voices[i].car, carvol); opl_writereg(OPL_FEEDBACK + opl_voices[i].num, opl_voices[i].timbre->fb & channel->pan); + + if (opl_extp) + { + opl_writereg(0x107, (opl_voices[i].num & 0xFF) + ((opl_voices[i].num & 0x100) * 9 / 256)); + opl_writereg(0x108, channel->panex * 2); + } } } } @@ -317,17 +329,24 @@ void OPL3MIDI::opl_updatevol(opl_channel *channel, byte vol) void OPL3MIDI::opl_updatepan(opl_channel *channel, byte pan) { - if (pan < 48) + if (opl_extp) { - channel->pan = 0xdf; - } - else if(pan > 80) - { - channel->pan = 0xef; + channel->panex = pan; } else { - channel->pan = 0xff; + if (pan < 48) + { + channel->pan = 0xdf; + } + else if(pan > 80) + { + channel->pan = 0xef; + } + else + { + channel->pan = 0xff; + } } opl_updatevolpan(channel); } @@ -414,7 +433,7 @@ void OPL3MIDI::opl_midipitchbend(opl_channel *channel, byte parm1, byte parm2) } -int OPL3MIDI::midi_init(unsigned int rate, unsigned int bank) +int OPL3MIDI::midi_init(unsigned int rate, unsigned int bank, unsigned int extp) { uint32_t i; @@ -425,6 +444,11 @@ int OPL3MIDI::midi_init(unsigned int rate, unsigned int bank) } opl_opl3mode = true; + + opl_extp = !!extp; + + if (opl_extp) + opl_writereg(0x106, 0x17); opl_writereg(OPL_LSI, 0x00); opl_writereg(OPL_TIMER, 0x60); @@ -489,6 +513,7 @@ int OPL3MIDI::midi_init(unsigned int rate, unsigned int bank) opl_channels[i].pitch = 0; opl_channels[i].volume = 0; opl_channels[i].pan = 0xff; + opl_channels[i].panex = 64; opl_channels[i].sustained = false; } diff --git a/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.h b/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.h index 966f1db61..2fb2a35a1 100755 --- a/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.h +++ b/Plugins/MIDI/MIDI/synthlib_opl3w/opl3midi.h @@ -68,7 +68,7 @@ typedef struct opl_timbre *timbre; int32_t pitch; uint32_t volume; - uint32_t pan; + uint32_t pan, panex; bool sustained; } opl_channel; @@ -91,6 +91,7 @@ class OPL3MIDI : public midisynth { private: fm_chip *opl_chip; bool opl_opl3mode; + bool opl_extp; uint32_t opl_voice_num; @@ -125,7 +126,7 @@ public: const char *midi_synth_name(void); unsigned int midi_bank_count(void); const char * midi_bank_name(unsigned int bank); - int midi_init(unsigned int rate, unsigned int bank); + int midi_init(unsigned int rate, unsigned int bank, unsigned int extp); void midi_write(unsigned int data); void midi_generate(signed short *buffer, unsigned int length); };