Pitch Changes with Block Size on Windows Audio Driver

Well, I’m new to Juce development, but not to software development (it’s my day job). But new to audio programming and was hoping Juce would provide a nice way in. I’m trying to build a super-simple standalone VST host that will make it easy to layer up VSTs spontaneously for jamming with friends rather than having to fiddle with my laptop trackpad and Ableton when I could be making music.

I’ve got some basics up and running so I can select a VST and play it through my MIDI keyboard.

All good except for the weird “distortion”. It almost sounds like there are two versions of the VST playing each once slightly detuned from the other. However this only happens when using windows audio in any mode. Direct sound is fine. When I come to run this on my actual music laptop I’ll be wanting to use ASIO.

To isolate the issue I downloaded the Audio Processor Graph tutorial project which just has an oscillator and some effects - no VSTs or anything. When I run that out of the box I get the same problem.

Changing the block size changes the level of detuning. Again only on windows audio driver.

If I run the same VST I’m testing with (Vital) in it’s own standalone mode using windows audio driver it doesn’t suffer the same issue.

So it seems to be Windows Audio Driver in Juce as a standalone where it happens.

Any thoughts on what might be going on?

FYI. I am using an AudioProcessorGraph for this project, seems like the most logical fit for what I’m trying to achieve, but I guess if there’s an issue with this I could just hook things up in processBlock manually.

Went back to basics and created a new project based on the plugin host example. This example doesn’t actually work, however quickly implementing processBlock to send the buffer and midibuffer to the VST (so long as there is one) instantly worked. I’m guessing there’s some sort of issue in the AudioProcesssorGraph.

For anyone else trying to get the example vst project working this did the trick for me:

void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midibuffer) final
{
    if (inner != nullptr)
    {
        inner->processBlock(buffer, midibuffer);
    }
}

void processBlock (AudioBuffer<double>& buffer, MidiBuffer& midibuffer) final
{
    if (inner != nullptr)
    {
        inner->processBlock(buffer, midibuffer);
    }
}

probably should add a lock on innerMutex too.

Also interestingly doing this:

 inner->processBlock(buffer, midibuffer);
 inner->processBlock(buffer, midibuffer);

almost had the same effect that using the graph did, as if something is being processed twice.