Sampled Instrument Player with static and monolithic design. All instruments are built-in.
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.
 
 

267 lines
10 KiB

import os
import sys
import struct
import time
import unittest
sys.path = ["./py"] + sys.path
import cbox
global Document
Document = cbox.Document
def verify_region(region, has, has_not, full = False):
values = set()
values_dict = {}
rtext = region.as_string() if not full else region.as_string_full()
for pair in rtext.split(" "):
if "=" in pair:
key, value = pair.split("=")
values.add(pair)
values.add(key)
values_dict[key] = value
if 'genericmod' in rtext:
print (rtext, "Expected:", has)
assert False
for i in has:
if '_oncc' in i:
i = i.replace('_oncc', '_cc')
if i not in values:
print("Not found: %s, has: %s" % (i, rtext))
assert False
for i in has_not:
if i in values:
print("Found unwanted string: %s=%s" % (i, values_dict[i]))
assert False
scene = Document.get_scene()
scene.clear()
instrument = scene.add_new_instrument_layer("test_sampler", "sampler").get_instrument()
npfs = instrument.engine.load_patch_from_string(0, '.', '', 'new_patch')
instrument.engine.set_patch(1, 0)
glb = npfs.get_global()
assert glb
assert glb.get_children()
master = glb.get_children()[0]
g1 = master.new_child()
g1.set_param("cutoff", "100")
g1.set_param("resonance", "6")
g1.set_param("fil_type", "lpf_4p")
g1.set_param("fileg_decay", "0.2")
g1.set_param("fileg_sustain", "10")
g1.set_param("fileg_depth", "5400")
g1.set_param("fileg_release", "10")
g1.set_param("ampeg_release", "0.1")
g1.set_param("amp_veltrack", "0")
g1.set_param("volume", "-12")
g1.set_param("fileg_depthcc14", "-5400")
def check_exception(param, value, substr):
error = False
try:
g1.set_param(param, value)
except Exception as e:
error = True
assert substr in str(e), "Exception with substring '%s' expected when setting %s to %s, caught another one: %s" % (substr, param, value, str(e))
assert error, "Exception with substring '%s' expected when setting %s to %s, none caught" % (substr, param, value)
check_exception("cutoff", "bla", "correct numeric value")
check_exception("key", "bla", "valid note name")
check_exception("lochan", "bla", "correct integer value")
check_exception("lochan", "10.5", "correct integer value")
check_exception("offset", "bla", "correct unsigned integer value")
check_exception("offset", "10.5", "correct unsigned integer value")
check_exception("offset", "-1000", "correct unsigned integer value")
# Make sure that multiple CC assignments work
g1.set_param("locc5", "100")
g1.set_param("locc8", "100")
g1.set_param("hicc8", "110")
#g1.set_param("cutoff", "1000")
#g1.set_param("fillfo_freq", "4")
#g1.set_param("fillfo_depth", "2400")
#g1.set_param("fillfo_wave", "12")
r1 = g1.new_child()
r1.set_param("sample", "*saw")
r1.set_param("transpose", "0")
r1.set_param("tune", "5")
r1.set_param("gain_cc17", "12")
verify_region(g1, ["locc5=100", "locc8=100", "hicc8=110"], ['hicc5'])
verify_region(r1, ["locc5=100", "locc8=100", "hicc8=110"], [], full=True)
r1.set_param("hicc5", "120")
r1.set_param("hicc8", "124")
verify_region(g1, ["locc5=100", "locc8=100", "hicc8=110"], ['hicc5'])
verify_region(g1, ["locc5=100", "hicc5=127", "locc8=100", "hicc8=110"], [], full=True)
verify_region(r1, ["locc5=100", "hicc5=120", "locc8=100", "hicc8=124"], [], full=True)
r2 = g1.new_child()
r2.set_param("sample", "*sqr")
r2.set_param("transpose", "12")
r2.set_param("gain_cc17", "-12")
verify_region(r2, ["sample=*sqr", "gain_cc17=-12", "transpose=12"], [])
r2.set_param("gain_cc17", "-24")
verify_region(r2, ["gain_cc17=-24"], ["gain_cc17=-12"])
r2.unset_param("gain_cc17")
verify_region(r2, ["sample=*sqr"], ["gain_cc17"])
r2.unset_param("transpose")
verify_region(r2, ["sample=*sqr"], ["transpose"])
r2.unset_param("sample")
verify_region(r2, [], ["transpose", "sample"])
g1.unset_param("cutoff")
g1.unset_param("resonance")
g1.unset_param("fil_type")
g1.unset_param("fileg_sustain")
g1.unset_param("fileg_decay")
g1.unset_param("fileg_depth")
g1.unset_param("fileg_release")
g1.unset_param("ampeg_release")
g1.unset_param("amp_veltrack")
g1.unset_param("volume")
g1.unset_param("fileg_depthcc14")
g1.unset_param("locc5")
g1.unset_param("locc8")
g1.unset_param("hicc8")
params_to_test = [
'lokey', 'hikey', 'lovel', 'hivel', 'key',
'cutoff', 'pan', 'offset', 'tune', 'position', 'width',
'amp_random', 'fil_random', 'pitch_random', 'delay_random',
'pitch_veltrack', 'reloffset_veltrack', 'offset_veltrack',
'delay_cc5', 'delay_cc10', 'reloffset_cc5', 'reloffset_cc10', 'offset_cc5', 'offset_cc10',
'delay_curvecc8', 'reloffset_curvecc5', 'offset_curvecc10',
'delay_stepcc8', 'reloffset_stepcc5', 'offset_stepcc10',
'cutoff_cc1', "resonance_cc1", 'pitch_cc1', 'tonectl_cc1', 'gain_cc1', 'amplitude_cc1',
'cutoff_oncc2', "resonance_oncc2", 'pitch_oncc2', 'tonectl_oncc2', 'gain_oncc2', 'amplitude_oncc2',
'cutoff_curvecc1', 'resonance_curvecc5', 'pitch_curvecc10', 'amplitude_curvecc10',
'cutoff_smoothcc1', 'resonance_smoothcc5', 'pitch_smoothcc10', 'amplitude_smoothcc10',
'cutoff_stepcc1', 'resonance_stepcc5', 'pitch_stepcc10', 'amplitude_stepcc10',
'loop_start', 'loop_end',
'ampeg_attack',
'amplfo_depth', 'fillfo_depth',
'fileg_vel2depth',
'fileg_depthcc5', 'fillfo_depthcc8','amplfo_depthcc5',
'fileg_depth_curvecc5', 'fillfo_depth_curvecc8','amplfo_depth_curvecc5',
'fileg_depth_smoothcc5', 'fillfo_depth_smoothcc8','amplfo_depth_smoothcc5',
'fileg_depth_stepcc5', 'fillfo_depth_stepcc8','amplfo_depth_stepcc5',
'amplfo_freqcc5', 'fillfo_freqcc10', 'pitchlfo_freqcc5',
'cutoff_chanaft', 'resonance_chanaft',
'cutoff_polyaft', 'resonance_polyaft',
'amplfo_depthpolyaft', 'fillfo_depthpolyaft', 'pitchlfo_depthpolyaft',
'amplfo_freqpolyaft', 'fillfo_freqpolyaft', 'pitchlfo_freqpolyaft',
'eq1_freqcc1', 'eq2_gaincc2', 'eq3_bwcc3',
'eq1_freq_curvecc1', 'eq2_gain_curvecc2', 'eq3_bw_curvecc3',
'eq1_freq_smoothcc1', 'eq2_gain_smoothcc2', 'eq3_bw_smoothcc3',
'eq1_freq_stepcc1', 'eq2_gain_stepcc2', 'eq3_bw_stepcc3',
'fileg_vel2start', 'fileg_vel2delay', 'fileg_vel2attack', 'fileg_vel2hold', 'fileg_vel2decay', 'fileg_vel2sustain', 'fileg_vel2release',
'fileg_startcc1', 'fileg_delaycc1', 'fileg_attackcc1', 'fileg_holdcc1', 'fileg_decaycc1', 'fileg_sustaincc1', 'fileg_releasecc1',
'fileg_start_curvecc1', 'fileg_delay_curvecc1', 'fileg_attack_curvecc1', 'fileg_hold_curvecc1', 'fileg_decay_curvecc1', 'fileg_sustain_curvecc1', 'fileg_release_curvecc1',
'fileg_start_smoothcc1', 'fileg_delay_smoothcc1', 'fileg_attack_smoothcc1', 'fileg_hold_smoothcc1', 'fileg_decay_smoothcc1', 'fileg_sustain_smoothcc1', 'fileg_release_smoothcc1',
'fileg_start_stepcc1', 'fileg_delay_stepcc1', 'fileg_attack_stepcc1', 'fileg_hold_stepcc1', 'fileg_decay_stepcc1', 'fileg_sustain_stepcc1', 'fileg_release_stepcc1',
'cutoff2', 'resonance2', 'fileg_depth2', 'fileg_depth2cc1', 'fileg_depth2_stepcc1',
'fillfo_depth2', 'fillfo_depth2cc1', 'fillfo_depth2_stepcc1',
'amp_velcurve_5', 'amp_velcurve_127',
'locc5', 'hicc5',
'on_locc8', 'on_hicc8',
'lfo5_freq', 'lfo1_wave', 'lfo3_fade', 'lfo4_delay',
]
for i in range(len(params_to_test)):
param = params_to_test[0]
print ("Trying %s" % param)
rest = params_to_test[1:]
value1, value2 = "100", "80"
if 'key' in param:
value1, value2 = "e1", "g1"
# Verify that a setting is reported back
r2.set_param(param, value1)
verify_region(r2, ["%s=%s" % (param, value1)], rest)
# Verify that setting the same value in parent doesn't change the local 'has' flag
g1.set_param(param, value1)
verify_region(r2, ["%s=%s" % (param, value1)], rest)
# Verify that setting a different local value doesn't get overridden by parent
r2.set_param(param, value2)
verify_region(r2, ["%s=%s" % (param, value2)], rest)
# Write the original value
r2.set_param(param, value1)
verify_region(r2, ["%s=%s" % (param, value1)], rest)
# Delete the parent value, confirm the deletion doesn't propagate to child
g1.unset_param(param)
verify_region(r2, ["%s=%s" % (param, value1)], rest)
# Set a different value in the parent, confirm it doesn't affect the child
g1.set_param(param, value2)
verify_region(g1, ["%s=%s" % (param, value2)], rest)
verify_region(r2, ["%s=%s" % (param, value1)], rest)
# Check that the newly created child inherits the setting from the parent
r3 = g1.new_child()
verify_region(r3, [], [param])
verify_region(r3, ["%s=%s" % (param, value2)], [], full=True)
r3.delete()
# Verify that the original child still has the original value
verify_region(r2, ["%s=%s" % (param, value1)], [], full=True)
# Delete the child value, make sure it disappears but the inherited
# value is still reported in the full listing
r2.unset_param(param)
verify_region(r2, [], params_to_test)
verify_region(r2, ["%s=%s" % (param, value2)], [], full=True)
# Delete the setting in the parent, make sure the inherited value in the
# child disappears too
g1.unset_param(param)
verify_region(r2, [], ["%s=%s" % (param, value2)], full=True)
master.set_param(param, value1)
verify_region(master, ["%s=%s" % (param, value1)], [])
verify_region(g1, [], params_to_test)
verify_region(g1, ["%s=%s" % (param, value1)], [], full=True)
verify_region(r2, [], params_to_test)
verify_region(r2, ["%s=%s" % (param, value1)], [], full=True)
master.unset_param(param)
verify_region(master, [], params_to_test)
verify_region(g1, [], params_to_test)
verify_region(r2, [], params_to_test)
params_to_test = params_to_test[1:] + params_to_test[0:1]
old_names = [
("hilev", "hivel"),
("lolev", "lovel"),
("loopstart", "loop_start"),
("loopend", "loop_end"),
("loopmode", "loop_mode", "one_shot", "loop_continuous"),
("bendup", "bend_up"),
("benddown", "bend_down"),
("offby", "off_by"),
]
for t in old_names:
if len(t) == 2:
old, new = t
v1, v2 = "10", "20"
else:
old, new, v1, v2 = t
print ("Trying alias: %s" % old)
r1.set_param(old, v1)
verify_region(r1, ["%s=%s" % (new, v1)], [old])
r1.set_param(old, v2)
verify_region(r1, ["%s=%s" % (new, v2)], [old])
r1.unset_param(old)
verify_region(r1, [], [old, new])
r1.set_param(new, v1)
verify_region(r1, ["%s=%s" % (new, v1)], [old])
r1.set_param(new, v2)
verify_region(r1, ["%s=%s" % (new, v2)], [old])
r1.unset_param(new)
verify_region(r1, [], [old, new])