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 }