123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- #pragma once
- #include "openmpt/all/BuildSettings.hpp"
- #include "mpt/base/span.hpp"
- #include "Snd_defs.h"
- #include <map>
- OPENMPT_NAMESPACE_BEGIN
- #if defined(MPT_BUILD_DEBUG) || defined(MPT_BUILD_FUZZER)
- #define MPT_VERIFY_ROWVISITOR_LOOPSTATE
- #endif
- class CSoundFile;
- class ModSequence;
- struct ModChannel;
- class RowVisitor
- {
- protected:
- using ChannelStates = mpt::span<const ModChannel>;
- class LoopState
- {
- static constexpr uint64 FNV1a_BASIS = 14695981039346656037ull;
- static constexpr uint64 FNV1a_PRIME = 1099511628211ull;
- uint64 m_hash = FNV1a_BASIS;
- #ifdef MPT_VERIFY_ROWVISITOR_LOOPSTATE
- std::vector<std::pair<uint8, uint8>> m_counts;
- #endif
- public:
- LoopState() = default;
- LoopState(const ChannelStates &chnState, const bool ignoreRow);
- LoopState(const LoopState &) = default;
- LoopState(LoopState&&) = default;
- LoopState &operator=(const LoopState &) = default;
- LoopState &operator=(LoopState&&) = default;
- [[nodiscard]] bool operator==(const LoopState &other) const noexcept
- {
- #ifdef MPT_VERIFY_ROWVISITOR_LOOPSTATE
- if((m_counts == other.m_counts) != (m_hash == other.m_hash))
- std::abort();
- #endif
- return m_hash == other.m_hash;
- }
-
- [[nodiscard]] bool HasLoops() const noexcept
- {
- #ifdef MPT_VERIFY_ROWVISITOR_LOOPSTATE
- if(m_counts.empty() != (m_hash == FNV1a_BASIS))
- std::abort();
- #endif
- return m_hash != FNV1a_BASIS;
- }
- };
- using LoopStateSet = std::vector<LoopState>;
-
- std::vector<std::vector<bool>> m_visitedRows;
-
- std::map<std::pair<ORDERINDEX, ROWINDEX>, LoopStateSet> m_visitedLoopStates;
- const CSoundFile &m_sndFile;
- ROWINDEX m_rowsSpentInLoops = 0;
- const SEQUENCEINDEX m_sequence;
- public:
- RowVisitor(const CSoundFile &sndFile, SEQUENCEINDEX sequence = SEQUENCEINDEX_INVALID);
-
- void MoveVisitedRowsFrom(RowVisitor &other) noexcept;
-
-
- void Initialize(bool reset);
-
- bool Visit(ORDERINDEX ord, ROWINDEX row, const ChannelStates &chnState, bool ignoreRow);
-
-
-
-
- [[nodiscard]] bool GetFirstUnvisitedRow(ORDERINDEX &order, ROWINDEX &row, bool onlyUnplayedPatterns) const;
-
-
- [[nodiscard]] bool ModuleTooComplex(ROWINDEX threshold) const noexcept { return m_rowsSpentInLoops >= threshold; }
- void ResetComplexity() { m_rowsSpentInLoops = 0; }
- protected:
-
- [[nodiscard]] ROWINDEX VisitedRowsVectorSize(PATTERNINDEX pattern) const noexcept;
- [[nodiscard]] const ModSequence &Order() const;
- };
- OPENMPT_NAMESPACE_END
|