2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
Sequence.h
|
|
|
|
|
|
|
|
Dominic Mazzoni
|
|
|
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#ifndef __AUDACITY_SEQUENCE__
|
|
|
|
#define __AUDACITY_SEQUENCE__
|
|
|
|
|
2021-05-09 15:16:56 +00:00
|
|
|
|
2016-01-29 16:12:56 +00:00
|
|
|
#include <vector>
|
2020-08-28 19:07:04 +00:00
|
|
|
#include <functional>
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
#include "SampleFormat.h"
|
|
|
|
#include "xml/XMLTagHandler.h"
|
|
|
|
|
2021-05-23 03:20:14 +00:00
|
|
|
#include "Identifier.h"
|
The fabled realtime effects...
I've made it where you can enable and disable via experimentals:
EXPERIMENTAL_REALTIME_EFFECTS
EXPERIMENTAL_EFFECTS_RACK
You will notice that, as of now, the only effects currently set up for
realtime are VSTs. Now that this is in, I will start converting the
rest.
As I start to convert the effects, the astute of you may notice that
they no longer directly access tracks or any "internal" Audacity
objects. This isolates the effects from changes in Audacity and makes
it much easier to add new ones.
Anyway, all 3 platforms can now display VST effects in graphical mode.
Yes, that means Linux too. There are quite a few VSTs for Linux if
you search for them.
The so-called "rack" definitely needs some discussion, work, and attention
from someone much better at graphics than me. I'm not really sure it should
stay in as-is. I'd originally planned for it to be simply a utility window
where you can store your (preconfigured) favorite effects. It should probably
revert back to that idea.
You may notice that this DOES include the API work I did. The realtime effects
were too tied to it and I didn't want to redo the whole thing. As I mentioned
elsewhere, the API stuff may or may not be very future proof.
So, let the critter complaints commence. I absolute KNOW there will be some.
(I know I'll be hearing from the Linux peeps pretty darn quickly. ;-))
2014-10-26 03:24:10 +00:00
|
|
|
|
2020-07-01 05:45:17 +00:00
|
|
|
class SampleBlock;
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
class SampleBlockFactory;
|
|
|
|
using SampleBlockFactoryPtr = std::shared_ptr<SampleBlockFactory>;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// This is an internal data structure! For advanced use only.
|
|
|
|
class SeqBlock {
|
|
|
|
public:
|
2020-07-01 05:45:17 +00:00
|
|
|
using SampleBlockPtr = std::shared_ptr<SampleBlock>;
|
|
|
|
SampleBlockPtr sb;
|
2010-01-23 19:44:49 +00:00
|
|
|
///the sample in the global wavetrack that this block starts at.
|
|
|
|
sampleCount start;
|
2016-01-29 16:12:56 +00:00
|
|
|
|
|
|
|
SeqBlock()
|
2020-07-01 05:45:17 +00:00
|
|
|
: sb{}, start(0)
|
2016-01-29 16:12:56 +00:00
|
|
|
{}
|
|
|
|
|
2020-07-01 05:45:17 +00:00
|
|
|
SeqBlock(const SampleBlockPtr &sb_, sampleCount start_)
|
|
|
|
: sb(sb_), start(start_)
|
2016-01-29 16:12:56 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
// Construct a SeqBlock with changed start, same file
|
|
|
|
SeqBlock Plus(sampleCount delta) const
|
|
|
|
{
|
2020-07-01 05:45:17 +00:00
|
|
|
return SeqBlock(sb, start + delta);
|
2016-01-29 16:12:56 +00:00
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
2016-01-29 16:12:56 +00:00
|
|
|
class BlockArray : public std::vector<SeqBlock> {};
|
2016-02-16 14:35:03 +00:00
|
|
|
using BlockPtrArray = std::vector<SeqBlock*>; // non-owning pointers
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2021-05-01 02:48:38 +00:00
|
|
|
// Put extra symbol information in the release build, for the purpose of gathering
|
|
|
|
// profiling information (as from Windows Process Monitor), when there otherwise
|
|
|
|
// isn't a need for AUDACITY_DLL_API.
|
|
|
|
#ifdef IS_ALPHA
|
|
|
|
#define PROFILE_DLL_API AUDACITY_DLL_API
|
|
|
|
#else
|
|
|
|
#define PROFILE_DLL_API
|
|
|
|
#endif
|
|
|
|
|
2016-01-29 14:00:02 +00:00
|
|
|
class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
2010-01-23 19:44:49 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
//
|
|
|
|
// Static methods
|
|
|
|
//
|
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
static void SetMaxDiskBlockSize(size_t bytes);
|
|
|
|
static size_t GetMaxDiskBlockSize();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Constructor / Destructor / Duplicator
|
|
|
|
//
|
|
|
|
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
Sequence(const SampleBlockFactoryPtr &pFactory, sampleFormat format);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
Sequence(const Sequence &orig, const SampleBlockFactoryPtr &pFactory);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2020-07-07 06:01:11 +00:00
|
|
|
Sequence( const Sequence& ) = delete;
|
2016-11-24 22:17:06 +00:00
|
|
|
Sequence& operator= (const Sequence&) PROHIBITED;
|
|
|
|
|
2016-02-03 18:01:55 +00:00
|
|
|
~Sequence();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Editing
|
|
|
|
//
|
|
|
|
|
|
|
|
sampleCount GetNumSamples() const { return mNumSamples; }
|
|
|
|
|
|
|
|
bool Get(samplePtr buffer, sampleFormat format,
|
2017-03-20 14:54:03 +00:00
|
|
|
sampleCount start, size_t len, bool mayThrow) const;
|
2016-09-06 13:19:27 +00:00
|
|
|
|
|
|
|
// Note that len is not size_t, because nullptr may be passed for buffer, in
|
|
|
|
// which case, silence is inserted, possibly a large amount.
|
2020-11-30 00:09:58 +00:00
|
|
|
void SetSamples(constSamplePtr buffer, sampleFormat format,
|
2020-07-01 05:45:17 +00:00
|
|
|
sampleCount start, sampleCount len);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-21 04:25:49 +00:00
|
|
|
// where is input, assumed to be nondecreasing, and its size is len + 1.
|
|
|
|
// min, max, rms, bl are outputs, and their lengths are len.
|
|
|
|
// Each position in the output arrays corresponds to one column of pixels.
|
|
|
|
// The column for pixel p covers samples from
|
|
|
|
// where[p] up to (but excluding) where[p + 1].
|
|
|
|
// bl is negative wherever data are not yet available.
|
|
|
|
// Return true if successful.
|
2016-02-03 18:01:55 +00:00
|
|
|
bool GetWaveDisplay(float *min, float *max, float *rms, int* bl,
|
2017-03-24 18:59:22 +00:00
|
|
|
size_t len, const sampleCount *where) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-11-07 19:27:31 +00:00
|
|
|
// Return non-null, or else throw!
|
2020-07-07 20:41:50 +00:00
|
|
|
// Must pass in the correct factory for the result. If it's not the same
|
|
|
|
// as in this, then block contents must be copied.
|
|
|
|
std::unique_ptr<Sequence> Copy( const SampleBlockFactoryPtr &pFactory,
|
|
|
|
sampleCount s0, sampleCount s1) const;
|
2016-11-27 16:00:23 +00:00
|
|
|
void Paste(sampleCount s0, const Sequence *src);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t GetIdealAppendLen() const;
|
2020-11-30 00:09:58 +00:00
|
|
|
void Append(constSamplePtr buffer, sampleFormat format, size_t len);
|
2020-08-30 22:18:18 +00:00
|
|
|
|
|
|
|
//! Append data, not coalescing blocks, returning a pointer to the new block.
|
2020-11-30 00:09:58 +00:00
|
|
|
SeqBlock::SampleBlockPtr AppendNewBlock(
|
|
|
|
constSamplePtr buffer, sampleFormat format, size_t len);
|
2020-08-30 22:18:18 +00:00
|
|
|
//! Append a complete block, not coalescing
|
|
|
|
void AppendSharedBlock(const SeqBlock::SampleBlockPtr &pBlock);
|
2016-11-29 02:49:00 +00:00
|
|
|
void Delete(sampleCount start, sampleCount len);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-11-29 14:42:32 +00:00
|
|
|
void SetSilence(sampleCount s0, sampleCount len);
|
2016-11-27 15:39:46 +00:00
|
|
|
void InsertSilence(sampleCount s0, sampleCount len);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
const SampleBlockFactoryPtr &GetFactory() { return mpFactory; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// XMLTagHandler callback methods for loading and saving
|
|
|
|
//
|
|
|
|
|
2016-02-24 06:06:47 +00:00
|
|
|
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
|
|
|
|
void HandleXMLEndTag(const wxChar *tag) override;
|
|
|
|
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
|
2017-02-22 19:23:35 +00:00
|
|
|
void WriteXML(XMLWriter &xmlFile) const /* not override */;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
bool GetErrorOpening() { return mErrorOpening; }
|
|
|
|
|
|
|
|
//
|
2020-07-20 22:58:22 +00:00
|
|
|
// Lock all of this sequence's sample blocks, keeping them
|
|
|
|
// from being destroyed when closing.
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2020-07-07 20:41:50 +00:00
|
|
|
bool CloseLock();//should be called upon project close.
|
2016-04-12 03:38:33 +00:00
|
|
|
// not balanced by unlocking calls.
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
//
|
|
|
|
// Manipulating Sample Format
|
|
|
|
//
|
|
|
|
|
|
|
|
sampleFormat GetSampleFormat() const;
|
2016-11-28 15:15:34 +00:00
|
|
|
|
|
|
|
// Return true iff there is a change
|
2020-08-28 19:07:04 +00:00
|
|
|
bool ConvertToSampleFormat(sampleFormat format,
|
|
|
|
const std::function<void(size_t)> & progressReport = {});
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Retrieving summary info
|
|
|
|
//
|
|
|
|
|
2016-12-25 13:40:15 +00:00
|
|
|
std::pair<float, float> GetMinMax(
|
|
|
|
sampleCount start, sampleCount len, bool mayThrow) const;
|
|
|
|
float GetRMS(sampleCount start, sampleCount len, bool mayThrow) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
2015-03-28 18:46:40 +00:00
|
|
|
// Getting block size and alignment information
|
2010-01-23 19:44:49 +00:00
|
|
|
//
|
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
// This returns a possibly large or negative value
|
2015-03-28 18:46:40 +00:00
|
|
|
sampleCount GetBlockStart(sampleCount position) const;
|
2016-09-06 13:19:27 +00:00
|
|
|
|
|
|
|
// These return a nonnegative number of samples meant to size a memory buffer
|
|
|
|
size_t GetBestBlockSize(sampleCount start) const;
|
|
|
|
size_t GetMaxBlockSize() const;
|
|
|
|
size_t GetIdealBlockSize() const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// This should only be used if you really, really know what
|
|
|
|
// you're doing!
|
|
|
|
//
|
|
|
|
|
2019-06-05 15:54:13 +00:00
|
|
|
BlockArray &GetBlockArray() { return mBlock; }
|
|
|
|
const BlockArray &GetBlockArray() const { return mBlock; }
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
//
|
|
|
|
// Private static variables
|
2014-06-03 20:30:19 +00:00
|
|
|
//
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
static size_t sMaxDiskBlockSize;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Private variables
|
|
|
|
//
|
|
|
|
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
SampleBlockFactoryPtr mpFactory;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-01-30 17:50:53 +00:00
|
|
|
BlockArray mBlock;
|
2010-01-23 19:44:49 +00:00
|
|
|
sampleFormat mSampleFormat;
|
2016-09-06 13:19:27 +00:00
|
|
|
|
|
|
|
// Not size_t! May need to be large:
|
2016-02-26 19:43:33 +00:00
|
|
|
sampleCount mNumSamples{ 0 };
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t mMinSamples; // min samples per block
|
|
|
|
size_t mMaxSamples; // max samples per block
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-02-26 19:43:33 +00:00
|
|
|
bool mErrorOpening{ false };
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
//
|
|
|
|
// Private methods
|
|
|
|
//
|
|
|
|
|
|
|
|
int FindBlock(sampleCount pos) const;
|
|
|
|
|
2020-08-30 22:18:18 +00:00
|
|
|
SeqBlock::SampleBlockPtr DoAppend(
|
2020-11-30 00:09:58 +00:00
|
|
|
constSamplePtr buffer, sampleFormat format, size_t len, bool coalesce);
|
2020-08-30 22:18:18 +00:00
|
|
|
|
2020-07-07 20:41:50 +00:00
|
|
|
static void AppendBlock(SampleBlockFactory *pFactory, sampleFormat format,
|
|
|
|
BlockArray &blocks,
|
2020-07-01 05:45:17 +00:00
|
|
|
sampleCount &numSamples,
|
|
|
|
const SeqBlock &b);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2020-07-01 05:45:17 +00:00
|
|
|
static bool Read(samplePtr buffer,
|
|
|
|
sampleFormat format,
|
|
|
|
const SeqBlock &b,
|
|
|
|
size_t blockRelativeStart,
|
|
|
|
size_t len,
|
|
|
|
bool mayThrow);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-11-29 13:41:10 +00:00
|
|
|
// Accumulate NEW block files onto the end of a block array.
|
|
|
|
// Does not change this sequence. The intent is to use
|
|
|
|
// CommitChangesIfConsistent later.
|
Unitary changes (#599)
* Define SampleBlockFactory replacing static members of SampleBlock...
... This will become an abstract base class
* Sequence and WaveTrack only store SampleBlockFactory not Project...
... This adds a dependency from Track to SampleBlock which temporarily enlarges
a cycle in the dependency graph
* Register a global factory of SampleBlockFactory...
... so that later we can make an abstract SampleBlockFactory, separate from the
concrete implementation in terms of sqlite, and inject the dependency at startup
avoiding static dependency
* New concrete classes SqliteSampleBlock, SqliteSampleBlockFactory...
... separated from abstract base classes and put into a new source file,
breaking dependency cycles, and perhaps allowing easy reimplementation for other
databases in the future.
Note that the new file is a header-less plug-in! Nothing depends on it. It
uses static initialization to influence the program's behavior.
* Compile dependency on sqlite3.h limited to just two .cpp files...
... these are ProjectFileIO.cpp and SqliteSampleBlock.cpp.
But there is still close cooperation of ProjectFileIO and SqliteSampleBlock.cpp.
This suggests that these files ought to be merged, and perhaps ProjectFileIO
also needs to be split into abstract and concrete classes, and there should be
another injection of a factory function at startup. That will make the choice
of database implementation even more modular.
Also removed one unnecessary inclusion of ProjectFileIO.h
* Fix crashes cutting and pasting cross-project...
... in case the source project is closed before the paste happens.
This caused destruction of the ProjectFileIO object and a closing of the sqlite
database with the sample data in it, leaving dangling references in the
SqliteSampleBlock objects.
The fix is that the SqliteSampleBlockFactory object holds a shared_ptr to the
ProjectFileIO object. So the clipboard may own WaveTracks, which own WaveClips,
which own Sequences, which own SqliteSampleBlockFactories, which keep the
ProjectFileIO and the database connection alive until the clipboard is cleared.
The consequence of the fix is delayed closing of the entire database associated
with the source project.
If the source project is reopened before the clipboard is cleared, will there
be correct concurrent access to the same persistent store? My preliminary
trials suggest this is so (reopening a saved project, deleting from it, closing
it again -- the clipboard contents are still unchanged and available).
2020-07-02 23:11:38 +00:00
|
|
|
static void Blockify(SampleBlockFactory &factory,
|
2020-07-01 05:45:17 +00:00
|
|
|
size_t maxSamples,
|
|
|
|
sampleFormat format,
|
|
|
|
BlockArray &list,
|
|
|
|
sampleCount start,
|
2020-11-30 00:09:58 +00:00
|
|
|
constSamplePtr buffer,
|
2020-07-01 05:45:17 +00:00
|
|
|
size_t len);
|
|
|
|
|
|
|
|
bool Get(int b,
|
|
|
|
samplePtr buffer,
|
|
|
|
sampleFormat format,
|
|
|
|
sampleCount start,
|
|
|
|
size_t len,
|
|
|
|
bool mayThrow) const;
|
2016-02-04 04:36:36 +00:00
|
|
|
|
2016-11-28 14:50:09 +00:00
|
|
|
public:
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
//
|
2016-11-28 14:50:09 +00:00
|
|
|
// Public methods
|
2010-01-23 19:44:49 +00:00
|
|
|
//
|
|
|
|
|
2016-11-28 14:50:09 +00:00
|
|
|
// This function throws if the track is messed up
|
2010-01-23 19:44:49 +00:00
|
|
|
// because of inconsistent block starts & lengths
|
2016-11-28 14:50:09 +00:00
|
|
|
void ConsistencyCheck (const wxChar *whereStr, bool mayThrow = true) const;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// This function prints information to stdout about the blocks in the
|
|
|
|
// tracks and indicates if there are inconsistencies.
|
2016-11-28 14:50:09 +00:00
|
|
|
static void DebugPrintf
|
|
|
|
(const BlockArray &block, sampleCount numSamples, wxString *dest);
|
|
|
|
|
|
|
|
private:
|
|
|
|
static void ConsistencyCheck
|
2017-07-23 16:32:27 +00:00
|
|
|
(const BlockArray &block, size_t maxSamples, size_t from,
|
2016-11-28 14:50:09 +00:00
|
|
|
sampleCount numSamples, const wxChar *whereStr,
|
|
|
|
bool mayThrow = true);
|
|
|
|
|
|
|
|
// The next two are used in methods that give a strong guarantee.
|
|
|
|
// They either throw because final consistency check fails, or swap the
|
|
|
|
// changed contents into place.
|
|
|
|
|
|
|
|
void CommitChangesIfConsistent
|
|
|
|
(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr);
|
|
|
|
|
|
|
|
void AppendBlocksIfConsistent
|
|
|
|
(BlockArray &additionalBlocks, bool replaceLast,
|
|
|
|
sampleCount numSamples, const wxChar *whereStr);
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // __AUDACITY_SEQUENCE__
|
|
|
|
|