Bug 1336 - Tracks -> Mix Stereo to Mono ignores envelope

This commit is contained in:
Leland Lucius 2020-04-17 14:52:31 -05:00
parent 01ccb518fd
commit e8f9f4a7e9
2 changed files with 99 additions and 67 deletions

View File

@ -19,7 +19,9 @@
#include <wx/intl.h>
#include "../Mix.h"
#include "../Project.h"
#include "../TimeTrack.h"
#include "../WaveTrack.h"
const ComponentInterfaceSymbol EffectStereoToMono::Symbol
@ -81,89 +83,125 @@ bool EffectStereoToMono::Process()
this->CopyInputTracks(); // Set up mOutputTracks.
bool bGoodResult = true;
// Determine the total time (in samples) used by all of the target tracks
sampleCount totalTime = 0;
auto trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
while (trackRange.first != trackRange.second)
{
auto left = *trackRange.first;
auto channels = TrackList::Channels(left);
if (channels.size() > 1)
{
auto right = *channels.rbegin();
if (left->GetRate() == right->GetRate())
{
auto start = wxMin(left->TimeToLongSamples(left->GetStartTime()),
right->TimeToLongSamples(right->GetStartTime()));
auto end = wxMin(left->TimeToLongSamples(left->GetEndTime()),
right->TimeToLongSamples(right->GetEndTime()));
totalTime += (end - start);
}
}
++trackRange.first;
}
// Process each stereo track
sampleCount curTime = 0;
bool refreshIter = false;
int count = 0;
while ( trackRange.first != trackRange.second ) {
mLeftTrack = *trackRange.first;
auto channels = TrackList::Channels( mLeftTrack );
if (channels.size() != 2) {
// TODO: more-than-two-channels
++ trackRange.first;
continue;
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
while (trackRange.first != trackRange.second)
{
auto left = *trackRange.first;
auto channels = TrackList::Channels(left);
if (channels.size() > 1)
{
auto right = *channels.rbegin();
if (left->GetRate() == right->GetRate())
{
bGoodResult = ProcessOne(curTime, totalTime, left, right);
if (!bGoodResult)
{
break;
}
// The right channel has been deleted, so we must restart from the beginning
refreshIter = true;
}
}
mRightTrack = * channels.rbegin();
if ((mLeftTrack->GetRate() == mRightTrack->GetRate())) {
auto leftTrackStart = mLeftTrack->TimeToLongSamples(mLeftTrack->GetStartTime());
auto rightTrackStart = mRightTrack->TimeToLongSamples(mRightTrack->GetStartTime());
mStart = wxMin(leftTrackStart, rightTrackStart);
auto leftTrackEnd = mLeftTrack->TimeToLongSamples(mLeftTrack->GetEndTime());
auto rightTrackEnd = mRightTrack->TimeToLongSamples(mRightTrack->GetEndTime());
mEnd = wxMax(leftTrackEnd, rightTrackEnd);
bGoodResult = ProcessOne(count);
if (!bGoodResult)
break;
// The right channel has been deleted, so we must restart from the beginning
refreshIter = true;
}
if (refreshIter) {
if (refreshIter)
{
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
refreshIter = false;
}
else
{
++trackRange.first;
count++;
}
}
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
}
bool EffectStereoToMono::ProcessOne(int count)
bool EffectStereoToMono::ProcessOne(sampleCount & curTime, sampleCount totalTime, WaveTrack *left, WaveTrack *right)
{
float curLeftFrame;
float curRightFrame;
float curMonoFrame;
auto idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
auto index = mStart;
Floats leftBuffer { idealBlockLen };
Floats rightBuffer{ idealBlockLen };
auto idealBlockLen = left->GetMaxBlockSize() * 2;
bool bResult = true;
sampleCount processed = 0;
auto outTrack = mLeftTrack->EmptyCopy();
outTrack->ConvertToSampleFormat( floatSample );
auto start = wxMin(left->TimeToLongSamples(left->GetStartTime()),
right->TimeToLongSamples(right->GetStartTime()));
auto end = wxMin(left->TimeToLongSamples(left->GetEndTime()),
right->TimeToLongSamples(right->GetEndTime()));
while (index < mEnd) {
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);
bResult &= mRightTrack->Get((samplePtr)rightBuffer.get(), floatSample, index, idealBlockLen);
auto limit = limitSampleBufferSize( idealBlockLen, mEnd - index );
for (decltype(limit) i = 0; i < limit; ++i) {
index++;
curLeftFrame = leftBuffer[i];
curRightFrame = rightBuffer[i];
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
leftBuffer[i] = curMonoFrame;
WaveTrackConstArray tracks;
tracks.push_back(left->SharedPointer< const WaveTrack >());
tracks.push_back(right->SharedPointer< const WaveTrack >());
auto timeTrack = *(inputTracks()->Any<const TimeTrack>().begin());
Mixer mixer(tracks,
true, // Throw to abort mix-and-render if read fails:
Mixer::WarpOptions(timeTrack ? timeTrack->GetEnvelope() : nullptr),
start.as_double(),
end.as_double(),
1,
idealBlockLen,
false, // Not interleaved
mProjectRate,
floatSample);
auto outTrack = left->EmptyCopy();
outTrack->ConvertToSampleFormat(floatSample);
while (auto blockLen = mixer.Process(idealBlockLen))
{
auto buffer = mixer.GetBuffer();
for (auto i = 0; i < blockLen; i++)
{
((float *)buffer)[i] /= 2.0;
}
outTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit);
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
return false;
}
outTrack->Append(buffer, floatSample, blockLen);
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
curTime += blockLen;
if (TotalProgress(curTime.as_double() / totalTime.as_double()))
{
return false;
}
}
outTrack->Flush();
mLeftTrack->Paste(minStart, outTrack.get());
mOutputTracks->GroupChannels( *mLeftTrack, 1 );
mOutputTracks->Remove(mRightTrack);
double minStart = wxMin(left->GetStartTime(), right->GetStartTime());
left->Clear(left->GetStartTime(), left->GetEndTime());
left->Paste(minStart, outTrack.get());
mOutputTracks->GroupChannels(*left, 1);
mOutputTracks->Remove(right);
return bResult;
}
@ -172,4 +210,3 @@ bool EffectStereoToMono::IsHidden()
{
return true;
}

View File

@ -44,13 +44,8 @@ public:
private:
// EffectStereoToMono implementation
bool ProcessOne(int count);
bool ProcessOne(sampleCount & curTime, sampleCount totalTime, WaveTrack *left, WaveTrack *right);
private:
sampleCount mStart;
sampleCount mEnd;
WaveTrack *mLeftTrack;
WaveTrack *mRightTrack;
};
#endif