Question on ```insertWaveClip()```

I am having issues with importing audio clips with insertWaveClip(). Sometimes the clip imports just fine. Sometimes it is just silence. Sometimes it is wildly distorted. Sometimes it doesn’t import at all. And the clips are known good audio files, all of which were created by my DAW, and otherwise play back normally.

I am almost certainly not using insertWaveClip() properly.

My code is below…

File file{ editViewState.audioFilePath };
FileChooser fileChooser("Open Audio File", file, "*.wav");
if (fileChooser.browseForFileToOpen())
{
	file = fileChooser.getResult();

	const auto clipTrack{ dynamic_cast<te::ClipTrack*>(trackPtr) };
	te::AudioFile audioFile{ trackPtr->edit.engine, file };

	const auto sampleRate{ transport.engine.getDeviceManager().getSampleRate() };
	const auto audioFileSampleRate{ audioFile.getSampleRate() };

	if (audioFileSampleRate != sampleRate)
	{
		AlertWindow::showMessageBoxAsync(MessageBoxIconType::WarningIcon, "Import Audio Error", "FileSampleRate= " + String(audioFileSampleRate) + "\nEditSampleRate= " + String(sampleRate));
	}
	else
	{
		const auto clipLength{ audioFile.getLength() };
		const auto start{ transport.getCurrentPosition() };
		clipTrack->insertWaveClip(file.getFileNameWithoutExtension(),file,{{start, clipLength}, 0.0}, false) ;
	}
}

Some suggestions and guidance is most appreciated.

The only dodgy thing I can see is that {start, clipLength} for the EditTimeRange. That has start and end times so should probably be {start, start + clipLength}?

I modified the bottom section of the code above to be as follows;

const auto clipLength{ audioFile.getLength() };
if (const auto waveAudioClip{ clipTrack->insertWaveClip(file.getFileNameWithoutExtension(),file,{{0.0, clipLength}, 0.0}, false) })
{
	const auto start{ transport.getCurrentPosition() };
	waveAudioClip->setStart(start, true, true);
}

This code seems to make importing a bit more consistent, However, importing of some files, in particular my renders, visually creates a solid block of color and plays back as a loud buzz.

I am not sure what to try next?

It could be that they’re being time stretched and that’s not working. If they’re exports, are they WAV? Presumably they’ll have tempo metadata in them then.

What time stretch engine are you using? Can you see if a proxy file is being created for them?

Also, break in WaveNode and see what file is actually getting played back. If you open that on your OS, is it also junk?

Well that is what is so puzzling,…they are just plain WAV files. They look and play back completely normally in other contexts! For example, the rendered file that when imported is visually a solid block, and produces a loud buzz, looks and plays back perfectly in Audacity.

I do not do any time stretching.

In some more testing, it seems that WAV files created as clips in a track, will import as intended now. So, it seems that it is just the rendered files that import incorrectly. So, perhaps there is a difference in how rendered files are treated for export?

Can you try loading the files in to Waveform? Do they play there?

I can try Waveform later in the studio. But, I do have Tracktion 7 installed on my development computer, and the file imports correctly in Tracktion 7. It looks normal, and plays back normally.

Sis you try breaking in the WaveNode constructor like I suggested to check that it’s the same file that’s being played back and not a proxy that’s been generated?

With a breakpoint in the WaveNode constructor, the file path is as below;

fullPath	{text={data=0x000001943ed533f0 "C:\\Users\\User\\AppData\\Roaming\\TheDAW\\Temporary\\edit_0_41e6d\\clip_0_1046_1dd4129a24eee8c2.wav" } }	juce::String

…which appears to me to be the clip name that the file will be imported to. Is that correct?

There is otherwise no mention, that I can find, of the imported file, which is simply named “Render.wav”.

Well it looks like it’s generating that clip file from your original. I’m not at my computer at the moment and can’t remember off hand what the “clip” prefix is for but it could be looped or a proxy…

Does that file play back on the OS or is it garbage too?

The temporary file is garbage also.

What is really strange is that sometimes the import works perfectly!? And everything is the same. In other words, all of the files were created by my DAW, which is totally JUCE and TracktionEngine based. And all the files play normally in other contexts such as Windows Media Player or Audacity (except for the temporary mentioned above).

Well I’ve set this several times but what’s most likely happening is that when you exported these files they have the tempo and pitch metadata they were exported from embedded in the files. This is to be expected as it enables you to tempo/pitch match them when importing them.

So when you import the files, Tracktion Engine tries to create a proxy file to match the source file tempo/pitch to the Edit’s tempo/pitch. If you put a breakpoint in AudioClipBase::getProxyFileToCreate you’ll see this triggered.

It sounds like if you don’t have SoundTouch or Elastique timestretching enabled, junk is getting created. Tbh I’m not sure what it should do in these situations, you really should have one time stretch mode enabled.

I was not aware the time stretch was required.

Since I have no need of it, what is the most benign way to invoke time stretch with the least impact on the program?

Probably just disable auto-tempo and auto-pitch on newly added clips?
I think that would do it.

But I should also add an assertion or similar to the time stretching render code to catch this case.

I was going to ask how to disable auto-tempo and auto-pitch, then I found setTimeStretchMode(), and I was going to use;

waveAudioClip->setTimeStretchMode(te::TimeStretcher::disabled);

But then I also noticed that “disabled” is the default. So, that will not change anything.

So, what is the way to disable auto-tempo and auto-pitch?

I think I found it!

waveAudioClip->setAutoPitch(false);
waveAudioClip->setAutoTempo(false);

I will try this out.

Please let me know if there is anything else I need to change?

Adding the lines below seems to have fixed the issue.

waveAudioClip->setAutoPitch(false);
waveAudioClip->setAutoTempo(false);

I will let you know if I run into any issues.

I would argue that auto-tempo and auto-pitch should default to “false”.

Are there any other unusual requirements I might be missing?

I will do more testing, but the code below is currently working for doing successful audio imports.

File file{ editViewState.audioFilePath };
FileChooser fileChooser("Open Audio File", file, "*.wav");
if (fileChooser.browseForFileToOpen())
{
	file = fileChooser.getResult();
	
	const auto clipTrack{ dynamic_cast<te::ClipTrack*>(trackPtr) };
	
	te::AudioFile audioFile{ trackPtr->edit.engine, file };
	const auto sampleRate{ transport.engine.getDeviceManager().getSampleRate() };
	const auto audioFileSampleRate{ audioFile.getSampleRate() };

	if (audioFileSampleRate != sampleRate)
	{
		AlertWindow::showMessageBoxAsync(MessageBoxIconType::WarningIcon, "Import Audio Error", "FileSampleRate= " + String(audioFileSampleRate) + "\nEditSampleRate= " + String(sampleRate));
	}
		else
	{
		const auto clipLength{ audioFile.getLength() };
		if (const auto waveAudioClip{ clipTrack->insertWaveClip(file.getFileNameWithoutExtension(),file,{{0.0, clipLength}, 0.0}, false) })
		{
			const auto start{ transport.getCurrentPosition() };
			waveAudioClip->setStart(start, false, true);
			waveAudioClip->setAutoPitch(false);// needed to disable pitch shift
			waveAudioClip->setAutoTempo(false);// needed to disable time stretch
		}
	}
}

Thank you for the help!

2 Likes