1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-01-02 06:08:44 +01:00
Files
audacity/src/effects/StereoToMono.cpp
Paul Licameli 78be459fa1 Convert sampleCount <-> floating or -> long long explicitly ...
... A non-narrowing conversion out to long long is a necessity, but the
conversions to float and double are simply conveniences.

Conversion from floating is explicit, to avoid unintended consequences with
arithmetic operators, when later sampleCount ceases to be an alias for an
integral type.

Some conversions are not made explicit, where I expect to change the type of
the variable later to have mere size_t width.
2016-09-15 21:02:31 -04:00

181 lines
4.8 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()
{
}
// IdentInterface implementation
wxString EffectStereoToMono::GetSymbol()
{
return STEREOTOMONO_PLUGIN_SYMBOL;
}
wxString EffectStereoToMono::GetDescription()
{
return XO("Converts stereo tracks to mono");
}
// EffectIdentInterface 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 implementatino
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;
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
mLeftTrack = (WaveTrack *)iter.First();
bool refreshIter = false;
if(mLeftTrack)
{
// create a NEW WaveTrack to hold all of the output
AudacityProject *p = GetActiveProject();
mOutTrack = p->GetTrackFactory()->NewWaveTrack(floatSample, mLeftTrack->GetRate());
}
int count = 0;
while (mLeftTrack) {
if (mLeftTrack->GetKind() == Track::Wave &&
mLeftTrack->GetSelected() &&
mLeftTrack->GetLinked()) {
// Assume linked track is wave
mRightTrack = static_cast<WaveTrack*>(iter.Next());
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;
mOutTrack->Clear(mOutTrack->GetStartTime(), mOutTrack->GetEndTime());
// The right channel has been deleted, so we must restart from the beginning
refreshIter = true;
}
}
if (refreshIter) {
mLeftTrack = (WaveTrack *)iter.First();
refreshIter = false;
}
else {
mLeftTrack = (WaveTrack *)iter.Next();
}
count++;
}
mOutTrack.reset();
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
}
bool EffectStereoToMono::ProcessOne(int count)
{
float curLeftFrame;
float curRightFrame;
float curMonoFrame;
auto idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
auto index = mStart;
float *leftBuffer = new float[idealBlockLen];
float *rightBuffer = new float[idealBlockLen];
bool bResult = true;
while (index < mEnd) {
bResult &= mLeftTrack->Get((samplePtr)leftBuffer, floatSample, index, idealBlockLen);
bResult &= mRightTrack->Get((samplePtr)rightBuffer, 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;
}
bResult &= mOutTrack->Append((samplePtr)leftBuffer, floatSample, limit);
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
return false;
}
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
bResult &= mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
bResult &= mOutTrack->Flush();
bResult &= mLeftTrack->Paste(minStart, mOutTrack.get());
mLeftTrack->SetLinked(false);
mRightTrack->SetLinked(false);
mLeftTrack->SetChannel(Track::MonoChannel);
mOutputTracks->Remove(mRightTrack);
delete [] leftBuffer;
delete [] rightBuffer;
return bResult;
}
bool EffectStereoToMono::IsHidden()
{
return true;
}