diff --git a/HISTORY.rst b/HISTORY.rst index 0bff24c4..a0cd1a06 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,14 @@ History ======= +1.1.0 (2026-05-19) +------------------ + +Changed: +^^^^^^^^ +- Replaced the `freq` parameter with `smoothing_parameter` in the edc functions, added deprecation warnings and deprecation tests (PR #152) + + 1.0.1 (2026-05-05) ------------------ diff --git a/examples/energy_decay_curves_and_reverberation_time.ipynb b/examples/energy_decay_curves_and_reverberation_time.ipynb index a4e3c8c2..0126506b 100644 --- a/examples/energy_decay_curves_and_reverberation_time.ipynb +++ b/examples/energy_decay_curves_and_reverberation_time.ipynb @@ -190,10 +190,13 @@ " The room impulse response with dimension [..., n_samples]\n", "sampling_rate: integer\n", " The sampling rate of the room impulse response.\n", - "freq: integer OR string\n", - " The frequency band. If set to 'broadband',\n", - " the time window of the Lundeby-algorithm will not be set in dependence\n", - " of frequency.\n", + "smoothing_parameter : int or array_like of int or {'broadband'}\n", + " Used to determine the smoothing time window in the Lundeby\n", + " algorithm. It should represent the center frequency (in Hz) of the\n", + " frequency band(s) in which the RIR data was computed.\n", + " If set to 'broadband', the smoothing time window will not be set\n", + " in dependence of frequency and a fixed time window of 30 ms\n", + " is used.\n", "noise_level: ndarray, double OR string\n", " If not specified, the noise level is calculated based on the last 10\n", " percent of the RIR. Otherwise specify manually for each channel\n", @@ -276,7 +279,7 @@ "source": [ "intersection_time, late_reveberation_time, noise_level_lundeby = \\\n", " ra.edc.intersection_time_lundeby(\n", - " rir_1_noise, freq='broadband', is_energy=False,\n", + " rir_1_noise, smoothing_parameter='broadband', is_energy=False,\n", " time_shift=True, channel_independent=False, plot=True)\n", "\n", "output_string = \"The estimated intersection time is {}s, the late reverberation time is {}s and the estimated noise is {}dB.\".format(intersection_time, late_reveberation_time, 10*np.log10(np.abs(noise_level_lundeby)))\n", @@ -297,7 +300,7 @@ "outputs": [], "source": [ "edc_truncation = ra.edc.energy_decay_curve_truncation(\n", - " rir_1_noise, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_1_noise, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", "\n", "plt.figure(figsize=(10, 4))\n", @@ -422,7 +425,7 @@ "outputs": [], "source": [ "edc_chu_lundeby = ra.edc.energy_decay_curve_chu_lundeby(\n", - " rir_1_noise, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_1_noise, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", "\n", "plt.figure(figsize=(10, 4))\n", diff --git a/pyrato/dsp.py b/pyrato/dsp.py index d917de42..9a4285f5 100644 --- a/pyrato/dsp.py +++ b/pyrato/dsp.py @@ -142,7 +142,7 @@ def _smooth_rir( The room impulse response with dimension ``(..., n_samples)``. sampling_rate: integer Defines the sampling rate of the room impulse response. - smooth_block_length : double + smooth_block_length : double or array-like of double Defines the block-length of the smoothing algorithm in seconds. Returns @@ -156,26 +156,42 @@ def _smooth_rir( """ cshape = data.shape[:-1] - data = np.atleast_2d(data) n_samples = data.shape[-1] + data = data.reshape(-1, n_samples) + smooth_block_length = (np.atleast_1d(smooth_block_length)).flatten() + n_channels = len(smooth_block_length) n_samples_nan = np.count_nonzero(np.isnan(data), axis=-1) - n_samples_per_block = int(np.round(smooth_block_length * sampling_rate, 0)) + n_samples_per_block = (np.round( + smooth_block_length * sampling_rate, 0)).astype(int) n_blocks = np.asarray( np.floor((n_samples-n_samples_nan)/n_samples_per_block), dtype=int) - # average data in blocks - n_blocks_min = int(np.min(n_blocks)) - n_samples_actual = int(n_blocks_min*n_samples_per_block) - reshaped_array = np.reshape( - data[..., :n_samples_actual], - (*cshape, n_blocks_min, n_samples_per_block)) - time_window_data = np.mean(reshaped_array, axis=-1) - + n_blocks_min = (np.min(n_blocks)).astype(int) + n_samples_actual = (n_blocks_min*n_samples_per_block).astype(int) + time_window_data = np.empty((n_channels, n_blocks_min)) # Use average time instances corresponding to the average energy level # instead of time for the first sample of the block - time_vector_window = \ + if n_channels > 1: + for ch in range(n_channels): + reshaped_array = np.reshape( + data[ch, :n_samples_actual[ch]], + (n_blocks_min, n_samples_per_block[ch])) + time_window_data[ch, :] = np.mean(reshaped_array, axis=-1) + time_vector_window = ( + (0.5+np.arange(0, n_blocks_min)).reshape(1, -1) * ( + n_samples_per_block/sampling_rate).reshape(-1, 1)) + time_window_data = np.reshape( + time_window_data, (cshape + (n_blocks_min,))) + time_vector_window = np.reshape( + time_vector_window, (cshape + (n_blocks_min,))) + else: + reshaped_array = np.reshape( + data[..., :n_samples_actual[0]], + (-1, n_blocks_min, n_samples_per_block[0])) + time_window_data = np.mean(reshaped_array, axis=-1) + time_vector_window = \ ((0.5+np.arange(0, n_blocks_min)) * n_samples_per_block/sampling_rate) # Use the time corresponding to the sampling of the original data diff --git a/pyrato/edc.py b/pyrato/edc.py index 47ab2c23..e3f45558 100644 --- a/pyrato/edc.py +++ b/pyrato/edc.py @@ -187,9 +187,13 @@ def _schroeder_integration(impulse_response, is_energy=False): return energy_decay_curve +@pf._utils.rename_arg( + {"freq" : "smoothing_parameter"}, + "'freq' will be deprecated in " + "pyrato 1.1.0 in favor of 'smoothing_parameter'") def energy_decay_curve_truncation( data, - freq='broadband', + smoothing_parameter='broadband', noise_level='auto', is_energy=False, time_shift=True, @@ -218,10 +222,13 @@ def energy_decay_curve_truncation( ---------- data : pyfar.Signal The room impulse response. - freq: integer OR string - The frequency band. If set to 'broadband', - the time window of the Lundeby-algorithm will not be set in dependence - of frequency. + smoothing_parameter : int or array_like of int or {'broadband'} + Used to determine the smoothing time window in the Lundeby + algorithm. It should represent the center frequency (in Hz) of the + frequency band(s) in which the RIR data was computed. + If set to 'broadband', the smoothing time window will not be set + in dependence of frequency and a fixed time window of 30 ms + is used. noise_level: ndarray, double OR string If not specified, the noise level is calculated based on the last 10 percent of the RIR. Otherwise specify manually for each channel @@ -301,7 +308,7 @@ def energy_decay_curve_truncation( intersection_time = intersection_time_lundeby( energy_data, - freq=freq, + smoothing_parameter=smoothing_parameter, initial_noise_power=noise_level, is_energy=True, time_shift=False, @@ -350,9 +357,13 @@ def energy_decay_curve_truncation( return edc +@pf._utils.rename_arg( + {"freq" : "smoothing_parameter"}, + "'freq' will be deprecated in " + "pyrato 1.1.0 in favor of 'smoothing_parameter'") def energy_decay_curve_lundeby( data, - freq='broadband', + smoothing_parameter='broadband', noise_level='auto', is_energy=False, time_shift=True, @@ -381,10 +392,13 @@ def energy_decay_curve_lundeby( ---------- data : pyfar.Signal The room impulse response. - freq: integer OR string - The frequency band. If set to 'broadband', - the time window of the Lundeby-algorithm will not be set in dependence - of frequency. + smoothing_parameter : int or array_like of int or {'broadband'} + Used to determine the smoothing time window in the Lundeby + algorithm. It should represent the center frequency (in Hz) of the + frequency band(s) in which the RIR data was computed. + If set to 'broadband', the smoothing time window will not be set + in dependence of frequency and a fixed time window of 30 ms + is used. noise_level: ndarray, double OR string If not specified, the noise level is calculated based on the last 10 percent of the RIR. Otherwise specify manually for each channel @@ -462,7 +476,7 @@ def energy_decay_curve_lundeby( intersection_time, late_reverberation_time, noise_estimation = \ intersection_time_lundeby( energy_data, - freq=freq, + smoothing_parameter=smoothing_parameter, initial_noise_power=noise_level, is_energy=True, time_shift=False, @@ -653,9 +667,13 @@ def energy_decay_curve_chu( return edc +@pf._utils.rename_arg( + {"freq" : "smoothing_parameter"}, + "'freq' will be deprecated in " + "pyrato 1.1.0 in favor of 'smoothing_parameter'") def energy_decay_curve_chu_lundeby( data, - freq='broadband', + smoothing_parameter='broadband', noise_level='auto', is_energy=False, time_shift=True, @@ -686,10 +704,13 @@ def energy_decay_curve_chu_lundeby( ---------- data : pyfar.Signal The room impulse response. - freq: integer OR string - The frequency band. If set to 'broadband', - the time window of the Lundeby-algorithm will not be set in dependence - of frequency. + smoothing_parameter : int or array_like of int or {'broadband'} + Used to determine the smoothing time window in the Lundeby + algorithm. It should represent the center frequency (in Hz) of the + frequency band(s) in which the RIR data was computed. + If set to 'broadband', the smoothing time window will not be set + in dependence of frequency and a fixed time window of 30 ms + is used. noise_level: ndarray, double OR string If not specified, the noise level is calculated based on the last 10 percent of the RIR. Otherwise specify manually for each channel @@ -770,7 +791,7 @@ def energy_decay_curve_chu_lundeby( intersection_time, late_reverberation_time, noise_level = \ intersection_time_lundeby( energy_data, - freq=freq, + smoothing_parameter=smoothing_parameter, initial_noise_power=noise_level, is_energy=True, time_shift=False, @@ -824,9 +845,13 @@ def energy_decay_curve_chu_lundeby( return edc +@pf._utils.rename_arg( + {"freq" : "smoothing_parameter"}, + "'freq' will be deprecated in " + "pyrato 1.1.0 in favor of 'smoothing_parameter'") def intersection_time_lundeby( data, - freq='broadband', + smoothing_parameter='broadband', initial_noise_power='auto', is_energy=False, time_shift=False, @@ -843,10 +868,15 @@ def intersection_time_lundeby( ---------- data : pyfar.Signal The room impulse response - freq: integer OR string - The frequency band. If set to 'broadband', - the time window of the Lundeby-algorithm will not be set in dependence - of frequency. + smoothing_parameter : scalar or array_like of scalar or {'broadband'} + Used to determine the smoothing time window in the Lundeby + algorithm. It should represent the center frequency (in Hz) of the + frequency band(s) in which the RIR data was computed. + If set to 'broadband', the smoothing time window will not be set + in dependence of frequency and a fixed time window of 30 ms + is used. + If set to an array_like, the length of the array must match + the number of frequency bands in the RIR data, i.e., data.cshape[0]. initial_noise_power: ndarray, double OR string If ``'auto'``, the noise level is calculated based on the last 10 percent of the RIR. Otherwise specify manually for each channel @@ -942,11 +972,30 @@ def intersection_time_lundeby( sampling_rate = np.round(1/np.diff(data.times).mean(), decimals=4) energy_data = energy_data.time - if freq == "broadband": + # number of frequency bands given by first channel axis + n_bands = data.cshape[0] + if smoothing_parameter == "broadband": # broadband: use 30 ms windows sizes - freq_dependent_window_time = 0.03 + freq_dependent_window_time = np.atleast_1d([0.03] * n_bands) + elif isinstance(smoothing_parameter, (int, float, list, + tuple, np.ndarray)): + smoothing_parameter = np.atleast_1d(smoothing_parameter) + if smoothing_parameter.size == 1: + smoothing_parameter = np.tile(smoothing_parameter, n_bands) + elif smoothing_parameter.size != n_bands: + raise ValueError( + "The size of smoothing_parameter must match the number of " + "frequency bands.") + freq_dependent_window_time = (800 / smoothing_parameter + 10) / 1000 else: - freq_dependent_window_time = (800/freq+10) / 1000 + raise TypeError( + "smoothing_parameter must be an int or float, an array_like" + " of int or float, or 'broadband'") + + freq_dependent_window_time = np.broadcast_to( + freq_dependent_window_time.reshape( + n_bands, *([1] * (len(data.cshape) - 1))), + data.cshape).copy() # (1) SMOOTH time_window_data, time_vector_window, time_vector = dsp._smooth_rir( @@ -965,12 +1014,12 @@ def intersection_time_lundeby( noise_peak_level = np.zeros(data.cshape, data.time.dtype) for ch in np.ndindex(data.cshape): - output = _intersection_time_lundby( - time_window_data[ch], noise_estimation[ch], energy_data[ch], - time_vector_window, dB_above_noise, n_intervals_per_10dB, - use_dyn_range_for_regression, sampling_rate, ch, failure_policy) - + time_window_data[ch], noise_estimation[ch], energy_data[ch], + np.squeeze(np.atleast_2d(time_vector_window)[ch]), + dB_above_noise, n_intervals_per_10dB, + use_dyn_range_for_regression, sampling_rate, + ch, failure_policy) if output is None: reverberation_time[ch] = np.nan noise_level[ch] = np.nan diff --git a/tests/test_data/generate_test_data.py b/tests/test_data/generate_test_data.py index 702a8aba..11c20966 100644 --- a/tests/test_data/generate_test_data.py +++ b/tests/test_data/generate_test_data.py @@ -100,24 +100,24 @@ substracted_2D = pyrato.edc.subtract_noise_from_squared_rir(rir_array**2) edc_truncation_1D = pyrato.energy_decay_curve_truncation( - rir_array[0], freq='broadband', is_energy=False, time_shift=True, + rir_array[0], smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True) edc_truncation_2D = pyrato.energy_decay_curve_truncation( - rir_array, freq='broadband', is_energy=False, time_shift=True, + rir_array, smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True) edc_lundeby_1D = pyrato.energy_decay_curve_lundeby( - rir_array[0], freq='broadband', is_energy=False, time_shift=True, + rir_array[0], smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True, plot=False) edc_lundeby_2D = pyrato.energy_decay_curve_lundeby( - rir_array, freq='broadband', is_energy=False, time_shift=True, + rir_array, smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True, plot=False) edc_lundeby_chu_1D = pyrato.energy_decay_curve_chu_lundeby( - rir_array[0], freq='broadband', is_energy=False, time_shift=True, + rir_array[0], smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True, plot=False) edc_lundeby_chu_2D = pyrato.energy_decay_curve_chu_lundeby( - rir_array, freq='broadband', is_energy=False, time_shift=True, + rir_array, smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, normalize=True, plot=False) edc_chu_1D = pyrato.energy_decay_curve_chu( @@ -128,10 +128,10 @@ channel_independent=False, normalize=True, plot=False) intersection_time_1D = pyrato.intersection_time_lundeby( - rir_array[0], freq='broadband', is_energy=False, time_shift=True, + rir_array[0], smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, plot=False) intersection_time_2D = pyrato.intersection_time_lundeby( - rir_array, freq='broadband', is_energy=False, time_shift=True, + rir_array, smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, plot=False) # noise_energy_from_edc_1D = pyrato.edc.estimate_noise_energy_from_edc( diff --git a/tests/test_data/test_notebook.ipynb b/tests/test_data/test_notebook.ipynb index e359199a..5ca91a7c 100644 --- a/tests/test_data/test_notebook.ipynb +++ b/tests/test_data/test_notebook.ipynb @@ -168,38 +168,38 @@ " substracted_2D = nh.subtract_noise_from_squared_rir(rir_array**2)\n", "\n", " edc_truncation_1D = nh.energy_decay_curve_truncation(\n", - " rir_array[0], sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array[0], sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True)\n", " edc_truncation_2D = nh.energy_decay_curve_truncation(\n", - " rir_array, sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array, sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True)\n", "\n", " edc_lundeby_1D = nh.energy_decay_curve_lundeby(\n", - " rir_array[0], sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array[0], sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", " edc_lundeby_2D = nh.energy_decay_curve_lundeby(\n", - " rir_array, sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array, sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", "\n", " edc_lundeby_chu_1D = nh.energy_decay_curve_chu_lundeby(\n", - " rir_array[0], sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array[0], sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", " edc_lundeby_chu_2D = nh.energy_decay_curve_chu_lundeby(\n", - " rir_array, sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array, sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", "\n", " edc_chu_1D = nh.energy_decay_curve_chu(\n", - " rir_array[0], sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array[0], sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", " edc_chu_2D = nh.energy_decay_curve_chu(\n", - " rir_array, sampling_rate, freq='broadband', is_energy=False, time_shift=True,\n", + " rir_array, sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=True,\n", " channel_independent=False, normalize=True, plot=False)\n", "\n", " intersection_time_1D = nh.intersection_time_lundeby(\n", - " rir_array[0], sampling_rate, freq='broadband', is_energy=False, time_shift=False,\n", + " rir_array[0], sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=False,\n", " channel_independent=False, plot=False)\n", " intersection_time_2D = nh.intersection_time_lundeby(\n", - " rir_array, sampling_rate, freq='broadband', is_energy=False, time_shift=False,\n", + " rir_array, sampling_rate, smoothing_parameter='broadband', is_energy=False, time_shift=False,\n", " channel_independent=False, plot=False)\n", "\n", " noise_energy_from_edc_1D = nh.estimate_noise_energy_from_edc(\n", diff --git a/tests/test_deprecation_warnings.py b/tests/test_deprecation_warnings.py index 9d5457c1..cef13ca1 100644 --- a/tests/test_deprecation_warnings.py +++ b/tests/test_deprecation_warnings.py @@ -1,6 +1,10 @@ import pytest import pyrato +import pyfar +import os from packaging import version +from numpy import genfromtxt +from pyfar.classes.warnings import PyfarDeprecationWarning # deprecate in 1.0.0 ---------------------------------------------------------- @@ -34,3 +38,41 @@ def test_deprecation_find_impulse_response_start(): if version.parse(pyrato.__version__) >= version.parse('1.0.0'): with pytest.raises(AttributeError): _ = pyrato.dsp.find_impulse_response_start + + +# deprecate in 1.1.0 ---------------------------------------------------------- +@pytest.mark.parametrize("function", + [(pyrato.edc.energy_decay_curve_truncation), + (pyrato.edc.energy_decay_curve_chu_lundeby), + (pyrato.edc.energy_decay_curve_lundeby), + (pyrato.edc.intersection_time_lundeby)]) +def test_deprecation_edc_freq_parameter(function): + """Test deprecation of the 'freq' parameter in the edc functions.""" + + rir = pyfar.Signal(genfromtxt( + os.path.join((os.path.join(os.path.dirname(__file__), 'test_data')), + 'analytic_rir_psnr50_1D.csv'), delimiter=','), 3000) + if version.parse(pyrato.__version__) >= version.parse('1.1.0'): + with pytest.raises(AttributeError): + function(rir, freq='broadband') + + +@pytest.mark.parametrize("function", + [(pyrato.edc.energy_decay_curve_truncation), + (pyrato.edc.energy_decay_curve_chu_lundeby), + (pyrato.edc.energy_decay_curve_lundeby), + (pyrato.edc.intersection_time_lundeby)]) +def test_deprecation_warning_edc_freq_parameter(function): + """ + Test whether deprecation warnings are raised for the 'freq' parameter in + the edc functions. + """ + + rir = pyfar.Signal(genfromtxt( + os.path.join((os.path.join(os.path.dirname(__file__), 'test_data')), + 'analytic_rir_psnr50_1D.csv'), delimiter=','), 3000) + + with pytest.warns( + PyfarDeprecationWarning, match="'freq' will be deprecated in " + "pyrato 1.1.0 in favor of 'smoothing_parameter'"): + function(data=rir, freq='broadband') diff --git a/tests/test_edc_noise_handling.py b/tests/test_edc_noise_handling.py index 5b388759..2ed17ced 100644 --- a/tests/test_edc_noise_handling.py +++ b/tests/test_edc_noise_handling.py @@ -50,7 +50,7 @@ def test_edc_truncation_1D(): actual = enh.energy_decay_curve_truncation( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, @@ -63,7 +63,7 @@ def test_edc_truncation_1D(): actual = enh.energy_decay_curve_truncation( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, @@ -88,7 +88,7 @@ def test_edc_truncation_2D(): actual = enh.energy_decay_curve_truncation( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=True, @@ -107,7 +107,7 @@ def test_edc_lundeby_1D(): actual = enh.energy_decay_curve_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, @@ -126,7 +126,7 @@ def test_edc_lundeby_2D(): actual = enh.energy_decay_curve_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=True, @@ -145,7 +145,7 @@ def test_edc_lundeby_chu_1D(): actual = enh.energy_decay_curve_chu_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=False, @@ -164,7 +164,7 @@ def test_edc_lundeby_chu_2D(): actual = enh.energy_decay_curve_chu_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=True, channel_independent=True, @@ -243,7 +243,7 @@ def test_intersection_time_lundeby_single(): actual = enh.intersection_time_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=False, channel_independent=False, @@ -264,7 +264,7 @@ def test_intersection_time_lundeby_multichannel(): actual = enh.intersection_time_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=False, channel_independent=False, @@ -288,7 +288,7 @@ def test_intersection_time_lundeby_multi_dimensional(): actual = enh.intersection_time_lundeby( rir, - freq='broadband', + smoothing_parameter='broadband', is_energy=False, time_shift=False, channel_independent=False, @@ -296,6 +296,61 @@ def test_intersection_time_lundeby_multi_dimensional(): npt.assert_allclose(actual, expected) +def test_intersection_time_smoothing_parameter_error(): + """ + Test the errors if an incorrect type or value is specified for + the `smoothing_parameter` in the intersection_time_lundeby function. + """ + rir = pf.Signal(genfromtxt( + os.path.join(test_data_path, 'analytic_rir_psnr50_2D.csv'), + delimiter=','), 3e3) + with pytest.raises(ValueError, match="size of smoothing_parameter must" + " match the number of frequency bands."): + enh.intersection_time_lundeby(rir, smoothing_parameter=(125, 1e3, 4e3)) + with pytest.raises(TypeError, match="must be an int or float," + " an array_like of int or float, or 'broadband'"): + enh.intersection_time_lundeby(rir, smoothing_parameter=None) + with pytest.raises(TypeError, match="must be an int or float," + " an array_like of int or float, or 'broadband'"): + enh.intersection_time_lundeby(rir, smoothing_parameter=("brodband")) + + +def test_intersection_time_smoothing_parameter_array_like(): + """ + Test correct computation of the intersection time with an array-like + value for smoothing_parameter. + """ + rir = genfromtxt( + os.path.join(test_data_path, 'analytic_rir_psnr50_1D.csv'), + delimiter=',') + rir1 = pf.Signal(rir, 3e3) + rir2 = pf.Signal((rir, rir), 3e3) + # Calculate intersection_time_lundeby with int values for + # smoothing_parameter + ch1 = np.vstack( + enh.intersection_time_lundeby(rir1, smoothing_parameter=(125))) + ch2 = np.vstack( + enh.intersection_time_lundeby(rir1, smoothing_parameter=(1000))) + expected = np.hstack((ch1, ch2)) + # Calculate intersection_time_lundeby with an array-like value + # for smoothing_parameter + actual = np.vstack( + enh.intersection_time_lundeby(rir2, smoothing_parameter=(125, 1000))) + npt.assert_allclose(actual, expected) + + +def test_intersection_time_lundeby_smoothing_parameter_cdim2(): + """ + Test correct computation of the intersection time with 2-dimensional + cshape of the RIR. + """ + rir = pf.signals.files.room_impulse_response(crop_noise_tail=False) + rirs = rir.copy() + rirs = (pf.utils.concatenate_channels((rirs, rirs, rirs, rirs), 0) + ).reshape((2, 2)) + enh.intersection_time_lundeby(rirs, smoothing_parameter=[1e3, 4e3]) + + def test_intersection_time_failure_handling(): """Test warnings and errors when computing the intersection time."""