- added mix
- redesigned multi buffer
This commit is contained in:
+35
-4
@@ -49,7 +49,7 @@ class Buffer
|
|||||||
std::vector<T> &m_buffer;
|
std::vector<T> &m_buffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer(size_t capacity)
|
Buffer(size_t capacity=1)
|
||||||
: m_index(0)
|
: m_index(0)
|
||||||
, m_mask(0)
|
, m_mask(0)
|
||||||
, m_offset(0)
|
, m_offset(0)
|
||||||
@@ -59,7 +59,6 @@ class Buffer
|
|||||||
, m_allocated_capacity(1)
|
, m_allocated_capacity(1)
|
||||||
{
|
{
|
||||||
resize(capacity);
|
resize(capacity);
|
||||||
m_buffer.assign(m_allocated_capacity, T());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer(const Buffer<T> &buffer, int offset=0, uint increment=1)
|
Buffer(const Buffer<T> &buffer, int offset=0, uint increment=1)
|
||||||
@@ -82,7 +81,7 @@ class Buffer
|
|||||||
, m_buffer(*new std::vector<T>(v))
|
, m_buffer(*new std::vector<T>(v))
|
||||||
, m_allocated_capacity(1)
|
, m_allocated_capacity(1)
|
||||||
{
|
{
|
||||||
resize(v.size());
|
resize(v.size(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t capacity() const
|
size_t capacity() const
|
||||||
@@ -95,13 +94,18 @@ class Buffer
|
|||||||
m_index = 0;
|
m_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(uint capacity)
|
void resize(uint capacity, bool doAssign=true)
|
||||||
{
|
{
|
||||||
m_allocated_capacity = 1;
|
m_allocated_capacity = 1;
|
||||||
while (m_allocated_capacity < capacity)
|
while (m_allocated_capacity < capacity)
|
||||||
{
|
{
|
||||||
m_allocated_capacity *= 2;
|
m_allocated_capacity *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doAssign)
|
||||||
|
{
|
||||||
|
m_buffer.assign(m_allocated_capacity, T());
|
||||||
|
}
|
||||||
|
|
||||||
m_capacity = capacity;
|
m_capacity = capacity;
|
||||||
m_mask = unsigned(m_allocated_capacity - 1);
|
m_mask = unsigned(m_allocated_capacity - 1);
|
||||||
@@ -163,6 +167,33 @@ class Buffer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer& operator = (const std::initializer_list<T> &v)
|
||||||
|
{
|
||||||
|
if (v.size() > m_allocated_capacity)
|
||||||
|
{
|
||||||
|
resize(v.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for (auto v_: v)
|
||||||
|
{
|
||||||
|
(*this)[i++] = v_;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer& operator = (const Buffer<T> &other)
|
||||||
|
{
|
||||||
|
m_buffer = other.m_buffer;
|
||||||
|
m_index = other.m_index;
|
||||||
|
m_mask = other.m_mask;
|
||||||
|
m_offset = other.m_offset;
|
||||||
|
m_increment = other.m_increment;
|
||||||
|
m_capacity = other.m_capacity;
|
||||||
|
m_allocated_capacity = other.m_allocated_capacity;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
+45
-15
@@ -33,16 +33,20 @@ namespace dsp {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class BufferMulti
|
class BufferMulti
|
||||||
{
|
{
|
||||||
Buffer<T> m_buffer;
|
Buffer<T> *m_buffer;
|
||||||
size_t m_numChannels;
|
uint m_numChannels;
|
||||||
size_t m_capacity;
|
size_t m_capacity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BufferMulti(size_t numChannels, size_t capacity)
|
BufferMulti(size_t numChannels, size_t capacity)
|
||||||
: m_buffer(capacity*numChannels)
|
: m_buffer(new Buffer<T>[numChannels])
|
||||||
, m_numChannels(numChannels)
|
, m_numChannels(numChannels)
|
||||||
, m_capacity(capacity)
|
, m_capacity(capacity)
|
||||||
{
|
{
|
||||||
|
for (int c=0; c < numChannels; c++)
|
||||||
|
{
|
||||||
|
m_buffer[c].resize(capacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer<T> & buffer()
|
Buffer<T> & buffer()
|
||||||
@@ -52,7 +56,10 @@ class BufferMulti
|
|||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_buffer.reset();
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
m_buffer[c].reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t capacity()
|
size_t capacity()
|
||||||
@@ -77,58 +84,81 @@ class BufferMulti
|
|||||||
|
|
||||||
BufferMulti & operator ++()
|
BufferMulti & operator ++()
|
||||||
{
|
{
|
||||||
++m_buffer;
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
++(m_buffer[c]);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMulti & operator +=(int i)
|
BufferMulti & operator +=(int i)
|
||||||
{
|
{
|
||||||
m_buffer += i;
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
m_buffer[c] += i;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMulti & operator --()
|
BufferMulti & operator --()
|
||||||
{
|
{
|
||||||
--m_buffer;
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
--(m_buffer[c]);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMulti & operator -=(int i)
|
BufferMulti & operator -=(int i)
|
||||||
{
|
{
|
||||||
m_buffer -= i;
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
m_buffer[c] -= i;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMulti & operator =(T value)
|
BufferMulti & operator = (const T& value)
|
||||||
{
|
{
|
||||||
for (uint c=0; c < m_numChannels; c++)
|
for (uint c=0; c < m_numChannels; c++)
|
||||||
{
|
{
|
||||||
this->at(c)[0] = value;
|
m_buffer[c][0] = value;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsp::Buffer<T> quer(int offset=0)
|
dsp::Buffer<T> quer(int offset=0)
|
||||||
{
|
{
|
||||||
return Buffer<T>(m_buffer, offset, m_capacity);
|
Buffer<T> querBuffer(numChannels());
|
||||||
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
querBuffer[c] = m_buffer[c][offset];
|
||||||
|
}
|
||||||
|
return querBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsp::Buffer<T> quer(int offset=0) const
|
const dsp::Buffer<T> quer(int offset=0) const
|
||||||
{
|
{
|
||||||
return Buffer<T>(m_buffer, offset, m_capacity);
|
Buffer<T> querBuffer(numChannels());
|
||||||
|
for (int c=0; c < m_numChannels; c++)
|
||||||
|
{
|
||||||
|
querBuffer[c] = m_buffer[c][offset];
|
||||||
|
}
|
||||||
|
return querBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
Buffer<T> at(uint channel)
|
Buffer<T> at(uint channel)
|
||||||
{
|
{
|
||||||
return Buffer<T>(m_buffer, channel*m_capacity);
|
return m_buffer[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Buffer<T> at(uint channel) const
|
const Buffer<T> at(uint channel) const
|
||||||
{
|
{
|
||||||
return Buffer<T>(m_buffer, channel*m_capacity);
|
return m_buffer[channel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ CXXFLAGS += -std=c++20
|
|||||||
|
|
||||||
INCLUDES += -I $(realpath .) -I $(realpath ../../)
|
INCLUDES += -I $(realpath .) -I $(realpath ../../)
|
||||||
|
|
||||||
CXX_SRCS := test_main.cpp test_buffer.cpp test_buffer_multi.cpp
|
CXX_SRCS := test_main.cpp test_buffer.cpp test_buffer_multi.cpp test_mix.cpp
|
||||||
|
|
||||||
LIBS := -lstdc++
|
LIBS := -lstdc++
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ template<typename T>
|
|||||||
void print(const dsp::Buffer<T> &v, size_t size, std::string name=std::string(""))
|
void print(const dsp::Buffer<T> &v, size_t size, std::string name=std::string(""))
|
||||||
{
|
{
|
||||||
std::cout << "----------------------------------------------" << std::endl;
|
std::cout << "----------------------------------------------" << std::endl;
|
||||||
std::cout << "- " << name << std::endl;
|
std::cout << "- " << name << ", " << size << std::endl;
|
||||||
std::cout << "----------------------------------------------" << std::endl;
|
|
||||||
for(int i=0; i < size; i++)
|
for(int i=0; i < size; i++)
|
||||||
{
|
{
|
||||||
std::cout << v[i] << std::endl;
|
std::cout << v[i] << " ";
|
||||||
}
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
extern void test_buffer();
|
extern void test_buffer();
|
||||||
extern void test_buffer_multi();
|
extern void test_buffer_multi();
|
||||||
|
extern void test_mix();
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test_buffer();
|
test_buffer();
|
||||||
// test_buffer_multi();
|
test_buffer_multi();
|
||||||
|
test_mix();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#include "delay/buffer_multi.hpp"
|
||||||
|
#include "test_common.hpp"
|
||||||
|
#include <delay/buffer.hpp>
|
||||||
|
#include <mix.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
int test_mix_1()
|
||||||
|
{
|
||||||
|
std::cout << "----------------------------------------------" << std::endl;
|
||||||
|
std::cout << "Start test_mix_1::shuffle" << std::endl;
|
||||||
|
std::cout << "----------------------------------------------" << std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
dsp::Buffer<int> r_buf(5);
|
||||||
|
dsp::Buffer<int> t_buf{105, 106, 107, 108, 109};
|
||||||
|
t_buf = {105, 106, 107, 108, 109};
|
||||||
|
|
||||||
|
dsp::Buffer<int> s_spec = {1, 3, 2, 4, 0};
|
||||||
|
Shuffle<int>::outOfPlace(t_buf, r_buf, s_spec);
|
||||||
|
print(r_buf, 5, "r-buf");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dsp::BufferMulti<int> r_buf(5, 5);
|
||||||
|
dsp::BufferMulti<int> t_buf{5, 5};
|
||||||
|
t_buf[0] = {105, 106, 107, 108, 109};
|
||||||
|
t_buf[1] = {205, 206, 207, 208, 209};
|
||||||
|
t_buf[2] = {305, 306, 307, 308, 309};
|
||||||
|
t_buf[3] = {405, 406, 407, 408, 409};
|
||||||
|
t_buf[4] = {505, 506, 507, 508, 509};
|
||||||
|
print(t_buf[0], 5, "t-buf 0");
|
||||||
|
print(t_buf[1], 5, "t-buf 1");
|
||||||
|
|
||||||
|
dsp::Buffer<int> s_spec = {-1, 0, -3, 2, -4};
|
||||||
|
Shuffle<int>::outOfPlace(t_buf, r_buf, s_spec);
|
||||||
|
print(r_buf[0], 5, "r-buf 0");
|
||||||
|
print(r_buf[1], 5, "r-buf 1");
|
||||||
|
print(r_buf[2], 5, "r-buf 2");
|
||||||
|
print(r_buf[3], 5, "r-buf 3");
|
||||||
|
print(r_buf[4], 5, "r-buf 4");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_mix_2()
|
||||||
|
{
|
||||||
|
dsp::BufferMulti<int> r_buf(5, 20);
|
||||||
|
|
||||||
|
for (int i=0; i < r_buf.capacity(); i++)
|
||||||
|
{
|
||||||
|
r_buf = 100 +i ;
|
||||||
|
++r_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_buf.reset();
|
||||||
|
for (int c=0; c < r_buf.numChannels(); c++)
|
||||||
|
{
|
||||||
|
print(r_buf[c], r_buf.capacity(), "r-buf");
|
||||||
|
std::cout << "----------------------------------------------" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c=0; c < r_buf.numChannels(); c++)
|
||||||
|
{
|
||||||
|
dsp::Buffer<int> v(r_buf[c], c);
|
||||||
|
print(v, r_buf.capacity(), "v-buf");
|
||||||
|
std::cout << "----------------------------------------------" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_mix()
|
||||||
|
{
|
||||||
|
test_mix_1();
|
||||||
|
test_mix_2();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
#include "delay/buffer_multi.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#ifndef MIX_HPP
|
||||||
|
#define MIX_HPP
|
||||||
|
|
||||||
|
#include <delay/buffer.hpp>
|
||||||
|
|
||||||
|
// Use like `Householder<double, 8>::inPlace(data)` - size must be ≥ 1
|
||||||
|
template<typename Sample, int size>
|
||||||
|
class Householder
|
||||||
|
{
|
||||||
|
static constexpr Sample multiplier{-2.0/size};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void inPlace(Sample *arr)
|
||||||
|
{
|
||||||
|
double sum = 0;
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
sum += arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
sum *= multiplier;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
arr[i] += sum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use like `Hadamard<double, 8>::inPlace(data)` - size must be a power of 2
|
||||||
|
template<typename Sample, int size>
|
||||||
|
class Hadamard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline void recursiveUnscaled(Sample * data)
|
||||||
|
{
|
||||||
|
if (size <= 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
constexpr int hSize = size/2;
|
||||||
|
|
||||||
|
// Two (unscaled) Hadamards of half the size
|
||||||
|
Hadamard<Sample, hSize>::recursiveUnscaled(data);
|
||||||
|
Hadamard<Sample, hSize>::recursiveUnscaled(data + hSize);
|
||||||
|
|
||||||
|
// Combine the two halves using sum/difference
|
||||||
|
for (int i = 0; i < hSize; ++i)
|
||||||
|
{
|
||||||
|
double a = data[i];
|
||||||
|
double b = data[i + hSize];
|
||||||
|
data[i] = (a + b);
|
||||||
|
data[i + hSize] = (a - b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void inPlace(Sample * data)
|
||||||
|
{
|
||||||
|
recursiveUnscaled(data);
|
||||||
|
|
||||||
|
Sample scalingFactor = std::sqrt(1.0/size);
|
||||||
|
for (int c = 0; c < size; ++c)
|
||||||
|
{
|
||||||
|
data[c] *= scalingFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Shuffle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static inline void outOfPlace(dsp::Buffer<T> &in, dsp::Buffer<T> &out, dsp::Buffer<T> &shuffle_spec)
|
||||||
|
{
|
||||||
|
for (int c=0; c < shuffle_spec.capacity(); c++)
|
||||||
|
{
|
||||||
|
T sign = 1;
|
||||||
|
int s = (int)shuffle_spec[c];
|
||||||
|
if (s < 0)
|
||||||
|
{
|
||||||
|
sign = -1;
|
||||||
|
s *= -1;
|
||||||
|
}
|
||||||
|
if (s >= shuffle_spec.capacity())
|
||||||
|
{
|
||||||
|
s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[s] = sign * in[c];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static inline void outOfPlace(dsp::BufferMulti<T> &in, dsp::BufferMulti<T> &out, dsp::Buffer<T> &shuffle_spec)
|
||||||
|
{
|
||||||
|
for (int c=0; c < shuffle_spec.capacity(); c++)
|
||||||
|
{
|
||||||
|
T sign = 1;
|
||||||
|
int s = (int)shuffle_spec[c];
|
||||||
|
if (s < 0)
|
||||||
|
{
|
||||||
|
sign = -1;
|
||||||
|
s *= -1;
|
||||||
|
}
|
||||||
|
if (s >= shuffle_spec.capacity())
|
||||||
|
{
|
||||||
|
s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int n=0; n < in.capacity(); n++)
|
||||||
|
{
|
||||||
|
out[c][n] = sign * in[s][n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user