midicontrol example

This commit is contained in:
Sam 2021-09-23 04:03:08 +02:00
parent fe6a56efaa
commit dcaa716d29
5 changed files with 214 additions and 7 deletions

View File

@ -2,7 +2,7 @@
Miredis hooks to all midi devices connected and listen for events. Miredis hooks to all midi devices connected and listen for events.
Miredis can optionnaly hook to opensourced Link protocol (200+ music & videos apps) -> "/beat" & "/bpm" Miredis can optionnaly hook to opensourced Link protocol (200+ music & videos apps) -> "/beat" & "/bpm"
All events are forwarded to a redis server and an OSC server. All events are forwarded to your redis server and your OSC server.
![Clitools](https://www.teamlaser.fr/images/miredispad.png) ![Clitools](https://www.teamlaser.fr/images/miredispad.png)
@ -19,8 +19,11 @@ To enable Link :
python3 miredis.py -link python3 miredis.py -link
(for cheap midi interface midisport/midiman from audio on Linux : apt-get install midisport-firmware)
## New Features ## New Features
- Client example : midicontrol.py
- Added verbose mode -v - Added verbose mode -v
- Added redis subscribe events - Added redis subscribe events
- Added Clitools program selection mode for Launchpads - Added Clitools program selection mode for Launchpads
@ -29,6 +32,8 @@ python3 miredis.py -link
## OSC ## OSC
Following messages will be sent to an outside OSC server :
/midi/noteon midichannel note velocity /midi/noteon midichannel note velocity
/midi/noteoff midichannel note /midi/noteoff midichannel note

View File

@ -4,17 +4,18 @@
''' '''
Ableton Link with bridge to OSC & Redis alink v0.2
Ableton Link bridge to OSC & Redis
LICENCE : CC LICENCE : CC
Sam Neurohack Sam Neurohack
Get: Needs link.cpython library. Comes with some precompiled libraries.
To build it :
git clone --recursive https://github.com/gonzaloflirt/link-python.git git clone --recursive https://github.com/gonzaloflirt/link-python.git
Build:
Make sure python 3 is installed on your system. Make sure python 3 is installed on your system.
mkdir build mkdir build

View File

@ -162,7 +162,7 @@ def SendUI(oscaddress,oscargs=''):
osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort)) osclientlj.sendto(oscmsg, (TouchOSCIP, TouchOSCPort))
oscmsg.clearData() oscmsg.clearData()
except: except:
log.err('Connection to Aurora UI refused : died ?') log.err('Connection to UI refused : died ?')
pass pass
#time.sleep(0.001 #time.sleep(0.001

202
midicontrol.py Normal file
View File

@ -0,0 +1,202 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Midi controlled skeleton
v0.1.0
Needs miredis (listen to midi devices)
Licensed under GNU GPLv3
by Sam Neurohack
'''
import sys
import traceback
import argparse
import redis
import ast
argsparser = argparse.ArgumentParser(description="Midi/Redis control skeleton")
argsparser.add_argument("-c","--channel",help="Default midi channel (1)",default="1",type=str)
argsparser.add_argument("-m","--mode",help="Default running mode (33)",default="33",type=str)
args = argsparser.parse_args()
cchannel=args.channel
note = args.mode
ip = '127.0.0.1'
port = 6379
rds = redis.Redis(
host=ip,
port=port)
MidiSub = rds.pubsub()
MidiSub.subscribe("/midi/last_event")
print("Midi events subscribed")
cc = [0]*128
bpm = 120
notejump = {"33": "modeA()",
"35": "modeB()",
"44": "sys.exit(0)" # Beware
}
def MidiSubEvent():
global note
msg = MidiSub.get_message()
if msg:
message = str(msg['data'])
# Noteon change main function via notejump
if message.find('noteon') != -1:
noteon = message.split("/")
#print(noteon)
#if noteon[3] == cchannel:
if noteon[4] in notejump:
note = noteon[4]
print(notejump[note])
# Audio Redis keys continuously updated by specredis
def Current():
global data1, data2, data3
# live audio parameters from specredis.py in redis
# if data1 key like "[2.96, 1.01, 4.89, 3.29, 2.53, 2.10, 1.84, 1.66, 1.56, 1.50]"
data1redis = rds.get('levels')
data1 = ast.literal_eval(data1redis.decode('ascii'))
data1width = len(data1)
data2 = float(rds.get('spectrummax'))
data3 = float(rds.get('spectrumsum'))
# 1 CC -> 7 bits number : 0-127
# rerange end value between low high
# midifactor(ccnumber, channel, low, high, default)
def midifactor(ccnumber, channel = cchannel, low =0, high=127, default =1):
ccvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(ccnumber))
if ccvalue is not None:
return rerange(int(ccvalue), 0, 127, low, high)
else:
print('Default value returned. No midi value in redis for channel', channel, 'CC', ccnumber)
return default
# 2 CC -> 14 bits number : 0 - 16383
# rerange end value between low high
# midifactor(ccnumber, channel, low, high, default)
def midifactor14(highcc, lowcc, channel = cchannel, low =0, high=16383, default =1):
lowvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(lowcc))
highvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(highcc))
if lowvalue is not None and highcc is not None:
return rerange((int(highvalue) << 7)+ int(lowvalue), 0, 16383, low, high)
else:
print('Default value returned. No midi value in redis for channel', channel, 'CC', ccnumber)
return default
# increase or decrease value
def Encoder(ccnumber, channel = cchannel):
ccvalue = rds.get('/midi/cc/'+str(channel)+'/'+str(ccnumber))
# encoder turned to right
if ccvalue == 1:
EncoderPlusOne(ccnumber)
# encoder turned to left
if ccvalue == 127:
EncoderMinusOne(ccnumber)
def EncoderPlusOne(ccnumber):
global cc
cc[ccnumber] +=1
print(cc[ccnumber])
def EncoderMinusOne(ccnumber):
global cc
if cc[ccnumber] >0:
cc[ccnumber] -= 1
print(cc[ccnumber])
def rerange(s,a1,a2,b1,b2):
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
#
# mode A
#
def modeA():
print(midifactor(0, channel = cchannel, low =0, high=127, default =1))
pass
#
# mode B
#
def modeB():
print(midifactor14(0, 1, channel = cchannel, low =0, high=16383, default =1))
pass
#
# Main loop
#
if __name__ == "__main__":
note = "33"
running = True
try:
if (note in notejump) == False:
print('No function for that note')
sys.exit(0)
print('running', notejump[note])
while running:
# Some redis keys pull
Current()
# /noteon redis subscribe event like noteon -> change mode via eval
MidiSubEvent()
eval(notejump[str(note)])
except Exception:
print(traceback.print_exc())
except KeyboardInterrupt:
sys.exit(0)
finally:
print("End")
sys.exit(0)

View File

@ -106,7 +106,6 @@ if __name__ == '__main__':
midix.check() midix.check()
midix.loadConf() midix.loadConf()
midix.toKey("/beats","0.0") midix.toKey("/beats","0.0")
midix.toKey("/bpm",120) midix.toKey("/bpm",120)