SmartGuitarAmp

Guitar plugin made with JUCE that uses neural networks to emulate a tube amplifier
Log | Files | Refs | Submodules | README

Convolution.cpp (3505B)


      1 /*
      2   ==============================================================================
      3 
      4     Convolution.cpp
      5     Created: 3 Jan 2019 10:58:34am
      6     Author:  Damskägg Eero-Pekka
      7 
      8   ==============================================================================
      9 */
     10 
     11 #include "Convolution.h"
     12 
     13 Convolution::Convolution(size_t inputChannels, size_t outputChannels, int filterWidth, int dilation) :
     14     bias(outputChannels),
     15     outVec(outputChannels),
     16     pos(0),
     17     dilation(dilation),
     18     inputChannels(inputChannels),
     19     outputChannels(outputChannels),
     20     filterWidth(filterWidth)
     21 {
     22     resetFifo();
     23     resetKernel();
     24 }
     25 
     26 void Convolution::resetKernel()
     27 {
     28     kernel.clear();
     29     kernel.reserve(filterWidth);
     30     for (int i = 0; i < filterWidth; ++i)
     31     {
     32         Eigen::MatrixXf x(inputChannels, outputChannels);
     33         x.setZero();
     34         kernel.push_back(x);
     35     }
     36     bias = Eigen::RowVectorXf (outputChannels);
     37     bias.setZero();
     38 }
     39 
     40 void Convolution::resetFifo()
     41 {
     42     memory.clear();
     43     memory.reserve(getFilterOrder());
     44     for (int i = 0; i < getFilterOrder(); ++i)
     45     {
     46         Eigen::RowVectorXf x(inputChannels);
     47         x.setZero();
     48         memory.push_back(x);
     49     }
     50     pos = 0;
     51 }
     52 
     53 void Convolution::setParams(size_t newInputChannels, size_t newOutputChannels,
     54                             int newFilterWidth, int newDilation)
     55 {
     56     inputChannels = newInputChannels;
     57     outputChannels = newOutputChannels;
     58     filterWidth = newFilterWidth;
     59     dilation = newDilation;
     60     outVec = Eigen::RowVectorXf (outputChannels);
     61     resetFifo();
     62     resetKernel();
     63 }
     64 
     65 int Convolution::getFilterOrder() const
     66 {
     67     return (filterWidth-1)*dilation + 1;
     68 }
     69 
     70 void Convolution::process(float* data, int numSamples)
     71 {
     72     for (int i = 0; i < numSamples; ++i)
     73     {
     74         processSingleSample(data, i , numSamples);
     75     }
     76 }
     77 
     78 void Convolution::processSingleSample(float* data, int i, int numSamples)  
     79 {
     80     if (memory.size() != getFilterOrder()) 
     81         resetFifo();  
     82     auto fifo = memory.begin();   
     83     for (int ch = 0; ch < inputChannels; ++ch)  
     84         (*(fifo+pos))[ch] = data[idx(ch, i, numSamples)]; 
     85     outVec.setZero();  
     86     std::vector<Eigen::MatrixXf>::iterator it;
     87     int j = 0;
     88     for (auto it = kernel.begin(); it != kernel.end(); it++) 
     89     {
     90         int readPos = mod((pos - j * dilation), getFilterOrder()); 
     91         outVec = outVec + *(fifo+readPos) * (*it);  
     92         j += 1; 
     93     }
     94     outVec = outVec + bias;  
     95     for (int ch = 0; ch < outputChannels; ++ch)  
     96         data[idx(ch, i, numSamples)] = outVec[ch];  
     97     pos = mod(pos + 1, getFilterOrder()); 
     98 }
     99 
    100 
    101 int Convolution::mod(int a, int b)
    102 {
    103     int r = a % b;
    104     return r < 0 ? r + b : r;
    105 }
    106 
    107 int Convolution::idx(int ch, int i, int numSamples)
    108 {
    109     return ch * numSamples + i;
    110 }
    111 
    112 void Convolution::setWeight(std::vector<float> W, std::string name)
    113 {
    114     if (name == "W")
    115         setKernel(W);
    116     else if (name == "b")
    117         setBias(W);
    118 }
    119 
    120 void Convolution::setKernel(std::vector<float> W)
    121 {
    122     assert(W.size() == inputChannels*outputChannels*filterWidth);
    123     size_t i = 0;
    124     for (size_t k = 0; k < filterWidth; ++k)
    125         for(size_t row = 0; row < inputChannels; ++row)
    126             for (size_t col = 0; col < outputChannels; ++col)
    127             {
    128                 kernel[filterWidth-1-k](row,col) = W[i];
    129                 i += 1;
    130             }
    131 }
    132 
    133 void Convolution::setBias(std::vector<float> W)
    134 {
    135     assert(W.size() == outputChannels);
    136     for (size_t i = 0; i < outputChannels; ++i)
    137         bias(i) = W[i];
    138 }