2020-07-01 05:45:17 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
SampleBlock.cpp
|
|
|
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include "Audacity.h"
|
2020-07-23 06:04:46 +00:00
|
|
|
#include "InconsistencyException.h"
|
2020-07-01 05:45:17 +00:00
|
|
|
#include "SampleBlock.h"
|
2020-07-05 19:13:30 +00:00
|
|
|
#include "SampleFormat.h"
|
2020-07-01 05:45:17 +00:00
|
|
|
|
|
|
|
#include <wx/defs.h>
|
|
|
|
|
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 SampleBlockFactoryFactory& installedFactory()
|
2020-07-01 05:45:17 +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
|
|
|
static SampleBlockFactoryFactory theFactory;
|
|
|
|
return theFactory;
|
2020-07-01 05:45:17 +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
|
|
|
SampleBlockFactoryFactory SampleBlockFactory::RegisterFactoryFactory(
|
|
|
|
SampleBlockFactoryFactory newFactory )
|
2020-07-01 05:45:17 +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
|
|
|
auto &theFactory = installedFactory();
|
|
|
|
auto result = std::move( theFactory );
|
|
|
|
theFactory = std::move( newFactory );
|
|
|
|
return result;
|
2020-07-01 05:45:17 +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
|
|
|
SampleBlockFactoryPtr SampleBlockFactory::New( AudacityProject &project )
|
2020-07-01 05:45:17 +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
|
|
|
auto &factory = installedFactory();
|
|
|
|
if ( ! factory )
|
|
|
|
THROW_INCONSISTENCY_EXCEPTION;
|
|
|
|
return factory( project );
|
2020-07-01 05:45:17 +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
|
|
|
SampleBlockFactory::~SampleBlockFactory() = default;
|
2020-07-01 05:45:17 +00:00
|
|
|
|
2020-07-05 19:13:30 +00:00
|
|
|
SampleBlockPtr SampleBlockFactory::Create(samplePtr src,
|
|
|
|
size_t numsamples,
|
|
|
|
sampleFormat srcformat)
|
|
|
|
{
|
|
|
|
auto result = DoCreate(src, numsamples, srcformat);
|
|
|
|
if (!result)
|
|
|
|
THROW_INCONSISTENCY_EXCEPTION;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SampleBlockPtr SampleBlockFactory::CreateSilent(
|
|
|
|
size_t numsamples,
|
|
|
|
sampleFormat srcformat)
|
|
|
|
{
|
|
|
|
auto result = DoCreateSilent(numsamples, srcformat);
|
|
|
|
if (!result)
|
|
|
|
THROW_INCONSISTENCY_EXCEPTION;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SampleBlockPtr SampleBlockFactory::CreateFromXML(
|
|
|
|
sampleFormat srcformat,
|
|
|
|
const wxChar **attrs)
|
|
|
|
{
|
|
|
|
auto result = DoCreateFromXML(srcformat, attrs);
|
|
|
|
if (!result)
|
|
|
|
THROW_INCONSISTENCY_EXCEPTION;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
SampleBlock::~SampleBlock() = default;
|
2020-07-01 05:45:17 +00:00
|
|
|
|
2020-07-05 19:13:30 +00:00
|
|
|
size_t SampleBlock::GetSamples(samplePtr dest,
|
|
|
|
sampleFormat destformat,
|
|
|
|
size_t sampleoffset,
|
|
|
|
size_t numsamples, bool mayThrow)
|
|
|
|
{
|
|
|
|
try{ return DoGetSamples(dest, destformat, sampleoffset, numsamples); }
|
|
|
|
catch( ... ) {
|
|
|
|
if( mayThrow )
|
|
|
|
throw;
|
|
|
|
ClearSamples( dest, destformat, 0, numsamples );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MinMaxRMS SampleBlock::GetMinMaxRMS(
|
|
|
|
size_t start, size_t len, bool mayThrow)
|
|
|
|
{
|
|
|
|
try{ return DoGetMinMaxRMS(start, len); }
|
|
|
|
catch( ... ) {
|
|
|
|
if( mayThrow )
|
|
|
|
throw;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MinMaxRMS SampleBlock::GetMinMaxRMS(bool mayThrow) const
|
|
|
|
{
|
|
|
|
try{ return DoGetMinMaxRMS(); }
|
|
|
|
catch( ... ) {
|
|
|
|
if( mayThrow )
|
|
|
|
throw;
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|