aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2016-04-07 23:39:02 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2016-04-07 23:39:02 +0800
commit8f8782f43bd838e825f3792b611d27fffa90399b (patch)
tree1fbd96dd7ce061010edacf67f72f0ffb07889edf /core
parent70fd2d85c1bd6fb8732e680e8fda9d36c317c732 (diff)
downloadQMidiPlayer-8f8782f43bd838e825f3792b611d27fffa90399b.tar.xz
Lunatic Princess.
Diffstat (limited to 'core')
-rw-r--r--core/qmpmidimapperrtmidi.cpp88
-rw-r--r--core/qmpmidimappers.hpp23
-rw-r--r--core/qmpmidiplay.cpp54
-rw-r--r--core/qmpmidiplay.hpp6
4 files changed, 165 insertions, 6 deletions
diff --git a/core/qmpmidimapperrtmidi.cpp b/core/qmpmidimapperrtmidi.cpp
new file mode 100644
index 0000000..adba267
--- /dev/null
+++ b/core/qmpmidimapperrtmidi.cpp
@@ -0,0 +1,88 @@
+#include <cstdio>
+#include <cstring>
+#include <vector>
+#include "RtMidi.h"
+#include "qmpmidimappers.hpp"
+RtMidiOut* qmpMidiMapperRtMidi::dummy=NULL;
+qmpMidiMapperRtMidi::qmpMidiMapperRtMidi()
+{
+ dummy=new RtMidiOut();
+ memset(ports,0,sizeof(ports));
+}
+qmpMidiMapperRtMidi::~qmpMidiMapperRtMidi()
+{
+ delete dummy;for(int i=0;i<16;++i)if(ports[i])delete ports[i];
+}
+int qmpMidiMapperRtMidi::enumDevices()
+{
+ return dummy->getPortCount();
+}
+std::string qmpMidiMapperRtMidi::deviceName(int id)
+{
+ fprintf(stderr,"port #%d: %s\n",id,dummy->getPortName(id).c_str());
+ return dummy->getPortName(id);
+}
+int qmpMidiMapperRtMidi::deviceInit(int id)
+{
+ int i=0;for(;ports[i]&&i<16;++i);
+ if(i==16)return -1;
+ try
+ {
+ ports[i]=new RtMidiOut();
+ ports[i]->openPort(id);
+ }
+ catch(RtMidiError e)
+ {
+ printf("Device initialization failure: %s\n",e.what());
+ ports[i]=NULL;
+ return -1;
+ }
+ return i;
+}
+void qmpMidiMapperRtMidi::deviceDeinit(int iid)
+{
+ if(ports[iid]){ports[iid]->closePort();delete ports[iid];ports[iid]=NULL;}
+}
+void qmpMidiMapperRtMidi::noteOn(int iid,int ch,int key,int vel)
+{
+ if(!ports[iid])return;ch&=0x0F;
+ std::vector<unsigned char>message;
+ message.push_back(0x90|ch);
+ message.push_back(key);
+ message.push_back(vel);
+ ports[iid]->sendMessage(&message);
+}
+void qmpMidiMapperRtMidi::noteOff(int iid,int ch,int key)
+{
+ if(!ports[iid])return;ch&=0x0F;
+ std::vector<unsigned char>message;
+ message.push_back(0x80|ch);message.push_back(key);message.push_back(0);
+ ports[iid]->sendMessage(&message);
+}
+void qmpMidiMapperRtMidi::ctrlChange(int iid,int ch,int cc,int val)
+{
+ if(!ports[iid])return;ch&=0x0F;
+ std::vector<unsigned char>message;
+ message.push_back(0xB0|ch);message.push_back(cc);message.push_back(val);
+ ports[iid]->sendMessage(&message);
+}
+void qmpMidiMapperRtMidi::progChange(int iid,int ch,int val)
+{
+ if(!ports[iid])return;ch&=0x0F;
+ std::vector<unsigned char>message;
+ message.push_back(0xC0|ch);message.push_back(val);
+ ports[iid]->sendMessage(&message);
+}
+void qmpMidiMapperRtMidi::pitchBend(int iid,int ch,int val)
+{
+ if(!ports[iid])return;ch&=0x0F;
+ std::vector<unsigned char>message;
+ message.push_back(0xE0|ch);message.push_back(val&0xFF);
+ message.push_back(val>>8);ports[iid]->sendMessage(&message);
+}
+void qmpMidiMapperRtMidi::sysEx(int iid,int length,const char *data)
+{
+ if(!ports[iid])return;
+ std::vector<unsigned char>message(data,data+length);
+ ports[iid]->sendMessage(&message);
+}
diff --git a/core/qmpmidimappers.hpp b/core/qmpmidimappers.hpp
new file mode 100644
index 0000000..156caaa
--- /dev/null
+++ b/core/qmpmidimappers.hpp
@@ -0,0 +1,23 @@
+#ifndef QMPMIDIMAPPERS_H
+#define QMPMIDIMAPPERS_H
+#include "RtMidi.h"
+class qmpMidiMapperRtMidi
+{
+private:
+ RtMidiOut *ports[16];
+ static RtMidiOut *dummy;
+public:
+ qmpMidiMapperRtMidi();
+ ~qmpMidiMapperRtMidi();
+ int deviceInit(int id);
+ void deviceDeinit(int iid);
+ void noteOn(int iid,int ch,int key,int vel);
+ void noteOff(int iid,int ch,int key);
+ void ctrlChange(int iid,int ch,int cc,int val);
+ void progChange(int iid,int ch,int val);
+ void pitchBend(int iid,int ch,int val);
+ void sysEx(int iid,int length,const char* data);
+ int enumDevices();
+ std::string deviceName(int id);
+};
+#endif // QMPMIDIMAPPERS_H
diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp
index 6f69e33..e65a2a1 100644
--- a/core/qmpmidiplay.cpp
+++ b/core/qmpmidiplay.cpp
@@ -1,4 +1,5 @@
#include <cstdio>
+#include <cstring>
#include <chrono>
#include <thread>
#include <fluidsynth.h>
@@ -46,12 +47,18 @@ void CMidiPlayer::processEvent(const SEvent *e)
switch(e->type&0xF0)
{
case 0x80://Note off
- fluid_synth_noteoff(synth,e->type&0x0F,e->p1);
+ if(mappedoutput[e->type&0x0F])
+ mapper->noteOff(mappedoutput[e->type&0x0F]-1,e->type*0x0F,e->p1);
+ else
+ fluid_synth_noteoff(synth,e->type&0x0F,e->p1);
break;
case 0x90://Note on
if((mute>>(e->type&0x0F))&1)break;//muted
if(solo&&!((solo>>(e->type&0x0F))&1))break;
- fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2);
+ if(mappedoutput[e->type&0x0F])
+ mapper->noteOn(mappedoutput[e->type&0x0F]-1,e->type*0x0F,e->p1,e->p2);
+ else
+ fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2);
break;
case 0xB0://CC
if(e->p1==100)rpnid=e->p2;
@@ -61,13 +68,22 @@ void CMidiPlayer::processEvent(const SEvent *e)
if(rpnid==0)fluid_synth_pitch_wheel_sens(synth,e->type&0x0F,rpnval);
rpnid=rpnval=-1;
}
- fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2);
+ if(mappedoutput[e->type&0x0F])
+ mapper->ctrlChange(mappedoutput[e->type&0x0F]-1,e->type*0x0F,e->p1,e->p2);
+ else
+ fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2);
break;
case 0xC0://PC
- fluid_synth_program_change(synth,e->type&0x0F,e->p1);
+ if(mappedoutput[e->type&0x0F])
+ mapper->progChange(mappedoutput[e->type&0x0F]-1,e->type*0x0F,e->p1);
+ else
+ fluid_synth_program_change(synth,e->type&0x0F,e->p1);
break;
case 0xE0://PW
- fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1);
+ if(mappedoutput[e->type&0x0F])
+ mapper->pitchBend(mappedoutput[e->type&0x0F]-1,e->type*0x0F,e->p1);
+ else
+ fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1);
break;
case 0xF0://Meta/SysEx
if((e->type&0x0F)==0x0F)
@@ -94,7 +110,11 @@ void CMidiPlayer::processEvent(const SEvent *e)
if((e->type&0x0F)==0x00||(e->type&0x0F)==07)
{
int io=0;
- if(sendSysEx)fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0);
+ if(sendSysEx)
+ {
+ for(int i=0;i<16;++i)if(deviceusage[i])mapper->sysEx(i,e->p1,e->str);
+ fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0);
+ }
}
break;
}
@@ -231,6 +251,9 @@ CMidiPlayer::CMidiPlayer(bool singleInst)
{
midiFile=NULL;resumed=false;singleInstance=singleInst;
settings=NULL;synth=NULL;adriver=NULL;waitvoice=true;
+ memset(mappedoutput,0,sizeof(mappedoutput));
+ memset(deviceusage,0,sizeof(deviceusage));
+ mapper=new qmpMidiMapperRtMidi();
#ifdef _WIN32
QueryPerformanceFrequency((LARGE_INTEGER*)&pf);
#endif
@@ -238,6 +261,7 @@ CMidiPlayer::CMidiPlayer(bool singleInst)
CMidiPlayer::~CMidiPlayer()
{
if(singleInstance)fluidDeinitialize();
+ delete mapper;
}
void CMidiPlayer::playerPanic(bool reset)
{
@@ -402,3 +426,21 @@ int CMidiPlayer::getSFCount()
{return synth?fluid_synth_sfcount(synth):0;}
fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid)
{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;}
+
+qmpMidiMapperRtMidi* CMidiPlayer::getMidiMapper(){return mapper;}
+void CMidiPlayer::setChannelOutput(int ch,int devid)
+{
+ int origoutput=mappedoutput[ch];
+ int newoutput=0;
+ if(devid>0)
+ {
+ if(!deviceusage[devid-1])deviceiid[devid]=newoutput=mapper->deviceInit(devid-1);
+ ++deviceusage[deviceiid[devid]];
+ }
+ mappedoutput[ch]=devid?deviceiid[devid]+1:0;
+ if(origoutput>0)
+ {
+ --deviceusage[origoutput-1];
+ if(!deviceusage[origoutput-1])mapper->deviceDeinit(origoutput-1);
+ }
+}
diff --git a/core/qmpmidiplay.hpp b/core/qmpmidiplay.hpp
index fafd677..a7e7f88 100644
--- a/core/qmpmidiplay.hpp
+++ b/core/qmpmidiplay.hpp
@@ -5,6 +5,7 @@
#include <cstdint>
#include <cstdlib>
#include <fluidsynth.h>
+#include "qmpmidimappers.hpp"
struct SEvent
{
uint32_t iid,time,p1,p2;
@@ -69,6 +70,8 @@ class CMidiPlayer
//thread control
uint32_t tceptr,tcpaused,tcstop;
uint32_t finished,resumed;
+ qmpMidiMapperRtMidi *mapper;
+ int mappedoutput[16],deviceusage[16],deviceiid[128];
void setBit(uint16_t &n,uint16_t bn,uint16_t b);
void processEvent(const SEvent *e);
@@ -133,5 +136,8 @@ class CMidiPlayer
void pushSoundFont(const char* sf);
int getSFCount();
fluid_sfont_t* getSFPtr(int sfid);
+
+ qmpMidiMapperRtMidi* getMidiMapper();
+ void setChannelOutput(int ch,int devid);
};
#endif