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>
193 std::map< SampleBlockID, std::weak_ptr< SqliteSampleBlock > >;
203 switch (message.
type) {
204 case UndoRedoMessage::BeginPurge:
205 return OnBeginPurge(message.begin, message.end);
206 case UndoRedoMessage::EndPurge:
219 auto sb = std::make_shared<SqliteSampleBlock>(shared_from_this());
220 sb->SetSamples(src, numsamples, srcformat);
229 for (
auto end = mAllBlocks.end(), it = mAllBlocks.begin(); it !=
end;) {
230 if (it->second.expired())
232 it = mAllBlocks.erase(it);
234 result.insert( it->first );
247 result = std::make_shared<SqliteSampleBlock>(
nullptr);
248 result->mBlockID =
id;
252 result->mValid =
true;
263 for (
auto pair : attrs)
265 auto attr = pair.first;
266 auto value = pair.second;
270 if (attr ==
"blockid" && value.TryGet(nValue))
286 if (
auto block = wb.lock())
290 auto ssb = std::make_shared<SqliteSampleBlock>(shared_from_this());
292 ssb->mSampleFormat = srcformat;
307 auto cache =
mCache.lock();
315 const auto newCache =
326 std::rethrow_exception(std::current_exception());
327 std::fill(newCache->begin(), newCache->end(), 0.f);
334 const std::shared_ptr<SqliteSampleBlockFactory> &pFactory)
384 auto &pConnection =
mpFactory->mppConnection->mpConnection;
389 XO(
"Connection to project file is null"),
391 "Error:_Disk_full_or_not_writable"
394 return pConnection.get();
424 memset(dest, 0, numsamples *
size);
430 "SELECT samples FROM sampleblocks WHERE blockid = ?1;");
444 auto sizes =
SetSizes(numsamples, srcformat);
458 "SELECT summary256 FROM sampleblocks WHERE blockid = ?1;");
466 "SELECT summary64k FROM sampleblocks WHERE blockid = ?1;");
495 memset(dest, 0, 3 * numframes *
sizeof(
float ));
526 float max = -FLT_MAX;
540 float *samples = (
float *) blockData.
ptr();
543 for (
size_t i = 0; i < copied; ++i, ++samples)
545 float sample = *samples;
557 sumsq += (sample * sample);
561 return {
min, max, (float)
sqrt(sumsq / len) };
602 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
605 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
608 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
612 rc = sqlite3_step(stmt);
613 if (rc != SQLITE_ROW)
618 wxLogDebug(
wxT(
"SqliteSampleBlock::GetBlob - SQLITE error %s"), sqlite3_errmsg(db));
621 sqlite3_clear_bindings(stmt);
638 size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
640 srcoffset =
std::min(srcoffset, blobbytes);
641 minbytes =
std::min(srcbytes, blobbytes - srcoffset);
682 wxASSERT(destformat ==
floatSample || destformat == srcformat);
692 if (srcbytes - minbytes)
694 memset(dest, 0, srcbytes - minbytes);
698 sqlite3_clear_bindings(stmt);
720 "SELECT sampleformat, summin, summax, sumrms,"
722 " FROM sampleblocks WHERE blockid = ?1;");
727 if (sqlite3_bind_int64(stmt, 1, sbid))
733 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
737 rc = sqlite3_step(stmt);
738 if (rc != SQLITE_ROW)
745 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
748 sqlite3_clear_bindings(stmt);
759 mSumMin = sqlite3_column_double(stmt, 1);
760 mSumMax = sqlite3_column_double(stmt, 2);
761 mSumRms = sqlite3_column_double(stmt, 3);
766 sqlite3_clear_bindings(stmt);
774 const auto mSummary256Bytes = sizes.first;
775 const auto mSummary64kBytes = sizes.second;
782 "INSERT INTO sampleblocks (sampleformat, summin, summax, sumrms,"
783 " summary256, summary64k, samples)"
784 " VALUES(?1,?2,?3,?4,?5,?6,?7);");
789 if (sqlite3_bind_int(stmt, 1,
static_cast<int>(
mSampleFormat)) ||
790 sqlite3_bind_double(stmt, 2,
mSumMin) ||
791 sqlite3_bind_double(stmt, 3,
mSumMax) ||
792 sqlite3_bind_double(stmt, 4,
mSumRms) ||
793 sqlite3_bind_blob(stmt, 5,
mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
794 sqlite3_bind_blob(stmt, 6,
mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
799 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
803 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
807 rc = sqlite3_step(stmt);
808 if (rc != SQLITE_DONE)
813 wxLogDebug(
wxT(
"SqliteSampleBlock::Commit - SQLITE error %s"), sqlite3_errmsg(db));
816 sqlite3_clear_bindings(stmt);
825 mBlockID = sqlite3_last_insert_rowid(db);
837 sqlite3_clear_bindings(stmt);
852 "DELETE FROM sampleblocks WHERE blockid = ?1;");
857 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
860 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
863 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
867 rc = sqlite3_step(stmt);
868 if (rc != SQLITE_DONE)
873 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
876 sqlite3_clear_bindings(stmt);
885 sqlite3_clear_bindings(stmt);
897 mSampleFormat = srcformat;
898 mSampleCount = numsamples;
899 mSampleBytes = mSampleCount *
SAMPLE_SIZE(mSampleFormat);
901 int frames64k = (mSampleCount + 65535) / 65536;
902 int frames256 = frames64k * 256;
903 return { frames256 * bytesPerFrame, frames64k * bytesPerFrame };
913 const auto mSummary256Bytes = sizes.first;
914 const auto mSummary64kBytes = sizes.second;
928 samples = samplebuffer.get();
940 double totalSquares = 0.0;
941 double fraction = 0.0;
947 for (
int i = 0; i < sumLen; ++i)
949 min = samples[i * 256];
950 max = samples[i * 256];
957 fraction = 1.0 - (jcount / 256.0);
960 for (
int j = 1; j < jcount; ++j)
962 float f1 = samples[i * 256 + j];
975 totalSquares += sumsq;
978 summary256[i *
fields + 1] = max;
980 summary256[i *
fields + 2] = (float)
sqrt(sumsq / jcount);
983 for (
int i = sumLen, frames256 = mSummary256Bytes /
bytesPerFrame;
989 summary256[i *
fields] = FLT_MAX;
990 summary256[i *
fields + 1] = -FLT_MAX;
991 summary256[i *
fields + 2] = 0.0f;
1000 for (
int i = 0; i < sumLen; ++i)
1002 min = summary256[3 * i * 256];
1003 max = summary256[3 * i * 256 + 1];
1004 sumsq = summary256[3 * i * 256 + 2];
1007 for (
int j = 1; j < 256; ++j)
1011 if (summary256[3 * (i * 256 + j)] <
min)
1013 min = summary256[3 * (i * 256 + j)];
1016 if (summary256[3 * (i * 256 + j) + 1] > max)
1018 max = summary256[3 * (i * 256 + j) + 1];
1021 float r1 = summary256[3 * (i * 256 + j) + 2];
1025 double denom = (i < sumLen - 1) ? 256.0 : summaries - fraction;
1026 float rms = (float)
sqrt(sumsq / denom);
1029 summary64k[i *
fields + 1] = max;
1030 summary64k[i *
fields + 2] = rms;
1033 for (
int i = sumLen, frames64k = mSummary64kBytes /
bytesPerFrame;
1036 wxASSERT_MSG(
false,
wxT(
"Out of data for mSummaryInfo"));
1038 summary64k[i *
fields] = 0.0f;
1039 summary64k[i *
fields + 1] = 0.0f;
1040 summary64k[i *
fields + 2] = 0.0f;
1044 min = summary64k[0];
1045 max = summary64k[1];
1047 for (
int i = 1; i < sumLen; ++i)
1054 if (summary64k[i *
fields + 1] > max)
1056 max = summary64k[i *
fields + 1];
1081 if (
const auto saved =
manager.GetSavedState(); saved >= 0)
1082 manager.VisitStates(f, saved, saved + 1);
1091 auto id = pBlock->GetBlockID();
1092 if (
id > 0 && !wontDelete.count(
id))
1093 mayDelete.insert(
id);
1099 return mayDelete.size();
1111 constexpr auto ProgressDialogShowDelay = std::chrono::milliseconds (200);
1115 auto purgeStartTime = std::chrono::system_clock::now();
1116 std::shared_ptr<ProgressDialog> progressDialog;
1121 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
1122 std::chrono::system_clock::now() - purgeStartTime);
1123 if(elapsed >= ProgressDialogShowDelay)
1124 progressDialog =
MakeProgress(
XO(
"Progress"),
XO(
"Discarding undo/redo history"), 0);
1127 progressDialog->Poll(nDeleted, nToDelete);
1139 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)
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,...
std::function< void(const SampleBlock &)> DeletionCallback
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::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
SampleBlock::DeletionCallback mSampleBlockDeletionCallback
~SqliteSampleBlockFactory() override
SampleBlock::DeletionCallback GetSampleBlockDeletionCallback() const
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.