Skip to content

feat: New getR128Gain function to get track replay gain value#16

Merged
cyanChill merged 7 commits into
mainfrom
feat/replay-gain
Jun 3, 2026
Merged

feat: New getR128Gain function to get track replay gain value#16
cyanChill merged 7 commits into
mainfrom
feat/replay-gain

Conversation

@cyanChill

@cyanChill cyanChill commented Jun 3, 2026

Copy link
Copy Markdown
Member

This PR introduces a new getR128Gain function that returns the track replay gain value in the embedded metadata. Currently, we support and verified:

  • REPLAYGAIN_TRACK_GAIN in TXXX tag for ID3v2.
    • Represented by the TextInformationFrame class.
  • ReplayGain Xing/Info tag for ID3v2.
    • Represented by the Mp3InfoReplayGain class.

Note

We also support R128_TRACK_GAIN in TXXX tag, but have no files to verify.

We also support both tags in VorbisComment, but have no files to verify.

Supposedly, the range of values returned should be within ± 20.

Examples of Replay Gain in Embedded Metadata

entries=[
  TIT2: description=null: values=[One Way],
  ReplayGain Xing/Info: peak=0.0, field 1=GainField{name=1, originator=3, gain=-8.6}, field 2=null
]

entries=[
  TXXX: description=REPLAYGAIN_ALGORITHM: values=[BS.1770],
  TXXX: description=comment: values=[:R128_TRACK_GAIN:],
  TXXX: description=REPLAYGAIN_TRACK_GAIN: values=[-1.63 dB],
  TXXX: description=REPLAYGAIN_TRACK_PEAK: values=[0.588893],
  TXXX: description=REPLAYGAIN_ALBUM_GAIN: values=[-1.63 dB],
  TXXX: description=REPLAYGAIN_ALBUM_PEAK: values=[0.588893],
  TXXX: description=REPLAYGAIN_REFERENCE_LOUDNESS: values=[-18.00 LUFS],
  TXXX: description=REPLAYGAIN_TRACK_RANGE: values=[1.07 dB],
  TXXX: description=REPLAYGAIN_ALBUM_RANGE: values=[1.07 dB]
]

entries=[
  TXXX: description=replaygain_reference_loudness: values=[89.0 dB],
  TXXX: description=replaygain_track_gain: values=[+0.655000 dB],
  TXXX: description=replaygain_track_peak: values=[0.443497],
  TXXX: description=replaygain_album_gain: values=[-0.040000 dB],
  TXXX: description=replaygain_album_peak: values=[0.449919],
  TXXX: description=MP3GAIN_MINMAX: values=[110,181],
  TXXX: description=MP3GAIN_ALBUM_MINMAX: values=[061,205],
  TXXX: description=MP3GAIN_UNDO: values=[+005,+005,N]
]

Summary by CodeRabbit

  • New Features

    • Added a public API to fetch R128 replay gain values from audio tracks.
  • Bug Fixes

    • Improved lyric extraction to more safely handle text frames and stop earlier for synchronized lyrics.
  • Documentation

    • Updated the API reference with the new replay-gain function and its signature.

cyanChill added 2 commits June 2, 2026 19:49
- These are from know fields from files that I can work with.
  - I have files that use the `ReplayGain Xing/Info` tag and others with `TXXX`.
- We only return the value assocaited with the track and not the album-wide replay gain.
@cyanChill cyanChill added the enhancement New feature or request label Jun 3, 2026
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 61707781-3666-4a2a-bc75-c18a48e4bc85

📥 Commits

Reviewing files that changed from the base of the PR and between 8a66d92 and b3fb126.

📒 Files selected for processing (2)
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/utils/ReplayGainParser.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt

📝 Walkthrough

Walkthrough

Adds a getR128Gain API: a Kotlin ReplayGainParser, a native Android MetadataRetrieverModule method to expose the parsed gain, TypeScript TurboModule declaration and JS wrapper, small lyric-handling fixes, and README documentation.

Changes

Replay Gain Feature

Layer / File(s) Summary
Replay gain parsing utility
android/src/main/java/com/cyanchill/missingcore/metadataretriever/utils/ReplayGainParser.kt
ReplayGainParser class initializes a nullable gain by detecting Metadata.Entry subtypes (TextInformationFrame, Mp3InfoReplayGain, VorbisComment) and parsing sanitized numeric strings to Float.
Android native implementation
android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt
Imports ReplayGainParser, adds getR128Gain(uri, promise) that iterates metadata entries and resolves the first non-null gain or null; updates getLyric to use firstOrNull() and an extra if (isLyricsSync) break to control iteration; maps certain ExecutionExceptions to ENOENT and other failures to ERR_REPLAY_GAIN.
TypeScript bridge and public API
src/NativeMetadataRetriever.ts, src/index.ts
Adds getR128Gain(uri: string): Promise<number | null> to the TurboModule Spec and exports getR128Gain in src/index.ts delegating to the native MetadataRetriever.getR128Gain.
API documentation
README.md
Adds README API entry documenting getR128Gain(uri: string): Promise<number | null) with its TypeScript signature and a short description.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: introducing a new getR128Gain function for retrieving track replay gain values, which is the primary focus of this pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt`:
- Around line 309-318: The code can clobber a previously found non-null gain
because the inner break only exits the inner loop; ensure once a non-null gain
is found it is not overwritten by later metadata entries by capturing the parser
result into a candidate and if candidate != null assign to gain and break out of
the outer loop (use a labeled break, e.g., break@outer) or alternatively only
assign when gain is null and candidate is non-null; update the loops around
metadataList and ReplayGainParser(...) accordingly and keep the final
promise.resolve(gain) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 348134cf-3f4c-4ae5-95f6-ef6e159cd4e7

📥 Commits

Reviewing files that changed from the base of the PR and between 41e8395 and beb1ded.

📒 Files selected for processing (5)
  • README.md
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/utils/ReplayGainParser.kt
  • src/NativeMetadataRetriever.ts
  • src/index.ts

@cyanChill cyanChill marked this pull request as ready for review June 3, 2026 00:40
@cyanChill

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@android/src/main/java/com/cyanchill/missingcore/metadataretriever/utils/ReplayGainParser.kt`:
- Line 26: The code unsafely indexes frame.values[0] inside the
COMMON_REPLAY_GAIN_TAGS branch which can throw IndexOutOfBoundsException for
empty values; update the logic in ReplayGainParser (the branch that currently
returns frame.values[0].parseReplayGainAdjustment()) to first check
values.isNotEmpty() or use values.firstOrNull()?.parseReplayGainAdjustment() and
handle the null case (return null or a safe default) so empty value lists are
handled without throwing.
- Around line 24-27: handleTextInformationFrame currently assumes
frame.values[0] exists and treats R128 and REPLAYGAIN tags the same; update
handleTextInformationFrame(frame: TextInformationFrame) to first check that
frame.values is not empty (return null if empty) before indexing, and then call
a tag-aware parser: in parseReplayGainAdjustment (or add a helper used by that
function) detect the frame.description (or tag name) equal to R128_TRACK_GAIN
and parse its numeric value as Q7.8 fixed-point by dividing the parsed integer
by 256f, otherwise parse the usual REPLAYGAIN_TRACK_GAIN as a plain float;
ensure you reference the constants R128_TRACK_GAIN and REPLAYGAIN_TRACK_GAIN (or
COMMON_REPLAY_GAIN_TAGS) when choosing the parsing branch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 832b07f2-ad86-416d-9b32-7efe378fde50

📥 Commits

Reviewing files that changed from the base of the PR and between beb1ded and 8a66d92.

📒 Files selected for processing (2)
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/utils/ReplayGainParser.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataRetrieverModule.kt

@cyanChill

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cyanChill cyanChill merged commit 4f07ed8 into main Jun 3, 2026
4 checks passed
@cyanChill cyanChill deleted the feat/replay-gain branch June 3, 2026 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant