You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.4 KiB
111 lines
4.4 KiB
3 years ago
|
#! /usr/bin/env python3
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
NUMBER_OF_INSTRUMENTS = 240
|
||
|
"""
|
||
|
2021-11-13 Benchmark:
|
||
|
NumberOfInstruments,StartInSeconds,QuitInSeconds
|
||
|
30, 5, 3
|
||
|
60, 10, 6
|
||
|
120, 21, 12
|
||
|
240, 42, 25
|
||
|
|
||
|
Conclusion: Linear time.
|
||
|
"""
|
||
|
|
||
|
from calfbox import cbox
|
||
|
|
||
|
import atexit
|
||
|
from datetime import datetime
|
||
|
|
||
|
#Capture Ctlr+C / SIGINT and let @atexit handle the rest.
|
||
|
import signal
|
||
|
import sys
|
||
|
def signal_handler(sig, frame):
|
||
|
sys.exit(0) #atexit will trigger
|
||
|
signal.signal(signal.SIGINT, signal_handler)
|
||
|
|
||
|
|
||
|
def cmd_dumper(cmd, fb, args):
|
||
|
#print ("%s(%s)" % (cmd, ",".join(list(map(repr,args)))))
|
||
|
pass
|
||
|
|
||
|
def stopSession():
|
||
|
"""This got registered with atexit in the nsm new or open callback above.
|
||
|
will handle all python exceptions, but not segfaults of C modules. """
|
||
|
print()
|
||
|
print("Starting Quit through @atexit, stopSession")
|
||
|
starttime = datetime.now()
|
||
|
#Don't do that. We are just a client.
|
||
|
#cbox.Transport.stop()
|
||
|
#print("@atexit: Calfbox Transport stopped ")
|
||
|
cbox.stop_audio()
|
||
|
print("@atexit: Calfbox Audio stopped ")
|
||
|
cbox.shutdown_engine()
|
||
|
print("@atexit: Calfbox Engine shutdown ")
|
||
|
endtime = datetime.now() - starttime
|
||
|
print (f"Shutdown took {endtime.seconds} seconds for {NUMBER_OF_INSTRUMENTS} instruments")
|
||
|
|
||
|
cbox.init_engine()
|
||
|
cbox.start_audio(cmd_dumper)
|
||
|
atexit.register(stopSession) #this will handle all python exceptions, but not segfaults of C modules.
|
||
|
|
||
|
scenes = {}
|
||
|
jackAudioOutLefts = {}
|
||
|
jackAudioOutRights = {}
|
||
|
outputMergerRouters = {}
|
||
|
routerToGlobalSummingStereoMixers = {}
|
||
|
lmixUuid = cbox.JackIO.create_audio_output('left_mix', "#1") #add "#1" as second parameter for auto-connection to system out 1
|
||
|
rmixUuid = cbox.JackIO.create_audio_output('right_mix', "#2") #add "#2" as second parameter for auto-connection to system out 2
|
||
|
cboxMidiPortUids = {}
|
||
|
sfzSamplerLayers = {}
|
||
|
instrumentLayers = {}\
|
||
|
|
||
|
|
||
|
print (f"Creating {NUMBER_OF_INSTRUMENTS} instruments")
|
||
|
starttime = datetime.now()
|
||
|
|
||
|
for i in range(NUMBER_OF_INSTRUMENTS):
|
||
|
scenes[i] = cbox.Document.get_engine().new_scene()
|
||
|
scenes[i].clear()
|
||
|
|
||
|
#instrumentLayer = scenes[i].status().layers[0].get_instrument()
|
||
|
sfzSamplerLayers[i] = scenes[i].add_new_instrument_layer(str(i), "sampler") #"sampler" is the cbox sfz engine
|
||
|
scenes[i].status().layers[0].get_instrument().engine.load_patch_from_string(0, "", "", "") #fill with null instruments
|
||
|
|
||
|
jackAudioOutLefts[i] = cbox.JackIO.create_audio_output(str(i) +"_L")
|
||
|
jackAudioOutRights[i] = cbox.JackIO.create_audio_output(str(i) +"_R")
|
||
|
|
||
|
outputMergerRouters[i] = cbox.JackIO.create_audio_output_router(jackAudioOutLefts[i], jackAudioOutRights[i])
|
||
|
outputMergerRouters[i].set_gain(-3.0)
|
||
|
#instrumentLayer = sfzSamplerLayers[i].get_instrument()
|
||
|
instrumentLayers[i] = scenes[i].status().layers[0].get_instrument()
|
||
|
instrumentLayers[i].get_output_slot(0).rec_wet.attach(outputMergerRouters[i]) #output_slot is 0 based and means a pair. Most sfz instrument have only one stereo pair. #TODO: And what if not?
|
||
|
|
||
|
routerToGlobalSummingStereoMixers[i] = cbox.JackIO.create_audio_output_router(lmixUuid, rmixUuid)
|
||
|
routerToGlobalSummingStereoMixers[i].set_gain(-3.0)
|
||
|
instrument = sfzSamplerLayers[i].get_instrument()
|
||
|
instrument.get_output_slot(0).rec_wet.attach(routerToGlobalSummingStereoMixers[i])
|
||
|
|
||
|
#Create Midi Input Port
|
||
|
cboxMidiPortUids[i] = cbox.JackIO.create_midi_input(str(i) + "midi_in")
|
||
|
cbox.JackIO.set_appsink_for_midi_input(cboxMidiPortUids[i], True) #This sounds like a program wide sink, but it is needed for every port.
|
||
|
cbox.JackIO.route_midi_input(cboxMidiPortUids[i], scenes[i].uuid) #Route midi input to the scene. Without this we have no sound, but the python processor would still work.
|
||
|
|
||
|
#Actually load the instrument
|
||
|
programNumber = 0
|
||
|
#program = instrumentLayers[i].engine.load_patch_from_tar(programNumber, "bug.tar", f'Saw{1}.sfz', f'Saw{i+1}') #tar_name, sfz_name, display_name
|
||
|
program = instrumentLayers[i].engine.load_patch_from_string(programNumber, ".", "", "<group> <region> sample=*saw") #fill with null instruments
|
||
|
print (f"[{i}]", program.status())
|
||
|
instrumentLayers[i].engine.set_patch(1, programNumber) #1 is the channel, counting from 1. #TODO: we want this to be on all channels.
|
||
|
|
||
|
endtime = datetime.now() - starttime
|
||
|
print (f"Creation took {endtime.seconds} seconds for {NUMBER_OF_INSTRUMENTS} instruments")
|
||
|
|
||
|
print()
|
||
|
print("Press Ctrl+C for a controlled shutdown.")
|
||
|
print()
|
||
|
|
||
|
while True:
|
||
|
cbox.call_on_idle(cmd_dumper)
|