Skip to content

Commit 237ca2b

Browse files
authored
Merge pull request #413 from iver56/ij/fix-noise-offset
Reproduce and fix a logic bug that led to wrong noise offset in AddBackgroundNoise
2 parents 341be5a + c31a8d3 commit 237ca2b

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

audiomentations/augmentations/add_background_noise.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ def randomize_parameters(self, samples: NDArray[np.float32], sample_rate: int):
113113
file_idx = random.randint(0, len(self.sound_file_paths) - 1)
114114
self.parameters["noise_file_path"] = self.sound_file_paths[file_idx]
115115

116-
if self.time_info_arr[file_idx] != -1.0:
116+
if self.time_info_arr[file_idx] == -1.0:
117117
self.time_info_arr[file_idx] = librosa.get_duration(
118118
path=self.parameters["noise_file_path"]
119119
)
120120

121-
noise_duration = self.time_info_arr[file_idx]
121+
noise_duration = float(self.time_info_arr[file_idx])
122122
signal_duration = len(samples) / sample_rate
123123

124124
min_noise_offset = 0.0

tests/test_add_background_noise.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
import random
33
import warnings
44

5+
import librosa
56
import numpy as np
67
import pytest
78

89
from audiomentations import AddBackgroundNoise, Reverse
910
from demo.demo import DEMO_DIR
11+
from tests.utils import fast_autocorr
1012

1113

1214
def test_add_background_noise():
@@ -23,6 +25,64 @@ def test_add_background_noise():
2325
assert samples_out.dtype == np.float32
2426

2527

28+
def test_background_noise_offset_variation():
29+
# Check variation in chosen offsets when noise is longer than signal
30+
np.random.seed(123)
31+
random.seed(456)
32+
samples = np.sin(np.linspace(0, 440 * 2 * np.pi, 500)).astype(np.float32)
33+
sample_rate = 44100
34+
noise_path = os.path.join(DEMO_DIR, "background_noises", "hens.ogg")
35+
augmenter = AddBackgroundNoise(sounds_path=noise_path, p=1.0)
36+
37+
offsets = set()
38+
for i in range(5):
39+
augmenter(samples=samples, sample_rate=sample_rate)
40+
offsets.add(augmenter.parameters["offset"])
41+
42+
assert len(offsets) >= 4 # we have many different values
43+
44+
45+
def test_background_noise_offset_and_duration():
46+
# Check the correctness of noise duration and offset
47+
np.random.seed(44)
48+
random.seed(55)
49+
samples = np.sin(np.linspace(0, 440 * 2 * np.pi, 500)).astype(np.float32)
50+
sample_rate = 2000
51+
noise_path = os.path.join(DEMO_DIR, "background_noises", "hens.ogg")
52+
noise, _ = librosa.load(path=noise_path, sr=sample_rate, mono=True)
53+
noise_duration = noise.shape[-1] / sample_rate
54+
augmenter = AddBackgroundNoise(
55+
sounds_path=noise_path,
56+
min_snr_db=20.0,
57+
max_snr_db=20.0,
58+
p=1.0,
59+
)
60+
samples_out = augmenter(samples=samples, sample_rate=sample_rate)
61+
62+
assert augmenter.time_info_arr[0] == pytest.approx(
63+
noise_duration, abs=1 / sample_rate
64+
)
65+
66+
added_noise = samples_out - samples
67+
68+
best_offset_int = -1
69+
max_corr_coef = 0.0
70+
for candidate_offset_int in range(0, noise.shape[-1] - samples.shape[-1]):
71+
candidate_noise_slice = noise[
72+
candidate_offset_int : candidate_offset_int + samples.shape[-1]
73+
]
74+
corr_coef = fast_autocorr(added_noise, candidate_noise_slice)
75+
if corr_coef > max_corr_coef:
76+
max_corr_coef = corr_coef
77+
best_offset_int = candidate_offset_int
78+
79+
assert max_corr_coef > 0.95
80+
actual_offset = best_offset_int / sample_rate
81+
assert augmenter.parameters["offset"] == pytest.approx(
82+
actual_offset, abs=1 / sample_rate
83+
)
84+
85+
2686
def test_add_background_noise_when_noise_sound_is_too_short():
2787
sample_rate = 44100
2888
samples = np.sin(np.linspace(0, 440 * 2 * np.pi, 14 * sample_rate)).astype(

tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def get_randn_test(sample_rate, duration):
6060
return samples.astype(np.float32)
6161

6262

63-
def fast_autocorr(original: NDArray, delayed: NDArray, t: int = 1):
63+
def fast_autocorr(original: NDArray, delayed: NDArray, t: int = 0):
6464
"""Only every 4th sample is considered in order to improve execution time"""
6565
if t == 0:
6666
return np.corrcoef([original[::4], delayed[::4]])[1, 0]

0 commit comments

Comments
 (0)