-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding mixing functionality #196
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. Comments inline.
################################################## | ||
|
||
def convolve(self, other, method='auto', normalize=True, | ||
scale=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs needed for all of these methods
@@ -102,3 +102,7 @@ | |||
# that use the level_in argument: | |||
LEVEL_MIN = .015625 | |||
LEVEL_MAX = 64 | |||
|
|||
MIN_LOUDNESS = -70 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a comment with units.
direct: The convolution is determined directly from sums, the definition of convolution. | ||
fft: The Fourier Transform is used to perform the convolution by calling fftconvolve. | ||
auto: Automatically chooses direct or Fourier method based on an estimate of which is faster (default). | ||
normalize: Whether to apply a normalization factor which will prevent clipping. Defaults to True. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think normalize
and scale
are very similar, and happen at different points in this function, so it'd be nice to have some clarity about the difference between these two args in the docs.
s1_ch, s2_ch / factor, mode='full', method=method) | ||
output.append(convolved_ch) | ||
else: | ||
for i, s1_ch in enumerate(signal.get_channels()): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need these enumerates()? You're not using the index vars.
convolved_ch = scipy.signal.convolve( | ||
s1_ch, s2_ch / factor, mode='full', method=method) | ||
output.append(convolved_ch) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pedantic: Maybe add a comment saying that at least one of these for loops is over 1 item. Wasn't clear to me at first.
n_loudness = max(MIN_LOUDNESS, bg_signal.loudness()) | ||
loudness = max(MIN_LOUDNESS, fg_signal.loudness()) | ||
|
||
if loudness - snr < MIN_LOUDNESS: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this logic be replaced with np.clip()
? If not, an explanatory comment would be nice to get an overview.
bg_signal.zero_pad(0, pad_len) | ||
bg_signal.truncate_samples(fg_signal.signal_length) | ||
|
||
n_loudness = max(MIN_LOUDNESS, bg_signal.loudness()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you find more descriptive variable names for n_loudness
, loudness
, and t_loudness
? They're hard to keep straight @ line 126 when you do the computation.
pad_len = max(0, fg_signal.signal_length - bg_signal.signal_length) | ||
bg_signal.zero_pad(0, pad_len) | ||
bg_signal.truncate_samples(fg_signal.signal_length) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like here we should be doing some checks to make sure things like sample_rate, n_channels, & length are OK. Maybe call utils.verify_audio_signal_list_strict([fg_signal, bg_signal])
here.
fg_signal = copy.deepcopy(fg_signal) | ||
bg_signal = copy.deepcopy(bg_signal) | ||
|
||
pad_len = max(0, fg_signal.signal_length - bg_signal.signal_length) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two things:
- I think you should bubble up whether to do
min(len(fg), len(bg))
and truncate the longer one ormax(len(fg), len(bg))
and pad the shorter one. (I don't think the former is useful, but I figure why not give the option to the user?) I think the opinionated way you've written it now is too subtle and could cause unintended side effects. - Should that be it's own subroutine? Not sure if it's much use outside this function, but maybe
def _match_signal_lengths(signal_list, mode='pad')
or even something on AudioSignal likesignal1.match_length(signal2)
. Just spitballing, lmk what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw: By "bubble up" I mean add an arg for the user.
normalize=normalize, scale=scale) | ||
|
||
def mix(self, other, snr=10): | ||
from . import mixing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this lazy import is to avoid a circular import?
This PR adds convolution reverb functionality to AudioSignal, following discussion in #172. The functionality is:
It also adds a method to mix two signals together at a specified signal-to-noise ratio.
Checklist: