2021-04-01 18:38:40 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "CoreMinimal.h"
# include "DSP/MidiNoteQuantizer.h"
# include "Internationalization/Text.h"
2021-04-05 20:22:19 -04:00
# include "MetasoundEnumRegistrationMacro.h"
2021-04-01 18:38:40 -04:00
# include "MetasoundFacade.h"
# include "MetasoundPrimitives.h"
# include "MetasoundScaleEnums.h"
# include "MetasoundAudioBuffer.h"
# include "MetasoundParamHelper.h"
# include "MetasoundOperatorSettings.h"
# include "MetasoundStandardNodesNames.h"
# include "MetasoundExecutableOperator.h"
# include "MetasoundNodeRegistrationMacro.h"
# include "MetasoundStandardNodesCategories.h"
# include "MetasoundDataTypeRegistrationMacro.h"
2021-04-07 02:57:54 -04:00
# define LOCTEXT_NAMESPACE "MetasoundStandardNodes_MidiScaleToArray"
2021-04-01 18:38:40 -04:00
namespace Metasound
{
2023-03-15 15:04:43 -04:00
DEFINE_METASOUND_ENUM_BEGIN ( Audio : : EMusicalScale : : Scale , FEnumEMusicalScale , " MusicalScale " )
// modes
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Major , " MajorDescription " , " Major Scale " , " MajorDescriptionTT " , " Major (Ionian) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Minor_Dorian , " Minor_DorianDescription " , " Minor (Dorian) " , " Minor_DorianDescriptionTT " , " Dorian Minor " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Phrygian , " PhrygianDescription " , " Phrygian " , " PhrygianDescriptionTT " , " Phrygian " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Lydian , " LydianDescription " , " Lydian " , " LydianDescriptionTT " , " Lydian (sharp-4) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Dominant7th_Mixolydian , " Dominant7th_MixolydianDescription " , " Dominant 7th (Mixolydian) " , " Dominant7th_MixolydianDescriptionTT " , " Mioxlydian (Dominant 7) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : NaturalMinor_Aeolian , " NaturalMinor_AeolianDescription " , " Natural Minor (Aeolian) " , " NaturalMinor_AeolianDescriptionTT " , " Natural Minor (Aeolian) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : HalfDiminished_Locrian , " HalfDiminished_LocrianDescription " , " Half Diminished (Locrian) " , " HalfDiminished_LocrianDescriptionTT " , " Half-Diminished (Locrian) " ) ,
// non-diatonic
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Chromatic , " ChromaticDescription " , " Chromatic " , " ChromaticDescriptionTT " , " Chromatic " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : WholeTone , " WholeToneDescription " , " Whole-Tone " , " WholeToneDescriptionTT " , " Whole Tone " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : DiminishedWholeTone , " DiminishedWholeToneDescription " , " Diminished Whole-Tone " , " DiminishedWholeToneDescriptionTT " , " Diminished Whole Tone " ) ,
// petantonic
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : MajorPentatonic , " MajorPentatonicDescription " , " Major Pentatonic " , " MajorPentatonicDescriptionTT " , " Major Pentatonic " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : MinorPentatonic , " MinorPentatonicDescription " , " Minor Pentatonic " , " MinorPentatonicDescriptionTT " , " Minor Pentatonic " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Blues , " BluesDescription " , " Blues " , " BluesDescriptionTT " , " Blues " ) ,
// bebop
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Bebop_Major , " Bebop_MajorDescription " , " Bebop (Major) " , " Bebop_MajorDescriptionTT " , " Bebop Major " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Bebop_Minor , " Bebop_MinorDescription " , " Bebop (Minor) " , " Bebop_MinorDescriptionTT " , " Bebop Minor " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Bebop_MinorNumber2 , " Bebop_MinorNumber2Description " , " Bebop (Minor) #2 " , " Bebop_MinorNumber2DescriptionTT " , " Bebop Minor #2 " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Bebop_Dominant , " Bebop_DominantDescription " , " Bebop (Dominant) " , " Bebop_DominantDescriptionTT " , " Bebop Dominant " ) ,
// common major/minors
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : HarmonicMajor , " HarmonicMajorDescription " , " Harmonic Major " , " HarmonicMajorDescriptionTT " , " Harmonic Major " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : HarmonicMinor , " HarmonicMinorDescription " , " Harmonic Minor " , " HarmonicMinorDescriptionTT " , " Harmonic Minor " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : MelodicMinor , " MelodicMinorDescription " , " Melodic Minor " , " MelodicMinorDescriptionTT " , " Melodic Minor " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : SixthModeOfHarmonicMinor , " SixthModeOfHarmonicMinorDescription " , " Sixth Mode of Harmonic Minor " , " SixthModeOfHarmonicMinorDescriptionTT " , " Sixth Mode of Harmonic Minor " ) ,
// lydian/augmented
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : LydianAugmented , " LydianAugmentedDescription " , " Lydian Augmented " , " LydianAugmentedDescriptionTT " , " Lydian Augmented " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : LydianDominant , " LydianDominantDescription " , " Lydian Dominant " , " LydianDominantDescriptionTT " , " Lydian Dominant " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Augmented , " AugmentedDescription " , " Augmented " , " AugmentedDescriptionTT " , " Augmented " ) ,
// diminished
2023-05-25 18:45:39 -04:00
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Diminished , " DiminishedDescription " , " Diminished " , " DiminishedDescriptionTT " , " Diminished " ) ,
2023-03-15 15:04:43 -04:00
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Diminished_BeginWithHalfStep , " Diminished_BeginWithHalfStepDescription " , " Diminished (Begin With Half-Step) " , " Diminished_BeginWithHalfStepDescriptionTT " , " Diminished (begins with Half Step) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Diminished_BeginWithWholeStep , " Diminished_BeginWithWholeStepDescription " , " Diminished (Begin With Whole-Step " , " Diminished_BeginWithWholeStepDescriptionTT " , " Diminished (begins with Whole Step) " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : HalfDiminished_LocrianNumber2 , " HalfDiminished_LocrianNumber2Description " , " Half-Diminished (Locrian #2) " , " HalfDiminished_LocrianNumber2DescriptionTT " , " Half Diminished Locrian (#2) " ) ,
// other
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Spanish_or_Jewish , " Spanish_or_JewishDescription " , " Spanish or Jewish Scale " , " Spanish_or_JewishDescriptionTT " , " Spanish/Jewish " ) ,
DEFINE_METASOUND_ENUM_ENTRY ( Audio : : EMusicalScale : : Scale : : Hindu , " HinduDescription " , " Hindu " , " HinduDescriptionTT " , " Hindu " )
DEFINE_METASOUND_ENUM_END ( )
2021-04-01 18:38:40 -04:00
# pragma region Parameter Names
namespace MusicalScaleToNoteArrayParameterNames
{
// inputs
METASOUND_PARAM ( ParamScaleDegreesPreset , " Scale Degrees " , " Select scale preset " ) ;
2023-05-25 18:45:39 -04:00
METASOUND_PARAM ( ParamChordTonesOnly , " Chord Tones Only " , " If true, will only return a subset of the scale represeting chord tones. (i.e. scale degrees 1,3,5,7). Will not include chord extensions (i.e. 9, 11, 13). " ) ;
2021-04-01 18:38:40 -04:00
// outputs
2023-05-25 18:45:39 -04:00
METASOUND_PARAM ( ParamNoteArrayOutput , " Scale Array Out " , " Array represeting the scale as semitones above the root starting at 0.0. The scale only includes one octave and each note only once. " ) ;
2021-04-01 18:38:40 -04:00
} // namespace MusicalScaleToNoteArrayParameterNames
using namespace MusicalScaleToNoteArrayParameterNames ;
# pragma endregion // Parameter Names
# pragma region Operator Declaration
class FMusicalScaleToNoteArrayOperator : public TExecutableOperator < FMusicalScaleToNoteArrayOperator >
{
public :
using FArrayScaleDegreeWriteRef = TDataWriteReference < TArray < float > > ;
using ScaleDegreeArrayType = TArray < float > ;
// ctor
FMusicalScaleToNoteArrayOperator (
2023-10-13 19:29:51 -04:00
const FBuildOperatorParams & InParams
2021-04-01 18:38:40 -04:00
, const FEnumMusicalScaleReadRef & InScale
, const FBoolReadRef & InChordTonesOnly
) ;
// node interface
static const FNodeClassMetadata & GetNodeInfo ( ) ;
static FVertexInterface DeclareVertexInterface ( ) ;
2023-10-13 19:29:51 -04:00
static TUniquePtr < IOperator > CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults ) ;
2023-05-22 13:28:27 -04:00
virtual void BindInputs ( FInputVertexInterfaceData & InOutVertexData ) override ;
virtual void BindOutputs ( FOutputVertexInterfaceData & InOutVertexData ) override ;
2021-04-01 18:38:40 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override ;
virtual FDataReferenceCollection GetOutputs ( ) const override ;
2023-03-02 14:40:35 -05:00
void Reset ( const IOperator : : FResetParams & InParams ) ;
2021-04-01 18:38:40 -04:00
void Execute ( ) ;
private : // members
// input pins
FEnumMusicalScaleReadRef Scale ;
FBoolReadRef bChordTonesOnly ;
// output pins
FArrayScaleDegreeWriteRef ScaleArrayOutput ;
// cached values
Audio : : EMusicalScale : : Scale PreviousScale = Audio : : EMusicalScale : : Scale : : Count ;
bool bPreviousChordTones = false ;
} ; // class FMusicalScaleToNoteArrayOperator
# pragma endregion // Operator Declaration
# pragma region Operator Implementation
// ctor
FMusicalScaleToNoteArrayOperator : : FMusicalScaleToNoteArrayOperator (
2023-10-13 19:29:51 -04:00
const FBuildOperatorParams & InParams
2021-04-01 18:38:40 -04:00
, const FEnumMusicalScaleReadRef & InScale
, const FBoolReadRef & InChordTonesOnly
)
: Scale ( InScale )
, bChordTonesOnly ( InChordTonesOnly )
, ScaleArrayOutput ( FArrayScaleDegreeWriteRef : : CreateNew ( ) )
{
2021-04-07 03:05:51 -04:00
// prime our output array
2023-03-02 14:40:35 -05:00
Reset ( InParams ) ;
2021-04-01 18:38:40 -04:00
}
const FNodeClassMetadata & FMusicalScaleToNoteArrayOperator : : GetNodeInfo ( )
{
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
{
FNodeClassMetadata Info ;
2021-08-09 15:08:37 -04:00
Info . ClassName = { StandardNodes : : Namespace , TEXT ( " Musical Scale To Note Array " ) , StandardNodes : : AudioVariant } ;
2021-04-01 18:38:40 -04:00
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
2022-02-10 18:36:47 -05:00
Info . DisplayName = METASOUND_LOCTEXT ( " Metasound_ScaleToNoteArray_NodeDisplayName " , " Scale to Note Array " ) ;
Info . Description = METASOUND_LOCTEXT ( " MusicalScaleToNoteArray_NodeDescription " , " Returns an array represeting the selected scale " ) ;
2021-04-01 18:38:40 -04:00
Info . Author = PluginAuthor ;
Info . PromptIfMissing = PluginNodeMissingPrompt ;
Info . DefaultInterface = DeclareVertexInterface ( ) ;
2021-08-09 15:08:37 -04:00
Info . CategoryHierarchy . Emplace ( NodeCategories : : Music ) ;
2022-08-17 16:42:56 -04:00
Info . Keywords . Add ( METASOUND_LOCTEXT ( " ScaleToArrayPitchKeyword " , " Pitch " ) ) ;
Info . Keywords . Add ( METASOUND_LOCTEXT ( " ScaleToArrayMIDIKeyword " , " MIDI " ) ) ;
2021-04-01 18:38:40 -04:00
return Info ;
} ;
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
return Info ;
}
FVertexInterface FMusicalScaleToNoteArrayOperator : : DeclareVertexInterface ( )
{
static const FVertexInterface Interface (
FInputVertexInterface (
2023-05-25 18:45:39 -04:00
TInputDataVertex < FEnumEMusicalScale > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( ParamScaleDegreesPreset ) , ( int32 ) Audio : : EMusicalScale : : Scale : : Major ) ,
TInputDataVertex < bool > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( ParamChordTonesOnly ) , false )
2021-04-01 18:38:40 -04:00
) ,
FOutputVertexInterface (
2022-03-31 16:49:59 -04:00
TOutputDataVertex < ScaleDegreeArrayType > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( ParamNoteArrayOutput ) )
2021-04-01 18:38:40 -04:00
)
) ;
return Interface ;
}
2023-10-13 19:29:51 -04:00
TUniquePtr < IOperator > FMusicalScaleToNoteArrayOperator : : CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults )
2021-04-01 18:38:40 -04:00
{
2023-10-13 19:29:51 -04:00
const FInputVertexInterfaceData & InputData = InParams . InputData ;
2021-04-01 18:38:40 -04:00
// inputs
2023-10-13 19:29:51 -04:00
FEnumMusicalScaleReadRef Scale = InputData . GetOrCreateDefaultDataReadReference < FEnumEMusicalScale > ( METASOUND_GET_PARAM_NAME ( ParamScaleDegreesPreset ) , InParams . OperatorSettings ) ;
FBoolReadRef ChordTonesOnly = InputData . GetOrCreateDefaultDataReadReference < bool > ( METASOUND_GET_PARAM_NAME ( ParamChordTonesOnly ) , InParams . OperatorSettings ) ;
2021-04-01 18:38:40 -04:00
return MakeUnique < FMusicalScaleToNoteArrayOperator > (
2023-03-02 14:40:35 -05:00
InParams
2021-04-01 18:38:40 -04:00
, Scale
, ChordTonesOnly
) ;
}
2023-05-22 13:28:27 -04:00
void FMusicalScaleToNoteArrayOperator : : BindInputs ( FInputVertexInterfaceData & InOutVertexData )
{
2023-06-27 19:07:52 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( ParamScaleDegreesPreset ) , Scale ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( ParamChordTonesOnly ) , bChordTonesOnly ) ;
2023-05-22 13:28:27 -04:00
}
void FMusicalScaleToNoteArrayOperator : : BindOutputs ( FOutputVertexInterfaceData & InOutVertexData )
{
2023-06-27 19:07:52 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( ParamNoteArrayOutput ) , ScaleArrayOutput ) ;
2023-05-22 13:28:27 -04:00
}
2021-04-01 18:38:40 -04:00
FDataReferenceCollection FMusicalScaleToNoteArrayOperator : : GetInputs ( ) const
{
2023-05-22 13:28:27 -04:00
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
2021-04-01 18:38:40 -04:00
}
FDataReferenceCollection FMusicalScaleToNoteArrayOperator : : GetOutputs ( ) const
{
2023-05-22 13:28:27 -04:00
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
2021-04-01 18:38:40 -04:00
}
2023-03-02 14:40:35 -05:00
void FMusicalScaleToNoteArrayOperator : : Reset ( const IOperator : : FResetParams & InParams )
{
PreviousScale = * Scale ;
bPreviousChordTones = * bChordTonesOnly ;
* ScaleArrayOutput = Audio : : FMidiNoteQuantizer : : ScaleDegreeSetMap [ PreviousScale ] . GetScaleDegreeSet ( bPreviousChordTones ) ;
}
2021-04-01 18:38:40 -04:00
void FMusicalScaleToNoteArrayOperator : : Execute ( )
{
// calculate new output and cache values if needed
if ( ( PreviousScale ! = * Scale ) | | ( bPreviousChordTones ! = * bChordTonesOnly ) )
{
// cache values
PreviousScale = * Scale ;
bPreviousChordTones = * bChordTonesOnly ;
2023-03-02 14:40:35 -05:00
* ScaleArrayOutput = Audio : : FMidiNoteQuantizer : : ScaleDegreeSetMap [ PreviousScale ] . GetScaleDegreeSet ( bPreviousChordTones ) ;
2021-04-01 18:38:40 -04:00
}
}
# pragma endregion // Operator Implementation
# pragma region Node Declaration
class METASOUNDSTANDARDNODES_API FMusicalScaleToNoteArrayNode : public FNodeFacade
{
public :
// public node api needs to define two conversion constructors:
// (1: from FString)
2021-09-13 14:13:39 -04:00
FMusicalScaleToNoteArrayNode ( const FVertexName & InInstanceName , const FGuid & InInstanceID )
2021-04-01 18:38:40 -04:00
: FNodeFacade ( InInstanceName , InInstanceID , TFacadeOperatorClass < FMusicalScaleToNoteArrayOperator > ( ) )
{ }
// (2: From an NodeInitData struct)
FMusicalScaleToNoteArrayNode ( const FNodeInitData & InInitData )
: FMusicalScaleToNoteArrayNode ( InInitData . InstanceName , InInitData . InstanceID )
{ }
} ;
# pragma endregion // Node Declaration
# pragma region Node Registration
METASOUND_REGISTER_NODE ( FMusicalScaleToNoteArrayNode ) ;
# pragma endregion // Node Registration
} // namespace Metasound
2021-04-05 20:22:19 -04:00
# undef LOCTEXT_NAMESPACE //MetasoundBasicFilterNodes