94 lines
3.6 KiB
Python
94 lines
3.6 KiB
Python
|
|
"""Test SoundBuffer sfxr synthesis."""
|
||
|
|
import mcrfpy
|
||
|
|
import sys
|
||
|
|
|
||
|
|
# Test 1: All presets work
|
||
|
|
presets = ["coin", "laser", "explosion", "powerup", "hurt", "jump", "blip"]
|
||
|
|
for preset in presets:
|
||
|
|
buf = mcrfpy.SoundBuffer.sfxr(preset)
|
||
|
|
assert buf is not None, f"sfxr('{preset}') returned None"
|
||
|
|
assert buf.sample_count > 0, f"sfxr('{preset}') has 0 samples"
|
||
|
|
assert buf.duration > 0, f"sfxr('{preset}') has 0 duration"
|
||
|
|
assert buf.sfxr_params is not None, f"sfxr('{preset}') has no params"
|
||
|
|
print(f" PASS: sfxr('{preset}') -> {buf.duration:.3f}s, {buf.sample_count} samples")
|
||
|
|
|
||
|
|
print("PASS: All sfxr presets generate audio")
|
||
|
|
|
||
|
|
# Test 2: Deterministic with seed
|
||
|
|
buf1 = mcrfpy.SoundBuffer.sfxr("coin", seed=42)
|
||
|
|
buf2 = mcrfpy.SoundBuffer.sfxr("coin", seed=42)
|
||
|
|
assert buf1.sample_count == buf2.sample_count, "Same seed should produce same sample count"
|
||
|
|
assert buf1.duration == buf2.duration, "Same seed should produce same duration"
|
||
|
|
print("PASS: Deterministic with seed")
|
||
|
|
|
||
|
|
# Test 3: Different seeds produce different results
|
||
|
|
buf3 = mcrfpy.SoundBuffer.sfxr("coin", seed=99)
|
||
|
|
# May have same count by chance, but params should differ
|
||
|
|
p1 = buf1.sfxr_params
|
||
|
|
p3 = buf3.sfxr_params
|
||
|
|
# At least one param should differ (with very high probability)
|
||
|
|
differs = any(p1[k] != p3[k] for k in p1.keys() if k != 'wave_type')
|
||
|
|
assert differs, "Different seeds should produce different params"
|
||
|
|
print("PASS: Different seeds produce different results")
|
||
|
|
|
||
|
|
# Test 4: sfxr_params dict contains expected keys
|
||
|
|
params = buf1.sfxr_params
|
||
|
|
expected_keys = [
|
||
|
|
'wave_type', 'base_freq', 'freq_limit', 'freq_ramp', 'freq_dramp',
|
||
|
|
'duty', 'duty_ramp', 'vib_strength', 'vib_speed',
|
||
|
|
'env_attack', 'env_sustain', 'env_decay', 'env_punch',
|
||
|
|
'lpf_freq', 'lpf_ramp', 'lpf_resonance',
|
||
|
|
'hpf_freq', 'hpf_ramp',
|
||
|
|
'pha_offset', 'pha_ramp', 'repeat_speed',
|
||
|
|
'arp_speed', 'arp_mod'
|
||
|
|
]
|
||
|
|
for key in expected_keys:
|
||
|
|
assert key in params, f"Missing key '{key}' in sfxr_params"
|
||
|
|
print("PASS: sfxr_params has all expected keys")
|
||
|
|
|
||
|
|
# Test 5: sfxr with custom params
|
||
|
|
buf_custom = mcrfpy.SoundBuffer.sfxr(wave_type=2, base_freq=0.5, env_decay=0.3)
|
||
|
|
assert buf_custom is not None
|
||
|
|
assert buf_custom.sfxr_params is not None
|
||
|
|
assert buf_custom.sfxr_params['wave_type'] == 2
|
||
|
|
assert abs(buf_custom.sfxr_params['base_freq'] - 0.5) < 0.001
|
||
|
|
print("PASS: sfxr with custom params")
|
||
|
|
|
||
|
|
# Test 6: sfxr_mutate
|
||
|
|
mutated = buf1.sfxr_mutate(0.1)
|
||
|
|
assert mutated is not None
|
||
|
|
assert mutated.sfxr_params is not None
|
||
|
|
assert mutated.sample_count > 0
|
||
|
|
# Params should be similar but different
|
||
|
|
mp = mutated.sfxr_params
|
||
|
|
op = buf1.sfxr_params
|
||
|
|
differs = any(abs(mp[k] - op[k]) > 0.0001 for k in mp.keys() if isinstance(mp[k], float))
|
||
|
|
# Note: with small mutation and few params, there's a chance all stay same.
|
||
|
|
# But with 0.1 amount and ~20 float params, extremely unlikely all stay same.
|
||
|
|
print(f"PASS: sfxr_mutate produces {'different' if differs else 'similar'} params")
|
||
|
|
|
||
|
|
# Test 7: sfxr_mutate with seed for reproducibility
|
||
|
|
m1 = buf1.sfxr_mutate(0.05, 42)
|
||
|
|
m2 = buf1.sfxr_mutate(0.05, 42)
|
||
|
|
assert m1.sample_count == m2.sample_count, "Same seed should produce same mutation"
|
||
|
|
print("PASS: sfxr_mutate deterministic with seed")
|
||
|
|
|
||
|
|
# Test 8: sfxr_mutate on non-sfxr buffer raises error
|
||
|
|
tone_buf = mcrfpy.SoundBuffer.tone(440, 0.5, "sine")
|
||
|
|
try:
|
||
|
|
tone_buf.sfxr_mutate(0.1)
|
||
|
|
assert False, "Should have raised RuntimeError"
|
||
|
|
except RuntimeError:
|
||
|
|
pass
|
||
|
|
print("PASS: sfxr_mutate on non-sfxr buffer raises RuntimeError")
|
||
|
|
|
||
|
|
# Test 9: Invalid preset raises ValueError
|
||
|
|
try:
|
||
|
|
mcrfpy.SoundBuffer.sfxr("nonexistent_preset")
|
||
|
|
assert False, "Should have raised ValueError"
|
||
|
|
except ValueError:
|
||
|
|
pass
|
||
|
|
print("PASS: Invalid preset raises ValueError")
|
||
|
|
|
||
|
|
print("\nAll soundbuffer_sfxr tests passed!")
|
||
|
|
sys.exit(0)
|