LCOV - code coverage report
Current view: top level - src/engraving/playback/utils - pitchutils.h Coverage Total Hit
Test: filtered_coverage.info Lines: 88.4 % 43 38
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #pragma once
      24              : 
      25              : #include "mpe/mpetypes.h"
      26              : 
      27              : #include "engraving/dom/pitchspelling.h"
      28              : 
      29              : namespace mu::engraving {
      30         1574 : inline muse::mpe::PitchClass pitchClassFromTpc(const int tpc)
      31              : {
      32         1574 :     switch (tpc) {
      33              :     // C
      34          268 :     case TPC_D_BB:
      35              :     case TPC_C:
      36              :     case TPC_B_S:
      37              :     case TPC_A_SSS:
      38          268 :         return muse::mpe::PitchClass::C;
      39           72 :     case TPC_E_BBB:
      40              :     case TPC_D_B:
      41              :     case TPC_C_S:
      42              :     case TPC_B_SS:
      43           72 :         return muse::mpe::PitchClass::C_sharp;
      44              : 
      45              :     // D
      46           92 :     case TPC_F_BBB:
      47              :     case TPC_E_BB:
      48              :     case TPC_D:
      49              :     case TPC_C_SS:
      50              :     case TPC_B_SSS:
      51           92 :         return muse::mpe::PitchClass::D;
      52           32 :     case TPC_F_BB:
      53              :     case TPC_E_B:
      54              :     case TPC_D_S:
      55              :     case TPC_C_SSS:
      56           32 :         return muse::mpe::PitchClass::D_sharp;
      57              : 
      58              :     // E
      59          100 :     case TPC_G_BBB:
      60              :     case TPC_F_B:
      61              :     case TPC_E:
      62              :     case TPC_D_SS:
      63          100 :         return muse::mpe::PitchClass::E;
      64              : 
      65              :     // F
      66          663 :     case TPC_G_BB:
      67              :     case TPC_F:
      68              :     case TPC_E_S:
      69              :     case TPC_D_SSS:
      70          663 :         return muse::mpe::PitchClass::F;
      71            1 :     case TPC_A_BBB:
      72              :     case TPC_G_B:
      73              :     case TPC_F_S:
      74              :     case TPC_E_SS:
      75            1 :         return muse::mpe::PitchClass::F_sharp;
      76              : 
      77              :     // G
      78           89 :     case TPC_A_BB:
      79              :     case TPC_G:
      80              :     case TPC_F_SS:
      81              :     case TPC_E_SSS:
      82           89 :         return muse::mpe::PitchClass::G;
      83            0 :     case TPC_B_BBB:
      84              :     case TPC_A_B:
      85              :     case TPC_G_S:
      86              :     case TPC_F_SSS:
      87            0 :         return muse::mpe::PitchClass::G_sharp;
      88              : 
      89              :     // A
      90          184 :     case TPC_C_BBB:
      91              :     case TPC_B_BB:
      92              :     case TPC_A:
      93              :     case TPC_G_SS:
      94          184 :         return muse::mpe::PitchClass::A;
      95            8 :     case TPC_C_BB:
      96              :     case TPC_B_B:
      97              :     case TPC_A_S:
      98              :     case TPC_G_SSS:
      99            8 :         return muse::mpe::PitchClass::A_sharp;
     100              : 
     101              :     // B
     102           65 :     case TPC_D_BBB:
     103              :     case TPC_C_B:
     104              :     case TPC_B:
     105              :     case TPC_A_SS:
     106           65 :         return muse::mpe::PitchClass::B;
     107              : 
     108            0 :     default:
     109            0 :         return muse::mpe::PitchClass::Undefined;
     110              :     }
     111              : }
     112              : 
     113         1574 : inline muse::mpe::octave_t actualOctave(const int nominalOctave, const muse::mpe::PitchClass nominalPitchClass,
     114              :                                         const AccidentalVal accidental)
     115              : {
     116         1574 :     int shift = static_cast<int>(nominalPitchClass) - static_cast<int>(accidental);
     117              : 
     118         1574 :     constexpr int lowerBound = 0;
     119         1574 :     constexpr int upperBound = muse::mpe::STEPS_PER_OCTAVE - 1;
     120              : 
     121         1574 :     if (shift < lowerBound) {
     122            2 :         return static_cast<muse::mpe::octave_t>(nominalOctave + 1);
     123              :     }
     124              : 
     125         1572 :     if (shift > upperBound) {
     126            0 :         return static_cast<muse::mpe::octave_t>(nominalOctave - 1);
     127              :     }
     128              : 
     129         1572 :     return static_cast<muse::mpe::octave_t>(nominalOctave);
     130              : }
     131              : 
     132         1558 : inline muse::mpe::pitch_level_t notePitchLevel(const int noteTpc, const int noteOctave, const double tuningCents = 0.0)
     133              : {
     134         1558 :     muse::mpe::PitchClass pitchClass = pitchClassFromTpc(noteTpc);
     135              : 
     136         1558 :     double tuningFactor = tuningCents / 100.0;
     137              : 
     138         1558 :     muse::mpe::pitch_level_t result = muse::mpe::pitchLevel(pitchClass, actualOctave(noteOctave, pitchClass, tpc2alter(noteTpc)));
     139         1558 :     result += tuningFactor * muse::mpe::PITCH_LEVEL_STEP;
     140              : 
     141         1558 :     return result;
     142              : }
     143              : }
        

Generated by: LCOV version 2.0-1