41 std::weak_ptr<std::vector<float>>
mCache;
46 const std::shared_ptr<SqliteSampleBlockFactory> &pFactory);
65 size_t numsamples) override;
69 bool GetSummary256(
float *dest,
size_t frameoffset,
size_t numframes) override;
70 bool GetSummary64k(
float *dest,
size_t frameoffset,
size_t numframes) override;
117 const std::shared_ptr<SqliteSampleBlockFactory>
mpFactory;
134#if defined(WORDS_BIGENDIAN)
135#error All sample block data is little endian...big endian not yet supported
142static std::map< SampleBlockID, std::shared_ptr<SqliteSampleBlock> >
148 ,
public std::enable_shared_from_this<SqliteSampleBlockFactory>
180 std::optional<SampleBlock::DeletionCallback::Scope>
mScope;
188 std::map< SampleBlockID, std::weak_ptr< SqliteSampleBlock > >;
198 switch (message.
type) {
199 case UndoRedoMessage::BeginPurge:
200 return OnBeginPurge(message.begin, message.end);
201 case UndoRedoMessage::EndPurge:
214 auto sb = std::make_shared<SqliteSampleBlock>(shared_from_this());
215 sb->SetSamples(src, numsamples, srcformat);
224 for (
auto end = mAllBlocks.end(), it = mAllBlocks.begin(); it !=
end;) {
225 if (it->second.expired())
227 it = mAllBlocks.erase(it);
229 result.insert( it->first );
242 result = std::make_shared<SqliteSampleBlock>(
nullptr);
243 result->mBlockID =
id;
247 result->mValid =
true;
258 for (
auto pair : attrs)
260 auto attr = pair.first;
261 auto value = pair.second;
265 if (attr ==
"blockid" && value.TryGet(nValue))
281 if (
auto block = wb.lock())
285 auto ssb = std::make_shared<SqliteSampleBlock>(shared_from_this());
287 ssb->mSampleFormat = srcformat;
302 auto cache =
mCache.lock();
310 const auto newCache =
321 std::rethrow_exception(std::current_exception());
322 std::fill(newCache->begin(), newCache->end(), 0.f);
329 const std::shared_ptr<SqliteSampleBlockFactory> &pFactory)
374 auto &pConnection =
mpFactory->mppConnection->mpConnection;
379 XO(
"Connection to project file is null"),
381 "Error:_Disk_full_or_not_writable"
384 return pConnection.get();
414 memset(dest, 0, numsamples *
size);
420 "SELECT samples FROM sampleblocks WHERE blockid = ?1;");
434 auto sizes =
SetSizes(numsamples, srcformat);
448 "SELECT summary256 FROM sampleblocks WHERE blockid = ?1;");
456 "SELECT summary64k FROM sampleblocks WHERE blockid = ?1;");
485 memset(dest, 0, 3 * numframes *
sizeof(
float ));
516 float max = -FLT_MAX;
530 float *samples = (
float *) blockData.
ptr();
533 for (
size_t i = 0; i < copied; ++i, ++samples)
535 float sample = *samples;
547 sumsq += (sample * sample);
551 return {
min, max, (float)
sqrt(sumsq / len) };
592 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
595 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
598 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
602 rc = sqlite3_step(stmt);
603 if (rc != SQLITE_ROW)
608 wxLogDebug(
wxT(
"SqliteSampleBlock::GetBlob - SQLITE error %s"), sqlite3_errmsg(db));
611 sqlite3_clear_bindings(stmt);
628 size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
630 srcoffset =
std::min(srcoffset, blobbytes);
631 minbytes =
std::min(srcbytes, blobbytes - srcoffset);
672 wxASSERT(destformat ==
floatSample || destformat == srcformat);
682 if (srcbytes - minbytes)
684 memset(dest, 0, srcbytes - minbytes);
688 sqlite3_clear_bindings(stmt);
710 "SELECT sampleformat, summin, summax, sumrms,"
712 " FROM sampleblocks WHERE blockid = ?1;");
717 if (sqlite3_bind_int64(stmt, 1, sbid))
723 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
727 rc = sqlite3_step(stmt);
728 if (rc != SQLITE_ROW)
735 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
738 sqlite3_clear_bindings(stmt);
749 mSumMin = sqlite3_column_double(stmt, 1);
750 mSumMax = sqlite3_column_double(stmt, 2);
751 mSumRms = sqlite3_column_double(stmt, 3);
756 sqlite3_clear_bindings(stmt);
764 const auto mSummary256Bytes = sizes.first;
765 const auto mSummary64kBytes = sizes.second;
772 "INSERT INTO sampleblocks (sampleformat, summin, summax, sumrms,"
773 " summary256, summary64k, samples)"
774 " VALUES(?1,?2,?3,?4,?5,?6,?7);");
779 if (sqlite3_bind_int(stmt, 1,
static_cast<int>(
mSampleFormat)) ||
780 sqlite3_bind_double(stmt, 2,
mSumMin) ||
781 sqlite3_bind_double(stmt, 3,
mSumMax) ||
782 sqlite3_bind_double(stmt, 4,
mSumRms) ||
783 sqlite3_bind_blob(stmt, 5,
mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
784 sqlite3_bind_blob(stmt, 6,
mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
789 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
793 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
797 rc = sqlite3_step(stmt);
798 if (rc != SQLITE_DONE)
803 wxLogDebug(
wxT(
"SqliteSampleBlock::Commit - SQLITE error %s"), sqlite3_errmsg(db));
806 sqlite3_clear_bindings(stmt);
815 mBlockID = sqlite3_last_insert_rowid(db);
827 sqlite3_clear_bindings(stmt);
842 "DELETE FROM sampleblocks WHERE blockid = ?1;");
847 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
850 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
853 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
857 rc = sqlite3_step(stmt);
858 if (rc != SQLITE_DONE)
863 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
866 sqlite3_clear_bindings(stmt);
875 sqlite3_clear_bindings(stmt);
887 mSampleFormat = srcformat;
888 mSampleCount = numsamples;
889 mSampleBytes = mSampleCount *
SAMPLE_SIZE(mSampleFormat);
891 int frames64k = (mSampleCount + 65535) / 65536;
892 int frames256 = frames64k * 256;
893 return { frames256 * bytesPerFrame, frames64k * bytesPerFrame };
903 const auto mSummary256Bytes = sizes.first;
904 const auto mSummary64kBytes = sizes.second;
918 samples = samplebuffer.get();
930 double totalSquares = 0.0;
931 double fraction = 0.0;
937 for (
int i = 0; i < sumLen; ++i)
939 min = samples[i * 256];
940 max = samples[i * 256];
947 fraction = 1.0 - (jcount / 256.0);
950 for (
int j = 1; j < jcount; ++j)
952 float f1 = samples[i * 256 + j];
965 totalSquares += sumsq;
968 summary256[i *
fields + 1] = max;
970 summary256[i *
fields + 2] = (float)
sqrt(sumsq / jcount);
973 for (
int i = sumLen, frames256 = mSummary256Bytes /
bytesPerFrame;
979 summary256[i *
fields] = FLT_MAX;
980 summary256[i *
fields + 1] = -FLT_MAX;
981 summary256[i *
fields + 2] = 0.0f;
990 for (
int i = 0; i < sumLen; ++i)
992 min = summary256[3 * i * 256];
993 max = summary256[3 * i * 256 + 1];
994 sumsq = summary256[3 * i * 256 + 2];
997 for (
int j = 1; j < 256; ++j)
1001 if (summary256[3 * (i * 256 + j)] <
min)
1003 min = summary256[3 * (i * 256 + j)];
1006 if (summary256[3 * (i * 256 + j) + 1] > max)
1008 max = summary256[3 * (i * 256 + j) + 1];
1011 float r1 = summary256[3 * (i * 256 + j) + 2];
1015 double denom = (i < sumLen - 1) ? 256.0 : summaries - fraction;
1016 float rms = (float)
sqrt(sumsq / denom);
1019 summary64k[i *
fields + 1] = max;
1020 summary64k[i *
fields + 2] = rms;
1023 for (
int i = sumLen, frames64k = mSummary64kBytes /
bytesPerFrame;
1026 wxASSERT_MSG(
false,
wxT(
"Out of data for mSummaryInfo"));
1028 summary64k[i *
fields] = 0.0f;
1029 summary64k[i *
fields + 1] = 0.0f;
1030 summary64k[i *
fields + 2] = 0.0f;
1034 min = summary64k[0];
1035 max = summary64k[1];
1037 for (
int i = 1; i < sumLen; ++i)
1044 if (summary64k[i *
fields + 1] > max)
1046 max = summary64k[i *
fields + 1];
1071 if (
const auto saved =
manager.GetSavedState(); saved >= 0)
1072 manager.VisitStates(f, saved, saved + 1);
1081 auto id = pBlock->GetBlockID();
1082 if (
id > 0 && !wontDelete.count(
id))
1083 mayDelete.insert(
id);
1089 return mayDelete.size();
1101 constexpr auto ProgressDialogShowDelay = std::chrono::milliseconds (200);
1105 auto purgeStartTime = std::chrono::system_clock::now();
1106 std::shared_ptr<ProgressDialog> progressDialog;
1107 mScope.emplace([=, nDeleted = 0](
auto&)
mutable {
1111 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
1112 std::chrono::system_clock::now() - purgeStartTime);
1113 if(elapsed >= ProgressDialogShowDelay)
1114 progressDialog =
MakeProgress(
XO(
"Progress"),
XO(
"Discarding undo/redo history"), 0);
1117 progressDialog->Poll(nDeleted, nToDelete);
1129 return std::make_shared<SqliteSampleBlockFactory>(
project );
@ Internal
Indicates internal failure from Audacity.
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
An audio segment is either a whole clip or the silence between clips. Views allow shared references t...
std::shared_ptr< std::vector< float > > BlockSampleView
Toolkit-neutral facade for basic user interface services.
std::shared_ptr< SampleBlock > SampleBlockPtr
std::unordered_set< SampleBlockID > SampleBlockIDSet
Declare DBConnection, which maintains database connection and associated status and background thread...
static const AttachedProjectObjects::RegisteredFactory manager
std::shared_ptr< const SampleBlock > SampleBlockConstPtr
#define ADD_EXCEPTION_CONTEXT(name, value)
static size_t EstimateRemovedBlocks(AudacityProject &project, size_t begin, size_t end)
Just to find a denominator for a progress indicator.
static std::map< SampleBlockID, std::shared_ptr< SqliteSampleBlock > > sSilentBlocks
static SampleBlockFactory::Factory::Scope scope
std::vector< Attribute > AttributesList
void reinit(Integral count, bool initialize=false)
Base class for exceptions specially processed by the application.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
void ThrowException(bool write) const
throw and show appropriate message box
sqlite3_stmt * Prepare(enum StatementID id, const char *sql)
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
typename GlobalVariable< Factory, const std::function< SampleBlockFactoryPtr(AudacityProject &) >, nullptr, Options... >::Scope Scope
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
A move-only handle representing a connection to a Publisher.
static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid)
abstract base class with methods to produce SampleBlock objects
std::unordered_set< SampleBlockID > SampleBlockIDs
Abstract class allows access to contents of a block of sound samples, serialization as XML,...
A MessageBoxException that shows a given, unvarying string.
Implementation of SampleBlockFactory using Sqlite database.
SampleBlockIDs GetActiveBlockIDs() override
SampleBlockPtr DoCreateFromXML(sampleFormat srcformat, const AttributesList &attrs) override
std::optional< SampleBlock::DeletionCallback::Scope > mScope
std::map< SampleBlockID, std::weak_ptr< SqliteSampleBlock > > AllBlocksMap
SqliteSampleBlockFactory(AudacityProject &project)
AudacityProject & mProject
SampleBlockPtr DoCreate(constSamplePtr src, size_t numsamples, sampleFormat srcformat) override
SampleBlockPtr DoCreateFromId(sampleFormat srcformat, SampleBlockID id) override
void OnBeginPurge(size_t begin, size_t end)
const std::shared_ptr< ConnectionPtr > mppConnection
~SqliteSampleBlockFactory() override
SampleBlockPtr DoCreateSilent(size_t numsamples, sampleFormat srcformat) override
Observer::Subscription mUndoSubscription
Implementation of SampleBlock using Sqlite database.
size_t GetSpaceUsage() const override
size_t DoGetSamples(samplePtr dest, sampleFormat destformat, size_t sampleoffset, size_t numsamples) override
Sizes SetSizes(size_t numsamples, sampleFormat srcformat)
BlockSampleView GetFloatSampleView(bool mayThrow) override
bool GetSummary(float *dest, size_t frameoffset, size_t numframes, DBConnection::StatementID id, const char *sql)
void Load(SampleBlockID sbid)
std::pair< size_t, size_t > Sizes
Numbers of bytes needed for 256 and for 64k summaries.
void CalcSummary(Sizes sizes)
bool GetSummary64k(float *dest, size_t frameoffset, size_t numframes) override
Non-throwing, should fill with zeroes on failure.
SqliteSampleBlock(const std::shared_ptr< SqliteSampleBlockFactory > &pFactory)
~SqliteSampleBlock() override
std::weak_ptr< std::vector< float > > mCache
sampleFormat mSampleFormat
void CloseLock() noexcept override
size_t GetBlob(void *dest, sampleFormat destformat, sqlite3_stmt *stmt, sampleFormat srcformat, size_t srcoffset, size_t srcbytes)
ArrayOf< char > mSummary256
ArrayOf< char > mSummary64k
const std::shared_ptr< SqliteSampleBlockFactory > mpFactory
MinMaxRMS DoGetMinMaxRMS() const override
Gets extreme values for the entire block.
friend SqliteSampleBlockFactory
void SetSamples(constSamplePtr src, size_t numsamples, sampleFormat srcformat)
DBConnection * Conn() const
This must never be called for silent blocks.
SampleBlockID GetBlockID() const override
sampleFormat GetSampleFormat() const override
bool GetSummary256(float *dest, size_t frameoffset, size_t numframes) override
Non-throwing, should fill with zeroes on failure.
size_t GetSampleCount() const override
void SaveXML(XMLWriter &xmlFile) override
static TrackList & Get(AudacityProject &project)
static UndoManager & Get(AudacityProject &project)
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
void WriteAttr(const wxString &name, const Identifier &value)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
TRACK_API TrackList * Find(const UndoStackElem &state)
WAVE_TRACK_API void InspectBlocks(const TrackList &tracks, BlockInspector inspector, SampleBlockIDSet *pIDs=nullptr)
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
__finl float_x4 __vecc sqrt(const float_x4 &a)
Type of message published by UndoManager.
enum UndoRedoMessage::Type type
Holds one item with description and time range for the UndoManager.