Sono da anni un fan dei prodotti Telos Axia che ritengo particolarmente innovativi ed affidabili, con un ottimo rapporto qualità/prezzo.
Uno dei loro ultimi prodotti – Altus – è un mixer completamente virtuale, distribuito come container Docker il cui controllo avviene esclusivamente tramite interfaccia web.
L’idea è geniale: è in pratica possibile fare regia da qualunque dispositivo dotato di un browser (ad esempio un iPad) da qualunque parte del mondo!
La stessa cosa è fattibile con i mixer della serie Quasar ed iQx per i quali è disponibile una licenza che abilita il controllo tramite interfaccia HTML5.
L’unico problema che ho riscontrato è che alcuni speaker non riescono a rinunciare al feeling del fader fisico: ho allora sviluppato uno script Python che fa da interfaccia tra il Livewire Control Protocol e generiche superfici Midi.
Nell’esempio che segue ho utilizzato un controller Korg Nano Kontrol; di seguito i parametri da configurare:
client_socket.connect(('10.1.5.3', 4010))
Modificare questa riga con l’indirizzo del mixer che si intende controllare.
fader = {2:1,3:2,4:3,5:4,6:5,8:6,9:7,12:8,13:9}
Seguono poi delle variabili dizionario dove abbino il numero del controllo del dispositivo midi al numero del fader Axia, ad esempio sul Nano Kontrol il primo fader ha control change numero 2 mentre l’ultimo ha CC 13.
Essendo il volume un valore logaritmico ho inserito una funzione per convertire i valori lineari del midi in modo da avere una risposta più realistica al movimento dei fader.
Infine in un ciclo loop lo script riceve i comandi dal controller, se li trova nei dizionari manda il comando al mixer, altrimenti stampa il control change in modo da facilitare la configurazione. Ecco lo script completo:
import mido, socket, math
inport = mido.open_input()
client_socket = socket.socket()
# inserire qui l'ip dell'engine
client_socket.connect(('10.1.5.3', 4010))
# control number : numero del fader
fader = {2:1,3:2,4:3,5:4,6:5,8:6,9:7,12:8,13:9}
# control number : numero del tasto pfl
pfl = {23:1,24:2,25:3,26:4,27:5,28:6,29:7,30:8,31:9}
# control number : numero del tasto on/off
onoff = {33:1,34:2,35:3,36:4,37:5,38:6,39:7,40:8,41:9}
# converto valori da lin a log per un feel più fedele
def midi_to_db(midi_value, midi_min=0, midi_max=127, db_min=-100, db_max=0):
if midi_value <= midi_min:
return db_min
if midi_value >= midi_max:
return db_max
normalized = (midi_value - midi_min) / (midi_max - midi_min)
log_value = math.pow(normalized, 0.3)
db_value = db_min + (log_value * (db_max - db_min))
return round(db_value, 1)
while True:
msg = inport.receive()
# gestione fader
if msg.type == 'control_change' and msg.control in fader:
message = "SET FaCH#" + str(fader.get(msg.control)) + " Fader_Gain=" + str(midi_to_db(msg.value)) + "\n"
client_socket.send(message.encode())
print (message)
# gestione pulsanti pfl
elif msg.type == 'control_change' and msg.control in pfl and msg.value == 127:
message = "SET FaCH#" + str(pfl.get(msg.control)) + " Asg_PREV=ON\n"
client_socket.send(message.encode())
print (message)
elif msg.type == 'control_change' and msg.control in pfl and msg.value == 0:
message = "SET FaCH#" + str(pfl.get(msg.control)) + " Asg_PREV=OFF\n"
client_socket.send(message.encode())
print (message)
# gestione pulsanti on/off
elif msg.type == 'control_change' and msg.control in onoff and msg.value == 127:
message = "SET FaCH#" + str(onoff.get(msg.control)) + " ON_State=ON\n"
client_socket.send(message.encode())
print (message)
elif msg.type == 'control_change' and msg.control in onoff and msg.value == 0:
message = "SET FaCH#" + str(onoff.get(msg.control)) + " ON_State=OFF\n"
client_socket.send(message.encode())
print (message)
# se non trova cc nel dict lo stampa
else:
print (msg)