mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 07:39:42 +02:00
Fixes for bugs 2534 and 1215
This commit is contained in:
parent
9e41e8fa7d
commit
5bca69ca31
@ -247,7 +247,7 @@ bool EffectChangePitch::Process()
|
||||
// eliminate the next line:
|
||||
mSemitones = m_dSemitonesChange;
|
||||
#endif
|
||||
return EffectSoundTouch::ProcessWithTimeWarper(initer, warper);
|
||||
return EffectSoundTouch::ProcessWithTimeWarper(initer, warper, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ bool EffectChangeTempo::Process()
|
||||
double mT1Dashed = mT0 + (mT1 - mT0)/(m_PercentChange/100.0 + 1.0);
|
||||
RegionTimeWarper warper{ mT0, mT1,
|
||||
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed ) };
|
||||
success = EffectSoundTouch::ProcessWithTimeWarper(initer, warper);
|
||||
success = EffectSoundTouch::ProcessWithTimeWarper(initer, warper, false);
|
||||
}
|
||||
|
||||
if(success)
|
||||
|
@ -20,6 +20,7 @@ effect that uses SoundTouch to do its processing (ChangeTempo
|
||||
#include <math.h>
|
||||
|
||||
#include "../LabelTrack.h"
|
||||
#include "../WaveClip.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../NoteTrack.h"
|
||||
#include "TimeWarper.h"
|
||||
@ -67,7 +68,9 @@ bool EffectSoundTouch::ProcessNoteTrack(NoteTrack *nt, const TimeWarper &warper)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer, const TimeWarper &warper)
|
||||
bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer,
|
||||
const TimeWarper &warper,
|
||||
bool preserveLength)
|
||||
{
|
||||
// Assumes that mSoundTouch has already been initialized
|
||||
// by the subclass for subclass-specific parameters. The
|
||||
@ -85,6 +88,7 @@ bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer, const TimeWarp
|
||||
this->CopyInputTracks(true);
|
||||
bool bGoodResult = true;
|
||||
|
||||
mPreserveLength = preserveLength;
|
||||
mCurTrackNum = 0;
|
||||
m_maxNewLength = 0.0;
|
||||
|
||||
@ -107,14 +111,9 @@ bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer, const TimeWarp
|
||||
if (!leftTrack->GetSelected())
|
||||
return fallthrough();
|
||||
|
||||
//Get start and end times from track
|
||||
mCurT0 = leftTrack->GetStartTime();
|
||||
mCurT1 = leftTrack->GetEndTime();
|
||||
|
||||
//Set the current bounds to whichever left marker is
|
||||
//greater and whichever right marker is less
|
||||
mCurT0 = wxMax(mT0, mCurT0);
|
||||
mCurT1 = wxMin(mT1, mCurT1);
|
||||
//Get start and end times from selection
|
||||
mCurT0 = mT0;
|
||||
mCurT1 = mT1;
|
||||
|
||||
// Process only if the right marker is to the right of the left marker
|
||||
if (mCurT1 > mCurT0) {
|
||||
@ -250,9 +249,8 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
||||
outputTrack->Flush();
|
||||
}
|
||||
|
||||
// Take the output track and insert it in place of the original
|
||||
// sample data
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), false, true, &warper);
|
||||
// Transfer output samples to the original
|
||||
Finalize(track, outputTrack.get(), warper);
|
||||
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
m_maxNewLength = wxMax(m_maxNewLength, newLength);
|
||||
@ -345,12 +343,10 @@ bool EffectSoundTouch::ProcessStereo(
|
||||
outputRightTrack->Flush();
|
||||
}
|
||||
|
||||
// Take the output tracks and insert in place of the original
|
||||
// sample data.
|
||||
leftTrack->ClearAndPaste(
|
||||
mCurT0, mCurT1, outputLeftTrack.get(), false, true, &warper);
|
||||
rightTrack->ClearAndPaste(
|
||||
mCurT0, mCurT1, outputRightTrack.get(), false, true, &warper);
|
||||
// Transfer output samples to the original
|
||||
Finalize(leftTrack, outputLeftTrack.get(), warper);
|
||||
Finalize(rightTrack, outputRightTrack.get(), warper);
|
||||
|
||||
|
||||
// Track the longest result length
|
||||
double newLength = outputLeftTrack->GetEndTime();
|
||||
@ -384,4 +380,57 @@ bool EffectSoundTouch::ProcessStereoResults(const size_t outputCount,
|
||||
return true;
|
||||
}
|
||||
|
||||
void EffectSoundTouch::Finalize(WaveTrack* orig, WaveTrack* out, const TimeWarper &warper)
|
||||
{
|
||||
if (mPreserveLength) {
|
||||
auto newLen = out->GetNumSamples();
|
||||
auto oldLen = out->TimeToLongSamples(mCurT1) - out->TimeToLongSamples(mCurT0);
|
||||
|
||||
// Pad output track to original length since SoundTouch may remove samples
|
||||
if (newLen < oldLen) {
|
||||
out->InsertSilence(out->LongSamplesToTime(newLen - 1),
|
||||
out->LongSamplesToTime(oldLen - newLen));
|
||||
}
|
||||
// Trim output track to original length since SoundTouch may add extra samples
|
||||
else if (newLen > oldLen) {
|
||||
out->Trim(0, out->LongSamplesToTime(oldLen));
|
||||
}
|
||||
}
|
||||
|
||||
// Silenced samples will be inserted in gaps between clips, so capture where these
|
||||
// gaps are for later deletion
|
||||
std::vector<std::pair<double, double>> gaps;
|
||||
double last = 0.0;
|
||||
auto clips = orig->SortedClipArray();
|
||||
auto front = clips.front();
|
||||
auto back = clips.back();
|
||||
for (auto &clip : clips) {
|
||||
auto st = clip->GetStartTime();
|
||||
auto et = clip->GetEndTime();
|
||||
|
||||
if (st >= mCurT0 || et < mCurT1) {
|
||||
if (mCurT0 < st && clip == front) {
|
||||
gaps.push_back(std::make_pair(mCurT0, st));
|
||||
}
|
||||
if (mCurT1 > et && clip == back) {
|
||||
gaps.push_back(std::make_pair(et, mCurT1));
|
||||
}
|
||||
if (last >= mCurT0) {
|
||||
gaps.push_back(std::make_pair(last, st));
|
||||
}
|
||||
}
|
||||
last = et;
|
||||
}
|
||||
|
||||
// Take the output track and insert it in place of the original sample data
|
||||
orig->ClearAndPaste(mCurT0, mCurT1, out, true, true, &warper);
|
||||
|
||||
// Finally, recreate the gaps
|
||||
for (auto gap : gaps) {
|
||||
auto st = orig->LongSamplesToTime(orig->TimeToLongSamples(gap.first));
|
||||
auto et = orig->LongSamplesToTime(orig->TimeToLongSamples(gap.second));
|
||||
orig->SplitDelete(warper.Warp(st), warper.Warp(et));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_SOUNDTOUCH
|
||||
|
@ -49,7 +49,9 @@ protected:
|
||||
// Effect implementation
|
||||
|
||||
using InitFunction = std::function< void(soundtouch::SoundTouch *soundtouch) >;
|
||||
bool ProcessWithTimeWarper(InitFunction initer, const TimeWarper &warper);
|
||||
bool ProcessWithTimeWarper(InitFunction initer,
|
||||
const TimeWarper &warper,
|
||||
bool preserveLength);
|
||||
|
||||
std::unique_ptr<soundtouch::SoundTouch> mSoundTouch;
|
||||
double mCurT0;
|
||||
@ -69,6 +71,9 @@ private:
|
||||
bool ProcessStereoResults(const size_t outputCount,
|
||||
WaveTrack* outputLeftTrack,
|
||||
WaveTrack* outputRightTrack);
|
||||
void Finalize(WaveTrack* orig, WaveTrack* out, const TimeWarper &warper);
|
||||
|
||||
bool mPreserveLength;
|
||||
|
||||
int mCurTrackNum;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user