underbridge/underbridge.py

316 lines
9.5 KiB
Python
Raw Normal View History

2022-03-28 17:37:27 +02:00
# Underbridge OP-Z multichannel exporter
# Copyright 2022 Thomas Herrmann Email: herrmann@raise-uav.com
2022-03-28 13:02:05 +02:00
import mido
import pyaudio
import wave
from tkinter import *
from tkinter import filedialog as fd
import time
import threading
import os
loop_time = 0
inport = 0
outport = 0
path = 0
folder = 0
2022-03-28 15:01:27 +02:00
pattern_nr = 0
2022-03-28 13:02:05 +02:00
j = 0
mode_select=0
addsec = 0
2022-03-28 15:01:27 +02:00
projectpath = 0
2022-03-28 17:37:27 +02:00
cancel = 0
2022-03-28 15:01:27 +02:00
2022-03-28 13:02:05 +02:00
2022-03-28 17:37:27 +02:00
def getMIDIDevice():
2022-03-28 13:02:05 +02:00
pass
def getBPM():
inport= mido.open_input('OP-Z:OP-Z MIDI 1 20:0')
msg = inport.poll()
2022-03-28 17:37:27 +02:00
#print(msg)
2022-03-28 13:02:05 +02:00
def setLoop():
global loop_time
bpm = bpm_input.get()
bar = bar_input.get()
addsec = add_sec.get()
loop_time = (240 / int(bpm) * int(bar)) + int(addsec)
print("Loop time set!")
displaymsg.set("BPM Set!")
return time
def setParam():
setLoop()
2022-03-28 15:01:27 +02:00
#mode = mode_select.get()
#if mode == 2:
# projnr = project_input.get()
# setProject(projnr)
2022-03-28 13:02:05 +02:00
def openMidi():
global outport
outport= mido.open_output('OP-Z:OP-Z MIDI 1 20:0')
print(outport)
def setProject(projnr):
global outport
msg= mido.Message('program_change',song= projnr, program = 1)
outport.send(msg)
def muteAll():
global outport
for i in range (0,15):
msg = mido.Message('control_change',control= 53, channel= i, value=1)
outport.send(msg)
def setSolo(chn):
global outport
msg = mido.Message('control_change',control= 53, channel= chn, value=0)
outport.send(msg)
def start_MIDI():
global outport
msg = mido.Message('start')
outport.send(msg)
displaymsg.set("Playback started")
def stop_MIDI():
global outport
msg = mido.Message('stop')
outport.send(msg)
displaymsg.set("Playback stopped")
2022-03-28 15:01:27 +02:00
def unmuteAll():
global outport
for i in range (0,15):
msg = mido.Message('control_change',control= 53, channel= i, value=0)
2022-03-28 17:37:27 +02:00
outport.send(msg)
2022-03-28 15:01:27 +02:00
2022-03-28 13:02:05 +02:00
def nextPattern():
global outport
msg = mido.Message('control_change', control = 103, value = 16)
outport.send(msg)
displaymsg.set("Next Pattern")
def nextSong():
pass
def closeMidi():
pass
def setPath():
global path
folder = name_input.get()
path = fd.askdirectory()
displaymsg.set("Directory set")
makeDir()
def makeDir():
global folder
2022-03-28 15:01:27 +02:00
global projectpath
2022-03-28 13:02:05 +02:00
folder = name_input.get()
2022-03-28 15:01:27 +02:00
projectpath = path + '/' + folder
2022-03-28 17:37:27 +02:00
try:
os.mkdir(projectpath)
except:
displaymsg.set("Directory Error")
2022-03-28 15:01:27 +02:00
def makeDirNr(pattern_nr):
global projectpath
2022-03-28 15:41:09 +02:00
#Pfad wird addiert deswegen zusätzliche verzeichnisse
#projectpath = projectpath + '/' + str(pattern_nr)
2022-03-28 17:37:27 +02:00
try:
os.mkdir(projectpath + '/' + str(pattern_nr))
except:
displaymsg.set("Directory Error")
#print(projectpath)
2022-03-28 13:02:05 +02:00
def start_Rec():
displaymsg.set("Recording...")
global path
global time
global j
2022-03-28 15:01:27 +02:00
global pro
2022-03-28 15:41:09 +02:00
global pattern_nr
2022-03-28 13:02:05 +02:00
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = loop_time
WAVE_OUTPUT_FILENAME = name_input.get()+ "_" + "track" + str(j+1) + ".wav"
p = pyaudio.PyAudio()
2022-03-28 17:37:27 +02:00
start_MIDI()
2022-03-28 13:02:05 +02:00
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK
)
2022-03-28 17:37:27 +02:00
#print("* recording")
2022-03-28 13:02:05 +02:00
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
2022-03-28 17:37:27 +02:00
#print("Done recording")
2022-03-28 13:02:05 +02:00
stream.stop_stream()
stream.close()
p.terminate()
2022-03-28 15:41:09 +02:00
if mode_select.get() == 2:
wf = wave.open(projectpath + '/' + str(pattern_nr) + '/' + WAVE_OUTPUT_FILENAME, 'wb')
else:
wf = wave.open(projectpath + '/' + WAVE_OUTPUT_FILENAME, 'wb')
2022-03-28 13:02:05 +02:00
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
j = j + 1
2022-03-28 15:41:09 +02:00
if j == 8:
j= 0
2022-03-28 13:02:05 +02:00
displaymsg.set("End of Recording")
def sequenceMaster():
2022-03-28 17:37:27 +02:00
global cancel
2022-03-28 15:01:27 +02:00
global pattern_nr
2022-03-28 17:37:27 +02:00
cancel = 0
2022-03-28 18:03:23 +02:00
#print("test")
displaymsg.set("Sequence started")
openMidi()
2022-03-28 15:01:27 +02:00
if mode_select.get() == 2:
makeDirNr(pattern_nr)
2022-03-28 13:02:05 +02:00
2022-03-28 18:03:23 +02:00
for i in range (0,8): #
pattern_limit = patterns_input.get()
if cancel == 1 or pattern_nr == pattern_limit:
break
#print("sequence started",i)
2022-03-28 13:02:05 +02:00
muteAll()
setSolo(i)
#starting Midi during wave record for timing
2022-03-28 17:37:27 +02:00
start_Rec()
2022-03-28 13:02:05 +02:00
#print(i)
stop_MIDI()
2022-03-28 17:37:27 +02:00
unmuteAll()
2022-03-28 18:03:23 +02:00
mode = mode_select.get()
2022-03-28 13:02:05 +02:00
if i == 7 and mode == 2:
2022-03-28 17:37:27 +02:00
#print(mode_select)
2022-03-28 13:02:05 +02:00
time.sleep(5)
nextPattern()
2022-03-28 15:01:27 +02:00
pattern_nr += 1
2022-03-28 17:37:27 +02:00
if pattern_nr == 9 :
2022-03-28 15:01:27 +02:00
pattern_nr = 0
2022-03-28 17:37:27 +02:00
sequenceMaster()
2022-03-28 18:03:23 +02:00
2022-03-28 17:37:27 +02:00
def cancelRec():
global cancel
global j
j = 0
cancel = 1
2022-03-28 13:02:05 +02:00
#GUI Main
buttonsize_x = 8
buttonsize_y = 2
mode_select = 0
root = Tk()
root.title('underbridge for OP-Z')
root.resizable(width=False, height=False) #565A5E
root.tk_setPalette(background='#565A5E', foreground='black',activeBackground='#283867', activeForeground='black' )
upperframe= LabelFrame(root, text= "Parameter",padx= 10, pady =10, fg = 'white')
upperframe.grid(row = 0, column = 0, padx =2, pady =2, columnspan=7)
2022-03-28 18:22:47 +02:00
lowerframe= Frame(root,padx= 10, pady =10)
2022-03-28 13:02:05 +02:00
lowerframe.grid(row = 1, column = 0, padx =2, pady =2, columnspan=7)
2022-03-28 17:37:27 +02:00
footer= Frame(root,padx= 15, pady =10)
footer. grid(row = 2, column = 0, padx =2, pady =2, columnspan=7)
2022-03-28 13:02:05 +02:00
mode_select = IntVar()
displaymsg = StringVar()
#root.geometry('550x150+0+0')
Get_BPM = Button(upperframe, text="Get BPM",width = buttonsize_x, height = buttonsize_y, fg = 'white', command = lambda:getBPM())
#ALL = Radiobutton(lowerframe, text= 'ALL', value = 1 , variable = mode_select, width = buttonsize_x, height = buttonsize_y , indicatoron = 0, bg= '#1b7d24' )
Song = Radiobutton(lowerframe, text= 'Project', value = 2 , variable = mode_select, width = buttonsize_x, height = buttonsize_y , indicatoron = 0, bg= '#1b7d24' )
Pattern = Radiobutton(lowerframe, text= 'Pattern', value = 3 , variable = mode_select, width = buttonsize_x, height = buttonsize_y, indicatoron = 0,bg= '#1b7d24' )
Pattern.select()
bar_input = Scale(upperframe, from_ = 1, to = 4, orient = HORIZONTAL, label="Nr. Bars", sliderlength= 10, length= 75, fg = 'white')
#bar_text = Label(upperframe,text="Nr. of Bars", width = 8, height = 1)
patterns_input = Scale(upperframe, from_ = 1, to = 10, orient = HORIZONTAL, label="Patterns",sliderlength= 10, length= 75, fg = 'white')
2022-03-28 18:03:23 +02:00
patterns_input.set(value=10)
2022-03-28 13:02:05 +02:00
bpm_input = Entry(upperframe, width =10, text="BPM",bg= 'white')
#bpm_text = Label(upperframe,text="BPM", width = 8, height = 1)
bpm_input.insert(0, "BPM")
#project_input = Entry(upperframe, width =10, text="Project",bg= 'white')
#bpm_text = Label(upperframe,text="BPM", width = 8, height = 1)
#project_input.insert(0, "Project Nr.")
add_sec = Scale(upperframe, from_ = 0, to = 10, orient = HORIZONTAL, label="extra Sec", sliderlength= 10, length= 75, fg = 'white')
#add_text = Label(upperframe,text="Sec offset", width = 8, height = 1)
name_input = Entry(upperframe, width =10, text="Name",bg = 'white')
name_input.insert(0, "Name")
#name_text = Label(upperframe,text="Prj Name", width = 8, height = 1)
2022-03-28 18:03:23 +02:00
set_param = Button(lowerframe, text="set Param",width = buttonsize_x, height = buttonsize_y, fg = 'white',bg= '#0095FF', command = lambda:setParam())
set_path = Button(lowerframe, text="Directory",width = buttonsize_x, height = buttonsize_y,fg = 'white',bg= '#0095FF', command = lambda:setPath())
start_recording = Button(lowerframe, text="RECORD",width = buttonsize_x, height = buttonsize_y,fg = 'white', bg = '#FF2200', command = lambda:threading.Thread(target = sequenceMaster).start())
2022-03-28 17:37:27 +02:00
2022-03-28 18:22:47 +02:00
tutorial = Label(footer,text="Enter Parameter, then press set Param, choose directory and start recording", width = 70, height = 2, bg ='grey',fg= 'white', relief = SUNKEN)
2022-03-28 17:37:27 +02:00
display = Label(footer,textvariable= displaymsg, width = 15, height = 2, bg ='white', relief = SUNKEN)
2022-03-28 18:03:23 +02:00
cancel = Button(lowerframe,text = "CANCEL" , width = buttonsize_x, height = buttonsize_y, bg ='#FFCC00', fg= 'white', command = lambda: cancelRec())
2022-03-28 17:37:27 +02:00
cancel.grid(row = 1, column = 6, padx =2, pady =2)
2022-03-28 13:02:05 +02:00
2022-03-28 17:37:27 +02:00
donate = Label(footer, text= "donate <3 @ https://link.raise-uav.com", width= 40, height = 1)
donate.grid(row = 3, column = 5, padx =2, pady =2, columnspan=2)
2022-03-28 13:02:05 +02:00
#Get_BPM.grid(row = 1, column = 0, padx =2, pady =2)
2022-03-28 17:37:27 +02:00
#ALL.grid()
2022-03-28 13:02:05 +02:00
Song.grid(row = 1, column = 1, padx =5, pady =2)
Pattern.grid(row = 1, column = 2, padx =5, pady =2)
name_input.grid(row = 0, column = 0, padx =5, pady =0)
#name_text.grid(row = 1, column = 2, padx =0, pady =0)
bpm_input.grid(row = 0, column = 1, padx =5, pady =0)
#bpm_text.grid(row = 0, column = 0, padx =0, pady =0)
#project_input.grid(row = 0, column = 2, padx =5, pady =0)
bar_input.grid(row = 0, column = 3, padx =5, pady =2)
#bar_text.grid(row = 1, column = 2, padx =0, pady =0)
patterns_input.grid(row = 0, column = 4, padx =5, pady =2)
add_sec.grid(row = 0, column = 5, padx =5, pady =2)
#add_text.grid(row = 1, column = 0, padx =0, pady =0)
2022-03-28 18:22:47 +02:00
set_param.grid(row = 1, column = 3, padx =5, pady =5)
set_path.grid(row = 1, column = 4, padx =5, pady =5)
start_recording.grid(row = 1, column = 5, padx =5, pady =5)
2022-03-28 13:02:05 +02:00
2022-03-28 18:22:47 +02:00
tutorial.grid(row = 2, column = 0, padx =2, pady =5, columnspan=6)
2022-03-28 17:37:27 +02:00
display.grid(row = 3, column = 0, padx =2, pady =5)
2022-03-28 13:02:05 +02:00
root.mainloop()