mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 15:49:36 +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:
|
// eliminate the next line:
|
||||||
mSemitones = m_dSemitonesChange;
|
mSemitones = m_dSemitonesChange;
|
||||||
#endif
|
#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);
|
double mT1Dashed = mT0 + (mT1 - mT0)/(m_PercentChange/100.0 + 1.0);
|
||||||
RegionTimeWarper warper{ mT0, mT1,
|
RegionTimeWarper warper{ mT0, mT1,
|
||||||
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed ) };
|
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed ) };
|
||||||
success = EffectSoundTouch::ProcessWithTimeWarper(initer, warper);
|
success = EffectSoundTouch::ProcessWithTimeWarper(initer, warper, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
|
@ -20,6 +20,7 @@ effect that uses SoundTouch to do its processing (ChangeTempo
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "../LabelTrack.h"
|
#include "../LabelTrack.h"
|
||||||
|
#include "../WaveClip.h"
|
||||||
#include "../WaveTrack.h"
|
#include "../WaveTrack.h"
|
||||||
#include "../NoteTrack.h"
|
#include "../NoteTrack.h"
|
||||||
#include "TimeWarper.h"
|
#include "TimeWarper.h"
|
||||||
@ -67,7 +68,9 @@ bool EffectSoundTouch::ProcessNoteTrack(NoteTrack *nt, const TimeWarper &warper)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
// Assumes that mSoundTouch has already been initialized
|
||||||
// by the subclass for subclass-specific parameters. The
|
// by the subclass for subclass-specific parameters. The
|
||||||
@ -85,6 +88,7 @@ bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer, const TimeWarp
|
|||||||
this->CopyInputTracks(true);
|
this->CopyInputTracks(true);
|
||||||
bool bGoodResult = true;
|
bool bGoodResult = true;
|
||||||
|
|
||||||
|
mPreserveLength = preserveLength;
|
||||||
mCurTrackNum = 0;
|
mCurTrackNum = 0;
|
||||||
m_maxNewLength = 0.0;
|
m_maxNewLength = 0.0;
|
||||||
|
|
||||||
@ -107,14 +111,9 @@ bool EffectSoundTouch::ProcessWithTimeWarper(InitFunction initer, const TimeWarp
|
|||||||
if (!leftTrack->GetSelected())
|
if (!leftTrack->GetSelected())
|
||||||
return fallthrough();
|
return fallthrough();
|
||||||
|
|
||||||
//Get start and end times from track
|
//Get start and end times from selection
|
||||||
mCurT0 = leftTrack->GetStartTime();
|
mCurT0 = mT0;
|
||||||
mCurT1 = leftTrack->GetEndTime();
|
mCurT1 = mT1;
|
||||||
|
|
||||||
//Set the current bounds to whichever left marker is
|
|
||||||
//greater and whichever right marker is less
|
|
||||||
mCurT0 = wxMax(mT0, mCurT0);
|
|
||||||
mCurT1 = wxMin(mT1, mCurT1);
|
|
||||||
|
|
||||||
// Process only if the right marker is to the right of the left marker
|
// Process only if the right marker is to the right of the left marker
|
||||||
if (mCurT1 > mCurT0) {
|
if (mCurT1 > mCurT0) {
|
||||||
@ -250,9 +249,8 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
|||||||
outputTrack->Flush();
|
outputTrack->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take the output track and insert it in place of the original
|
// Transfer output samples to the original
|
||||||
// sample data
|
Finalize(track, outputTrack.get(), warper);
|
||||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), false, true, &warper);
|
|
||||||
|
|
||||||
double newLength = outputTrack->GetEndTime();
|
double newLength = outputTrack->GetEndTime();
|
||||||
m_maxNewLength = wxMax(m_maxNewLength, newLength);
|
m_maxNewLength = wxMax(m_maxNewLength, newLength);
|
||||||
@ -345,12 +343,10 @@ bool EffectSoundTouch::ProcessStereo(
|
|||||||
outputRightTrack->Flush();
|
outputRightTrack->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take the output tracks and insert in place of the original
|
// Transfer output samples to the original
|
||||||
// sample data.
|
Finalize(leftTrack, outputLeftTrack.get(), warper);
|
||||||
leftTrack->ClearAndPaste(
|
Finalize(rightTrack, outputRightTrack.get(), warper);
|
||||||
mCurT0, mCurT1, outputLeftTrack.get(), false, true, &warper);
|
|
||||||
rightTrack->ClearAndPaste(
|
|
||||||
mCurT0, mCurT1, outputRightTrack.get(), false, true, &warper);
|
|
||||||
|
|
||||||
// Track the longest result length
|
// Track the longest result length
|
||||||
double newLength = outputLeftTrack->GetEndTime();
|
double newLength = outputLeftTrack->GetEndTime();
|
||||||
@ -384,4 +380,57 @@ bool EffectSoundTouch::ProcessStereoResults(const size_t outputCount,
|
|||||||
return true;
|
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
|
#endif // USE_SOUNDTOUCH
|
||||||
|
@ -49,7 +49,9 @@ protected:
|
|||||||
// Effect implementation
|
// Effect implementation
|
||||||
|
|
||||||
using InitFunction = std::function< void(soundtouch::SoundTouch *soundtouch) >;
|
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;
|
std::unique_ptr<soundtouch::SoundTouch> mSoundTouch;
|
||||||
double mCurT0;
|
double mCurT0;
|
||||||
@ -69,6 +71,9 @@ private:
|
|||||||
bool ProcessStereoResults(const size_t outputCount,
|
bool ProcessStereoResults(const size_t outputCount,
|
||||||
WaveTrack* outputLeftTrack,
|
WaveTrack* outputLeftTrack,
|
||||||
WaveTrack* outputRightTrack);
|
WaveTrack* outputRightTrack);
|
||||||
|
void Finalize(WaveTrack* orig, WaveTrack* out, const TimeWarper &warper);
|
||||||
|
|
||||||
|
bool mPreserveLength;
|
||||||
|
|
||||||
int mCurTrackNum;
|
int mCurTrackNum;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user