diff --git a/src/effects/StereoToMono.cpp b/src/effects/StereoToMono.cpp index a1d499e11..49310f528 100644 --- a/src/effects/StereoToMono.cpp +++ b/src/effects/StereoToMono.cpp @@ -19,7 +19,9 @@ #include +#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().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; } - diff --git a/src/effects/StereoToMono.h b/src/effects/StereoToMono.h index 30b4232e4..811c8ba61 100644 --- a/src/effects/StereoToMono.h +++ b/src/effects/StereoToMono.h @@ -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