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>
194 std::map< SampleBlockID, std::weak_ptr< SqliteSampleBlock > >;
204 switch (message.
type) {
205 case UndoRedoMessage::BeginPurge:
206 return OnBeginPurge(message.begin, message.end);
207 case UndoRedoMessage::EndPurge:
220 auto sb = std::make_shared<SqliteSampleBlock>(shared_from_this());
221 sb->SetSamples(src, numsamples, srcformat);
230 for (
auto end = mAllBlocks.end(), it = mAllBlocks.begin(); it !=
end;) {
231 if (it->second.expired())
233 it = mAllBlocks.erase(it);
235 result.insert( it->first );
248 result = std::make_shared<SqliteSampleBlock>(
nullptr);
249 result->mBlockID =
id;
253 result->mValid =
true;
264 for (
auto pair : attrs)
266 auto attr = pair.first;
267 auto value = pair.second;
271 if (attr ==
"blockid" && value.TryGet(nValue))
287 if (
auto block = wb.lock())
291 auto ssb = std::make_shared<SqliteSampleBlock>(shared_from_this());
293 ssb->mSampleFormat = srcformat;
308 auto cache =
mCache.lock();
316 const auto newCache =
327 std::rethrow_exception(std::current_exception());
328 std::fill(newCache->begin(), newCache->end(), 0.f);
335 const std::shared_ptr<SqliteSampleBlockFactory> &pFactory)
382 auto &pConnection =
mpFactory->mppConnection->mpConnection;
387 XO(
"Connection to project file is null"),
389 "Error:_Disk_full_or_not_writable"
392 return pConnection.get();
422 memset(dest, 0, numsamples *
size);
428 "SELECT samples FROM sampleblocks WHERE blockid = ?1;");
442 auto sizes =
SetSizes(numsamples, srcformat);
456 "SELECT summary256 FROM sampleblocks WHERE blockid = ?1;");
464 "SELECT summary64k FROM sampleblocks WHERE blockid = ?1;");
493 memset(dest, 0, 3 * numframes *
sizeof(
float ));
524 float max = -FLT_MAX;
538 float *samples = (
float *) blockData.
ptr();
541 for (
size_t i = 0; i < copied; ++i, ++samples)
543 float sample = *samples;
555 sumsq += (sample * sample);
559 return {
min, max, (float)
sqrt(sumsq / len) };
600 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
603 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
606 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
610 rc = sqlite3_step(stmt);
611 if (rc != SQLITE_ROW)
616 wxLogDebug(
wxT(
"SqliteSampleBlock::GetBlob - SQLITE error %s"), sqlite3_errmsg(db));
619 sqlite3_clear_bindings(stmt);
636 size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
638 srcoffset =
std::min(srcoffset, blobbytes);
639 minbytes =
std::min(srcbytes, blobbytes - srcoffset);
680 wxASSERT(destformat ==
floatSample || destformat == srcformat);
690 if (srcbytes - minbytes)
692 memset(dest, 0, srcbytes - minbytes);
696 sqlite3_clear_bindings(stmt);
718 "SELECT sampleformat, summin, summax, sumrms,"
720 " FROM sampleblocks WHERE blockid = ?1;");
725 if (sqlite3_bind_int64(stmt, 1, sbid))
731 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
735 rc = sqlite3_step(stmt);
736 if (rc != SQLITE_ROW)
743 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
746 sqlite3_clear_bindings(stmt);
757 mSumMin = sqlite3_column_double(stmt, 1);
758 mSumMax = sqlite3_column_double(stmt, 2);
759 mSumRms = sqlite3_column_double(stmt, 3);
764 sqlite3_clear_bindings(stmt);
772 const auto mSummary256Bytes = sizes.first;
773 const auto mSummary64kBytes = sizes.second;
780 "INSERT INTO sampleblocks (sampleformat, summin, summax, sumrms,"
781 " summary256, summary64k, samples)"
782 " VALUES(?1,?2,?3,?4,?5,?6,?7);");
787 if (sqlite3_bind_int(stmt, 1,
static_cast<int>(
mSampleFormat)) ||
788 sqlite3_bind_double(stmt, 2,
mSumMin) ||
789 sqlite3_bind_double(stmt, 3,
mSumMax) ||
790 sqlite3_bind_double(stmt, 4,
mSumRms) ||
791 sqlite3_bind_blob(stmt, 5,
mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
792 sqlite3_bind_blob(stmt, 6,
mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
797 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
801 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
805 rc = sqlite3_step(stmt);
806 if (rc != SQLITE_DONE)
811 wxLogDebug(
wxT(
"SqliteSampleBlock::Commit - SQLITE error %s"), sqlite3_errmsg(db));
814 sqlite3_clear_bindings(stmt);
823 mBlockID = sqlite3_last_insert_rowid(db);
835 sqlite3_clear_bindings(stmt);
850 "DELETE FROM sampleblocks WHERE blockid = ?1;");
855 if (sqlite3_bind_int64(stmt, 1,
mBlockID))
858 "sqlite3.rc", std::to_string(sqlite3_errcode(
Conn()->
DB())));
861 wxASSERT_MSG(
false,
wxT(
"Binding failed...bug!!!"));
865 rc = sqlite3_step(stmt);
866 if (rc != SQLITE_DONE)
871 wxLogDebug(
wxT(
"SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
874 sqlite3_clear_bindings(stmt);
883 sqlite3_clear_bindings(stmt);
895 mSampleFormat = srcformat;
896 mSampleCount = numsamples;
897 mSampleBytes = mSampleCount *
SAMPLE_SIZE(mSampleFormat);
899 int frames64k = (mSampleCount + 65535) / 65536;
900 int frames256 = frames64k * 256;
901 return { frames256 * bytesPerFrame, frames64k * bytesPerFrame };
911 const auto mSummary256Bytes = sizes.first;
912 const auto mSummary64kBytes = sizes.second;
926 samples = samplebuffer.get();
938 double totalSquares = 0.0;
939 double fraction = 0.0;
945 for (
int i = 0; i < sumLen; ++i)
947 min = samples[i * 256];
948 max = samples[i * 256];
955 fraction = 1.0 - (jcount / 256.0);
958 for (
int j = 1; j < jcount; ++j)
960 float f1 = samples[i * 256 + j];
973 totalSquares += sumsq;
976 summary256[i *
fields + 1] = max;
978 summary256[i *
fields + 2] = (float)
sqrt(sumsq / jcount);
981 for (
int i = sumLen, frames256 = mSummary256Bytes /
bytesPerFrame;
987 summary256[i *
fields] = FLT_MAX;
988 summary256[i *
fields + 1] = -FLT_MAX;
989 summary256[i *
fields + 2] = 0.0f;
998 for (
int i = 0; i < sumLen; ++i)
1000 min = summary256[3 * i * 256];
1001 max = summary256[3 * i * 256 + 1];
1002 sumsq = summary256[3 * i * 256 + 2];
1005 for (
int j = 1; j < 256; ++j)
1009 if (summary256[3 * (i * 256 + j)] <
min)
1011 min = summary256[3 * (i * 256 + j)];
1014 if (summary256[3 * (i * 256 + j) + 1] > max)
1016 max = summary256[3 * (i * 256 + j) + 1];
1019 float r1 = summary256[3 * (i * 256 + j) + 2];
1023 double denom = (i < sumLen - 1) ? 256.0 : summaries - fraction;
1024 float rms = (float)
sqrt(sumsq / denom);
1027 summary64k[i *
fields + 1] = max;
1028 summary64k[i *
fields + 2] = rms;
1031 for (
int i = sumLen, frames64k = mSummary64kBytes /
bytesPerFrame;
1034 wxASSERT_MSG(
false,
wxT(
"Out of data for mSummaryInfo"));
1036 summary64k[i *
fields] = 0.0f;
1037 summary64k[i *
fields + 1] = 0.0f;
1038 summary64k[i *
fields + 2] = 0.0f;
1042 min = summary64k[0];
1043 max = summary64k[1];
1045 for (
int i = 1; i < sumLen; ++i)
1052 if (summary64k[i *
fields + 1] > max)
1054 max = summary64k[i *
fields + 1];
1079 if (
const auto saved =
manager.GetSavedState(); saved >= 0)
1080 manager.VisitStates(f, saved, saved + 1);
1089 auto id = pBlock->GetBlockID();
1090 if (
id > 0 && !wontDelete.count(
id))
1091 mayDelete.insert(
id);
1097 return mayDelete.size();
1109 constexpr auto ProgressDialogShowDelay = std::chrono::milliseconds (200);
1113 auto purgeStartTime = std::chrono::system_clock::now();
1114 std::shared_ptr<ProgressDialog> progressDialog;
1119 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
1120 std::chrono::system_clock::now() - purgeStartTime);
1121 if(elapsed >= ProgressDialogShowDelay)
1122 progressDialog =
MakeProgress(
XO(
"Progress"),
XO(
"Discarding undo/redo history"), 0);
1125 progressDialog->Poll(nDeleted, nToDelete);
1137 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,...
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
void OnSampleBlockDtor(const SampleBlock &)
std::map< SampleBlockID, std::weak_ptr< SqliteSampleBlock > > AllBlocksMap
SqliteSampleBlockFactory(AudacityProject &project)
AudacityProject & mProject
SampleBlockPtr DoCreate(constSamplePtr src, size_t numsamples, sampleFormat srcformat) override
std::function< void()> mSampleBlockDeletionCallback
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.