|
- #pragma once
-
- #include <stdint.h>
- #include <memory>
- #include <assert.h>
- #include "asserts.h"
-
- #include "PitchUtils.h"
-
-
- // forward declare smart pointers
- class MidiEvent;
- class MidiEndEvent;
- class MidiNoteEvent;
- class MidiTestEvent;
- class MidiEndEvent;
- using MidiEndEventPtr = std::shared_ptr<MidiEndEvent>;
- using MidiTestEventPtr = std::shared_ptr<MidiTestEvent>;
- using MidiEventPtr = std::shared_ptr<MidiEvent>;
- using MidiEventPtrC = std::shared_ptr<const MidiEvent>;
- using MidiNoteEventPtr = std::shared_ptr<MidiNoteEvent>;
- using MidiNoteEventPtrC = std::shared_ptr<const MidiNoteEvent>;
-
-
- /**
- * Abstract base class for all events
- */
- class MidiEvent
- {
- public:
- typedef float time_t;
- enum class Type
- {
- Note,
- End,
- Test
- };
-
- Type type = Type::Test;
-
- /**
- * time units are floats, 1.0 == quarter note
- */
- time_t startTime = 0;
-
- bool operator == (const MidiEvent&) const;
- bool operator != (const MidiEvent&) const;
-
- virtual MidiEventPtr clone() const = 0;
-
- virtual void assertValid() const;
-
- virtual ~MidiEvent()
- {
- #ifdef _DEBUG
- --_count;
- #endif
- }
- #ifdef _DEBUG
- static int _count; // for debugging - reference count
- #endif
-
- protected:
- MidiEvent()
- {
- #ifdef _DEBUG
- ++_count;
- #endif
- }
- MidiEvent(const MidiEvent& e)
- {
- #ifdef _DEBUG
- ++_count;
- #endif
- this->startTime = e.startTime;
- }
-
- public:
- virtual bool isEqualBase(const MidiEvent& other) const
- {
- return this->startTime == other.startTime;
- }
- virtual bool isEqual(const MidiEvent& other) const = 0;
- };
-
-
- inline bool MidiEvent::operator == (const MidiEvent& other) const
- {
- if (other.type != this->type) {
- return false;
- }
- return isEqual(other);
- }
-
- inline bool MidiEvent::operator != (const MidiEvent& other) const
- {
- return !(*this == other);
- }
-
- inline void MidiEvent::assertValid() const
- {
- assertGE(startTime, 0);
- }
-
- /**
- * Derived pointers must provide an implementation for casting
- * base (MidiEventPtr) to derived pointer
- */
- template<typename T, typename Q>
- inline std::shared_ptr<T> safe_cast(std::shared_ptr<Q>)
- {
- // default implementation always fails.
- // this avoids linker errors for unimplemented cases
- return nullptr;
- }
-
- /********************************************************************
- **
- ** MidiNoteEvent
- **
- ********************************************************************/
-
- class MidiNoteEvent : public MidiEvent
- {
- public:
- MidiNoteEvent()
- {
- type = Type::Note;
- }
- MidiNoteEvent(const MidiNoteEvent& n) : MidiEvent(n)
- {
- type = Type::Note;
- this->pitchCV = n.pitchCV;
- this->duration = n.duration;
- }
-
- /**
- * Pitch is VCV standard 1V/8
- */
- float pitchCV = 0;
- float duration = 1;
- void assertValid() const override;
-
- void setPitch(int octave, int semi);
- std::pair<int, int> getPitch() const;
-
- virtual MidiEventPtr clone() const override;
- MidiNoteEventPtr clonen() const;
-
- protected:
- virtual bool isEqual(const MidiEvent&) const override;
- };
-
- inline std::pair<int, int> MidiNoteEvent::getPitch() const
- {
- return PitchUtils::cvToPitch(pitchCV);
- }
-
- inline void MidiNoteEvent::setPitch(int octave, int semi)
- {
- pitchCV = PitchUtils::pitchToCV(octave, semi);
- }
-
- inline void MidiNoteEvent::assertValid() const
- {
- MidiEvent::assertValid();
- assertLE(pitchCV, 10);
- assertGE(pitchCV, -10);
- assertGT(duration, 0);
- }
-
- inline bool MidiNoteEvent::isEqual(const MidiEvent& other) const
- {
- const MidiNoteEvent* otherNote = static_cast<const MidiNoteEvent*>(&other);
- return other.isEqualBase(*this) &&
- this->pitchCV == otherNote->pitchCV &&
- this->duration == otherNote->duration;
- }
-
- template<>
- inline MidiNoteEventPtr safe_cast(std::shared_ptr<MidiEvent> ev)
- {
- MidiNoteEventPtr note;
- if (ev->type == MidiEvent::Type::Note) {
- note = std::static_pointer_cast<MidiNoteEvent>(ev);
- }
- return note;
- }
-
- template<>
- inline std::shared_ptr<MidiEvent> safe_cast(std::shared_ptr<MidiNoteEvent> ev)
- {
- return ev;
- }
-
- inline MidiNoteEventPtr MidiNoteEvent::clonen() const
- {
- return std::make_shared<MidiNoteEvent>(*this);
- }
-
- inline MidiEventPtr MidiNoteEvent::clone() const
- {
- return this->clonen();
- }
- /********************************************************************
- **
- ** MidiEndEvent
- **
- ********************************************************************/
-
- class MidiEndEvent : public MidiEvent
- {
- public:
- void assertValid() const override;
- MidiEndEvent()
- {
- type = Type::End;
- }
-
- MidiEndEvent(const MidiEndEvent& e) : MidiEvent(e)
- {
- type = Type::End;
- }
-
- virtual MidiEventPtr clone() const override;
- MidiEndEventPtr clonee() const;
- protected:
- virtual bool isEqual(const MidiEvent&) const override;
- };
-
- inline void MidiEndEvent::assertValid() const
- {
- MidiEvent::assertValid();
- }
-
- inline bool MidiEndEvent::isEqual(const MidiEvent& other) const
- {
- //const MidiEndEvent* otherNote = static_cast<const MidiEndEvent*>(&other);
- return other.isEqualBase(*this);
- }
-
- template<>
- inline std::shared_ptr<MidiEndEvent> safe_cast(std::shared_ptr<MidiEvent> ev)
- {
- std::shared_ptr<MidiEndEvent> endev;
- if (ev->type == MidiEvent::Type::End) {
- endev = std::static_pointer_cast<MidiEndEvent>(ev);
- }
- return endev;
- }
-
- template<>
- inline std::shared_ptr<MidiEvent> safe_cast(std::shared_ptr<MidiEndEvent> ev)
- {
- return ev;
- }
-
- inline MidiEventPtr MidiEndEvent::clone() const
- {
- return std::make_shared<MidiEndEvent>(*this);
- }
-
-
- /********************************************************************
- **
- ** MidiTestEvent
- ** (just for unit tests)
- ********************************************************************/
-
- class MidiTestEvent : public MidiEvent
- {
- public:
- void assertValid() const override;
- MidiTestEvent()
- {
- type = Type::Test;
- }
- virtual MidiEventPtr clone() const override;
- protected:
- virtual bool isEqual(const MidiEvent&) const override;
- };
-
- inline void MidiTestEvent::assertValid() const
- {
- MidiEvent::assertValid();
- }
-
- inline bool MidiTestEvent::isEqual(const MidiEvent& other) const
- {
- return other.isEqualBase(*this);
- }
-
- template<>
- inline std::shared_ptr<MidiTestEvent> safe_cast(std::shared_ptr<MidiEvent> ev)
- {
- std::shared_ptr<MidiTestEvent> test;
- if (ev->type == MidiEvent::Type::Test) {
- test = std::static_pointer_cast<MidiTestEvent>(ev);
- }
- return test;
- }
-
- template<>
- inline std::shared_ptr<MidiEvent> safe_cast(std::shared_ptr<MidiTestEvent> ev)
- {
- return ev;
- }
-
- inline MidiEventPtr MidiTestEvent::clone() const
- {
- return std::make_shared<MidiTestEvent>(*this);
- }
|