diff --git a/delay/buffer.hpp b/delay/buffer.hpp index 2d59aba..4396462 100644 --- a/delay/buffer.hpp +++ b/delay/buffer.hpp @@ -39,21 +39,53 @@ class Buffer { uint m_index; uint m_mask; + int m_offset; + uint m_increment; size_t m_capacity; - vector m_buffer; + size_t m_allocated_capacity; + + std::vector m_buffer; public: Buffer(size_t capacity) : m_index(0) , m_mask(0) + , m_offset(0) + , m_increment(1) , m_capacity(0) + , m_buffer() + , m_allocated_capacity(1) { resize(capacity); + m_buffer.assign(m_allocated_capacity, T()); + } + + Buffer(const Buffer &buffer, int offset=0, uint increment=1) + : m_buffer(buffer.m_buffer) + , m_index(buffer.m_index) + , m_mask(buffer.m_mask) + , m_offset(offset) + , m_increment(increment) + , m_capacity(buffer.m_capacity) + , m_allocated_capacity(buffer.m_allocated_capacity) + { + } + + Buffer(const std::vector &v) + : m_index(0) + , m_mask(0) + , m_offset(0) + , m_increment(1) + , m_capacity(v.capacity()) + , m_buffer(v) + , m_allocated_capacity(1) + { + resize(v.capacity()); } size_t capacity() { - return m_buffer.capacity(); + return m_capacity/m_increment; } void reset() @@ -61,16 +93,16 @@ class Buffer m_index = 0; } - void resize(int capacity, T value=T()) + void resize(uint capacity) { - m_capacity = 1; - while (m_capacity < capacity) + m_allocated_capacity = 1; + while (m_allocated_capacity < capacity) { - m_capacity *= 2; + m_allocated_capacity *= 2; } - m_buffer.assign(m_capacity, value); - m_mask = unsigned(m_capacity - 1); + m_capacity = capacity; + m_mask = unsigned(m_allocated_capacity - 1); m_index = 0; } @@ -112,41 +144,26 @@ class Buffer return *this; } - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - iterator begin() + bool operator == (const Buffer &other) const { - return m_buffer.begin(); + return m_buffer == other.m_buffer; } - iterator end() - { - return m_buffer.end(); - } - - const_iterator begin() const - { - return m_buffer.begin(); - } - - const_iterator end() const - { - return m_buffer.end(); - } protected: - virtual T & at(int offset) + + T& at(int offset) { - int i = (m_index + (uint)offset) & m_mask; + int i = (m_offset + m_index + (uint)offset*m_increment) & m_mask; return m_buffer[i]; } - virtual const T & at(int offset) const + T const & at(int offset) const { - return at(offset); + int i = (m_offset + m_index + (uint)offset*m_increment) & m_mask; + return m_buffer[i]; } - }; } diff --git a/delay/buffer_multi.hpp b/delay/buffer_multi.hpp index 2c3b6df..8e1275d 100644 --- a/delay/buffer_multi.hpp +++ b/delay/buffer_multi.hpp @@ -31,19 +31,30 @@ namespace dsp { template -class BufferMulti : public Buffer +class BufferMulti { + Buffer m_buffer; size_t m_numChannels; size_t m_capacity; public: BufferMulti(size_t numChannels, size_t capacity) - : Buffer(capacity*numChannels) + : m_buffer(capacity*numChannels) , m_numChannels(numChannels) , m_capacity(capacity) { } + Buffer & buffer() + { + return m_buffer; + } + + void reset() + { + m_buffer.reset(); + } + size_t capacity() { return m_capacity; @@ -54,18 +65,70 @@ class BufferMulti : public Buffer return m_numChannels; } - using Buffer::at; - T & at(uint channel, int offset) + Buffer operator[](uint channel) { - return at(int(m_capacity*channel + offset)); + return at(channel); } - const T & at(uint channel, int offset) const + const Buffer operator [](uint channel) const { - return at(channel, offset); + return at(channel); + } + + BufferMulti & operator ++() + { + ++m_buffer; + return *this; + } + + BufferMulti & operator +=(int i) + { + m_buffer += i; + return *this; + } + + BufferMulti & operator --() + { + --m_buffer; + return *this; + } + + BufferMulti & operator -=(int i) + { + m_buffer -= i; + return *this; + } + + BufferMulti & operator =(T value) + { + for (uint c=0; c < m_numChannels; c++) + { + this->at(c)[0] = value; + } + return *this; + } + + dsp::Buffer quer(int offset=0) + { + return Buffer(m_buffer, offset, m_capacity); + } + + const dsp::Buffer quer(int offset=0) const + { + return Buffer(m_buffer, offset, m_capacity); } protected: + Buffer at(uint channel) + { + return Buffer(m_buffer, channel*m_capacity); + } + + const Buffer at(uint channel) const + { + return Buffer(m_buffer, channel*m_capacity); + } + }; } diff --git a/delay/buffer_multi_view.hpp b/delay/buffer_multi_view.hpp new file mode 100644 index 0000000..c43d702 --- /dev/null +++ b/delay/buffer_multi_view.hpp @@ -0,0 +1,89 @@ +/* + * jayDSP, A cross-platform Digital Signal Processing library written in modern C++. + * Copyright (C) 2025 Jens Ahrensfeld, All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + * File: buffer_view.hpp + * Author Jens Ahrensfeld on 26.10.2025. + */ + +#ifndef DSP_BUFFER_VIEW_H +#define DSP_BUFFER_VIEW_H + +#include "buffer_multi.hpp" + + +namespace dsp { + +template +class BufferMultiView +{ + BufferMulti &m_buffer; + uint m_offset; + uint m_channel; + + public: + BufferMultiView(BufferMulti &buffer, int offset, int channel) + : m_buffer(buffer) + , m_offset(offset) + , m_channel(channel) + { + } + + T & operator[](int offset) + { + return m_buffer.at(m_channel, m_offset + offset); + } + + const T & operator[](int offset) const + { + return m_buffer[m_offset + offset]; + } + + size_t size() + { + return m_buffer.size(); + } + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + iterator begin() + { + return m_buffer.begin(); + } + + iterator end() + { + return m_buffer.end(); + } + + const_iterator begin() const + { + return m_buffer.begin(); + } + + const_iterator end() const + { + return m_buffer.end(); + } + +}; +} + +#endif // DSP_BUFFER_VIEW_H diff --git a/delay/tests/test_buffer.cpp b/delay/tests/test_buffer.cpp index 3c7bb55..9de7709 100644 --- a/delay/tests/test_buffer.cpp +++ b/delay/tests/test_buffer.cpp @@ -1,23 +1,11 @@ +#include "test_common.hpp" + #include #include #include #include -template -void print(dsp::BufferView &v, size_t size) -{ - for(const auto&i : v) - { - std::cout << i << std::endl; - } - std::cout << "----------------------------------------------" << std::endl; - for (int i=0; i < size; i++) - { - std::cout << v[i] << std::endl; - } - -} int test_buffer_1() { @@ -42,16 +30,92 @@ int test_buffer_1() auto v1 = dsp::BufferView(buffer, 0); auto v2 = dsp::BufferView(buffer, -5); - for(const auto&i : buffer) + for(int i=0; i < buffer.capacity(); i++) { - std::cout << i+100 << std::endl; + std::cout << buffer[i] << std::endl; } return 0; } +int test_buffer_2() +{ + std::cout << "----------------------------------------------" << std::endl; + std::cout << "Start test_buffer_2" << std::endl; + std::cout << "----------------------------------------------" << std::endl; + + dsp::Buffer buffer(10); + printf("Buffer capacity = %zu\n", buffer.capacity()); + for (int i=0; i < 10; i++) + { + buffer[i] = i+1; + } + buffer += 5; + + for (int i=-5; i < 5; i++) + { + int v = buffer[i]; + printf("i=%d: v=%d\n", i, v); + } + + buffer.reset(); + const auto v1 = dsp::Buffer(buffer, -1); + const auto v2 = dsp::Buffer(buffer, -5); + + for(int i=0; i < buffer.capacity(); i++) + { + std::cout << buffer[i] << std::endl; + } + + std::cout << "print(buffer, 10);" << std::endl; + print(buffer, 10); + std::cout << "print(v1, 10);" << std::endl; + print(v1, 10); + std::cout << "print(v2, 10);" << std::endl; + print(v2, 10); + + + return 0; +} + +int test_buffer_3() +{ + std::cout << "----------------------------------------------" << std::endl; + std::cout << "Start test_buffer_3" << std::endl; + std::cout << "----------------------------------------------" << std::endl; + + dsp::Buffer buffer(50); + printf("Buffer capacity = %zu\n", buffer.capacity()); + for (int i=0; i < buffer.capacity(); i++) + { + buffer[i] = i; + } + + buffer.reset(); + + uint incr = 5; + for (int offset=0; offset < 5; offset++) + { + std::cout << "----------------------------------------------" << std::endl; + std::cout << "offset = " << offset << std::endl; + std::cout << "----------------------------------------------" << std::endl; + auto v1 = dsp::Buffer(buffer, offset, incr); + for(int i=0; i < v1.capacity()/incr; i++) + { + std::cout << v1[i] << std::endl; + } + + } + + + + return 0; +} + int test_buffer() { test_buffer_1(); + test_buffer_2(); + test_buffer_3(); return 0; } \ No newline at end of file diff --git a/delay/tests/test_buffer_multi.cpp b/delay/tests/test_buffer_multi.cpp index fe81f02..5e74414 100644 --- a/delay/tests/test_buffer_multi.cpp +++ b/delay/tests/test_buffer_multi.cpp @@ -1,7 +1,11 @@ +#include "dsp_types.hpp" +#include "test_common.hpp" #include +#include #include #include +#include int test_buffer_multi_1() @@ -17,26 +21,26 @@ int test_buffer_multi_1() { for (int c=0; c < 5; c++) { - buffer.at(c, 0) = i+1; + buffer[c][0] = i+1; } buffer += 1; } - buffer.reset(); + for (int c=0; c < 5; c++) + { + buffer[c].reset(); + } + for (int i=0; i < 10; i++) { for (int c=0; c < 5; c++) { - int v = buffer.at(c, i); + int v = buffer[c][i]; printf("c=%d: i=%d: v=%d\n", c, i, v); } } - for(const auto&i : buffer) - { - } - return 0; } @@ -53,8 +57,8 @@ int test_buffer_multi_2() { for (int c=0; c < 5; c++) { - buffer.at(c, 0) = i+1; - int v = buffer.at(c, -2); + buffer[c][0] = i+1; + int v = buffer[c][-2]; printf("c=%d: i=%d: v=%d\n", c, i, v); } buffer += 1; @@ -88,20 +92,89 @@ int test_buffer_multi_3() { for (int c=0; c < 5; c++) { - buffer.at(c, 0) = i+1; - int v = buffer.at(c, -c); + buffer[c][0] = i+1; + int v = buffer[c][-c]; printf("c=%d: i=%d: v=%d\n", c, i, v); } + } + return 0; +} + +int test_buffer_multi_4() +{ + std::cout << "----------------------------------------------" << std::endl; + std::cout << "Start test_buffer_multi_4()" << std::endl; + std::cout << "----------------------------------------------" << std::endl; + + dsp::BufferMultibuffer(5, 10); + printf("Buffer capacity = %zu\n", buffer.capacity()); + + dsp::Buffer *mbv[5]; + for (int c=0; c < 5; c++) + { + mbv[c] = new dsp::Buffer(buffer[c], -c); + } + + for (int i=0; i < 10; i++) + { + for (int c=0; c < 5; c++) + { + buffer[c][0] = i+1; + } buffer += 1; } + + buffer.reset(); + for (int c=0; c < 5; c++) + { + for (int i=0; i < 10; i++) + { + print(*mbv[c], 10); + } + } + return 0; +} + +int test_buffer_multi_5() +{ + std::cout << "----------------------------------------------" << std::endl; + std::cout << "Start test_buffer_multi_5()" << std::endl; + std::cout << "----------------------------------------------" << std::endl; + + dsp::BufferMultibuffer(5, 10); + printf("Buffer capacity = %zu\n", buffer.capacity()); + + for (int i=0; i < 10; i++) + { + buffer = i+1; + buffer += 1; + } + + buffer.reset(); + print(buffer.buffer(), buffer.buffer().capacity()); + + + for (int i=0; i < 10; i++) + { + print(buffer.quer(i), buffer.quer().capacity()); +// if (buffer.quer(0) == dsp::Buffer(std::vector{1,1,1,1,1})) +// { +// std::cout << "Okay" << std::endl; +// } + } + return 0; } int test_buffer_multi() { - test_buffer_multi_1(); - test_buffer_multi_2(); - test_buffer_multi_3(); + std::vector v { 34,23 }; + const std::vector v2 { 34,23 }; +// test_buffer_multi_1(); +// test_buffer_multi_2(); +// test_buffer_multi_3(); + test_buffer_multi_4(); + test_buffer_multi_5(); return 0; } diff --git a/delay/tests/test_common.hpp b/delay/tests/test_common.hpp new file mode 100644 index 0000000..d0085bb --- /dev/null +++ b/delay/tests/test_common.hpp @@ -0,0 +1,28 @@ +#include +#include +#include + +#include + +#ifndef TEST_COMMON_H +#define TEST_COMMON_H + +template +void print(const dsp::Buffer &v, size_t size, std::string name=std::string("")) +{ + std::cout << "----------------------------------------------" << std::endl; + std::cout << "-" << name << std::endl; + std::cout << "----------------------------------------------" << std::endl; + for(int i=0; i < size; i++) + { + std::cout << v[i] << std::endl; + } +} + +template +bool check(const dsp::Buffer &target, const dsp::Buffer &actual) +{ + assert(target == actual); +} + +#endif \ No newline at end of file diff --git a/delay/tests/test_main.cpp b/delay/tests/test_main.cpp index 36dd5b7..f39f7f8 100644 --- a/delay/tests/test_main.cpp +++ b/delay/tests/test_main.cpp @@ -4,7 +4,7 @@ extern void test_buffer_multi(); int main() { test_buffer(); - test_buffer_multi(); +// test_buffer_multi(); return 0; } \ No newline at end of file