1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-23 07:29:46 +02:00

Merge branch 'master' into HEAD

This commit is contained in:
Paul Licameli 2017-04-01 11:30:12 -04:00
commit 1f0e01b8ca
46 changed files with 694 additions and 671 deletions

1
.gitignore vendored
View File

@ -177,6 +177,7 @@ win/Debug
win/Release
win/Projects/*/Debug
win/Projects/*/Release
win/.vs/
# All those help files
help/manual*

View File

@ -70,7 +70,9 @@ public:
sampleCount ( int v ) : value { v } {}
sampleCount ( unsigned v ) : value { v } {}
sampleCount ( long v ) : value { v } {}
sampleCount ( unsigned long v ) : value { v } {}
// unsigned long is 64 bit on some platforms. Let it narrow.
sampleCount ( unsigned long v ) : value ( v ) {}
// Beware implicit conversions from floating point values!
// Otherwise the meaning of binary operators with sampleCount change

View File

@ -3,10 +3,10 @@
# Antonio Paniagua Navarro <aplist@gmail.com>, 2011, 2012, 2013, 2014, 2015, 2016.
msgid ""
msgstr ""
"Project-Id-Version: Audacity 2.0.x\n"
"Project-Id-Version: Audacity 2.2.x\n"
"Report-Msgid-Bugs-To: audacity-translation@lists.sourceforge.net\n"
"POT-Creation-Date: 2017-03-18 18:41+0000\n"
"PO-Revision-Date: 2016-11-22 17:44+0100\n"
"PO-Revision-Date: 2017-03-30 02:21-0000\n"
"Last-Translator: Antonio Paniagua Navarro <aplist@gmail.com>\n"
"Language-Team: Spanish <audacity-translation@lists.sourceforge.net>\n"
"Language: es\n"
@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.5\n"
"X-Generator: Poedit 1.6.9\n"
#: lib-src/FileDialog/gtk/FileDialogPrivate.cpp:75
#, c-format
@ -3812,7 +3812,7 @@ msgstr "Pistas seleccionadas silenciadas durante %.2f segundos en %.2f"
#: src/Menus.cpp:4772 src/effects/Silence.h:22
msgid "Silence"
msgstr "Silenciar"
msgstr "Silencio"
#: src/Menus.cpp:4803
msgid "Duplicated"

View File

@ -1,141 +1,100 @@
;nyquist plug-in
;version 1
;version 4
;type process
;preview enabled
;categories "http://audacityteam.org/namespace#NoiseRemoval"
;name "Clip Fix..."
;action "Reconstructing clips..."
;author "Benjamin Schwartz"
;author "Benjamin Schwartz and Steve Daulton"
;copyright "Licensing confirmed under terms of the GNU General Public License version 2"
;; clipfix.ny by Benjamin Schwartz.
;; Licensing confirmed under terms of the GNU General Public License version 2:
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
;; with kind agreement of Benjamin Schwartz, December 2011.
;; GUI updated by Steve Daulton July 2012
;;
;; For information about writing and modifying Nyquist plug-ins:
;; http://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference
;; Algorithm by Benjamin Schwartz
;; Clip Fix is a simple, stupid (but not blind) digital-clipping-corrector
;; The algorithm is fairly simple:
;; 1. Find all clipped regions
;; 2. Get the slope immediately on either side of the region
;; 3. Do a cubic spline interpolation.
;; 4. Go to next region
;control thresh "Threshold of Clipping (%)" real "" 95 0 100
;control threshold "Threshold of Clipping (%)" float "" 95 0 100
;control gain "Reduce amplitude to allow for restored peaks (dB)" float "" -9 -30 0
(setf largenumber 100000000) ;;Largest number of samples that can be imported
(setf blocksize 100000)
;;Clip Fix is a simple, stupid (but not blind) digital-clipping-corrector
;;The algorithm is fairly simple:
;;1. Find all clipped regions
;;2. Get the slope immediately on either side of the region
;;3. Do a cubic spline interpolation.
;;4. Go to next region
;;Coded from start (didn't know lisp (well, scheme, but not not lisp and certainly not
;;some XLISP 2.0 derivative)) to finish
;;(fully working, more or less) in one afternoon (and some evening).
;;Written by Benjamin Schwartz, MIT class of 2006, on May 25, 2004.
;;Explanatory text added by Gale Andrews, May 2008.
(defun declip (sin) ;;Central function
(let* ((threshold (* (peak sin largenumber) thresh 0.01))
(s2 (snd-copy sin))
(samplerate (snd-srate s2))
(s2length (snd-length s2 largenumber)))
(seqrep (i (1+ (/ s2length blocksize)))
(let ((l (min blocksize (- s2length (* i blocksize)))))
;;(print (list i t0 l samplerate))
(snd-from-array 0 samplerate
(workhorse
;;(let () (print (list s2 (type-of s2) l (type-of l)))
(snd-fetch-array s2 l l)
;;)
threshold))))
;;(setf r (snd-fetch-array (snd-copy s) (snd-length s largenumber) 1)) ;;Create a sound array
;;(snd-from-array (snd-t0 s) (snd-srate s) (workhorse r threshold))
))
(defun workhorse (r threshold)
(setf n (length r)) ;; Record its length
(setf exithigh ()) ;;Times when the wavefrom left the allowed region
(setf returnhigh ()) ;;Times when it returned to the allowed region
(setf drange 4)
(let ((i drange) (max (- n drange))) ;;Leave room at ends for derivative processing
(while (< i max)
(if (>= (aref r i) threshold)
(if (< (aref r (- i 1)) threshold)
(setq exithigh (cons (- i 1) exithigh))) ;;We just crossed the threshold up
(if (>= (aref r (- i 1)) threshold)
(setq returnhigh (cons i returnhigh)))) ;;We just crossed the threshold down
(setq i (1+ i))))
(setq exithigh (reverse exithigh)) ;;List comes out backwards
(setq returnhigh (reverse returnhigh))
(if (>= (aref r (1- drange)) threshold) ;;If the audio begins in a clipped region, ignore
(setq returnhigh (cdr returnhigh))) ;the extra return from threshold
(setf exitlow ()) ;; Same as above, but for the bottom threshold
(setf returnlow ())
(setf threshlow (* -1 threshold)) ;;Assumes your digital range is zero-centered
(setf threshold (/ threshold 100))
(setf gain (db-to-linear gain))
(setf buffersize 100000)
(setf slopelength 4) ; number of samples used to calculate the exit / re-entry slope
(let ((i drange) (max (- n drange)))
(while (< i max)
(if (<= (aref r i) threshlow)
(if (> (aref r (- i 1)) threshlow)
(setq exitlow (cons (- i 1) exitlow)))
(if (<= (aref r (- i 1)) threshlow)
(setq returnlow (cons i returnlow))))
(setq i (1+ i))))
(defun declip (sig thresh peak)
(let* ((threshold (* thresh peak))
(ln (truncate len))
(finalbufsize (rem ln buffersize)))
;; Calculate the number of buffers we can process.
;; if final buffer is not large enough for de-clipping we
;; will just add it on the end as is.
(if (>= finalbufsize slopelength)
(setf buffercount (1+ (/ ln buffersize)))
(setf buffercount (/ ln buffersize)))
;;; Make output sequence from processed buffers
(setf out
(seqrep (i buffercount)
(let* ((step (min buffersize (- ln (* i buffersize))))
(buffer (snd-fetch-array sig step step))
(processed (process buffer threshold step)))
(cue (mult gain
(snd-from-array 0 *sound-srate* processed))))))
;;; If there's unprocessed audio remaining, add it to the end
(if (and (> finalbufsize 0)(< finalbufsize slopelength))
(seq out (cue (getfinalblock sig finalbufsize gain)))
out)))
(setq exitlow (reverse exitlow))
(setq returnlow (reverse returnlow))
(if (<= (aref r (1- drange)) threshlow)
(setq returnlow (cdr returnlow)))
(defun getfinalblock (sig step gain)
(let ((block (snd-fetch-array sig step step)))
(mult gain (snd-from-array 0 *sound-srate* block))))
(while (and exithigh returnhigh) ;;If there are more clipped regions
(let* ((t1 (car exithigh)) ;;exit time
(t2 (car returnhigh)) ;;return time
(d1 (max 0 (/ (- (aref r t1) (aref r (- t1 (1- drange)))) (1- drange)))) ;;slope at exit
(d2 (min 0 (/ (- (aref r (+ t2 (1- drange))) (aref r t2)) (1- drange)))) ;;slope at return
(m (/ (+ d2 d1) (* (- t2 t1) (- t2 t1)))) ;;interpolation is by (t-t1)(t-t2)(mx+b)
(b (- (/ d2 (- t2 t1)) (* m t2))) ;;These values of m and b make the cubic seamless
(j (1+ t1))) ;; j is the index
(while (< j t2)
(setf (aref r j) (+ (aref r t1) (* (- j t1) (- j t2) (+ (* m j) b))))
(setf (aref r j) (+ (* (- t2 j) (/ (aref r t1) (- t2 t1))) (* (- j t1) (/ (aref r t2) (- t2 t1))) (* (- j t1) (- j t2) (+ (* m j) b))))
(setq j (1+ j))))
(setq exithigh (cdr exithigh))
(setq returnhigh (cdr returnhigh)))
(defun process (buffer threshold bufferlength)
;;; Find threshold crossings
(setf exit-list ()) ; list of times when waveform exceeds threshold
(setf return-list ()) ; list of times when waveform returns below threshold
;; Limitation of algorithm: the first and last 'slopelength' at ends of buffer are ignored
;; so that we have enough samples beyond the threshold crossing to calculate the slope.
(let ((last-sample (- bufferlength slopelength)))
(do ((i slopelength (1+ i)))
((>= i last-sample))
(if (>= (abs (aref buffer i)) threshold)
(when (< (abs (aref buffer (- i 1))) threshold) ; we just crossed threshold
(push (- i 1) exit-list))
(when (>= (abs (aref buffer (- i 1))) threshold) ; we just got back in range
(push i return-list)))))
;; Reverse lists back into chronological order.
;; This is faster than appending values in chronological order.
(setf exit-list (reverse exit-list))
(setf return-list (reverse return-list))
;; If the audio begins in a clipped region, discard the first return
(when (>= (abs (aref buffer (1- slopelength))) threshold)
(setq return-list (cdr return-list)))
;; Interpolate between each pair of exit / entry points
(let ((slopelen (1- slopelength)))
(mapc (lambda (t0 t1)
(interpolate buffer t0 t1 slopelen))
exit-list return-list))
buffer)
(while (and exitlow returnlow) ;;Same for bottom
(let* ((t1 (car exitlow))
(t2 (car returnlow))
(d1 (min 0 (/ (- (aref r t1) (aref r (- t1 (1- drange)))) (1- drange)))) ;;slope at exit
(d2 (max 0 (/ (- (aref r (+ t2 (1- drange))) (aref r t2)) (1- drange)))) ;;slope at return
(m (/ (+ d2 d1) (* (- t2 t1) (- t2 t1))))
(b (- (/ d2 (- t2 t1)) (* m t2)))
(a (/ (+ (aref r t1) (aref r t2)) 2))
(j (1+ t1)))
(while (< j t2)
(setf (aref r j) (+ (* (- t2 j) (/ (aref r t1) (- t2 t1))) (* (- j t1) (/ (aref r t2) (- t2 t1))) (* (- j t1) (- j t2) (+ (* m j) b))))
(setq j (1+ j))))
(setq exitlow (cdr exitlow))
(setq returnlow (cdr returnlow)))
r)
(defun interpolate (buffer t0 t1 dur)
"Cubic spline interpolation"
(let* ((d0 (/ (- (aref buffer t0) (aref buffer (- t0 dur))) dur)) ; slope at start
(d1 (/ (- (aref buffer (+ t1 dur)) (aref buffer t1)) dur)) ; slope at end
(m (/ (+ d1 d0) (* (- t1 t0) (- t1 t0))))
(b (- (/ d1 (- t1 t0)) (* m t1))))
(do ((j (1+ t0) (1+ j)))
((= j t1))
(setf (aref buffer j)
(+ (* (- t1 j) (/ (aref buffer t0) (- t1 t0)))
(* (- j t0) (/ (aref buffer t1) (- t1 t0)))
(* (- j t0) (- j t1) (+ (* m j) b)))))))
(if (arrayp s)
(dotimes (j (length s))
(setf (aref s j) (declip (aref s j))))
(setq s (declip s)))
s
;; (get '*selection* 'peak) introduced in Audacity 2.1.3
(multichan-expand #'declip *track* threshold (get '*selection* 'peak))

View File

@ -50,6 +50,21 @@ MessageBoxException::~MessageBoxException()
wxAtomicDec( sOutstandingMessages );
}
SimpleMessageBoxException::~SimpleMessageBoxException()
{
}
wxString SimpleMessageBoxException::ErrorMessage() const
{
return message;
}
std::unique_ptr< AudacityException > SimpleMessageBoxException::Move()
{
return std::unique_ptr< AudacityException >
{ safenew SimpleMessageBoxException{ std::move( *this ) } };
}
// This is meant to be invoked via wxEvtHandler::CallAfter
void MessageBoxException::DelayedHandlerAction()
{

View File

@ -69,6 +69,30 @@ private:
mutable bool moved { false };
};
// MessageBoxException that shows a given, unvarying string.
class SimpleMessageBoxException /* not final */ : public MessageBoxException
{
public:
explicit SimpleMessageBoxException( const wxString &message_,
const wxString &caption = wxString{} )
: MessageBoxException{ caption }
, message{ message_ }
{}
~SimpleMessageBoxException() override;
SimpleMessageBoxException( const SimpleMessageBoxException& ) = default;
SimpleMessageBoxException &operator = (
SimpleMessageBoxException && ) PROHIBITED;
std::unique_ptr< AudacityException > Move() override;
// Format a default, internationalized error message for this exception.
virtual wxString ErrorMessage() const override;
private:
wxString message;
};
struct DefaultDelayedHandlerAction
{
void operator () (AudacityException *pException) const

View File

@ -2474,13 +2474,10 @@ void AudioIO::StopStream()
}
if( appendRecord )
{ // append-recording
bool bResult;
if (recordingOffset < 0)
bResult = track->Clear(mT0, mT0 - recordingOffset); // cut the latency out
track->Clear(mT0, mT0 - recordingOffset); // cut the latency out
else
bResult = track->InsertSilence(mT0, recordingOffset); // put silence in
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
track->InsertSilence(mT0, recordingOffset); // put silence in
}
else
{ // recording into a NEW track

View File

@ -337,11 +337,14 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
// Rememebr the old blocksize, so that we can restore it later.
auto oldBlockSize = Sequence::GetMaxDiskBlockSize();
const auto cleanup = finally([=]
{ Sequence::SetMaxDiskBlockSize(oldBlockSize); }
);
Sequence::SetMaxDiskBlockSize(blockSize * 1024);
const auto cleanup = finally( [&] {
Sequence::SetMaxDiskBlockSize(oldBlockSize);
gPrefs->Write(wxT("/GUI/EditClipCanMove"), editClipCanMove);
gPrefs->Flush();
} );
wxBusyCursor busy;
HoldPrint(true);
@ -426,8 +429,11 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
if (mEditDetail)
Printf(wxT("Cut: %d - %d \n"), x0 * chunkSize, (x0 + xlen) * chunkSize);
auto tmp = t->Cut(double (x0 * chunkSize), double ((x0 + xlen) * chunkSize));
if (!tmp) {
Track::Holder tmp;
try {
tmp = t->Cut(double (x0 * chunkSize), double ((x0 + xlen) * chunkSize));
}
catch (const AudacityException&) {
Printf(wxT("Trial %d\n"), z);
Printf(wxT("Cut (%d, %d) failed.\n"), (x0 * chunkSize),
(x0 + xlen) * chunkSize);
@ -443,8 +449,10 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
if (mEditDetail)
Printf(wxT("Paste: %d\n"), y0 * chunkSize);
if (!t->Paste((double)(y0 * chunkSize), tmp.get()))
{
try {
t->Paste((double)(y0 * chunkSize), tmp.get());
}
catch (const AudacityException&) {
Printf(wxT("Trial %d\nFailed on Paste.\n"), z);
goto fail;
}
@ -540,7 +548,4 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
Printf(wxT("Benchmark completed successfully.\n"));
HoldPrint(false);
gPrefs->Write(wxT("/GUI/EditClipCanMove"), editClipCanMove);
gPrefs->Flush();
}

View File

@ -198,7 +198,7 @@ EnvPoint *Envelope::AddPointAtEnd( double t, double val )
void Envelope::CopyFrom(const Envelope *e, double t0, double t1)
{
wxASSERT( t0 < t1 );
wxASSERT( t0 <= t1 );
mOffset = wxMax(t0, e->mOffset);
mTrackLen = wxMin(t1, e->mOffset + e->mTrackLen) - mOffset;

View File

@ -22,7 +22,7 @@ public:
const wxString &caption = wxString{},
const wxFileName &renameTarget_ = {})
: MessageBoxException{ caption }
, fileName{ fileName_ }, cause{ cause_ }, renameTarget{ renameTarget_ }
, cause{ cause_ }, fileName{ fileName_ }, renameTarget{ renameTarget_ }
{}
FileException(FileException&& that)

View File

@ -153,7 +153,7 @@ void LabelTrack::SetOffset(double dOffset)
labelStruct.selectedRegion.move(dOffset);
}
bool LabelTrack::Clear(double b, double e)
void LabelTrack::Clear(double b, double e)
{
// May DELETE labels, so use subscripts to iterate
for (size_t i = 0; i < mLabels.size(); ++i) {
@ -175,8 +175,6 @@ bool LabelTrack::Clear(double b, double e)
else if (relation == LabelStruct::WITHIN_LABEL)
labelStruct.selectedRegion.moveT1( - (e-b));
}
return true;
}
#if 0
@ -2339,10 +2337,8 @@ bool LabelTrack::Save(wxTextFile * out, bool overwrite)
Track::Holder LabelTrack::Cut(double t0, double t1)
{
auto tmp = Copy(t0, t1);
if (!tmp)
return{};
if (!Clear(t0, t1))
return{};
Clear(t0, t1);
return tmp;
}
@ -2353,8 +2349,7 @@ Track::Holder LabelTrack::SplitCut(double t0, double t1)
// SplitCut() == Copy() + SplitDelete()
Track::Holder tmp = Copy(t0, t1);
if (!tmp)
return {};
if (!SplitDelete(t0, t1))
return {};
@ -2417,6 +2412,7 @@ Track::Holder LabelTrack::Copy(double t0, double t1, bool) const
bool LabelTrack::PasteOver(double t, const Track * src)
{
if (src->GetKind() != Track::Label)
// THROW_INCONSISTENCY_EXCEPTION; // ?
return false;
int len = mLabels.size();
@ -2440,17 +2436,18 @@ bool LabelTrack::PasteOver(double t, const Track * src)
return true;
}
bool LabelTrack::Paste(double t, const Track *src)
void LabelTrack::Paste(double t, const Track *src)
{
if (src->GetKind() != Track::Label)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
LabelTrack *lt = (LabelTrack *)src;
double shiftAmt = lt->mClipLen > 0.0 ? lt->mClipLen : lt->GetEndTime();
ShiftLabelsOnInsert(shiftAmt, t);
return PasteOver(t, src);
PasteOver(t, src);
}
// This repeats the labels in a time interval a specified number of times.
@ -2506,7 +2503,7 @@ bool LabelTrack::Repeat(double t0, double t1, int n)
return true;
}
bool LabelTrack::Silence(double t0, double t1)
void LabelTrack::Silence(double t0, double t1)
{
int len = mLabels.size();
@ -2550,11 +2547,9 @@ bool LabelTrack::Silence(double t0, double t1)
}
SortLabels();
return true;
}
bool LabelTrack::InsertSilence(double t, double len)
void LabelTrack::InsertSilence(double t, double len)
{
for (auto &labelStruct: mLabels) {
double t0 = labelStruct.getT0();
@ -2566,8 +2561,6 @@ bool LabelTrack::InsertSilence(double t, double len)
t1 += len;
labelStruct.selectedRegion.setTimes(t0, t1);
}
return true;
}
int LabelTrack::GetNumLabels() const

View File

@ -156,12 +156,12 @@ class AUDACITY_DLL_API LabelTrack final : public Track
Track::Holder Cut (double t0, double t1) override;
Track::Holder Copy (double t0, double t1, bool forClipboard = true) const override;
bool Clear(double t0, double t1) override;
bool Paste(double t, const Track * src) override;
void Clear(double t0, double t1) override;
void Paste(double t, const Track * src) override;
bool Repeat(double t0, double t1, int n);
bool Silence(double t0, double t1) override;
bool InsertSilence(double t, double len) override;
void Silence(double t0, double t1) override;
void InsertSilence(double t, double len) override;
int OverGlyph(int x, int y);
static wxBitmap & GetGlyph( int i);

View File

@ -4177,8 +4177,7 @@ void AudacityProject::OnCut()
dest = n->Copy(mViewInfo.selectedRegion.t0(),
mViewInfo.selectedRegion.t1());
if (dest)
FinishCopy(n, std::move(dest), newClipboard);
FinishCopy(n, std::move(dest), newClipboard);
}
n = iter.Next();
}
@ -4309,8 +4308,7 @@ void AudacityProject::OnCopy()
if (n->GetSelected()) {
auto dest = n->Copy(mViewInfo.selectedRegion.t0(),
mViewInfo.selectedRegion.t1());
if (dest)
FinishCopy(n, std::move(dest), newClipboard);
FinishCopy(n, std::move(dest), newClipboard);
}
n = iter.Next();
}
@ -4351,31 +4349,29 @@ void AudacityProject::OnPaste()
if (c == NULL)
return;
Track *ff = NULL;
const Track *tmpSrc = NULL;
const Track *tmpC = NULL;
const Track *prev = NULL;
const Track *lastClipBeforeMismatch = NULL;
const Track *mismatchedClip = NULL;
const Track *prevClip = NULL;
bool bAdvanceClipboard = true;
bool bPastedSomething = false;
bool bTrackTypeMismatch = false;
while (n && c) {
if (n->GetSelected()) {
bAdvanceClipboard = true;
if (tmpC)
c = tmpC;
if (mismatchedClip)
c = mismatchedClip;
if (c->GetKind() != n->GetKind()) {
if (!bTrackTypeMismatch) {
tmpSrc = prev;
tmpC = c;
if (!mismatchedClip) {
lastClipBeforeMismatch = prevClip;
mismatchedClip = c;
}
bTrackTypeMismatch = true;
bAdvanceClipboard = false;
c = tmpSrc;
c = lastClipBeforeMismatch;
// If the types still don't match...
while (c && c->GetKind() != n->GetKind()) {
prev = c;
prevClip = c;
c = clipIter.Next();
}
}
@ -4383,12 +4379,16 @@ void AudacityProject::OnPaste()
// Handle case where the first track in clipboard
// is of different type than the first selected track
if (!c) {
c = tmpC;
c = mismatchedClip;
while (n && (c->GetKind() != n->GetKind() || !n->GetSelected()))
{
// Must perform sync-lock adjustment before incrementing n
if (n->IsSyncLockSelected()) {
bPastedSomething |= n->SyncLockAdjust(t1, t0+(msClipT1 - msClipT0));
auto newT1 = t0 + (msClipT1 - msClipT0);
if (t1 != newT1 && t1 <= n->GetEndTime()) {
n->SyncLockAdjust(t1, newT1);
bPastedSomething = true;
}
}
n = iter.Next();
}
@ -4399,39 +4399,40 @@ void AudacityProject::OnPaste()
// The last possible case for cross-type pastes: triggered when we try to
// paste 1+ tracks from one type into 1+ tracks of another type. If
// there's a mix of types, this shouldn't run.
if (!c) {
wxMessageBox(
_("Pasting one type of track into another is not allowed."),
_("Error"), wxICON_ERROR, this);
c = n;//so we don't trigger any !c conditions on our way out
break;
}
if (!c)
// Throw, so that any previous changes to the project in this loop
// are discarded.
throw SimpleMessageBoxException{
_("Pasting one type of track into another is not allowed.")
};
// When trying to copy from stereo to mono track, show error and exit
// TODO: Automatically offer user to mix down to mono (unfortunately
// this is not easy to implement
if (c->GetLinked() && !n->GetLinked())
{
wxMessageBox(
_("Copying stereo audio into a mono track is not allowed."),
_("Error"), wxICON_ERROR, this);
break;
}
// Throw, so that any previous changes to the project in this loop
// are discarded.
throw SimpleMessageBoxException{
_("Copying stereo audio into a mono track is not allowed.")
};
if (!ff)
ff = n;
Maybe<WaveTrack::Locker> locker;
if (msClipProject != this && c->GetKind() == Track::Wave)
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(static_cast<const WaveTrack*>(c));
if (c->GetKind() == Track::Wave && n && n->GetKind() == Track::Wave)
wxASSERT( n && c );
if (c->GetKind() == Track::Wave && n->GetKind() == Track::Wave)
{
bPastedSomething |=
((WaveTrack*)n)->ClearAndPaste(t0, t1, (WaveTrack*)c, true, true);
bPastedSomething = true;
((WaveTrack*)n)->ClearAndPaste(t0, t1, (WaveTrack*)c, true, true);
}
else if (c->GetKind() == Track::Label &&
n && n->GetKind() == Track::Label)
n->GetKind() == Track::Label)
{
((LabelTrack *)n)->Clear(t0, t1);
@ -4444,7 +4445,9 @@ void AudacityProject::OnPaste()
}
else
{
bPastedSomething |= n->Paste(t0, c);
bPastedSomething = true;
n->Clear(t0, t1);
n->Paste(t0, c);
}
// When copying from mono to stereo track, paste the wave form
@ -4454,23 +4457,29 @@ void AudacityProject::OnPaste()
n = iter.Next();
if (n->GetKind() == Track::Wave) {
bPastedSomething |= ((WaveTrack *)n)->ClearAndPaste(t0, t1, c, true, true);
bPastedSomething = true;
((WaveTrack *)n)->ClearAndPaste(t0, t1, c, true, true);
}
else
{
n->Clear(t0, t1);
bPastedSomething |= n->Paste(t0, c);
bPastedSomething = true;
n->Paste(t0, c);
}
}
if (bAdvanceClipboard){
prev = c;
prevClip = c;
c = clipIter.Next();
}
} // if (n->GetSelected())
else if (n->IsSyncLockSelected())
{
bPastedSomething |= n->SyncLockAdjust(t1, t0 + msClipT1 - msClipT0);
auto newT1 = t0 + (msClipT1 - msClipT0);
if (t1 != newT1 && t1 <= n->GetEndTime()) {
n->SyncLockAdjust(t1, newT1);
bPastedSomething = true;
}
}
n = iter.Next();
@ -4487,19 +4496,18 @@ void AudacityProject::OnPaste()
while (n) {
if (n->GetSelected() && n->GetKind()==Track::Wave) {
if (c && c->GetKind() == Track::Wave) {
bPastedSomething |=
((WaveTrack *)n)->ClearAndPaste(t0, t1, (WaveTrack *)c, true, true);
if (c) {
wxASSERT(c->GetKind() == Track::Wave);
bPastedSomething = true;
((WaveTrack *)n)->ClearAndPaste(t0, t1, (WaveTrack *)c, true, true);
}
else {
auto tmp = mTrackFactory->NewWaveTrack( ((WaveTrack*)n)->GetSampleFormat(), ((WaveTrack*)n)->GetRate());
bool bResult = tmp->InsertSilence(0.0, msClipT1 - msClipT0); // MJS: Is this correct?
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
tmp->InsertSilence(0.0, msClipT1 - msClipT0); // MJS: Is this correct?
tmp->Flush();
bPastedSomething |=
((WaveTrack *)n)->ClearAndPaste(t0, t1, tmp.get(), true, true);
bPastedSomething = true;
((WaveTrack *)n)->ClearAndPaste(t0, t1, tmp.get(), true, true);
}
}
else if (n->GetKind() == Track::Label && n->GetSelected())
@ -4598,44 +4606,56 @@ bool AudacityProject::HandlePasteNothingSelected()
while (pClip) {
Maybe<WaveTrack::Locker> locker;
if ((msClipProject != this) && (pClip->GetKind() == Track::Wave))
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(static_cast<const WaveTrack*>(pClip));
Track::Holder pNewTrack;
Track::Holder uNewTrack;
Track *pNewTrack;
switch (pClip->GetKind()) {
case Track::Wave:
{
WaveTrack *w = (WaveTrack *)pClip;
pNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate());
uNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate()),
pNewTrack = uNewTrack.get();
}
break;
#ifdef USE_MIDI
case Track::Note:
pNewTrack = mTrackFactory->NewNoteTrack();
uNewTrack = mTrackFactory->NewNoteTrack(),
pNewTrack = uNewTrack.get();
break;
#endif // USE_MIDI
case Track::Label:
pNewTrack = mTrackFactory->NewLabelTrack();
uNewTrack = mTrackFactory->NewLabelTrack(),
pNewTrack = uNewTrack.get();
break;
case Track::Time:
pNewTrack = mTrackFactory->NewTimeTrack();
case Track::Time: {
// Maintain uniqueness of the time track!
pNewTrack = GetTracks()->GetTimeTrack();
if (!pNewTrack)
uNewTrack = mTrackFactory->NewTimeTrack(),
pNewTrack = uNewTrack.get();
break;
}
default:
pClip = iterClip.Next();
continue;
}
wxASSERT(pClip);
bool bResult = pNewTrack->Paste(0.0, pClip);
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
pNewTrack->Paste(0.0, pClip);
if (!pFirstNewTrack)
pFirstNewTrack = pNewTrack.get();
pFirstNewTrack = pNewTrack;
pNewTrack->SetSelected(true);
FinishCopy(pClip, std::move(pNewTrack), *mTracks);
if (uNewTrack)
FinishCopy(pClip, std::move(uNewTrack), *mTracks);
else
FinishCopy(pClip, pNewTrack);
pClip = iterClip.Next();
}
@ -4899,11 +4919,9 @@ void AudacityProject::OnDuplicate()
// Make copies not for clipboard but for direct addition to the project
auto dest = n->Copy(mViewInfo.selectedRegion.t0(),
mViewInfo.selectedRegion.t1(), false);
if (dest) {
dest->Init(*n);
dest->SetOffset(wxMax(mViewInfo.selectedRegion.t0(), n->GetOffset()));
mTracks->Add(std::move(dest));
}
dest->Init(*n);
dest->SetOffset(wxMax(mViewInfo.selectedRegion.t0(), n->GetOffset()));
mTracks->Add(std::move(dest));
}
if (n == l) {
@ -5114,22 +5132,19 @@ void AudacityProject::OnSplit()
double sel0 = mViewInfo.selectedRegion.t0();
double sel1 = mViewInfo.selectedRegion.t1();
dest = NULL;
n->Copy(sel0, sel1, &dest);
if (dest) {
dest->Init(*n);
dest->SetOffset(wxMax(sel0, n->GetOffset()));
dest = n->Copy(sel0, sel1);
dest->Init(*n);
dest->SetOffset(wxMax(sel0, n->GetOffset()));
if (sel1 >= n->GetEndTime())
n->Clear(sel0, sel1);
else if (sel0 <= n->GetOffset()) {
n->Clear(sel0, sel1);
n->SetOffset(sel1);
} else
n->Silence(sel0, sel1);
if (sel1 >= n->GetEndTime())
n->Clear(sel0, sel1);
else if (sel0 <= n->GetOffset()) {
n->Clear(sel0, sel1);
n->SetOffset(sel1);
} else
n->Silence(sel0, sel1);
newTracks.Add(dest);
}
newTracks.Add(dest);
}
n = iter.Next();
}
@ -5175,10 +5190,8 @@ void AudacityProject::OnSplitNew()
mViewInfo.selectedRegion.t1());
}
#endif
if (dest) {
dest->SetOffset(wxMax(newt0, offset));
FinishCopy(n, std::move(dest), *mTracks);
}
dest->SetOffset(wxMax(newt0, offset));
FinishCopy(n, std::move(dest), *mTracks);
}
if (n == l) {
@ -7225,8 +7238,7 @@ void AudacityProject::OnResample()
// But the thrown exception will cause rollback in the application
// level handler.
if (!((WaveTrack*)t)->Resample(newRate, &progress))
break;
((WaveTrack*)t)->Resample(newRate, &progress);
// Each time a track is successfully, completely resampled,
// commit that to the undo stack. The second and later times,

View File

@ -255,7 +255,7 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
, mQueueMaxLen{ 65536 }
, mSampleQueue{ mNumInputTracks, mQueueMaxLen }
, mNumChannels{ static_cast<size_t>(numOutChannels) }
, mNumChannels{ numOutChannels }
, mGains{ mNumChannels }
, mMayThrow{ mayThrow }

View File

@ -191,6 +191,7 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
size.GetHeight() - ctrlPos.y - kQuadrupleInset;
ctrlSize.Set(kLeftSideStackWidth - kQuadrupleInset, nGainSliderHeight);
#ifdef USE_MIDI
if (GetNote()) {
mSlider_Gain =
safenew MixerTrackSlider(
@ -201,6 +202,7 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
true, 0.0, wxVERTICAL);
}
else
#endif
mSlider_Gain =
safenew MixerTrackSlider(
this, ID_SLIDER_GAIN,
@ -322,15 +324,17 @@ WaveTrack *MixerTrackCluster::GetRight() const
{
auto left = GetWave();
if (left)
return static_cast<WaveTrack*>(left);
return static_cast<WaveTrack*>(left->GetLink());
else
return nullptr;
}
#ifdef USE_MIDI
NoteTrack *MixerTrackCluster::GetNote() const
{
return dynamic_cast< NoteTrack * >( mTrack );
}
#endif
void MixerTrackCluster::UpdatePrefs()
{

View File

@ -435,7 +435,8 @@ int NoteTrack::GetVisibleChannels()
Track::Holder NoteTrack::Cut(double t0, double t1)
{
if (t1 <= t0)
return{};
//THROW_INCONSISTENCY_EXCEPTION
;
double len = t1-t0;
auto newTrack = std::make_unique<NoteTrack>(mDirManager);
@ -457,7 +458,8 @@ Track::Holder NoteTrack::Cut(double t0, double t1)
Track::Holder NoteTrack::Copy(double t0, double t1, bool) const
{
if (t1 <= t0)
return{};
//THROW_INCONSISTENCY_EXCEPTION
;
double len = t1-t0;
auto newTrack = std::make_unique<NoteTrack>(mDirManager);
@ -490,20 +492,19 @@ bool NoteTrack::Trim(double t0, double t1)
return true;
}
bool NoteTrack::Clear(double t0, double t1)
void NoteTrack::Clear(double t0, double t1)
{
// If t1 = t0, should Clear return true?
if (t1 <= t0)
return false;
// THROW_INCONSISTENCY_EXCEPTION; ?
return;
double len = t1-t0;
if (mSeq)
mSeq->clear(t0 - GetOffset(), len, false);
return true;
}
bool NoteTrack::Paste(double t, const Track *src)
void NoteTrack::Paste(double t, const Track *src)
{
// Paste inserts src at time t. If src has a positive offset,
// the offset is treated as silence which is also inserted. If
@ -515,11 +516,13 @@ bool NoteTrack::Paste(double t, const Track *src)
//Check that src is a non-NULL NoteTrack
if (src == NULL || src->GetKind() != Track::Note)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
NoteTrack* other = (NoteTrack*)src;
if (other->mSeq == NULL)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
if(!mSeq)
mSeq = std::make_unique<Alg_seq>();
@ -530,8 +533,16 @@ bool NoteTrack::Paste(double t, const Track *src)
t += other->GetOffset();
}
mSeq->paste(t - GetOffset(), other->mSeq.get());
}
return true;
void NoteTrack::Silence(double, double)
{
// to do
}
void NoteTrack::InsertSilence(double, double)
{
// to do
}
// Call this function to manipulate the underlying sequence data. This is
@ -758,6 +769,8 @@ bool NoteTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
double dblValue;
if (!wxStrcmp(attr, wxT("name")) && XMLValueChecker::IsGoodString(strValue))
mName = strValue;
else if (this->NoteTrackBase::HandleXMLAttribute(attr, value))
{}
else if (!wxStrcmp(attr, wxT("offset")) &&
XMLValueChecker::IsGoodString(strValue) &&
Internat::CompatibleToDouble(strValue, &dblValue))
@ -831,10 +844,7 @@ void NoteTrack::WriteXML(XMLWriter &xmlFile) const
saveme->mSeq->write(data, true);
xmlFile.StartTag(wxT("notetrack"));
xmlFile.WriteAttr(wxT("name"), saveme->mName);
#ifdef EXPERIMENTAL_MIDI_OUT
xmlFile.WriteAttr(wxT("mute"), mMute);
xmlFile.WriteAttr(wxT("solo"), mSolo);
#endif
this->NoteTrackBase::WriteXMLAttributes(xmlFile);
xmlFile.WriteAttr(wxT("offset"), saveme->GetOffset());
xmlFile.WriteAttr(wxT("visiblechannels"), saveme->mVisibleChannels);
xmlFile.WriteAttr(wxT("height"), saveme->GetActualHeight());

View File

@ -103,8 +103,10 @@ class AUDACITY_DLL_API NoteTrack final
Track::Holder Cut (double t0, double t1) override;
Track::Holder Copy (double t0, double t1, bool forClipboard = true) const override;
bool Trim (double t0, double t1) /* not override */;
bool Clear(double t0, double t1) override;
bool Paste(double t, const Track *src) override;
void Clear(double t0, double t1) override;
void Paste(double t, const Track *src) override;
void Silence(double t0, double t1) override;
void InsertSilence(double t, double len) override;
bool Shift(double t) /* not override */;
#ifdef EXPERIMENTAL_MIDI_OUT

View File

@ -4993,9 +4993,7 @@ void AudacityProject::EditClipboardByLabel( EditDestFunction action )
// right to left. Any placeholder already in merged is kept.
// Only the rightmost placeholder is important in the final
// result.
bool bResult = merged->Paste( 0.0 , dest.get() );
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
merged->Paste( 0.0 , dest.get() );
}
}
else // nothing copied but there is a 'region', so the 'region' must be a 'point label' so offset

View File

@ -382,7 +382,7 @@ public:
void SkipEnd(bool shift);
typedef bool (WaveTrack::* EditFunction)(double, double);
typedef void (WaveTrack::* EditFunction)(double, double);
typedef std::unique_ptr<Track> (WaveTrack::* EditDestFunction)(double, double);
void EditByLabel(EditFunction action, bool bSyncLockedTracks);

View File

@ -378,8 +378,10 @@ float Sequence::GetRMS(sampleCount start, sampleCount len, bool mayThrow) const
std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
{
if (s0 >= s1 || s0 >= mNumSamples || s1 < 0)
return {};
auto dest = std::make_unique<Sequence>(mDirManager, mSampleFormat);
if (s0 >= s1 || s0 >= mNumSamples || s1 < 0) {
return dest;
}
int numBlocks = mBlock.size();
@ -391,7 +393,6 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
wxUnusedVar(numBlocks);
wxASSERT(b0 <= b1);
auto dest = std::make_unique<Sequence>(mDirManager, mSampleFormat);
dest->mBlock.reserve(b1 - b0 + 1);
SampleBuffer buffer(mMaxSamples, mSampleFormat);
@ -437,7 +438,8 @@ std::unique_ptr<Sequence> Sequence::Copy(sampleCount s0, sampleCount s1) const
}
if (! ConsistencyCheck(wxT("Sequence::Copy()")))
return {};
//THROW_INCONSISTENCY_EXCEPTION
;
return dest;
}
@ -1113,6 +1115,7 @@ int Sequence::FindBlock(sampleCount pos) const
return rval;
}
//static
bool Sequence::Read(samplePtr buffer, sampleFormat format,
const SeqBlock &b, size_t blockRelativeStart, size_t len,
bool mayThrow)
@ -1297,7 +1300,7 @@ struct MinMaxSumsq
}
bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
size_t len, const sampleCount *where)
size_t len, const sampleCount *where) const
{
wxASSERT(len > 0);
const auto s0 = std::max(sampleCount(0), where[0]);
@ -1332,7 +1335,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl,
// Find the range of sample values for this block that
// are in the display.
SeqBlock &seqBlock = mBlock[b];
const SeqBlock &seqBlock = mBlock[b];
const auto start = seqBlock.start;
nextSrcX = std::min(s1, start + seqBlock.f->GetLength());

View File

@ -101,7 +101,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
// bl is negative wherever data are not yet available.
// Return true if successful.
bool GetWaveDisplay(float *min, float *max, float *rms, int* bl,
size_t len, const sampleCount *where);
size_t len, const sampleCount *where) const;
std::unique_ptr<Sequence> Copy(sampleCount s0, sampleCount s1) const;
bool Paste(sampleCount s0, const Sequence *src);

View File

@ -63,20 +63,24 @@ TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const Zo
blankPen.SetColour(214, 214, 214);
}
TimeTrack::TimeTrack(const TimeTrack &orig):
Track(orig)
TimeTrack::TimeTrack(const TimeTrack &orig, double *pT0, double *pT1)
: Track(orig)
, mZoomInfo(orig.mZoomInfo)
{
Init(orig); // this copies the TimeTrack metadata (name, range, etc)
///@TODO: Give Envelope:: a copy-constructor instead of this?
mEnvelope = std::make_unique<Envelope>();
mEnvelope->Flatten(1.0);
mEnvelope->SetTrackLen(DBL_MAX);
SetInterpolateLog(orig.GetInterpolateLog()); // this calls Envelope::SetInterpolateDB
mEnvelope->Flatten(1.0);
mEnvelope->SetOffset(0);
mEnvelope->SetRange(orig.mEnvelope->GetMinValue(), orig.mEnvelope->GetMaxValue());
mEnvelope->Paste(0.0, orig.mEnvelope.get());
if ( pT0 && pT1 )
// restricted copy
mEnvelope->CopyFrom(orig.mEnvelope.get(), *pT0, *pT1);
else
mEnvelope->Paste(0.0, orig.mEnvelope.get());
///@TODO: Give Ruler:: a copy-constructor instead of this?
mRuler = std::make_unique<Ruler>();
@ -103,6 +107,42 @@ TimeTrack::~TimeTrack()
{
}
Track::Holder TimeTrack::Cut( double t0, double t1 )
{
auto result = Copy( t0, t1, false );
Clear( t0, t1 );
return result;
}
Track::Holder TimeTrack::Copy( double t0, double t1, bool ) const
{
auto result = std::make_unique<TimeTrack>( *this, &t0, &t1 );
return Track::Holder{ std::move( result ) };
}
void TimeTrack::Clear(double t0, double t1)
{
mEnvelope->CollapseRegion(t0, t1);
}
void TimeTrack::Paste(double t, const Track * src)
{
if (src->GetKind() != Track::Time)
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
mEnvelope->Paste(t, static_cast<const TimeTrack*>(src)->mEnvelope.get());
}
void TimeTrack::Silence(double t0, double t1)
{
}
void TimeTrack::InsertSilence(double t, double len)
{
mEnvelope->InsertSpace(t, len);
}
Track::Holder TimeTrack::Duplicate() const
{
return std::make_unique<TimeTrack>(*this);

View File

@ -34,11 +34,20 @@ class TimeTrack final : public Track {
* Envelope:: and Ruler:: members in order to copy one to the other - unfortunately both lack a
* copy-constructor to encapsulate this.
* @param orig The original track to copy from
* @param pT0 if not null, then the start of the sub-range to copy
* @param pT1 if not null, then the end of the sub-range to copy
*/
TimeTrack(const TimeTrack &orig);
TimeTrack(const TimeTrack &orig, double *pT0 = nullptr, double *pT1 = nullptr);
virtual ~TimeTrack();
Holder Cut( double t0, double t1 ) override;
Holder Copy( double t0, double t1, bool forClipboard ) const override;
void Clear(double t0, double t1) override;
void Paste(double t, const Track * src) override;
void Silence(double t0, double t1) override;
void InsertSilence(double t, double len) override;
// Identifying the type of track
int GetKind() const override { return Time; }

View File

@ -300,29 +300,22 @@ bool Track::IsSyncLockSelected() const
return false;
}
bool Track::SyncLockAdjust(double oldT1, double newT1)
void Track::SyncLockAdjust(double oldT1, double newT1)
{
if (newT1 > oldT1) {
// Insert space within the track
if (oldT1 > GetEndTime())
return true;
return;
auto tmp = Cut(oldT1, GetEndTime());
if (!tmp) return false;
bool ret = Paste(newT1, tmp.get());
wxASSERT(ret); // TODO: handle this.
return ret;
Paste(newT1, tmp.get());
}
else if (newT1 < oldT1) {
// Remove from the track
return Clear(newT1, oldT1);
Clear(newT1, oldT1);
}
// fall-through: no change
return true;
}
void PlayableTrack::Init( const PlayableTrack &orig )
@ -341,6 +334,33 @@ void PlayableTrack::Merge( const Track &orig )
AudioTrack::Merge( *pOrig );
}
// Serialize, not with tags of its own, but as attributes within a tag.
void PlayableTrack::WriteXMLAttributes(XMLWriter &xmlFile) const
{
xmlFile.WriteAttr(wxT("mute"), mMute);
xmlFile.WriteAttr(wxT("solo"), mSolo);
AudioTrack::WriteXMLAttributes(xmlFile);
}
// Return true iff the attribute is recognized.
bool PlayableTrack::HandleXMLAttribute(const wxChar *attr, const wxChar *value)
{
const wxString strValue{ value };
long nValue;
if (!wxStrcmp(attr, wxT("mute")) &&
XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) {
mMute = (nValue != 0);
return true;
}
else if (!wxStrcmp(attr, wxT("solo")) &&
XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) {
mSolo = (nValue != 0);
return true;
}
return AudioTrack::HandleXMLAttribute(attr, value);
}
// TrackListIterator
TrackListIterator::TrackListIterator(TrackList * val)
: l(val)
@ -589,16 +609,9 @@ SyncLockedTracksIterator::SyncLockedTracksIterator(TrackList * val)
}
namespace {
bool IsSyncLockableNonLabelTrack( const Track *pTrack )
inline bool IsSyncLockableNonLabelTrack( const Track *pTrack )
{
if ( pTrack->GetKind() == Track::Wave )
return true;
#ifdef USE_MIDI
else if ( pTrack->GetKind() == Track::Note )
return true;
#endif
else
return false;
return nullptr != dynamic_cast< const AudioTrack * >( pTrack );
}
}

View File

@ -206,28 +206,27 @@ class AUDACITY_DLL_API Track /* not final */ : public XMLTagHandler
// separate from the Track.
const std::shared_ptr<DirManager> &GetDirManager() const { return mDirManager; }
// Create a NEW track and modify this track (or return null for failure)
virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) { return{}; }
// Create a NEW track and modify this track
// Return non-NULL or else throw
virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
// Create a NEW track and don't modify this track (or return null for failure)
// Create a NEW track and don't modify this track
// Return non-NULL or else throw
// Note that subclasses may want to distinguish tracks stored in a clipboard
// from those stored in a project
virtual Holder Copy
(double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const
{ return{}; }
(double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
// Return true for success
virtual bool Clear(double WXUNUSED(t0), double WXUNUSED(t1)) {return false;}
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
// Return true for success
virtual bool Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) {return false;}
virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
// This can be used to adjust a sync-lock selected track when the selection
// is replaced by one of a different length.
virtual bool SyncLockAdjust(double oldT1, double newT1);
virtual void SyncLockAdjust(double oldT1, double newT1);
virtual bool Silence(double WXUNUSED(t0), double WXUNUSED(t1)) {return false;}
virtual bool InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) {return false;}
virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
virtual int GetKind() const { return None; }
@ -251,6 +250,13 @@ public:
AudioTrack(const std::shared_ptr<DirManager> &projDirManager)
: Track{ projDirManager } {}
AudioTrack(const Track &orig) : Track{ orig } {}
// Serialize, not with tags of its own, but as attributes within a tag.
void WriteXMLAttributes(XMLWriter &xmlFile) const {}
// Return true iff the attribute is recognized.
bool HandleXMLAttribute(const wxChar * /*attr*/, const wxChar * /*value*/)
{ return false; }
};
class PlayableTrack /* not final */ : public AudioTrack
@ -268,6 +274,12 @@ public:
void Init( const PlayableTrack &init );
void Merge( const Track &init ) override;
// Serialize, not with tags of its own, but as attributes within a tag.
void WriteXMLAttributes(XMLWriter &xmlFile) const;
// Return true iff the attribute is recognized.
bool HandleXMLAttribute(const wxChar *attr, const wxChar *value);
protected:
bool mMute { false };
bool mSolo { false };

View File

@ -6283,25 +6283,14 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, const wxRect &
// When user presses left button on cut line, expand the line again
double cutlineStart = 0, cutlineEnd = 0;
if (track->ExpandCutLine(mCapturedTrackLocation.pos, &cutlineStart, &cutlineEnd))
track->ExpandCutLine(mCapturedTrackLocation.pos, &cutlineStart, &cutlineEnd);
{
// Assume linked track is wave or null
const auto linked =
static_cast<WaveTrack*>(track->GetLink());
if (linked) {
if (linked)
// Expand the cutline in the opposite channel if it is present.
// PRL: Do NOT report that the event is not handled if the other
// channel doesn't also have a cutline to expand at the same time.
// Just ignore the return. Bug1310.
/* bool success = */
linked->ExpandCutLine(mCapturedTrackLocation.pos);
/*
if (!success)
return false;
*/
}
linked->ExpandCutLine(mCapturedTrackLocation.pos);
mViewInfo->selectedRegion.setTimes(cutlineStart, cutlineEnd);
DisplaySelection();
@ -6311,8 +6300,7 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, const wxRect &
}
else if (mCapturedTrackLocation.typ == WaveTrackLocation::locationMergePoint) {
const double pos = mCapturedTrackLocation.pos;
if (!track->MergeClips(mCapturedTrackLocation.clipidx1, mCapturedTrackLocation.clipidx2))
return false;
track->MergeClips(mCapturedTrackLocation.clipidx1, mCapturedTrackLocation.clipidx2);
// Assume linked track is wave or null
const auto linked =
@ -6322,8 +6310,7 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, const wxRect &
int idx = FindMergeLine(linked, pos);
if (idx >= 0) {
WaveTrack::Location location = linked->GetCachedLocations()[idx];
if (!linked->MergeClips(location.clipidx1, location.clipidx2))
return false;
linked->MergeClips(location.clipidx1, location.clipidx2);
}
}
@ -8338,16 +8325,12 @@ void TrackPanel::OnFormatChange(wxCommandEvent & event)
if (newFormat == ((WaveTrack*)mPopupMenuTarget)->GetSampleFormat())
return; // Nothing to do.
bool bResult = ((WaveTrack*)mPopupMenuTarget)->ConvertToSampleFormat(newFormat);
wxASSERT(bResult); // TO DO: Actually handle this.
((WaveTrack*)mPopupMenuTarget)->ConvertToSampleFormat(newFormat);
// Assume linked track is wave or null
const auto partner =
static_cast<WaveTrack*>(mPopupMenuTarget->GetLink());
if (partner)
{
bResult = partner->ConvertToSampleFormat(newFormat);
wxASSERT(bResult); // TO DO: Actually handle this.
}
partner->ConvertToSampleFormat(newFormat);
MakeParentPushState(wxString::Format(_("Changed '%s' to %s"),
mPopupMenuTarget->GetName().

View File

@ -1539,6 +1539,7 @@ void WaveClip::WriteXML(XMLWriter &xmlFile) const
}
bool WaveClip::Paste(double t0, const WaveClip* other)
// STRONG-GUARANTEE
{
const bool clipNeedsResampling = other->mRate != mRate;
const bool clipNeedsNewFormat =
@ -1558,34 +1559,42 @@ bool WaveClip::Paste(double t0, const WaveClip* other)
// Force sample formats to match.
newClip->ConvertToSampleFormat(mSequence->GetSampleFormat());
pastedClip = newClip.get();
} else
}
else
{
// No resampling or format change needed, just use original clip without making a copy
pastedClip = other;
}
// Paste cut lines contained in pasted clip
WaveClipHolders newCutlines;
for (const auto &cutline: pastedClip->mCutLines)
{
newCutlines.push_back(
make_movable<WaveClip>
( *cutline, mSequence->GetDirManager(),
// Recursively copy cutlines of cutlines. They don't need
// their offsets adjusted.
true));
newCutlines.back()->Offset(t0 - mOffset);
}
sampleCount s0;
TimeToSamplesClip(t0, &s0);
bool result = false;
// Assume STRONG-GUARANTEE from Sequence::Paste
if (mSequence->Paste(s0, pastedClip->mSequence.get()))
{
// Assume NOFAIL-GUARANTEE in the remaining
MarkChanged();
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
mEnvelope->RemoveUnneededPoints();
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
// Paste cut lines contained in pasted clip
for (const auto &cutline: pastedClip->mCutLines)
{
mCutLines.push_back(
make_movable<WaveClip>
( *cutline, mSequence->GetDirManager(),
// Recursively copy cutlines of cutlines. They don't need
// their offsets adjusted.
true));
mCutLines.back()->Offset(t0 - mOffset);
}
for (auto &holder : newCutlines)
mCutLines.push_back(std::move(holder));
result = true;
}
@ -1727,7 +1736,7 @@ bool WaveClip::ClearAndAddCutLine(double t0, double t1)
bool WaveClip::FindCutLine(double cutLinePosition,
double* cutlineStart /* = NULL */,
double* cutlineEnd /* = NULL */)
double* cutlineEnd /* = NULL */) const
{
for (const auto &cutline: mCutLines)
{
@ -1745,28 +1754,33 @@ bool WaveClip::FindCutLine(double cutLinePosition,
}
bool WaveClip::ExpandCutLine(double cutLinePosition)
// STRONG-GUARANTEE
{
for (auto it = mCutLines.begin(); it != mCutLines.end(); ++it)
{
WaveClip *const cutline = it->get();
if (fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001)
{
if (!Paste(mOffset+cutline->GetOffset(), cutline))
return false;
// Now erase the cutline,
// but be careful to find it again, because Paste above may
// have modified the array of cutlines (if our cutline contained
// another cutline!), invalidating the iterator we had.
auto begin = mCutLines.begin(), end = mCutLines.end();
it = std::find_if(begin, end,
[=](decltype(*begin) &p){ return p.get() == cutline; });
if (it != end)
mCutLines.erase(it); // deletes cutline!
else {
wxASSERT(false);
}
return true;
auto end = mCutLines.end();
auto it = std::find_if( mCutLines.begin(), end,
[&](const WaveClipHolder &cutline) {
return fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001;
} );
if ( it != end ) {
auto cutline = it->get();
// assume STRONG-GUARANTEE from Paste
if (!Paste(mOffset+cutline->GetOffset(), cutline))
return false;
// Now erase the cutline,
// but be careful to find it again, because Paste above may
// have modified the array of cutlines (if our cutline contained
// another cutline!), invalidating the iterator we had.
end = mCutLines.end();
it = std::find_if(mCutLines.begin(), end,
[=](const WaveClipHolder &p) { return p.get() == cutline; });
if (it != end)
mCutLines.erase(it); // deletes cutline!
else {
// THROW_INCONSISTENCY_EXCEPTION;
wxASSERT(false);
}
return true;
}
return false;
@ -1788,6 +1802,7 @@ bool WaveClip::RemoveCutLine(double cutLinePosition)
}
void WaveClip::OffsetCutLines(double t0, double len)
// NOFAIL-GUARANTEE
{
for (const auto &cutLine : mCutLines)
{

View File

@ -141,7 +141,8 @@ public:
class WaveClip;
// Array of pointers that assume ownership
using WaveClipHolders = std::vector < movable_ptr< WaveClip > >;
using WaveClipHolder = movable_ptr< WaveClip >;
using WaveClipHolders = std::vector < WaveClipHolder >;
using WaveClipConstHolders = std::vector < movable_ptr< const WaveClip > >;
// Temporary arrays of mere pointers
@ -331,7 +332,7 @@ public:
* position could be found. Return false otherwise. */
bool FindCutLine(double cutLinePosition,
double* cutLineStart = NULL,
double *cutLineEnd = NULL);
double *cutLineEnd = NULL) const;
/** Expand cut line (that is, re-insert audio, then DELETE audio saved in
* cut line). Returns true if a cut line could be found and sucessfully

View File

@ -501,13 +501,13 @@ float WaveTrack::GetChannelGain(int channel) const
return right*mGain;
}
bool WaveTrack::ConvertToSampleFormat(sampleFormat format)
void WaveTrack::ConvertToSampleFormat(sampleFormat format)
// WEAK-GUARANTEE
// might complete on only some tracks
{
for (const auto &clip : mClips)
clip->ConvertToSampleFormat(format);
mFormat = format;
return true;
}
bool WaveTrack::IsEmpty(double t0, double t1) const
@ -532,15 +532,12 @@ bool WaveTrack::IsEmpty(double t0, double t1) const
Track::Holder WaveTrack::Cut(double t0, double t1)
{
if (t1 < t0)
return{};
// THROW_INCONSISTENCY_EXCEPTION
;
auto tmp = Copy(t0, t1);
if (!tmp)
return{};
if (!Clear(t0, t1))
return{};
Clear(t0, t1);
return tmp;
}
@ -548,14 +545,13 @@ Track::Holder WaveTrack::Cut(double t0, double t1)
Track::Holder WaveTrack::SplitCut(double t0, double t1)
{
if (t1 < t0)
return{};
//THROW_INCONSISTENCY_EXCEPTION
;
// SplitCut is the same as 'Copy', then 'SplitDelete'
auto tmp = Copy(t0, t1);
if (!tmp)
return{};
if (!SplitDelete(t0, t1))
return{};
SplitDelete(t0, t1);
return tmp;
}
@ -564,14 +560,15 @@ Track::Holder WaveTrack::SplitCut(double t0, double t1)
Track::Holder WaveTrack::CutAndAddCutLine(double t0, double t1)
{
if (t1 < t0)
return {};
//THROW_INCONSISTENCY_EXCEPTION
;
// Cut is the same as 'Copy', then 'Delete'
auto tmp = Copy(t0, t1);
if (!tmp)
return {};
if (!ClearAndAddCutLine(t0, t1))
return {};
//THROW_INCONSISTENCY_EXCEPTION
;
return tmp;
}
@ -581,7 +578,7 @@ Track::Holder WaveTrack::CutAndAddCutLine(double t0, double t1)
//Trim trims within a clip, rather than trimming everything.
//If a bound is outside a clip, it trims everything.
bool WaveTrack::Trim (double t0, double t1)
void WaveTrack::Trim (double t0, double t1)
{
bool inside0 = false;
bool inside1 = false;
@ -600,14 +597,14 @@ bool WaveTrack::Trim (double t0, double t1)
if(t1 > clip->GetStartTime() && t1 < clip->GetEndTime())
{
if (!clip->Clear(t1,clip->GetEndTime()))
return false;
return;
inside1 = true;
}
if(t0 > clip->GetStartTime() && t0 < clip->GetEndTime())
{
if (!clip->Clear(clip->GetStartTime(),t0))
return false;
return;
clip->SetOffset(t0);
inside0 = true;
}
@ -616,18 +613,10 @@ bool WaveTrack::Trim (double t0, double t1)
//if inside0 is false, then the left selector was between
//clips, so DELETE everything to its left.
if(false == inside1)
{
if (!Clear(t1,GetEndTime()))
return false;
}
Clear(t1,GetEndTime());
if(false == inside0)
{
if (!SplitDelete(0,t0))
return false;
}
return true;
SplitDelete(0,t0);
}
@ -636,7 +625,8 @@ bool WaveTrack::Trim (double t0, double t1)
Track::Holder WaveTrack::Copy(double t0, double t1, bool forClipboard) const
{
if (t1 <= t0)
return{};
//THROW_INCONSISTENCY_EXCEPTION
;
WaveTrack *newTrack;
Track::Holder result
@ -711,14 +701,14 @@ Track::Holder WaveTrack::CopyNonconst(double t0, double t1)
return Copy(t0, t1);
}
bool WaveTrack::Clear(double t0, double t1)
void WaveTrack::Clear(double t0, double t1)
{
return HandleClear(t0, t1, false, false);
HandleClear(t0, t1, false, false);
}
bool WaveTrack::ClearAndAddCutLine(double t0, double t1)
void WaveTrack::ClearAndAddCutLine(double t0, double t1)
{
return HandleClear(t0, t1, true, false);
HandleClear(t0, t1, true, false);
}
const SpectrogramSettings &WaveTrack::GetSpectrogramSettings() const
@ -796,7 +786,7 @@ void WaveTrack::SetWaveformSettings(std::unique_ptr<WaveformSettings> &&pSetting
// be pasted with visible split lines. Normally, effects do not
// want these extra lines, so they may be merged out.
//
bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
void WaveTrack::ClearAndPaste(double t0, // Start of time to clear
double t1, // End of time to clear
const Track *src, // What to paste
bool preserve, // Whether to reinsert splits/cuts
@ -810,7 +800,8 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
// If duration is 0, then it's just a plain paste
if (dur == 0.0) {
return Paste(t0, src);
Paste(t0, src);
return;
}
// If provided time warper was NULL, use a default one that does nothing
@ -862,10 +853,12 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
const auto tolerance = 2.0 / GetRate();
// Now, clear the selection
if (HandleClear(t0, t1, false, false)) {
HandleClear(t0, t1, false, false);
{
// And paste in the NEW data
if (Paste(t0, src)) {
Paste(t0, src);
{
// First, merge the NEW clip(s) in with the existing clips
if (merge && splits.GetCount() > 0)
{
@ -883,11 +876,8 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
// Merge this clip and the previous clip if the end time
// falls within it and this isn't the first clip in the track.
if (fabs(t1 - clip->GetStartTime()) < tolerance) {
if (prev) {
bool bResult = MergeClips(GetClipIndex(prev), GetClipIndex(clip));
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
}
if (prev)
MergeClips(GetClipIndex(prev), GetClipIndex(clip));
break;
}
prev = clip;
@ -903,9 +893,7 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
WaveClip *prev = nullptr;
for (const auto clip : clips) {
if (prev) {
bool bResult = MergeClips(GetClipIndex(prev), GetClipIndex(clip));
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
MergeClips(GetClipIndex(prev), GetClipIndex(clip));
break;
}
if (fabs(t0 - clip->GetEndTime()) < tolerance)
@ -953,15 +941,13 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
}
}
}
return true;
}
bool WaveTrack::SplitDelete(double t0, double t1)
void WaveTrack::SplitDelete(double t0, double t1)
{
bool addCutLines = false;
bool split = true;
return HandleClear(t0, t1, addCutLines, split);
HandleClear(t0, t1, addCutLines, split);
}
namespace
@ -1019,11 +1005,12 @@ void WaveTrack::AddClip(movable_ptr<WaveClip> &&clip)
mClips.push_back(std::move(clip)); // transfer ownership
}
bool WaveTrack::HandleClear(double t0, double t1,
void WaveTrack::HandleClear(double t0, double t1,
bool addCutLines, bool split)
{
if (t1 < t0)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
bool editClipCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
@ -1058,8 +1045,7 @@ bool WaveTrack::HandleClear(double t0, double t1,
// Clip data is affected by command
if (addCutLines)
{
if (!clip->ClearAndAddCutLine(t0,t1))
return false;
clip->ClearAndAddCutLine(t0,t1);
}
else
{
@ -1116,7 +1102,7 @@ bool WaveTrack::HandleClear(double t0, double t1,
}
}
if (!clip->Clear(t0,t1))
return false;
return;
clip->GetEnvelope()->RemoveUnneededPoints(t0);
}
}
@ -1141,11 +1127,9 @@ bool WaveTrack::HandleClear(double t0, double t1,
for (auto &clip: clipsToAdd)
mClips.push_back(std::move(clip)); // transfer ownership
return true;
}
bool WaveTrack::SyncLockAdjust(double oldT1, double newT1)
void WaveTrack::SyncLockAdjust(double oldT1, double newT1)
{
if (newT1 > oldT1) {
// Insert space within the track
@ -1154,63 +1138,57 @@ bool WaveTrack::SyncLockAdjust(double oldT1, double newT1)
// GetEndTime() looks through the clips and may give us EXACTLY the same
// value as T1, when T1 was set to be at the end of one of those clips.
if (oldT1 >= GetEndTime())
return true;
return;
// If track is empty at oldT1 insert whitespace; otherwise, silence
if (IsEmpty(oldT1, oldT1))
{
bool ret = true;
// Check if clips can move
bool clipsCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &clipsCanMove);
if (clipsCanMove) {
auto tmp = Cut (oldT1, GetEndTime() + 1.0/GetRate());
if (!tmp)
return false;
ret = Paste(newT1, tmp.get());
wxASSERT(ret);
Paste(newT1, tmp.get());
}
return ret;
return;
}
else {
// AWD: Could just use InsertSilence() on its own here, but it doesn't
// follow EditClipCanMove rules (Paste() does it right)
AudacityProject *p = GetActiveProject();
if (!p) return false;
if (!p)
// THROW_INCONSISTENCY_EXCEPTION
;
TrackFactory *f = p->GetTrackFactory();
if (!f) return false;
if (!f)
// THROW_INCONSISTENCY_EXCEPTION
;
auto tmp = f->NewWaveTrack(GetSampleFormat(), GetRate());
bool bResult = tmp->InsertSilence(0.0, newT1 - oldT1);
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
tmp->InsertSilence(0.0, newT1 - oldT1);
tmp->Flush();
bResult = Paste(oldT1, tmp.get());
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
Paste(oldT1, tmp.get());
}
}
else if (newT1 < oldT1) {
return Clear(newT1, oldT1);
Clear(newT1, oldT1);
}
// fall-through: no change
return true;
}
bool WaveTrack::Paste(double t0, const Track *src)
void WaveTrack::Paste(double t0, const Track *src)
// WEAK-GUARANTEE
{
bool editClipCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
if( src == NULL )
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
if (src->GetKind() != Track::Wave)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
const WaveTrack* other = static_cast<const WaveTrack*>(src);
@ -1236,7 +1214,7 @@ bool WaveTrack::Paste(double t0, const Track *src)
//
if (other->GetNumClips() == 0)
return false;
return;
//printf("paste: we have at least one clip\n");
@ -1253,9 +1231,7 @@ bool WaveTrack::Paste(double t0, const Track *src)
// move everything to the right, then try to paste again
if (!IsEmpty(t0, GetEndTime())) {
auto tmp = Cut(t0, GetEndTime()+1.0/mRate);
bool bResult = Paste(t0 + insertDuration, tmp.get());
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
Paste(t0 + insertDuration, tmp.get());
}
}
else {
@ -1287,7 +1263,8 @@ bool WaveTrack::Paste(double t0, const Track *src)
insideClip = clip.get();
break;
}
} else
}
else
{
// If clips are immovable we also allow prepending to clips
if (clip->WithinClip(t0) ||
@ -1312,16 +1289,16 @@ bool WaveTrack::Paste(double t0, const Track *src)
if (clip->GetStartTime() > insideClip->GetStartTime() &&
insideClip->GetEndTime() + insertDuration >
clip->GetStartTime())
{
wxMessageBox(
_("There is not enough room available to paste the selection"),
_("Error"), wxICON_STOP);
return false;
}
// STRONG-GUARANTEE in case of this path
// not that it matters.
throw SimpleMessageBoxException{
_("There is not enough room available to paste the selection")
};
}
}
return insideClip->Paste(t0, other->GetClipByIndex(0));
insideClip->Paste(t0, other->GetClipByIndex(0));
return;
}
// Just fall through and exhibit NEW behaviour
@ -1331,12 +1308,11 @@ bool WaveTrack::Paste(double t0, const Track *src)
//printf("paste: multi clip mode!\n");
if (!editClipCanMove && !IsEmpty(t0, t0+insertDuration-1.0/mRate))
{
wxMessageBox(
_("There is not enough room available to paste the selection"),
_("Error"), wxICON_STOP);
return false;
}
// STRONG-GUARANTEE in case of this path
// not that it matters.
throw SimpleMessageBoxException{
_("There is not enough room available to paste the selection")
};
for (const auto &clip : other->mClips)
{
@ -1351,13 +1327,13 @@ bool WaveTrack::Paste(double t0, const Track *src)
mClips.push_back(std::move(newClip)); // transfer ownership
}
}
return true;
}
bool WaveTrack::Silence(double t0, double t1)
void WaveTrack::Silence(double t0, double t1)
{
if (t1 < t0)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
auto start = (sampleCount)floor(t0 * mRate + 0.5);
auto len = (sampleCount)floor(t1 * mRate + 0.5) - start;
@ -1386,25 +1362,25 @@ bool WaveTrack::Silence(double t0, double t1)
if (!clip->GetSequence()->SetSilence(inclipDelta, samplesToCopy))
{
wxASSERT(false); // should always work
return false;
return;
}
clip->MarkChanged();
}
}
return result;
}
bool WaveTrack::InsertSilence(double t, double len)
void WaveTrack::InsertSilence(double t, double len)
{
if (len <= 0)
return false;
// THROW_INCONSISTENCY_EXCEPTION; // ?
return;
if (mClips.empty())
{
// Special case if there is no clip yet
WaveClip* clip = CreateClip();
return clip->InsertSilence(0, len);
clip->InsertSilence(0, len);
return;
}
for (const auto &clip : mClips)
@ -1414,17 +1390,15 @@ bool WaveTrack::InsertSilence(double t, double len)
else if (clip->WithinClip(t))
{
if (!clip->InsertSilence(t, len)) {
return false;
return;
}
}
}
return true;
}
//Performs the opposite of Join
//Analyses selected region for possible Joined clips and disjoins them
bool WaveTrack::Disjoin(double t0, double t1)
void WaveTrack::Disjoin(double t0, double t1)
{
auto minSamples = TimeToLongSamples( WAVETRACK_MERGE_POINT_TOLERANCE );
const size_t maxAtOnce = 1048576;
@ -1499,11 +1473,9 @@ bool WaveTrack::Disjoin(double t0, double t1)
const Region &region = regions.at(i);
SplitDelete(region.start, region.end );
}
return true;
}
bool WaveTrack::Join(double t0, double t1)
void WaveTrack::Join(double t0, double t1)
{
// Merge all WaveClips overlapping selection into one
@ -1527,7 +1499,7 @@ bool WaveTrack::Join(double t0, double t1)
//if there are no clips to DELETE, nothing to do
if( clipsToDelete.size() == 0 )
return true;
return;
newClip = CreateClip();
double t = clipsToDelete[0]->GetOffset();
@ -1540,9 +1512,7 @@ bool WaveTrack::Join(double t0, double t1)
if (clip->GetOffset() - t > (1.0 / mRate)) {
double addedSilence = (clip->GetOffset() - t);
//printf("Adding %.6f seconds of silence\n");
bool bResult = newClip->InsertSilence(t, addedSilence);
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
newClip->InsertSilence(t, addedSilence);
t += addedSilence;
}
@ -1555,29 +1525,26 @@ bool WaveTrack::Join(double t0, double t1)
auto it = FindClip(mClips, clip);
mClips.erase(it); // deletes the clip
}
return true;
}
bool WaveTrack::Append(samplePtr buffer, sampleFormat format,
void WaveTrack::Append(samplePtr buffer, sampleFormat format,
size_t len, unsigned int stride /* = 1 */,
XMLWriter *blockFileLog /* = NULL */)
{
return RightmostOrNewClip()->Append(buffer, format, len, stride,
RightmostOrNewClip()->Append(buffer, format, len, stride,
blockFileLog);
}
bool WaveTrack::AppendAlias(const wxString &fName, sampleCount start,
void WaveTrack::AppendAlias(const wxString &fName, sampleCount start,
size_t len, int channel,bool useOD)
{
return RightmostOrNewClip()->AppendAlias(fName, start, len, channel, useOD);
RightmostOrNewClip()->AppendAlias(fName, start, len, channel, useOD);
}
bool WaveTrack::AppendCoded(const wxString &fName, sampleCount start,
void WaveTrack::AppendCoded(const wxString &fName, sampleCount start,
size_t len, int channel, int decodeType)
{
return RightmostOrNewClip()->AppendCoded(fName, start, len, channel, decodeType);
RightmostOrNewClip()->AppendCoded(fName, start, len, channel, decodeType);
}
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
@ -1648,10 +1615,10 @@ size_t WaveTrack::GetIdealBlockSize()
return NewestOrNewClip()->GetSequence()->GetIdealBlockSize();
}
bool WaveTrack::Flush()
void WaveTrack::Flush()
{
// After appending, presumably. Do this to the clip that gets appended.
return RightmostOrNewClip()->Flush();
RightmostOrNewClip()->Flush();
}
bool WaveTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
@ -1685,12 +1652,8 @@ bool WaveTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
// track is created.
mLegacyProjectFileOffset = dblValue;
}
else if (!wxStrcmp(attr, wxT("mute")) &&
XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
mMute = (nValue != 0);
else if (!wxStrcmp(attr, wxT("solo")) &&
XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
mSolo = (nValue != 0);
else if (this->PlayableTrack::HandleXMLAttribute(attr, value))
{}
else if (!wxStrcmp(attr, wxT("height")) &&
XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
mHeight = nValue;
@ -1789,8 +1752,7 @@ void WaveTrack::WriteXML(XMLWriter &xmlFile) const
xmlFile.WriteAttr(wxT("name"), mName);
xmlFile.WriteAttr(wxT("channel"), mChannel);
xmlFile.WriteAttr(wxT("linked"), mLinked);
xmlFile.WriteAttr(wxT("mute"), mMute);
xmlFile.WriteAttr(wxT("solo"), mSolo);
this->PlayableTrack::WriteXMLAttributes(xmlFile);
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
int height;
if(MONO_PAN)
@ -2056,11 +2018,9 @@ bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
return result;
}
bool WaveTrack::Set(samplePtr buffer, sampleFormat format,
void WaveTrack::Set(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len)
{
bool result = true;
for (const auto &clip: mClips)
{
auto clipStart = clip->GetStartSample();
@ -2097,13 +2057,11 @@ bool WaveTrack::Set(samplePtr buffer, sampleFormat format,
format, inclipDelta, samplesToCopy.as_size_t() ))
{
wxASSERT(false); // should always work
return false;
return;
}
clip->MarkChanged();
}
}
return result;
}
void WaveTrack::GetEnvelopeValues(double *buffer, size_t bufferLen,
@ -2338,15 +2296,14 @@ bool WaveTrack::CanInsertClip(WaveClip* clip)
return true;
}
bool WaveTrack::Split( double t0, double t1 )
void WaveTrack::Split( double t0, double t1 )
{
bool ret = SplitAt( t0 );
if( ret && t0 != t1 )
ret = SplitAt( t1 );
return ret;
SplitAt( t0 );
if( t0 != t1 )
SplitAt( t1 );
}
bool WaveTrack::SplitAt(double t)
void WaveTrack::SplitAt(double t)
{
for (const auto &c : mClips)
{
@ -2363,11 +2320,11 @@ bool WaveTrack::SplitAt(double t)
auto newClip = make_movable<WaveClip>( *c, mDirManager, true );
if (!c->Clear(t, c->GetEndTime()))
{
return false;
return;
}
if (!newClip->Clear(c->GetStartTime(), t))
{
return false;
return;
}
//offset the NEW clip by the splitpoint (noting that it is already offset to c->GetStartTime())
@ -2376,11 +2333,8 @@ bool WaveTrack::SplitAt(double t)
// This could invalidate the iterators for the loop! But we return
// at once so it's okay
mClips.push_back(std::move(newClip)); // transfer ownership
return true;
}
}
return true;
}
void WaveTrack::UpdateLocationsCache() const
@ -2450,59 +2404,57 @@ void WaveTrack::UpdateLocationsCache() const
}
// Expand cut line (that is, re-insert audio, then DELETE audio saved in cut line)
bool WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
void WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
double* cutlineEnd)
// STRONG-GUARANTEE
{
bool editClipCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
// Find clip which contains this cut line
for (const auto &clip : mClips)
double start = 0, end = 0;
auto pEnd = mClips.end();
auto pClip = std::find_if( mClips.begin(), pEnd,
[&](const WaveClipHolder &clip) {
return clip->FindCutLine(cutLinePosition, &start, &end); } );
if (pClip != pEnd)
{
double start = 0, end = 0;
if (clip->FindCutLine(cutLinePosition, &start, &end))
auto &clip = *pClip;
if (!editClipCanMove)
{
if (!editClipCanMove)
// We are not allowed to move the other clips, so see if there
// is enough room to expand the cut line
for (const auto &clip2: mClips)
{
// We are not allowed to move the other clips, so see if there
// is enough room to expand the cut line
for (const auto &clip2: mClips)
{
if (clip2->GetStartTime() > clip->GetStartTime() &&
clip->GetEndTime() + end - start > clip2->GetStartTime())
{
wxMessageBox(
_("There is not enough room available to expand the cut line"),
_("Error"), wxICON_STOP);
return false;
}
}
}
if (clip2->GetStartTime() > clip->GetStartTime() &&
clip->GetEndTime() + end - start > clip2->GetStartTime())
// STRONG-GUARANTEE in case of this path
throw SimpleMessageBoxException{
_("There is not enough room available to expand the cut line")
};
}
}
if (!clip->ExpandCutLine(cutLinePosition))
return false;
if (!clip->ExpandCutLine(cutLinePosition))
return;
if (cutlineStart)
*cutlineStart = start;
if (cutlineEnd)
*cutlineEnd = end;
// STRONG-GUARANTEE provided that the following gives NOFAIL-GUARANTEE
// Move clips which are to the right of the cut line
if (editClipCanMove)
if (cutlineStart)
*cutlineStart = start;
if (cutlineEnd)
*cutlineEnd = end;
// Move clips which are to the right of the cut line
if (editClipCanMove)
{
for (const auto &clip2 : mClips)
{
for (const auto &clip2 : mClips)
{
if (clip2->GetStartTime() > clip->GetStartTime())
clip2->Offset(end - start);
}
if (clip2->GetStartTime() > clip->GetStartTime())
clip2->Offset(end - start);
}
return true;
}
}
return false;
}
bool WaveTrack::RemoveCutLine(double cutLinePosition)
@ -2514,26 +2466,26 @@ bool WaveTrack::RemoveCutLine(double cutLinePosition)
return false;
}
bool WaveTrack::MergeClips(int clipidx1, int clipidx2)
void WaveTrack::MergeClips(int clipidx1, int clipidx2)
{
WaveClip* clip1 = GetClipByIndex(clipidx1);
WaveClip* clip2 = GetClipByIndex(clipidx2);
if (!clip1 || !clip2) // Could happen if one track of a linked pair had a split and the other didn't.
return false;
return; // Don't throw, just do nothing.
// Append data from second clip to first clip
if (!clip1->Paste(clip1->GetEndTime(), clip2))
return false;
return;
// Delete second clip
auto it = FindClip(mClips, clip2);
mClips.erase(it);
return true;
}
bool WaveTrack::Resample(int rate, ProgressDialog *progress)
void WaveTrack::Resample(int rate, ProgressDialog *progress)
// WEAK-GUARANTEE
// Partial completion may leave clips at differing sample rates!
{
for (const auto &clip : mClips)
if (!clip->Resample(rate, progress))
@ -2541,12 +2493,10 @@ bool WaveTrack::Resample(int rate, ProgressDialog *progress)
wxLogDebug( wxT("Resampling problem! We're partially resampled") );
// FIXME: The track is now in an inconsistent state since some
// clips are resampled and some are not
return false;
return;
}
mRate = rate;
return true;
}
namespace {

View File

@ -150,7 +150,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
void SetVirtualState(bool state, bool half=false);
#endif
sampleFormat GetSampleFormat() const { return mFormat; }
bool ConvertToSampleFormat(sampleFormat format);
void ConvertToSampleFormat(sampleFormat format);
const SpectrogramSettings &GetSpectrogramSettings() const;
SpectrogramSettings &GetSpectrogramSettings();
@ -175,32 +175,32 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
Track::Holder Copy(double t0, double t1, bool forClipboard = true) const override;
Track::Holder CopyNonconst(double t0, double t1) /* not override */;
bool Clear(double t0, double t1) override;
bool Paste(double t0, const Track *src) override;
bool ClearAndPaste(double t0, double t1,
void Clear(double t0, double t1) override;
void Paste(double t0, const Track *src) override;
void ClearAndPaste(double t0, double t1,
const Track *src,
bool preserve = true,
bool merge = true,
const TimeWarper *effectWarper = NULL) /* not override */;
bool Silence(double t0, double t1) override;
bool InsertSilence(double t, double len) override;
void Silence(double t0, double t1) override;
void InsertSilence(double t, double len) override;
bool SplitAt(double t) /* not override */;
bool Split(double t0, double t1) /* not override */;
void SplitAt(double t) /* not override */;
void Split(double t0, double t1) /* not override */;
// Track::Holder CutAndAddCutLine(double t0, double t1) /* not override */;
bool ClearAndAddCutLine(double t0, double t1) /* not override */;
void ClearAndAddCutLine(double t0, double t1) /* not override */;
Track::Holder SplitCut(double t0, double t1) /* not override */;
bool SplitDelete(double t0, double t1) /* not override */;
bool Join(double t0, double t1) /* not override */;
bool Disjoin(double t0, double t1) /* not override */;
void SplitDelete(double t0, double t1) /* not override */;
void Join(double t0, double t1) /* not override */;
void Disjoin(double t0, double t1) /* not override */;
bool Trim(double t0, double t1) /* not override */;
void Trim(double t0, double t1) /* not override */;
bool HandleClear(double t0, double t1, bool addCutLines, bool split);
void HandleClear(double t0, double t1, bool addCutLines, bool split);
bool SyncLockAdjust(double oldT1, double newT1) override;
void SyncLockAdjust(double oldT1, double newT1) override;
/** @brief Returns true if there are no WaveClips in the specified region
*
@ -216,20 +216,20 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
* appended to that clip. If there are no WaveClips in the track, then a NEW
* one is created.
*/
bool Append(samplePtr buffer, sampleFormat format,
void Append(samplePtr buffer, sampleFormat format,
size_t len, unsigned int stride=1,
XMLWriter* blockFileLog=NULL);
/// Flush must be called after last Append
bool Flush();
void Flush();
bool AppendAlias(const wxString &fName, sampleCount start,
void AppendAlias(const wxString &fName, sampleCount start,
size_t len, int channel,bool useOD);
///for use with On-Demand decoding of compressed files.
///decodeType should be an enum from ODDecodeTask that specifies what
///Type of encoded file this is, such as eODFLAC
//vvv Why not use the ODTypeEnum typedef to enforce that for the parameter?
bool AppendCoded(const wxString &fName, sampleCount start,
void AppendCoded(const wxString &fName, sampleCount start,
size_t len, int channel, int decodeType);
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
@ -254,7 +254,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
bool Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len,
fillFormat fill = fillZero, bool mayThrow = true) const;
bool Set(samplePtr buffer, sampleFormat format,
void Set(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len);
void GetEnvelopeValues(double *buffer, size_t bufferLen,
double t0) const;
@ -486,7 +486,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
// Merge two clips, that is append data from clip2 to clip1,
// then remove clip2 from track.
// clipidx1 and clipidx2 are indices into the clip list.
bool MergeClips(int clipidx1, int clipidx2);
void MergeClips(int clipidx1, int clipidx2);
// Cache special locations (e.g. cut lines) for later speedy access
void UpdateLocationsCache() const;
@ -495,7 +495,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
const std::vector<Location> &GetCachedLocations() const { return mDisplayLocationsCache; }
// Expand cut line (that is, re-insert audio, then DELETE audio saved in cut line)
bool ExpandCutLine(double cutLinePosition, double* cutlineStart = NULL, double* cutlineEnd = NULL);
void ExpandCutLine(double cutLinePosition, double* cutlineStart = NULL, double* cutlineEnd = NULL);
// Remove cut line, without expanding the audio in it
bool RemoveCutLine(double cutLinePosition);
@ -505,7 +505,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
void Merge(const Track &orig) override;
// Resample track (i.e. all clips in the track)
bool Resample(int rate, ProgressDialog *progress = NULL);
void Resample(int rate, ProgressDialog *progress = NULL);
//
// AutoSave related

View File

@ -539,7 +539,7 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
if (bResult)
{
LinearTimeWarper warper { mCurT0, mCurT0, mCurT1, mCurT0 + newLength };
bResult = track->ClearAndPaste(
track->ClearAndPaste(
mCurT0, mCurT1, outputTrack.get(), true, false, &warper);
}

View File

@ -1278,8 +1278,6 @@ bool Effect::ProcessPass()
{
bool bGoodResult = true;
bool isGenerator = GetType() == EffectTypeGenerate;
bool editClipCanMove;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true);
FloatBuffers inBuffer, outBuffer;
ArrayOf<float *> inBufPos, outBufPos;
@ -1970,8 +1968,7 @@ void Effect::GetSamples(
t1 = t0 + mDuration;
if (mT0 == mT1) {
// Not really part of the calculation, but convenient to put here
bool bResult = track->InsertSilence(t0, t1);
wxASSERT(bResult); // TO DO: Actually handle this.
track->InsertSilence(t0, t1);
}
}
#endif

View File

@ -1173,20 +1173,15 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
//remove the old audio and get the NEW
t->Clear(clipStartEndTimes[i].first,clipStartEndTimes[i].second);
auto toClipOutput = output->Copy(clipStartEndTimes[i].first-startT+offsetT0,clipStartEndTimes[i].second-startT+offsetT0);
if(toClipOutput)
{
//put the processed audio in
bool bResult = t->Paste(clipStartEndTimes[i].first, toClipOutput.get());
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
//if the clip was only partially selected, the Paste will have created a split line. Join is needed to take care of this
//This is not true when the selection is fully contained within one clip (second half of conditional)
if( (clipRealStartEndTimes[i].first != clipStartEndTimes[i].first ||
clipRealStartEndTimes[i].second != clipStartEndTimes[i].second) &&
!(clipRealStartEndTimes[i].first <= startT &&
clipRealStartEndTimes[i].second >= startT+lenT) )
t->Join(clipRealStartEndTimes[i].first,clipRealStartEndTimes[i].second);
}
//put the processed audio in
t->Paste(clipStartEndTimes[i].first, toClipOutput.get());
//if the clip was only partially selected, the Paste will have created a split line. Join is needed to take care of this
//This is not true when the selection is fully contained within one clip (second half of conditional)
if( (clipRealStartEndTimes[i].first != clipStartEndTimes[i].first ||
clipRealStartEndTimes[i].second != clipStartEndTimes[i].second) &&
!(clipRealStartEndTimes[i].first <= startT &&
clipRealStartEndTimes[i].second >= startT+lenT) )
t->Join(clipRealStartEndTimes[i].first,clipRealStartEndTimes[i].second);
}
}

View File

@ -558,19 +558,15 @@ bool EffectEqualization48x::ProcessTail(WaveTrack * t, WaveTrack * output, sampl
t->Clear(clipStartEndTimes[i].first,clipStartEndTimes[i].second);
// output->Copy(clipStartEndTimes[i].first-startT+offsetT0,clipStartEndTimes[i].second-startT+offsetT0, &toClipOutput);
auto toClipOutput = output->Copy(clipStartEndTimes[i].first-startT, clipStartEndTimes[i].second-startT);
if(toClipOutput)
{
//put the processed audio in
bool bResult = t->Paste(clipStartEndTimes[i].first, toClipOutput.get());
wxASSERT(bResult); // TO DO: Actually handle this.
//if the clip was only partially selected, the Paste will have created a split line. Join is needed to take care of this
//This is not true when the selection is fully contained within one clip (second half of conditional)
if( (clipRealStartEndTimes[i].first != clipStartEndTimes[i].first ||
clipRealStartEndTimes[i].second != clipStartEndTimes[i].second) &&
!(clipRealStartEndTimes[i].first <= startT &&
clipRealStartEndTimes[i].second >= startT+lenT) )
t->Join(clipRealStartEndTimes[i].first,clipRealStartEndTimes[i].second);
}
//put the processed audio in
t->Paste(clipStartEndTimes[i].first, toClipOutput.get());
//if the clip was only partially selected, the Paste will have created a split line. Join is needed to take care of this
//This is not true when the selection is fully contained within one clip (second half of conditional)
if( (clipRealStartEndTimes[i].first != clipStartEndTimes[i].first ||
clipRealStartEndTimes[i].second != clipStartEndTimes[i].second) &&
!(clipRealStartEndTimes[i].first <= startT &&
clipRealStartEndTimes[i].second >= startT+lenT) )
t->Join(clipRealStartEndTimes[i].first,clipRealStartEndTimes[i].second);
}
return true;
}

View File

@ -80,7 +80,7 @@ bool Generator::Process()
tmp->Flush();
StepTimeWarper warper{
mT0+GetDuration(), GetDuration()-(mT1-mT0) };
bGoodResult = track->ClearAndPaste(
track->ClearAndPaste(
p->GetSel0(), p->GetSel1(), &*tmp, true, false, &warper);
}

View File

@ -1333,9 +1333,7 @@ bool EffectNoiseReduction::Worker::ProcessOne
double tLen = outputTrack->LongSamplesToTime(len);
// Filtering effects always end up with more data than they started with. Delete this 'tail'.
outputTrack->HandleClear(tLen, outputTrack->GetEndTime(), false, false);
bool bResult = track->ClearAndPaste(t0, t0 + tLen, &*outputTrack, true, false);
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
track->ClearAndPaste(t0, t0 + tLen, &*outputTrack, true, false);
}
return bLoopSuccess;

View File

@ -575,8 +575,7 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
double tLen = mOutputTrack->LongSamplesToTime(len);
// Filtering effects always end up with more data than they started with. Delete this 'tail'.
mOutputTrack->HandleClear(tLen, mOutputTrack->GetEndTime(), false, false);
bool bResult = track->ClearAndPaste(t0, t0 + tLen, mOutputTrack.get(), true, false);
wxASSERT(bResult); // TO DO: Actually handle this.
track->ClearAndPaste(t0, t0 + tLen, mOutputTrack.get(), true, false);
}
}

View File

@ -378,11 +378,11 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun
}
}
outputTrack->Flush();
if (!cancelled){
outputTrack->Flush();
track->Clear(t0,t1);
bool success = track->Paste(t0, outputTrack.get());
if (!cancelled && success){
track->Clear(t0,t1);
track->Paste(t0, outputTrack.get());
m_t1 = mT0 + outputTrack->GetEndTime();
}

View File

@ -139,12 +139,12 @@ bool EffectRepeat::Process()
auto dest = track->Copy(mT0, mT1);
for(int j=0; j<repeatCount; j++)
{
if (!track->Paste(tc, dest.get()) ||
TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
if (TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
{
bGoodResult = false;
break;
}
track->Paste(tc, dest.get());
tc += tLen;
}
if (tc > maxDestLen)

View File

@ -440,19 +440,12 @@ bool EffectSBSMS::Process()
if(rightTrack)
rb.outputRightTrack->Flush();
bool bResult =
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack.get(),
true, false, warper.get());
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
if(rightTrack)
{
bResult =
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack.get(),
true, false, warper.get());
wxASSERT(bResult); // TO DO: Actually handle this.
}
}
}
mCurTrackNum++;

View File

@ -97,7 +97,6 @@ bool EffectSilence::GenerateTrack(WaveTrack *tmp,
const WaveTrack & WXUNUSED(track),
int WXUNUSED(ntrack))
{
bool bResult = tmp->InsertSilence(0.0, GetDuration());
wxASSERT(bResult);
return bResult;
tmp->InsertSilence(0.0, GetDuration());
return true;
}

View File

@ -157,15 +157,15 @@ bool EffectStereoToMono::ProcessOne(int count)
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
leftBuffer[i] = curMonoFrame;
}
bResult &= mOutTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit);
mOutTrack->Append((samplePtr)leftBuffer.get(), 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->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
mOutTrack->Flush();
mLeftTrack->Paste(minStart, mOutTrack.get());
mLeftTrack->SetLinked(false);
mRightTrack->SetLinked(false);
mLeftTrack->SetChannel(Track::MonoChannel);

View File

@ -998,7 +998,6 @@ bool NyquistEffect::ProcessOne()
cmd += wxString::Format(wxT("(putprop '*SELECTION* (vector %s) 'PEAK)\n"), peakString) :
cmd += wxString::Format(wxT("(putprop '*SELECTION* %s 'PEAK)\n"), peakString);
// TODO: Documen, PEAK-LEVEL is deprecated as of 2.1.3.
// TODO: Document, PEAK-LEVEL is nil if NaN or INF.
if (!std::isinf(maxPeakLevel) && !std::isnan(maxPeakLevel) && (maxPeakLevel < FLT_MAX)) {
cmd += wxString::Format(wxT("(putprop '*SELECTION* (float %s) 'PEAK-LEVEL)\n"),
@ -1881,11 +1880,9 @@ int NyquistEffect::PutCallback(float *buffer, int channel,
}
}
if (mOutputTrack[channel]->Append((samplePtr)buffer, floatSample, len)) {
return 0; // success
}
mOutputTrack[channel]->Append((samplePtr)buffer, floatSample, len);
return -1; // failure
return 0; // success
}, MakeSimpleGuard( -1 ) ); // translate all exceptions into failure
}

View File

@ -175,8 +175,10 @@ void MidiIOPrefs::PopulateOrExchange( ShuttleGui & S ) {
void MidiIOPrefs::OnHost(wxCommandEvent & e)
{
wxString itemAtIndex;
int index = mHost->GetCurrentSelection();
wxString itemAtIndex = mHostNames.Item(index);
if (index >= 0 && index < mHostNames.Count())
itemAtIndex = mHostNames.Item(index);
int nDevices = Pm_CountDevices();
if (nDevices == 0) {

View File

@ -1003,9 +1003,7 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
newTrack->InsertSilence(0.0, t0 - t1);
newTrack->Flush();
wt->Clear(t1, t0);
bool bResult = wt->Paste(t1, newTrack.get());
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
wt->Paste(t1, newTrack.get());
}
recordingTracks.push_back(wt);
// Don't record more channels than configured recording pref.

View File

@ -14,7 +14,8 @@ Authors:
Martyn Shaw
========================================================================
This document is for Audacity version 2.1.2.
This document is for Audacity version 2.1.3 and is currently also valid
for building 2.2.0-alpha.
If the advice here is inaccurate or incomplete,
email audacity-devel@lists.sourceforge.net.
@ -41,7 +42,7 @@ To simplify the implementation of a near-identical user
interface across platforms, Audacity uses wxWidgets, a
GUI framework.
Audacity 2.1.2 requires wxWidgets 3.0.2.
Audacity 2.1.3 requires wxWidgets 3.0.2.
To be able to build Audacity for Windows, download and install
wxWidgets from http://www.wxwidgets.org/.