This commit is contained in:
Symonty 2022-03-31 09:29:54 -07:00
commit 3c7149f741
5 changed files with 118 additions and 44 deletions

View File

@ -2,40 +2,62 @@
## Multitrack exporter ## Multitrack exporter
--- ---
## Despription ## Description
- Exports Patterns and projects individual Audio Tracks to seperate folders for use in your DAW - Exports patterns and projects individual audio tracks to seperate folders for use in your DAW.
- Python cross plattform with single file binary for x86 linux - Python cross plattform with single file binary for x86 linux.
## Installation ## Using Packaged single file Binarys _(The easy way)_
### Ubuntu 20.10 LTS (If the binary in /dist doesn't work)
`sudo apt install portaudio19-dev`
`sudo apt install python3-tk`
`pip install python-rtmidi`
`pip install pyaudio`
### Mac Install
`brew install portaudio`
`brew install python-tk`
`pip install python-rtmidi`
`pip install pyaudio`
`pip install mido`
`python3 underbridge.py` to start
### Linux binary
- Executables reside in the folder `/dist/`
- on Windows
`underbridge.exe`
- On Linux:
``./underbridge`` ``./underbridge``
Underbridge_alt was packaged on a different system. Might help if you run into problems.
Underbridge_alt was packaged on a different system. Might help if you run into problems. (Outdated)
## Installation _(Less easy way)_
### Windows
- Install Python 3.9 if not already, 3.10 seems to cause problems.
- install portaudio_dev : `apt install portaudio19-dev`
- install mido : `pip install mido`
- install rt-midi: `pip isntall rt-midi`
- install pipwin: `pip install pipwin`
- install pyaudio `pipwin install pyaudio`
**Activate OP-Z device input in sound settings of windows and make it default**
- run `python underbridge.py`
### Mac Install - ( tested on Mac OS Monterey 12.3 )
install portaudio: `brew install portaudio`
install mido: `pip install mido`
install tk: `brew install python-tk`
install rt-midi: `pip install python-rtmidi`
install pyaudio: `pip install pyaudio`
**Set OP-Z device as input in sound of system preferences**
open terminal and type: `python3 underbridge.py` to start
### Ubuntu 20.10 LTS
- `sudo apt install portaudio19-dev`
- `sudo apt install python3-tk`
- `pip install python-rtmidi`
- `pip install pyaudio`
`python3 underbridge.py` to start
## Steps ## Steps
- connect OP-Z via USB - connect OP-Z via USB
- in /dist/ directory run ``./underbridge`` - Run underbridge
- Alternatively python3 underbridge.py in root directory. Make sure you have installed dependencies before..
### Single Pattern Mode ### Single Pattern Mode
@ -53,7 +75,7 @@ Underbridge_alt was packaged on a different system. Might help if you run into p
- Select Porject and first Pattern you want to export on OP-Z. - Select Porject and first Pattern you want to export on OP-Z.
- Enter name for the project. This is used for the folder structure - Enter name for the project. This is used for the folder structure
- Get BPM from led code or Smartphone app. - Get BPM from led code or Smartphone app.
- Enter BPM - Enter BPM
- Enter longest Bar of you track (1-4) - Enter longest Bar of you track (1-4)
- Enter the Nr. of Patterns your song consists of. - Enter the Nr. of Patterns your song consists of.
- Optionally enter additional seconds at the end of the recording to capture reverb tails etc. - Optionally enter additional seconds at the end of the recording to capture reverb tails etc.
@ -61,7 +83,5 @@ Underbridge_alt was packaged on a different system. Might help if you run into p
- Select directory you want to record the waves to - Select directory you want to record the waves to
- Click record and wait until finished. - Click record and wait until finished.
### Troubleshooting
- When the recorded audio contains buzzing or other artifacts try disabling the USB charging with "display" and "bottom right key" to disable.

BIN
dist/underbridge vendored

Binary file not shown.

BIN
dist/underbridge.exe vendored Normal file

Binary file not shown.

7
import pyaudio.py Normal file
View File

@ -0,0 +1,7 @@
import pyaudio
p = pyaudio.PyAudio()
info = p.get_host_api_info_by_index(0)
numdevices = info.get('deviceCount')
for i in range(0, numdevices):
if (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
print("Input Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name'))

View File

@ -1,7 +1,6 @@
# Underbridge OP-Z multichannel exporter # Underbridge OP-Z multichannel exporter
# Copyright 2022 Thomas Herrmann Email: herrmann@raise-uav.com # Copyright 2022 Thomas Herrmann Email: herrmann@raise-uav.com
import mido import mido
import pyaudio import pyaudio
import wave import wave
@ -11,6 +10,9 @@ import time
import threading import threading
import os import os
device_list = []
op_device = []
audio_device = []
loop_time = 0 loop_time = 0
inport = 0 inport = 0
outport = 0 outport = 0
@ -25,11 +27,39 @@ cancel = 0
def getMIDIDevice(): def getMIDIDevice():
pass global device_list
global op_device
device_list = mido.get_output_names()
print (device_list)
try:
op_device = list(filter(lambda x: 'OP-Z' in x, device_list))
op_device = op_device[0]
print (op_device)
displaymsg.set("OP-Z found")
except:
displaymsg.set("Can´t find OP-Z : MIDI Error.")
def getAudioDevice():
global audio_device
p = pyaudio.PyAudio()
try:
info = p.get_host_api_info_by_index(0)
numdevices = info.get('deviceCount')
for i in range(0, numdevices):
if (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
print("Input Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0, i).get('name'))
for i in range(0, numdevices):
#audio_device = p.get_device_info_by_host_api_device_index(0, i).get('name')
if "OP-Z" in p.get_device_info_by_host_api_device_index(0, i).get('name') and (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
audio_device = i
print ("Detected OP-Z audio at Index:",audio_device, p.get_device_info_by_host_api_device_index(0, audio_device).get('name'))
except:
displaymsg.set("OP-Z Audio Device not found.")
def getBPM(): def getBPM():
inport= mido.open_input('OP-Z:OP-Z MIDI 1 20:0') global op_device
inport= mido.open_input(op_device)
msg = inport.poll() msg = inport.poll()
#print(msg) #print(msg)
@ -55,8 +85,9 @@ def setParam():
def openMidi(): def openMidi():
global outport global outport
outport= mido.open_output('OP-Z:OP-Z MIDI 1 20:0') global op_device
displaymsg.set("OP-Z MIDI not connected :(") outport= mido.open_output(op_device)
#displaymsg.set("OP-Z MIDI not connected :(")
print(outport) print(outport)
def setProject(projnr): def setProject(projnr):
@ -102,8 +133,10 @@ def nextPattern():
def nextSong(): def nextSong():
pass pass
def closeMidi(): def closeMidi():
pass global outport
outport.close()
displaymsg.set("MIDI closed")
def setPath(): def setPath():
global path global path
@ -139,26 +172,29 @@ def start_Rec():
global j global j
global pro global pro
global pattern_nr global pattern_nr
CHUNK = 1024 global audio_device
CHUNK = 128
FORMAT = pyaudio.paInt16 FORMAT = pyaudio.paInt16
CHANNELS = 2 CHANNELS = 2
RATE = 44100 RATE = 48000
RECORD_SECONDS = loop_time RECORD_SECONDS = loop_time
WAVE_OUTPUT_FILENAME = name_input.get()+ "_" + "track" + str(j+1) + ".wav" WAVE_OUTPUT_FILENAME = name_input.get()+ "_" + "track" + str(j+1) + ".wav"
p = pyaudio.PyAudio() p = pyaudio.PyAudio()
start_MIDI()
stream = p.open(format=FORMAT, stream = p.open(format=FORMAT,
channels=CHANNELS, channels=CHANNELS,
rate=RATE, rate=RATE,
input=True, input=True,
input_device_index= audio_device,
frames_per_buffer=CHUNK frames_per_buffer=CHUNK
) )
#print("* recording") #print("* recording")
frames = [] frames = []
start_MIDI()
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK) data = stream.read(CHUNK)
frames.append(data) frames.append(data)
@ -184,12 +220,19 @@ def start_Rec():
displaymsg.set("End of Recording") displaymsg.set("End of Recording")
def sequenceMaster(): def sequenceMaster():
global cancel global cancel
global pattern_nr global pattern_nr
cancel = 0 cancel = 0
#print("test") #print("test")
getMIDIDevice()
time.sleep(1)
getAudioDevice()
displaymsg.set("Sequence started") displaymsg.set("Sequence started")
try:
try:
openMidi() openMidi()
if mode_select.get() == 2: if mode_select.get() == 2:
@ -201,11 +244,13 @@ def sequenceMaster():
break break
#print("sequence started",i) #print("sequence started",i)
muteAll() muteAll()
time.sleep(0.1)
setSolo(i) setSolo(i)
#starting Midi during wave record for timing #starting Midi during wave record for timing
start_Rec() start_Rec()
#print(i) #print(i)
stop_MIDI() stop_MIDI()
time.sleep(1)
unmuteAll() unmuteAll()
mode = mode_select.get() mode = mode_select.get()
@ -218,13 +263,15 @@ def sequenceMaster():
pattern_nr = 0 pattern_nr = 0
sequenceMaster() sequenceMaster()
except: except:
displaymsg.set("OP-Z connection Problem :(") displaymsg.set("OP-Z Sequence error try restarting the OP-Z or press CANCEL Button")
def cancelRec(): def cancelRec():
global cancel global cancel
global outport
global j global j
j = 0 j = 0
cancel = 1 cancel = 1
closeMidi()
#GUI Main #GUI Main
buttonsize_x = 7 buttonsize_x = 7