mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-08 14:13:57 +01:00
... 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.
141 lines
4.3 KiB
C++
141 lines
4.3 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
SimpleMono.cpp
|
|
|
|
Dominic Mazzoni
|
|
|
|
*******************************************************************//**
|
|
\class EffectSimpleMono
|
|
\brief An abstract Effect class that simplifies the implementation of a basic
|
|
monaural effect. Inherit from it if your effect just modifies
|
|
a single track in place and doesn't care how many samples
|
|
it gets at a time.
|
|
|
|
Your derived class only needs to implement
|
|
GetEffectName, GetEffectAction, and ProcessSimpleMono.
|
|
|
|
*//*******************************************************************/
|
|
|
|
|
|
#include "../Audacity.h"
|
|
|
|
#include "SimpleMono.h"
|
|
#include "../WaveTrack.h"
|
|
|
|
#include <math.h>
|
|
|
|
bool EffectSimpleMono::Process()
|
|
{
|
|
//Iterate over each track
|
|
this->CopyInputTracks(); // Set up mOutputTracks.
|
|
bool bGoodResult = true;
|
|
|
|
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
|
|
WaveTrack* pOutWaveTrack = (WaveTrack*)(iter.First());
|
|
mCurTrackNum = 0;
|
|
while (pOutWaveTrack != NULL)
|
|
{
|
|
//Get start and end times from track
|
|
double trackStart = pOutWaveTrack->GetStartTime();
|
|
double trackEnd = pOutWaveTrack->GetEndTime();
|
|
|
|
//Set the current bounds to whichever left marker is
|
|
//greater and whichever right marker is less:
|
|
mCurT0 = mT0 < trackStart? trackStart: mT0;
|
|
mCurT1 = mT1 > trackEnd? trackEnd: mT1;
|
|
|
|
// Process only if the right marker is to the right of the left marker
|
|
if (mCurT1 > mCurT0) {
|
|
|
|
//Transform the marker timepoints to samples
|
|
auto start = pOutWaveTrack->TimeToLongSamples(mCurT0);
|
|
auto end = pOutWaveTrack->TimeToLongSamples(mCurT1);
|
|
|
|
//Get the track rate and samples
|
|
mCurRate = pOutWaveTrack->GetRate();
|
|
mCurChannel = pOutWaveTrack->GetChannel();
|
|
|
|
//NewTrackSimpleMono() will returns true by default
|
|
//ProcessOne() processes a single track
|
|
if (!NewTrackSimpleMono() || !ProcessOne(pOutWaveTrack, start, end))
|
|
{
|
|
bGoodResult = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Iterate to the next track
|
|
pOutWaveTrack = (WaveTrack*)(iter.Next());
|
|
mCurTrackNum++;
|
|
}
|
|
|
|
this->ReplaceProcessedTracks(bGoodResult);
|
|
return bGoodResult;
|
|
}
|
|
|
|
|
|
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
|
//and executes ProcessSimpleMono on these blocks
|
|
bool EffectSimpleMono::ProcessOne(WaveTrack * track,
|
|
sampleCount start, sampleCount end)
|
|
{
|
|
//Get the length of the buffer (as double). len is
|
|
//used simple to calculate a progress meter, so it is easier
|
|
//to make it a double now than it is to do it later
|
|
auto len = (end - start).as_double();
|
|
|
|
//Initiate a processing buffer. This buffer will (most likely)
|
|
//be shorter than the length of the track being processed.
|
|
float *buffer = new float[track->GetMaxBlockSize()];
|
|
|
|
//Go through the track one buffer at a time. s counts which
|
|
//sample the current buffer starts at.
|
|
auto s = start;
|
|
while (s < end) {
|
|
//Get a block of samples (smaller than the size of the buffer)
|
|
//Adjust the block size if it is the final block in the track
|
|
const auto block =
|
|
limitSampleBufferSize( track->GetBestBlockSize(s), end - s );
|
|
|
|
//Get the samples from the track and put them in the buffer
|
|
track->Get((samplePtr) buffer, floatSample, s, block);
|
|
|
|
//Process the buffer. If it fails, clean up and exit.
|
|
if (!ProcessSimpleMono(buffer, block)) {
|
|
delete[]buffer;
|
|
|
|
//Return false because the effect failed.
|
|
return false;
|
|
}
|
|
|
|
//Processing succeeded. copy the newly-changed samples back
|
|
//onto the track.
|
|
track->Set((samplePtr) buffer, floatSample, s, block);
|
|
|
|
//Increment s one blockfull of samples
|
|
s += block;
|
|
|
|
//Update the Progress meter
|
|
if (TrackProgress(mCurTrackNum,
|
|
(s - start).as_double() /
|
|
len)) {
|
|
delete[]buffer;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//Clean up the buffer
|
|
delete[]buffer;
|
|
|
|
//Return true because the effect processing succeeded.
|
|
return true;
|
|
}
|
|
|
|
//null implementation of NewTrackSimpleMono
|
|
bool EffectSimpleMono::NewTrackSimpleMono()
|
|
{
|
|
return true;
|
|
}
|