LCOV - code coverage report
Current view: top level - src/importexport/guitarpro/internal/guitarbendimport - bendinfoconverter.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 91.7 % 60 55
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) 2025 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              : #include "bendinfoconverter.h"
      23              : 
      24              : #include <engraving/dom/note.h>
      25              : 
      26              : using namespace mu::engraving;
      27              : 
      28              : namespace mu::iex::guitarpro {
      29          121 : ImportedBendInfo BendInfoConverter::fillBendInfo(const Note* note, const PitchValues& pitchValues)
      30              : {
      31              :     enum class PitchValuesDiff {
      32              :         NONE,
      33              :         SAME_PITCH_AND_TIME,
      34              :         SAME_PITCH_DIFF_TIME,
      35              :         INCREASED_PITCH_SAME_TIME,
      36              :         INCREASED_PITCH_DIFF_TIME,
      37              :         DECREASED_PITCH_DIFF_TIME
      38              :     };
      39              : 
      40              :     using pvd = PitchValuesDiff;
      41              : 
      42          121 :     ImportedBendInfo importedInfo;
      43              :     PitchValuesDiff currentPitchDiff;
      44          121 :     PitchValuesDiff previousPitchDiff = PitchValuesDiff::NONE;
      45              : 
      46          231 :     auto pitchDiff = [](const PitchValue& prev, const PitchValue& cur) {
      47          231 :         if (prev.pitch == cur.pitch) {
      48           86 :             return prev.time == cur.time ? pvd::SAME_PITCH_AND_TIME : pvd::SAME_PITCH_DIFF_TIME;
      49              :         }
      50              : 
      51          145 :         if (prev.time == cur.time) {
      52            0 :             return pvd::INCREASED_PITCH_SAME_TIME;
      53              :         }
      54              : 
      55          145 :         return prev.pitch < cur.pitch ? pvd::INCREASED_PITCH_DIFF_TIME : pvd::DECREASED_PITCH_DIFF_TIME;
      56              :     };
      57              : 
      58          140 :     auto addPrebendOrHold = [&importedInfo](const PitchValue& start) {
      59          140 :         importedInfo.timeOffsetFromStart = start.time;
      60          140 :         importedInfo.pitchOffsetFromStart = start.pitch;
      61          140 :         if (start.pitch > 0) {
      62           64 :             importedInfo.type = BendType::PREBEND;
      63              :         }
      64          261 :     };
      65              : 
      66          352 :     for (size_t i = 0; i < pitchValues.size() - 1; i++) {
      67          231 :         currentPitchDiff = pitchDiff(pitchValues[i], pitchValues[i + 1]);
      68          231 :         if (currentPitchDiff == pvd::SAME_PITCH_AND_TIME) {
      69            0 :             continue;
      70              :         }
      71              : 
      72          231 :         if (currentPitchDiff == previousPitchDiff && !importedInfo.segments.empty()) {
      73           17 :             BendSegment& lastSegment = importedInfo.segments.back();
      74           17 :             lastSegment.middleTime = pitchValues[i + 1].time; // there is no "hold" in bend, cause both segments go same direction
      75           17 :             lastSegment.endTime = pitchValues[i + 1].time;
      76           17 :             lastSegment.endPitch = pitchValues[i + 1].pitch;
      77           17 :             continue;
      78           17 :         }
      79              : 
      80          214 :         switch (currentPitchDiff) {
      81            0 :         case pvd::NONE:
      82              :         case pvd::SAME_PITCH_AND_TIME:
      83            0 :             break;
      84              : 
      85           86 :         case pvd::SAME_PITCH_DIFF_TIME:
      86              :         case pvd::INCREASED_PITCH_SAME_TIME:
      87              :         {
      88           86 :             if (importedInfo.segments.empty()) {
      89           43 :                 addPrebendOrHold(pitchValues[i]);
      90              :             } else {
      91           43 :                 BendSegment& lastSegment = importedInfo.segments.back();
      92           43 :                 lastSegment.middleTime = lastSegment.endTime;
      93           43 :                 lastSegment.endTime = pitchValues[i + 1].time;
      94           43 :                 lastSegment.endPitch = pitchValues[i + 1].pitch;
      95              :             }
      96              : 
      97           86 :             break;
      98              :         }
      99              : 
     100          128 :         case pvd::INCREASED_PITCH_DIFF_TIME:
     101              :         case pvd::DECREASED_PITCH_DIFF_TIME:
     102              :         {
     103          128 :             if (importedInfo.segments.empty()) {
     104           97 :                 addPrebendOrHold(pitchValues[i]);
     105              :             }
     106              : 
     107          128 :             BendSegment newSegment;
     108          128 :             newSegment.startPitch = pitchValues[i].pitch;
     109          128 :             newSegment.endPitch = pitchValues[i + 1].pitch;
     110          128 :             newSegment.startTime = pitchValues[i].time;
     111          128 :             newSegment.middleTime = pitchValues[i + 1].time;
     112          128 :             newSegment.endTime = pitchValues[i + 1].time;
     113          128 :             importedInfo.segments.push_back(newSegment);
     114          128 :             break;
     115              :         }
     116              :         }
     117              : 
     118          214 :         previousPitchDiff = currentPitchDiff;
     119              :     }
     120              : 
     121          121 :     importedInfo.note = note;
     122          121 :     if (!importedInfo.segments.empty()) {
     123           97 :         importedInfo.segments.back().endTime = PitchValue::MAX_TIME;
     124              :     }
     125              : 
     126          249 :     for (auto& seg : importedInfo.segments) {
     127          128 :         if (seg.endTime - seg.middleTime == 1) {
     128            9 :             seg.middleTime = seg.endTime;
     129              :         }
     130              :     }
     131              : 
     132          190 :     if (importedInfo.segments.size() == 1 && importedInfo.type == BendType::NORMAL_BEND
     133          190 :         && importedInfo.segments.front().pitchDiff() == GP_PITCH_PER_QUARTERTONE) {
     134           14 :         importedInfo.type = BendType::SLIGHT_BEND;
     135              :     }
     136              : 
     137          121 :     return importedInfo;
     138            0 : }
     139              : } // namespace mu::iex::guitarpro
        

Generated by: LCOV version 2.0-1