diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/pattern.h | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/pattern.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/pattern.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/pattern.h b/Src/external_dependencies/openmpt-trunk/soundlib/pattern.h new file mode 100644 index 00000000..c5e98aad --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/pattern.h @@ -0,0 +1,214 @@ +/* + * Pattern.h + * --------- + * Purpose: Module Pattern header class + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + +#include <vector> +#include "modcommand.h" +#include "Snd_defs.h" + + +OPENMPT_NAMESPACE_BEGIN + + +class CPatternContainer; +class CSoundFile; +class EffectWriter; + +typedef ModCommand* PatternRow; + + +class CPattern +{ + friend class CPatternContainer; + +public: + CPattern& operator= (const CPattern &pat); + bool operator== (const CPattern &other) const; + bool operator!= (const CPattern &other) const { return !(*this == other); } + +public: + ModCommand* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) { return &m_ModCommands[r * GetNumChannels() + c]; } + const ModCommand* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) const { return &m_ModCommands[r * GetNumChannels() + c]; } + + ROWINDEX GetNumRows() const { return m_Rows; } + ROWINDEX GetRowsPerBeat() const { return m_RowsPerBeat; } // pattern-specific rows per beat + ROWINDEX GetRowsPerMeasure() const { return m_RowsPerMeasure; } // pattern-specific rows per measure + bool GetOverrideSignature() const { return (m_RowsPerBeat + m_RowsPerMeasure > 0); } // override song time signature? + + // Returns true if pattern data can be accessed at given row, false otherwise. + bool IsValidRow(const ROWINDEX row) const { return (row < GetNumRows()); } + // Returns true if any pattern data is present. + bool IsValid() const { return !m_ModCommands.empty(); } + + // Return PatternRow object which has operator[] defined so that ModCommand + // at (iRow, iChn) can be accessed with GetRow(iRow)[iChn]. + PatternRow GetRow(const ROWINDEX row) { return GetpModCommand(row, 0); } + PatternRow GetRow(const ROWINDEX row) const { return const_cast<ModCommand *>(GetpModCommand(row, 0)); } + + CHANNELINDEX GetNumChannels() const; + + // Add or remove rows from the pattern. + bool Resize(const ROWINDEX newRowCount, bool enforceFormatLimits = true, bool resizeAtEnd = true); + + // Check if there is any note data on a given row. + bool IsEmptyRow(ROWINDEX row) const; + + // Allocate new pattern memory and replace old pattern data. + bool AllocatePattern(ROWINDEX rows); + // Deallocate pattern data. + void Deallocate(); + + // Removes all modcommands from the pattern. + void ClearCommands(); + + // Returns associated soundfile. + CSoundFile& GetSoundFile(); + const CSoundFile& GetSoundFile() const; + + const std::vector<ModCommand> &GetData() const { return m_ModCommands; } + void SetData(std::vector<ModCommand> &&data) { MPT_ASSERT(data.size() == GetNumRows() * GetNumChannels()); m_ModCommands = std::move(data); } + + // Set pattern signature (rows per beat, rows per measure). Returns true on success. + bool SetSignature(const ROWINDEX rowsPerBeat, const ROWINDEX rowsPerMeasure); + void RemoveSignature() { m_RowsPerBeat = m_RowsPerMeasure = 0; } + + bool HasTempoSwing() const { return !m_tempoSwing.empty(); } + const TempoSwing& GetTempoSwing() const { return m_tempoSwing; } + void SetTempoSwing(const TempoSwing &swing) { m_tempoSwing = swing; m_tempoSwing.Normalize(); } + void RemoveTempoSwing() { m_tempoSwing.clear(); } + + // Pattern name functions - bool functions return true on success. + bool SetName(const std::string &newName); + bool SetName(const char *newName, size_t maxChars); + template<size_t bufferSize> + bool SetName(const char (&buffer)[bufferSize]) + { + return SetName(buffer, bufferSize); + } + + std::string GetName() const { return m_PatternName; } + +#ifdef MODPLUG_TRACKER + // Double number of rows + bool Expand(); + + // Halve number of rows + bool Shrink(); +#endif // MODPLUG_TRACKER + + // Write some kind of effect data to the pattern + bool WriteEffect(EffectWriter &settings); + + typedef std::vector<ModCommand>::iterator iterator; + typedef std::vector<ModCommand>::const_iterator const_iterator; + + iterator begin() { return m_ModCommands.begin(); } + const_iterator begin() const { return m_ModCommands.begin(); } + const_iterator cbegin() const { return m_ModCommands.cbegin(); } + + iterator end() { return m_ModCommands.end(); } + const_iterator end() const { return m_ModCommands.end(); } + const_iterator cend() const { return m_ModCommands.cend(); } + + CPattern(CPatternContainer& patCont) : m_rPatternContainer(patCont) {} + CPattern(const CPattern &) = default; + CPattern(CPattern &&) noexcept = default; + +protected: + ModCommand& GetModCommand(size_t i) { return m_ModCommands[i]; } + //Returns modcommand from (floor[i/channelCount], i%channelCount) + + ModCommand& GetModCommand(ROWINDEX r, CHANNELINDEX c) { return m_ModCommands[r * GetNumChannels() + c]; } + const ModCommand& GetModCommand(ROWINDEX r, CHANNELINDEX c) const { return m_ModCommands[r * GetNumChannels() + c]; } + + +protected: + std::vector<ModCommand> m_ModCommands; + ROWINDEX m_Rows = 0; + ROWINDEX m_RowsPerBeat = 0; // patterns-specific time signature. if != 0, this is implicitely set. + ROWINDEX m_RowsPerMeasure = 0; // ditto + TempoSwing m_tempoSwing; + std::string m_PatternName; + CPatternContainer& m_rPatternContainer; +}; + + +const char FileIdPattern[] = "mptP"; + +void ReadModPattern(std::istream& iStrm, CPattern& patc, const size_t nSize = 0); +void WriteModPattern(std::ostream& oStrm, const CPattern& patc); + + +// Class for conveniently writing an effect to the pattern. + +class EffectWriter +{ + friend class CPattern; + + // Row advance mode + enum RetryMode + { + rmIgnore, // If effect can't be written, abort. + rmTryNextRow, // If effect can't be written, try next row. + rmTryPreviousRow, // If effect can't be written, try previous row. + }; + +public: + // Constructors with effect commands + EffectWriter(EffectCommand cmd, ModCommand::PARAM param) : m_command(cmd), m_param(param), m_isVolEffect(false) { Init(); } + EffectWriter(VolumeCommand cmd, ModCommand::VOL param) : m_volcmd(cmd), m_vol(param), m_isVolEffect(true) { Init(); } + + // Additional constructors: + // Set row in which writing should start + EffectWriter &Row(ROWINDEX row) { m_row = row; return *this; } + // Set channel to which writing should be restricted to + EffectWriter &Channel(CHANNELINDEX chn) { m_channel = chn; return *this; } + // Allow multiple effects of the same kind to be written in the same row. + EffectWriter &AllowMultiple() { m_allowMultiple = true; return *this; } + // Set retry mode. + EffectWriter &RetryNextRow() { m_retryMode = rmTryNextRow; return *this; } + EffectWriter &RetryPreviousRow() { m_retryMode = rmTryPreviousRow; return *this; } + +protected: + RetryMode m_retryMode; + ROWINDEX m_row; + CHANNELINDEX m_channel; + + union + { + EffectCommand m_command; + VolumeCommand m_volcmd; + }; + union + { + ModCommand::PARAM m_param; + ModCommand::VOL m_vol; + }; + + bool m_retry : 1; + bool m_allowMultiple : 1; + bool m_isVolEffect : 1; + + // Common data initialisation + void Init() + { + m_row = 0; + m_channel = CHANNELINDEX_INVALID; // Any channel + m_retryMode = rmIgnore; // If effect couldn't be written, abort. + m_retry = true; + m_allowMultiple = false; // Stop if same type of effect is encountered + } +}; + + +OPENMPT_NAMESPACE_END |