Initial release
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Helpers
|
||||
// Filename : public.sdk/source/vst/vstaudioprocessoralgo.h
|
||||
// Created by : Steinberg, 04/2015
|
||||
// Description : Helper algo for AudioBusBuffers
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// This file is part of a Steinberg SDK. It is subject to the license terms
|
||||
// in the LICENSE file found in the top-level directory of this distribution
|
||||
// and at www.steinberg.net/sdklicenses.
|
||||
// No part of the SDK, including this file, may be copied, modified, propagated,
|
||||
// or distributed except according to the terms contained in the LICENSE file.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pluginterfaces/vst/ivstaudioprocessor.h"
|
||||
#include "pluginterfaces/vst/ivstevents.h"
|
||||
#include "pluginterfaces/vst/ivstparameterchanges.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace Steinberg {
|
||||
namespace Vst {
|
||||
|
||||
//---helpers---------
|
||||
/** Returns the current channelBuffers used (depending of symbolicSampleSize). */
|
||||
inline void** getChannelBuffersPointer (const ProcessSetup& processSetup,
|
||||
const AudioBusBuffers& bufs)
|
||||
{
|
||||
if (processSetup.symbolicSampleSize == kSample32)
|
||||
return (void**)bufs.channelBuffers32;
|
||||
return (void**)bufs.channelBuffers64;
|
||||
}
|
||||
|
||||
/** Returns the size in bytes of numSamples for one channel depending of symbolicSampleSize.*/
|
||||
inline uint32 getSampleFramesSizeInBytes (const ProcessSetup& processSetup, int32 numSamples)
|
||||
{
|
||||
if (processSetup.symbolicSampleSize == kSample32)
|
||||
return numSamples * sizeof (Sample32);
|
||||
return numSamples * sizeof (Sample64);
|
||||
}
|
||||
|
||||
/** return the bit-mask of channels for the given number of channel
|
||||
* for example:
|
||||
* numChannels = 1 => 0b0001 (binar) = 0x01 = 1 (decimal)
|
||||
* numChannels = 2 => 0b0011 (binar) = 0x03 = 3 (decimal)
|
||||
* numChannels = 6 => 0b0011 1111 (binar) = 0x3F = 63 (decimal)
|
||||
*/
|
||||
inline uint64 getChannelMask (int32 numChannels)
|
||||
{
|
||||
if (numChannels >= 64)
|
||||
return kMaxInt64u;
|
||||
|
||||
return ((uint64)1 << numChannels) - 1;
|
||||
}
|
||||
|
||||
namespace Algo {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach (AudioBusBuffers* audioBusBuffers, int32 busCount, const T& func)
|
||||
{
|
||||
if (!audioBusBuffers)
|
||||
return;
|
||||
|
||||
for (int32 busIndex = 0; busIndex < busCount; ++busIndex)
|
||||
{
|
||||
func (audioBusBuffers[busIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach32 (AudioBusBuffers& audioBuffer, const T& func)
|
||||
{
|
||||
for (int32 channelIndex = 0; channelIndex < audioBuffer.numChannels; ++channelIndex)
|
||||
{
|
||||
if (!audioBuffer.channelBuffers32[channelIndex])
|
||||
return;
|
||||
|
||||
func (audioBuffer.channelBuffers32[channelIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach64 (AudioBusBuffers& audioBuffer, const T& func)
|
||||
{
|
||||
for (int32 channelIndex = 0; channelIndex < audioBuffer.numChannels; ++channelIndex)
|
||||
{
|
||||
if (!audioBuffer.channelBuffers64[channelIndex])
|
||||
return;
|
||||
|
||||
func (audioBuffer.channelBuffers64[channelIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach32 (AudioBusBuffers& buffer1, AudioBusBuffers& buffer2, const T& func)
|
||||
{
|
||||
int32 numChannels = std::min<int32> (buffer1.numChannels, buffer2.numChannels);
|
||||
|
||||
for (int32 channelIndex = 0; channelIndex < numChannels; ++channelIndex)
|
||||
{
|
||||
func (buffer1.channelBuffers32[channelIndex], buffer2.channelBuffers32[channelIndex],
|
||||
channelIndex);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach64 (AudioBusBuffers& buffer1, AudioBusBuffers& buffer2, const T& func)
|
||||
{
|
||||
int32 numChannels = std::min<int32> (buffer1.numChannels, buffer2.numChannels);
|
||||
|
||||
for (int32 channelIndex = 0; channelIndex < numChannels; ++channelIndex)
|
||||
{
|
||||
func (buffer1.channelBuffers64[channelIndex], buffer2.channelBuffers64[channelIndex],
|
||||
channelIndex);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void copy32 (AudioBusBuffers* src, AudioBusBuffers* dest, int32 sliceSize, int32 startIndex)
|
||||
{
|
||||
if (!src || !dest)
|
||||
return;
|
||||
|
||||
int32 numChannels = std::min<int32> (src->numChannels, dest->numChannels);
|
||||
size_t numBytes = sliceSize * sizeof (Sample32);
|
||||
for (int32 chIdx = 0; chIdx < numChannels; ++chIdx)
|
||||
{
|
||||
memcpy (&dest->channelBuffers32[chIdx][startIndex], src->channelBuffers32[chIdx], numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void copy64 (AudioBusBuffers* src, AudioBusBuffers* dest, int32 sliceSize, int32 startIndex)
|
||||
{
|
||||
if (!src || !dest)
|
||||
return;
|
||||
|
||||
int32 numChannels = std::min<int32> (src->numChannels, dest->numChannels);
|
||||
size_t numBytes = sliceSize * sizeof (Sample64);
|
||||
for (int32 chIdx = 0; chIdx < numChannels; ++chIdx)
|
||||
{
|
||||
memcpy (&dest->channelBuffers64[chIdx][startIndex], src->channelBuffers64[chIdx], numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void clear32 (AudioBusBuffers* audioBusBuffers, int32 sampleCount, int32 busCount = 1)
|
||||
{
|
||||
if (!audioBusBuffers)
|
||||
return;
|
||||
|
||||
const int32 numBytes = sampleCount * sizeof (Sample32);
|
||||
foreach (audioBusBuffers, busCount, [&] (AudioBusBuffers& audioBuffer) {
|
||||
foreach32 (audioBuffer,
|
||||
[&] (Sample32* channelBuffer) { memset (channelBuffer, 0, numBytes); });
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void clear64 (AudioBusBuffers* audioBusBuffers, int32 sampleCount, int32 busCount = 1)
|
||||
{
|
||||
if (!audioBusBuffers)
|
||||
return;
|
||||
|
||||
const int32 numBytes = sampleCount * sizeof (Sample64);
|
||||
foreach (audioBusBuffers, busCount, [&] (AudioBusBuffers& audioBuffer) {
|
||||
foreach64 (audioBuffer,
|
||||
[&] (Sample64* channelBuffer) { memset (channelBuffer, 0, numBytes); });
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void mix32 (AudioBusBuffers& src, AudioBusBuffers& dest, int32 sampleCount)
|
||||
{
|
||||
foreach32 (src, dest, [&] (Sample32* srcBuffer, Sample32* destBuffer, int32 /*channelIndex*/) {
|
||||
for (int32 sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex)
|
||||
destBuffer[sampleIndex] += srcBuffer[sampleIndex];
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void mix64 (AudioBusBuffers& src, AudioBusBuffers& dest, int32 sampleCount)
|
||||
{
|
||||
foreach64 (src, dest, [&] (Sample64* srcBuffer, Sample64* destBuffer, int32 /*channelIndex*/) {
|
||||
for (int32 sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex)
|
||||
destBuffer[sampleIndex] += srcBuffer[sampleIndex];
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/* Multiply buffer with a constant */
|
||||
template <typename T>
|
||||
inline void multiply(T* srcBuffer, T* destBuffer, int32 sampleCount, T factor)
|
||||
{
|
||||
for (int32 sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex)
|
||||
destBuffer[sampleIndex] = srcBuffer[sampleIndex] * factor;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/* Multiply all channels of AudioBusBuffer with a constant */
|
||||
inline void multiply32 (AudioBusBuffers& src, AudioBusBuffers& dest, int32 sampleCount, float factor)
|
||||
{
|
||||
foreach32 (src, dest, [&](Sample32* srcBuffer, Sample32* destBuffer, int32 /*channelIndex*/) {
|
||||
multiply (srcBuffer, destBuffer, sampleCount, factor);
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/* Multiply all channels of AudioBusBuffer with a constant */
|
||||
inline void multiply64 (AudioBusBuffers& src, AudioBusBuffers& dest, int32 sampleCount, double factor)
|
||||
{
|
||||
foreach64 (src, dest, [&] (Sample64* srcBuffer, Sample64* destBuffer, int32 /*channelIndex*/) {
|
||||
multiply (srcBuffer, destBuffer, sampleCount, factor);
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool isSilent32 (AudioBusBuffers& audioBuffer, int32 sampleCount, int32 startIndex = 0)
|
||||
{
|
||||
const float epsilon = 1e-10f; // under -200dB...
|
||||
|
||||
sampleCount += startIndex;
|
||||
for (int32 channelIndex = 0; channelIndex < audioBuffer.numChannels; ++channelIndex)
|
||||
{
|
||||
if (!audioBuffer.channelBuffers32[channelIndex])
|
||||
return true;
|
||||
|
||||
for (int32 sampleIndex = startIndex; sampleIndex < sampleCount; ++sampleIndex)
|
||||
{
|
||||
float val = audioBuffer.channelBuffers32[channelIndex][sampleIndex];
|
||||
if (std::abs (val) > epsilon)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool isSilent64 (AudioBusBuffers& audioBuffer, int32 sampleCount, int32 startIndex = 0)
|
||||
{
|
||||
const double epsilon = 1e-10f; // under -200dB...
|
||||
|
||||
sampleCount += startIndex;
|
||||
for (int32 channelIndex = 0; channelIndex < audioBuffer.numChannels; ++channelIndex)
|
||||
{
|
||||
if (!audioBuffer.channelBuffers64[channelIndex])
|
||||
return true;
|
||||
|
||||
for (int32 sampleIndex = startIndex; sampleIndex < sampleCount; ++sampleIndex)
|
||||
{
|
||||
double val = audioBuffer.channelBuffers64[channelIndex][sampleIndex];
|
||||
if (std::abs (val) > epsilon)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach (IEventList* eventList, const T& func)
|
||||
{
|
||||
if (!eventList)
|
||||
return;
|
||||
|
||||
auto eventCount = eventList->getEventCount ();
|
||||
for (int32 eventIndex = 0; eventIndex < eventCount; ++eventIndex)
|
||||
{
|
||||
Vst::Event event = {};
|
||||
if (eventList->getEvent (eventIndex, event) != kResultOk)
|
||||
continue;
|
||||
|
||||
func (event);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach (IParamValueQueue& paramQueue, const T& func)
|
||||
{
|
||||
auto paramId = paramQueue.getParameterId ();
|
||||
auto numPoints = paramQueue.getPointCount ();
|
||||
for (int32 pointIndex = 0; pointIndex < numPoints; ++pointIndex)
|
||||
{
|
||||
int32 sampleOffset = 0;
|
||||
ParamValue value = 0;
|
||||
if (paramQueue.getPoint (pointIndex, sampleOffset, value) != kResultOk)
|
||||
continue;
|
||||
|
||||
func (paramId, sampleOffset, value);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreachLast (IParamValueQueue& paramQueue, const T& func)
|
||||
{
|
||||
auto paramId = paramQueue.getParameterId ();
|
||||
auto numPoints = paramQueue.getPointCount ();
|
||||
int32 sampleOffset = 0;
|
||||
ParamValue value = 0;
|
||||
if (paramQueue.getPoint (numPoints - 1, sampleOffset, value) == kResultOk)
|
||||
func (paramId, sampleOffset, value);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline void foreach (IParameterChanges* changes, const T& func)
|
||||
{
|
||||
if (!changes)
|
||||
return;
|
||||
|
||||
auto paramCount = changes->getParameterCount ();
|
||||
for (int32 paramIndex = 0; paramIndex < paramCount; ++paramIndex)
|
||||
{
|
||||
auto paramValueQueue = changes->getParameterData (paramIndex);
|
||||
if (!paramValueQueue)
|
||||
continue;
|
||||
|
||||
func (*paramValueQueue);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace Algo
|
||||
} // namespace Vst
|
||||
} // namespace Steinberg
|
||||
Reference in New Issue
Block a user