|
|
@@ -921,6 +921,101 @@ template <> struct VST3FloatAndDoubleBusMapCompositeHelper<double> |
|
|
|
static VST3BufferExchange<double>::BusMap& get (VST3FloatAndDoubleBusMapComposite& impl) { return impl.doubleVersion; }
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class FloatCache
|
|
|
|
{
|
|
|
|
using FlagType = uint32_t;
|
|
|
|
|
|
|
|
public:
|
|
|
|
FloatCache() = default;
|
|
|
|
|
|
|
|
explicit FloatCache (size_t sizeIn)
|
|
|
|
: values (sizeIn),
|
|
|
|
flags (divCeil (sizeIn, numFlagBits))
|
|
|
|
{
|
|
|
|
std::fill (values.begin(), values.end(), 0.0f);
|
|
|
|
std::fill (flags.begin(), flags.end(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size() const noexcept { return values.size(); }
|
|
|
|
|
|
|
|
void set (size_t index, float value)
|
|
|
|
{
|
|
|
|
jassert (index < size());
|
|
|
|
values[index].store (value, std::memory_order_relaxed);
|
|
|
|
flags[index / numFlagBits].fetch_or ((FlagType) 1 << (index % numFlagBits),
|
|
|
|
std::memory_order_acq_rel);
|
|
|
|
}
|
|
|
|
|
|
|
|
float get (size_t index) const noexcept
|
|
|
|
{
|
|
|
|
jassert (index < size());
|
|
|
|
return values[index].load (std::memory_order_relaxed);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calls the supplied callback for any entries which have been modified
|
|
|
|
since the last call to this function.
|
|
|
|
*/
|
|
|
|
template <typename Callback>
|
|
|
|
void ifSet (Callback&& callback)
|
|
|
|
{
|
|
|
|
for (size_t flagIndex = 0; flagIndex < flags.size(); ++flagIndex)
|
|
|
|
{
|
|
|
|
const auto prevFlags = flags[flagIndex].exchange (0, std::memory_order_acq_rel);
|
|
|
|
|
|
|
|
for (size_t bit = 0; bit < numFlagBits; ++bit)
|
|
|
|
{
|
|
|
|
if (prevFlags & ((FlagType) 1 << bit))
|
|
|
|
{
|
|
|
|
const auto itemIndex = (flagIndex * numFlagBits) + bit;
|
|
|
|
callback (itemIndex, values[itemIndex].load (std::memory_order_relaxed));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static constexpr size_t numFlagBits = 8 * sizeof (FlagType);
|
|
|
|
|
|
|
|
static constexpr size_t divCeil (size_t a, size_t b)
|
|
|
|
{
|
|
|
|
return (a / b) + ((a % b) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::atomic<float>> values;
|
|
|
|
std::vector<std::atomic<FlagType>> flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Provides very quick polling of all parameter states.
|
|
|
|
|
|
|
|
We must iterate all parameters on each processBlock call to check whether any
|
|
|
|
parameter value has changed. This class attempts to make this polling process
|
|
|
|
as quick as possible.
|
|
|
|
*/
|
|
|
|
class CachedParamValues
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CachedParamValues() = default;
|
|
|
|
|
|
|
|
explicit CachedParamValues (std::vector<Steinberg::Vst::ParamID> paramIdsIn)
|
|
|
|
: paramIds (std::move (paramIdsIn)), floatCache (paramIds.size()) {}
|
|
|
|
|
|
|
|
size_t size() const noexcept { return floatCache.size(); }
|
|
|
|
|
|
|
|
Steinberg::Vst::ParamID getParamID (size_t index) const noexcept { return paramIds[index]; }
|
|
|
|
|
|
|
|
void set (size_t index, float value) { floatCache.set (index, value); }
|
|
|
|
|
|
|
|
float get (size_t index) const noexcept { return floatCache.get (index); }
|
|
|
|
|
|
|
|
template <typename Callback>
|
|
|
|
void ifSet (Callback&& callback) { floatCache.ifSet (std::forward<Callback> (callback)); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<Steinberg::Vst::ParamID> paramIds;
|
|
|
|
FloatCache floatCache;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace juce
|
|
|
|
|
|
|
|
#endif // ! DOXYGEN
|