Overriding SamplerVoice::renderNextBlock


#1

This is driving me nuts... I spent HOURS trying to do this without success :(

I have subclassed SamplerVoice and SamplerSound and that works fine (I can play my own sounds w/o any problem using those new classes).
I even used FM sounds (subclassing SynthesiserVoice and SynthesiserSound the same way it's done in JuceDemo) playing simultaneously with sampled sounds with no problem. The problem started when tried to override the SamplerVoice::renderNextBlock method in my new voice class (called WaveVoice). 

Clearly I must be doing somehthing wrong. Could someone out there give me a direction ? please ? I'm desperate...

Here is what I have done:

/** Wavetable synth sound */
class WaveSound : public SamplerSound
{
public:
    WaveSound (const String& soundName,
              AudioFormatReader& source,
              const BigInteger& notes,
              const int midiNoteForNormalPitch,
              const double attackTimeSecs,
              const double releaseTimeSecs,
              const double maxSampleLengthSeconds) :
    SamplerSound (soundName, source, notes, midiNoteForNormalPitch, attackTimeSecs, releaseTimeSecs, maxSampleLengthSeconds)
    {
        ... Same code as for SamplerSound constructor
    }
    String name;
    ScopedPointer<AudioSampleBuffer> data;
    double sourceSampleRate;
    BigInteger midiNotes;
    int length, attackSamples, releaseSamples;
    int midiRootNote;
};

//==============================================================================
/** Wavetable synth voice */
class WaveVoice  : public SamplerVoice
{
public:
    WaveVoice()
    : pitchRatio (0.0),
    sourceSamplePosition (0.0),
    lgain (0.0f), rgain (0.0f),
    attackReleaseLevel (0), attackDelta (0), releaseDelta (0),
    isInAttack (false), isInRelease (false)
    {
    }
    
    //==============================================================================
    void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
    {
        if (WaveSound* playingSound = static_cast <WaveSound*> (getCurrentlyPlayingSound().get()))
        { ... Same code as in SamplerVoice::renderNextBlock
        }
    }

Thanks

 


#2

Your WaveVoice class probably needs to override "canPlaySound(SynthesiserSound* sound)" so the synthesiser knows what sounds the voice is able to play. 

bool WaveVoice::canPlaySound(SynthesiserSound* sound)
{
    return dynamic_cast<const WaveSound*> (sound) != nullptr;
}

#3

It looks like you're redefining all of SamplerSound's fields which doesn't seem right.  Are you certain you want to be doing that?  Also having a copy of SamplerSound's constructor code in your subclass's constructor doesn't seem like the right thing to be doing either.


#4

Thanks... but it still does not work. And frankly I don't understand why it would need this. The SamplerVoice::canPlaySound should do the work, shouldn't it ?

The weird thing is that if I just rename my renderNextBlock to something else (i.e. I don't use it) , it works (I can hear the sounds). So the rest of the code looks ok.

H E L P !!!!


#5

In fact if I do this (call superclass from my renderNextBlock) it works (but obviously this is not what I want...) :

    void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
    {
        SamplerVoice::renderNextBlock(outputBuffer, startSample, numSamples);
        return;
    }

#6

Thank you but the code shown here is just for testing purpose and minimize the changes to see where it doesn't work. Shouldn't hurt though. Or am I missing something ?

Obviously when I get this to work I will modify the code and the variables.

 


#7

OK. Found the problem ! sound variables were not intialized. If I copy the methods from the superclasses it works.

Now I just have to do this in a clean way.

Thanks to those who responded. It always helps to know you're not alone...

:)