511 lines
19 KiB
Python
511 lines
19 KiB
Python
# Copyright 2024-2025 XMOS LIMITED.
|
|
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
|
import numpy as np
|
|
import pytest
|
|
from functools import partial
|
|
import warnings
|
|
|
|
import audio_dsp.dsp.utils as utils
|
|
import audio_dsp.dsp.signal_gen as gen
|
|
import audio_dsp.dsp.generic as dspg
|
|
import audio_dsp.dsp.reverb as rv
|
|
import audio_dsp.dsp.reverb_stereo as rvs
|
|
import audio_dsp.dsp.reverb_plate as rvp
|
|
|
|
|
|
@pytest.mark.parametrize("signal, freq", [["sine", 20],
|
|
["sine", 1000],
|
|
["sine", 10000],
|
|
["sine", 23000],
|
|
["noise", None]])
|
|
@pytest.mark.parametrize("algo, param", [["mono_room", 0.1],
|
|
["mono_room", 1],
|
|
["mono_room", 4],
|
|
["stereo_room", 0.1],
|
|
["stereo_room", 1],
|
|
["stereo_room", 4],
|
|
["stereo_plate", 0.95],]
|
|
)
|
|
def test_reverb_overflow(signal, freq, algo, param):
|
|
# check no overflow errors occur
|
|
fs = 48000
|
|
q_format = 31
|
|
|
|
if signal == "sine":
|
|
sig = gen.sin(fs, 5, freq, 1)
|
|
elif signal == "chirp":
|
|
sig = gen.log_chirp(fs, 5, 1, 20, 20000)
|
|
elif signal == "noise":
|
|
sig = gen.white_noise(fs, 5, 1)
|
|
|
|
sig = sig/np.max(np.abs(sig))
|
|
|
|
if algo == "stereo_room":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvs.reverb_room_stereo(fs, 2, max_room_size=param, room_size=1, decay=1.0, damping=0.0, Q_sig=q_format)
|
|
elif algo == "mono_room":
|
|
reverb = rv.reverb_room(fs, 1, max_room_size=param, room_size=1, decay=1.0, damping=0.0, Q_sig=q_format)
|
|
elif algo == "stereo_plate":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvp.reverb_plate_stereo(fs, 2, decay=param, damping=0.0, Q_sig=q_format)
|
|
|
|
#print(reverb.get_buffer_lens())
|
|
|
|
output_xcore = np.zeros_like(sig)
|
|
output_flt = np.zeros_like(sig)
|
|
|
|
if "stereo" in algo:
|
|
for n in range(sig.shape[1]):
|
|
output_xcore[:, n] = reverb.process_channels_xcore(sig[:, n])
|
|
reverb.reset_state()
|
|
for n in range(sig.shape[1]):
|
|
output_flt[:, n] = reverb.process_channels(sig[:, n])
|
|
else:
|
|
for n in range(len(sig)):
|
|
output_xcore[n] = reverb.process_xcore(sig[n])
|
|
reverb.reset_state()
|
|
for n in range(len(sig)):
|
|
output_flt[n] = reverb.process(sig[n])
|
|
|
|
|
|
def calc_reverb_time(in_sig, reverb_output):
|
|
# extend by 2x
|
|
sig = np.concatenate((in_sig, np.zeros_like(in_sig)))
|
|
output_xcore = np.concatenate((reverb_output, np.zeros_like(reverb_output)))
|
|
|
|
sig_spect = np.fft.rfft(sig)
|
|
output_xcore_spect = np.fft.rfft(output_xcore)
|
|
|
|
# Y = HX, Y/X = H
|
|
H_xcore_spect = output_xcore_spect/sig_spect
|
|
h_xcore = np.fft.irfft(H_xcore_spect)
|
|
h_xcore = h_xcore[:len(h_xcore)//2]
|
|
|
|
return h_xcore
|
|
|
|
|
|
@pytest.mark.parametrize("max_room_size_diffusion", [0.5, 0.9])
|
|
@pytest.mark.parametrize("decay, damping", [[0.5, 0.35],
|
|
[1.0, 0.0]])
|
|
@pytest.mark.parametrize("q_format", [27, 31])
|
|
@pytest.mark.parametrize("algo, width", [["mono_room", None],
|
|
["stereo_room", 1.0],
|
|
["stereo_plate", 1.0],]
|
|
)
|
|
@pytest.mark.parametrize("wdmix", [0.5, 1.0])
|
|
def test_reverb_time(max_room_size_diffusion, decay, damping, q_format, width, algo, wdmix):
|
|
# measure reverb time with chirp
|
|
fs = 48000
|
|
|
|
if "plate" in algo:
|
|
pregain = 0.5**(q_format - 26)
|
|
else:
|
|
pregain = 0.015 * 2**(27 - q_format)
|
|
|
|
sig = np.zeros(int(fs*max_room_size_diffusion*6) + fs)
|
|
sig[:1*fs] = gen.log_chirp(fs, 1, 1, 20, 20000)
|
|
sig = sig* (2**q_format - 1)/(2**q_format)
|
|
|
|
if algo =="stereo_room":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvs.reverb_room_stereo(fs, 2, max_room_size=max_room_size_diffusion, room_size=1, decay=decay, damping=damping, Q_sig=q_format, pregain=pregain, width=width)
|
|
elif algo =="mono_room":
|
|
reverb = rv.reverb_room(fs, 1, max_room_size=max_room_size_diffusion, room_size=1, decay=decay, damping=damping, Q_sig=q_format, pregain=pregain)
|
|
elif algo =="stereo_plate":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvp.reverb_plate_stereo(fs, 2, early_diffusion=max_room_size_diffusion,
|
|
late_diffusion=max_room_size_diffusion,
|
|
decay=decay, damping=damping, Q_sig=q_format,
|
|
pregain=pregain, width=width)
|
|
reverb.set_wet_dry_mix(wdmix)
|
|
|
|
output_xcore = np.zeros_like(sig)
|
|
output_flt = np.zeros_like(sig)
|
|
|
|
if "stereo" in algo:
|
|
for n in range(sig.shape[1]):
|
|
output_flt[:, n] = reverb.process_channels(sig[:, n])
|
|
|
|
reverb.reset_state()
|
|
|
|
with warnings.catch_warnings(record=True) as w:
|
|
warnings.simplefilter('always', utils.SaturationWarning)
|
|
for n in range(sig.shape[1]):
|
|
output_xcore[:, n] = reverb.process_channels_xcore(sig[:, n])
|
|
|
|
else:
|
|
for n in range(len(sig)):
|
|
output_flt[n] = reverb.process(sig[n])
|
|
|
|
reverb.reset_state()
|
|
|
|
with warnings.catch_warnings(record=True) as w:
|
|
warnings.simplefilter('always', utils.SaturationWarning)
|
|
for n in range(len(sig)):
|
|
output_xcore[n] = reverb.process_xcore(sig[n])
|
|
|
|
# if we triggered a saturation warning, can't guarantee arrays are the same
|
|
sat_warn_flag = any([wi.category is utils.SaturationWarning for wi in w])
|
|
|
|
# # in this case, pregain should be adjusted
|
|
# if sat_warn_flag: assert False
|
|
|
|
# small signals are always going to be ropey due to quantizing, so just check average error of top half
|
|
top_half = np.logical_and(utils.db(output_flt) > -50, utils.db(output_flt) < (6*(31-q_format)))
|
|
if np.any(top_half):
|
|
error_flt = np.abs(utils.db(output_xcore[top_half])-utils.db(output_flt[top_half]))
|
|
mean_error_flt = utils.db(np.nanmean(utils.db2gain(error_flt)))
|
|
assert mean_error_flt < 0.055
|
|
|
|
|
|
@pytest.mark.parametrize("max_room_size", [0.5])
|
|
@pytest.mark.parametrize("decay", [0.5])
|
|
@pytest.mark.parametrize("damping", [0.5])
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_noise_floor(max_room_size, decay, damping, algo):
|
|
# check the reverb decays to 0 (no limit cycle noise)
|
|
fs = 48000
|
|
q_format = 27
|
|
|
|
sig = np.zeros(int(fs*max_room_size*40) + fs)
|
|
sig[:1*fs] = gen.log_chirp(fs, 1, 1, 20, 20000)
|
|
sig = sig* (2**q_format - 1)/(2**q_format)
|
|
|
|
if algo =="stereo_room":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvs.reverb_room_stereo(fs, 2, max_room_size=max_room_size, room_size=1, decay=decay, damping=damping, Q_sig=q_format)
|
|
elif algo =="mono_room":
|
|
reverb = rv.reverb_room(fs, 1, max_room_size=max_room_size, room_size=1, decay=decay, damping=damping, Q_sig=q_format)
|
|
elif algo == "stereo_plate":
|
|
sig = np.tile(sig, [2, 1])
|
|
reverb = rvp.reverb_plate_stereo(fs, 2, decay=decay, damping=damping, Q_sig=q_format)
|
|
#print(reverb.get_buffer_lens())
|
|
|
|
output_xcore = np.zeros_like(sig)
|
|
output_flt = np.zeros_like(sig)
|
|
|
|
if "stereo" in algo:
|
|
for n in range(sig.shape[1]):
|
|
output_flt[:, n] = reverb.process_channels(sig[:, n])
|
|
|
|
reverb.reset_state()
|
|
with warnings.catch_warnings(record=True) as w:
|
|
for n in range(sig.shape[1]):
|
|
output_xcore[:, n] = reverb.process_channels_xcore(sig[:, n])
|
|
else:
|
|
for n in range(len(sig)):
|
|
output_flt[n] = reverb.process(sig[n])
|
|
|
|
reverb.reset_state()
|
|
with warnings.catch_warnings(record=True) as w:
|
|
for n in range(len(sig)):
|
|
output_xcore[n] = reverb.process_xcore(sig[n])
|
|
|
|
# check noise floor
|
|
if "stereo" in algo:
|
|
assert np.max(np.abs(output_xcore[:, -1000:])) < 2**-(reverb.Q_sig + 1)
|
|
else:
|
|
assert np.max(np.abs(output_xcore[-1000:])) < 2**-(reverb.Q_sig + 1)
|
|
|
|
# small signals are always going to be ropey due to quantizing, so just check average error of top half
|
|
top_half = np.logical_and(utils.db(output_flt) > -50, utils.db(output_flt) < (6*(31-q_format)))
|
|
if np.any(top_half):
|
|
error_flt = np.abs(utils.db(output_xcore[top_half])-utils.db(output_flt[top_half]))
|
|
mean_error_flt = utils.db(np.nanmean(utils.db2gain(error_flt)))
|
|
assert mean_error_flt < 0.055
|
|
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_bypass(algo):
|
|
# test that a drc component is bit exact when the signal is below
|
|
# the threshold (or above in the case of a noise gate).
|
|
fs = 48000
|
|
signal = gen.log_chirp(fs, 0.5, 1)
|
|
|
|
if algo == "stereo_room":
|
|
signal = np.tile(signal, [2, 1])
|
|
reverb = rvs.reverb_room_stereo(fs, 2, dry_gain_db=0, wet_gain_db=-np.inf)
|
|
elif algo == "mono_room":
|
|
reverb = rv.reverb_room(fs, 1, dry_gain_db=0, wet_gain_db=-np.inf)
|
|
elif algo == "stereo_plate":
|
|
signal = np.tile(signal, [2, 1])
|
|
reverb = rvp.reverb_plate_stereo(fs, 2, dry_gain_db=0, wet_gain_db=-np.inf)
|
|
|
|
output_xcore = np.zeros_like(signal)
|
|
output_flt = np.zeros_like(signal)
|
|
|
|
if "stereo" in algo:
|
|
for n in range(signal.shape[1]):
|
|
output_xcore[:, n] = reverb.process_channels_xcore(signal[:, n])
|
|
reverb.reset_state()
|
|
for n in range(signal.shape[1]):
|
|
output_flt[:, n] = reverb.process_channels(signal[:, n])
|
|
else:
|
|
for n in range(len(signal)):
|
|
output_xcore[n] = reverb.process_xcore(signal[n])
|
|
reverb.reset_state()
|
|
for n in range(len(signal)):
|
|
output_flt[n] = reverb.process(signal[n])
|
|
|
|
np.testing.assert_array_equal(signal, output_flt)
|
|
# quantization noise from multiply by dry gain
|
|
np.testing.assert_allclose(signal, output_xcore, atol=2**-(reverb.Q_sig-1))
|
|
|
|
@pytest.mark.parametrize("algo", ["stereo_room", "stereo_plate"])
|
|
@pytest.mark.parametrize("width", [0, 1])
|
|
def test_reverb_width(algo, width):
|
|
# test that a drc component is bit exact when the signal is below
|
|
# the threshold (or above in the case of a noise gate).
|
|
fs = 48000
|
|
signal = gen.log_chirp(fs, 0.5, 1)
|
|
|
|
if algo == "stereo_room":
|
|
signal = np.tile(signal, [2, 1])
|
|
reverb = rvs.reverb_room_stereo(fs, 2)
|
|
elif algo == "mono_room":
|
|
reverb = rv.reverb_room(fs, 1)
|
|
elif algo == "stereo_plate":
|
|
signal = np.tile(signal, [2, 1])
|
|
reverb = rvp.reverb_plate_stereo(fs, 2)
|
|
|
|
reverb.width = width
|
|
|
|
output_xcore = np.zeros_like(signal)
|
|
output_flt = np.zeros_like(signal)
|
|
|
|
if "stereo" in algo:
|
|
for n in range(signal.shape[1]):
|
|
output_xcore[:, n] = reverb.process_channels_xcore(signal[:, n])
|
|
reverb.reset_state()
|
|
for n in range(signal.shape[1]):
|
|
output_flt[:, n] = reverb.process_channels(signal[:, n])
|
|
else:
|
|
for n in range(len(signal)):
|
|
output_xcore[n] = reverb.process_xcore(signal[n])
|
|
reverb.reset_state()
|
|
for n in range(len(signal)):
|
|
output_flt[n] = reverb.process(signal[n])
|
|
|
|
# small signals are always going to be ropey due to quantizing, so just check average error of top half
|
|
q_format = 27
|
|
top_half = np.logical_and(utils.db(output_flt) > -50, utils.db(output_flt) < (6*(31-q_format)))
|
|
if np.any(top_half):
|
|
error_flt = np.abs(utils.db(output_xcore[top_half])-utils.db(output_flt[top_half]))
|
|
mean_error_flt = utils.db(np.nanmean(utils.db2gain(error_flt)))
|
|
assert mean_error_flt < 0.055
|
|
|
|
if width == 0:
|
|
assert np.all(output_xcore[0, :] == output_xcore)
|
|
assert np.all(output_flt[0, :] == output_flt)
|
|
else:
|
|
assert not np.all(output_xcore[0, :] == output_xcore[1:, :])
|
|
assert not np.all(output_flt[0, :] == output_flt[1:, :])
|
|
|
|
|
|
@pytest.mark.parametrize("fs", [48000])
|
|
@pytest.mark.parametrize("q_format", [27, 31])
|
|
@pytest.mark.parametrize("algo, param", [["mono_room", 0.1],
|
|
["mono_room", 1],
|
|
["mono_room", 4],
|
|
["stereo_room", 0.1],
|
|
["stereo_room", 1],
|
|
["stereo_room", 4],
|
|
["stereo_plate", 0.1],
|
|
["stereo_plate", 0.5],
|
|
["stereo_plate", 0.9],]
|
|
)
|
|
def test_reverb_frames(fs, q_format, algo, param):
|
|
# test the process_frame functions of the reverb components
|
|
|
|
# if q_format > 27:
|
|
# pytest.xfail("This test is not meant to pass with a q more then 27")
|
|
|
|
if algo == "stereo_room":
|
|
reverb = rvs.reverb_room_stereo(fs, 2, max_room_size=param, width=0, Q_sig=q_format)
|
|
|
|
signal = gen.log_chirp(fs, 0.5, 1)
|
|
t = np.arange(len(signal))/fs
|
|
signal *= np.sin(t*2*np.pi*0.5)
|
|
signal = np.tile(signal, [2, 1])
|
|
elif algo == "mono_room":
|
|
reverb = rv.reverb_room(fs, 1, max_room_size=param, Q_sig=q_format)
|
|
|
|
signal = gen.log_chirp(fs, 0.5, 1)
|
|
t = np.arange(len(signal))/fs
|
|
signal *= np.sin(t*2*np.pi*0.5)
|
|
signal = np.tile(signal, [1, 1])
|
|
elif algo == "stereo_plate":
|
|
reverb = rvp.reverb_plate_stereo(fs, 2, decay=param, width=0, Q_sig=q_format)
|
|
|
|
signal = gen.log_chirp(fs, 0.5, 1)
|
|
t = np.arange(len(signal))/fs
|
|
signal *= np.sin(t*2*np.pi*0.5)
|
|
signal = np.tile(signal, [2, 1])
|
|
|
|
frame_size = 1
|
|
signal_frames = utils.frame_signal(signal, frame_size, 1)
|
|
|
|
output_int = np.zeros_like(signal)
|
|
output_flt = np.zeros_like(signal)
|
|
|
|
for n in range(len(signal_frames)):
|
|
output_int[:, n*frame_size:(n+1)*frame_size] = reverb.process_frame_xcore(signal_frames[n])
|
|
reverb.reset_state()
|
|
for n in range(len(signal_frames)):
|
|
output_flt[:, n*frame_size:(n+1)*frame_size] = reverb.process_frame(signal_frames[n])
|
|
|
|
assert np.all(output_int[0, :] == output_int)
|
|
assert np.all(output_flt[0, :] == output_flt)
|
|
|
|
|
|
@pytest.mark.parametrize("ratio", [0, 0.5, 1])
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_wet_dry_mix(ratio, algo):
|
|
fs = 48000
|
|
q_format = 27
|
|
max_room_sz = 1
|
|
room_sz = 1
|
|
damp = 0.22
|
|
|
|
a = utils.db2gain(-10)
|
|
sig = gen.pink_noise(fs, 1, a)
|
|
|
|
if algo == "stereo_room":
|
|
sig = np.tile(sig, [2, 1])
|
|
verb = rvs.reverb_room_stereo(fs, 2, max_room_size=max_room_sz, damping=damp, room_size=room_sz, Q_sig=q_format)
|
|
elif algo =="mono_room":
|
|
verb = rv.reverb_room(fs, 1, max_room_size=max_room_sz, damping=damp, room_size=room_sz, Q_sig=q_format)
|
|
elif algo == "stereo_plate":
|
|
sig = np.tile(sig, [2, 1])
|
|
verb = rvp.reverb_plate_stereo(fs, 2, Q_sig=q_format)
|
|
|
|
verb.set_wet_dry_mix(ratio)
|
|
sig_py = np.zeros_like(sig)
|
|
sig_xc = np.zeros_like(sig)
|
|
if "stereo" in algo:
|
|
for i in range(sig.shape[1]):
|
|
sig_py[:, i] = verb.process_channels(sig[:, i])
|
|
verb.reset_state()
|
|
for i in range(sig.shape[1]):
|
|
sig_xc[:, i] = verb.process_channels_xcore(sig[:, i])
|
|
else:
|
|
for i in range(len(sig)):
|
|
sig_py[i] = verb.process(sig[i])
|
|
verb.reset_state()
|
|
for i in range(len(sig)):
|
|
sig_xc[i] = verb.process_xcore(sig[i])
|
|
|
|
# small signals are always going to be ropey due to quantizing, so just check average error of top half
|
|
top_half = utils.db(sig_py) > -50
|
|
if np.any(top_half):
|
|
error_vpu = np.abs(utils.db(sig_py[top_half])-utils.db(sig_xc[top_half]))
|
|
mean_error_vpu = utils.db(np.nanmean(utils.db2gain(error_vpu)))
|
|
assert mean_error_vpu < 0.005
|
|
|
|
def get_algo_partial(algo):
|
|
if algo =="stereo_room":
|
|
r = partial(rvs.reverb_room_stereo, 48000, 2)
|
|
elif algo =="mono_room":
|
|
r = partial(rv.reverb_room, 48000, 1)
|
|
elif algo =="stereo_plate":
|
|
r = partial(rvp.reverb_plate_stereo, 48000, 2)
|
|
|
|
return r
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_properties_decay(algo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
r = get_algo_partial(algo)
|
|
|
|
val = 0.1
|
|
a = r(decay=val)
|
|
b = r()
|
|
b.decay = val
|
|
|
|
should_be_val = np.array([i.decay for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_properties_pregain(algo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
r = get_algo_partial(algo)
|
|
|
|
val = 0.1
|
|
a = r(pregain=val)
|
|
b = r()
|
|
b.pregain = val
|
|
|
|
should_be_val = np.array([i.pregain for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_properties_wet_db(algo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
r = get_algo_partial(algo)
|
|
|
|
val = -6
|
|
a = r(wet_gain_db=val)
|
|
b = r()
|
|
b.wet_db = val
|
|
|
|
should_be_val = np.array([i.wet_db for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_properties_dry_db(algo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
r = get_algo_partial(algo)
|
|
|
|
val = -6
|
|
a = r(dry_gain_db=val)
|
|
b = r()
|
|
b.dry_db = val
|
|
|
|
should_be_val = np.array([i.dry_db for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
|
|
@pytest.mark.parametrize("algo", ["mono_room", "stereo_room", "stereo_plate"])
|
|
def test_reverb_properties_damping(algo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
r = get_algo_partial(algo)
|
|
|
|
val = 0.5
|
|
a = r(damping=val)
|
|
b = r()
|
|
b.damping = val
|
|
|
|
should_be_val = np.array([i.damping for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
@pytest.mark.parametrize("stereo", [True, False])
|
|
def test_reverb_properties_room_size(stereo):
|
|
"""Basic tests to check for consistency when setting the properties."""
|
|
if stereo:
|
|
r = partial(rvs.reverb_room_stereo, 48000, 2)
|
|
else:
|
|
r = partial(rv.reverb_room, 48000, 1)
|
|
|
|
val = 0.5
|
|
a = r(room_size=val)
|
|
b = r()
|
|
b.room_size = val
|
|
|
|
should_be_val = np.array([i.room_size for i in (a, b)])
|
|
np.testing.assert_allclose(should_be_val, val)
|
|
|
|
if __name__ == "__main__":
|
|
test_reverb_width("stereo_plate", 1)
|
|
# test_reverb_time(0.5, 0.25, 0.35, 29, 0.5, 1, "stereo_plate")
|
|
# test_reverb_overflow("sine", 20, "stereo_plate", 0.1)
|
|
# test_reverb_time(0.01, 1)
|
|
# test_reverb_frames(48000, 27, "stereo_plate", 0.5)
|
|
# test_reverb_wet_dry_mix(1.0, "stereo_plate")
|
|
# test_reverb_bypass_stereo()
|
|
# test_reverb_noise_floor_stereo(1.0, 1.0, 0)
|
|
# test_reverb_time(0.01, 1, 0, 31, 0.001, 0.5)
|
|
# test_reverb_properties_room_size(True)
|