aboutsummaryrefslogtreecommitdiff
path: root/core/qmpmidioutfluid.cpp
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2017-06-21 13:03:30 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2017-06-21 13:03:30 +0800
commit0c3fe540e925829022d9d8aa567c2dc2bd3d33d5 (patch)
treeab9ecae4def5a329b5e796839ece97f4b9c0297f /core/qmpmidioutfluid.cpp
parent64c91c7da66ba71e2bb32077680f234aba4ac65d (diff)
downloadQMidiPlayer-0c3fe540e925829022d9d8aa567c2dc2bd3d33d5.tar.xz
Complete rewrite of the MIDI mapper.
Enforces single fluidsynth instance. Documentation update. Minor changes to make lite version work.
Diffstat (limited to 'core/qmpmidioutfluid.cpp')
-rw-r--r--core/qmpmidioutfluid.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/core/qmpmidioutfluid.cpp b/core/qmpmidioutfluid.cpp
new file mode 100644
index 0000000..da3282f
--- /dev/null
+++ b/core/qmpmidioutfluid.cpp
@@ -0,0 +1,282 @@
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include "qmpmidioutfluid.hpp"
+qmpMidiOutFluid::qmpMidiOutFluid()
+{
+ settings=new_fluid_settings();
+ synth=NULL;adriver=NULL;
+}
+qmpMidiOutFluid::~qmpMidiOutFluid()
+{
+ delete_fluid_settings(settings);
+ settings=NULL;
+}
+void qmpMidiOutFluid::deviceInit()
+{
+ synth=new_fluid_synth(settings);
+ if(!synth){fputs("Error creating fluidsynth instance!",stderr);return;}
+ fluid_set_log_function(FLUID_DBG,NULL,NULL);
+ fluid_set_log_function(FLUID_INFO,NULL,NULL);
+ fluid_set_log_function(FLUID_WARN,NULL,NULL);
+ fluid_set_log_function(FLUID_ERR,fluid_default_log_function,NULL);
+ fluid_set_log_function(FLUID_PANIC,fluid_default_log_function,NULL);
+ adriver=new_fluid_audio_driver(settings,synth);
+ if(!adriver)
+ {
+ fputs("Error creating fluidsynth audio driver!",stderr);
+ delete_fluid_synth(synth);synth=NULL;
+ return;
+ }
+ fluid_synth_set_chorus(synth,FLUID_CHORUS_DEFAULT_N,FLUID_CHORUS_DEFAULT_LEVEL,
+ FLUID_CHORUS_DEFAULT_SPEED,FLUID_CHORUS_DEFAULT_DEPTH,
+ FLUID_CHORUS_DEFAULT_TYPE);
+ /*if(midiFile->std==4)
+ fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_MELODIC);
+ else if(midiFile->std==1)
+ fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM);
+ else
+ {
+ fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM);
+ fluid_synth_bank_select(synth,9,128);
+ }*/
+}
+void qmpMidiOutFluid::deviceDeinit(){deviceDeinit(false);}
+void qmpMidiOutFluid::deviceDeinit(bool freshsettings)
+{
+ if(!synth||!adriver)return;
+ delete_fluid_audio_driver(adriver);
+ delete_fluid_synth(synth);
+ synth=NULL;adriver=NULL;
+ if(freshsettings)
+ {
+ delete_fluid_settings(settings);
+ settings=new_fluid_settings();
+ }
+}
+void qmpMidiOutFluid::basicMessage(uint8_t type,uint8_t p1,uint8_t p2)
+{
+ uint8_t chan=type&0x0F;
+ switch(type&0xF0)
+ {
+ case 0x80:
+ fluid_synth_noteoff(synth,chan,p1);
+ break;
+ case 0x90:
+ if(p2)fluid_synth_noteon(synth,chan,p1,p2);
+ else fluid_synth_noteoff(synth,chan,p1);
+ break;
+ case 0xB0:
+ fluid_synth_cc(synth,chan,p1,p2);
+ break;
+ case 0xC0:
+ fluid_synth_program_change(synth,chan,p1);
+ break;
+ case 0xE0:
+ fluid_synth_pitch_bend(synth,chan,(p1|p2<<7)&0x3fff);
+ break;
+ }
+}
+void qmpMidiOutFluid::extendedMessage(uint8_t length,const char *data)
+{
+ int rlen=0;
+ fluid_synth_sysex(synth,data,length,NULL,&rlen,NULL,0);
+}
+void qmpMidiOutFluid::rpnMessage(uint8_t ch,uint16_t type,uint16_t val)
+{
+ if(type==0)fluid_synth_pitch_wheel_sens(synth,ch,val>>7);
+ else
+ {
+ fluid_synth_cc(synth,ch,0x64,type&0x7F);
+ fluid_synth_cc(synth,ch,0x65,type>>7);
+ fluid_synth_cc(synth,ch,0x06,val>>7);
+ fluid_synth_cc(synth,ch,0x26,val&0x7F);
+ }
+}
+void qmpMidiOutFluid::nrpnMessage(uint8_t ch,uint16_t type,uint16_t val)
+{
+ fluid_synth_cc(synth,ch,0x62,type&0x7F);
+ fluid_synth_cc(synth,ch,0x63,type>>7);
+ fluid_synth_cc(synth,ch,0x06,val>>7);
+ fluid_synth_cc(synth,ch,0x26,val&0x7F);
+}
+void qmpMidiOutFluid::panic(uint8_t ch)
+{
+ fluid_synth_cc(synth,ch,64,0);
+ fluid_synth_pitch_bend(synth,ch,8192);
+ fluid_synth_all_notes_off(synth,ch);
+}
+void qmpMidiOutFluid::reset(uint8_t ch)
+{
+ this->panic(ch);
+ fluid_synth_cc(synth,ch,0,0);
+ fluid_synth_cc(synth,ch,7,100);
+ fluid_synth_cc(synth,ch,10,64);
+ fluid_synth_cc(synth,ch,11,127);
+ fluid_synth_cc(synth,ch,32,0);
+ fluid_synth_pitch_wheel_sens(synth,ch,2);
+}
+void qmpMidiOutFluid::onMapped(uint8_t,int)
+{
+}
+void qmpMidiOutFluid::onUnmapped(uint8_t,int)
+{
+}
+void qmpMidiOutFluid::setOptStr(const char *opt,const char *val)
+{
+ fluid_settings_setstr(settings,opt,val);
+}
+void qmpMidiOutFluid::setOptInt(const char *opt,int val)
+{
+ fluid_settings_setint(settings,opt,val);
+}
+void qmpMidiOutFluid::setOptNum(const char *opt,double val)
+{
+ fluid_settings_setnum(settings,opt,val);
+}
+void qmpMidiOutFluid::loadSFont(const char *path)
+{
+ if(synth)fluid_synth_sfload(synth,path,1);
+}
+int qmpMidiOutFluid::getSFCount()
+{
+ return synth?fluid_synth_sfcount(synth):0;
+}
+std::vector<std::pair<std::pair<int,int>,std::string>> qmpMidiOutFluid::listPresets()
+{
+ std::vector<std::pair<std::pair<int,int>,std::string>> ret;
+ std::map<std::pair<int,int>,std::string> pmap;
+ for(int i=getSFCount()-1;i>=0;--i)
+ {
+ fluid_sfont_t* psf=fluid_synth_get_sfont(synth,i);
+ fluid_preset_t preset;
+ psf->iteration_start(psf);
+ while(psf->iteration_next(psf,&preset))
+ pmap[std::make_pair(
+ preset.get_banknum(&preset),
+ preset.get_num(&preset)
+ )]=preset.get_name(&preset);
+ }
+ for(auto i=pmap.begin();i!=pmap.end();++i)
+ ret.push_back(std::make_pair(i->first,i->second));
+ return ret;
+}
+int qmpMidiOutFluid::getPolyphone()
+{
+ return synth?fluid_synth_get_active_voice_count(synth):0;
+}
+int qmpMidiOutFluid::getMaxPolyphone()
+{
+ return synth?fluid_synth_get_polyphony(synth):0;
+}
+void qmpMidiOutFluid::setGain(double gain)
+{
+ if(settings)fluid_settings_setnum(settings,"synth.gain",gain);
+}
+void qmpMidiOutFluid::getChannelInfo(int ch,int *b, int *p, char *s)
+{
+ if(!synth)return;
+ fluid_synth_channel_info_t chinfo;
+ fluid_synth_get_channel_info(synth,ch,&chinfo);
+ *b=chinfo.bank;*p=chinfo.program;
+ strcpy(s,chinfo.name);
+}
+void qmpMidiOutFluid::getReverbPara(double *r,double *d,double *w,double *l)
+{
+ if(!synth)return;
+ *r=fluid_synth_get_reverb_roomsize(synth);
+ *d=fluid_synth_get_reverb_damp(synth);
+ *w=fluid_synth_get_reverb_width(synth);
+ *l=fluid_synth_get_reverb_level(synth);
+}
+void qmpMidiOutFluid::setReverbPara(int e,double r,double d,double w,double l)
+{
+ if(!synth)return;
+ fluid_synth_set_reverb_on(synth,e);
+ fluid_synth_set_reverb(synth,r,d,w,l);
+}
+void qmpMidiOutFluid::getChorusPara(int *fb,double *l,double *r,double *d,int *type)
+{
+ if(!synth)return;
+ *fb=fluid_synth_get_chorus_nr(synth);
+ *l=fluid_synth_get_chorus_level(synth);
+ *r=fluid_synth_get_chorus_speed_Hz(synth);
+ *d=fluid_synth_get_chorus_depth_ms(synth);
+ *type=fluid_synth_get_chorus_type(synth);
+}
+void qmpMidiOutFluid::setChorusPara(int e,int fb,double l,double r,double d,int type)
+{
+ if(!synth)return;
+ fluid_synth_set_chorus_on(synth,e);
+ fluid_synth_set_chorus(synth,fb,l,r,d,type);
+}
+
+qmpFileRendererFluid::qmpFileRendererFluid(const char *_fn,const char *_ofn)
+{
+ settings=new_fluid_settings();
+ fluid_settings_setstr(settings,"audio.file.name",_ofn);
+ fn=std::string(_fn);
+ finished=false;
+}
+qmpFileRendererFluid::~qmpFileRendererFluid()
+{
+ if(player||synth||settings)renderDeinit();
+}
+void qmpFileRendererFluid::renderInit()
+{
+ synth=new_fluid_synth(settings);
+ player=new_fluid_player(synth);
+ fluid_player_add(player,fn.c_str());
+}
+void qmpFileRendererFluid::renderDeinit()
+{
+ delete_fluid_player(player);
+ delete_fluid_synth(synth);
+ delete_fluid_settings(settings);
+ player=NULL;synth=NULL;settings=NULL;
+}
+void qmpFileRendererFluid::renderWorker()
+{
+ fluid_file_renderer_t* renderer=new_fluid_file_renderer(synth);
+ fluid_player_play(player);
+ while(fluid_player_get_status(player)==FLUID_PLAYER_PLAYING)
+ if(fluid_file_renderer_process_block(renderer)!=FLUID_OK)break;
+ delete_fluid_file_renderer(renderer);
+ finished=true;
+}
+void qmpFileRendererFluid::setOptStr(const char *opt,const char *val)
+{
+ fluid_settings_setstr(settings,opt,val);
+}
+void qmpFileRendererFluid::setOptInt(const char *opt,int val)
+{
+ fluid_settings_setint(settings,opt,val);
+}
+void qmpFileRendererFluid::setOptNum(const char *opt,double val)
+{
+ fluid_settings_setnum(settings,opt,val);
+}
+void qmpFileRendererFluid::loadSFont(const char *path)
+{
+ if(synth)fluid_synth_sfload(synth,path,1);
+}
+bool qmpFileRendererFluid::isFinished()
+{
+ return finished;
+}
+void qmpFileRendererFluid::setGain(double gain)
+{
+ if(settings)fluid_settings_setnum(settings,"synth.gain",gain);
+}
+void qmpFileRendererFluid::setReverbPara(int e,double r,double d,double w,double l)
+{
+ if(!synth)return;
+ fluid_synth_set_reverb_on(synth,e);
+ fluid_synth_set_reverb(synth,r,d,w,l);
+}
+void qmpFileRendererFluid::setChorusPara(int e,int fb,double l,double r,double d,int type)
+{
+ if(!synth)return;
+ fluid_synth_set_chorus_on(synth,e);
+ fluid_synth_set_chorus(synth,fb,l,r,d,type);
+}