From dc47e5071ab7e3f7cb285e068cac9e964949ed4d Mon Sep 17 00:00:00 2001 From: ddey <6568233+daniel-deychakiwsky@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:47:06 -0500 Subject: [PATCH 1/3] [PATCH-5] make hop_length configurable --- .../callbacks/spectrogram_visualization.py | 13 ++++---- .../test_spectrogram_visualization.py | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/realbook/callbacks/spectrogram_visualization.py b/realbook/callbacks/spectrogram_visualization.py index 405538a..3d957c6 100644 --- a/realbook/callbacks/spectrogram_visualization.py +++ b/realbook/callbacks/spectrogram_visualization.py @@ -135,11 +135,13 @@ def on_train_begin(self, logs: Any = None) -> None: # Ignore the single channel dimension, if it exists. spectrograms = spectrograms[:, :, :, 0] - # We can infer the hop length, as we know the input audio length - # and sample rate used in the spectrogram - length_in_samples = data.shape[-1] - length_in_frames = spectrograms.shape[-2] - hop_length = int(tf.math.ceil(length_in_samples / length_in_frames)) + if "hop_length" not in self.specshow_arguments: + # We can infer the hop length, as we know the input audio length + # and sample rate used in the spectrogram + length_in_samples = data.shape[-1] + length_in_frames = spectrograms.shape[-2] if self.transpose else spectrograms.shape[-1] + hop_length = int(tf.math.ceil(length_in_samples / length_in_frames)) + self.specshow_arguments["hop_length"] = hop_length figs = [] for spectrogram in spectrograms: @@ -157,7 +159,6 @@ def on_train_begin(self, logs: Any = None) -> None: img = librosa.display.specshow( spectrogram, sr=self.sample_rate_hz, - hop_length=hop_length, ax=ax, **self.specshow_arguments, ) diff --git a/tests/callbacks/test_spectrogram_visualization.py b/tests/callbacks/test_spectrogram_visualization.py index 6e7ac9c..2ceab77 100644 --- a/tests/callbacks/test_spectrogram_visualization.py +++ b/tests/callbacks/test_spectrogram_visualization.py @@ -350,3 +350,36 @@ def test_enable_colorbar() -> None: model.fit(fake_data, callbacks=[cb]) assert True + + +@pytest.mark.skipif( + SpectrogramVisualizationCallback is None, + reason="SpectrogramVisualizationCallback import fails on this platform", +) +def test_set_hop_length() -> None: + fake_data = tf.data.Dataset.zip( + ( + tf.data.Dataset.from_tensor_slices([TEST_AUDIO]), + tf.data.Dataset.from_tensor_slices([1]), + ) + ).batch(1) + + model = tf.keras.Sequential( + [ + tf.keras.Input(shape=(None,)), + Spectrogram(), + tf.keras.layers.Dense(1), + ] + ) + model.compile(loss="binary_crossentropy") + + cb = SpectrogramVisualizationCallback( + FakeWriter(), + fake_data, + sample_rate=DEFAULT_SAMPLE_RATE, + raise_on_error=True, + hop_length=1024, + ) + + model.fit(fake_data, callbacks=[cb]) + assert True From ff631f12cd9d76fcc762f8e679528a15b92567c0 Mon Sep 17 00:00:00 2001 From: ddey <6568233+daniel-deychakiwsky@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:54:26 -0500 Subject: [PATCH 2/3] [PATCH-5] document hop_length behavior in docstring --- realbook/callbacks/spectrogram_visualization.py | 1 + 1 file changed, 1 insertion(+) diff --git a/realbook/callbacks/spectrogram_visualization.py b/realbook/callbacks/spectrogram_visualization.py index 3d957c6..d3037a1 100644 --- a/realbook/callbacks/spectrogram_visualization.py +++ b/realbook/callbacks/spectrogram_visualization.py @@ -63,6 +63,7 @@ class SpectrogramVisualizationCallback(tf.keras.callbacks.Callback): - transpose: whether to transpose the spectrogram before plotting it. - add_colorbar: whether to add a colorbar to the spectrogram plot. - Any remaining keyword arguments are passed through to librosa.display.specshow. + If `hop_length` is not set, it is inferred. """ def __init__( From a57755ce78d05800e8ba823077ce9568c1d0b842 Mon Sep 17 00:00:00 2001 From: ddey <6568233+daniel-deychakiwsky@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:22:09 -0500 Subject: [PATCH 3/3] trigger GitHub actions