mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-28 06:08:40 +02:00
Certain short-lived things don't need to persist as member variables...
... so that there will be less need for save-and-restore RAII code
This commit is contained in:
commit
97fd8f5689
221
src/Envelope.cpp
221
src/Envelope.cpp
@ -57,27 +57,19 @@ Envelope::Envelope()
|
||||
mDB = true;
|
||||
mDefaultValue = 1.0;
|
||||
mDragPoint = -1;
|
||||
mDirty = false;
|
||||
mIsDeleting = false;
|
||||
mMirror = true;
|
||||
|
||||
mMinValue = 1.0e-7;
|
||||
mMaxValue = 2.0;
|
||||
|
||||
mButton = wxMOUSE_BTN_NONE;
|
||||
|
||||
mSearchGuess = -1;
|
||||
|
||||
mDragPointValid = false;
|
||||
}
|
||||
|
||||
Envelope::~Envelope()
|
||||
{
|
||||
}
|
||||
|
||||
void Envelope::Mirror(bool mirror)
|
||||
{
|
||||
mMirror = mirror;
|
||||
}
|
||||
|
||||
/// Rescale function for time tracks (could also be used for other tracks though).
|
||||
/// This is used to load old time track project files where the envelope used a 0 to 1
|
||||
/// range instead of storing the actual time track values. This function will change the range of the envelope
|
||||
@ -112,6 +104,84 @@ void Envelope::Flatten(double value)
|
||||
mDefaultValue = ClampValue(value);
|
||||
}
|
||||
|
||||
void Envelope::SetDragPoint(int dragPoint)
|
||||
{
|
||||
mDragPoint = std::max(-1, std::min(int(mEnv.size() - 1), dragPoint));
|
||||
mDragPointValid = (mDragPoint >= 0);
|
||||
}
|
||||
|
||||
void Envelope::SetDragPointValid(bool valid)
|
||||
{
|
||||
mDragPointValid = (valid && mDragPoint >= 0);
|
||||
if (mDragPoint >= 0 && !valid) {
|
||||
// We're going to be deleting the point; On
|
||||
// screen we show this by having the envelope move to
|
||||
// the position it will have after deletion of the point.
|
||||
// Without deleting the point we move it left or right
|
||||
// to the same position as the previous or next point.
|
||||
|
||||
static const double big = std::numeric_limits<double>::max();
|
||||
auto size = mEnv.size();
|
||||
|
||||
if( size <= 1) {
|
||||
// There is only one point - just move it
|
||||
// off screen and at default height.
|
||||
// temporary state when dragging only!
|
||||
mEnv[mDragPoint].SetT(big);
|
||||
mEnv[mDragPoint].SetVal(mDefaultValue);
|
||||
return;
|
||||
}
|
||||
else if ( mDragPoint + 1 == size ) {
|
||||
// Put the point at the height of the last point, but also off screen.
|
||||
mEnv[mDragPoint].SetT(big);
|
||||
mEnv[mDragPoint].SetVal(mEnv[ size - 1 ].GetVal());
|
||||
}
|
||||
else {
|
||||
// Place it exactly on its right neighbour.
|
||||
// That way the drawing code will overpaint the dark dot with
|
||||
// a light dot, as if it were deleted.
|
||||
const auto &neighbor = mEnv[mDragPoint + 1];
|
||||
mEnv[mDragPoint].SetT(neighbor.GetT());
|
||||
mEnv[mDragPoint].SetVal(neighbor.GetVal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Envelope::MoveDragPoint(double newWhen, double value)
|
||||
{
|
||||
SetDragPointValid(true);
|
||||
if (!mDragPointValid)
|
||||
return;
|
||||
|
||||
// We'll limit the drag point time to be between those of the preceding
|
||||
// and next envelope point.
|
||||
double limitLo = 0.0;
|
||||
double limitHi = mTrackLen;
|
||||
|
||||
if (mDragPoint > 0)
|
||||
limitLo = std::max(limitLo, mEnv[mDragPoint - 1].GetT());
|
||||
if (mDragPoint + 1 < mEnv.size())
|
||||
limitHi = std::min(limitHi, mEnv[mDragPoint + 1].GetT());
|
||||
|
||||
EnvPoint &dragPoint = mEnv[mDragPoint];
|
||||
const double tt =
|
||||
std::max(limitLo, std::min(limitHi, newWhen));
|
||||
|
||||
// This might temporary violate the constraint that at most two
|
||||
// points share a time value.
|
||||
dragPoint.SetT(tt);
|
||||
dragPoint.SetVal(value);
|
||||
}
|
||||
|
||||
void Envelope::ClearDragPoint()
|
||||
{
|
||||
if (!mDragPointValid && mDragPoint >= 0)
|
||||
Delete(mDragPoint);
|
||||
|
||||
mDragPoint = -1;
|
||||
mDragPointValid = false;
|
||||
}
|
||||
|
||||
void Envelope::SetRange(double minValue, double maxValue) {
|
||||
mMinValue = minValue;
|
||||
mMaxValue = maxValue;
|
||||
@ -186,7 +256,7 @@ static void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top)
|
||||
/// TODO: This should probably move to track artist.
|
||||
void Envelope::DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax) const
|
||||
float zoomMin, float zoomMax, bool mirrored) const
|
||||
{
|
||||
dc.SetPen(AColor::envelopePen);
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
@ -207,7 +277,7 @@ void Envelope::DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||
|
||||
y = GetWaveYPos(v, zoomMin, zoomMax, r.height, dB,
|
||||
true, dBRange, false);
|
||||
if (!mMirror) {
|
||||
if (!mirrored) {
|
||||
DrawPoint(dc, r, x, y, true);
|
||||
}
|
||||
else {
|
||||
@ -311,7 +381,7 @@ inline int SQR(int x) { return x * x; }
|
||||
/// @dB - display mode either linear or log.
|
||||
/// @zoomMin - vertical scale, typically -1.0
|
||||
/// @zoomMax - vertical scale, typically +1.0
|
||||
float Envelope::ValueOfPixel( int y, int height, bool upper,
|
||||
float EnvelopeEditor::ValueOfPixel( int y, int height, bool upper,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax)
|
||||
{
|
||||
@ -320,9 +390,9 @@ float Envelope::ValueOfPixel( int y, int height, bool upper,
|
||||
// MB: this is mostly equivalent to what the old code did, I'm not sure
|
||||
// if anything special is needed for asymmetric ranges
|
||||
if(upper)
|
||||
return ClampValue(v);
|
||||
return mEnvelope.ClampValue(v);
|
||||
else
|
||||
return ClampValue(-v);
|
||||
return mEnvelope.ClampValue(-v);
|
||||
}
|
||||
|
||||
/// HandleMouseButtonDown either finds an existing control point or adds a NEW one
|
||||
@ -331,13 +401,13 @@ float Envelope::ValueOfPixel( int y, int height, bool upper,
|
||||
/// a given time value:
|
||||
/// We have an upper and lower envelope line.
|
||||
/// Also we may be showing an inner envelope (at 0.5 the range).
|
||||
bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
bool EnvelopeEditor::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax)
|
||||
{
|
||||
int ctr = (int)(r.height * zoomMax / (zoomMax - zoomMin));
|
||||
bool upper = !mMirror || (zoomMin >= 0.0) || (event.m_y - r.y < ctr);
|
||||
bool upper = !mMirrored || (zoomMin >= 0.0) || (event.m_y - r.y < ctr);
|
||||
|
||||
int clip_y = event.m_y - r.y;
|
||||
if(clip_y < 0) clip_y = 0; //keeps point in rect r, even if mouse isn't
|
||||
@ -348,16 +418,15 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
|
||||
// Member variables hold state that will be needed in dragging.
|
||||
mButton = event.GetButton();
|
||||
mIsDeleting = false;
|
||||
mContourOffset = false;
|
||||
|
||||
// wxLogDebug(wxT("Y:%i Height:%i Offset:%i"), y, height, mContourOffset );
|
||||
int len = mEnv.size();
|
||||
int len = mEnvelope.GetNumberOfPoints();
|
||||
|
||||
// TODO: extract this into a function FindNearestControlPoint()
|
||||
// TODO: also fix it so that we can drag the last point on an envelope.
|
||||
for (int i = 0; i < len; i++) { //search for control point nearest click
|
||||
const double time = mEnv[i].GetT() + mOffset;
|
||||
const double time = mEnvelope[i].GetT() + mEnvelope.GetOffset();
|
||||
const wxInt64 position = zoomInfo.TimeToPosition(time);
|
||||
if (position >= 0 && position < r.width) {
|
||||
|
||||
@ -366,7 +435,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
int numControlPoints;
|
||||
|
||||
// Outer control points
|
||||
double value = mEnv[i].GetVal();
|
||||
double value = mEnvelope[i].GetVal();
|
||||
y[0] = GetWaveYPos(value, zoomMin, zoomMax, r.height,
|
||||
dB, true, dBRange, false);
|
||||
y[1] = GetWaveYPos(-value, zoomMin, zoomMax, r.height,
|
||||
@ -383,7 +452,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
if (y[2] > y[3])
|
||||
numControlPoints = 2;
|
||||
|
||||
if (!mMirror)
|
||||
if (!mMirrored)
|
||||
numControlPoints = 1;
|
||||
|
||||
const int deltaXSquared = SQR(x - (event.m_x - r.x));
|
||||
@ -400,7 +469,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
}
|
||||
|
||||
if (bestNum >= 0) {
|
||||
mDragPoint = bestNum;
|
||||
mEnvelope.SetDragPoint(bestNum);
|
||||
}
|
||||
else {
|
||||
// TODO: Extract this into a function CreateNewPoint
|
||||
@ -409,13 +478,13 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
// if (when <= 0 || when >= mTrackLen)
|
||||
// return false;
|
||||
|
||||
const double v = GetValue( when );
|
||||
const double v = mEnvelope.GetValue( when );
|
||||
|
||||
int ct = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB,
|
||||
false, dBRange, false) ;
|
||||
int cb = GetWaveYPos( -v-.000000001, zoomMin, zoomMax, r.height, dB,
|
||||
false, dBRange, false) ;
|
||||
if( ct <= cb || !mMirror ){
|
||||
if (ct <= cb || !mMirrored) {
|
||||
int t = GetWaveYPos( v, zoomMin, zoomMax, r.height, dB,
|
||||
true, dBRange, false) ;
|
||||
int b = GetWaveYPos( -v, zoomMin, zoomMax, r.height, dB,
|
||||
@ -424,7 +493,7 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
ct = (t + ct) / 2;
|
||||
cb = (b + cb) / 2;
|
||||
|
||||
if(mMirror &&
|
||||
if (mMirrored &&
|
||||
(event.m_y - r.y) > ct &&
|
||||
((event.m_y - r.y) < cb))
|
||||
mContourOffset = true;
|
||||
@ -435,48 +504,20 @@ bool Envelope::HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
double newVal = ValueOfPixel(clip_y, r.height, upper, dB, dBRange,
|
||||
zoomMin, zoomMax);
|
||||
|
||||
mDragPoint = Insert(when - mOffset, newVal);
|
||||
mEnvelope.SetDragPoint(mEnvelope.Insert(when - mEnvelope.GetOffset(), newVal));
|
||||
mDirty = true;
|
||||
}
|
||||
|
||||
mUpper = upper;
|
||||
|
||||
mInitialVal = mEnv[mDragPoint].GetVal();
|
||||
|
||||
mInitialY = event.m_y+mContourOffset;
|
||||
// const int dragPoint = mEnvelope.GetDragPoint();
|
||||
// mInitialVal = mEnvelope[dragPoint].GetVal();
|
||||
// mInitialY = event.m_y+mContourOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Mark dragged point for deletion.
|
||||
/// It will be deleted on mouse button up.
|
||||
void Envelope::MarkDragPointForDeletion()
|
||||
{
|
||||
mIsDeleting = true;
|
||||
|
||||
// We're going to be deleting the point; On
|
||||
// screen we show this by having the envelope move to
|
||||
// the position it will have after deletion of the point.
|
||||
// Without delting the point we move it left or right
|
||||
// to the same position as the previous or next point.
|
||||
|
||||
if( mEnv.size() <= 1)
|
||||
{
|
||||
// There is only one point - just move it
|
||||
// off screen and at default height.
|
||||
// temporary state when dragging only!
|
||||
mEnv[mDragPoint].SetT(-1000000.0);
|
||||
mEnv[mDragPoint].SetVal(mDefaultValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Place it exactly on one of its neighbours.
|
||||
int iNeighbourPoint = mDragPoint + ((mDragPoint > 0) ? -1:+1);
|
||||
mEnv[mDragPoint].SetT(mEnv[iNeighbourPoint].GetT());
|
||||
mEnv[mDragPoint].SetVal(mEnv[iNeighbourPoint].GetVal());
|
||||
}
|
||||
|
||||
void Envelope::MoveDraggedPoint( const wxMouseEvent & event, wxRect & r,
|
||||
void EnvelopeEditor::MoveDragPoint(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax)
|
||||
{
|
||||
@ -491,29 +532,14 @@ void Envelope::MoveDraggedPoint( const wxMouseEvent & event, wxRect & r,
|
||||
// TODO: However because mTrackEpsilon assumes 200KHz this use
|
||||
// of epsilon is a tad bogus. What we need to do instead is DELETE
|
||||
// a duplicated point on a mouse up.
|
||||
double newWhen = zoomInfo.PositionToTime(event.m_x, r.x) - mOffset;
|
||||
|
||||
// We'll limit the drag point time to be between those of the preceding
|
||||
// and next envelope point.
|
||||
double limitLo = 0.0;
|
||||
double limitHi = mTrackLen;
|
||||
|
||||
if (mDragPoint > 0)
|
||||
limitLo = mEnv[mDragPoint - 1].GetT() + mTrackEpsilon;
|
||||
if (mDragPoint < (int)mEnv.size() - 1 )
|
||||
limitHi = mEnv[mDragPoint + 1].GetT() - mTrackEpsilon;
|
||||
|
||||
newWhen = Limit( limitLo, newWhen, limitHi );
|
||||
newWhen = Limit( mTrackEpsilon, newWhen, mTrackLen - mTrackEpsilon);
|
||||
|
||||
mEnv[mDragPoint].SetT(newWhen);
|
||||
mEnv[mDragPoint].SetVal(newVal);
|
||||
|
||||
double newWhen = zoomInfo.PositionToTime(event.m_x, r.x) - mEnvelope.GetOffset();
|
||||
mEnvelope.MoveDragPoint(newWhen, newVal);
|
||||
}
|
||||
|
||||
bool Envelope::HandleDragging( const wxMouseEvent & event, wxRect & r,
|
||||
bool EnvelopeEditor::HandleDragging(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax)
|
||||
float zoomMin, float zoomMax,
|
||||
float WXUNUSED(eMin), float WXUNUSED(eMax))
|
||||
{
|
||||
mDirty = true;
|
||||
|
||||
@ -523,27 +549,24 @@ bool Envelope::HandleDragging( const wxMouseEvent & event, wxRect & r,
|
||||
if (larger.Contains(event.m_x, event.m_y))
|
||||
{
|
||||
// IF we're in the rect THEN we're not deleting this point (anymore).
|
||||
mIsDeleting = false;
|
||||
// ...we're dragging it.
|
||||
MoveDraggedPoint( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax);
|
||||
MoveDragPoint( event, r, zoomInfo, dB, dBRange, zoomMin, zoomMax);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(mIsDeleting )
|
||||
if(!mEnvelope.GetDragPointValid())
|
||||
// IF we already know we're deleting THEN no envelope point to update.
|
||||
return false;
|
||||
|
||||
MarkDragPointForDeletion();
|
||||
// Invalidate the point
|
||||
mEnvelope.SetDragPointValid(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exit dragging mode and deletes dragged point if neccessary.
|
||||
bool Envelope::HandleMouseButtonUp()
|
||||
// Exit dragging mode and delete dragged point if neccessary.
|
||||
bool EnvelopeEditor::HandleMouseButtonUp()
|
||||
{
|
||||
if (mIsDeleting) {
|
||||
Delete(mDragPoint);
|
||||
}
|
||||
mDragPoint = -1;
|
||||
mEnvelope.ClearDragPoint();
|
||||
mButton = wxMOUSE_BTN_NONE;
|
||||
return true;
|
||||
}
|
||||
@ -559,14 +582,14 @@ void Envelope::Insert(int point, const EnvPoint &p)
|
||||
}
|
||||
|
||||
// Returns true if parent needs to be redrawn
|
||||
bool Envelope::MouseEvent(const wxMouseEvent & event, wxRect & r,
|
||||
bool EnvelopeEditor::MouseEvent(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax)
|
||||
{
|
||||
if (event.ButtonDown() && mButton == wxMOUSE_BTN_NONE)
|
||||
return HandleMouseButtonDown( event, r, zoomInfo, dB, dBRange,
|
||||
zoomMin, zoomMax);
|
||||
if (event.Dragging() && mDragPoint >= 0)
|
||||
if (event.Dragging() && mEnvelope.GetDragPoint() >= 0)
|
||||
return HandleDragging( event, r, zoomInfo, dB, dBRange,
|
||||
zoomMin, zoomMax);
|
||||
if (event.ButtonUp() && event.GetButton() == mButton)
|
||||
@ -1523,7 +1546,6 @@ void Envelope::testMe()
|
||||
double t0=0, t1=0;
|
||||
|
||||
SetInterpolateDB(false);
|
||||
Mirror(false);
|
||||
|
||||
Flatten(0.5);
|
||||
checkResult( 1, Integral(0.0,100.0), 50);
|
||||
@ -1575,3 +1597,18 @@ void Envelope::testMe()
|
||||
checkResult( 19, NextPointAfter( 5 ), 10 );
|
||||
}
|
||||
|
||||
EnvelopeEditor::EnvelopeEditor(Envelope &envelope, bool mirrored)
|
||||
: mEnvelope(envelope)
|
||||
, mMirrored(mirrored)
|
||||
, mContourOffset(-1)
|
||||
// , mInitialVal(-1.0)
|
||||
// , mInitialY(-1)
|
||||
, mUpper(false)
|
||||
, mButton(wxMOUSE_BTN_NONE)
|
||||
, mDirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
EnvelopeEditor::~EnvelopeEditor()
|
||||
{
|
||||
}
|
||||
|
112
src/Envelope.h
112
src/Envelope.h
@ -81,13 +81,14 @@ class Envelope final : public XMLTagHandler {
|
||||
|
||||
virtual ~ Envelope();
|
||||
|
||||
double GetOffset() const { return mOffset; }
|
||||
double GetTrackLen() const { return mTrackLen; }
|
||||
|
||||
bool GetInterpolateDB() { return mDB; }
|
||||
void SetInterpolateDB(bool db) { mDB = db; }
|
||||
void Mirror(bool mirror);
|
||||
void Rescale(double minValue, double maxValue);
|
||||
|
||||
void Flatten(double value);
|
||||
int GetDragPoint(void) {return mDragPoint;}
|
||||
|
||||
double GetMinValue() const { return mMinValue; }
|
||||
double GetMaxValue() const { return mMaxValue; }
|
||||
@ -108,20 +109,7 @@ class Envelope final : public XMLTagHandler {
|
||||
|
||||
void DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax) const;
|
||||
|
||||
// Event Handlers
|
||||
// Each ofthese returns true if parents needs to be redrawn
|
||||
bool MouseEvent(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
bool HandleMouseButtonDown( const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
bool HandleDragging( const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
bool HandleMouseButtonUp();
|
||||
float zoomMin, float zoomMax, bool mirrored) const;
|
||||
|
||||
// Handling Cut/Copy/Paste events
|
||||
void CollapseRegion(double t0, double t1);
|
||||
@ -181,28 +169,38 @@ class Envelope final : public XMLTagHandler {
|
||||
/** \brief Return number of points */
|
||||
size_t GetNumberOfPoints() const;
|
||||
|
||||
private:
|
||||
friend class EnvelopeEditor;
|
||||
/** \brief Accessor for points */
|
||||
const EnvPoint &operator[] (int index) const
|
||||
EnvPoint &operator[] (int index)
|
||||
{
|
||||
return mEnv[index];
|
||||
}
|
||||
|
||||
public:
|
||||
/** \brief Returns the sets of when and value pairs */
|
||||
void GetPoints(double *bufferWhen,
|
||||
double *bufferValue,
|
||||
int bufferLen) const;
|
||||
|
||||
// UI-related
|
||||
// The drag point needs to display differently.
|
||||
int GetDragPoint() const { return mDragPoint; }
|
||||
// Choose the drag point.
|
||||
void SetDragPoint(int dragPoint);
|
||||
// Mark or unmark the drag point for deletion.
|
||||
void SetDragPointValid(bool valid);
|
||||
bool GetDragPointValid() const { return mDragPointValid; }
|
||||
// Modify the dragged point and change its value.
|
||||
// But consistency constraints may move it less then you ask for.
|
||||
void MoveDragPoint(double newWhen, double value);
|
||||
// May delete the drag point. Restores envelope consistency.
|
||||
void ClearDragPoint();
|
||||
|
||||
private:
|
||||
EnvPoint * AddPointAtEnd( double t, double val );
|
||||
void MarkDragPointForDeletion();
|
||||
float ValueOfPixel( int y, int height, bool upper,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
void BinarySearchForTime( int &Lo, int &Hi, double t ) const;
|
||||
double GetInterpolationStartValueAtPoint( int iPoint ) const;
|
||||
void MoveDraggedPoint( const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
|
||||
// Possibly inline functions:
|
||||
// This function resets them integral memoizers (call whenever the Envelope changes)
|
||||
@ -210,7 +208,6 @@ private:
|
||||
|
||||
// The list of envelope control points.
|
||||
EnvArray mEnv;
|
||||
bool mMirror;
|
||||
|
||||
/** \brief The time at which the envelope starts, i.e. the start offset */
|
||||
double mOffset;
|
||||
@ -224,21 +221,7 @@ private:
|
||||
* before being considered the same point */
|
||||
double mTrackEpsilon;
|
||||
double mDefaultValue;
|
||||
|
||||
/** \brief Number of pixels contour is from the true envelope. */
|
||||
int mContourOffset;
|
||||
|
||||
double mInitialVal;
|
||||
|
||||
// These are used in dragging.
|
||||
int mDragPoint;
|
||||
int mInitialY;
|
||||
bool mUpper;
|
||||
bool mIsDeleting;
|
||||
int mButton;
|
||||
bool mDB;
|
||||
bool mDirty;
|
||||
|
||||
double mMinValue, mMaxValue;
|
||||
|
||||
// These are memoizing variables for Integral()
|
||||
@ -246,8 +229,11 @@ private:
|
||||
double lastIntegral_t1;
|
||||
double lastIntegral_result;
|
||||
|
||||
mutable int mSearchGuess;
|
||||
// UI stuff
|
||||
bool mDragPointValid;
|
||||
int mDragPoint;
|
||||
|
||||
mutable int mSearchGuess;
|
||||
};
|
||||
|
||||
inline EnvPoint::EnvPoint(Envelope *envelope, double t, double val)
|
||||
@ -262,5 +248,49 @@ inline void EnvPoint::SetVal(double val)
|
||||
mVal = mEnvelope->ClampValue(val);
|
||||
}
|
||||
|
||||
#endif
|
||||
// A class that holds state for the duration of dragging
|
||||
// of an envelope point.
|
||||
class EnvelopeEditor
|
||||
{
|
||||
public:
|
||||
EnvelopeEditor(Envelope &envelope, bool mirrored);
|
||||
~EnvelopeEditor();
|
||||
|
||||
// Event Handlers
|
||||
// Each of these returns true if the envelope needs to be redrawn
|
||||
bool MouseEvent(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin = -1.0, float zoomMax = 1.0);
|
||||
|
||||
private:
|
||||
bool HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin = -1.0, float zoomMax = 1.0);
|
||||
bool HandleDragging(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin = -1.0, float zoomMax = 1.0, float eMin = 0., float eMax = 2.);
|
||||
bool HandleMouseButtonUp();
|
||||
|
||||
private:
|
||||
float ValueOfPixel(int y, int height, bool upper,
|
||||
bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
void MoveDragPoint(const wxMouseEvent & event, wxRect & r,
|
||||
const ZoomInfo &zoomInfo, bool dB, double dBRange,
|
||||
float zoomMin, float zoomMax);
|
||||
|
||||
Envelope &mEnvelope;
|
||||
const bool mMirrored;
|
||||
|
||||
/** \brief Number of pixels contour is from the true envelope. */
|
||||
int mContourOffset;
|
||||
|
||||
// double mInitialVal;
|
||||
|
||||
// int mInitialY;
|
||||
bool mUpper;
|
||||
int mButton;
|
||||
bool mDirty;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -48,7 +48,6 @@ TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const Zo
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
mEnvelope->SetInterpolateDB(true);
|
||||
mEnvelope->Flatten(1.0);
|
||||
mEnvelope->Mirror(false);
|
||||
mEnvelope->SetOffset(0);
|
||||
mEnvelope->SetRange(TIMETRACK_MIN, TIMETRACK_MAX);
|
||||
|
||||
@ -75,7 +74,6 @@ TimeTrack::TimeTrack(const TimeTrack &orig):
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
SetInterpolateLog(orig.GetInterpolateLog()); // this calls Envelope::SetInterpolateDB
|
||||
mEnvelope->Flatten(1.0);
|
||||
mEnvelope->Mirror(false);
|
||||
mEnvelope->SetOffset(0);
|
||||
mEnvelope->SetRange(orig.mEnvelope->GetMinValue(), orig.mEnvelope->GetMaxValue());
|
||||
mEnvelope->Paste(0.0, orig.mEnvelope.get());
|
||||
|
@ -1926,7 +1926,7 @@ void TrackArtist::DrawClipWaveform(const WaveTrack *track,
|
||||
|
||||
if (drawEnvelope) {
|
||||
DrawEnvelope(dc, mid, env, zoomMin, zoomMax, dB, dBRange);
|
||||
clip->GetEnvelope()->DrawPoints(dc, rect, zoomInfo, dB, dBRange, zoomMin, zoomMax);
|
||||
clip->GetEnvelope()->DrawPoints(dc, rect, zoomInfo, dB, dBRange, zoomMin, zoomMax, true);
|
||||
}
|
||||
|
||||
// Draw arrows on the left side if the track extends to the left of the
|
||||
@ -3209,7 +3209,7 @@ void TrackArtist::DrawTimeTrack(const TimeTrack *track,
|
||||
upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / mdBrange + 1.0;
|
||||
}
|
||||
track->GetEnvelope()->DrawPoints(dc, envRect, zoomInfo,
|
||||
track->GetDisplayLog(), mdBrange, lower, upper);
|
||||
track->GetDisplayLog(), mdBrange, lower, upper, false);
|
||||
}
|
||||
|
||||
void TrackArtist::UpdatePrefs()
|
||||
|
@ -3213,8 +3213,13 @@ void TrackPanel::ForwardEventToTimeTrackEnvelope(wxMouseEvent & event)
|
||||
lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dBRange + 1.0;
|
||||
upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dBRange + 1.0;
|
||||
}
|
||||
if (event.ButtonDown()) {
|
||||
mEnvelopeEditor = std::make_unique<EnvelopeEditor>(*pspeedenvelope, false);
|
||||
mEnvelopeEditorRight.reset();
|
||||
}
|
||||
bool needUpdate =
|
||||
pspeedenvelope->MouseEvent(
|
||||
mEnvelopeEditor &&
|
||||
mEnvelopeEditor->MouseEvent(
|
||||
event, envRect,
|
||||
*mViewInfo,
|
||||
ptimetrack->GetDisplayLog(), dBRange, lower, upper);
|
||||
@ -3250,7 +3255,13 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event)
|
||||
wxRect envRect = mCapturedRect;
|
||||
float zoomMin, zoomMax;
|
||||
pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
needUpdate = penvelope->MouseEvent(
|
||||
if (event.ButtonDown()) {
|
||||
mEnvelopeEditor = std::make_unique<EnvelopeEditor>(*penvelope, true);
|
||||
mEnvelopeEditorRight.reset();
|
||||
}
|
||||
needUpdate =
|
||||
mEnvelopeEditor &&
|
||||
mEnvelopeEditor->MouseEvent(
|
||||
event, envRect,
|
||||
*mViewInfo,
|
||||
dB, dBRange, zoomMin, zoomMax);
|
||||
@ -3260,30 +3271,23 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event)
|
||||
// Assume linked track is wave or null
|
||||
const auto link = static_cast<WaveTrack *>(mCapturedTrack->GetLink());
|
||||
if (link) {
|
||||
if (event.ButtonDown()) {
|
||||
Envelope *e2 = link->GetEnvelopeAtX(event.GetX());
|
||||
if (e2)
|
||||
mEnvelopeEditorRight = std::make_unique<EnvelopeEditor>(*e2, true);
|
||||
else {
|
||||
// There isn't necessarily an envelope there; no guarantee a
|
||||
// linked track has the same WaveClip structure...
|
||||
bool updateNeeded = false;
|
||||
if (e2) {
|
||||
}
|
||||
}
|
||||
if (mEnvelopeEditorRight) {
|
||||
wxRect envRect = mCapturedRect;
|
||||
float zoomMin, zoomMax;
|
||||
pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
updateNeeded = e2->MouseEvent(event, envRect,
|
||||
*mViewInfo, dB, dBRange,
|
||||
needUpdate|= mEnvelopeEditorRight->MouseEvent(event, envRect,
|
||||
*mViewInfo,
|
||||
dB, dBRange,
|
||||
zoomMin, zoomMax);
|
||||
needUpdate |= updateNeeded;
|
||||
}
|
||||
if(!e2 || !updateNeeded) // no envelope found at this x point, or found but not updated
|
||||
{
|
||||
if( (e2 = link->GetActiveEnvelope()) != 0 ) // search for any active DragPoint
|
||||
{
|
||||
wxRect envRect = mCapturedRect;
|
||||
float zoomMin, zoomMax;
|
||||
pwavetrack->GetDisplayBounds(&zoomMin, &zoomMax);
|
||||
needUpdate |= e2->MouseEvent(event, envRect,
|
||||
*mViewInfo, dB, dBRange,
|
||||
zoomMin, zoomMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
class wxMenu;
|
||||
class wxRect;
|
||||
|
||||
class EnvelopeEditor;
|
||||
class LabelTrack;
|
||||
class SpectrumAnalyst;
|
||||
class TrackPanel;
|
||||
@ -809,6 +810,9 @@ protected:
|
||||
// Keeps track of extra fractional vertical scroll steps
|
||||
double mVertScrollRemainder;
|
||||
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditor;
|
||||
std::unique_ptr<EnvelopeEditor> mEnvelopeEditorRight;
|
||||
|
||||
protected:
|
||||
|
||||
// The screenshot class needs to access internals
|
||||
|
@ -810,7 +810,7 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
||||
const Track *src, // What to paste
|
||||
bool preserve, // Whether to reinsert splits/cuts
|
||||
bool merge, // Whether to remove 'extra' splits
|
||||
TimeWarper *effectWarper // How does time change
|
||||
const TimeWarper *effectWarper // How does time change
|
||||
)
|
||||
{
|
||||
double dur = wxMin(t1 - t0, src->GetEndTime());
|
||||
@ -824,12 +824,7 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
||||
|
||||
// If provided time warper was NULL, use a default one that does nothing
|
||||
IdentityTimeWarper localWarper;
|
||||
TimeWarper *warper = NULL;
|
||||
if (effectWarper != NULL) {
|
||||
warper = effectWarper;
|
||||
} else {
|
||||
warper = &localWarper;
|
||||
}
|
||||
const TimeWarper *warper = (effectWarper ? effectWarper : &localWarper);
|
||||
|
||||
// Align to a sample
|
||||
t0 = LongSamplesToTime(TimeToLongSamples(t0));
|
||||
@ -2228,18 +2223,6 @@ Envelope* WaveTrack::GetEnvelopeAtX(int xcoord)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search for any active DragPoint on the current track
|
||||
Envelope* WaveTrack::GetActiveEnvelope(void)
|
||||
{
|
||||
for (const auto &clip : mClips)
|
||||
{
|
||||
Envelope* env = clip->GetEnvelope() ;
|
||||
if (env->GetDragPoint() >= 0)
|
||||
return env;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Sequence* WaveTrack::GetSequenceAtX(int xcoord)
|
||||
{
|
||||
WaveClip* clip = GetClipAtX(xcoord);
|
||||
|
@ -175,7 +175,7 @@ class AUDACITY_DLL_API WaveTrack final : public Track {
|
||||
const Track *src,
|
||||
bool preserve = true,
|
||||
bool merge = true,
|
||||
TimeWarper *effectWarper = NULL) /* not override */;
|
||||
const TimeWarper *effectWarper = NULL) /* not override */;
|
||||
|
||||
bool Silence(double t0, double t1) override;
|
||||
bool InsertSilence(double t, double len) override;
|
||||
@ -264,7 +264,6 @@ class AUDACITY_DLL_API WaveTrack final : public Track {
|
||||
WaveClip* GetClipAtX(int xcoord);
|
||||
Sequence* GetSequenceAtX(int xcoord);
|
||||
Envelope* GetEnvelopeAtX(int xcoord);
|
||||
Envelope* GetActiveEnvelope(void);
|
||||
|
||||
WaveClip* GetClipAtSample(sampleCount sample);
|
||||
|
||||
|
@ -194,7 +194,7 @@ bool EffectChangePitch::Process()
|
||||
#endif
|
||||
{
|
||||
mSoundTouch = std::make_unique<SoundTouch>();
|
||||
SetTimeWarper(std::make_unique<IdentityTimeWarper>());
|
||||
IdentityTimeWarper warper;
|
||||
mSoundTouch->setPitchSemiTones((float)(m_dSemitonesChange));
|
||||
#ifdef USE_MIDI
|
||||
// Pitch shifting note tracks is currently only supported by SoundTouchEffect
|
||||
@ -209,7 +209,7 @@ bool EffectChangePitch::Process()
|
||||
// eliminate the next line:
|
||||
mSemitones = m_dSemitonesChange;
|
||||
#endif
|
||||
return EffectSoundTouch::Process();
|
||||
return EffectSoundTouch::ProcessWithTimeWarper(warper);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,10 +455,10 @@ bool EffectChangeSpeed::TransferDataFromWindow()
|
||||
// the region are shifted along according to how the region size changed.
|
||||
bool EffectChangeSpeed::ProcessLabelTrack(LabelTrack *lt)
|
||||
{
|
||||
SetTimeWarper(std::make_unique<RegionTimeWarper>(mT0, mT1,
|
||||
RegionTimeWarper warper { mT0, mT1,
|
||||
std::make_unique<LinearTimeWarper>(mT0, mT0,
|
||||
mT1, mT0 + (mT1-mT0)*mFactor)));
|
||||
lt->WarpLabels(*GetTimeWarper());
|
||||
mT1, mT0 + (mT1-mT0)*mFactor) };
|
||||
lt->WarpLabels(warper);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -542,8 +542,9 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
if (bResult)
|
||||
{
|
||||
SetTimeWarper(std::make_unique<LinearTimeWarper>(mCurT0, mCurT0, mCurT1, mCurT0 + newLength));
|
||||
bResult = track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, false, GetTimeWarper());
|
||||
LinearTimeWarper warper { mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
|
||||
bResult = track->ClearAndPaste(
|
||||
mCurT0, mCurT1, outputTrack.get(), true, false, &warper);
|
||||
}
|
||||
|
||||
if (newLength > mMaxNewLength)
|
||||
|
@ -183,9 +183,9 @@ bool EffectChangeTempo::Process()
|
||||
mSoundTouch = std::make_unique<SoundTouch>();
|
||||
mSoundTouch->setTempoChange(m_PercentChange);
|
||||
double mT1Dashed = mT0 + (mT1 - mT0)/(m_PercentChange/100.0 + 1.0);
|
||||
SetTimeWarper(std::make_unique<RegionTimeWarper>(mT0, mT1,
|
||||
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed )));
|
||||
success = EffectSoundTouch::Process();
|
||||
RegionTimeWarper warper{ mT0, mT1,
|
||||
std::make_unique<LinearTimeWarper>(mT0, mT0, mT1, mT1Dashed ) };
|
||||
success = EffectSoundTouch::ProcessWithTimeWarper(warper);
|
||||
}
|
||||
|
||||
if(success)
|
||||
|
@ -91,8 +91,6 @@ Effect::Effect()
|
||||
|
||||
mClient = NULL;
|
||||
|
||||
mWarper = NULL;
|
||||
|
||||
mTracks = NULL;
|
||||
mOutputTracksType = Track::None;
|
||||
mT0 = 0.0;
|
||||
@ -2036,18 +2034,6 @@ void Effect::GetSamples(
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::SetTimeWarper(std::unique_ptr<TimeWarper> &&warper)
|
||||
{
|
||||
wxASSERT(warper);
|
||||
mWarper = std::move(warper);
|
||||
}
|
||||
|
||||
TimeWarper *Effect::GetTimeWarper()
|
||||
{
|
||||
wxASSERT(mWarper);
|
||||
return mWarper.get();
|
||||
}
|
||||
|
||||
//
|
||||
// private methods
|
||||
//
|
||||
|
@ -46,7 +46,6 @@ class ShuttleGui;
|
||||
class AudacityProject;
|
||||
class LabelTrack;
|
||||
class SelectedRegion;
|
||||
class TimeWarper;
|
||||
class EffectUIHost;
|
||||
class Track;
|
||||
class TrackList;
|
||||
@ -330,9 +329,6 @@ protected:
|
||||
void GetSamples(
|
||||
const WaveTrack *track, sampleCount *start, sampleCount *len);
|
||||
|
||||
void SetTimeWarper(std::unique_ptr<TimeWarper> &&warper);
|
||||
TimeWarper *GetTimeWarper();
|
||||
|
||||
// Previewing linear effect can be optimised by pre-mixing. However this
|
||||
// should not be used for non-linear effects such as dynamic processors
|
||||
// To allow pre-mixing before Preview, set linearEffectFlag to true.
|
||||
@ -446,7 +442,6 @@ protected:
|
||||
double mF0;
|
||||
double mF1;
|
||||
#endif
|
||||
std::unique_ptr<TimeWarper> mWarper;
|
||||
wxArrayString mPresetNames;
|
||||
wxArrayString mPresetValues;
|
||||
int mPass;
|
||||
|
@ -241,12 +241,10 @@ EffectEqualization::EffectEqualization()
|
||||
|
||||
mLogEnvelope = std::make_unique<Envelope>();
|
||||
mLogEnvelope->SetInterpolateDB(false);
|
||||
mLogEnvelope->Mirror(false);
|
||||
mLogEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range
|
||||
|
||||
mLinEnvelope = std::make_unique<Envelope>();
|
||||
mLinEnvelope->SetInterpolateDB(false);
|
||||
mLinEnvelope->Mirror(false);
|
||||
mLinEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range
|
||||
|
||||
mEnvelope = (mLin ? mLinEnvelope : mLogEnvelope).get();
|
||||
@ -2365,7 +2363,6 @@ void EffectEqualization::ErrMin(void)
|
||||
int j=0;
|
||||
Envelope testEnvelope;
|
||||
testEnvelope.SetInterpolateDB(false);
|
||||
testEnvelope.Mirror(false);
|
||||
testEnvelope.SetRange(-120.0, 60.0);
|
||||
testEnvelope.Flatten(0.);
|
||||
testEnvelope.SetTrackLen(1.0);
|
||||
@ -2893,8 +2890,8 @@ EqualizationPanel::EqualizationPanel(EffectEqualization *effect, wxWindow *paren
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
|
||||
mEditor = std::make_unique<EnvelopeEditor>(*mEffect->mEnvelope, false);
|
||||
mEffect->mEnvelope->Flatten(0.);
|
||||
mEffect->mEnvelope->Mirror(false);
|
||||
mEffect->mEnvelope->SetTrackLen(1.0);
|
||||
|
||||
ForceRecalc();
|
||||
@ -3103,7 +3100,7 @@ void EqualizationPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
|
||||
if( mEffect->mDraw->GetValue() )
|
||||
{
|
||||
mEffect->mEnvelope->DrawPoints(memDC, mEnvRect, ZoomInfo(0.0, mEnvRect.width-1), false, 0.0,
|
||||
mEffect->mdBMin, mEffect->mdBMax);
|
||||
mEffect->mdBMin, mEffect->mdBMax, false);
|
||||
}
|
||||
|
||||
dc.Blit(0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE);
|
||||
@ -3121,7 +3118,7 @@ void EqualizationPanel::OnMouseEvent(wxMouseEvent & event)
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
if (mEffect->mEnvelope->MouseEvent(event, mEnvRect, ZoomInfo(0.0, mEnvRect.width),
|
||||
if (mEditor->MouseEvent(event, mEnvRect, ZoomInfo(0.0, mEnvRect.width),
|
||||
false, 0.0,
|
||||
mEffect->mdBMin, mEffect->mdBMax))
|
||||
{
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
|
||||
class Envelope;
|
||||
class EnvelopeEditor;
|
||||
class EqualizationPanel;
|
||||
|
||||
//
|
||||
@ -308,6 +309,7 @@ public:
|
||||
private:
|
||||
wxWindow *mParent;
|
||||
EffectEqualization *mEffect;
|
||||
std::unique_ptr<EnvelopeEditor> mEditor;
|
||||
|
||||
bool mRecalcRequired;
|
||||
|
||||
|
@ -78,9 +78,10 @@ bool Generator::Process()
|
||||
else {
|
||||
// Transfer the data from the temporary track to the actual one
|
||||
tmp->Flush();
|
||||
SetTimeWarper(std::make_unique<StepTimeWarper>(mT0+GetDuration(), GetDuration()-(mT1-mT0)));
|
||||
bGoodResult = track->ClearAndPaste(p->GetSel0(), p->GetSel1(), &*tmp, true,
|
||||
false, GetTimeWarper());
|
||||
StepTimeWarper warper{
|
||||
mT0+GetDuration(), GetDuration()-(mT1-mT0) };
|
||||
bGoodResult = track->ClearAndPaste(
|
||||
p->GetSel0(), p->GetSel1(), &*tmp, true, false, &warper);
|
||||
}
|
||||
|
||||
if (!bGoodResult) {
|
||||
|
@ -45,7 +45,6 @@
|
||||
|
||||
#include "NoiseRemoval.h"
|
||||
|
||||
#include "../Envelope.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
|
@ -163,7 +163,7 @@ bool EffectNormalize::Process()
|
||||
WaveTrack *track = (WaveTrack *) iter.First();
|
||||
WaveTrack *prevTrack;
|
||||
prevTrack = track;
|
||||
mCurTrackNum = 0;
|
||||
int curTrackNum = 0;
|
||||
wxString topMsg;
|
||||
if(mDC && mGain)
|
||||
topMsg = _("Removing DC offset and Normalizing...\n");
|
||||
@ -193,9 +193,11 @@ bool EffectNormalize::Process()
|
||||
msg = topMsg + _("Analyzing: ") + trackName;
|
||||
else
|
||||
msg = topMsg + _("Analyzing first track of stereo pair: ") + trackName;
|
||||
AnalyseTrack(track, msg); // sets mOffset and offset-adjusted mMin and mMax
|
||||
if(!track->GetLinked() || mStereoInd) { // mono or 'stereo tracks independently'
|
||||
float extent = wxMax(fabs(mMax), fabs(mMin));
|
||||
float offset, min, max;
|
||||
AnalyseTrack(track, msg, curTrackNum, offset, min, max);
|
||||
if(!track->GetLinked() || mStereoInd) {
|
||||
// mono or 'stereo tracks independently'
|
||||
float extent = wxMax(fabs(max), fabs(min));
|
||||
if( (extent > 0) && mGain )
|
||||
mMult = ratio / extent;
|
||||
else
|
||||
@ -204,7 +206,7 @@ bool EffectNormalize::Process()
|
||||
if(track->GetLinked() || prevTrack->GetLinked()) // only get here if there is a linked track but we are processing independently
|
||||
msg = topMsg + _("Processing stereo channels independently: ") + trackName;
|
||||
|
||||
if (!ProcessOne(track, msg))
|
||||
if (!ProcessOne(track, msg, curTrackNum, offset))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -215,37 +217,27 @@ bool EffectNormalize::Process()
|
||||
// we have a linked stereo track
|
||||
// so we need to find it's min, max and offset
|
||||
// as they are needed to calc the multiplier for both tracks
|
||||
float offset1 = mOffset; // remember ones from first track
|
||||
float min1 = mMin;
|
||||
float max1 = mMax;
|
||||
track = (WaveTrack *) iter.Next(); // get the next one
|
||||
mCurTrackNum++; // keeps progress bar correct
|
||||
msg = topMsg + _("Analyzing second track of stereo pair: ") + trackName;
|
||||
AnalyseTrack(track, msg); // sets mOffset and offset-adjusted mMin and mMax
|
||||
float offset2 = mOffset; // ones for second track
|
||||
float min2 = mMin;
|
||||
float max2 = mMax;
|
||||
float extent = wxMax(fabs(min1), fabs(max1));
|
||||
float offset2, min2, max2;
|
||||
AnalyseTrack(track, msg, curTrackNum + 1, offset2, min2, max2);
|
||||
float extent = wxMax(fabs(min), fabs(max));
|
||||
extent = wxMax(extent, fabs(min2));
|
||||
extent = wxMax(extent, fabs(max2));
|
||||
if( (extent > 0) && mGain )
|
||||
mMult = ratio / extent; // we need to use this for both linked tracks
|
||||
else
|
||||
mMult = 1.0;
|
||||
mOffset = offset1;
|
||||
track = (WaveTrack *) iter.Prev(); // go back to the first linked one
|
||||
mCurTrackNum--; // keeps progress bar correct
|
||||
msg = topMsg + _("Processing first track of stereo pair: ") + trackName;
|
||||
if (!ProcessOne(track, msg))
|
||||
if (!ProcessOne(track, msg, curTrackNum, offset))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
mOffset = offset2;
|
||||
track = (WaveTrack *) iter.Next(); // go to the second linked one
|
||||
mCurTrackNum++; // keeps progress bar correct
|
||||
msg = topMsg + _("Processing second track of stereo pair: ") + trackName;
|
||||
if (!ProcessOne(track, msg))
|
||||
if (!ProcessOne(track, msg, curTrackNum, offset2))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -256,7 +248,7 @@ bool EffectNormalize::Process()
|
||||
//Iterate to the next track
|
||||
prevTrack = track;
|
||||
track = (WaveTrack *) iter.Next();
|
||||
mCurTrackNum++;
|
||||
curTrackNum++;
|
||||
}
|
||||
|
||||
this->ReplaceProcessedTracks(bGoodResult);
|
||||
@ -333,7 +325,9 @@ bool EffectNormalize::TransferDataFromWindow()
|
||||
|
||||
// EffectNormalize implementation
|
||||
|
||||
void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg)
|
||||
void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
int curTrackNum,
|
||||
float &offset, float &min, float &max)
|
||||
{
|
||||
if(mGain) {
|
||||
// Since we need complete summary data, we need to block until the OD tasks are done for this track
|
||||
@ -344,28 +338,29 @@ void EffectNormalize::AnalyseTrack(const WaveTrack * track, const wxString &msg)
|
||||
wxMilliSleep(100);
|
||||
}
|
||||
|
||||
track->GetMinMax(&mMin, &mMax, mCurT0, mCurT1); // set mMin, mMax. No progress bar here as it's fast.
|
||||
track->GetMinMax(&min, &max, mCurT0, mCurT1);
|
||||
} else {
|
||||
mMin = -1.0, mMax = 1.0; // sensible defaults?
|
||||
min = -1.0, max = 1.0; // sensible defaults?
|
||||
}
|
||||
|
||||
if(mDC) {
|
||||
AnalyseDC(track, msg); // sets mOffset
|
||||
mMin += mOffset;
|
||||
mMax += mOffset;
|
||||
AnalyseDC(track, msg, curTrackNum, offset);
|
||||
min += offset;
|
||||
max += offset;
|
||||
} else {
|
||||
mOffset = 0.0;
|
||||
offset = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
//AnalyseDC() takes a track, transforms it to bunch of buffer-blocks,
|
||||
//and executes AnalyzeData on it...
|
||||
// sets mOffset
|
||||
bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg)
|
||||
bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg,
|
||||
int curTrackNum,
|
||||
float &offset)
|
||||
{
|
||||
bool rc = true;
|
||||
|
||||
mOffset = 0.0; // we might just return
|
||||
offset = 0.0; // we might just return
|
||||
|
||||
if(!mDC) // don't do analysis if not doing dc removal
|
||||
return(rc);
|
||||
@ -407,7 +402,7 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg)
|
||||
s += block;
|
||||
|
||||
//Update the Progress meter
|
||||
if (TrackProgress(mCurTrackNum,
|
||||
if (TrackProgress(curTrackNum,
|
||||
((s - start).as_double() / len)/2.0, msg)) {
|
||||
rc = false; //lda .. break, not return, so that buffer is deleted
|
||||
break;
|
||||
@ -417,7 +412,7 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg)
|
||||
//Clean up the buffer
|
||||
delete[] buffer;
|
||||
|
||||
mOffset = -mSum / mCount.as_double(); // calculate actual offset (amount that needs to be added on)
|
||||
offset = -mSum / mCount.as_double(); // calculate actual offset (amount that needs to be added on)
|
||||
|
||||
//Return true because the effect processing succeeded ... unless cancelled
|
||||
return rc;
|
||||
@ -425,8 +420,10 @@ bool EffectNormalize::AnalyseDC(const WaveTrack * track, const wxString &msg)
|
||||
|
||||
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
||||
//and executes ProcessData, on it...
|
||||
// uses mMult and mOffset to normalize a track. Needs to have them set before being called
|
||||
bool EffectNormalize::ProcessOne(WaveTrack * track, const wxString &msg)
|
||||
// uses mMult and offset to normalize a track.
|
||||
// mMult must be set before this is called
|
||||
bool EffectNormalize::ProcessOne(
|
||||
WaveTrack * track, const wxString &msg, int curTrackNum, float offset)
|
||||
{
|
||||
bool rc = true;
|
||||
|
||||
@ -458,7 +455,7 @@ bool EffectNormalize::ProcessOne(WaveTrack * track, const wxString &msg)
|
||||
track->Get((samplePtr) buffer, floatSample, s, block);
|
||||
|
||||
//Process the buffer.
|
||||
ProcessData(buffer, block);
|
||||
ProcessData(buffer, block, offset);
|
||||
|
||||
//Copy the newly-changed samples back onto the track.
|
||||
track->Set((samplePtr) buffer, floatSample, s, block);
|
||||
@ -467,7 +464,7 @@ bool EffectNormalize::ProcessOne(WaveTrack * track, const wxString &msg)
|
||||
s += block;
|
||||
|
||||
//Update the Progress meter
|
||||
if (TrackProgress(mCurTrackNum,
|
||||
if (TrackProgress(curTrackNum,
|
||||
0.5+((s - start).as_double() / len)/2.0, msg)) {
|
||||
rc = false; //lda .. break, not return, so that buffer is deleted
|
||||
break;
|
||||
@ -487,10 +484,10 @@ void EffectNormalize::AnalyzeData(float *buffer, size_t len)
|
||||
mCount += len;
|
||||
}
|
||||
|
||||
void EffectNormalize::ProcessData(float *buffer, size_t len)
|
||||
void EffectNormalize::ProcessData(float *buffer, size_t len, float offset)
|
||||
{
|
||||
for(decltype(len) i = 0; i < len; i++) {
|
||||
float adjFrame = (buffer[i] + mOffset) * mMult;
|
||||
float adjFrame = (buffer[i] + offset) * mMult;
|
||||
buffer[i] = adjFrame;
|
||||
}
|
||||
}
|
||||
|
@ -56,11 +56,15 @@ public:
|
||||
private:
|
||||
// EffectNormalize implementation
|
||||
|
||||
bool ProcessOne(WaveTrack * t, const wxString &msg);
|
||||
void AnalyseTrack(const WaveTrack * track, const wxString &msg);
|
||||
bool ProcessOne(
|
||||
WaveTrack * t, const wxString &msg, int curTrackNum, float offset);
|
||||
void AnalyseTrack(const WaveTrack * track, const wxString &msg,
|
||||
int curTrackNum,
|
||||
float &offset, float &min, float &max);
|
||||
void AnalyzeData(float *buffer, size_t len);
|
||||
bool AnalyseDC(const WaveTrack * track, const wxString &msg);
|
||||
void ProcessData(float *buffer, size_t len);
|
||||
bool AnalyseDC(const WaveTrack * track, const wxString &msg, int curTrackNum,
|
||||
float &offset);
|
||||
void ProcessData(float *buffer, size_t len, float offset);
|
||||
|
||||
void OnUpdateUI(wxCommandEvent & evt);
|
||||
void UpdateUI();
|
||||
@ -71,13 +75,9 @@ private:
|
||||
bool mDC;
|
||||
bool mStereoInd;
|
||||
|
||||
int mCurTrackNum;
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
float mMult;
|
||||
float mOffset;
|
||||
float mMin;
|
||||
float mMax;
|
||||
double mSum;
|
||||
sampleCount mCount;
|
||||
|
||||
|
@ -187,9 +187,9 @@ std::unique_ptr<TimeWarper> createTimeWarper(double t0, double t1, double durati
|
||||
// it are shifted along appropriately.
|
||||
bool EffectSBSMS::ProcessLabelTrack(LabelTrack *lt)
|
||||
{
|
||||
auto warper = createTimeWarper(mT0,mT1,(mT1-mT0)*mTotalStretch,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(std::make_unique<RegionTimeWarper>(mT0, mT1, std::move(warper)));
|
||||
lt->WarpLabels(*GetTimeWarper());
|
||||
auto warper1 = createTimeWarper(mT0,mT1,(mT1-mT0)*mTotalStretch,rateStart,rateEnd,rateSlideType);
|
||||
RegionTimeWarper warper{ mT0, mT1, std::move(warper1) };
|
||||
lt->WarpLabels(warper);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -372,7 +372,6 @@ bool EffectSBSMS::Process()
|
||||
maxDuration = duration;
|
||||
|
||||
auto warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
|
||||
SetTimeWarper(std::move(warper));
|
||||
|
||||
rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
|
||||
leftTrack->GetRate());
|
||||
@ -419,7 +418,7 @@ bool EffectSBSMS::Process()
|
||||
|
||||
bool bResult =
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack.get(),
|
||||
true, false, GetTimeWarper());
|
||||
true, false, warper.get());
|
||||
wxASSERT(bResult); // TO DO: Actually handle this.
|
||||
wxUnusedVar(bResult);
|
||||
|
||||
@ -427,7 +426,7 @@ bool EffectSBSMS::Process()
|
||||
{
|
||||
bResult =
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack.get(),
|
||||
true, false, GetTimeWarper());
|
||||
true, false, warper.get());
|
||||
wxASSERT(bResult); // TO DO: Actually handle this.
|
||||
}
|
||||
}
|
||||
|
@ -25,24 +25,25 @@ effect that uses SoundTouch to do its processing (ChangeTempo
|
||||
#include "TimeWarper.h"
|
||||
#include "../NoteTrack.h"
|
||||
|
||||
bool EffectSoundTouch::ProcessLabelTrack(LabelTrack *lt)
|
||||
bool EffectSoundTouch::ProcessLabelTrack(
|
||||
LabelTrack *lt, const TimeWarper &warper)
|
||||
{
|
||||
// SetTimeWarper(std::make_unique<RegionTimeWarper>(mCurT0, mCurT1,
|
||||
// std::make_unique<LinearTimeWarper>(mCurT0, mCurT0,
|
||||
// mCurT1, mCurT0 + (mCurT1-mCurT0)*mFactor)));
|
||||
lt->WarpLabels(*GetTimeWarper());
|
||||
lt->WarpLabels(warper);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_MIDI
|
||||
bool EffectSoundTouch::ProcessNoteTrack(NoteTrack *nt)
|
||||
bool EffectSoundTouch::ProcessNoteTrack(NoteTrack *nt, const TimeWarper &warper)
|
||||
{
|
||||
nt->WarpAndTransposeNotes(mCurT0, mCurT1, *GetTimeWarper(), mSemitones);
|
||||
nt->WarpAndTransposeNotes(mCurT0, mCurT1, warper, mSemitones);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool EffectSoundTouch::Process()
|
||||
bool EffectSoundTouch::ProcessWithTimeWarper(const TimeWarper &warper)
|
||||
{
|
||||
// Assumes that mSoundTouch has already been initialized
|
||||
// by the subclass for subclass-specific parameters. The
|
||||
@ -51,7 +52,7 @@ bool EffectSoundTouch::Process()
|
||||
// Check if this effect will alter the selection length; if so, we need
|
||||
// to operate on sync-lock selected tracks.
|
||||
bool mustSync = true;
|
||||
if (mT1 == GetTimeWarper()->Warp(mT1)) {
|
||||
if (mT1 == warper.Warp(mT1)) {
|
||||
mustSync = false;
|
||||
}
|
||||
|
||||
@ -70,7 +71,7 @@ bool EffectSoundTouch::Process()
|
||||
if (t->GetKind() == Track::Label &&
|
||||
(t->GetSelected() || (mustSync && t->IsSyncLockSelected())) )
|
||||
{
|
||||
if (!ProcessLabelTrack(static_cast<LabelTrack*>(t)))
|
||||
if (!ProcessLabelTrack(static_cast<LabelTrack*>(t), warper))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -80,7 +81,7 @@ bool EffectSoundTouch::Process()
|
||||
else if (t->GetKind() == Track::Note &&
|
||||
(t->GetSelected() || (mustSync && t->IsSyncLockSelected())))
|
||||
{
|
||||
if (!ProcessNoteTrack(static_cast<NoteTrack*>(t)))
|
||||
if (!ProcessNoteTrack(static_cast<NoteTrack*>(t), warper))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -123,7 +124,7 @@ bool EffectSoundTouch::Process()
|
||||
mSoundTouch->setChannels(2);
|
||||
|
||||
//ProcessStereo() (implemented below) processes a stereo track
|
||||
if (!ProcessStereo(leftTrack, rightTrack, start, end))
|
||||
if (!ProcessStereo(leftTrack, rightTrack, start, end, warper))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -138,7 +139,7 @@ bool EffectSoundTouch::Process()
|
||||
mSoundTouch->setChannels(1);
|
||||
|
||||
//ProcessOne() (implemented below) processes a single track
|
||||
if (!ProcessOne(leftTrack, start, end))
|
||||
if (!ProcessOne(leftTrack, start, end, warper))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
@ -148,7 +149,7 @@ bool EffectSoundTouch::Process()
|
||||
mCurTrackNum++;
|
||||
}
|
||||
else if (mustSync && t->IsSyncLockSelected()) {
|
||||
t->SyncLockAdjust(mT1, GetTimeWarper()->Warp(mT1));
|
||||
t->SyncLockAdjust(mT1, warper.Warp(mT1));
|
||||
}
|
||||
|
||||
//Iterate to the next track
|
||||
@ -169,7 +170,8 @@ bool EffectSoundTouch::Process()
|
||||
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
||||
//and executes ProcessSoundTouch on these blocks
|
||||
bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
||||
sampleCount start, sampleCount end)
|
||||
sampleCount start, sampleCount end,
|
||||
const TimeWarper &warper)
|
||||
{
|
||||
mSoundTouch->setSampleRate((unsigned int)(track->GetRate()+0.5));
|
||||
|
||||
@ -234,7 +236,7 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
||||
|
||||
// Take the output track and insert it in place of the original
|
||||
// sample data
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, false, GetTimeWarper());
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack.get(), true, false, &warper);
|
||||
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
m_maxNewLength = wxMax(m_maxNewLength, newLength);
|
||||
@ -243,8 +245,9 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EffectSoundTouch::ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end)
|
||||
bool EffectSoundTouch::ProcessStereo(
|
||||
WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end, const TimeWarper &warper)
|
||||
{
|
||||
mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate()+0.5));
|
||||
|
||||
@ -335,8 +338,10 @@ bool EffectSoundTouch::ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack
|
||||
|
||||
// Take the output tracks and insert in place of the original
|
||||
// sample data.
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, outputLeftTrack.get(), true, false, GetTimeWarper());
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, outputRightTrack.get(), true, false, GetTimeWarper());
|
||||
leftTrack->ClearAndPaste(
|
||||
mCurT0, mCurT1, outputLeftTrack.get(), true, false, &warper);
|
||||
rightTrack->ClearAndPaste(
|
||||
mCurT0, mCurT1, outputRightTrack.get(), true, false, &warper);
|
||||
|
||||
// Track the longest result length
|
||||
double newLength = outputLeftTrack->GetEndTime();
|
||||
|
@ -32,16 +32,13 @@
|
||||
using namespace soundtouch;
|
||||
|
||||
|
||||
class TimeWarper;
|
||||
class WaveTrack;
|
||||
|
||||
class EffectSoundTouch /* not final */ : public Effect
|
||||
{
|
||||
public:
|
||||
|
||||
// Effect implementation
|
||||
|
||||
bool Process() override;
|
||||
|
||||
// EffectSoundTouch implementation
|
||||
|
||||
#ifdef USE_MIDI
|
||||
@ -50,18 +47,25 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Effect implementation
|
||||
|
||||
bool ProcessWithTimeWarper(const TimeWarper &warper);
|
||||
|
||||
std::unique_ptr<SoundTouch> mSoundTouch;
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
|
||||
private:
|
||||
bool ProcessLabelTrack(LabelTrack *track);
|
||||
bool ProcessLabelTrack(LabelTrack *track, const TimeWarper &warper);
|
||||
#ifdef USE_MIDI
|
||||
bool ProcessNoteTrack(NoteTrack *track);
|
||||
bool ProcessNoteTrack(NoteTrack *track, const TimeWarper &warper);
|
||||
#endif
|
||||
bool ProcessOne(WaveTrack * t, sampleCount start, sampleCount end);
|
||||
bool ProcessOne(
|
||||
WaveTrack * t, sampleCount start, sampleCount end,
|
||||
const TimeWarper &warper);
|
||||
bool ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end);
|
||||
sampleCount start, sampleCount end,
|
||||
const TimeWarper &warper);
|
||||
bool ProcessStereoResults(const unsigned int outputCount,
|
||||
WaveTrack* outputLeftTrack,
|
||||
WaveTrack* outputRightTrack);
|
||||
|
@ -31,7 +31,6 @@ updating the ODPCMAliasBlockFile and the GUI of the newly available data.
|
||||
ODComputeSummaryTask::ODComputeSummaryTask()
|
||||
{
|
||||
mMaxBlockFiles = 0;
|
||||
mComputedBlockFiles = 0;
|
||||
mHasUpdateRan=false;
|
||||
}
|
||||
|
||||
@ -83,7 +82,6 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
success = true;
|
||||
blockStartSample = bf->GetStart();
|
||||
blockEndSample = blockStartSample + bf->GetLength();
|
||||
mComputedBlockFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -75,7 +75,6 @@ protected:
|
||||
ODLock mBlockFilesMutex;
|
||||
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles;
|
||||
int mMaxBlockFiles;
|
||||
int mComputedBlockFiles;
|
||||
ODLock mHasUpdateRanMutex;
|
||||
bool mHasUpdateRan;
|
||||
};
|
||||
|
@ -27,7 +27,6 @@ updating the ODDecodeBlockFile and the GUI of the newly available data.
|
||||
ODDecodeTask::ODDecodeTask()
|
||||
{
|
||||
mMaxBlockFiles = 0;
|
||||
mComputedBlockFiles = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +73,6 @@ void ODDecodeTask::DoSomeInternal()
|
||||
success = true;
|
||||
blockStartSample = bf->GetStart();
|
||||
blockEndSample = blockStartSample + bf->GetLength();
|
||||
mComputedBlockFiles++;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -93,7 +93,6 @@ protected:
|
||||
std::vector<movable_ptr<ODFileDecoder>> mDecoders;
|
||||
|
||||
int mMaxBlockFiles;
|
||||
int mComputedBlockFiles;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user