0

EDIT: This turned out to be an uninitialized variable creating chaotic behavior. See this post about getting more compiler warnings for JUCE

I was attempting to create a basic synthesizer and I quickly ran into an absurd problem when simply attempting to assign a value to a newly declared variable. After following along with the JUCE simple sine synthesis tutorial I ran into the problem. This is the basic code of my getNextAudioBlock() function when it is producing white noise. Note how there are four integers declared and assigned throughout:

const int numChannels = bufferToFill.buffer->getNumChannels();
const int numSamples = bufferToFill.numSamples;
for (int channel = 0; channel < numChannels; channel++){
    float* const buffer = bufferToFill.buffer -> getWritePointer(channel, bufferToFill.startSample);
    for (int sample; sample < numSamples; sample++){
        buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f);
    }
}

However, as soon as I attempt to add another int I no longer get sound. Just simply adding the line int unusedVariable = 0; anywhere in the getNextAudioBlock() function but before the buffer[sample] assignment immediately returns from the function and it therefore produces no audio.

If I simply declare the new variable (int unusedVariable;) then it still works. It is only specifically the assignment part that causes the error. Also, if I declare the variable as a global member then the assignment within the function works just fine.

To reiterate, this works:

buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

This works:

int unusedVariable;
buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

But this doesn't:

int unusedVariable = 0;
buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;

My only idea was that allocating new memory on the Audio thread causes the error but I have seen declaration and assignment done in other online sources and even in my exact same function with numChannels, numSamples, channel, and sample all allocated and assigned just fine. I also considered that it has something to do with using the Random class, but I get the same problem even when it is generating sine waves.

EDIT: Here is the exact code copied from the project. Right here nextSample is declared globally, as the buffer does not get filled when it is declared locally

  void MainContentComponent::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
  {
    const int numChannels = bufferToFill.buffer->getNumChannels();
    const int numSamples = bufferToFill.numSamples;
    for (int channel = 0; channel < numChannels; channel++){
        float* const buffer = bufferToFill.buffer -> getWritePointer (channel, bufferToFill.startSample);
        for (int sample; sample < numSamples; sample++){
            // nextSample = (randomGen.nextFloat() * 2.0f - 1.0f); // For Randomly generated White Noise
            nextSample = (float) std::sin (currentAngle);
            currentAngle += angleDelta;
            buffer[sample] = nextSample * volumeLevel;
        }
    }
  }
brenthompson2
  • 391
  • 3
  • 9
  • Probably not the solution to your problem, but is condition `numChannels` in `for (int channel = 0; numChannels; channel++)` intended? It will very likely produce an endless loop. – Stephan Lechner Aug 20 '17 at 22:10
  • sorry, my original code properly says (...; channel < numChannels;...) – brenthompson2 Aug 20 '17 at 22:13
  • 1
    Please paste the real code here. `buffer[sample] = (randomGen.nextFloat() * 2.0f - 1.0f;` won't even compile because of missing closing `)`. Or actually provide [mcve](https://stackoverflow.com/help/mcve). – user7860670 Aug 21 '17 at 09:20
  • I added the exact code as well as linked to FirstSynth and AdditiveManual, two projects that only work when the variables are global members – brenthompson2 Aug 21 '17 at 19:27
  • @brenthompson2 -- if you're a paid licensee and live build is not working for you, you should post on the JUCE forum https://forum.juce.com/, which is monitored by the JUCE development team. – bgporter Aug 26 '17 at 13:37

1 Answers1

1

I created a new AudioApplication project in the Projucer and pasted this block of code into the getNextAudioBlock() method (adding sensible member variables as you're referencing them here).

The compiler pointed at the problem right away -- the loop variable sample below isn't initialized (and C++ won't default init it for you), so if the memory used by that variable happened to have contained a value that's less than the buffer size, you'll generate some audio; if not, the buffer passed into this function is unaffected because the loop never runs.

    for (int sample; sample < numSamples; sample++){
        nextSample = (randomGen.nextFloat() * 2.0f - 1.0f); // For Randomly generated White Noise
        //nextSample = (float) std::sin (currentAngle);
        //currentAngle += angleDelta;
        buffer[sample] = nextSample * volumeLevel;
    }

see if changing that to for (int sample=0; doesn't fix things for you.

bgporter
  • 35,114
  • 8
  • 59
  • 65
  • Thank you very much. That makes a lot of sense. I will try that in the morning. What compiler were you using? – brenthompson2 Aug 25 '17 at 05:21
  • Xcode 8, but I'd expect the behavior here to be similarly unpredictable everywhere -- see this SO answer: https://stackoverflow.com/questions/1597405/what-happens-to-a-declared-uninitialized-variable-in-c-does-it-have-a-value – bgporter Aug 25 '17 at 11:51
  • This was the solution. It also fixed my problem where audio wasn't outputting to both channels. Now if only [I can figure out how to compile with those warnings on my Ubuntu machine...](https://stackoverflow.com/questions/45891062/how-to-get-compiler-warnings-juce-ubuntu) – brenthompson2 Aug 26 '17 at 01:16