Thank you all for the suggestions! I’m running valgrind right now but it sure is slow. I’ll follow up with those results.
@stoermelder My widget doesn’t define a destructor, so it should just have the empty one inherited from ModuleWidget
right?
@chaircrusher @synthi There’s only one place where I’ve used dynamic memory, and it isn’t shared between instances. It’s in the following class. Have I screwed up the memory management?
template <typename T>
class RamMemory
{
private:
T *buffer_;
uint32_t buffer_size_;
uint32_t head_;
public:
RamMemory()
{
buffer_ = NULL;
}
~RamMemory()
{
delete[] buffer_;
}
void Init(uint32_t size, uint32_t initial_head_position = 0)
{
delete[] buffer_;
buffer_ = new T[size];
buffer_size_ = size;
head_ = initial_head_position;
memset(buffer_, 0, buffer_size_ * sizeof(T));
}
void Write(T *source, uint32_t length)
{
if (head_ + length <= buffer_size_)
{
memcpy(&buffer_[head_], source, length * sizeof(T));
head_ += length;
head_ %= buffer_size_;
}
else
{
uint32_t length_a = buffer_size_ - head_;
uint32_t length_b = length - length_a;
memcpy(&buffer_[head_], source, length_a * sizeof(T));
memcpy(buffer_, &source[length_a], length_b * sizeof(T));
head_ = length_b;
}
}
void Read(T *dest, uint32_t delay, uint32_t length)
{
uint32_t offset = head_;
if (head_ < delay)
{
offset += buffer_size_;
}
offset -= delay;
if (offset + length <= buffer_size_)
{
memcpy(dest, &buffer_[offset], length * sizeof(T));
}
else
{
uint32_t length_a = buffer_size_ - offset;
uint32_t length_b = length - length_a;
memcpy(dest, &buffer_[offset], length_a * sizeof(T));
memcpy(&dest[length_a], buffer_, length_b * sizeof(T));
}
}
};