def test_sent_directly(self): from alsamidi import pitchbendevent data = (1, 0, 9) expected = (13, 1, 0, 253, (0, 0), (0, 0), (0, 0), data) self.assertEqual(expected, pitchbendevent(1, 9))
def test_scheduled(self): from alsamidi import pitchbendevent data = (1, 0, 9) expected = (13, 1, 0, 0, (1, 0), (0, 0), (0, 0), data) self.assertEqual(expected, pitchbendevent(1, 9, 1000))
def MidimanToYoshiRouter_Poll(self): ' Router, worker, poll often, so we do not have to use threads ;)' if not self.mDev.Poll(): return False # no midi events, nothing processed #print('got a midi event!') pkt = self.mDev.ReadMidi() # read only 1 message at a time if pkt == None: # ignore bogus(alsaseq giving 3 odd pkts per sec) return True # processed something m_b0 = pkt[0] # rx_ch | midi_ctrl m_b1 = pkt[1] # note or param m_b2 = pkt[2] # velocity or value rx_ch = m_b0 & 0xf # The channel in lower first nibble tx_ch = self.mChannel # send channel, send on channel we select if (m_b0 & 0xf0) == 0xb0: # CC control message upper nibble idxEffectKnob = -1 if m_b1 == KNOB0_CC: idxEffectKnob = 0 if m_b1 == KNOB1_CC: idxEffectKnob = 1 if m_b1 == KNOB2_CC: idxEffectKnob = 2 if m_b1 == KNOB3_CC: idxEffectKnob = 3 if idxEffectKnob >= 0: # knob 0-3 change CC event? # map them to the 4 yoshi system effects 0 level control effect_num = 4 # system effect(4=system, 8=insert) effect_index = idxEffectKnob # effect index self.last_sys_effect = effect_index if self.verbose & 1: map_desc = 'system effect level(%d)= %d' % (effect_index+1, m_b2) msb_effect_ctrl = 0 # level(volume, dry/wet) cc_data = m_b2 # route CC data value to new use self.Send_NRPN(tx_ch, effect_num, effect_index, msb_effect_ctrl, cc_data) if self.verbose & 1: print('map CC %d %d to: ' % (m_b1, m_b2) + map_desc) elif m_b1 == KNOB4_CC: if self.verbose & 1: map_desc = ' master PAN CC-10= %d' % (m_b2) self.mDev.Write([0xb0 | tx_ch, 10, m_b2]) # route to CC-10 PAN(master) if self.verbose & 1: print('map CC-%d %d to PAN CC-10:' % (m_b1, m_b2) + map_desc) elif m_b1 == KNOB5_CC: # this one routes pan based on last first 4 knobs used. # routes pan to that system effect. effect_num = 4 # system effect(4=system, 8=insert) effect_index = self.last_sys_effect # effect index, last vol chged above if self.verbose & 1: map_desc = ' Effect Pan, System(%d)= %d' % (effect_index+1, m_b2) msb_effect_ctrl = 1 # Pan cc_data = m_b2 # route CC data value to new use self.Send_NRPN(tx_ch, effect_num, effect_index, msb_effect_ctrl, cc_data) if self.verbose & 1: print('map CC %d %d to: ' % (m_b1, m_b2) + map_desc) elif m_b1 == KNOB6_CC: if self.verbose & 1: map_desc = 'master Yoshi-Portamento CC-65= %d' % (m_b2) # This is digital on/off, > 64 is on, less off self.mDev.Write([0xb0 | tx_ch, 65, m_b2]) # route to CC-65 Yoshi portamento if self.verbose & 1: print('map CC-%d %d to: ' % (m_b1, m_b2) + map_desc) elif m_b1 == KNOB7_CC: # yoshi expression cc-11, seems like same as master volume? #map_desc = 'master Yoshi-Expression CC-11= %d' % (m_b2) #mOut.Write([0xb0 | tx_ch, 11, m_b2]) # route to CC-11 Yoshi portamento if self.verbose & 1: map_desc = 'master Yoshi-Sustain CC-64= %d' % (m_b2) self.mDev.Write([0xb0 | tx_ch, 64, m_b2]) # route to CC-11 Yoshi sustain? if self.verbose & 1: print('map CC-%d %d to: ' % (m_b1, m_b2) + map_desc) else: if m_b1 == 1: # mod wheel if MODWHEEL_BANKPROG_KEY_FEATURE: # mod wheel escape for setting bank/prog selection. # we save last mod value to try out using to set # bank/prog as escape sequence - push mod up > 100 # then press a key, then pull mod down < 100 # kludgy, don't think I like it very much, but.. self.last_modwheel = m_b2 if self.last_modwheel > 100: if self.verbose & 2: pr('Filter Mod-Wheel %d' % (self.last_modwheel)) return True # processed, filter out if MODWHEEL_TO_PITCH_FEATURE: # mod wheel convert to differential pitch modulation # make it do what pitch wheel does, but without dead middle spot diff_mod = m_b2 - self.last_modwheel self.last_modwheel = m_b2 # pitch value see from -8192 to 8191 self.virtual_pitchval += (diff_mod * 64) if self.virtual_pitchval > 8191: self.virtual_pitchval = 8191 if self.virtual_pitchval < -8192: self.virtual_pitchval = -8192 ev = alsamidi.pitchbendevent(tx_ch, self.virtual_pitchval) if self.verbose & 4: print('made:') print(ev) fixed_ev = (13,0,0,253, (0,0), (0,0), (0,0), (0,0,0, 0,0, self.virtual_pitchval)) ev = fixed_ev if self.verbose & 4: print('fixed:') print(ev) #self.mDev.Write(ev) # send out as pitch wheel control alsaseq.output(ev) # put out a pitch wheel change based on mod wheel change if self.verbose & 2: pr('Filter Mod-Wheel %d, to pitch %d bend' % (self.last_modwheel, self.virtual_pitchval)) return True # processed, filter out if self.pass_thru: if self.verbose & 2: desc = self.mDev.SummaryCC_Desc(m_b1, m_b2) print('pass thru CC event:' + desc) #self.mDev.WriteAlsaEvent(alsa_event) alsaseq.outlast((tx_ch | 0x10, 0,0,0)) # modify first(channel) elif (m_b0 & 0xf0) == 0x90: if self.verbose & 2: print('ch:%d NoteOff:%d Vel:%d' % (rx_ch, m_b1, m_b2)) self.mDev.Write([0x90 | tx_ch, m_b1, m_b2]) elif (m_b0 & 0xf0) == 0x80: if self.verbose & 2: print('ch:%d NoteOn:%d Vel:%d' % (rx_ch, m_b1, m_b2)) if MODWHEEL_BANKPROG_KEY_FEATURE: if self.last_modwheel > 100: # using top of modwheel to set program(12 choices) if m_b2 != 0: # velocity: off (only do when key on) self.key_select = m_b1 % 12 # C-B, 12 choices, any octave self.ProgBankListSelect(self.key_select) if self.verbose & 2: pr('Filter Prog Key') return True # processed, don't pass thru, filter if MODWHEEL_TO_PITCH_FEATURE: if self.virtual_pitchval != 0: self.virtual_pitchval = 0 # reset it and send out ev = alsamidi.pitchbendevent(tx_ch, self.virtual_pitchval) #fixed_ev = (13,0,0,253, (0,0), (28,0), (130,0), (0,0,0, 0,0,0)) ev = fixed_ev #self.mDev.Write(ev) # send out as pitch wheel control self.mDev.WriteAlsaEvent(ev) #alsaseq.output(ev) # put out a pitch wheel change based on mod wheel change if self.verbose & 2: pr('RESET Filter Mod-Wheel %d, to pitch %d bend' % (self.last_modwheel, self.virtual_pitchval)) if self.pass_thru: if self.verbose & 2: print('pass thru noteon') alsaseq.outlast((tx_ch | 0x10, 0,0,0)) # modify first(channel) else: if self.verbose & 1: print('Unhandled event ch:%d Cmd:%d Vel:%d' % (rx_ch, m_b1, m_b2)) if self.pass_thru: if self.verbose & 2: print('pass thru event') #self.mDev.WriteAlsaEvent(alsa_event) #self.mDev.Write([0x80 | tx_ch, m_b1, m_b2]) alsaseq.outlast((tx_ch | 0x10, 0,0,0)) # modify first(channel) return True # processed something