1

When trying to initialize or use my fields in the cpp file, I receive a compiler error that the "identifier is undefined" when I have defined them all in the header file.

SynthVoice.H

#pragma once
#include <JuceHeader.h>
#include "SynthSound.h"


class SynthVoice : public juce::SynthesiserVoice
{   
    public:

    bool canPlaySound(juce::SynthesiserSound* sound) override;

    void setPitchBend(int pitchWheelPos);

    float pitchBendCents();

    static double noteHz(int midiNoteNumber, double centsOffset);

    void getOscType(float* selection);

    void getOsc2Type(float* selection);
   
    double setEnvelope();

    void getWillsParams(float* mGain, float* blend, float* pbup, float* pbdn);

    void getFilterParams(float* filterType, float* filterCutoff, float* filterRes);


    void startNote(int midiNoteNumber, float velocity, juce::SynthesiserSound* sound, int currentPitchWheelPosition) override;

    void stopNote(float velocity, bool allowTailOff) override;

    void controllerMoved(int controllerNumber, int newControllerValue) override;

    void prepareToPlay(double sampleRate, int samplesPerBlock, int outputChannels);

    void renderNextBlock(juce::AudioBuffer <float>& outputBuffer, int startSample, int numSamples);


private:
    double level;
    double frequency;
    int theWave, theWave2;
    float masterGain;
    float osc2blend;
    int noteNumber;
    float pitchBend = 0.0f;
    float pitchBendUpSemitones = 2.0f;
    float pitchBendDownSemitones = 2.0f;
    int filterChoice;
    float cutoff;
    float resonance;
    bool isPrepared{ false };
};

SynthVoice.cpp

#pragma once
#include "SynthVoice.h"
class SynthVoice : public juce::SynthesiserVoice
{
public:

    bool SynthVoice::canPlaySound(juce::SynthesiserSound* sound) override
    {
        return dynamic_cast <SynthSound*>(sound) != nullptr;
    }

    void SynthVoice::setPitchBend(int pitchWheelPos)
    {
        if (pitchWheelPos > 8192)
        {
            // shifting up
            pitchBend = float(pitchWheelPos - 8192) / (16383 - 8192);
        }
        else
        {
            // shifting down
            pitchBend = float(8192 - pitchWheelPos) / -8192;    // negative number
        }
    }

    float SynthVoice::pitchBendCents()
    {
        if (pitchBend >= 0.0f)
        {
            // shifting up
            return pitchBend * pitchBendUpSemitones * 100;
        }
        else
        {
            // shifting down
            return pitchBend * pitchBendDownSemitones * 100;
        }
    }

    static double SynthVoice::noteHz(int midiNoteNumber, double centsOffset)
    {
        double hertz = juce::MidiMessage::getMidiNoteInHertz(midiNoteNumber);
        hertz *= std::pow(2.0, centsOffset / 1200);
        return hertz;
    }

    //=======================================================

    void SynthVoice::getOscType(float* selection)
    {
        theWave = *selection;

    }

    void SynthVoice::getOsc2Type(float* selection)
    {

        theWave2 = *selection;
    }
    //=======================================================

  

   
    double SynthVoice::setEnvelope()
    {
        return env1.adsr(setOscType(), env1.trigger);
    }

    //=======================================================

    void SynthVoice::getWillsParams(float* mGain, float* blend, float* pbup, float* pbdn)
    {
        masterGain = *mGain;
        osc2blend = *blend;
        pitchBendUpSemitones = *pbup;
        pitchBendDownSemitones = *pbdn;
    }

    void SynthVoice::getFilterParams(float* filterType, float* filterCutoff, float* filterRes)
    {
        filterChoice = *filterType;
        cutoff = *filterCutoff;
        resonance = *filterRes;
    }

    //=======================================================

    void SynthVoice::startNote(int midiNoteNumber, float velocity, juce::SynthesiserSound* sound, int currentPitchWheelPosition) override
    {
        noteNumber = midiNoteNumber;
        env1.trigger = 1;
        setPitchBend(currentPitchWheelPosition);
        frequency = noteHz(noteNumber, pitchBendCents());
        level = velocity;
    }

    //=======================================================

    void SynthVoice::stopNote(float velocity, bool allowTailOff) override
    {
        env1.trigger = 0;
        allowTailOff = true;

        if (velocity == 0)
            clearCurrentNote();
    }

    //=======================================================

    void SynthVoice::pitchWheelMoved(int newPitchWheelValue) override
    {
        setPitchBend(newPitchWheelValue);
        SynthVoice::frequency = noteHz(noteNumber, pitchBendCents());
    }

    //=======================================================

    void SynthVoice::controllerMoved(int controllerNumber, int newControllerValue) override
    {

    }

    //=======================================================
    void SynthVoice::prepareToPlay(double sampleRate, int samplesPerBlock, int outputChannels)
    {
        isPrepared = true;
    }

    //=======================================================

    void SynthVoice::renderNextBlock(juce::AudioBuffer <float>& outputBuffer, int startSample, int numSamples)
    {
        for (int sample = 0; sample < numSamples; ++sample)
        {
            for (int channel = 0; channel < outputBuffer.getNumChannels(); ++channel)
            {
                outputBuffer.addSample(channel, startSample, setEnvelope() * masterGain);
            }
            ++startSample;
        }
    }


};

I'm getting the red underline on ALL the private fields in the cpp file before I attempt to build it. I'm not exactly sure why. Originally I thought it was because I didn't have a constructor but this isn't the case for the instructor I'm watching.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
tyHos
  • 21
  • 2

1 Answers1

1

You defined the class SynthVoice in the header SynthVoice.H

class SynthVoice : public juce::SynthesiserVoice
{
    //...
};

and then redefined it in the file SynthVoice.cpp with member function definitions

class SynthVoice : public juce::SynthesiserVoice
{
    //...
};

If you want to define member functions declared in the class defined in the header then what you need is to write for example

bool SynthVoice::canPlaySound(juce::SynthesiserSound* sound)
{
    return dynamic_cast <SynthSound*>(sound) != nullptr;
}

outside the class definition.

Here is a simple program that demonstrates how member functions are defined outside a class where they are declared.

#include <iostream>

class A
{
private:
    int x;
    
public:
    A( int );
    const int & get_x() const ;
    void set_x( int );
};

A::A( int x ) : x( x ) {}

const int & A::get_x() const { return x; }

void A::set_x( int x ) { A::x = x; }

int main() 
{
    A a( 10 );
    
    std::cout << a.get_x() << '\n';
    
    return 0;
}

The program output is

10
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Ah I see it's been a minute since I've coded in c++ so I'm a little hazy on syntax. Thank you for your help! – tyHos May 21 '21 at 18:04