JUCE learner using a vector inside juce crashes program


#1

Hi all, I am using a vector to store a list of possible notes that I want to randomly select and play. I have a bunch of binary notes stored.
My code is crashing the program. I have been looking at it for quite some time and tried moving the declaration of variables and populating the vectors around without much luck … Perhaps a more experience JUCE and C++ user can point me in the direction of a solution before I use up all my brownie points on this forum. Thanks in advance for your replies!
Sean

    // edited version of play file demo
    // I have a bunch of mp3 files loaded as binary resources
    // I used the named resource[] to select them and play them in this method
    void playfile(int n)
    {
        AudioFormatReader* reader = formatManager.createReaderFor( new MemoryInputStream(BinaryData::getNamedResource(BinaryData::namedResourceList[n], mp3Size), mp3Size, false));
        if (reader != nullptr)
        {
            ScopedPointer<AudioFormatReaderSource> newSource = new AudioFormatReaderSource (reader, true);
            transportSource.setSource (newSource, 0, nullptr, reader->sampleRate);
            playButton.setEnabled (true);
            readerSource = newSource.release();
        }
        if (reader == nullptr)
        {
            playButton.setEnabled (false);
        }
        transportSource.setPosition (0.0);
        changeState (Starting);
    }
    // this code is what is crashing the plugin
    // ###THIS WOULD WORK #####
    // int choice2 = Random::getSystemRandom().nextInt(35);
    // playfile(choice2);
    // ### i am trying to replace it with this //
    void playButtonClicked()
    {
    // I am not sure where this for loop should be located and
     //   if the variables are correctly in scope
        for (int i; i < 11; i++)
        {
            if (numbers[i] == 1)
            {
                myvector.push_back(i);
            }
        }
    // select a random number and than grap an index from my vector
        int choice = Random::getSystemRandom().nextInt(4);
        int f = myvector.at(choice);
    
        playfile(f);
    }

    TextButton playButton;
    AudioFormatManager formatManager;
    ScopedPointer<AudioFormatReaderSource> readerSource;
    AudioTransportSource transportSource;
    TransportState state;
    char* note;
    char* newnote;

    int filesPlayed = 0;
    int f;
    int i;
    // size of each binary file is the same
    int mp3Size = 21924;
    // boolean array of available notes from chrom scale
    int numbers[12] = {0,1,1,0,0,1,1,0,0,1,0,0};
    // vector to contain notes
    std::vector<int> myvector;
 

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};


Component* createMainContentComponent()     { return new MainContentComponent(); }


#endif  // MAINCOMPONENT_H_INCLUDED ```

#2

Hi Sean!

Hmm, one problem is that you’re not initializing the variable i in the for loop, so it’ll start off as some nasty crazy garbage. Try something like int i = 0; or int i{ 0 }; instead: they both do essentially the same thing just with slightly different syntax.

Try that and see how you go from there. :slight_smile:


#3

As something of a footnote, while it’s certainly a good idea to understand how to construct a basic for loop, the frequency and overwhelming likelihood of mistakes when writing code like this (as we’ve just seen) are a strong motivation behind other streamlined, less error-prone ways of working through a collection, such as for (auto& number : numbers) {...} (range-based for loop) and std::for_each(begin(numbers), end(numbers), ...); (a flattened, “loop-less” version). The latter of these requires knowledge of lambdas or “function objects” in general, but it’s generally worth gravitating towards this way of thinking as you become more comfortable with the language. You can always replace a small portion of code at a time.

The C++ Core Guidelines are great reading and cover a lot of interesting topics.

I would also advise getting extremely familiar with the built-in standard library algorithms. It’s really worth taking your time to get to know each and every one. They provide all kinds of incredibly useful operations and once you can understand and recognise what they do, you can often break down your intent into fairly trivial combinations of a handful of these. Clear benefits are that it helps to flatten your code so you don’t have a whole mess of nested statements everywhere, and it helps to build a shared vocabulary when talking about decomposing problems. It’s much easier to reason about a linear sequence of well-defined instructions rather than free-form blocks of code within other blocks … with fors, ifs and whiles all over the place. :wink:

Sean Parent does an excellent demonstration of all this as part of his “Better Code” presentation, of which there are various videos available freely online.

Once you get the hang of these techniques, I’m sure you’ll start seeing much simpler ways to achieve what you want to do.

In short, modern C++ provides numerous ways to avoid having to write everything out so explicitly while simultaneously increasing the elegance, clarity, terseness and modularity of your code; it’s well worth the effort to learn these other ways of expressing your ideas.


#4

Thanks! Such a simple mistake! It fixed my code!
The xcode compiler was giving a warning that the variable hadn’t been initialised. I should have taken more notice!
I should have seen it!
I will look into the std library that sounds like a good idea.
It’s only been a few weeks of C++ lots to learn!
I obviously need to learn how to use a decent debugger inside all of this. That would have helped me see the garbage being passed around. It looks like Xcode has one for C++. I might check that too. Sorry to use this forum as a debugging tool ! Thanks again for your help …
Sean


#5

You’re welcome! I’m really glad to hear it.

Oh yes, compiler warnings are definitely your friend! :wink:

Wishing you the very best on your voyage of discovery; it’s a fantastic time to get into C++.