mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-03 17:39:25 +02:00
Bug 1336 - Tracks -> Mix Stereo to Mono ignores envelope
This commit is contained in:
parent
01ccb518fd
commit
e8f9f4a7e9
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
#include <wx/intl.h>
|
#include <wx/intl.h>
|
||||||
|
|
||||||
|
#include "../Mix.h"
|
||||||
#include "../Project.h"
|
#include "../Project.h"
|
||||||
|
#include "../TimeTrack.h"
|
||||||
#include "../WaveTrack.h"
|
#include "../WaveTrack.h"
|
||||||
|
|
||||||
const ComponentInterfaceSymbol EffectStereoToMono::Symbol
|
const ComponentInterfaceSymbol EffectStereoToMono::Symbol
|
||||||
@ -81,89 +83,125 @@ bool EffectStereoToMono::Process()
|
|||||||
this->CopyInputTracks(); // Set up mOutputTracks.
|
this->CopyInputTracks(); // Set up mOutputTracks.
|
||||||
bool bGoodResult = true;
|
bool bGoodResult = true;
|
||||||
|
|
||||||
|
// Determine the total time (in samples) used by all of the target tracks
|
||||||
|
sampleCount totalTime = 0;
|
||||||
|
|
||||||
auto trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
|
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;
|
bool refreshIter = false;
|
||||||
|
|
||||||
int count = 0;
|
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
|
||||||
while ( trackRange.first != trackRange.second ) {
|
while (trackRange.first != trackRange.second)
|
||||||
mLeftTrack = *trackRange.first;
|
{
|
||||||
auto channels = TrackList::Channels( mLeftTrack );
|
auto left = *trackRange.first;
|
||||||
if (channels.size() != 2) {
|
auto channels = TrackList::Channels(left);
|
||||||
// TODO: more-than-two-channels
|
if (channels.size() > 1)
|
||||||
++ trackRange.first;
|
{
|
||||||
continue;
|
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 (refreshIter)
|
||||||
|
{
|
||||||
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) {
|
|
||||||
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
|
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
|
||||||
refreshIter = false;
|
refreshIter = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
++trackRange.first;
|
++trackRange.first;
|
||||||
|
}
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->ReplaceProcessedTracks(bGoodResult);
|
this->ReplaceProcessedTracks(bGoodResult);
|
||||||
return bGoodResult;
|
return bGoodResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EffectStereoToMono::ProcessOne(int count)
|
bool EffectStereoToMono::ProcessOne(sampleCount & curTime, sampleCount totalTime, WaveTrack *left, WaveTrack *right)
|
||||||
{
|
{
|
||||||
float curLeftFrame;
|
auto idealBlockLen = left->GetMaxBlockSize() * 2;
|
||||||
float curRightFrame;
|
|
||||||
float curMonoFrame;
|
|
||||||
|
|
||||||
auto idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
|
|
||||||
auto index = mStart;
|
|
||||||
Floats leftBuffer { idealBlockLen };
|
|
||||||
Floats rightBuffer{ idealBlockLen };
|
|
||||||
bool bResult = true;
|
bool bResult = true;
|
||||||
|
sampleCount processed = 0;
|
||||||
|
|
||||||
auto outTrack = mLeftTrack->EmptyCopy();
|
auto start = wxMin(left->TimeToLongSamples(left->GetStartTime()),
|
||||||
outTrack->ConvertToSampleFormat( floatSample );
|
right->TimeToLongSamples(right->GetStartTime()));
|
||||||
|
auto end = wxMin(left->TimeToLongSamples(left->GetEndTime()),
|
||||||
|
right->TimeToLongSamples(right->GetEndTime()));
|
||||||
|
|
||||||
while (index < mEnd) {
|
WaveTrackConstArray tracks;
|
||||||
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);
|
tracks.push_back(left->SharedPointer< const WaveTrack >());
|
||||||
bResult &= mRightTrack->Get((samplePtr)rightBuffer.get(), floatSample, index, idealBlockLen);
|
tracks.push_back(right->SharedPointer< const WaveTrack >());
|
||||||
auto limit = limitSampleBufferSize( idealBlockLen, mEnd - index );
|
|
||||||
for (decltype(limit) i = 0; i < limit; ++i) {
|
auto timeTrack = *(inputTracks()->Any<const TimeTrack>().begin());
|
||||||
index++;
|
|
||||||
curLeftFrame = leftBuffer[i];
|
Mixer mixer(tracks,
|
||||||
curRightFrame = rightBuffer[i];
|
true, // Throw to abort mix-and-render if read fails:
|
||||||
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
|
Mixer::WarpOptions(timeTrack ? timeTrack->GetEnvelope() : nullptr),
|
||||||
leftBuffer[i] = curMonoFrame;
|
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);
|
outTrack->Append(buffer, floatSample, blockLen);
|
||||||
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
|
curTime += blockLen;
|
||||||
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
|
if (TotalProgress(curTime.as_double() / totalTime.as_double()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
outTrack->Flush();
|
outTrack->Flush();
|
||||||
mLeftTrack->Paste(minStart, outTrack.get());
|
|
||||||
mOutputTracks->GroupChannels( *mLeftTrack, 1 );
|
double minStart = wxMin(left->GetStartTime(), right->GetStartTime());
|
||||||
mOutputTracks->Remove(mRightTrack);
|
left->Clear(left->GetStartTime(), left->GetEndTime());
|
||||||
|
left->Paste(minStart, outTrack.get());
|
||||||
|
mOutputTracks->GroupChannels(*left, 1);
|
||||||
|
mOutputTracks->Remove(right);
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
@ -172,4 +210,3 @@ bool EffectStereoToMono::IsHidden()
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +44,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
// EffectStereoToMono implementation
|
// 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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user