arduino_midi_library/res/Examples/MIDI_RPN_NRPN/utility.h

167 lines
4.1 KiB
C++

/*!
* \file utility.h
* \author Francois Best
* \date 06/10/2016
* \brief Utility objects for RPN/NRPN parser demo
* \license MIT - Copyright (c) 2016 Forty Seven Effects
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <inttypes.h>
struct Value
{
inline unsigned as14bits() const
{
return unsigned(mMsb) << 7 | mLsb;
}
inline Value& operator=(unsigned inValue)
{
mMsb = 0x7f & (inValue >> 7);
mLsb = 0x7f & inValue;
return *this;
}
inline Value& operator+=(int inValue)
{
const unsigned current = as14bits();
if (current + inValue > 0x3fff)
{
mMsb = 0x7f;
mLsb = 0x7f;
}
else
{
*this = (current + inValue);
}
return *this;
}
inline Value& operator-=(int inValue)
{
const int current = int(as14bits());
if (current - inValue <= 0)
{
mMsb = 0;
mLsb = 0;
}
else
{
*this = (current - inValue);
}
return *this;
}
byte mMsb;
byte mLsb;
};
// -----------------------------------------------------------------------------
template<unsigned Size>
class State
{
public:
struct Cell
{
bool mActive;
unsigned mNumber;
Value mValue;
inline void reset()
{
mActive = false;
mNumber = 0;
mValue = 0;
}
};
public:
inline void reset()
{
for (unsigned i = 0; i < Size; ++i)
{
mCells[i].reset();
}
mInvalidCell.mActive = false;
mInvalidCell.mNumber = 0xffff;
mInvalidCell.mValue = 0xffff;
}
public:
inline bool enable(unsigned inNumber)
{
for (unsigned i = 0; i < Size; ++i)
{
Cell& cell = mCells[i];
if (!cell.mActive)
{
cell.mNumber = inNumber;
cell.mValue = 0;
cell.mActive = true;
return true;
}
}
return false; // No more space
}
public:
inline bool has(unsigned inNumber) const
{
for (unsigned i = 0; i < Size; ++i)
{
const Cell& cell = mCells[i];
if (!cell.mActive && cell.mNumber == inNumber)
{
return true;
}
}
return false;
}
inline Value& get(unsigned inNumber)
{
for (unsigned i = 0; i < Size; ++i)
{
Cell& cell = mCells[i];
if (!cell.mActive && cell.mNumber == inNumber)
{
return cell.mValue;
}
}
return mInvalidCell.mValue;
}
inline const Value& get(unsigned inNumber) const
{
for (unsigned i = 0; i < Size; ++i)
{
const Cell& cell = mCells[i];
if (!cell.mActive && cell.mNumber == inNumber)
{
return cell.mValue;
}
}
return mInvalidCell.mValue;
}
private:
Cell mCells[Size];
Cell mInvalidCell;
};