Same audio input for more tracks

Hi,
Using the framework I tried to set a physical audio input to multiple audio tracks at the same time in order to record both from the same input, but it does not seem to be possible.
Analyzing the code, more specifically :

void InputDeviceInstance::setTargetTrack (AudioTrack& track, int index, bool moveToTrack)
{
    if (isRecording())
    {
        edit.engine.getUIBehaviour().showWarningMessage(TRANS("Can't change tracks while recording is active"));
        return;
    }
 

    if (owner.isTrackDevice() || moveToTrack)
    {
        for (auto t : getTargetTracks())
            removeTargetTrack(*t);
    }
    else
    {
        removeTargetTrack(track);
    }



    auto v = juce::ValueTree(IDs::INPUTDEVICEDESTINATION);
    state.addChild(v, -1, &edit.getUndoManager());
    
    auto& dest = *destTracks[destTracks.size() - 1];
    dest.targetTrack = track.itemID;
    dest.targetIndex = index;

    trackDeviceEnabler.triggerAsyncUpdate();
}

I noticed that programmatically, before setting an input on a track, it is removed from all the la the others (if any).
Commenting on that section :

if (owner.isTrackDevice() || moveToTrack)
    {
        for (auto t : getTargetTracks())
            removeTargetTrack(*t);
    }
    else
    {
        removeTargetTrack(track);
    }

multiple INPUTDEVICEDESTINATION children are created with different destTracks for a single input, and by doing so, arming the tracks, you can record correctly.

I would like to understand the need to therefore have such a block of code.

It should work as you expect if you set moveToTrack = false. The block of code is to stop the same input for being added to the same track more than once. Each track has 4 input slots, so if you add input to slot 1, it clears it from slot 2,3,4 first.

Does this mean that I can set up to 4 different physical audio inputs on the same track simultaneously ?

Yes, that is the index parameter.

It’s great !

One last question : what about the live input monitoring ?

To enable it, i need to call this method :

inputDeviceInstance->getInputDevice().flipEndToEnd();

But it is releated directly to the inputDeviceInstance so if i have 2 tracks with the same input and then enable the live input monitoring on the first track, also the second will affect.

is there some way to enable the live input only on one track ?
@RolandMR

@RolandMR
Hi,
I think i found a solution for setting live input monitoring only on a specific track.

Imagine you have this scenario :

Active input :

  • INPUT_1 ( stereo )

Active tracks :

  • INPUT_1 → TRACK_1 → DEFAULT_OUT
  • INPUT_1 → TRACK_2 → DEFAULT_OUT

In the actual situation , if you call input1DeviceInstance->getInputDevice().flipEndToEnd(); the live input is setted on the input, and so this affects the both TRACK_1 and TRACK_2.

Suppose you don’t want the live input monitoring on the TRACK_2 but only on the first one… actually it is not possibile just because even TRACK_2 has the INPUT_1 as input.

For a dummy test i’ve added a boolean property on the track state called live that should be true if you want the live input on that track.

In the EditNodeBuilder.cpp there is a method that is called when the system needs to create live input node for tracks :

std::unique_ptr<tracktion::graph::Node> createLiveInputsNode (AudioTrack& track, tracktion::graph::PlayHeadState& playHeadState, const CreateNodeParams& params)
{
    std::vector<std::unique_ptr<tracktion::graph::Node>> nodes;

    if (! params.forRendering)
        if (auto context = track.edit.getCurrentPlaybackContext())
            for (auto in : context->getAllInputs())
                if ((in->isLivePlayEnabled (track) || in->getInputDevice().isTrackDevice()) && in->isOnTargetTrack (track) )
                    if (auto node = createLiveInputNodeForDevice (*in, playHeadState, params))
                        nodes.push_back (std::move (node));

    if (nodes.empty())
        return {};

    if (nodes.size() == 1)
        return std::move (nodes.front());

    return std::make_unique<SummingNode> (std::move (nodes));
}

Now take a look at this condition :

if ((in->isLivePlayEnabled (track) || in->getInputDevice().isTrackDevice()) && in->isOnTargetTrack (track) )

Simply adding this condition in AND with the others && track.state.getProperty("live",false)) you can check if the specific track want the live input monitor enable and so the system could create a live input node only for the track that actually want it.

This is a dummy test, but you can modify the InputDeviceInstance class adding this two methods :

setLiveInputEnabled(AudioTrack&at, bool shouldBeEnabled){

for (auto dest : destTracks)
        if (dest->targetTrack == t.itemID)
            dest->liveInputEnabled= shouldBeEnabled;

}

isLiveInputEnabled(AudioTrack& at) const {

for (auto dest : destTracks)
        if (dest->targetTrack == t.itemID)
            if (dest->liveInputEnabled)
                return true;
    
    return false;

}

And in the InputDeviceDestination you must add a cached value :

juce::CachedValue<bool> liveInputEnabled;

and attach it to the state in the InputDeviceDestination’s constructor.

Adding this, in the condition mentioned before , you could write :

if ((in->isLivePlayEnabled (track) || in->getInputDevice().isTrackDevice()) && in->isOnTargetTrack (track) && in->isLiveInputMonitoringEnabled(at) )

What do you think about that ? Could be a good solution for my goals ?