giuliomoro
On the topic of std::array vs std::vector. The problem with the size needing to be known can be "fixed" by using templates. std::array has no overhead compared to c style arrays but you get all the benefits of container operations and ranged for loops so I think it's worth investigating. I recently figured out how to do this (for similar reasons as OP) and found if you're willing to deal with the added complexity of templates you can have your cake and eat it too.
for instance
template <size_t n> //non type template parameter
class Wavetable
{
public:
//constructor & destructor
private:
std::array<float,n> table_ { };
};
If you tried to use a member variable called "size" as the size parameter for the array instead of using a template it wouldn't compile.
Also, if you wanted the class to be type generic so you could use float or double or int we're already using templates so you could add another template parameter "typename T" (or whatever you name you choose) then change every instance of float within the class to T.
template <typename T, size_t n>
class Wavetable
{
public:
//constructor & destructor
private:
std::array<T,n> table_ { };
};
Then, in my main loop if I wanted to initialize a couple instance of the class with different types and sizes I would do it like so
int main()
{
Wavetable<float,44100> test_table_1;
Wavetable<double,2048> test_table_2;
Wavetable<int,10> test_table_3;
}
One last thing to demonstrate the flexibility of templates: say you wanted your class to own a function object (maybe its the function you're saving to the wavetable) that you pass to the constructor, but you don't want your class to be bound to one specific type of function object. Time for another template parameter!
template <typename Func, typename T, size_t n>
class Wavetable
{
public:
Wavetable(Func function) : function_(function) { }; //initializer list syntax
private:
Func function_;
std::array<T,n> table_ { };
};
Now, say I wanted to create a wavetable object that 'owns' the sine function. First, create a function object wrapper for cmath sine so we can treat it like an object but also call it as a function.
struct Sine
{
float operator()(float X) { return sin(x); }
};
Then in the main loop
int main()
{
Sine sinFunc; //declaring function object
float result = sinFunc(12); //how to call function object
Wavetable<Sine,float,4410> test_table(sinFunc);
}
Then, if we wanted to declare a new Wavetable object that holds a different function object it's as easy as changing the template parameter where we put "Sine" to the different object's type. Function objects as a topic are worthy of their own post - seeing how this one has turned into quite a digression I will save that for later.
Now thinking of the future - lets say you make your std::array based wavetable class and its just as badass and efficient as you imagined. Then you could make another class that owns a std::array of Wavetable objects whose outputs you can switch / interpolate between very easily. Maybe you could even use the same Wavetable class to hold an array of type Wavetable? Might break C++ lol but its worth a shot.
Hopefully this helps clear up some of your questions @RyanGo . I found myself asking those same exact questions just a few months ago and I believe that templates are the key to solving your problems.
Best of luck to you!