Skip to content

Conversation

@AkaakuHub
Copy link
Contributor

Summary

Adds audio normalization functionality to improve volume consistency in exported .osz files.

Key Features

  • Added "Normalize Audio" checkbox option in GUI and option in CLI
  • Normalizes audio volume when exporting to .osz format
  • Configurable target and minimum dB levels (-20.0 dBFS target, -35.0 dBFS minimum)

Technical Changes

  • config.py: Added normalize_audio boolean option
  • template/index.html: Added normalize audio checkbox with hidden config fields
  • osuT5/postprocessor.py: Added audio normalization processing for .osz exports
  • web-ui.py: Added parameter passing for normalization settings
  • inference.py: Integrated normalization into export pipeline

Benefits

  • Prevents quiet audio files in exported beatmaps

Testing

  • Verified normalization works with various audio volume levels
  • Confirmed .osz export includes properly normalized audio

@OliBomby OliBomby requested a review from Copilot November 23, 2025 09:26
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds audio normalization functionality to prevent quiet audio files in exported .osz beatmap files. Users can now optionally normalize audio volume during export through both GUI and CLI interfaces.

Key Changes:

  • Added a "Normalize Audio" checkbox in the web UI that appears when "Export .osz" is selected
  • Implemented audio normalization logic using pydub with configurable target dBFS levels
  • Integrated normalization into the .osz export pipeline with safety measures to prevent clipping

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
config.py Added normalize_audio boolean configuration option
configs/inference/default.yaml Added default value for normalize_audio parameter
template/index.html Added normalize audio checkbox with hidden target/min dBFS fields
static/app.js Added event handler to show/hide normalize audio option based on export_osz checkbox state
web-ui.py Added parameter passing for normalize_audio setting to inference command
cli_inference.sh Added CLI prompt for normalize audio option when exporting .osz
osuT5/osuT5/inference/postprocessor.py Implemented audio normalization function and integrated it into .osz export
inference.py Updated export_osz call to pass config for normalization

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

def normalize_audio_if_quiet(
self,
audio_path: str,
target_dbfs: float = -14.0, # More aggressive target for osu!
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring mentions -20.0 dBFS target (from PR description) but the default parameter is -14.0 dBFS. The comment 'More aggressive target for osu!' suggests -14.0 is intentional, but this should be documented in the function's docstring to explain why -14.0 was chosen over -20.0.

Copilot uses AI. Check for mistakes.
Comment on lines +538 to +544
temp_path = audio_path.replace('.', '_normalized.')
if '.' in audio_path:
# Keep the original extension
parts = audio_path.rsplit('.', 1)
temp_path = f"{parts[0]}_normalized.{parts[1]}"
else:
temp_path = f"{audio_path}_normalized.wav"
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 538 is redundant since it's immediately overwritten by the if-else block on lines 539-544. The initial assignment to temp_path serves no purpose and should be removed.

Copilot uses AI. Check for mistakes.
Comment on lines +971 to +974
$("#export_osz").on('change', () => {
const isChecked = $("#export_osz").is(':checked');
$("#normalize-audio-option").toggle(isChecked);
});
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normalize audio option visibility toggling should be integrated into the existing updateConditionalFields() method rather than using a separate event handler. This would maintain consistency with how other conditional fields are managed throughout the application.

Suggested change
$("#export_osz").on('change', () => {
const isChecked = $("#export_osz").is(':checked');
$("#normalize-audio-option").toggle(isChecked);
});
$("#export_osz").on('change', () => UIManager.updateConditionalFields());

Copilot uses AI. Check for mistakes.
Comment on lines +565 to +568
processed_audio_path = self.normalize_audio_if_quiet(
audio_path,
-14.0, # Fixed target dBFS for osu!
1.0 # Fixed safety margin
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The target dBFS (-14.0) and safety margin (1.0) are hardcoded in the export_osz method, but these values should use the hidden input fields from the HTML form (normalize_target_dbfs and normalize_min_dbfs). The hardcoded values make the HTML configuration fields non-functional.

Suggested change
processed_audio_path = self.normalize_audio_if_quiet(
audio_path,
-14.0, # Fixed target dBFS for osu!
1.0 # Fixed safety margin
target_dbfs = getattr(config, "normalize_target_dbfs", -14.0)
safety_margin = getattr(config, "normalize_min_dbfs", 1.0)
processed_audio_path = self.normalize_audio_if_quiet(
audio_path,
target_dbfs,
safety_margin

Copilot uses AI. Check for mistakes.
Comment on lines +174 to +175
<input type="hidden" id="normalize_target_dbfs" name="normalize_target_dbfs" value="-20.0" />
<input type="hidden" id="normalize_min_dbfs" name="normalize_min_dbfs" value="-35.0" />
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These hidden fields for normalize_target_dbfs and normalize_min_dbfs are defined but never read or passed through the pipeline. The postprocessor.py uses hardcoded values (-14.0 and 1.0) instead. Either wire these fields through the full pipeline or remove them if fixed values are intended.

Suggested change
<input type="hidden" id="normalize_target_dbfs" name="normalize_target_dbfs" value="-20.0" />
<input type="hidden" id="normalize_min_dbfs" name="normalize_min_dbfs" value="-35.0" />

Copilot uses AI. Check for mistakes.
Repository owner deleted a comment from Copilot AI Nov 23, 2025
@OliBomby
Copy link
Owner

Have you verified whether this normalization method always produces adequate volume levels for osu beatmaps regardless of source? Like are these defaults sane? Maybe some songs require compressor and gain to get enough volume while not clipping, or just need a better source.

@AkaakuHub
Copy link
Contributor Author

Thanks for the question. I haven’t validated that these defaults are universally sane across a wide range of osu! beatmaps. The normalization here is just a simple dBFS target and minimum floor; it won’t guarantee adequate loudness for all sources, and as you note some tracks really need proper compression/gain staging or a better source.

Given that, I’m totally fine if you’d rather not include this in the tool. I made this as I want to use this tool to make some osu! beatmaps for my own hobby.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants