Vita/tests/test_normalized_params.py

144 lines
5.2 KiB
Python

import pytest
import vita
from vita.constants import ValueScale
def test_normalized_linear_parameter():
"""Test normalized control on a linear parameter"""
synth = vita.Synth()
# Get a linear parameter (most parameters are linear by default)
info = synth.get_control_details("filter_1_cutoff")
if info.scale != ValueScale.Linear:
pytest.skip("filter_1_cutoff is not linear in this version")
# Test boundary values
controls = synth.get_controls()
controls["filter_1_cutoff"].set_normalized(0.0)
assert abs(controls["filter_1_cutoff"].get_normalized() - 0.0) < 0.001
assert abs(controls["filter_1_cutoff"].value() - info.min) < 0.001
controls["filter_1_cutoff"].set_normalized(1.0)
assert abs(controls["filter_1_cutoff"].get_normalized() - 1.0) < 0.001
assert abs(controls["filter_1_cutoff"].value() - info.max) < 0.001
# Test middle value
controls["filter_1_cutoff"].set_normalized(0.5)
assert abs(controls["filter_1_cutoff"].get_normalized() - 0.5) < 0.001
expected_mid = info.min + 0.5 * (info.max - info.min)
assert abs(controls["filter_1_cutoff"].value() - expected_mid) < 0.001
def test_normalized_quartic_parameter():
"""Test normalized control on a quartic parameter like env_1_delay"""
synth = vita.Synth()
# Verify env_1_delay uses quartic scaling
info = synth.get_control_details("env_1_delay")
assert info.scale == ValueScale.Quartic
# Test boundary values
controls = synth.get_controls()
controls["env_1_delay"].set_normalized(0.0)
assert abs(controls["env_1_delay"].get_normalized() - 0.0) < 0.001
controls["env_1_delay"].set_normalized(1.0)
assert abs(controls["env_1_delay"].get_normalized() - 1.0) < 0.001
# Test that normalized 0.5 maps to 0.25 seconds display (0.5^4 * 4.0)
# For quartic parameters in VST, normalized maps linearly to internal range
# but the knob DISPLAY position has a quartic relationship
controls["env_1_delay"].set_normalized(0.5)
expected_value = info.min + 0.5 * (info.max - info.min) # Linear mapping
assert abs(controls["env_1_delay"].value() - expected_value) < 0.001
assert abs(controls["env_1_delay"].get_normalized() - 0.5) < 0.001
actual_value = controls["env_1_delay"].value()
linear_mid = info.min + 0.5 * (info.max - info.min)
# With this implementation, normalized maps linearly to internal range
assert abs(actual_value - linear_mid) < 0.001
def test_normalized_indexed_parameter():
"""Test normalized control on an indexed/discrete parameter"""
synth = vita.Synth()
# delay_style is an indexed parameter
info = synth.get_control_details("delay_style")
assert info.scale == ValueScale.Indexed
assert info.is_discrete
num_options = len(info.options)
# Test each discrete value
controls = synth.get_controls()
for i in range(num_options):
normalized = i / (num_options - 1) if num_options > 1 else 0
controls["delay_style"].set_normalized(normalized)
# Check it maps to the correct index
actual_index = int(controls["delay_style"].value() - info.min)
assert actual_index == i
# Check text matches
assert controls["delay_style"].get_text() == info.options[i]
def test_normalized_vst_style_automation():
"""Demonstrate VST-style parameter automation using normalized values"""
synth = vita.Synth()
# Simulate a VST automation curve for filter cutoff
# This would be how a DAW sends parameter changes
automation_points = [
(0.0, 0.0), # Start closed
(0.25, 0.5), # Open to middle
(0.5, 1.0), # Full open
(0.75, 0.3), # Partially close
(1.0, 0.0), # Close again
]
controls = synth.get_controls()
for time, normalized_value in automation_points:
controls["filter_1_cutoff"].set_normalized(normalized_value)
# Verify the normalized value is preserved
retrieved = controls["filter_1_cutoff"].get_normalized()
assert abs(retrieved - normalized_value) < 0.001
# In a real scenario, you would render audio here
# audio = synth.render(60, 0.8, 0.1, 0.1)
def test_normalized_clipping():
"""Test that normalized values are properly clipped to 0-1 range"""
synth = vita.Synth()
# Test values outside 0-1 range
controls = synth.get_controls()
controls["filter_1_cutoff"].set_normalized(-0.5)
assert controls["filter_1_cutoff"].get_normalized() == 0.0
controls["filter_1_cutoff"].set_normalized(1.5)
assert controls["filter_1_cutoff"].get_normalized() == 1.0
if __name__ == "__main__":
# Run basic tests
test_normalized_linear_parameter()
print("✓ Linear parameter test passed")
test_normalized_quartic_parameter()
print("✓ Quartic parameter test passed")
test_normalized_indexed_parameter()
print("✓ Indexed parameter test passed")
test_normalized_vst_style_automation()
print("✓ VST-style automation test passed")
test_normalized_clipping()
print("✓ Clipping test passed")
print("\nAll normalized parameter tests passed!")