mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-02 17:23:18 +02:00
Remove EXPERIMENTAL_TRUNC_SILENCE #ifdefs since it is no longer experimental.
This commit is contained in:
parent
1af35d4168
commit
1ddee72498
@ -150,7 +150,4 @@
|
||||
//#define AUTOMATED_INPUT_LEVEL_ADJUSTMENT
|
||||
#endif
|
||||
|
||||
// AWD: new Truncate Silence code
|
||||
#define EXPERIMENTAL_TRUNC_SILENCE
|
||||
|
||||
#endif
|
||||
|
@ -119,342 +119,6 @@ bool EffectTruncSilence::TransferParameters( Shuttle & shuttle )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef EXPERIMENTAL_TRUNC_SILENCE
|
||||
#define QUARTER_SECOND_MS 250
|
||||
bool EffectTruncSilence::Process()
|
||||
{
|
||||
SelectedTrackListOfKindIterator iter(Track::Wave, mTracks);
|
||||
WaveTrack *t;
|
||||
double t0 = mT0;
|
||||
double t1 = mT1;
|
||||
int tndx;
|
||||
int tcount = 0;
|
||||
int fr;
|
||||
|
||||
// Init using first track
|
||||
t = (WaveTrack *) iter.First();
|
||||
double rate = t->GetRate();
|
||||
sampleCount blockLen = t->GetMaxBlockSize();
|
||||
|
||||
// Get the left and right bounds for all tracks
|
||||
while (t) {
|
||||
// Make sure all tracks have the same sample rate
|
||||
if (rate != t->GetRate()) {
|
||||
wxMessageBox(_("All tracks must have the same sample rate"), _("Truncate Silence"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Count the tracks
|
||||
tcount++;
|
||||
|
||||
// Set the current bounds to whichever left marker is
|
||||
// greater and whichever right marker is less
|
||||
t0 = wxMax(mT0, t->GetStartTime());
|
||||
t1 = wxMin(mT1, t->GetEndTime());
|
||||
|
||||
// Use the smallest block size of all the tracks
|
||||
blockLen = wxMin(blockLen, t->GetMaxBlockSize());
|
||||
|
||||
// Iterate to the next track
|
||||
t = (WaveTrack*) iter.Next();
|
||||
}
|
||||
|
||||
// Just a sanity check, really it should be much higher
|
||||
if(blockLen < 4*mBlendFrameCount)
|
||||
blockLen = 4*mBlendFrameCount;
|
||||
|
||||
// Transform the marker timepoints to samples
|
||||
t = (WaveTrack *) iter.First();
|
||||
sampleCount start = t->TimeToLongSamples(t0);
|
||||
sampleCount end = t->TimeToLongSamples(t1);
|
||||
|
||||
// Bigger buffers reduce 'reset'
|
||||
//blockLen *= 8;
|
||||
// Stress-test the logic for cutting samples through block endpoints
|
||||
//blockLen /= 8;
|
||||
|
||||
// Set thresholds
|
||||
// We have a lower bound on the amount of silence we chop out at a time
|
||||
// to avoid chopping up low frequency sounds. We're good down to 10Hz
|
||||
// if we use 100ms.
|
||||
const float minTruncMs = 1.0f;
|
||||
double truncDbSilenceThreshold = Enums::Db2Signal[mTruncDbChoiceIndex];
|
||||
int truncInitialAllowedSilentSamples =
|
||||
int((wxMax( mTruncInitialAllowedSilentMs, minTruncMs) * rate) / 1000.0);
|
||||
int truncLongestAllowedSilentSamples =
|
||||
int((wxMax( mTruncLongestAllowedSilentMs, minTruncMs) * rate) / 1000.0);
|
||||
|
||||
// Require at least 4 samples for lengths
|
||||
if(truncInitialAllowedSilentSamples < 4)
|
||||
truncInitialAllowedSilentSamples = 4;
|
||||
if(truncLongestAllowedSilentSamples < 4)
|
||||
truncLongestAllowedSilentSamples = 4;
|
||||
|
||||
// If the cross-fade is longer than the minimum length,
|
||||
// then limit the cross-fade length to the minimum length
|
||||
// This allows us to have reasonable cross-fade by default
|
||||
// and still allow for 1ms minimum lengths
|
||||
if(truncInitialAllowedSilentSamples < mBlendFrameCount)
|
||||
mBlendFrameCount = truncInitialAllowedSilentSamples;
|
||||
if(truncLongestAllowedSilentSamples < mBlendFrameCount)
|
||||
mBlendFrameCount = truncLongestAllowedSilentSamples;
|
||||
|
||||
// For sake of efficiency, don't let blockLen be less than double the longest silent samples
|
||||
// up until a sane limit of 1Meg samples
|
||||
while((blockLen > 0) && (blockLen < truncLongestAllowedSilentSamples*2) && (blockLen < 1048576)) {
|
||||
blockLen *= 2;
|
||||
}
|
||||
// Don't allow either value to be more than half of the block length
|
||||
if(truncLongestAllowedSilentSamples > blockLen/2)
|
||||
truncLongestAllowedSilentSamples = blockLen/2;
|
||||
if(truncInitialAllowedSilentSamples > truncLongestAllowedSilentSamples)
|
||||
truncInitialAllowedSilentSamples = truncLongestAllowedSilentSamples;
|
||||
|
||||
// We use the 'longest' variable as additive to the 'initial' variable
|
||||
truncLongestAllowedSilentSamples -= truncInitialAllowedSilentSamples;
|
||||
|
||||
// Perform the crossfade half-way through the minimum removed silence duration
|
||||
int rampInFrames = (truncInitialAllowedSilentSamples + mBlendFrameCount) / 2;
|
||||
if(rampInFrames > truncInitialAllowedSilentSamples)
|
||||
rampInFrames = truncInitialAllowedSilentSamples;
|
||||
|
||||
// Allocate buffers
|
||||
float **buffer = new float*[tcount];
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
buffer[tndx] = new float[blockLen];
|
||||
}
|
||||
|
||||
// Start processing
|
||||
//Track::All is needed because this effect has clear functionality
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
SelectedTrackListOfKindIterator iterOut(Track::Wave, mOutputTracks);
|
||||
|
||||
sampleCount index = start;
|
||||
sampleCount outTrackOffset = start;
|
||||
bool cancelled = false;
|
||||
// Reset
|
||||
bool ignoringFrames = false;
|
||||
bool truncToMinimum = true; // Ignore the initial samples until we get above the noise floor
|
||||
sampleCount consecutiveSilentFrames = 0;
|
||||
sampleCount truncIndex = 0;
|
||||
sampleCount i = 0;
|
||||
sampleCount keep;
|
||||
|
||||
while (index < end) {
|
||||
|
||||
// Limit size of current block if we've reached the end
|
||||
sampleCount count = blockLen-i;
|
||||
if ((index + count) > end) {
|
||||
count = end - index;
|
||||
}
|
||||
|
||||
// Fill the buffers
|
||||
tndx = 0;
|
||||
t = (WaveTrack *) iter.First();
|
||||
while (t) {
|
||||
t->Get((samplePtr)(buffer[tndx++]+i), floatSample, index, count);
|
||||
t = (WaveTrack *) iter.Next();
|
||||
}
|
||||
|
||||
// Shift over to account for samples remaining from prior block
|
||||
sampleCount limit = count+i;
|
||||
|
||||
// Look for silences in current block
|
||||
for ( ; i < limit; i++) {
|
||||
|
||||
// Is current frame in all tracks below threshold
|
||||
bool below = true;
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
if (fabs(buffer[tndx][i]) >= truncDbSilenceThreshold) {
|
||||
below = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Make sure we cross-fade and output the last silence
|
||||
// so we get a smooth transition into whatever follows the selected region
|
||||
// Also set the 'truncToMinimum' flag so that the last silence is truncated to the minimum amount
|
||||
if(below && ((index+i+1) == end)) {
|
||||
below = false;
|
||||
truncToMinimum = true;
|
||||
}
|
||||
|
||||
// Count frame if it's below threshold
|
||||
if (below) {
|
||||
consecutiveSilentFrames++;
|
||||
|
||||
// Ignore this frame (equivalent to cutting it)
|
||||
// otherwise, keep sample to be part of allowed silence
|
||||
if (consecutiveSilentFrames > truncInitialAllowedSilentSamples) {
|
||||
ignoringFrames = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ignoringFrames == true) {
|
||||
// Scale the consectiveSilentFrames so we keep a silence duration
|
||||
// which is proportional to the original silence up to the limit
|
||||
keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples;
|
||||
keep /= mSilenceCompressRatio;
|
||||
|
||||
// The first and last samples always get truncated to the minimum amount
|
||||
if(truncToMinimum == true)
|
||||
keep = 0;
|
||||
if(keep > truncLongestAllowedSilentSamples)
|
||||
keep = truncLongestAllowedSilentSamples;
|
||||
if(keep < 0)
|
||||
keep = 0;
|
||||
|
||||
// Compute the location of the cross-fade to be halfway through the silence
|
||||
// with restriction to the samples we still have available to use
|
||||
rampInFrames = (truncInitialAllowedSilentSamples - keep + mBlendFrameCount) / 2;
|
||||
if(rampInFrames > truncInitialAllowedSilentSamples)
|
||||
rampInFrames = truncInitialAllowedSilentSamples;
|
||||
if(rampInFrames < mBlendFrameCount)
|
||||
rampInFrames = mBlendFrameCount;
|
||||
|
||||
// Include the cross-fade samples in the count to make the loop logic easier
|
||||
keep += rampInFrames;
|
||||
truncIndex -= rampInFrames;
|
||||
if(truncIndex < 0) {
|
||||
// This happens when we have silence overlapping a block boundary
|
||||
keep += truncIndex;
|
||||
if(keep < 0)
|
||||
keep = 0;
|
||||
truncIndex = 0;
|
||||
}
|
||||
// back up for cross-fade
|
||||
sampleCount curOffset = i - keep;
|
||||
|
||||
if(curOffset < 0) {
|
||||
// This should never happen, but just in case...
|
||||
keep += curOffset - rampInFrames;
|
||||
if(keep < mBlendFrameCount)
|
||||
keep = mBlendFrameCount;
|
||||
curOffset = 0;
|
||||
}
|
||||
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
// Cross fade the cut point
|
||||
for (fr = 0; fr < mBlendFrameCount; fr++) {
|
||||
buffer[tndx][truncIndex+fr] = ((mBlendFrameCount-fr)*buffer[tndx][truncIndex+fr] + fr*buffer[tndx][curOffset + fr]) / mBlendFrameCount;
|
||||
}
|
||||
// Append the 'keep' samples, if any
|
||||
for ( ; fr < keep; fr++) {
|
||||
buffer[tndx][truncIndex+fr] = buffer[tndx][curOffset + fr];
|
||||
}
|
||||
}
|
||||
truncIndex += keep;
|
||||
}
|
||||
consecutiveSilentFrames = 0;
|
||||
ignoringFrames = false;
|
||||
truncToMinimum = false;
|
||||
}
|
||||
|
||||
// Can get here either because > dbThreshold
|
||||
// or silence duration isn't longer than allowed
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
buffer[tndx][truncIndex] = buffer[tndx][i];
|
||||
}
|
||||
truncIndex++;
|
||||
}
|
||||
|
||||
// Update tracks if any samples were removed, now or before
|
||||
if (outTrackOffset + truncIndex != index + limit) {
|
||||
// Put updated sample back into output tracks.
|
||||
tndx = 0;
|
||||
t = (WaveTrack *) iterOut.First();
|
||||
while (t) {
|
||||
t->Set((samplePtr)buffer[tndx++], floatSample, outTrackOffset, truncIndex);
|
||||
t = (WaveTrack *) iterOut.Next();
|
||||
}
|
||||
}
|
||||
|
||||
// If currently in a silent section, retain samples for the next pass
|
||||
if(consecutiveSilentFrames > mBlendFrameCount) {
|
||||
if (ignoringFrames == true) {
|
||||
// Retain only what we need for truncating the silence
|
||||
keep = consecutiveSilentFrames-truncInitialAllowedSilentSamples;
|
||||
if(keep > (truncLongestAllowedSilentSamples+mBlendFrameCount))
|
||||
keep = truncLongestAllowedSilentSamples+mBlendFrameCount;
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
// Cross fade the cut point
|
||||
for(fr = 0; fr < mBlendFrameCount; fr++) {
|
||||
buffer[tndx][fr] = ((mBlendFrameCount-fr)*buffer[tndx][truncIndex-mBlendFrameCount+fr]
|
||||
+ fr*buffer[tndx][i-keep+fr]) / mBlendFrameCount;
|
||||
}
|
||||
for( ; fr < keep; fr++) {
|
||||
buffer[tndx][fr] = buffer[tndx][i-keep+fr];
|
||||
}
|
||||
}
|
||||
// Update the output index, less what we are retaining for next time
|
||||
outTrackOffset += truncIndex - mBlendFrameCount;
|
||||
// Append the following buffer to the existing data
|
||||
i = keep;
|
||||
truncIndex = mBlendFrameCount;
|
||||
} else {
|
||||
// Retain the silent samples for the next buffer
|
||||
keep = consecutiveSilentFrames;
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
for(fr=0 ; fr < keep; fr++) {
|
||||
buffer[tndx][fr] = buffer[tndx][i-keep+fr];
|
||||
}
|
||||
}
|
||||
// Update the output index, less what we are retaining for next time
|
||||
outTrackOffset += truncIndex - keep;
|
||||
// Append the following buffer to the existing data
|
||||
i = keep;
|
||||
truncIndex = keep;
|
||||
}
|
||||
} else {
|
||||
// Maintain output index
|
||||
outTrackOffset += truncIndex;
|
||||
// Reset the buffer pointers to the beginning
|
||||
i = 0;
|
||||
truncIndex = 0;
|
||||
consecutiveSilentFrames = 0;
|
||||
}
|
||||
|
||||
// Update progress and bail if user cancelled
|
||||
cancelled = TrackProgress(0, ((double)index / (double)end));
|
||||
if (cancelled) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Bump to next block
|
||||
index += count;
|
||||
}
|
||||
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
// Remove stale data at end of output tracks.
|
||||
if (!cancelled && (outTrackOffset < end)) {
|
||||
t = (WaveTrack *) iterOut.First();
|
||||
while(t) {
|
||||
t->Clear(outTrackOffset / rate, t1);
|
||||
t = (WaveTrack *) iterOut.Next();
|
||||
}
|
||||
|
||||
t1 = outTrackOffset / rate;
|
||||
}
|
||||
|
||||
// Free buffers
|
||||
for (tndx = 0; tndx < tcount; tndx++) {
|
||||
delete [] buffer[tndx];
|
||||
}
|
||||
delete [] buffer;
|
||||
|
||||
mT0 = t0;
|
||||
mT1 = t1;
|
||||
|
||||
this->ReplaceProcessedTracks(!cancelled);
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
#else // defined(EXPERIMENTAL_TRUNC_SILENCE)
|
||||
|
||||
// AWD: this is the new version!
|
||||
bool EffectTruncSilence::Process()
|
||||
{
|
||||
// Typical fraction of total time taken by detection (better to guess low)
|
||||
@ -823,8 +487,6 @@ void EffectTruncSilence::Intersect(RegionList &dest, const RegionList &src)
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EXPERIMENTAL_TRUNC_SILENCE
|
||||
|
||||
void EffectTruncSilence::BlendFrames(float* buffer, int blendFrameCount, int leftIndex, int rightIndex)
|
||||
{
|
||||
float* bufOutput = &buffer[leftIndex];
|
||||
|
@ -61,9 +61,7 @@ public:
|
||||
private:
|
||||
//ToDo ... put BlendFrames in Effects, Project, or other class
|
||||
void BlendFrames(float* buffer, int leftIndex, int rightIndex, int blendFrameCount);
|
||||
#ifdef EXPERIMENTAL_TRUNC_SILENCE
|
||||
void Intersect(RegionList &dest, const RegionList &src);
|
||||
#endif
|
||||
|
||||
private:
|
||||
sampleCount mBlendFrameCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user