Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions zyngine/zynthian_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ def setup_controller(self, chan, cc, val, maxval=127):
self.labels=maxval
self.value_max=len(maxval)-1

def set_midi_chan(self, chan):
self.midi_chan=chan

def get_ctrl_array(self):
tit=self.short_name
if self.midi_chan:
Expand Down
56 changes: 44 additions & 12 deletions zyngine/zynthian_engine_fluidsynth.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self, zyngui=None):
super().__init__(zyngui)
self.name="FluidSynth"
self.nickname="FS"
self.command=("/usr/bin/fluidsynth", "-p", "fluidsynth", "-a", "jack", "-m", "jack" ,"-g", "1", "-j", "-o", "synth.midi-bank-select", "mma", "synth.cpu-cores", "3")
self.command=("/usr/bin/fluidsynth", "-p", "fluidsynth", "-a", "jack", "-m", "jack" ,"-g", "1", "-j", "-o", "synth.midi-bank-select=mma", "-o", "synth.cpu-cores=3", "-o", "synth.polyphony=64")

self.soundfont_dirs=[
('_', os.getcwd()+"/data/soundfonts/sf2"),
Expand All @@ -79,20 +79,21 @@ def stop(self):

def add_layer(self, layer):
super().add_layer(layer)
layer.part_i=self.get_free_parts()[0]
logging.debug("ADD LAYER => PART %s" % layer.part_i)
layer.part_i=None
self.setup_router(layer)

def del_layer(self, layer):
super().del_layer(layer)
self.set_all_midi_routes()
if layer.part_i is not None:
self.set_all_midi_routes()
self.unload_unused_soundfonts()

# ---------------------------------------------------------------------------
# MIDI Channel Management
# ---------------------------------------------------------------------------

def set_midi_chan(self, layer):
self.set_all_midi_routes()
self.setup_router(layer)

# ---------------------------------------------------------------------------
# Bank Management
Expand All @@ -113,7 +114,7 @@ def get_preset_list(self, bank):
logging.info("Getting Preset List for %s" % bank[2])
preset_list=[]
sfi=self.soundfont_index[bank[0]]
lines=self.proc_cmd("inst %d" % sfi)
lines=self.proc_cmd("inst %d" % sfi, 10)
for f in lines:
try:
prg=int(f[4:7])
Expand All @@ -136,7 +137,6 @@ def set_preset(self, layer, preset):
midi_prg=preset[1][2]
logging.debug("Set Preset => Layer: %d, SoundFont: %d, Bank: %d, Program: %d" % (layer.part_i,sfi,midi_bank,midi_prg))
self.proc_cmd("select %d %d %d %d" % (layer.part_i,sfi,midi_bank,midi_prg))
self.set_all_midi_routes()
else:
logging.warning("Can't set Instrument before loading SoundFont")

Expand All @@ -158,6 +158,12 @@ def load_soundfont(self, sf):
self.soundfont_count=self.soundfont_count+1
logging.info("Load SoundFont => %s (%d)" % (sf,self.soundfont_count))
self.proc_cmd("load \"%s\"" % sf, 20)

# Reselect presets for all layers to prevent instrument change
for layer in self.layers:
if layer.preset_info:
self.set_preset(layer, layer.preset_info)

self.soundfont_index[sf]=self.soundfont_count
return self.soundfont_count

Expand All @@ -169,14 +175,28 @@ def set_midi_channel(self, layer):
if layer.part_i is not None:
liblo.send(self.osc_target, "/part%d/Prcvchn" % layer.part_i, layer.get_midi_chan())

def setup_router(self, layer):
if layer.part_i is not None:
# Clear and recreate all routes if the routes for this layer were set already
self.set_all_midi_routes()
else:
# No need to clear routes if there is the only layer to add
try:
layer.part_i=self.get_free_parts()[0]
logging.debug("ADD LAYER => PART %s" % layer.part_i)
except:
logging.error("ADD LAYER => NO FREE PARTS!")
self.set_layer_midi_routes(layer)

def unload_unused_soundfonts(self):
#Make a copy of soundfont index and remove used soundfonts
sf_unload=copy.copy(self.soundfont_index)
for layer in self.layers:
bi=layer.bank_info
if bi[2] and bi[0] in sf_unload:
#print("Skip "+bi[0]+"("+str(sf_unload[bi[0]])+")")
del sf_unload[bi[0]]
if bi is not None:
if bi[2] and bi[0] in sf_unload:
#print("Skip "+bi[0]+"("+str(sf_unload[bi[0]])+")")
del sf_unload[bi[0]]
#Then, remove the remaining ;-)
for sf,sfi in sf_unload.items():
logging.info("Unload SoundFont => %d" % sfi)
Expand All @@ -186,8 +206,20 @@ def unload_unused_soundfonts(self):
def set_layer_midi_routes(self, layer):
if layer.part_i is not None:
midich=layer.get_midi_chan()
self.proc_cmd("router_begin note\nrouter_chan %d %d 0 %d\nrouter_end" % (midich,midich,layer.part_i))
self.proc_cmd("router_begin cc\nrouter_chan %d %d 0 %d\nrouter_end" % (midich,midich,layer.part_i))
self.proc_cmd(
"router_begin note\n"
"router_chan {0} {0} 0 {1}\n"
"router_end\n"
"router_begin cc\n"
"router_chan {0} {0} 0 {1}\n"
"router_end\n"
"router_begin pbend\n"
"router_chan {0} {0} 0 {1}\n"
"router_end\n"
"router_begin prog\n"
"router_chan {0} {0} 0 {1}\n"
"router_end".format(midich, layer.part_i)
)

def set_all_midi_routes(self):
self.clear_midi_routes()
Expand Down
Loading