BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

buffer.hpp (3256B)


      1 #pragma once
      2 
      3 #include "assert.h"
      4 #include "math.h"
      5 #include <algorithm>
      6 
      7 namespace bogaudio {
      8 namespace dsp {
      9 
     10 template<typename T>
     11 struct OverlappingBuffer {
     12 	const int _size;
     13 	const int _overlap;
     14 	const bool _autoProcess;
     15 	const int _overlapN;
     16 	const int _samplesN;
     17 	T* _samples;
     18 	int _sample;
     19 
     20 	OverlappingBuffer(int size, int o, bool autoProcess = true)
     21 	: _size(size)
     22 	, _overlap(o)
     23 	, _autoProcess(autoProcess)
     24 	, _overlapN(_size / _overlap)
     25 	, _samplesN(2*_size - _overlapN)
     26 	, _samples(new T[_samplesN])
     27 	, _sample(0)
     28 	{
     29 		assert(_size > 0);
     30 		assert(_overlap > 0 && _overlap <= _size && _size % _overlap == 0);
     31 	}
     32 	virtual ~OverlappingBuffer() {
     33 		delete[] _samples;
     34 	}
     35 
     36 	inline void process() { processBuffer(_samples + _sample - _size); }
     37 	virtual void processBuffer(T* samples) = 0;
     38 	void postProcess() {
     39 		if (_overlap == 1) {
     40 			_sample = 0;
     41 		}
     42 		else if (_sample == _samplesN) {
     43 			std::copy(_samples + _size, _samples + _samplesN, _samples);
     44 			_sample = _samplesN - _size;
     45 		}
     46 	}
     47 
     48 	virtual bool step(T sample) {
     49 		_samples[_sample++] = sample;
     50 		assert(_sample <= _samplesN);
     51 
     52 		if (_sample >= _size && _sample % _overlapN == 0) {
     53 			if (_autoProcess) {
     54 				process();
     55 				postProcess();
     56 			}
     57 			return true;
     58 		}
     59 		return false;
     60 	}
     61 };
     62 
     63 
     64 template<typename T>
     65 struct AveragingBuffer {
     66 	const int _size;
     67 	const int _framesN;
     68 	const float _inverseFramesN;
     69 	T* _sums;
     70 	T* _averages;
     71 	T* _frames;
     72 	int _currentFrame;
     73 	const int _resetsPerCommit;
     74 	int _currentReset;
     75 
     76 	AveragingBuffer(
     77 		int size,
     78 		int framesToAverage
     79 	)
     80 	: _size(size)
     81 	, _framesN(framesToAverage)
     82 	, _inverseFramesN(1.0 / (float)_framesN)
     83 	, _sums(new T[_size] {})
     84 	, _averages(new T[_size] {})
     85 	, _frames(new T[_size * _framesN] {})
     86 	, _currentFrame(0)
     87 	, _resetsPerCommit(std::max(_size / 100, 10))
     88 	, _currentReset(0)
     89 	{
     90 		assert(framesToAverage > 0);
     91 	}
     92 	~AveragingBuffer() {
     93 		delete[] _sums;
     94 		delete[] _averages;
     95 		delete[] _frames;
     96 	}
     97 
     98 	T* getInputFrame() {
     99 		float* frame = _frames + _currentFrame*_size;
    100 		for (int i = 0; i < _size; ++i) {
    101 			_sums[i] -= frame[i];
    102 		}
    103 		return frame;
    104 	}
    105 
    106 	void commitInputFrame() {
    107 		float* frame = _frames + _currentFrame*_size;
    108 		for (int i = 0; i < _size; ++i) {
    109 			_sums[i] += frame[i];
    110 			_averages[i] = _sums[i] * _inverseFramesN;
    111 		}
    112 
    113 		// Reset the average for some bins, such that reset overhead is even between calls -- avoids buildup of floating point error.
    114 		for (int i = 0; i < _resetsPerCommit; ++i) {
    115 			_sums[_currentReset] = 0.0;
    116 			for (int j = 0; j < _framesN; ++j) {
    117 				_sums[_currentReset] += _frames[j*_size + _currentReset];
    118 			}
    119 			_currentReset = (_currentReset + 1) % _size;
    120 		}
    121 
    122 		_currentFrame = (_currentFrame + 1) % _framesN;
    123 	}
    124 
    125 	const T* getAverages() {
    126 		return _averages;
    127 	}
    128 };
    129 
    130 template<typename T>
    131 struct HistoryBuffer {
    132 	int _size, _i;
    133 	T* _buf;
    134 
    135 	HistoryBuffer(int size, T initialValue)
    136 	: _size(size)
    137 	, _i(0)
    138 	{
    139 		assert(size > 0);
    140 		_buf = new T[size];
    141 		std::fill(_buf, _buf + size, initialValue);
    142 	}
    143 	~HistoryBuffer() {
    144 		delete[] _buf;
    145 	}
    146 
    147 	inline void push(T s) {
    148 		++_i;
    149 		_i %= _size;
    150 		_buf[_i] = s;
    151 	}
    152 
    153 	inline T value(int i) {
    154 		assert(i >= 0 && i < _size);
    155 		int j = _i - i;
    156 		if (j < 0) {
    157 			j += _size;
    158 		}
    159 		return _buf[j];
    160 	}
    161 };
    162 
    163 } // namespace dsp
    164 } // namespace bogaudio