Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

musesampler_overlapping_notes #21415

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/engraving/playback/playbackeventsrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,14 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol,
duration_t duration = timestampFromTicks(score, positionTick + ticksPositionOffset + durationTicks) - eventTimestamp;

voice_layer_idx_t voiceIdx = static_cast<voice_layer_idx_t>(chordSymbol->voice());
staff_layer_idx_t staffIdx = static_cast<staff_layer_idx_t>(chordSymbol->staffIdx());
Key key = chordSymbol->staff()->key(chordSymbol->tick());

ArticulationMap articulations = makeArticulations(mpe::ArticulationType::Standard, profile->pattern(mpe::ArticulationType::Standard),
eventTimestamp, duration);

double bps = score->tempomap()->tempo(positionTick).val;

for (auto it = notes.cbegin(); it != notes.cend(); ++it) {
int pitch = it->first;
int tpc = pitch2tpc(pitch, key, Prefer::NEAREST);
Expand All @@ -147,10 +150,11 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol,
events.emplace_back(mpe::NoteEvent(eventTimestamp,
duration,
voiceIdx,
staffIdx,
pitchLevel,
dynamicLevelFromType(mpe::DynamicType::Natural),
articulations,
score->tempomap()->tempo(positionTick).val));
bps));
}
}

Expand All @@ -168,6 +172,8 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol, const
PlaybackEventList& events = result[actualTimestamp];

voice_layer_idx_t voiceIdx = static_cast<voice_layer_idx_t>(chordSymbol->voice());
staff_layer_idx_t staffIdx = static_cast<staff_layer_idx_t>(chordSymbol->staffIdx());

Key key = chordSymbol->staff()->key(chordSymbol->tick());

ArticulationMap articulations = makeArticulations(mpe::ArticulationType::Standard, profile->pattern(mpe::ArticulationType::Standard),
Expand All @@ -182,10 +188,11 @@ void PlaybackEventsRenderer::renderChordSymbol(const Harmony* chordSymbol, const
events.emplace_back(mpe::NoteEvent(actualTimestamp,
actualDuration,
voiceIdx,
staffIdx,
pitchLevel,
dynamicLevelFromType(mpe::DynamicType::Natural),
articulations,
2.0));
Constants::DEFAULT_TEMPO.val));
}
}

Expand Down Expand Up @@ -233,6 +240,7 @@ void PlaybackEventsRenderer::renderMetronome(const Score* score, const int tick,
result[actualTimestamp].emplace_back(mpe::NoteEvent(actualTimestamp,
duration,
0,
0,
eventPitchLevel,
dynamicLevelFromType(mpe::DynamicType::Natural),
emptyArticulations,
Expand Down
7 changes: 7 additions & 0 deletions src/engraving/playback/renderingcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ inline mpe::duration_t noteNominalDuration(const Note* note, const RenderingCont

struct NominalNoteCtx {
voice_idx_t voiceIdx = 0;
staff_idx_t staffIdx = 0;
mpe::timestamp_t timestamp = 0;
mpe::duration_t duration = 0;
BeatsPerSecond tempo = 0;
Expand All @@ -108,6 +109,7 @@ struct NominalNoteCtx {

explicit NominalNoteCtx(const Note* note, const RenderingContext& ctx)
: voiceIdx(note->voice()),
staffIdx(note->staffIdx()),
timestamp(ctx.nominalTimestamp),
duration(ctx.nominalDuration),
tempo(ctx.beatsPerSecond),
Expand Down Expand Up @@ -165,6 +167,7 @@ inline mpe::NoteEvent buildNoteEvent(NominalNoteCtx&& ctx)
return mpe::NoteEvent(ctx.timestamp,
ctx.duration,
static_cast<mpe::voice_layer_idx_t>(ctx.voiceIdx),
static_cast<mpe::staff_layer_idx_t>(ctx.staffIdx),
ctx.pitchLevel,
ctx.chordCtx.nominalDynamicLevel,
ctx.chordCtx.commonArticulations,
Expand All @@ -177,6 +180,7 @@ inline mpe::NoteEvent buildNoteEvent(NominalNoteCtx&& ctx, const mpe::PitchCurve
return mpe::NoteEvent(ctx.timestamp,
ctx.duration,
static_cast<mpe::voice_layer_idx_t>(ctx.voiceIdx),
static_cast<mpe::staff_layer_idx_t>(ctx.staffIdx),
ctx.pitchLevel,
ctx.chordCtx.nominalDynamicLevel,
ctx.chordCtx.commonArticulations,
Expand All @@ -190,6 +194,7 @@ inline mpe::NoteEvent buildNoteEvent(const Note* note, const RenderingContext& c
return mpe::NoteEvent(ctx.nominalTimestamp,
noteNominalDuration(note, ctx),
static_cast<mpe::voice_layer_idx_t>(note->voice()),
static_cast<mpe::staff_layer_idx_t>(note->staffIdx()),
notePitchLevel(note->playingTpc(), note->playingOctave(), note->playingTuning()),
ctx.nominalDynamicLevel,
ctx.commonArticulations,
Expand All @@ -204,6 +209,7 @@ inline mpe::NoteEvent buildNoteEvent(NominalNoteCtx&& ctx, const mpe::duration_t
return mpe::NoteEvent(ctx.timestamp + timestampOffset,
eventDuration,
static_cast<mpe::voice_layer_idx_t>(ctx.voiceIdx),
static_cast<mpe::staff_layer_idx_t>(ctx.staffIdx),
ctx.pitchLevel + pitchLevelOffset,
ctx.chordCtx.nominalDynamicLevel,
ctx.chordCtx.commonArticulations,
Expand All @@ -218,6 +224,7 @@ inline mpe::NoteEvent buildFixedNoteEvent(const Note* note, const mpe::timestamp
return mpe::NoteEvent(actualTimestamp,
actualDuration,
static_cast<mpe::voice_layer_idx_t>(note->voice()),
static_cast<mpe::staff_layer_idx_t>(note->staffIdx()),
notePitchLevel(note->playingTpc(), note->playingOctave(), note->playingTuning()),
actualDynamicLevel,
articulations,
Expand Down
6 changes: 5 additions & 1 deletion src/framework/mpe/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ struct ArrangementContext
duration_t nominalDuration = 0;
duration_t actualDuration = 0;
voice_layer_idx_t voiceLayerIndex = 0;
double bps = 0;
staff_layer_idx_t staffLayerIndex = 0;
double bps = 0.0;

bool operator==(const ArrangementContext& other) const
{
Expand All @@ -64,6 +65,7 @@ struct ArrangementContext
&& nominalDuration == other.nominalDuration
&& actualDuration == other.actualDuration
&& voiceLayerIndex == other.voiceLayerIndex
&& staffLayerIndex == other.staffLayerIndex
&& bps == other.bps;
}
};
Expand Down Expand Up @@ -108,6 +110,7 @@ struct NoteEvent
explicit NoteEvent(const timestamp_t nominalTimestamp,
const duration_t nominalDuration,
const voice_layer_idx_t voiceIdx,
const staff_layer_idx_t staffIdx,
const pitch_level_t nominalPitchLevel,
const dynamic_level_t nominalDynamicLevel,
const ArticulationMap& articulationsApplied,
Expand All @@ -118,6 +121,7 @@ struct NoteEvent
m_arrangementCtx.nominalDuration = nominalDuration;
m_arrangementCtx.nominalTimestamp = nominalTimestamp;
m_arrangementCtx.voiceLayerIndex = voiceIdx;
m_arrangementCtx.staffLayerIndex = staffIdx;
m_arrangementCtx.bps = bps;

m_pitchCtx.nominalPitchLevel = nominalPitchLevel;
Expand Down
1 change: 1 addition & 0 deletions src/framework/mpe/mpetypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ using timestamp_t = usecs_t;
using duration_t = usecs_t;
using duration_percentage_t = percentage_t;
using voice_layer_idx_t = uint_fast8_t;
using staff_layer_idx_t = uint_fast16_t;

constexpr inline duration_percentage_t occupiedPercentage(const timestamp_t timestamp,
const duration_t overallDuration)
Expand Down
8 changes: 8 additions & 0 deletions src/framework/mpe/tests/multinotearticulationstest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Engraving_MultiNoteArticulationsTest : public ::testing::Test
firstNoteData.nominalTimestamp = 0;
firstNoteData.nominalDuration = 500;
firstNoteData.voiceIdx = 0; // first voice
firstNoteData.staffIdx = 0; // first staff;
firstNoteData.nominalPitchLevel = pitchLevel(PitchClass::A, 3);
firstNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);

Expand All @@ -48,6 +49,7 @@ class Engraving_MultiNoteArticulationsTest : public ::testing::Test
secondNoteData.nominalTimestamp = 500;
secondNoteData.nominalDuration = 500;
secondNoteData.voiceIdx = 0; // first voice
secondNoteData.staffIdx = 0; // first staff;
secondNoteData.nominalPitchLevel = pitchLevel(PitchClass::C, 4);
secondNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);

Expand All @@ -56,6 +58,7 @@ class Engraving_MultiNoteArticulationsTest : public ::testing::Test
thirdNoteData.nominalTimestamp = 1000;
thirdNoteData.nominalDuration = 500;
thirdNoteData.voiceIdx = 0; // first voice
thirdNoteData.staffIdx = 0; // first staff;
thirdNoteData.nominalPitchLevel = pitchLevel(PitchClass::A, 3);
thirdNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);

Expand All @@ -64,6 +67,7 @@ class Engraving_MultiNoteArticulationsTest : public ::testing::Test
fourthNoteData.nominalTimestamp = 1500;
fourthNoteData.nominalDuration = 500;
fourthNoteData.voiceIdx = 0; // first voice
fourthNoteData.staffIdx = 0; // first staff;
fourthNoteData.nominalPitchLevel = pitchLevel(PitchClass::C, 4);
fourthNoteData.nominalDynamicLevel = dynamicLevelFromType(DynamicType::f);

Expand All @@ -77,6 +81,7 @@ class Engraving_MultiNoteArticulationsTest : public ::testing::Test
timestamp_t nominalTimestamp = 0;
duration_t nominalDuration = 0;
voice_layer_idx_t voiceIdx = 0;
staff_layer_idx_t staffIdx = 0;

pitch_level_t nominalPitchLevel = 0;

Expand Down Expand Up @@ -119,6 +124,7 @@ TEST_F(Engraving_MultiNoteArticulationsTest, StandardPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.staffIdx,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations,
Expand Down Expand Up @@ -217,6 +223,7 @@ TEST_F(Engraving_MultiNoteArticulationsTest, GlissandoPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.staffIdx,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations[pair.first],
Expand Down Expand Up @@ -300,6 +307,7 @@ TEST_F(Engraving_MultiNoteArticulationsTest, CrescendoPattern)
NoteEvent noteEvent(pair.second.nominalTimestamp,
pair.second.nominalDuration,
pair.second.voiceIdx,
pair.second.staffIdx,
pair.second.nominalPitchLevel,
pair.second.nominalDynamicLevel,
appliedArticulations[pair.first],
Expand Down
9 changes: 9 additions & 0 deletions src/framework/mpe/tests/singlenotearticulationstest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Engraving_SingleNoteArticulationsTest : public ::testing::Test
m_nominalTimestamp = 0; // msecs
m_nominalDuration = 500; // msecs
m_voiceIdx = 0; // first voice
m_staffIdx = 0; // first staff

// [GIVEN] Pitch data of the note
m_pitchClass = PitchClass::A;
Expand All @@ -55,6 +56,7 @@ class Engraving_SingleNoteArticulationsTest : public ::testing::Test
timestamp_t m_nominalTimestamp;
duration_t m_nominalDuration;
voice_layer_idx_t m_voiceIdx;
staff_layer_idx_t m_staffIdx;

PitchClass m_pitchClass;
octave_t m_octave;
Expand Down Expand Up @@ -91,6 +93,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, StandardPattern)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -141,6 +144,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, StaccatoPattern)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -188,6 +192,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, AccentPattern)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -245,6 +250,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, AccentPattern_Nominal_MezzoForte)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -316,6 +322,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, PocoTenuto)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -367,6 +374,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, QuickFall)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down Expand Up @@ -418,6 +426,7 @@ TEST_F(Engraving_SingleNoteArticulationsTest, Scoop)
NoteEvent event(m_nominalTimestamp,
m_nominalDuration,
m_voiceIdx,
m_staffIdx,
pitchLevel(m_pitchClass, m_octave),
m_nominalDynamic,
std::move(appliedArticulations),
Expand Down
1 change: 1 addition & 0 deletions src/framework/musesampler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/internal/musesamplerwrapper.h
${CMAKE_CURRENT_LIST_DIR}/internal/musesamplersequencer.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/musesamplersequencer.h
${CMAKE_CURRENT_LIST_DIR}/internal/imusesamplertracks.h
${CMAKE_CURRENT_LIST_DIR}/internal/musesamplerconfiguration.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/musesamplerconfiguration.h
${CMAKE_CURRENT_LIST_DIR}/internal/apitypes.h
Expand Down
26 changes: 26 additions & 0 deletions src/framework/musesampler/internal/apitypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,30 @@ typedef ms_Result (* ms_MuseSampler_all_notes_off)(ms_MuseSampler);
typedef ms_PresetChange (* ms_MuseSampler_create_preset_change)(ms_MuseSampler ms, ms_Track track, long long location_us);

typedef ms_Result (* ms_MuseSampler_add_preset)(ms_MuseSampler ms, ms_Track track, ms_PresetChange preset_change, const char* preset_name);

namespace mu::musesampler {
using track_idx_t = size_t;
using TrackList = std::vector<ms_Track>;

struct InstrumentInfo {
int instrumentId = -1;
ms_InstrumentInfo msInstrument = nullptr;

bool isValid() const
{
return instrumentId != -1 && msInstrument != nullptr;
}
};

struct AuditionStartNoteEvent {
ms_AuditionStartNoteEvent_3 msEvent;
ms_Track msTrack = nullptr;
};

struct AuditionStopNoteEvent {
ms_AuditionStopNoteEvent msEvent;
ms_Track msTrack = nullptr;
};
}

#endif // MU_MUSESAMPLER_APITYPES_H
41 changes: 41 additions & 0 deletions src/framework/musesampler/internal/imusesamplertracks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2024 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef MU_MUSESAMPLER_IMUSESAMPLERTRACKS_H
#define MU_MUSESAMPLER_IMUSESAMPLERTRACKS_H

#include "apitypes.h"

namespace mu::musesampler {
class IMuseSamplerTracks
{
public:
virtual ~IMuseSamplerTracks() = default;

virtual const TrackList& allTracks() const = 0;
virtual ms_Track addTrack() = 0;
};

using IMuseSamplerTracksPtr = std::shared_ptr<IMuseSamplerTracks>;
}

#endif // MU_MUSESAMPLER_IMUSESAMPLERTRACKS_H
Loading