Skip to content

Revert changes to transposeTpc#33325

Open
miiizen wants to merge 1 commit into
musescore:mainfrom
miiizen:33312-enharmonicTranspose
Open

Revert changes to transposeTpc#33325
miiizen wants to merge 1 commit into
musescore:mainfrom
miiizen:33312-enharmonicTranspose

Conversation

@miiizen
Copy link
Copy Markdown
Contributor

@miiizen miiizen commented May 8, 2026

Resolves: #33312

Reverts changes to transposeTpc made in #30139. The old implementation handles enharmonic transpositions, though not in the most clear way.

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The Transpose::transposeTpc function in src/engraving/editing/transpose.cpp was refactored to replace arithmetic-based TPC delta computation with a step and alteration search algorithm. The new implementation validates the input TPC early, derives diatonic steps and chromatic semitone shifts directly from the Interval parameter, then iteratively adjusts the target step and accidental alteration to find an acceptable value within the bounds set by the useDoubleSharpsFlats flag. The final TPC is computed from the resulting step and alteration values.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description provides issue reference and context but lacks most of the required template sections like CLA signing confirmation and review checklist. Complete the description template by adding checked/unchecked checkboxes for CLA, title verification, commit messages, code standards, compilation, and testing as specified in the template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Revert changes to transposeTpc' accurately describes the main change—reverting a previous modification to the transposeTpc function.
Linked Issues check ✅ Passed The code changes (reverting transposeTpc to previous implementation) directly address issue #33312 by restoring enharmonic transposition handling that was broken in PR #30139.
Out of Scope Changes check ✅ Passed The changes are narrowly scoped to reverting transposeTpc implementation as required; no additional unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/engraving/editing/transpose.cpp (3)

732-734: 💤 Low value

Misleading guard comment, and consider using tpcIsValid for consistency.

The comment // perfect unison & perfect octave does not describe this guard: TPC_INVALID is a general "no spelling" sentinel. The perfect-unison/zero-interval path is handled separately at lines 749–751. Additionally, transposeTpcDiatonicByKey (line 685) uses tpcIsValid(tpc) for the same kind of guard; using the bare sentinel comparison here is inconsistent and would pass through any out-of-range TPC value that isn't exactly TPC_INVALID.

♻️ Proposed cleanup
-    if (tpc == Tpc::TPC_INVALID) { // perfect unison & perfect octave
+    if (!tpcIsValid(tpc)) {
         return tpc;
     }
🤖 Prompt for 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.

In `@src/engraving/editing/transpose.cpp` around lines 732 - 734, The guard
comparing tpc to Tpc::TPC_INVALID is misleading and inconsistent with other
code; replace the bare sentinel check with a call to tpcIsValid(tpc) (i.e., if
(!tpcIsValid(tpc)) return tpc;) so any invalid/out-of-range TPC values are
consistently handled, and change the trailing comment to describe that this is a
general "invalid/no spelling" sentinel (not "perfect unison & perfect octave");
note that the perfect-unison path is handled elsewhere (as in
transposeTpcDiatonicByKey) so keep that separate.

748-788: 💤 Low value

Commented-out dead code — consider cleaning up as part of this revert.

Four commented-out LOGD statements (lines 748, 786, 788) and an alternative code fragment (lines 765–770) are legacy artifacts that rode along with the revert. They add visual noise and make the loop harder to read.

♻️ Proposed cleanup (remove commented-out lines)
-// LOGD("transposeTpc tpc %d steps %d semitones %d", tpc, steps, semitones);
     if (semitones == 0 && steps == 0) {
         return tpc;
     }
 ...
         alter  = semitones - (p1 - pitch);
-        // alter  = p1 + semitones - pitch;
-
-//            if (alter < 0) {
-//                  alter *= -1;
-//                  alter = 12 - alter;
-//                  }
         while (alter < 0) {
 ...
-//            LOGD("  again alter %d steps %d, step %d", alter, steps, step);
     }
-//      LOGD("  = step %d alter %d  tpc %d", step, alter, step2tpc(step, alter));
     return step2tpc(step, AccidentalVal(alter));
🤖 Prompt for 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.

In `@src/engraving/editing/transpose.cpp` around lines 748 - 788, The loop in
transposeTpc contains commented-out debug LOGD calls and an inactive alternative
implementation (the p1+semitones line and the commented block that flips alter)
that are dead code and should be removed to improve readability; edit
transposeTpc in transpose.cpp to delete the commented LOGD statements and the
obsolete alternative fragment (including the commented if(alter < 0) block and
the commented assignment alter = p1 + semitones - pitch) so only the active
logic remains, leaving variable names (step, alter, pitch, p1) and the loop
intact.

757-789: 💤 Low value

Silent fallback if the search loop does not converge.

If no valid alter is found within 10 iterations the function falls through and returns step2tpc(step, AccidentalVal(alter)) with alter still outside [minAlter, maxAlter], producing an out-of-range TPC silently. For every valid musical interval convergence is guaranteed in ≤ 3 iterations, so this is not a reachable failure path in practice — but the removed LOGD calls (now commented out) were the only diagnostic for detecting it. Adding a post-loop assertion or log would make pathological inputs visible during development.

♻️ Proposed observability addition
-//            LOGD("  again alter %d steps %d, step %d", alter, steps, step);
     }
-//      LOGD("  = step %d alter %d  tpc %d", step, alter, step2tpc(step, alter));
+    if (alter < minAlter || alter > maxAlter) {
+        LOGE("transposeTpc: failed to find valid alteration (tpc=%d, diatonic=%d, chromatic=%d)",
+             tpc, interval.diatonic, interval.chromatic);
+    }
     return step2tpc(step, AccidentalVal(alter));
🤖 Prompt for 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.

In `@src/engraving/editing/transpose.cpp` around lines 757 - 789, The loop in
transpose.cpp that searches for a valid alter may exit after 10 iterations
without meeting minAlter/maxAlter, then returns step2tpc(step,
AccidentalVal(alter)) silently; add a post-loop check using the same symbols
(step, alter, minAlter, maxAlter, steps) to detect non-convergence: if alter is
outside [minAlter, maxAlter] emit a diagnostic (LOGD/LOGE) or assert with
contextual info (step, steps, tpc, semitones, pitch) and then either clamp alter
into the allowed range before calling step2tpc or fail fast, so pathological
inputs are visible during development.
🤖 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.

Nitpick comments:
In `@src/engraving/editing/transpose.cpp`:
- Around line 732-734: The guard comparing tpc to Tpc::TPC_INVALID is misleading
and inconsistent with other code; replace the bare sentinel check with a call to
tpcIsValid(tpc) (i.e., if (!tpcIsValid(tpc)) return tpc;) so any
invalid/out-of-range TPC values are consistently handled, and change the
trailing comment to describe that this is a general "invalid/no spelling"
sentinel (not "perfect unison & perfect octave"); note that the perfect-unison
path is handled elsewhere (as in transposeTpcDiatonicByKey) so keep that
separate.
- Around line 748-788: The loop in transposeTpc contains commented-out debug
LOGD calls and an inactive alternative implementation (the p1+semitones line and
the commented block that flips alter) that are dead code and should be removed
to improve readability; edit transposeTpc in transpose.cpp to delete the
commented LOGD statements and the obsolete alternative fragment (including the
commented if(alter < 0) block and the commented assignment alter = p1 +
semitones - pitch) so only the active logic remains, leaving variable names
(step, alter, pitch, p1) and the loop intact.
- Around line 757-789: The loop in transpose.cpp that searches for a valid alter
may exit after 10 iterations without meeting minAlter/maxAlter, then returns
step2tpc(step, AccidentalVal(alter)) silently; add a post-loop check using the
same symbols (step, alter, minAlter, maxAlter, steps) to detect non-convergence:
if alter is outside [minAlter, maxAlter] emit a diagnostic (LOGD/LOGE) or assert
with contextual info (step, steps, tpc, semitones, pitch) and then either clamp
alter into the allowed range before calling step2tpc or fail fast, so
pathological inputs are visible during development.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: df058d0e-1a96-4788-8801-aede76121794

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab3094 and c037ebc.

📒 Files selected for processing (1)
  • src/engraving/editing/transpose.cpp

@igorkorsukov igorkorsukov changed the base branch from master to main May 14, 2026 14:14
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.

Transpose fails between enharmonically equivalent key signatures

2 participants