#ifndef __AMUSE_AUDIOGROUPPOOL_HPP__ #define __AMUSE_AUDIOGROUPPOOL_HPP__ #include #include #include #include #include #include "Entity.hpp" #include "Common.hpp" #include "athena/MemoryReader.hpp" namespace amuse { class AudioGroupData; struct SoundMacroState; class Voice; /** Header at the top of the pool file */ template struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little) PoolHeader : BigDNA { AT_DECL_DNA Value soundMacrosOffset; Value tablesOffset; Value keymapsOffset; Value layersOffset; }; /** Header present at the top of each pool object */ template struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little) ObjectHeader : BigDNA { AT_DECL_DNA Value size; ObjectIdDNA objectId; Seek<2, athena::Current> pad; }; struct SoundMacro { /** SoundMacro command operations */ enum class CmdOp : uint8_t { End, Stop, SplitKey, SplitVel, WaitTicks, Loop, Goto, WaitMs, PlayMacro, SendKeyOff, SplitMod, PianoPan, SetAdsr, ScaleVolume, Panning, Envelope, StartSample, StopSample, KeyOff, SplitRnd, FadeIn, Spanning, SetAdsrCtrl, RndNote, AddNote, SetNote, LastNote, Portamento, Vibrato, PitchSweep1, PitchSweep2, SetPitch, SetPitchAdsr, ScaleVolumeDLS, Mod2Vibrange, SetupTremolo, Return, GoSub, TrapEvent = 0x28, UntrapEvent, SendMessage, GetMessage, GetVid, AddAgeCount = 0x30, /* unimplemented */ SetAgeCount, /* unimplemented */ SendFlag, /* unimplemented */ PitchWheelR, SetPriority = 0x36, /* unimplemented */ AddPriority, /* unimplemented */ AgeCntSpeed, /* unimplemented */ AgeCntVel, /* unimplemented */ VolSelect = 0x40, PanSelect, PitchWheelSelect, ModWheelSelect, PedalSelect, PortamentoSelect, ReverbSelect, /* serves as PostASelect */ SpanSelect, DopplerSelect, TremoloSelect, PreASelect, PreBSelect, PostBSelect, AuxAFXSelect, /* unimplemented */ AuxBFXSelect, /* unimplemented */ SetupLFO = 0x50, ModeSelect = 0x58, SetKeygroup, SRCmodeSelect, /* unimplemented */ AddVars = 0x60, SubVars, MulVars, DivVars, AddIVars, SetVar, IfEqual = 0x70, IfLess, CmdOpMAX, Invalid = 0xff }; enum class CmdType : uint8_t { Control, Pitch, Sample, Setup, Special, Structure, Volume, CmdTypeMAX }; /** Introspection structure used by editors to define user interactivity per command */ struct CmdIntrospection { struct Field { enum class Type { Invalid, Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, SoundMacroId, SoundMacroStep, TableId, SampleId, Choice }; Type m_tp; size_t m_offset; std::string_view m_name; int64_t m_min, m_max, m_default; std::string_view m_choices[4]; }; CmdType m_tp; std::string_view m_name; std::string_view m_description; Field m_fields[7]; }; /** Base command interface. All versions of MusyX encode little-endian parameters */ struct ICmd : LittleDNAV { AT_DECL_DNA_YAML AT_DECL_DNAV virtual bool Do(SoundMacroState& st, Voice& vox) const = 0; virtual CmdOp Isa() const = 0; }; struct CmdEnd : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::End; } }; struct CmdStop : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Stop; } }; struct CmdSplitKey : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value key; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SplitKey; } }; struct CmdSplitVel : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value velocity; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SplitVel; } }; struct CmdWaitTicks : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value keyOff; Value random; Value sampleEnd; Value absolute; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::WaitTicks; } }; struct CmdLoop : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value keyOff; Value random; Value sampleEnd; SoundMacroStepDNA macroStep; Value times; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Loop; } }; struct CmdGoto : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> dummy; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Goto; } }; struct CmdWaitMs : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value keyOff; Value random; Value sampleEnd; Value absolute; Seek<1, athena::SeekOrigin::Current> dummy; Value ms; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::WaitMs; } }; struct CmdPlayMacro : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value addNote; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; Value priority; Value maxVoices; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PlayMacro; } }; struct CmdSendKeyOff : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value variable; Value lastStarted; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SendKeyOff; } }; struct CmdSplitMod : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value modValue; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SplitMod; } }; struct CmdPianoPan : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Value centerKey; Value centerPan; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PianoPan; } }; struct CmdSetAdsr : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; TableIdDNA table; Value dlsMode; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetAdsr; } }; struct CmdScaleVolume : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Value add; TableIdDNA table; Value originalVol; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::ScaleVolume; } }; struct CmdPanning : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value panPosition; Value timeMs; Value width; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Panning; } }; struct CmdEnvelope : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Value add; TableIdDNA table; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Envelope; } }; struct CmdStartSample : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; enum class Mode : atInt8 { NoScale = 0, Negative = 1, Positive = 2 }; SampleIdDNA sample; Value mode; Value offset; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::StartSample; } }; struct CmdStopSample : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::StopSample; } }; struct CmdKeyOff : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::KeyOff; } }; struct CmdSplitRnd : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value rnd; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SplitRnd; } }; struct CmdFadeIn : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Value add; TableIdDNA table; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::FadeIn; } }; struct CmdSpanning : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value spanPosition; Value timeMs; Value width; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Spanning; } }; struct CmdSetAdsrCtrl : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value attack; Value decay; Value sustain; Value release; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetAdsrCtrl; } }; struct CmdRndNote : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value noteLo; Value detune; Value noteHi; Value fixedFree; Value absRel; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::RndNote; } }; struct CmdAddNote : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value add; Value detune; Value originalKey; Seek<1, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AddNote; } }; struct CmdSetNote : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value key; Value detune; Seek<2, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetNote; } }; struct CmdLastNote : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value add; Value detune; Seek<2, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::LastNote; } }; struct CmdPortamento : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; enum class PortState : atInt8 { Disable, Enable, MIDIControlled }; Value portState; enum class PortType : atInt8 { LastPressed, Always }; Value portType; Seek<2, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Portamento; } }; struct CmdVibrato : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value levelNote; Value levelFine; Value modwheelFlag; Seek<1, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Vibrato; } }; struct CmdPitchSweep1 : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value times; Value add; Seek<1, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PitchSweep1; } }; struct CmdPitchSweep2 : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value times; Value add; Seek<1, athena::SeekOrigin::Current> seek; Value msSwitch; Value ticksOrMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PitchSweep2; } }; struct CmdSetPitch : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; LittleUInt24 hz; Value fine; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetPitch; } }; struct CmdSetPitchAdsr : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; TableIdDNA table; Seek<1, athena::SeekOrigin::Current> seek; Value keys; Value cents; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetPitchAdsr; } }; struct CmdScaleVolumeDLS : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Value originalVol; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::ScaleVolumeDLS; } }; struct CmdMod2Vibrange : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value keys; Value cents; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Mod2Vibrange; } }; struct CmdSetupTremolo : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value scale; Seek<1, athena::SeekOrigin::Current> seek; Value modwAddScale; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetupTremolo; } }; struct CmdReturn : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::Return; } }; struct CmdGoSub : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> seek; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::GoSub; } }; struct CmdTrapEvent : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; enum class EventType : atInt8 { KeyOff, SampleEnd, MessageRecv }; Value event; SoundMacroIdDNA macro; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::TrapEvent; } }; struct CmdUntrapEvent : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value event; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::UntrapEvent; } }; struct CmdSendMessage : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value isVar; SoundMacroIdDNA macro; Value voiceVar; Value valueVar; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SendMessage; } }; struct CmdGetMessage : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value variable; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::GetMessage; } }; struct CmdGetVid : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value variable; Value playMacro; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::GetVid; } }; struct CmdAddAgeCount : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> seek; Value add; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AddAgeCount; } }; struct CmdSetAgeCount : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> seek; Value counter; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetAgeCount; } }; struct CmdSendFlag : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value flagId; Value value; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SendFlag; } }; struct CmdPitchWheelR : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value rangeUp; Value rangeDown; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PitchWheelR; } }; struct CmdSetPriority : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value prio; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetPriority; } }; struct CmdAddPriority : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> seek; Value prio; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AddPriority; } }; struct CmdAgeCntSpeed : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<3, athena::SeekOrigin::Current> seek; Value time; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AgeCntSpeed; } }; struct CmdAgeCntVel : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Seek<1, athena::SeekOrigin::Current> seek; Value ageBase; Value ageScale; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AgeCntVel; } }; enum class Combine : atInt8 { Set, Add, Mult }; struct CmdVolSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::VolSelect; } }; struct CmdPanSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PanSelect; } }; struct CmdPitchWheelSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PitchWheelSelect; } }; struct CmdModWheelSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::ModWheelSelect; } }; struct CmdPedalSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PedalSelect; } }; struct CmdPortamentoSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PortamentoSelect; } }; struct CmdReverbSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::ReverbSelect; } }; struct CmdSpanSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SpanSelect; } }; struct CmdDopplerSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::DopplerSelect; } }; struct CmdTremoloSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::TremoloSelect; } }; struct CmdPreASelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PreASelect; } }; struct CmdPreBSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PreBSelect; } }; struct CmdPostBSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::PostBSelect; } }; struct CmdAuxAFXSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; Value paramIndex; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AuxAFXSelect; } }; struct CmdAuxBFXSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value midiControl; Value scalingPercentage; Value combine; Value isVar; Value fineScaling; Value paramIndex; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AuxBFXSelect; } }; struct CmdSetupLFO : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value lfoNumber; Value periodInMs; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetupLFO; } }; struct CmdModeSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value dlsVol; Value itd; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::ModeSelect; } }; struct CmdSetKeygroup : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value group; Value killNow; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetKeygroup; } }; struct CmdSRCmodeSelect : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value srcType; Value type0SrcFilter; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SRCmodeSelect; } }; struct CmdAddVars : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value varCtrlC; Value c; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AddVars; } }; struct CmdSubVars : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value varCtrlC; Value c; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SubVars; } }; struct CmdMulVars : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value varCtrlC; Value c; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::MulVars; } }; struct CmdDivVars : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value varCtrlC; Value c; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::DivVars; } }; struct CmdAddIVars : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value imm; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::AddIVars; } }; struct CmdSetVar : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Seek<1, athena::Current> pad; Value imm; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::SetVar; } }; struct CmdIfEqual : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value notEq; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::IfEqual; } }; struct CmdIfLess : ICmd { AT_DECL_DNA_YAML AT_DECL_DNAV static const CmdIntrospection Introspective; Value varCtrlA; Value a; Value varCtrlB; Value b; Value notLt; SoundMacroStepDNA macroStep; bool Do(SoundMacroState& st, Voice& vox) const; CmdOp Isa() const { return CmdOp::IfLess; } }; template static O CmdDo(_Args&&... args); static std::unique_ptr MakeCmd(CmdOp op); static const CmdIntrospection* GetCmdIntrospection(CmdOp op); static std::string_view CmdOpToStr(CmdOp op); static CmdOp CmdStrToOp(std::string_view op); std::vector> m_cmds; int assertPC(int pc) const; const ICmd& getCmd(int i) const { return *m_cmds[assertPC(i)]; } template void readCmds(athena::io::IStreamReader& r, uint32_t size); template void writeCmds(athena::io::IStreamWriter& w) const; ICmd* insertNewCmd(int idx, CmdOp op) { return m_cmds.insert(m_cmds.begin() + idx, MakeCmd(op))->get(); } ICmd* insertCmd(int idx, std::unique_ptr&& cmd) { return m_cmds.insert(m_cmds.begin() + idx, std::move(cmd))->get(); } std::unique_ptr deleteCmd(int idx) { std::unique_ptr ret = std::move(m_cmds[idx]); m_cmds.erase(m_cmds.begin() + idx); return ret; } void swapPositions(int a, int b) { if (a == b) return; std::swap(m_cmds[a], m_cmds[b]); } void buildFromPrototype(const SoundMacro& other); }; template static inline T& AccessField(SoundMacro::ICmd* cmd, const SoundMacro::CmdIntrospection::Field& field) { return *reinterpret_cast(reinterpret_cast(std::addressof(*cmd)) + field.m_offset); } /** Converts time-cents representation to seconds */ static inline double TimeCentsToSeconds(int32_t tc) { if (uint32_t(tc) == 0x80000000) return 0.0; return std::exp2(tc / (1200.0 * 65536.0)); } /** Converts seconds representation to time-cents */ static inline int32_t SecondsToTimeCents(double sec) { if (sec == 0.0) return 0x80000000; return int32_t(std::log2(sec) * (1200.0 * 65536.0)); } /** Polymorphic interface for representing table data */ struct ITable : LittleDNAV { AT_DECL_DNA_YAML AT_DECL_DNAV enum class Type { ADSR, ADSRDLS, Curve }; virtual Type Isa() const = 0; }; /** Defines phase-based volume curve for macro volume control */ struct ADSR : ITable { AT_DECL_DNA_YAML AT_DECL_DNAV Value attack = 0; Value decay = 0x8000; Value sustain = 0; /* 0x1000 == 100% */ Value release = 0; /* milliseconds */ double getAttack() const { return attack / 1000.0; } void setAttack(double v) { attack = v * 1000.0; } double getDecay() const { return (decay == 0x8000) ? 0.0 : (decay / 1000.0); } void setDecay(double v) { decay = v == 0.0 ? 0x8000 : v * 1000.0; } double getSustain() const { return sustain / double(0x1000); } void setSustain(double v) { sustain = v * double(0x1000); } double getRelease() const { return release / 1000.0; } void setRelease(double v) { release = v * 1000.0; } Type Isa() const { return ITable::Type::ADSR; } }; /** Defines phase-based volume curve for macro volume control (modified DLS standard) */ struct ADSRDLS : ITable { AT_DECL_DNA_YAML AT_DECL_DNAV Value attack = 0x80000000; /* 16.16 Time-cents */ Value decay = 0x80000000; /* 16.16 Time-cents */ Value sustain = 0; /* 0x1000 == 100% */ Value release = 0; /* milliseconds */ Value velToAttack = 0x80000000; /* 16.16, 1000.0 == 100%; attack = + (vel/128) * */ Value keyToDecay = 0x80000000; /* 16.16, 1000.0 == 100%; decay = + (note/128) * */ double getAttack() const { return TimeCentsToSeconds(attack); } void setAttack(double v) { attack = SecondsToTimeCents(v); } double getDecay() const { return TimeCentsToSeconds(decay); } void setDecay(double v) { decay = SecondsToTimeCents(v); } double getSustain() const { return sustain / double(0x1000); } void setSustain(double v) { sustain = v * double(0x1000); } double getRelease() const { return release / 1000.0; } void setRelease(double v) { release = v * 1000.0; } double _getVelToAttack() const { if (velToAttack == 0x80000000) return 0.0; else return velToAttack / 65536.0 / 1000.0; } void _setVelToAttack(double v) { if (v == 0.0) velToAttack = 0x80000000; else velToAttack = atUint32(v * 1000.0 * 65536.0); } double _getKeyToDecay() const { if (keyToDecay == 0x80000000) return 0.0; else return keyToDecay / 65536.0 / 1000.0; } void _setKeyToDecay(double v) { if (v == 0.0) keyToDecay = 0x80000000; else keyToDecay = atUint32(v * 1000.0 * 65536.0); } double getVelToAttack(int8_t vel) const { if (velToAttack == 0x80000000) return getAttack(); return getAttack() + vel * (velToAttack / 65536.0 / 1000.0) / 128.0; } double getKeyToDecay(int8_t note) const { if (keyToDecay == 0x80000000) return getDecay(); return getDecay() + note * (keyToDecay / 65536.0 / 1000.0) / 128.0; } Type Isa() const { return ITable::Type::ADSRDLS; } }; /** Defines arbitrary data for use as volume curve */ struct Curve : ITable { AT_DECL_EXPLICIT_DNA_YAML AT_DECL_DNAV std::vector data; Type Isa() const { return ITable::Type::Curve; } }; /** Maps individual MIDI keys to sound-entity as indexed in table * (macro-voice, keymap, layer) */ template struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little) KeymapDNA : BigDNA { AT_DECL_DNA SoundMacroIdDNA macro; Value transpose; Value pan; /* -128 for surround-channel only */ Value prioOffset; Seek<3, athena::Current> pad; }; struct Keymap : BigDNA { AT_DECL_DNA_YAML SoundMacroIdDNA macro; Value transpose = 0; Value pan = 64; /* -128 for surround-channel only */ Value prioOffset = 0; Keymap() = default; template Keymap(const KeymapDNA& in) : macro(in.macro.id), transpose(in.transpose), pan(in.pan), prioOffset(in.prioOffset) {} template KeymapDNA toDNA() const { KeymapDNA ret; ret.macro.id = macro; ret.transpose = transpose; ret.pan = pan; ret.prioOffset = prioOffset; return ret; } uint64_t configKey() const { return uint64_t(macro.id) | (uint64_t(transpose) << 16) | (uint64_t(pan) << 24) | (uint64_t(prioOffset) << 32); } }; /** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */ template struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little) LayerMappingDNA : BigDNA { AT_DECL_DNA SoundMacroIdDNA macro; Value keyLo; Value keyHi; Value transpose; Value volume; Value prioOffset; Value span; Value pan; Seek<3, athena::Current> pad; }; struct LayerMapping : BigDNA { AT_DECL_DNA_YAML SoundMacroIdDNA macro; Value keyLo = 0; Value keyHi = 127; Value transpose = 0; Value volume = 127; Value prioOffset = 0; Value span = 0; Value pan = 64; LayerMapping() = default; template LayerMapping(const LayerMappingDNA& in) : macro(in.macro.id), keyLo(in.keyLo), keyHi(in.keyHi), transpose(in.transpose), volume(in.volume), prioOffset(in.prioOffset), span(in.span), pan(in.pan) {} template LayerMappingDNA toDNA() const { LayerMappingDNA ret; ret.macro.id = macro; ret.keyLo = keyLo; ret.keyHi = keyHi; ret.transpose = transpose; ret.volume = volume; ret.prioOffset = prioOffset; ret.span = span; ret.pan = pan; return ret; } }; /** Database of functional objects within Audio Group */ class AudioGroupPool { std::unordered_map> m_soundMacros; std::unordered_map>> m_tables; std::unordered_map>> m_keymaps; std::unordered_map>> m_layers; template static AudioGroupPool _AudioGroupPool(athena::io::IStreamReader& r); public: AudioGroupPool() = default; static AudioGroupPool CreateAudioGroupPool(const AudioGroupData& data); static AudioGroupPool CreateAudioGroupPool(SystemStringView groupPath); const std::unordered_map>& soundMacros() const { return m_soundMacros; } const std::unordered_map>>& tables() const { return m_tables; } const std::unordered_map>>& keymaps() const { return m_keymaps; } const std::unordered_map>>& layers() const { return m_layers; } std::unordered_map>& soundMacros() { return m_soundMacros; } std::unordered_map>>& tables() { return m_tables; } std::unordered_map>>& keymaps() { return m_keymaps; } std::unordered_map>>& layers() { return m_layers; } const SoundMacro* soundMacro(ObjectId id) const; const Keymap* keymap(ObjectId id) const; const std::vector* layer(ObjectId id) const; const ADSR* tableAsAdsr(ObjectId id) const; const ADSRDLS* tableAsAdsrDLS(ObjectId id) const; const Curve* tableAsCurves(ObjectId id) const; bool toYAML(SystemStringView groupPath) const; template bool toData(SystemStringView groupPath) const; AudioGroupPool(const AudioGroupPool&) = delete; AudioGroupPool& operator=(const AudioGroupPool&) = delete; AudioGroupPool(AudioGroupPool&&) = default; AudioGroupPool& operator=(AudioGroupPool&&) = default; }; } #endif // __AMUSE_AUDIOGROUPPOOL_HPP__