Audacity  3.0.3
Public Types | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
SqliteSampleBlock Class Referencefinal

Implementation of SampleBlock using Sqlite database. More...

Inheritance diagram for SqliteSampleBlock:
[legend]
Collaboration diagram for SqliteSampleBlock:
[legend]

Public Types

using Sizes = std::pair< size_t, size_t >
 Numbers of bytes needed for 256 and for 64k summaries. More...
 

Public Member Functions

 SqliteSampleBlock (const std::shared_ptr< SqliteSampleBlockFactory > &pFactory)
 
 ~SqliteSampleBlock () override
 
void CloseLock () override
 
void SetSamples (constSamplePtr src, size_t numsamples, sampleFormat srcformat)
 
void Commit (Sizes sizes)
 
void Delete ()
 
SampleBlockID GetBlockID () const override
 
size_t DoGetSamples (samplePtr dest, sampleFormat destformat, size_t sampleoffset, size_t numsamples) override
 
sampleFormat GetSampleFormat () const
 
size_t GetSampleCount () const override
 
bool GetSummary256 (float *dest, size_t frameoffset, size_t numframes) override
 Non-throwing, should fill with zeroes on failure. More...
 
bool GetSummary64k (float *dest, size_t frameoffset, size_t numframes) override
 Non-throwing, should fill with zeroes on failure. More...
 
double GetSumMin () const
 
double GetSumMax () const
 
double GetSumRms () const
 
MinMaxRMS DoGetMinMaxRMS (size_t start, size_t len) override
 Gets extreme values for the specified region. More...
 
MinMaxRMS DoGetMinMaxRMS () const override
 Gets extreme values for the entire block. More...
 
size_t GetSpaceUsage () const override
 
void SaveXML (XMLWriter &xmlFile) override
 
- Public Member Functions inherited from SampleBlock
virtual ~SampleBlock ()
 
size_t GetSamples (samplePtr dest, sampleFormat destformat, size_t sampleoffset, size_t numsamples, bool mayThrow=true)
 
MinMaxRMS GetMinMaxRMS (size_t start, size_t len, bool mayThrow=true)
 Gets extreme values for the specified region. More...
 
MinMaxRMS GetMinMaxRMS (bool mayThrow=true) const
 Gets extreme values for the entire block. More...
 

Private Types

enum  { fields = 3, bytesPerFrame = fields * sizeof(float) }
 

Private Member Functions

bool IsSilent () const
 
void Load (SampleBlockID sbid)
 
bool GetSummary (float *dest, size_t frameoffset, size_t numframes, DBConnection::StatementID id, const char *sql)
 
size_t GetBlob (void *dest, sampleFormat destformat, sqlite3_stmt *stmt, sampleFormat srcformat, size_t srcoffset, size_t srcbytes)
 
Sizes SetSizes (size_t numsamples, sampleFormat srcformat)
 
void CalcSummary (Sizes sizes)
 
DBConnectionConn () const
 This must never be called for silent blocks. More...
 
sqlite3 * DB () const
 

Private Attributes

friend SqliteSampleBlockFactory
 
const std::shared_ptr< SqliteSampleBlockFactorympFactory
 
bool mValid { false }
 
bool mLocked = false
 
SampleBlockID mBlockID { 0 }
 
ArrayOf< char > mSamples
 
size_t mSampleBytes
 
size_t mSampleCount
 
sampleFormat mSampleFormat
 
ArrayOf< char > mSummary256
 
ArrayOf< char > mSummary64k
 
double mSumMin
 
double mSumMax
 
double mSumRms
 

Additional Inherited Members

Detailed Description

Implementation of SampleBlock using Sqlite database.

Definition at line 27 of file SqliteSampleBlock.cpp.

Member Typedef Documentation

◆ Sizes

using SqliteSampleBlock::Sizes = std::pair< size_t, size_t >

Numbers of bytes needed for 256 and for 64k summaries.

Definition at line 41 of file SqliteSampleBlock.cpp.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private
Enumerator
fields 
bytesPerFrame 

Definition at line 85 of file SqliteSampleBlock.cpp.

85  {
86  fields = 3, /* min, max, rms */
87  bytesPerFrame = fields * sizeof(float),
88  };

Constructor & Destructor Documentation

◆ SqliteSampleBlock()

SqliteSampleBlock::SqliteSampleBlock ( const std::shared_ptr< SqliteSampleBlockFactory > &  pFactory)
explicit

Definition at line 293 of file SqliteSampleBlock.cpp.

295 : mpFactory(pFactory)
296 {
298  mSampleBytes = 0;
299  mSampleCount = 0;
300 
301  mSumMin = 0.0;
302  mSumMax = 0.0;
303  mSumRms = 0.0;
304 }

References floatSample, mSampleBytes, mSampleCount, mSampleFormat, mSumMax, mSumMin, and mSumRms.

◆ ~SqliteSampleBlock()

SqliteSampleBlock::~SqliteSampleBlock ( )
override

Definition at line 306 of file SqliteSampleBlock.cpp.

307 {
308  if (mpFactory) {
309  auto &callback = mpFactory->mCallback;
310  if (callback)
311  GuardedCall( [&]{ callback( *this ); } );
312  }
313 
314  if (IsSilent()) {
315  // The block object was constructed but failed to Load() or Commit().
316  // Or it's a silent block with no row in the database.
317  // Just let the stack unwind. Don't violate the assertion in
318  // Delete(), which may do odd recursive things in debug builds when it
319  // yields to the UI to put up a dialog, but then dispatches timer
320  // events that try again to finish recording.
321  return;
322  }
323 
324  // See ProjectFileIO::Bypass() for a description of mIO.mBypass
325  GuardedCall( [this]{
326  if (!mLocked && !Conn()->ShouldBypass())
327  {
328  // In case Delete throws, don't let an exception escape a destructor,
329  // but we can still enqueue the delayed handler so that an error message
330  // is presented to the user.
331  // The failure in this case may be a less harmful waste of space in the
332  // database, which should not cause aborting of the attempted edit.
333  Delete();
334  }
335  } );
336 }

References Conn(), Delete(), GuardedCall(), IsSilent(), mLocked, and mpFactory.

Here is the call graph for this function:

Member Function Documentation

◆ CalcSummary()

void SqliteSampleBlock::CalcSummary ( Sizes  sizes)
private

Calculates summary block data describing this sample data.

This method also has the side effect of setting the mSumMin, mSumMax, and mSumRms members of this class.

Definition at line 866 of file SqliteSampleBlock.cpp.

867 {
868  const auto mSummary256Bytes = sizes.first;
869  const auto mSummary64kBytes = sizes.second;
870 
871  Floats samplebuffer;
872  float *samples;
873 
874  if (mSampleFormat == floatSample)
875  {
876  samples = (float *) mSamples.get();
877  }
878  else
879  {
880  samplebuffer.reinit((unsigned) mSampleCount);
882  samplebuffer.get(), mSampleCount);
883  samples = samplebuffer.get();
884  }
885 
886  mSummary256.reinit(mSummary256Bytes);
887  mSummary64k.reinit(mSummary64kBytes);
888 
889  float *summary256 = (float *) mSummary256.get();
890  float *summary64k = (float *) mSummary64k.get();
891 
892  float min;
893  float max;
894  float sumsq;
895  double totalSquares = 0.0;
896  double fraction = 0.0;
897 
898  // Recalc 256 summaries
899  int sumLen = (mSampleCount + 255) / 256;
900  int summaries = 256;
901 
902  for (int i = 0; i < sumLen; ++i)
903  {
904  min = samples[i * 256];
905  max = samples[i * 256];
906  sumsq = min * min;
907 
908  int jcount = 256;
909  if (jcount > mSampleCount - i * 256)
910  {
911  jcount = mSampleCount - i * 256;
912  fraction = 1.0 - (jcount / 256.0);
913  }
914 
915  for (int j = 1; j < jcount; ++j)
916  {
917  float f1 = samples[i * 256 + j];
918  sumsq += f1 * f1;
919 
920  if (f1 < min)
921  {
922  min = f1;
923  }
924  else if (f1 > max)
925  {
926  max = f1;
927  }
928  }
929 
930  totalSquares += sumsq;
931 
932  summary256[i * fields] = min;
933  summary256[i * fields + 1] = max;
934  // The rms is correct, but this may be for less than 256 samples in last loop.
935  summary256[i * fields + 2] = (float) sqrt(sumsq / jcount);
936  }
937 
938  for (int i = sumLen, frames256 = mSummary256Bytes / bytesPerFrame;
939  i < frames256; ++i)
940  {
941  // filling in the remaining bits with non-harming/contributing values
942  // rms values are not "non-harming", so keep count of them:
943  summaries--;
944  summary256[i * fields] = FLT_MAX; // min
945  summary256[i * fields + 1] = -FLT_MAX; // max
946  summary256[i * fields + 2] = 0.0f; // rms
947  }
948 
949  // Calculate now while we can do it accurately
950  mSumRms = sqrt(totalSquares / mSampleCount);
951 
952  // Recalc 64K summaries
953  sumLen = (mSampleCount + 65535) / 65536;
954 
955  for (int i = 0; i < sumLen; ++i)
956  {
957  min = summary256[3 * i * 256];
958  max = summary256[3 * i * 256 + 1];
959  sumsq = summary256[3 * i * 256 + 2];
960  sumsq *= sumsq;
961 
962  for (int j = 1; j < 256; ++j)
963  {
964  // we can overflow the useful summary256 values here, but have put
965  // non-harmful values in them
966  if (summary256[3 * (i * 256 + j)] < min)
967  {
968  min = summary256[3 * (i * 256 + j)];
969  }
970 
971  if (summary256[3 * (i * 256 + j) + 1] > max)
972  {
973  max = summary256[3 * (i * 256 + j) + 1];
974  }
975 
976  float r1 = summary256[3 * (i * 256 + j) + 2];
977  sumsq += r1 * r1;
978  }
979 
980  double denom = (i < sumLen - 1) ? 256.0 : summaries - fraction;
981  float rms = (float) sqrt(sumsq / denom);
982 
983  summary64k[i * fields] = min;
984  summary64k[i * fields + 1] = max;
985  summary64k[i * fields + 2] = rms;
986  }
987 
988  for (int i = sumLen, frames64k = mSummary64kBytes / bytesPerFrame;
989  i < frames64k; ++i)
990  {
991  wxASSERT_MSG(false, wxT("Out of data for mSummaryInfo")); // Do we ever get here?
992 
993  summary64k[i * fields] = 0.0f; // probably should be FLT_MAX, need a test case
994  summary64k[i * fields + 1] = 0.0f; // probably should be -FLT_MAX, need a test case
995  summary64k[i * fields + 2] = 0.0f; // just padding
996  }
997 
998  // Recalc block-level summary (mRMS already calculated)
999  min = summary64k[0];
1000  max = summary64k[1];
1001 
1002  for (int i = 1; i < sumLen; ++i)
1003  {
1004  if (summary64k[i * fields] < min)
1005  {
1006  min = summary64k[i * fields];
1007  }
1008 
1009  if (summary64k[i * fields + 1] > max)
1010  {
1011  max = summary64k[i * fields + 1];
1012  }
1013  }
1014 
1015  mSumMin = min;
1016  mSumMax = max;
1017 }

References bytesPerFrame, fields, floatSample, min(), mSampleCount, mSampleFormat, mSamples, mSummary256, mSummary64k, mSumMax, mSumMin, mSumRms, ArrayOf< X >::reinit(), and SamplesToFloats().

Referenced by SetSamples().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CloseLock()

void SqliteSampleBlock::CloseLock ( )
overridevirtual

Implements SampleBlock.

Definition at line 356 of file SqliteSampleBlock.cpp.

357 {
358  mLocked = true;
359 }

References mLocked.

◆ Commit()

void SqliteSampleBlock::Commit ( Sizes  sizes)

Definition at line 731 of file SqliteSampleBlock.cpp.

732 {
733  const auto mSummary256Bytes = sizes.first;
734  const auto mSummary64kBytes = sizes.second;
735 
736  auto db = DB();
737  int rc;
738 
739  // Prepare and cache statement...automatically finalized at DB close
740  sqlite3_stmt *stmt = Conn()->Prepare(DBConnection::InsertSampleBlock,
741  "INSERT INTO sampleblocks (sampleformat, summin, summax, sumrms,"
742  " summary256, summary64k, samples)"
743  " VALUES(?1,?2,?3,?4,?5,?6,?7);");
744 
745  // Bind statement parameters
746  // Might return SQLITE_MISUSE which means it's our mistake that we violated
747  // preconditions; should return SQL_OK which is 0
748  if (sqlite3_bind_int(stmt, 1, mSampleFormat) ||
749  sqlite3_bind_double(stmt, 2, mSumMin) ||
750  sqlite3_bind_double(stmt, 3, mSumMax) ||
751  sqlite3_bind_double(stmt, 4, mSumRms) ||
752  sqlite3_bind_blob(stmt, 5, mSummary256.get(), mSummary256Bytes, SQLITE_STATIC) ||
753  sqlite3_bind_blob(stmt, 6, mSummary64k.get(), mSummary64kBytes, SQLITE_STATIC) ||
754  sqlite3_bind_blob(stmt, 7, mSamples.get(), mSampleBytes, SQLITE_STATIC))
755  {
756 
758  "sqlite3.rc", std::to_string(sqlite3_errcode(Conn()->DB())));
759  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Commit::bind");
760 
761 
762  wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
763  }
764 
765  // Execute the statement
766  rc = sqlite3_step(stmt);
767  if (rc != SQLITE_DONE)
768  {
769  ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
770  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Commit::step");
771 
772  wxLogDebug(wxT("SqliteSampleBlock::Commit - SQLITE error %s"), sqlite3_errmsg(db));
773 
774  // Clear statement bindings and rewind statement
775  sqlite3_clear_bindings(stmt);
776  sqlite3_reset(stmt);
777 
778  // Just showing the user a simple message, not the library error too
779  // which isn't internationalized
780  Conn()->ThrowException( true );
781  }
782 
783  // Retrieve returned data
784  mBlockID = sqlite3_last_insert_rowid(db);
785 
786  // Reset local arrays
787  mSamples.reset();
788  mSummary256.reset();
789  mSummary64k.reset();
790 
791  // Clear statement bindings and rewind statement
792  sqlite3_clear_bindings(stmt);
793  sqlite3_reset(stmt);
794 
795  mValid = true;
796 }

References ADD_EXCEPTION_CONTEXT, Conn(), DB(), DBConnection::InsertSampleBlock, mBlockID, mSampleBytes, mSampleFormat, mSamples, mSummary256, mSummary64k, mSumMax, mSumMin, mSumRms, mValid, DBConnection::Prepare(), and DBConnection::ThrowException().

Referenced by SetSamples().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Conn()

DBConnection * SqliteSampleBlock::Conn ( ) const
private

This must never be called for silent blocks.

Postcondition
return value is not null

Definition at line 338 of file SqliteSampleBlock.cpp.

339 {
340  if (!mpFactory)
341  return nullptr;
342 
343  auto &pConnection = mpFactory->mppConnection->mpConnection;
344  if (!pConnection) {
346  {
348  XO("Connection to project file is null"),
349  XO("Warning"),
350  "Error:_Disk_full_or_not_writable"
351  };
352  }
353  return pConnection.get();
354 }

References Internal, mpFactory, and XO.

Referenced by Commit(), DB(), Delete(), DoGetSamples(), GetBlob(), GetSpaceUsage(), GetSummary(), Load(), and ~SqliteSampleBlock().

Here is the caller graph for this function:

◆ DB()

sqlite3* SqliteSampleBlock::DB ( ) const
inlineprivate

Definition at line 96 of file SqliteSampleBlock.cpp.

97  {
98  return Conn()->DB();
99  }

References Conn(), and DBConnection::DB().

Referenced by Commit(), Delete(), GetBlob(), and Load().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Delete()

void SqliteSampleBlock::Delete ( )

Definition at line 798 of file SqliteSampleBlock.cpp.

799 {
800  auto db = DB();
801  int rc;
802 
803  wxASSERT(!IsSilent());
804 
805  // Prepare and cache statement...automatically finalized at DB close
806  sqlite3_stmt *stmt = Conn()->Prepare(DBConnection::DeleteSampleBlock,
807  "DELETE FROM sampleblocks WHERE blockid = ?1;");
808 
809  // Bind statement parameters
810  // Might return SQLITE_MISUSE which means it's our mistake that we violated
811  // preconditions; should return SQL_OK which is 0
812  if (sqlite3_bind_int64(stmt, 1, mBlockID))
813  {
815  "sqlite3.rc", std::to_string(sqlite3_errcode(Conn()->DB())));
816  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Delete::bind");
817 
818  wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
819  }
820 
821  // Execute the statement
822  rc = sqlite3_step(stmt);
823  if (rc != SQLITE_DONE)
824  {
825  ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
826  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Delete::step");
827 
828  wxLogDebug(wxT("SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
829 
830  // Clear statement bindings and rewind statement
831  sqlite3_clear_bindings(stmt);
832  sqlite3_reset(stmt);
833 
834  // Just showing the user a simple message, not the library error too
835  // which isn't internationalized
836  Conn()->ThrowException( true );
837  }
838 
839  // Clear statement bindings and rewind statement
840  sqlite3_clear_bindings(stmt);
841  sqlite3_reset(stmt);
842 }

References ADD_EXCEPTION_CONTEXT, Conn(), DB(), DBConnection::DeleteSampleBlock, IsSilent(), mBlockID, DBConnection::Prepare(), and DBConnection::ThrowException().

Referenced by ~SqliteSampleBlock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DoGetMinMaxRMS() [1/2]

MinMaxRMS SqliteSampleBlock::DoGetMinMaxRMS ( ) const
overridevirtual

Gets extreme values for the entire block.

Retrieves the minimum, maximum, and maximum RMS of this entire block. This is faster than the other GetMinMax function since these values are already computed.

Implements SampleBlock.

Definition at line 526 of file SqliteSampleBlock.cpp.

527 {
528  return { (float) mSumMin, (float) mSumMax, (float) mSumRms };
529 }

References mSumMax, mSumMin, and mSumRms.

◆ DoGetMinMaxRMS() [2/2]

MinMaxRMS SqliteSampleBlock::DoGetMinMaxRMS ( size_t  start,
size_t  len 
)
overridevirtual

Gets extreme values for the specified region.

Retrieves the minimum, maximum, and maximum RMS of the specified sample data in this block.

Parameters
startThe offset in this block where the region should begin
lenThe number of samples to include in the region

Implements SampleBlock.

Definition at line 479 of file SqliteSampleBlock.cpp.

480 {
481  if (IsSilent())
482  return {};
483 
484  float min = FLT_MAX;
485  float max = -FLT_MAX;
486  float sumsq = 0;
487 
488  if (!mValid)
489  {
490  Load(mBlockID);
491  }
492 
493  if (start < mSampleCount)
494  {
495  len = std::min(len, mSampleCount - start);
496 
497  // TODO: actually use summaries
498  SampleBuffer blockData(len, floatSample);
499  float *samples = (float *) blockData.ptr();
500 
501  size_t copied = DoGetSamples((samplePtr) samples, floatSample, start, len);
502  for (size_t i = 0; i < copied; ++i, ++samples)
503  {
504  float sample = *samples;
505 
506  if (sample > max)
507  {
508  max = sample;
509  }
510 
511  if (sample < min)
512  {
513  min = sample;
514  }
515 
516  sumsq += (sample * sample);
517  }
518  }
519 
520  return { min, max, (float) sqrt(sumsq / len) };
521 }

References DoGetSamples(), floatSample, IsSilent(), Load(), mBlockID, min(), mSampleCount, mValid, and SampleBuffer::ptr().

Here is the call graph for this function:

◆ DoGetSamples()

size_t SqliteSampleBlock::DoGetSamples ( samplePtr  dest,
sampleFormat  destformat,
size_t  sampleoffset,
size_t  numsamples 
)
overridevirtual

Implements SampleBlock.

Definition at line 376 of file SqliteSampleBlock.cpp.

380 {
381  if (IsSilent()) {
382  auto size = SAMPLE_SIZE(destformat);
383  memset(dest, 0, numsamples * size);
384  return numsamples;
385  }
386 
387  // Prepare and cache statement...automatically finalized at DB close
388  sqlite3_stmt *stmt = Conn()->Prepare(DBConnection::GetSamples,
389  "SELECT samples FROM sampleblocks WHERE blockid = ?1;");
390 
391  return GetBlob(dest,
392  destformat,
393  stmt,
395  sampleoffset * SAMPLE_SIZE(mSampleFormat),
397 }

References Conn(), GetBlob(), DBConnection::GetSamples, IsSilent(), mSampleFormat, DBConnection::Prepare(), SAMPLE_SIZE, and size.

Referenced by DoGetMinMaxRMS().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetBlob()

size_t SqliteSampleBlock::GetBlob ( void *  dest,
sampleFormat  destformat,
sqlite3_stmt *  stmt,
sampleFormat  srcformat,
size_t  srcoffset,
size_t  srcbytes 
)
private

Definition at line 539 of file SqliteSampleBlock.cpp.

545 {
546  auto db = DB();
547 
548  wxASSERT(!IsSilent());
549 
550  if (!mValid)
551  {
552  Load(mBlockID);
553  }
554 
555  int rc;
556  size_t minbytes = 0;
557 
558  // Bind statement parameters
559  // Might return SQLITE_MISUSE which means it's our mistake that we violated
560  // preconditions; should return SQL_OK which is 0
561  if (sqlite3_bind_int64(stmt, 1, mBlockID))
562  {
564  "sqlite3.rc", std::to_string(sqlite3_errcode(Conn()->DB())));
565  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::GetBlob::bind");
566 
567  wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
568  }
569 
570  // Execute the statement
571  rc = sqlite3_step(stmt);
572  if (rc != SQLITE_ROW)
573  {
574  ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
575  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::GetBlob::step");
576 
577  wxLogDebug(wxT("SqliteSampleBlock::GetBlob - SQLITE error %s"), sqlite3_errmsg(db));
578 
579  // Clear statement bindings and rewind statement
580  sqlite3_clear_bindings(stmt);
581  sqlite3_reset(stmt);
582 
583  // Just showing the user a simple message, not the library error too
584  // which isn't internationalized
585  // Actually this can lead to 'Could not read from file' error message
586  // but it can also lead to no error message at all and a flat line,
587  // depending on where GetBlob is called from.
588  // The latter can happen when repainting the screen.
589  // That possibly happens on a very slow machine. Possibly that's the
590  // right trade off when a machine can't keep up?
591  // ANSWER-ME: Do we always report an error when we should here?
592  Conn()->ThrowException( false );
593  }
594 
595  // Retrieve returned data
596  samplePtr src = (samplePtr) sqlite3_column_blob(stmt, 0);
597  size_t blobbytes = (size_t) sqlite3_column_bytes(stmt, 0);
598 
599  srcoffset = std::min(srcoffset, blobbytes);
600  minbytes = std::min(srcbytes, blobbytes - srcoffset);
601 
602  if (srcoffset != 0)
603  {
604  srcoffset += 0;
605  }
606 
607  /*
608  Will dithering happen in CopySamples? Answering this as of 3.0.3 by
609  examining all uses.
610 
611  As this function is called from GetSummary, no, because destination format
612  is float.
613 
614  There is only one other call to this function, in DoGetSamples. At one
615  call to that function, in DoGetMinMaxRMS, again format is float always.
616 
617  There is only one other call to DoGetSamples, in SampleBlock::GetSamples().
618  In one call to that function, in WaveformView.cpp, again format is float.
619 
620  That leaves two calls in Sequence.cpp. One of those can be proved to be
621  used only in copy and paste operations, always supplying the same sample
622  format as the samples were stored in, therefore no dither.
623 
624  That leaves uses of Sequence::Read(). There are uses of Read() in internal
625  operations also easily shown to use only the saved format, and
626  GetWaveDisplay() always reads as float.
627 
628  The remaining use of Sequence::Read() is in Sequence::Get(). That is used
629  by WaveClip::Resample(), always fetching float. It is also used in
630  WaveClip::GetSamples().
631 
632  There is only one use of that function not always fetching float, in
633  WaveTrack::Get().
634 
635  It can be shown that the only paths to WaveTrack::Get() not specifying
636  floatSample are in Benchmark, which is only a diagnostic test, and there
637  the sample format is the same as what the track was constructed with.
638 
639  Therefore, no dithering even there!
640  */
641  wxASSERT(destformat == floatSample || destformat == srcformat);
642 
643  CopySamples(src + srcoffset,
644  srcformat,
645  (samplePtr) dest,
646  destformat,
647  minbytes / SAMPLE_SIZE(srcformat));
648 
649  dest = ((samplePtr) dest) + minbytes;
650 
651  if (srcbytes - minbytes)
652  {
653  memset(dest, 0, srcbytes - minbytes);
654  }
655 
656  // Clear statement bindings and rewind statement
657  sqlite3_clear_bindings(stmt);
658  sqlite3_reset(stmt);
659 
660  return srcbytes;
661 }

References ADD_EXCEPTION_CONTEXT, Conn(), CopySamples(), DB(), floatSample, IsSilent(), Load(), mBlockID, min(), mValid, SAMPLE_SIZE, and DBConnection::ThrowException().

Referenced by DoGetSamples(), and GetSummary().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetBlockID()

SampleBlockID SqliteSampleBlock::GetBlockID ( ) const
overridevirtual

Implements SampleBlock.

Definition at line 361 of file SqliteSampleBlock.cpp.

362 {
363  return mBlockID;
364 }

References mBlockID.

◆ GetSampleCount()

size_t SqliteSampleBlock::GetSampleCount ( ) const
overridevirtual

Implements SampleBlock.

Definition at line 371 of file SqliteSampleBlock.cpp.

372 {
373  return mSampleCount;
374 }

References mSampleCount.

◆ GetSampleFormat()

sampleFormat SqliteSampleBlock::GetSampleFormat ( ) const

Definition at line 366 of file SqliteSampleBlock.cpp.

367 {
368  return mSampleFormat;
369 }

References mSampleFormat.

◆ GetSpaceUsage()

size_t SqliteSampleBlock::GetSpaceUsage ( ) const
overridevirtual

Implements SampleBlock.

Definition at line 531 of file SqliteSampleBlock.cpp.

532 {
533  if (IsSilent())
534  return 0;
535  else
537 }

References Conn(), ProjectFileIO::GetDiskUsage(), IsSilent(), and mBlockID.

Here is the call graph for this function:

◆ GetSummary()

bool SqliteSampleBlock::GetSummary ( float *  dest,
size_t  frameoffset,
size_t  numframes,
DBConnection::StatementID  id,
const char *  sql 
)
private

Definition at line 428 of file SqliteSampleBlock.cpp.

433 {
434  // Non-throwing, it returns true for success
435  bool silent = IsSilent();
436  if (!silent) {
437  // Not a silent block
438  try {
439  // Prepare and cache statement...automatically finalized at DB close
440  auto stmt = Conn()->Prepare(id, sql);
441  // Note GetBlob returns a size_t, not a bool
442  // REVIEW: An error in GetBlob() will throw an exception.
443  GetBlob(dest,
444  floatSample,
445  stmt,
446  floatSample,
447  frameoffset * fields * SAMPLE_SIZE(floatSample),
448  numframes * fields * SAMPLE_SIZE(floatSample));
449  return true;
450  }
451  catch ( const AudacityException & ) {
452  }
453  }
454  memset(dest, 0, 3 * numframes * sizeof( float ));
455  // Return true for success only if we didn't catch
456  return silent;
457 }

References Conn(), fields, floatSample, GetBlob(), IsSilent(), DBConnection::Prepare(), and SAMPLE_SIZE.

Referenced by GetSummary256(), and GetSummary64k().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSummary256()

bool SqliteSampleBlock::GetSummary256 ( float *  dest,
size_t  frameoffset,
size_t  numframes 
)
overridevirtual

Non-throwing, should fill with zeroes on failure.

Implements SampleBlock.

Definition at line 412 of file SqliteSampleBlock.cpp.

415 {
416  return GetSummary(dest, frameoffset, numframes, DBConnection::GetSummary256,
417  "SELECT summary256 FROM sampleblocks WHERE blockid = ?1;");
418 }

References GetSummary(), and DBConnection::GetSummary256.

Here is the call graph for this function:

◆ GetSummary64k()

bool SqliteSampleBlock::GetSummary64k ( float *  dest,
size_t  frameoffset,
size_t  numframes 
)
overridevirtual

Non-throwing, should fill with zeroes on failure.

Implements SampleBlock.

Definition at line 420 of file SqliteSampleBlock.cpp.

423 {
424  return GetSummary(dest, frameoffset, numframes, DBConnection::GetSummary64k,
425  "SELECT summary64k FROM sampleblocks WHERE blockid = ?1;");
426 }

References GetSummary(), and DBConnection::GetSummary64k.

Here is the call graph for this function:

◆ GetSumMax()

double SqliteSampleBlock::GetSumMax ( ) const

Definition at line 464 of file SqliteSampleBlock.cpp.

465 {
466  return mSumMax;
467 }

References mSumMax.

◆ GetSumMin()

double SqliteSampleBlock::GetSumMin ( ) const

Definition at line 459 of file SqliteSampleBlock.cpp.

460 {
461  return mSumMin;
462 }

References mSumMin.

◆ GetSumRms()

double SqliteSampleBlock::GetSumRms ( ) const

Definition at line 469 of file SqliteSampleBlock.cpp.

470 {
471  return mSumRms;
472 }

References mSumRms.

◆ IsSilent()

bool SqliteSampleBlock::IsSilent ( ) const
inlineprivate

Definition at line 71 of file SqliteSampleBlock.cpp.

71 { return mBlockID <= 0; }

References mBlockID.

Referenced by Delete(), DoGetMinMaxRMS(), DoGetSamples(), GetBlob(), GetSpaceUsage(), GetSummary(), and ~SqliteSampleBlock().

Here is the caller graph for this function:

◆ Load()

void SqliteSampleBlock::Load ( SampleBlockID  sbid)
private

Definition at line 663 of file SqliteSampleBlock.cpp.

664 {
665  auto db = DB();
666  int rc;
667 
668  wxASSERT(sbid > 0);
669 
670  mValid = false;
671  mSampleCount = 0;
672  mSampleBytes = 0;
673  mSumMin = FLT_MAX;
674  mSumMax = -FLT_MAX;
675  mSumMin = 0.0;
676 
677  // Prepare and cache statement...automatically finalized at DB close
678  sqlite3_stmt *stmt = Conn()->Prepare(DBConnection::LoadSampleBlock,
679  "SELECT sampleformat, summin, summax, sumrms,"
680  " length(samples)"
681  " FROM sampleblocks WHERE blockid = ?1;");
682 
683  // Bind statement parameters
684  // Might return SQLITE_MISUSE which means it's our mistake that we violated
685  // preconditions; should return SQL_OK which is 0
686  if (sqlite3_bind_int64(stmt, 1, sbid))
687  {
688 
689  ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(sqlite3_errcode(Conn()->DB())));
690  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Load::bind");
691 
692  wxASSERT_MSG(false, wxT("Binding failed...bug!!!"));
693  }
694 
695  // Execute the statement
696  rc = sqlite3_step(stmt);
697  if (rc != SQLITE_ROW)
698  {
699 
700  ADD_EXCEPTION_CONTEXT("sqlite3.rc", std::to_string(rc));
701  ADD_EXCEPTION_CONTEXT("sqlite3.context", "SqliteSampleBlock::Load::step");
702 
703 
704  wxLogDebug(wxT("SqliteSampleBlock::Load - SQLITE error %s"), sqlite3_errmsg(db));
705 
706  // Clear statement bindings and rewind statement
707  sqlite3_clear_bindings(stmt);
708  sqlite3_reset(stmt);
709 
710  // Just showing the user a simple message, not the library error too
711  // which isn't internationalized
712  Conn()->ThrowException( false );
713  }
714 
715  // Retrieve returned data
716  mBlockID = sbid;
717  mSampleFormat = (sampleFormat) sqlite3_column_int(stmt, 0);
718  mSumMin = sqlite3_column_double(stmt, 1);
719  mSumMax = sqlite3_column_double(stmt, 2);
720  mSumRms = sqlite3_column_double(stmt, 3);
721  mSampleBytes = sqlite3_column_int(stmt, 4);
723 
724  // Clear statement bindings and rewind statement
725  sqlite3_clear_bindings(stmt);
726  sqlite3_reset(stmt);
727 
728  mValid = true;
729 }

References ADD_EXCEPTION_CONTEXT, Conn(), DB(), DBConnection::LoadSampleBlock, mBlockID, mSampleBytes, mSampleCount, mSampleFormat, mSumMax, mSumMin, mSumRms, mValid, DBConnection::Prepare(), SAMPLE_SIZE, and DBConnection::ThrowException().

Referenced by DoGetMinMaxRMS(), and GetBlob().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SaveXML()

void SqliteSampleBlock::SaveXML ( XMLWriter xmlFile)
overridevirtual

Implements SampleBlock.

Definition at line 844 of file SqliteSampleBlock.cpp.

845 {
846  xmlFile.WriteAttr(wxT("blockid"), mBlockID);
847 }

References mBlockID, and XMLWriter::WriteAttr().

Here is the call graph for this function:

◆ SetSamples()

void SqliteSampleBlock::SetSamples ( constSamplePtr  src,
size_t  numsamples,
sampleFormat  srcformat 
)

Definition at line 399 of file SqliteSampleBlock.cpp.

402 {
403  auto sizes = SetSizes(numsamples, srcformat);
405  memcpy(mSamples.get(), src, mSampleBytes);
406 
407  CalcSummary( sizes );
408 
409  Commit( sizes );
410 }

References CalcSummary(), Commit(), mSampleBytes, mSamples, ArrayOf< X >::reinit(), and SetSizes().

Here is the call graph for this function:

◆ SetSizes()

auto SqliteSampleBlock::SetSizes ( size_t  numsamples,
sampleFormat  srcformat 
)
private

Definition at line 849 of file SqliteSampleBlock.cpp.

851 {
852  mSampleFormat = srcformat;
853  mSampleCount = numsamples;
855 
856  int frames64k = (mSampleCount + 65535) / 65536;
857  int frames256 = frames64k * 256;
858  return { frames256 * bytesPerFrame, frames64k * bytesPerFrame };
859 }

References SAMPLE_SIZE.

Referenced by SetSamples().

Here is the caller graph for this function:

Member Data Documentation

◆ mBlockID

SampleBlockID SqliteSampleBlock::mBlockID { 0 }
private

◆ mLocked

bool SqliteSampleBlock::mLocked = false
private

Definition at line 105 of file SqliteSampleBlock.cpp.

Referenced by CloseLock(), and ~SqliteSampleBlock().

◆ mpFactory

const std::shared_ptr<SqliteSampleBlockFactory> SqliteSampleBlock::mpFactory
private

Definition at line 103 of file SqliteSampleBlock.cpp.

Referenced by Conn(), and ~SqliteSampleBlock().

◆ mSampleBytes

size_t SqliteSampleBlock::mSampleBytes
private

Definition at line 110 of file SqliteSampleBlock.cpp.

Referenced by Commit(), Load(), SetSamples(), and SqliteSampleBlock().

◆ mSampleCount

size_t SqliteSampleBlock::mSampleCount
private

◆ mSampleFormat

sampleFormat SqliteSampleBlock::mSampleFormat
private

◆ mSamples

ArrayOf<char> SqliteSampleBlock::mSamples
private

Definition at line 109 of file SqliteSampleBlock.cpp.

Referenced by CalcSummary(), Commit(), and SetSamples().

◆ mSummary256

ArrayOf<char> SqliteSampleBlock::mSummary256
private

Definition at line 114 of file SqliteSampleBlock.cpp.

Referenced by CalcSummary(), and Commit().

◆ mSummary64k

ArrayOf<char> SqliteSampleBlock::mSummary64k
private

Definition at line 115 of file SqliteSampleBlock.cpp.

Referenced by CalcSummary(), and Commit().

◆ mSumMax

double SqliteSampleBlock::mSumMax
private

◆ mSumMin

double SqliteSampleBlock::mSumMin
private

◆ mSumRms

double SqliteSampleBlock::mSumRms
private

◆ mValid

bool SqliteSampleBlock::mValid { false }
private

Definition at line 104 of file SqliteSampleBlock.cpp.

Referenced by Commit(), DoGetMinMaxRMS(), GetBlob(), and Load().

◆ SqliteSampleBlockFactory

friend SqliteSampleBlock::SqliteSampleBlockFactory
private

Definition at line 101 of file SqliteSampleBlock.cpp.


The documentation for this class was generated from the following file:
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
DBConnection::DeleteSampleBlock
@ DeleteSampleBlock
Definition: DBConnection.h:79
SqliteSampleBlock::Conn
DBConnection * Conn() const
This must never be called for silent blocks.
Definition: SqliteSampleBlock.cpp:338
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), std::function< void(AudacityException *)> delayedHandler=DefaultDelayedHandlerAction{})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:202
SqliteSampleBlock::mSampleBytes
size_t mSampleBytes
Definition: SqliteSampleBlock.cpp:110
SqliteSampleBlock::mSampleFormat
sampleFormat mSampleFormat
Definition: SqliteSampleBlock.cpp:112
SqliteSampleBlock::mSamples
ArrayOf< char > mSamples
Definition: SqliteSampleBlock.cpp:109
SqliteSampleBlock::mBlockID
SampleBlockID mBlockID
Definition: SqliteSampleBlock.cpp:107
SqliteSampleBlock::Delete
void Delete()
Definition: SqliteSampleBlock.cpp:798
SqliteSampleBlock::mpFactory
const std::shared_ptr< SqliteSampleBlockFactory > mpFactory
Definition: SqliteSampleBlock.cpp:103
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
SqliteSampleBlock::SetSizes
Sizes SetSizes(size_t numsamples, sampleFormat srcformat)
Definition: SqliteSampleBlock.cpp:849
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
XO
#define XO(s)
Definition: Internat.h:31
SamplesToFloats
void SamplesToFloats(constSamplePtr src, sampleFormat srcFormat, float *dst, size_t len, size_t srcStride, size_t dstStride)
Copy samples from any format into the widest format, which is 32 bit float, with no dithering.
Definition: SampleFormat.cpp:102
DBConnection::GetSamples
@ GetSamples
Definition: DBConnection.h:74
SqliteSampleBlock::mSumMax
double mSumMax
Definition: SqliteSampleBlock.cpp:117
DBConnection::DB
sqlite3 * DB()
Definition: DBConnection.cpp:410
floatSample
@ floatSample
Definition: SampleFormat.h:34
SqliteSampleBlock::mValid
bool mValid
Definition: SqliteSampleBlock.cpp:104
SqliteSampleBlock::GetBlob
size_t GetBlob(void *dest, sampleFormat destformat, sqlite3_stmt *stmt, sampleFormat srcformat, size_t srcoffset, size_t srcbytes)
Definition: SqliteSampleBlock.cpp:539
AudacityException
Base class for exceptions specially processed by the application.
Definition: AudacityException.h:33
SqliteSampleBlock::fields
@ fields
Definition: SqliteSampleBlock.cpp:86
SqliteSampleBlock::mLocked
bool mLocked
Definition: SqliteSampleBlock.cpp:105
CopySamples
void CopySamples(constSamplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, size_t len, DitherType ditherType, unsigned int srcStride, unsigned int dstStride)
Copy samples from any format to any other format; apply dithering only if narrowing the format.
Definition: SampleFormat.cpp:111
SqliteSampleBlock::DB
sqlite3 * DB() const
Definition: SqliteSampleBlock.cpp:96
SqliteSampleBlock::DoGetSamples
size_t DoGetSamples(samplePtr dest, sampleFormat destformat, size_t sampleoffset, size_t numsamples) override
Definition: SqliteSampleBlock.cpp:376
SqliteSampleBlock::mSumMin
double mSumMin
Definition: SqliteSampleBlock.cpp:116
DBConnection::ThrowException
void ThrowException(bool write) const
throw and show appropriate message box
Definition: DBConnection.cpp:340
SqliteSampleBlock::IsSilent
bool IsSilent() const
Definition: SqliteSampleBlock.cpp:71
SampleBuffer
Definition: SampleFormat.h:69
sampleFormat
sampleFormat
Definition: SampleFormat.h:29
SqliteSampleBlock::GetSummary
bool GetSummary(float *dest, size_t frameoffset, size_t numframes, DBConnection::StatementID id, const char *sql)
Definition: SqliteSampleBlock.cpp:428
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
SqliteSampleBlock::Commit
void Commit(Sizes sizes)
Definition: SqliteSampleBlock.cpp:731
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
DBConnection::GetSummary256
@ GetSummary256
Definition: DBConnection.h:75
SqliteSampleBlock::mSummary64k
ArrayOf< char > mSummary64k
Definition: SqliteSampleBlock.cpp:115
DBConnection::GetSummary64k
@ GetSummary64k
Definition: DBConnection.h:76
SqliteSampleBlock::CalcSummary
void CalcSummary(Sizes sizes)
Definition: SqliteSampleBlock.cpp:866
DBConnection::InsertSampleBlock
@ InsertSampleBlock
Definition: DBConnection.h:78
SqliteSampleBlock::mSummary256
ArrayOf< char > mSummary256
Definition: SqliteSampleBlock.cpp:114
SqliteSampleBlock::bytesPerFrame
@ bytesPerFrame
Definition: SqliteSampleBlock.cpp:87
DBConnection::LoadSampleBlock
@ LoadSampleBlock
Definition: DBConnection.h:77
XMLWriter::WriteAttr
void WriteAttr(const wxString &name, const Identifier &value)
Definition: XMLWriter.h:34
ExceptionType::Internal
@ Internal
Indicates internal failure from Audacity.
SqliteSampleBlock::Load
void Load(SampleBlockID sbid)
Definition: SqliteSampleBlock.cpp:663
ProjectFileIO::GetDiskUsage
static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid)
Definition: ProjectFileIO.cpp:2372
ADD_EXCEPTION_CONTEXT
#define ADD_EXCEPTION_CONTEXT(name, value)
Definition: SentryHelper.h:21
SimpleMessageBoxException
A MessageBoxException that shows a given, unvarying string.
Definition: AudacityException.h:95
SqliteSampleBlock::mSumRms
double mSumRms
Definition: SqliteSampleBlock.cpp:118
DBConnection::Prepare
sqlite3_stmt * Prepare(enum StatementID id, const char *sql)
Definition: DBConnection.cpp:427
ArrayOf< float >
SqliteSampleBlock::mSampleCount
size_t mSampleCount
Definition: SqliteSampleBlock.cpp:111