audacia/src/effects/StereoToMono.cpp

171 lines
4.5 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
StereoToMono.cpp
Lynn Allan
*******************************************************************//**
\class EffectStereoToMono
\brief An Effect to convert stereo to mono.
*//*******************************************************************/
#include "../Audacity.h"
#include "StereoToMono.h"
#include <wx/intl.h>
#include "../Project.h"
#include "../WaveTrack.h"
EffectStereoToMono::EffectStereoToMono()
{
}
EffectStereoToMono::~EffectStereoToMono()
{
}
// ComponentInterface implementation
ComponentInterfaceSymbol EffectStereoToMono::GetSymbol()
{
return STEREOTOMONO_PLUGIN_SYMBOL;
}
TranslatableString EffectStereoToMono::GetDescription()
{
return XO("Converts stereo tracks to mono");
}
// EffectDefinitionInterface implementation
EffectType EffectStereoToMono::GetType()
{
// Really EffectTypeProcess, but this prevents it from showing in the Effect Menu
return EffectTypeHidden;
}
bool EffectStereoToMono::IsInteractive()
{
return false;
}
// EffectClientInterface implementation
unsigned EffectStereoToMono::GetAudioInCount()
{
return 2;
}
unsigned EffectStereoToMono::GetAudioOutCount()
{
return 1;
}
// Effect implementation
bool EffectStereoToMono::Process()
{
// Do not use mWaveTracks here. We will possibly DELETE tracks,
// so we must use the "real" tracklist.
this->CopyInputTracks(); // Set up mOutputTracks.
bool bGoodResult = true;
auto trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
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;
}
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) {
trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
refreshIter = false;
}
else
++trackRange.first;
count++;
}
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
}
bool EffectStereoToMono::ProcessOne(int count)
{
float curLeftFrame;
float curRightFrame;
float curMonoFrame;
auto idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
auto index = mStart;
Floats leftBuffer { idealBlockLen };
Floats rightBuffer{ idealBlockLen };
bool bResult = true;
AudacityProject *p = GetActiveProject();
auto outTrack =
TrackFactory::Get( *p ).NewWaveTrack(floatSample, mLeftTrack->GetRate());
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;
}
outTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit);
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
return false;
}
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
outTrack->Flush();
mLeftTrack->Paste(minStart, outTrack.get());
mOutputTracks->GroupChannels( *mLeftTrack, 1 );
mOutputTracks->Remove(mRightTrack);
return bResult;
}
bool EffectStereoToMono::IsHidden()
{
return true;
}