Files
UnrealEngine/Engine/Plugins/Runtime/Harmonix/Source/HarmonixMetasoundTests/Private/MidiOps/StuckNoteGuardTests.cpp
2025-05-18 13:04:45 +08:00

87 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "HarmonixMetasound/MidiOps/StuckNoteGuard.h"
#include "Misc/AutomationTest.h"
#if WITH_DEV_AUTOMATION_TESTS
namespace Harmonix::Midi::Ops::Tests
{
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FStuckNoteGuardBasicTest,
"Harmonix.Midi.Ops.StuckNoteGuard.Basic",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
bool FStuckNoteGuardBasicTest::RunTest(const FString&)
{
FStuckNoteGuard Guard;
HarmonixMetasound::FMidiStream InputStream;
HarmonixMetasound::FMidiStream OutputStream;
// Use a filter that only includes messages on channel 3
const auto Channel3Filter = [](const HarmonixMetasound::FMidiStreamEvent& Event)
{
return Event.MidiMessage.IsStd() && Event.MidiMessage.GetStdChannel() == 3;
};
constexpr uint8 NoteNumber = 43;
constexpr uint8 Velocity = 54;
// Add some note ons on all the channels
for (uint8 ChannelIdx = 0; ChannelIdx < Constants::GNumChannels; ++ChannelIdx)
{
InputStream.AddMidiEvent({ static_cast<uint32>(0), FMidiMsg::CreateNoteOn(ChannelIdx, NoteNumber, Velocity)});
}
// Process and expect no messages (because we don't have any stuck notes yet)
Guard.Process(InputStream, OutputStream, Channel3Filter);
UTEST_EQUAL("Got no events", OutputStream.GetEventsInBlock().Num(), 0);
// Now change the filter to include only messages on channel 4, process, and expect to get a note off for the newly-stuck note on channel 3
const auto Channel4Filter = [](const HarmonixMetasound::FMidiStreamEvent& Event)
{
return Event.MidiMessage.IsStd() && Event.MidiMessage.GetStdChannel() == 4;
};
InputStream.PrepareBlock();
OutputStream.PrepareBlock();
Guard.Process(InputStream, OutputStream, Channel4Filter);
const auto& Events = OutputStream.GetEventsInBlock();
UTEST_EQUAL("Got one event", Events.Num(), 1);
UTEST_TRUE("Got a note off", Events[0].MidiMessage.IsNoteOff());
UTEST_EQUAL("Got the right note number", Events[0].MidiMessage.GetStdData1(), NoteNumber);
UTEST_EQUAL("Got the note off on the right channel", Events[0].MidiMessage.GetStdChannel(), 3);
// Add some note ons on all the channels
InputStream.PrepareBlock();
OutputStream.PrepareBlock();
for (uint8 ChannelIdx = 0; ChannelIdx < Constants::GNumChannels; ++ChannelIdx)
{
InputStream.AddMidiEvent({ static_cast<uint32>(0), FMidiMsg::CreateNoteOn(ChannelIdx, NoteNumber, Velocity)});
}
// Process and expect no messages (because we don't have any stuck notes yet)
Guard.Process(InputStream, OutputStream, Channel4Filter);
UTEST_EQUAL("Got no events", OutputStream.GetEventsInBlock().Num(), 0);
// Now send note offs on all the channels, process, and expect no additional note offs
InputStream.PrepareBlock();
OutputStream.PrepareBlock();
for (uint8 ChannelIdx = 0; ChannelIdx < Constants::GNumChannels; ++ChannelIdx)
{
InputStream.AddMidiEvent({ static_cast<uint32>(0), FMidiMsg::CreateNoteOff(ChannelIdx, NoteNumber)});
}
Guard.Process(InputStream, OutputStream, Channel4Filter);
UTEST_EQUAL("Got no events", OutputStream.GetEventsInBlock().Num(), 0);
// Change the filter back to channel 3, and expect no new note offs
InputStream.PrepareBlock();
OutputStream.PrepareBlock();
Guard.Process(InputStream, OutputStream, Channel3Filter);
UTEST_EQUAL("Got no events", OutputStream.GetEventsInBlock().Num(), 0);
return true;
}
}
#endif