Added support for DMX and MSOPL true stereo extension.

CQTexperiment
Chris Moeller 2016-06-19 13:05:30 -07:00
parent 597a342838
commit 03e7b666ae
10 changed files with 163 additions and 32 deletions

View File

@ -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];

View File

@ -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;

View File

@ -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;
};

View File

@ -29,6 +29,10 @@
#include <string.h>
#include "opl3.h"
// Extended panning mode
#define _USE_MATH_DEFINES
#include <math.h>
#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

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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);
};