1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-20 06:10:06 +02:00
audacity/src/effects/StereoToMono.cpp

173 lines
4.7 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
StereoToMono.cpp
Lynn Allan
*******************************************************************//**
\class EffectStereoToMono
\brief An Effect.
*//*******************************************************************/
#include "../Audacity.h"
// For compilers that support precompilation, includes "wx.h".
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
// Include your minimal set of headers here, or wx.h
#include <wx/wx.h>
#endif
#include <math.h>
#include "StereoToMono.h"
#include "../Project.h"
EffectStereoToMono::EffectStereoToMono()
{
Init();
}
bool EffectStereoToMono::Init()
{
return true;
}
void EffectStereoToMono::End()
{
}
//TODO: There are a lot of places where a track is being checked
// to see if it is stereo. Consolidate these
bool EffectStereoToMono::CheckWhetherSkipEffect()
{
TrackListOfKindIterator iter(Track::Wave, mTracks);
WaveTrack *t = (WaveTrack*)iter.First();
while (t) {
if (t->GetLinked()) {
return false;
}
t = (WaveTrack *)iter.Next();
}
return true;
}
bool EffectStereoToMono::ProcessOne(int count)
{
float curLeftFrame;
float curRightFrame;
float curMonoFrame;
sampleCount idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
sampleCount index = mStart;
float *leftBuffer = new float[idealBlockLen];
float *rightBuffer = new float[idealBlockLen];
bool rc;
while (index < mEnd) {
rc = mLeftTrack->Get((samplePtr)leftBuffer, floatSample, index, idealBlockLen);
rc = mRightTrack->Get((samplePtr)rightBuffer, floatSample, index, idealBlockLen);
sampleCount limit = idealBlockLen;
if ((index + idealBlockLen) > mEnd) {
limit = mEnd - index;
}
for (sampleCount i = 0; i < limit; ++i) {
index++;
curLeftFrame = leftBuffer[i];
curRightFrame = rightBuffer[i];
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
leftBuffer[i] = curMonoFrame;
}
rc = mOutTrack->Append((samplePtr)leftBuffer, floatSample, limit);
if (TrackProgress(count, 2.*((double)index / (double)(mEnd - mStart))))
return false;
}
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
mOutTrack->Flush();
mLeftTrack->HandlePaste(minStart, mOutTrack);
mLeftTrack->SetLinked(false);
mRightTrack->SetLinked(false);
mLeftTrack->SetChannel(Track::MonoChannel);
mOutputTracks->Remove(mRightTrack);
delete mRightTrack;
delete [] leftBuffer;
delete [] rightBuffer;
return true;
}
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);
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()) {
mRightTrack = (WaveTrack *)iter.Next();
if ((mLeftTrack->GetRate() == mRightTrack->GetRate())) {
sampleCount leftTrackStart = mLeftTrack->TimeToLongSamples(mLeftTrack->GetStartTime());
sampleCount rightTrackStart = mRightTrack->TimeToLongSamples(mRightTrack->GetStartTime());
mStart = wxMin(leftTrackStart, rightTrackStart);
sampleCount leftTrackEnd = mLeftTrack->TimeToLongSamples(mLeftTrack->GetEndTime());
sampleCount 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++;
}
if(mOutTrack)
delete mOutTrack;
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;
}