1

I have a simple class

#ifndef _VOICE
#define _VOICE
#include "maximilian.h"

class voice{
public:
    voice(int waveType);
    void setNote(double pitch,double amplitude);
    void triggerNote();
    void releaseNote();
    double getOutput();
    bool getState();
private:
    maxiOsc op;
    convert mtof;
    double amp;
    double freq;
    double out;
    int type;
    bool state;
};

#endif // _VOICE

#include "voice.h"

voice::voice(int waveType){
    type=waveType;
    state=false;
    out=0;
}

void voice::setNote(double pitch,double amplitude){
    freq=pitch;
    amp=amplitude;
}

void voice::triggerNote(){
    if(type==1)
        out=op.sinewave(mtof.mtof(freq))*amp;
    if(type==2)
        out=op.triangle(mtof.mtof(freq))*amp;
    if(type==3)
        out=op.saw(mtof.mtof(freq))*amp;
    if(type==4)
        out=op.square(mtof.mtof(freq))*amp;
    state=true;
}

void voice::releaseNote(){
    out=0;
    state=false;
}

bool voice::getState(){
    return state;
}

double voice::getOutput(){
    return out;
}

I then store these voices in a vector

I wish to find a more effective way to acces the output sum of all objects within the vector

it looks something like this:

double PreMaster;
        PreMaster=voices[0].getOutput()+voices[1].getOutput()+voices[2].getOutput()+voices[3].getOutput()....(n-object)...;

(in my program it goes to 34)

(for) does not work since I need to output the value simultaneously in each objects...

there should be a way inside the class to have a global function that will return the output sum of each created objects within one function call...

I am a beginner at oop so please pardon me if solution seems obvious. And thanks in advance if you can point me in a useful direction.

EDIT:

I have a callback that gets called at sampling rate (44100hz).

I have a vector of voice object (they output simple synth waveforms) to form a sounding chord I need to sum the output of each voice "simultaneously".

I then feed the sum to my soundcard every sample at sampling rate frequency.

void testApp::audioOut (float * output, int bufferSize, int nChannels){

     for (int i = 0; i < bufferSize; i++){

         for(int j=0;j<voices.size();j++){
            if(keys[j]==true){
                voices[j].triggerNote();
            }
            else if(keys[j]==false)
                voices[j].releaseNote();
         }

        PreMaster=voices[0].getOutput()+voices[1].getOutput()+voices[2].getOutput()+voices[3].getOutput()
                          +voices[4].getOutput()+voices[5].getOutput()+voices[6].getOutput()+voices[7].getOutput()
                          +voices[8].getOutput()+voices[9].getOutput()+voices[10].getOutput()+voices[11].getOutput()
                          +voices[12].getOutput()+voices[13].getOutput()+voices[14].getOutput()+voices[15].getOutput()
                          +voices[16].getOutput()+voices[17].getOutput()+voices[18].getOutput()+voices[19].getOutput()
                          +voices[20].getOutput()+voices[21].getOutput()+voices[22].getOutput()+voices[23].getOutput()
                          +voices[24].getOutput()+voices[25].getOutput()+voices[26].getOutput()+voices[27].getOutput()
                          +voices[28].getOutput()+voices[29].getOutput()+voices[30].getOutput()+voices[31].getOutput()
                          +voices[32].getOutput()+voices[33].getOutput();

        MasterOut.stereo(PreMaster, outputs, 0.5);

        lAudioOut[i] = output[i*nChannels    ] = outputs[0]; /* You may end up with lots of outputs. add them here */
        rAudioOut[i] = output[i*nChannels + 1] = outputs[1];
        }
}

hope this clarify a bit...

Yeah I forgot about += so I tested it and it stop my program form outputing sounds.when I do it with my ugly method it works though...

  • Take a look at this: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – chris Sep 05 '12 at 20:41
  • 3
    'for does not work because...' I don't understand this comment, what's wrong with `double PreMaster = 0.0; for (int i = 0; i < 34; ++i) PreMaster += voices[i].getOutput();`? You say it doesn't work because you 'need to output the value simultaneously', please explain what you mean. – john Sep 05 '12 at 20:44
  • possible duplicate of [template function with macro - accumulate on vector](http://stackoverflow.com/questions/12287768/template-function-with-macro-accumulate-on-vector) – Bo Persson Sep 05 '12 at 20:56
  • @BoPersson I think this differs from the possible duplicate because a function call to each element of the container is required. I couldn't come up with a nice way to do that with `std::accumulate` (but I am quite tired). – juanchopanza Sep 05 '12 at 21:01
  • You can provide a function or functor as the last parameter to `std::accumulate`. It doesn't have to do just `x + y`, but could do `x + y.get_soemthing()`. – Bo Persson Sep 05 '12 at 21:06
  • @BoPersson but doesn't the initial value have to be of the type of the contained elements? – juanchopanza Sep 05 '12 at 21:12
  • Not really. It is a separate template parameter, also giving the result type. The input is a pair of iterators. Their value_type must (somehow) match the result and the operator, but it's pretty flexible. – Bo Persson Sep 05 '12 at 21:16
  • @BoPersson Thanks, of course you're right. I was really asleep. I reverted to a solution using `accumulate` instead of `for_each`. – juanchopanza Sep 06 '12 at 05:42

2 Answers2

3

You can perform a simple loop, since there is no reason to believe that a for does not work, given your code example:

double sum = 0;
for (const auto& v : voices) {
  sum += v.getOutput();
}

Another option is to use std::accumulate and a suitable functor:

// function to sum voice's getOutput() to get running total
double addOutput(double sum, const voice& v) { return sum + voice.getOutput(); }
....
double sum = std::accumulate(voices.begin(), voices.end(), 0.0, addOutput);
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

An example:

int sum = 0;
for(std::vector<voice>::iterator i = voices.begin(); i != voices.end(); i++)
    sum += i->getOutput();
perreal
  • 94,503
  • 21
  • 155
  • 181