is this the best way to have several different sources playing at once? - this will be in a Dynamic Library which will get a list of files of varying lengths which will get ‘play’ triggered at different points in time.
How do you determine, when these are triggered?
If you read my answer in the thread before, you know, that I would advise against using multiple TransportAudioSources, because the method how they are triggered doesn’t lend itself to play synchronous in a deterministic manner.
If it is a kind of DAW, create a special audio source subclass (preferably PositionableAudioSource or AudioFormatReaderSource), where you can additionally specify the offsets and gains, and feed it into the MixerAudioSource.
So I take it, that you don’t mind, when exactly the sound starts to play, within an uncertainty of 100 ms, plus you don’t mind quantisation to an arbitrary grid of the beginnings of audio buffers.
This is owed to the audio buffers and the fact, that the start stop messages are processed by the message queue, which might be busy with drawing, loading a file or what ever non-realtime job is to do.
In that case using an array of TransportAudioSources is fine. Just plug them into a MixerAudioSource and you are good to go, there is nothing special about it.
I’m looking at small buffers so quantisation shouldn’t be too big an issue - and the reference will be the frame-rate of the game engine, which even if it was to render at 100fps shouldn’t be too laggy.
The message queue shouldn’t have any drawing etc to do, it’s a headless DLL.
But, for sake of argument, let’s say I wanted less uncertainty, what would be my approach then?
The Synthesiser class addresses those issues, that you will face:
you will have the audio timestamped, i.e. counting samples and synchronise with that counter
you will need a way of setting the new sound in the audio thread, including with the information of the buffer offset
this is usually done via a fifo buffer
In your case I would attempt it with an AsyncUpdater for each source. You add the source to a list (using a SpinLock for adding to the container should be ok IMHO), and the async updater triggers the play/stop state. The benefit is, that it can be used in a thread safe manner, and it doesn’t use the message thread, which is in a DLL, problematic anyway, I’d assume.
No worries, the handling of number of channels in AudioSources is a bit opaque, and I am also not 100% happy about it.
The last link in the chain (probably AudioSourcePlayer) determines, how many channels it wants by supplying an AudioBuffer in AudioSourceChannelInfo with a certain number of channels.
Each AudioSource feeding another one has it’s own means to change the number of channels. So better don’t expect anything clever here.
Usually if it has less channels than requested, it will copy the channels, and if it is more channels than requested, it will sum them (averaging).
But I am not 100% sure, if that is true for all AudioSource types.
I don’t get, why people are so crazy about TransportAudioSource. It is really only suitable for a live player, not a plugin, and not to be combined with other TransportAudioSources.
Instead feed it through ResamplingAudioSource, that works reliable without the message thread.
The error, when there is no input into the MixerAudioSource seems like a genuine bug to me, so this loop might need some attention from the JUCE team.
So I’m not making a plugin. I am making a live-player, of sorts, its being played, like a game so I’d like to have stop/start on the individual sources.
Oh, sorry, I mixed that with another conversation, my bad.
I just am not a fan of TransportAudioSource, as you may have seen, because it is not clear, what drawbacks it brings when it is crossing the thread boundaries.
And when people started with the audio player tutorial, they are likely to try to use it in a plugin, and it works for a while, until somebody clicks bounce out.