findFreeVoice Hack


#1

I saw an older post briefly touch upon this, but it didn’t address my specific issue, so…

In my synth based off the Synth Demo code, I’m trying to customize the findFreeVoice function for purposes of note stealing, voice modes and unison. I tried bringing the findFreeVoice function into my Synth class, but it can’t access the private variables from SynthesiserVoice in this part of the code:

if (voice->canPlaySound (soundToPlay) && (oldest == nullptr || oldest->noteOnTime > voice->noteOnTime)) oldest = voice;

I tried adding:

as well as:

to my SynthVoice class but that didn’t fix it.

How can I get my synth subclass to be friends with SynthesiserVoice class?


#2

Rather than trying to hack yourself access to those variables, you should just implement your own algorithm independently of the way the base class does it.

It’s always a bad idea to try to use internal variables like that anyway, because if in the future I change the way the base class is implemented, it could silently break your code. That’s why they’re kept private.


#3

Makes sense.

I get what you’re saying, I’m just pretty hazy on how to do that. The relationship between my Synth class, it’s juce base, my SynthVoice class and it’s juce base, is a big mess in my head. Whenever I try to override functions from the Synthesiser and SynthesiserVoice class, I run into these private access problems. So then I add my own variables to my derived classes to use instead of the base class’s, but the overridden functions are still calling on the base class private variables, because they’re still using the “voice” object, which sometimes calls on SynthesiserVoice, and at other times SynthVoice. When I try to go even deeper and get “voice” to point to my SynthVoice functions/variables instead of SynthesiserVoice, I can get it to compile, but there’s no sound, because (as far as I can tell) somewhere there’s a disconnect between SynthesierVoice and SynthVoice.

When you say “implement your own algorithm” do you mean create my own functions instead of overriding the base class functions? (Sorry, my C++ understanding is growing, but not quite advanced to enough to fully understand this).


#4

OK, I’ve boiled down my problem to one issue and one question.

When

synth.addVoice is called, it adds a SynthVoice object to

OwnedArray <SynthesiserVoice> voices.

That’s why, whenver a function or variable is called via

it calls on the SynthesiserVoice base class, instead of my derived SynthVoice class. The only time it jumps ship to the SynthVoice class is when the SynthVoice function is an overridden version of the base class’s virtual function. Sooooo…

How do I add my own function to SynthVoice and be able to call on it via the “voices” object without also adding it as a virtual function in the Synthesiser base class?


#5

Look on google for dynamic_cast

This is a C++ issue not a Juce one.


#6

Ah. Sorry. Thanks.


#7

I too am running into a few design headache's / queries regarding custom voice classes derived from JUCE's synth voice class. 

Most of my issues have been solved by creating the various components of my Synth as AudioProcessors and hooking them up into an AudioProcessorGraph. 

So dealing with things like filter cutoff parameters and delay parameters is becoming much more flexible. 

 

However, I am still having the issue that my WaveTableOscillator class is being implemented as a member of my derived synth voice class. The various functions within the voice class for rendering the voice and noteOn call the oscillators output to fill the buffer and also in turn set it's frequency. 

I need access to a few paramters of my oscillator within my derived synth voice (fine tune etc. for modulation and GUI param changes). As previouslty stated in this thread the getVoices() function returns a SynthVoice and the only way i can call my derived voices functions/access its member variables is to perform a dynamic cast. 

I'm wondering whether dynamic casting in this instance really is the best / only option or not ? It's working but is it an ugly work around ? I'm working through the various Meyers texts and think im getting a reasonable understanding of the consequences of dynamic casts. 

 

Does anyone have any advice in regards to this ? 

 

Any help for a still "in learning" C++ programmer would be most appreciated.