Implementing multi-track functionality. Tutorials/examples?


#1

Good day, I am attempting to integrate functionality in JUCE for uploading 4 distinct tracks (of the same song - to be played back synchronously) for analysis (thinking in terms of uploading Stems). I am currently implementing a single file uploader as in the example/tutorial which uses the AudioTransportSource and AudioFormatReader(Source) classes; however, it would obviously be rather poor practice and likely ineffective to implement this for each instance if I am playing the files synchronously. From research that I have done on here, it seems the MixerAudioSource is likely the key to unlocking this particular instance, but there doesn’t really seem to be a clear picture available regarding how to configure all of this to work together. Any advice or links to tutorials on this particular approach would be greatly appreciated!


#2

Hello, so for any future inquiries, I have borrowed extensively from asi2015’s solution here: https://forum.juce.com/t/how-best-to-read-multi-mono-wave-files-into-a-single-audio-source/29641/13 . One of the major ways that I have adapted the code was using a HashMap to contain the references to the files as they are chosen instead of std::vector, delegating an index variable as the relative key which is passed down as an integer through capture on the “onClick” lambda function (this is another fun point, using [this, index] to capture).
I am only now experiencing the strange side-effect of the player crashing when there is only 1 file referenced in the HashMap, but other wise everything works well. The offending issue seems to have something to do with the getUnchecked() function in the getNextAudioBlock override.
I am sure there is a better way to do this, and hopefully it will become apparent when I go back to refine this application.


#3

I’m glad you found the code example I posted previously to be a useful starting point! I’m not sure why getUnchecked() would be a problem unless you are trying to call an index that is out of range. Maybe someone else has an idea. I haven’t worked with the HashMap, but if it’s like a standard map, maybe your indices have not been sorted, or there is a hole in the sequence somewhere, so when you getUnchecked() there is a mismatch? Good luck!


#4

The getUnchecked() is a method from Array, not from HashMap, so I assume that is a different part of the app…
The name getUnchecked() means, return the element of the array without checking, if the index is available. If your code can end up with an invalid index, you must check before yourself.
In asi2015’s code example, getUnchecked (0) was never reached, because the start method would not trigger, if the inputReaders array is empty.
Better would be to check if (! inputReaders.isEmpty()) or in general:

if (isPositiveAndBelow (index, inputReaders.size())
// ...

If you still have problems, be aware, that this array is accessed from the audio thread (getNextAudioBlock()) and the message thread (on creation, and if you add gui methods, that alter that array), so you need a thread synchronisation method here…

Hope that helps