Merge branch 'master' into feature/esfm
This commit is contained in:
commit
215c8c375a
46 changed files with 1596 additions and 829 deletions
|
|
@ -167,4 +167,8 @@ void DivEngine::setConf(String key, String value) {
|
|||
|
||||
bool DivEngine::hasConf(String key) {
|
||||
return conf.has(key);
|
||||
}
|
||||
}
|
||||
|
||||
DivConfig& DivEngine::getConfObject() {
|
||||
return conf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
case 0x82:
|
||||
return "82xx: Set panning (right channel)";
|
||||
case 0x88:
|
||||
return "88xx: Set panning (rear channels; x: left; y: right)";
|
||||
return "88xy: Set panning (rear channels; x: left; y: right)";
|
||||
break;
|
||||
case 0x89:
|
||||
return "89xx: Set panning (rear left channel)";
|
||||
|
|
@ -2188,6 +2188,13 @@ int DivEngine::getMaxVolumeChan(int ch) {
|
|||
return chan[ch].volMax>>8;
|
||||
}
|
||||
|
||||
int DivEngine::mapVelocity(int ch, float vel) {
|
||||
if (ch<0) return 0;
|
||||
if (ch>=chans) return 0;
|
||||
if (disCont[dispatchOfChan[ch]].dispatch==NULL) return 0;
|
||||
return disCont[dispatchOfChan[ch]].dispatch->mapVelocity(dispatchChanOfChan[ch],vel);
|
||||
}
|
||||
|
||||
unsigned char DivEngine::getOrder() {
|
||||
return prevOrder;
|
||||
}
|
||||
|
|
@ -3391,6 +3398,10 @@ void DivEngine::setMidiDirect(bool value) {
|
|||
midiIsDirect=value;
|
||||
}
|
||||
|
||||
void DivEngine::setMidiDirectProgram(bool value) {
|
||||
midiIsDirectProgram=value;
|
||||
}
|
||||
|
||||
void DivEngine::setMidiVolExp(float value) {
|
||||
midiVolExp=value;
|
||||
}
|
||||
|
|
@ -3459,6 +3470,12 @@ void DivEngine::rescanAudioDevices() {
|
|||
audioDevs.clear();
|
||||
if (output!=NULL) {
|
||||
audioDevs=output->listAudioDevices();
|
||||
}
|
||||
}
|
||||
|
||||
void DivEngine::rescanMidiDevices() {
|
||||
if (output!=NULL) {
|
||||
logV("re-scanning midi...");
|
||||
if (output->midiIn!=NULL) {
|
||||
midiIns=output->midiIn->listDevices();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class DivWorkPool;
|
|||
|
||||
#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "dev189"
|
||||
#define DIV_ENGINE_VERSION 189
|
||||
#define DIV_VERSION "dev190"
|
||||
#define DIV_ENGINE_VERSION 190
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
|
@ -176,16 +176,16 @@ struct DivNoteEvent {
|
|||
signed char channel;
|
||||
unsigned char ins;
|
||||
signed char note, volume;
|
||||
bool on, nop, pad1, pad2;
|
||||
DivNoteEvent(int c, int i, int n, int v, bool o):
|
||||
bool on, nop, insChange, fromMIDI;
|
||||
DivNoteEvent(int c, int i, int n, int v, bool o, bool ic=false, bool fm=false):
|
||||
channel(c),
|
||||
ins(i),
|
||||
note(n),
|
||||
volume(v),
|
||||
on(o),
|
||||
nop(false),
|
||||
pad1(false),
|
||||
pad2(false) {}
|
||||
insChange(ic),
|
||||
fromMIDI(fm) {}
|
||||
DivNoteEvent():
|
||||
channel(-1),
|
||||
ins(0),
|
||||
|
|
@ -193,8 +193,8 @@ struct DivNoteEvent {
|
|||
volume(-1),
|
||||
on(false),
|
||||
nop(true),
|
||||
pad1(false),
|
||||
pad2(false) {}
|
||||
insChange(false),
|
||||
fromMIDI(false) {}
|
||||
};
|
||||
|
||||
struct DivDispatchContainer {
|
||||
|
|
@ -415,6 +415,7 @@ class DivEngine {
|
|||
bool firstTick;
|
||||
bool skipping;
|
||||
bool midiIsDirect;
|
||||
bool midiIsDirectProgram;
|
||||
bool lowLatency;
|
||||
bool systemsRegistered;
|
||||
bool hasLoadedSomething;
|
||||
|
|
@ -701,6 +702,9 @@ class DivEngine {
|
|||
double getConfDouble(String key, double fallback);
|
||||
String getConfString(String key, String fallback);
|
||||
|
||||
// get config object
|
||||
DivConfig& getConfObject();
|
||||
|
||||
// set a config value
|
||||
void setConf(String key, bool value);
|
||||
void setConf(String key, int value);
|
||||
|
|
@ -851,6 +855,9 @@ class DivEngine {
|
|||
// get channel max volume
|
||||
int getMaxVolumeChan(int chan);
|
||||
|
||||
// map MIDI velocity to volume
|
||||
int mapVelocity(int ch, float vel);
|
||||
|
||||
// get current order
|
||||
unsigned char getOrder();
|
||||
|
||||
|
|
@ -1070,6 +1077,9 @@ class DivEngine {
|
|||
// rescan audio devices
|
||||
void rescanAudioDevices();
|
||||
|
||||
/** rescan midi devices */
|
||||
void rescanMidiDevices();
|
||||
|
||||
// set the console mode.
|
||||
void setConsoleMode(bool enable);
|
||||
|
||||
|
|
@ -1185,6 +1195,9 @@ class DivEngine {
|
|||
// set MIDI direct channel map
|
||||
void setMidiDirect(bool value);
|
||||
|
||||
// set MIDI direct program change
|
||||
void setMidiDirectProgram(bool value);
|
||||
|
||||
// set MIDI volume curve exponent
|
||||
void setMidiVolExp(float value);
|
||||
|
||||
|
|
@ -1257,6 +1270,7 @@ class DivEngine {
|
|||
firstTick(false),
|
||||
skipping(false),
|
||||
midiIsDirect(false),
|
||||
midiIsDirectProgram(false),
|
||||
lowLatency(false),
|
||||
systemsRegistered(false),
|
||||
hasLoadedSomething(false),
|
||||
|
|
|
|||
|
|
@ -6511,7 +6511,7 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) {
|
|||
if (ins->type==DIV_INS_GB) {
|
||||
w->writeText("- Game Boy parameters:\n");
|
||||
w->writeText(fmt::sprintf(" - volume: %d\n",ins->gb.envVol));
|
||||
w->writeText(fmt::sprintf(" - direction: %d\n",gbEnvDir[ins->gb.envDir?1:0]));
|
||||
w->writeText(fmt::sprintf(" - direction: %s\n",gbEnvDir[ins->gb.envDir?1:0]));
|
||||
w->writeText(fmt::sprintf(" - length: %d\n",ins->gb.envLen));
|
||||
w->writeText(fmt::sprintf(" - sound length: %d\n",ins->gb.soundLen));
|
||||
w->writeText(fmt::sprintf(" - use software envelope: %s\n",trueFalse[ins->gb.softEnv?1:0]));
|
||||
|
|
|
|||
|
|
@ -186,6 +186,17 @@ class DivPlatformOPN: public DivPlatformFMBase {
|
|||
void setCombo(bool combo) {
|
||||
useCombo=combo;
|
||||
}
|
||||
virtual int mapVelocity(int ch, float vel) {
|
||||
if (ch==csmChan) return vel*127.0;
|
||||
if (ch==adpcmBChanOffs) return vel*255.0;
|
||||
if (ch>=adpcmAChanOffs) {
|
||||
if (vel==0) return 0;
|
||||
if (vel>=1.0) return 31;
|
||||
return CLAMP(round(32.0-(56.0-log2(vel*127.0)*8.0)),0,31);
|
||||
}
|
||||
if (ch>=psgChanOffs) return round(15.0*pow(vel,0.33));
|
||||
return DivPlatformFMBase::mapVelocity(ch,vel);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ class DivPlatformFMBase: public DivDispatch {
|
|||
// -36: 2: 48
|
||||
// -42: 1: 56
|
||||
if (vel==0) return 0;
|
||||
if (vel==127) return 127;
|
||||
if (vel>=1.0) return 127;
|
||||
return CLAMP(round(128.0-(56.0-log2(vel*127.0)*8.0)),0,127);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1300,6 +1300,12 @@ DivDispatchOscBuffer* DivPlatformGenesis::getOscBuffer(int ch) {
|
|||
return oscBuf[ch];
|
||||
}
|
||||
|
||||
int DivPlatformGenesis::mapVelocity(int ch, float vel) {
|
||||
if (ch==csmChan) return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
if (ch>5) return DivPlatformOPN::mapVelocity(5,vel);
|
||||
return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformGenesis::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
|||
virtual unsigned short getPan(int chan);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
virtual int mapVelocity(int ch, float vel);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -818,6 +818,12 @@ DivDispatchOscBuffer* DivPlatformGenesisExt::getOscBuffer(int ch) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DivPlatformGenesisExt::mapVelocity(int ch, float vel) {
|
||||
if (ch>=extChanOffs+4) return DivPlatformGenesis::mapVelocity(ch-3,vel);
|
||||
if (ch>=extChanOffs) return DivPlatformGenesis::mapVelocity(extChanOffs,vel);
|
||||
return DivPlatformGenesis::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
void DivPlatformGenesisExt::reset() {
|
||||
DivPlatformGenesis::reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
|
|||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
for (int i=0; i<chans; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4;
|
||||
chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol,chan[i].std.vol.val,15);
|
||||
}
|
||||
if (chan[i].std.duty.had) {
|
||||
chan[i].noise=chan[i].std.duty.val;
|
||||
|
|
|
|||
|
|
@ -2104,6 +2104,21 @@ DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
|
|||
return oscBuf[ch];
|
||||
}
|
||||
|
||||
int DivPlatformOPL::mapVelocity(int ch, float vel) {
|
||||
if (ch==adpcmChan) return vel*255.0;
|
||||
// -0.75dB per step
|
||||
// -6: 64: 8
|
||||
// -12: 32: 16
|
||||
// -18: 16: 24
|
||||
// -24: 8: 32
|
||||
// -30: 4: 40
|
||||
// -36: 2: 48
|
||||
// -42: 1: 56
|
||||
if (vel==0) return 0;
|
||||
if (vel>=1.0) return 63;
|
||||
return CLAMP(round(64.0-(56.0-log2(vel*127.0)*8.0)),0,63);
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformOPL::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ class DivPlatformOPL: public DivDispatch {
|
|||
unsigned short getPan(int chan);
|
||||
DivChannelPair getPaired(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -962,6 +962,13 @@ DivDispatchOscBuffer* DivPlatformOPLL::getOscBuffer(int ch) {
|
|||
return oscBuf[ch];
|
||||
}
|
||||
|
||||
int DivPlatformOPLL::mapVelocity(int ch, float vel) {
|
||||
// -3dB per step
|
||||
if (vel==0) return 0;
|
||||
if (vel>=1.0) return 15;
|
||||
return CLAMP(round(16.0-(14.0-log2(vel*127.0)*2.0)),0,15);
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformOPLL::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ class DivPlatformOPLL: public DivDispatch {
|
|||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -692,6 +692,12 @@ DivDispatchOscBuffer* DivPlatformYM2203Ext::getOscBuffer(int ch) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DivPlatformYM2203Ext::mapVelocity(int ch, float vel) {
|
||||
if (ch>=extChanOffs+4) return DivPlatformOPN::mapVelocity(ch-3,vel);
|
||||
if (ch>=extChanOffs) return DivPlatformOPN::mapVelocity(extChanOffs,vel);
|
||||
return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
void DivPlatformYM2203Ext::reset() {
|
||||
DivPlatformYM2203::reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class DivPlatformYM2203Ext: public DivPlatformYM2203 {
|
|||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
|
|
|
|||
|
|
@ -767,6 +767,12 @@ DivDispatchOscBuffer* DivPlatformYM2608Ext::getOscBuffer(int ch) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DivPlatformYM2608Ext::mapVelocity(int ch, float vel) {
|
||||
if (ch>=extChanOffs+4) return DivPlatformOPN::mapVelocity(ch-3,vel);
|
||||
if (ch>=extChanOffs) return DivPlatformOPN::mapVelocity(extChanOffs,vel);
|
||||
return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
void DivPlatformYM2608Ext::reset() {
|
||||
DivPlatformYM2608::reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class DivPlatformYM2608Ext: public DivPlatformYM2608 {
|
|||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
|
|
|
|||
|
|
@ -757,6 +757,12 @@ DivDispatchOscBuffer* DivPlatformYM2610BExt::getOscBuffer(int ch) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DivPlatformYM2610BExt::mapVelocity(int ch, float vel) {
|
||||
if (ch>=extChanOffs+4) return DivPlatformOPN::mapVelocity(ch-3,vel);
|
||||
if (ch>=extChanOffs) return DivPlatformOPN::mapVelocity(extChanOffs,vel);
|
||||
return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
void DivPlatformYM2610BExt::reset() {
|
||||
DivPlatformYM2610B::reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B {
|
|||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
|
|
|
|||
|
|
@ -757,6 +757,12 @@ DivDispatchOscBuffer* DivPlatformYM2610Ext::getOscBuffer(int ch) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int DivPlatformYM2610Ext::mapVelocity(int ch, float vel) {
|
||||
if (ch>=extChanOffs+4) return DivPlatformOPN::mapVelocity(ch-3,vel);
|
||||
if (ch>=extChanOffs) return DivPlatformOPN::mapVelocity(extChanOffs,vel);
|
||||
return DivPlatformOPN::mapVelocity(ch,vel);
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::reset() {
|
||||
DivPlatformYM2610::reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
|||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
int mapVelocity(int ch, float vel);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
|
|
|
|||
|
|
@ -1376,8 +1376,15 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
pendingNotes.pop_front();
|
||||
continue;
|
||||
}
|
||||
if (note.insChange) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,note.channel,note.ins,0));
|
||||
pendingNotes.pop_front();
|
||||
continue;
|
||||
}
|
||||
if (note.on) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,note.channel,note.ins,1));
|
||||
if (!(midiIsDirect && midiIsDirectProgram && note.fromMIDI)) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,note.channel,note.ins,1));
|
||||
}
|
||||
if (note.volume>=0 && !disCont[dispatchOfChan[note.channel]].dispatch->isVolGlobal()) {
|
||||
float curvedVol=pow((float)note.volume/127.0f,midiVolExp);
|
||||
int mappedVol=disCont[dispatchOfChan[note.channel]].dispatch->mapVelocity(dispatchChanOfChan[note.channel],curvedVol);
|
||||
|
|
@ -1838,7 +1845,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
case TA_MIDI_NOTE_OFF: {
|
||||
if (chan<0 || chan>=chans) break;
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false,false,true));
|
||||
} else {
|
||||
autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
|
|
@ -1853,13 +1860,13 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
if (chan<0 || chan>=chans) break;
|
||||
if (msg.data[1]==0) {
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,-1,-1,-1,false,false,true));
|
||||
} else {
|
||||
autoNoteOff(msg.type&15,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
} else {
|
||||
if (midiIsDirect) {
|
||||
pendingNotes.push_back(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true));
|
||||
pendingNotes.push_back(DivNoteEvent(chan,ins,msg.data[0]-12,msg.data[1],true,false,true));
|
||||
} else {
|
||||
autoNoteOn(msg.type&15,ins,msg.data[0]-12,msg.data[1]);
|
||||
}
|
||||
|
|
@ -1867,7 +1874,9 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
break;
|
||||
}
|
||||
case TA_MIDI_PROGRAM: {
|
||||
// TODO: change instrument event thingy
|
||||
if (midiIsDirect && midiIsDirectProgram) {
|
||||
pendingNotes.push_back(DivNoteEvent(chan,msg.data[0],0,0,false,true,true));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue