From 0c3fe540e925829022d9d8aa567c2dc2bd3d33d5 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Wed, 21 Jun 2017 13:03:30 +0800 Subject: Complete rewrite of the MIDI mapper. Enforces single fluidsynth instance. Documentation update. Minor changes to make lite version work. --- core/qmpmidioutfluid.cpp | 282 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 core/qmpmidioutfluid.cpp (limited to 'core/qmpmidioutfluid.cpp') 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 +#include +#include +#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::string>> qmpMidiOutFluid::listPresets() +{ + std::vector,std::string>> ret; + std::map,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); +} -- cgit v1.2.3