Using static variable in parent class as counter

Good morning, I'm still finding my way around Arduino and using classes.

I would like to have an array of oscillators/waves and a parent class that holds values that relate to all the child instances. I'm using the "static" type, it's acting as I expected and I just want to check if this is the right approach.

class parent_wave {
   public:
      static int sum;
      static void sum_waves(int s){
         sum += s;
      }
};
int parent_wave::sum = 0;

class child_wave: public parent_wave {
   public:
      void set_value(int v){
         _v = v;
         sum_waves(_v);
      };
   private:
      int _v;
};
child_wave wave[2]; 
  
void setup() {
  wave[0].set_value(10);
  wave[1].set_value(20);
}

void loop() {
}

Why a parent class? You could define your static values in the 'child_wave' class directly and they are related to all instances of your class 'child_wave'.
Or is there another reason for this 'parent_class'?

1 Like

Great! Thank you. I'm still finding my way around classes and their relationships.

I didn't realise it could work that way. Sounds like a good idea.

However do realise. If you had a container of your different child classes (an array of parent class) you wont be able to access all the child class specific variables.

But you can implenet virtual methods to get them

I've done a bit more work on my oscillator class and it's all working as I hoped
I would like to have the wavemixer() function somehow incorporated into the oscillator class. What's a good way to do this? It simply adds the Y values of the classes together.

#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI); 

class Oscillator {
   public:
      float Y = 0;
      void set_rate(int CCvalue){
        //convert MIDI controller to value between 0 and 1
        _rate = CCvalue * 0.001/1.27;
      }
      void make(){
        float Y_max = 1;
        float Y_min = -1;
        Y = constrain(Y + (_direction * _rate), Y_min, Y_max);
  
        // flip direction at min & max points
        if(Y >= Y_max || Y <= Y_min){
          _direction = _direction * -1;            
        }
      }
    private:
      float _direction = 1;
      float _rate = 0.01;
};

Oscillator oscillator[2];

void handleControlChange(byte channel, byte CCnumber, byte CCvalue)
{
  if(CCnumber == 1) oscillator[0].set_rate(CCvalue);
  if(CCnumber == 2) oscillator[1].set_rate(CCvalue);
}

float wavemixer(){
  float wave;
  oscillator[0].make();
  oscillator[1].make();
  wave = oscillator[0].Y + oscillator[1].Y;
  return constrain(wave,-1,1);
}  

void setup() {
  Serial.begin(9600);
  MIDI.setHandleControlChange(handleControlChange);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
  Serial.print(wavemixer());Serial.print("\t");     
  Serial.print(oscillator[0].Y);Serial.print("\t");     
  Serial.print(oscillator[1].Y);Serial.print("\n");     
}
  

The Y value for each oscillator does not need to be public I only did that because I didn't know how else to add them together.

Try something like this

float wavemixer( Oscillator & o ){
  make();
  o.make();
  float wave = Y + o.Y;
  return constrain(wave,-1,1);
} 

Thank you for the suggestion. Like this?

#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI); 

class Oscillator {
  public:
    void set_rate(int MIDICCvalue){
      _rate = MIDICCvalue * 0.001/1.27;
    }
    float wavemixer( Oscillator & o ){
      make();
      o.make();
      float wave = _Y + o._Y;
      return constrain(wave,-1,1);
    } 
      
  private:
    float _Y = 0;
    float _direction = 1;
    float _rate = 0.01;
    void make(){
      float Y_max = 1;
      float Y_min = -1;
      _Y = constrain(_Y + (_direction * _rate), Y_min, Y_max);
      if(_Y >= Y_max || _Y <= Y_min) _direction *= -1;
      Serial.print(_Y);Serial.print("\t");
    }
};

Oscillator oscillator[2];

void handleControlChange(byte channel, byte CCnumber, byte CCvalue)
{
  if(CCnumber == 1) oscillator[0].set_rate(CCvalue);
  if(CCnumber == 2) oscillator[1].set_rate(CCvalue);
}

void setup() {
  Serial.begin(9600);
  MIDI.setHandleControlChange(handleControlChange);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
  Serial.print(oscillator[0].wavemixer(oscillator[1]));Serial.print("\n");     
}

That works!

Although, what do I do if I want to make the oscillator array larger? For example sometimes a system might run with 5, 10 or 15 individual oscillators.

That's why I was originally thinking of the parent and child classes. With wavemixer being a function of the parent class summing up each of the individual child oscillators.

Besides set_rate, nothing else in the oscillator needs to be accessible. Just the sum output from the wavemixer.

Just a reminder, I am new to classes and oop.

Maybe something like this :

static float wavemixer( Oscillator * oscillators, size_t count )
{
  float wave = 0; // Never forget to initialize a local variable if you care about its initial value

  for ( size_t i = 0; i < count; ++i )
  {
    Oscillator & oscillator = oscillators[i];
    oscillator.make();
    wave += oscillator._Y;
  }

  return wave;
}

...

Oscillator oscillators[2];

...

Oscillator::wavemixer( oscillators, 2 );
1 Like

I think I've come to a solution using nested classes. This seems nice and neat concise. Besides sum() and set_rate() everything else is kept out of the way.

Thanks for all your help!

#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI); 

class wave{
      private:
        float _Y = 0;
        float _direction = 1;
        float _rate = 0.01;
      public:
        void set_rate(int MIDICCvalue){
          _rate = MIDICCvalue * 0.005/1.27;
        }
        float make(){
          float Y_max = 1;
          float Y_min = -1;
          _Y = constrain(_Y + (_direction * _rate), Y_min, Y_max);
          if(_Y >= Y_max || _Y <= Y_min) _direction *= -1;
          Serial.print(_Y);Serial.print("\t");
          return _Y;
        }
};

class wave_mixer {
  public:
    wave w[2];
    float sum(){
      float wave = w[0].make() + w[1].make();
      return constrain(wave,-1,1);
    } 
};

wave_mixer wm;

void handleControlChange(byte channel, byte CCnumber, byte CCvalue)
{
  if(CCnumber == 1) wm.w[0].set_rate(CCvalue);
  if(CCnumber == 2) wm.w[1].set_rate(CCvalue);
}

void setup() {
  Serial.begin(9600);
  MIDI.setHandleControlChange(handleControlChange);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
  Serial.print(wm.sum());Serial.print("\n");     
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.