Created
July 13, 2018 22:16
-
-
Save nick-thompson/b018a62bf73d84666a3895dc35b1f491 to your computer and use it in GitHub Desktop.
Modulation Matrix Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <int Rows, int Cols, typename FloatType> | |
class ModulationMatrix | |
{ | |
public: | |
//============================================================================== | |
ModulationMatrix (std::array<std::array<FloatType*, Cols>, Rows> params) : m_rawMatrixParams(params) {} | |
~ModulationMatrix () {} | |
//============================================================================== | |
/** Returns the internal raw parameter matrix. */ | |
auto getRawMatrixParameters() { return m_rawMatrixParams; } | |
/** Computes the aggregate modulation value for each target. */ | |
template <unsigned long N, unsigned long M> | |
void tick (const std::array<FloatType, N> modValues, std::array<FloatType, M>& targetValues) | |
{ | |
static_assert(N == Cols, "The number of modulation values received must equal the number of columsn."); | |
static_assert(M == Rows, "The number of target values received must equal the number of rows."); | |
// Reset target values to zero | |
targetValues.fill(static_cast<FloatType>(0.)); | |
for (int i = 0; i < Rows; ++i) | |
{ | |
// Accumulate the various modulation sources | |
for (int j = 0; j < Cols; ++j) | |
{ | |
targetValues[i] += modValues[j] * (*m_rawMatrixParams[i][j]); | |
} | |
} | |
} | |
private: | |
//============================================================================== | |
std::array<std::array<FloatType*, Cols>, Rows> m_rawMatrixParams; | |
//============================================================================== | |
JUCE_LEAK_DETECTOR (ModulationMatrix) | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In your constructor, assuming AudioProcessorValueTreeState `m_state` | |
std::array<std::array<float*, NumSources>, NumTargets> rawMatrixParams; | |
for (int i = 0; i < ModulationTargets::NumTargets; ++i) | |
{ | |
for (int j = 0; j < ModulationSources::NumSources; ++j) | |
{ | |
String id = String("matrix/") + String(i) + String("/") + String(j); | |
m_state.createAndAddParameter(id, id, String(), | |
NormalisableRange<float>(0.f, 1.f), 0.f, | |
nullptr, nullptr); | |
rawMatrixParams[i][j] = m_state.getRawParameterValue(id); | |
} | |
} | |
// Assuming we'll process at least one channel, lets build the first modulation matrix. | |
// Note, this touches a member vector `std::vector<ci::ModulationMatrix<NumTargets, NumSources, float>> modMatrix;` | |
modMatrix.push_back(ci::ModulationMatrix<NumTargets, NumSources, float>(rawMatrixParams)); | |
// Then in prepareToPlay, you can allocate 1 matrix per channel | |
jassert (modMatrix.size() > 0); | |
modMatrix.resize(numChannels, modMatrix[0].getRawMatrixParameters()); | |
// And in processBlock, step each modulator and then step the matrix | |
float lfo1 = lfoMods[0].tick(); | |
float lfo2 = lfoMods[1].tick(); | |
float lfo3 = lfoMods[2].tick(); | |
// Now step the modulation matrix, overwriting `matrixValues`. | |
const std::array<float, NumSources> modValues { lfo1, lfo2, lfo3 }; | |
modMatrix[i].tick(modValues, matrixValues); | |
// Now `matrixValues` contains everything you need to apply to your parameters |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment