Proper way to add take to waveclip

What is the correct method to add a Take to a WaveAudioClip?

I’m doing waveClip->addTake(file); But this gives an assert:

jassert (edit.editFileRetriever && edit.editFileRetriever().existsAsFile());

And the take isn’t added.

How are you creating your Edit? That assertion is saying it doesn’t know how to create a relative path to the Edit file as it doesn’t know the Edit file’s location.

You might need to use these new functions: Saving and Opening Edits [Tracktion Engine]

Do I need to provide a file each time I create a new edit? I wanted to only create a file if I save the edit? Sometimes I may not even know what the file will be called until after I’ve diddled around in a session and name the file based on mood. :slight_smile:

I’ve been doing this: edit = te::createEmptyEdit(*engine, {});

I’ve given the edit a proper file and now I get an assertion in WaveCompManager& WaveAudioClip::getCompManager()

jassert (hasAnyTakes());

How do you want your paths to be saved in the Edit XML?
If you want them to be relative then you’ll need to set the Edit::editFileRetriever and Edit::filePathResolver functions.

I guess you could still store full paths in the Edit until you save but that’s not really recommended, we’d have to provide that as an option if you really did want to go that route.

When do you hit the assertion? Can you provide a stack trace please?
There’s literally millions of possible code paths in Tracktion Engine so it’s a bit difficult to guess how you’re ending up at assertions without a stack trace or at the very least the calling function.

> tracktion_engine::WaveAudioClip::getCompManager() C++
tracktion_engine::WaveAudioClip::setCurrentTake(int takeIndex) C++

Does that help? The reset is just Mouse calls from the button that I click to try and set the current take.

Can you explain the filePathResolver bits? I have a feeling this is caused by a relative path issue and the file isn’t being loaded.

Have you added the take first and it was added successfully?
The assertion is saying that the clip doesn’t have any takes and therefore it’s invalid to call setCurrentTake.

It’s in the docs here:

    /** This callback can be set to return the file for this Edit.
        By default this uses ProjectManager to find a matching file for the Edit's
        ProjectItemID but this can be overriden for custom behaviour.
    */
    std::function<juce::File()> editFileRetriever;

    /** This callback can be set to resolve file paths.
        By default:
        1) If the path is an absolute path it will simply return it
        2) If it is a relative path, the editFileRetriever will be used to try and find
           a File for the Edit and the path will be resolved against that

        You can set a custom resolver here in case the Edit is
        in memory or the files directory is different to the Edit file's location.
    */
    std::function<juce::File (const juce::String&)> filePathResolver;

Basically you set editFileRetriever to return the File for the Edit being used.
Then filePathResolver should take a path (which could be relative) and should return a fully resolved juce::File. The default implementation of that is probably fine though.

I’m simply adding the take this way: waveClip->addTake(fullPathNameToFile);
Is that not the correct way?

Ahh I think I found the issue. Adding 1 take to a clip does not give the clip 2 takes when a clip already has a file assigned to it. The original file does not become Take 0 and the 2nd file take 1.

Still doesn’t explain the assertion though because the compManager is saying there are NO take but when I do DBG(testClip->getNumTakes(false)); it shows there are.

Ah yes, that is a bit unclear.
The only way takes can be added in Waveform is when recording. A blank clip is created then each take is added with addTake so it doesn’t do anything with the original one.

Okay that explains things.So there’s no way to simulate this without recording? I would like to be able to quickly switch which audio file is sounding during playback.

I think you’ll just need to add the current source file and the new one so you have a total of two takes?

Yes, I did that but the compManager still barks that there are no takes.

But are they actually getting added correctly?
Once you’ve called addTake, can you call WaveAudioClip::hasAnyTakes() and see if that returns true or false?

If it’s false, can you print out the clip state to the console DBG(clip->state.toXmlString()); and see what the TAKES node contents is?

And if that’s not filled then it sounds like the takes aren’t getting added correctly, you might have to step through that process to see what stage is going wrong.

if (testClip->hasAnyTakes())
DBG(testClip->getNumTakes(false));

Returns 2.

Here’s the output anyway:

<AUDIOCLIP name="NM - Marsupial 140BPM-bounce-1" start="0.0" length="27.42857142857143"
           offset="0.0" id="1057" source="..\..\..\Temp\NM - Marsupial 140BPM-bounce-1.wav"
           sync="0" elastiqueMode="0" pan="0.0" colour="ffff0000">
  <LOOPINFO rootNote="-1" numBeats="64.0" oneShot="0" denominator="4" numerator="4"
            bpm="0.0" inMarker="0" outMarker="-1"/>
  <TAKES>
    <TAKE source="..\..\..\Temp\NM - Marsupial 140BPM-bounce-1.wav"/>
    <TAKE source="..\..\..\Temp\NM - Nautica 140BPM-bounce-1.wav"/>
  </TAKES>
</AUDIOCLIP>

This is failing in

void WaveAudioClip::setCurrentTake (int takeIndex):

auto takeSourceID = ProjectItemID::fromProperty (take, IDs::source);
auto mo = edit.engine.getProjectManager().getProjectItem (takeSourceID);
invalidateCurrentTake();

if (mo != nullptr || getCompManager().isTakeComp (takeIndex))
    sourceFileReference.setToProjectFileReference (takeSourceID);
else
    takesTree.removeChild (take, getUndoManager());

mo is null and thus the take is removed.