Audacity  2.2.2
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes | List of all members
Sequence Class Referencefinal

A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interface to an array of SeqBlock instances, corresponding to the audio BlockFiles on disk. Contrast with RingBuffer. More...

#include <Sequence.h>

Inheritance diagram for Sequence:
XMLTagHandler

Classes

struct  DeleteUpdateMutexLocker
 

Public Member Functions

 Sequence (const std::shared_ptr< DirManager > &projDirManager, sampleFormat format)
 
 Sequence (const Sequence &orig, const std::shared_ptr< DirManager > &projDirManager)
 
 Sequence (const Sequence &) PROHIBITED
 
Sequenceoperator= (const Sequence &) PROHIBITED
 
 ~Sequence ()
 
sampleCount GetNumSamples () const
 
bool Get (samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
 
void SetSamples (samplePtr buffer, sampleFormat format, sampleCount start, sampleCount len)
 
bool GetWaveDisplay (float *min, float *max, float *rms, int *bl, size_t len, const sampleCount *where) const
 
std::unique_ptr< SequenceCopy (sampleCount s0, sampleCount s1) const
 
void Paste (sampleCount s0, const Sequence *src)
 
size_t GetIdealAppendLen () const
 
void Append (samplePtr buffer, sampleFormat format, size_t len, XMLWriter *blockFileLog=NULL)
 
void Delete (sampleCount start, sampleCount len)
 
void AppendAlias (const wxString &fullPath, sampleCount start, size_t len, int channel, bool useOD)
 
void AppendCoded (const wxString &fName, sampleCount start, size_t len, int channel, int decodeType)
 
unsigned int GetODFlags ()
 gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc. More...
 
void AppendBlockFile (const BlockFilePtr &blockFile)
 
void SetSilence (sampleCount s0, sampleCount len)
 
void InsertSilence (sampleCount s0, sampleCount len)
 
const std::shared_ptr
< DirManager > & 
GetDirManager ()
 
bool HandleXMLTag (const wxChar *tag, const wxChar **attrs) override
 
void HandleXMLEndTag (const wxChar *tag) override
 
XMLTagHandlerHandleXMLChild (const wxChar *tag) override
 
void WriteXML (XMLWriter &xmlFile) const
 
bool GetErrorOpening ()
 
bool Lock ()
 
bool Unlock ()
 
bool CloseLock ()
 
sampleFormat GetSampleFormat () const
 
bool ConvertToSampleFormat (sampleFormat format)
 
std::pair< float, float > GetMinMax (sampleCount start, sampleCount len, bool mayThrow) const
 
float GetRMS (sampleCount start, sampleCount len, bool mayThrow) const
 
sampleCount GetBlockStart (sampleCount position) const
 
size_t GetBestBlockSize (sampleCount start) const
 
size_t GetMaxBlockSize () const
 
size_t GetIdealBlockSize () const
 
BlockArrayGetBlockArray ()
 
void LockDeleteUpdateMutex ()
 
void UnlockDeleteUpdateMutex ()
 
void ConsistencyCheck (const wxChar *whereStr, bool mayThrow=true) const
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual void HandleXMLEndTag (const wxChar *WXUNUSED(tag))
 
virtual void HandleXMLContent (const wxString &WXUNUSED(content))
 
bool ReadXMLTag (const char *tag, const char **attrs)
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 

Static Public Member Functions

static void SetMaxDiskBlockSize (size_t bytes)
 
static size_t GetMaxDiskBlockSize ()
 
static void DebugPrintf (const BlockArray &block, sampleCount numSamples, wxString *dest)
 

Private Member Functions

int FindBlock (sampleCount pos) const
 
bool Get (int b, samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
 
void CommitChangesIfConsistent (BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
 
void AppendBlocksIfConsistent (BlockArray &additionalBlocks, bool replaceLast, sampleCount numSamples, const wxChar *whereStr)
 

Static Private Member Functions

static void AppendBlock (DirManager &dirManager, BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b)
 
static bool Read (samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
 
static void Blockify (DirManager &dirManager, size_t maxSamples, sampleFormat format, BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
 
static void ConsistencyCheck (const BlockArray &block, size_t maxSamples, size_t from, sampleCount numSamples, const wxChar *whereStr, bool mayThrow=true)
 

Private Attributes

std::shared_ptr< DirManagermDirManager
 
BlockArray mBlock
 
sampleFormat mSampleFormat
 
sampleCount mNumSamples { 0 }
 
size_t mMinSamples
 
size_t mMaxSamples
 
bool mErrorOpening { false }
 
ODLock mDeleteUpdateMutex
 To block the Delete() method against the ODCalcSummaryTask::Update() method. More...
 

Static Private Attributes

static size_t sMaxDiskBlockSize = 1048576
 

Detailed Description

A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interface to an array of SeqBlock instances, corresponding to the audio BlockFiles on disk. Contrast with RingBuffer.

Definition at line 54 of file Sequence.h.

Constructor & Destructor Documentation

Sequence::Sequence ( const std::shared_ptr< DirManager > &  projDirManager,
sampleFormat  format 
)

Definition at line 59 of file Sequence.cpp.

60  : mDirManager(projDirManager)
64 {
65 }
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
size_t mMinSamples
Definition: Sequence.h:235
int format
Definition: ExportPCM.cpp:56
static size_t sMaxDiskBlockSize
Definition: Sequence.h:221
sampleFormat mSampleFormat
Definition: Sequence.h:230
Sequence::Sequence ( const Sequence orig,
const std::shared_ptr< DirManager > &  projDirManager 
)

Definition at line 70 of file Sequence.cpp.

References Paste().

71  : mDirManager(projDirManager)
73  , mMinSamples(orig.mMinSamples)
74  , mMaxSamples(orig.mMaxSamples)
75 {
76  Paste(0, &orig);
77 }
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
size_t mMinSamples
Definition: Sequence.h:235
void Paste(sampleCount s0, const Sequence *src)
Definition: Sequence.cpp:466
sampleFormat mSampleFormat
Definition: Sequence.h:230
Sequence::Sequence ( const Sequence )
Sequence::~Sequence ( )

Definition at line 79 of file Sequence.cpp.

80 {
81 }

Member Function Documentation

void Sequence::Append ( samplePtr  buffer,
sampleFormat  format,
size_t  len,
XMLWriter blockFileLog = NULL 
)

Definition at line 1565 of file Sequence.cpp.

References AppendBlocksIfConsistent(), sampleCount::as_double(), ConsistencyCheck(), CopySamples(), SeqBlock::f, GetIdealBlockSize(), min(), mMaxSamples, mMinSamples, mNumSamples, mSampleFormat, DirManager::NewSimpleBlockFile(), SampleBuffer::ptr(), Read(), SAMPLE_SIZE, and THROW_INCONSISTENCY_EXCEPTION.

1568 {
1569  if (len == 0)
1570  return;
1571 
1572  // Quick check to make sure that it doesn't overflow
1573  if (Overflows(mNumSamples.as_double() + ((double)len)))
1575 
1576  BlockArray newBlock;
1577  sampleCount newNumSamples = mNumSamples;
1578 
1579  // If the last block is not full, we need to add samples to it
1580  int numBlocks = mBlock.size();
1581  SeqBlock *pLastBlock;
1582  decltype(pLastBlock->f->GetLength()) length;
1583  size_t bufferSize = mMaxSamples;
1584  SampleBuffer buffer2(bufferSize, mSampleFormat);
1585  bool replaceLast = false;
1586  if (numBlocks > 0 &&
1587  (length =
1588  (pLastBlock = &mBlock.back())->f->GetLength()) < mMinSamples) {
1589  // Enlarge a sub-minimum block at the end
1590  const SeqBlock &lastBlock = *pLastBlock;
1591  const auto addLen = std::min(mMaxSamples - length, len);
1592 
1593  Read(buffer2.ptr(), mSampleFormat, lastBlock, 0, length, true);
1594 
1595  CopySamples(buffer,
1596  format,
1597  buffer2.ptr() + length * SAMPLE_SIZE(mSampleFormat),
1598  mSampleFormat,
1599  addLen);
1600 
1601  const auto newLastBlockLen = length + addLen;
1602 
1603  SeqBlock newLastBlock(
1604  mDirManager->NewSimpleBlockFile(
1605  buffer2.ptr(), newLastBlockLen, mSampleFormat,
1606  blockFileLog != NULL
1607  ),
1608  lastBlock.start
1609  );
1610 
1611  if (blockFileLog)
1612  // shouldn't throw, because XMLWriter is not XMLFileWriter
1613  static_cast< SimpleBlockFile * >( &*newLastBlock.f )
1614  ->SaveXML( *blockFileLog );
1615 
1616  newBlock.push_back( newLastBlock );
1617 
1618  len -= addLen;
1619  newNumSamples += addLen;
1620  buffer += addLen * SAMPLE_SIZE(format);
1621 
1622  replaceLast = true;
1623  }
1624  // Append the rest as NEW blocks
1625  while (len) {
1626  const auto idealSamples = GetIdealBlockSize();
1627  const auto addedLen = std::min(idealSamples, len);
1628  BlockFilePtr pFile;
1629  if (format == mSampleFormat) {
1630  pFile = mDirManager->NewSimpleBlockFile(
1631  buffer, addedLen, mSampleFormat, blockFileLog != NULL);
1632  }
1633  else {
1634  CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, addedLen);
1635  pFile = mDirManager->NewSimpleBlockFile(
1636  buffer2.ptr(), addedLen, mSampleFormat, blockFileLog != NULL);
1637  }
1638 
1639  if (blockFileLog)
1640  // shouldn't throw, because XMLWriter is not XMLFileWriter
1641  static_cast< SimpleBlockFile * >( &*pFile )->SaveXML( *blockFileLog );
1642 
1643  newBlock.push_back(SeqBlock(pFile, newNumSamples));
1644 
1645  buffer += addedLen * SAMPLE_SIZE(format);
1646  newNumSamples += addedLen;
1647  len -= addedLen;
1648  }
1649 
1650  AppendBlocksIfConsistent(newBlock, replaceLast,
1651  newNumSamples, wxT("Append"));
1652 
1653 // JKC: During generate we use Append again and again.
1654 // If generating a long sequence this test would give O(n^2)
1655 // performance - not good!
1656 #ifdef VERY_SLOW_CHECKING
1657  ConsistencyCheck(wxT("Append"));
1658 #endif
1659 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
A BlockFile that reads and writes uncompressed data using libsndfile.
double as_double() const
Definition: Types.h:88
size_t mMinSamples
Definition: Sequence.h:235
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
#define THROW_INCONSISTENCY_EXCEPTION
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
int format
Definition: ExportPCM.cpp:56
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
void AppendBlocksIfConsistent(BlockArray &additionalBlocks, bool replaceLast, sampleCount numSamples, const wxChar *whereStr)
Definition: Sequence.cpp:1935
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
size_t GetIdealBlockSize() const
Definition: Sequence.cpp:88
sampleFormat mSampleFormat
Definition: Sequence.h:230
void Sequence::AppendAlias ( const wxString &  fullPath,
sampleCount  start,
size_t  len,
int  channel,
bool  useOD 
)

Definition at line 716 of file Sequence.cpp.

References sampleCount::as_double(), mBlock, mDirManager, mNumSamples, and THROW_INCONSISTENCY_EXCEPTION.

720 {
721  // Quick check to make sure that it doesn't overflow
722  if (Overflows((mNumSamples.as_double()) + ((double)len)))
724 
725  SeqBlock newBlock(
726  useOD?
727  mDirManager->NewODAliasBlockFile(fullPath, start, len, channel):
728  mDirManager->NewAliasBlockFile(fullPath, start, len, channel),
730  );
731  mBlock.push_back(newBlock);
732  mNumSamples += len;
733 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
double as_double() const
Definition: Types.h:88
#define THROW_INCONSISTENCY_EXCEPTION
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::AppendBlock ( DirManager dirManager,
BlockArray blocks,
sampleCount numSamples,
const SeqBlock b 
)
staticprivate

Definition at line 752 of file Sequence.cpp.

References sampleCount::as_double(), DirManager::CopyBlockFile(), SeqBlock::f, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Copy(), and Paste().

754 {
755  // Quick check to make sure that it doesn't overflow
756  if (Overflows((mNumSamples.as_double()) + ((double)b.f->GetLength())))
758 
759  SeqBlock newBlock(
760  mDirManager.CopyBlockFile(b.f), // Bump ref count if not locked, else copy
762  );
763  // We can assume newBlock.f is not null
764 
765  mBlock.push_back(newBlock);
766  mNumSamples += newBlock.f->GetLength();
767 
768  // Don't do a consistency check here because this
769  // function gets called in an inner loop.
770 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
double as_double() const
Definition: Types.h:88
#define THROW_INCONSISTENCY_EXCEPTION
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::AppendBlockFile ( const BlockFilePtr blockFile)

Definition at line 2021 of file Sequence.cpp.

References ConsistencyCheck().

Referenced by RecordingRecoveryHandler::HandleXMLTag().

2022 {
2023  // We assume blockFile has the correct ref count already
2024 
2025  mBlock.push_back(SeqBlock(blockFile, mNumSamples));
2026  mNumSamples += blockFile->GetLength();
2027 
2028  // PRL: I hoisted the intended consistency check out of the inner loop
2029  // See RecordingRecoveryHandler::HandleXMLEndTag
2030 
2031 #ifdef VERY_SLOW_CHECKING
2032  ConsistencyCheck(wxT("AppendBlockFile"));
2033 #endif
2034 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::AppendBlocksIfConsistent ( BlockArray additionalBlocks,
bool  replaceLast,
sampleCount  numSamples,
const wxChar *  whereStr 
)
private

Definition at line 1935 of file Sequence.cpp.

Referenced by Append().

1937 {
1938  // Any additional blocks are meant to be appended,
1939  // replacing the final block if there was one.
1940 
1941  if (additionalBlocks.empty())
1942  return;
1943 
1944  bool tmpValid = false;
1945  SeqBlock tmp;
1946 
1947  if ( replaceLast && ! mBlock.empty() ) {
1948  tmp = mBlock.back(), tmpValid = true;
1949  mBlock.pop_back();
1950  }
1951 
1952  auto prevSize = mBlock.size();
1953 
1954  bool consistent = false;
1955  auto cleanup = finally( [&] {
1956  if ( !consistent ) {
1957  mBlock.resize( prevSize );
1958  if ( tmpValid )
1959  mBlock.push_back( tmp );
1960  }
1961  } );
1962 
1963  std::copy( additionalBlocks.begin(), additionalBlocks.end(),
1964  std::back_inserter( mBlock ) );
1965 
1966  // Check consistency only of the blocks that were added,
1967  // avoiding quadratic time for repeated checking of repeating appends
1968  ConsistencyCheck( mBlock, mMaxSamples, prevSize, numSamples, whereStr ); // may throw
1969 
1970  // now commit
1971  // use NOFAIL-GUARANTEE
1972 
1973  mNumSamples = numSamples;
1974  consistent = true;
1975 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::AppendCoded ( const wxString &  fName,
sampleCount  start,
size_t  len,
int  channel,
int  decodeType 
)

Definition at line 735 of file Sequence.cpp.

References sampleCount::as_double(), mBlock, mDirManager, mNumSamples, and THROW_INCONSISTENCY_EXCEPTION.

738 {
739  // Quick check to make sure that it doesn't overflow
740  if (Overflows((mNumSamples.as_double()) + ((double)len)))
742 
743  SeqBlock newBlock(
744  mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType),
746  );
747  mBlock.push_back(newBlock);
748  mNumSamples += len;
749 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
double as_double() const
Definition: Types.h:88
#define THROW_INCONSISTENCY_EXCEPTION
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::Blockify ( DirManager dirManager,
size_t  maxSamples,
sampleFormat  format,
BlockArray list,
sampleCount  start,
samplePtr  buffer,
size_t  len 
)
staticprivate

Definition at line 1662 of file Sequence.cpp.

References SeqBlock::f, DirManager::NewSimpleBlockFile(), SAMPLE_SIZE, and SeqBlock::start.

Referenced by ConvertToSampleFormat(), Delete(), and Paste().

1664 {
1665  if (len <= 0)
1666  return;
1667  auto num = (len + (mMaxSamples - 1)) / mMaxSamples;
1668  list.reserve(list.size() + num);
1669 
1670  for (decltype(num) i = 0; i < num; i++) {
1671  SeqBlock b;
1672 
1673  const auto offset = i * len / num;
1674  b.start = start + offset;
1675  int newLen = ((i + 1) * len / num) - offset;
1676  samplePtr bufStart = buffer + (offset * SAMPLE_SIZE(mSampleFormat));
1677 
1678  b.f = mDirManager.NewSimpleBlockFile(bufStart, newLen, mSampleFormat);
1679 
1680  list.push_back(b);
1681  }
1682 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
char * samplePtr
Definition: Types.h:203
BlockFilePtr f
Definition: Sequence.h:33
sampleFormat mSampleFormat
Definition: Sequence.h:230
bool Sequence::CloseLock ( )

Definition at line 101 of file Sequence.cpp.

References mBlock.

102 {
103  for (unsigned int i = 0; i < mBlock.size(); i++)
104  mBlock[i].f->CloseLock();
105 
106  return true;
107 }
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::CommitChangesIfConsistent ( BlockArray newBlock,
sampleCount  numSamples,
const wxChar *  whereStr 
)
private

Definition at line 1923 of file Sequence.cpp.

Referenced by ConvertToSampleFormat(), Delete(), Paste(), and SetSamples().

1924 {
1925  ConsistencyCheck( newBlock, mMaxSamples, 0, numSamples, whereStr ); // may throw
1926 
1927  // now commit
1928  // use NOFAIL-GUARANTEE
1929 
1930  mBlock.swap(newBlock);
1931  mNumSamples = numSamples;
1932 }
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::ConsistencyCheck ( const wxChar *  whereStr,
bool  mayThrow = true 
) const

Definition at line 1865 of file Sequence.cpp.

Referenced by Append(), AppendBlockFile(), Delete(), RecordingRecoveryHandler::HandleXMLEndTag(), and Paste().

1866 {
1867  ConsistencyCheck(mBlock, mMaxSamples, 0, mNumSamples, whereStr, mayThrow);
1868 }
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
BlockArray mBlock
Definition: Sequence.h:229
static void Sequence::ConsistencyCheck ( const BlockArray block,
size_t  maxSamples,
size_t  from,
sampleCount  numSamples,
const wxChar *  whereStr,
bool  mayThrow = true 
)
staticprivate
bool Sequence::ConvertToSampleFormat ( sampleFormat  format)

Definition at line 158 of file Sequence.cpp.

References Blockify(), CommitChangesIfConsistent(), CopySamples(), SeqBlock::f, format, mBlock, mDirManager, mMaxSamples, mMinSamples, mNumSamples, mSampleFormat, SampleBuffer::ptr(), Read(), SAMPLE_SIZE, and sMaxDiskBlockSize.

160 {
161  if (format == mSampleFormat)
162  // no change
163  return false;
164 
165  if (mBlock.size() == 0)
166  {
168  return true;
169  }
170 
171  const sampleFormat oldFormat = mSampleFormat;
173 
174  const auto oldMinSamples = mMinSamples, oldMaxSamples = mMaxSamples;
175  // These are the same calculations as in the constructor.
177  mMaxSamples = mMinSamples * 2;
178 
179  bool bSuccess = false;
180  auto cleanup = finally( [&] {
181  if (!bSuccess) {
182  // Conversion failed. Revert these member vars.
183  mSampleFormat = oldFormat;
184  mMaxSamples = oldMaxSamples;
185  mMinSamples = oldMinSamples;
186  }
187  } );
188 
189  BlockArray newBlockArray;
190  // Use the ratio of old to NEW mMaxSamples to make a reasonable guess
191  // at allocation.
192  newBlockArray.reserve
193  (1 + mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples));
194 
195  {
196  size_t oldSize = oldMaxSamples;
197  SampleBuffer bufferOld(oldSize, oldFormat);
198  size_t newSize = oldMaxSamples;
199  SampleBuffer bufferNew(newSize, format);
200 
201  for (size_t i = 0, nn = mBlock.size(); i < nn; i++)
202  {
203  SeqBlock &oldSeqBlock = mBlock[i];
204  const auto &oldBlockFile = oldSeqBlock.f;
205  const auto len = oldBlockFile->GetLength();
206  ensureSampleBufferSize(bufferOld, oldFormat, oldSize, len);
207  Read(bufferOld.ptr(), oldFormat, oldSeqBlock, 0, len, true);
208 
209  ensureSampleBufferSize(bufferNew, format, newSize, len);
210  CopySamples(bufferOld.ptr(), oldFormat, bufferNew.ptr(), format, len);
211 
212  // Note this fix for http://bugzilla.audacityteam.org/show_bug.cgi?id=451,
213  // using Blockify, allows (len < mMinSamples).
214  // This will happen consistently when going from more bytes per sample to fewer...
215  // This will create a block that's smaller than mMinSamples, which
216  // shouldn't be allowed, but we agreed it's okay for now.
217  //vvv ANSWER-ME: Does this cause any bugs, or failures on write, elsewhere?
218  // If so, need to special-case (len < mMinSamples) and start combining data
219  // from the old blocks... Oh no!
220 
221  // Using Blockify will handle the cases where len > the NEW mMaxSamples. Previous code did not.
222  const auto blockstart = oldSeqBlock.start;
224  newBlockArray, blockstart, bufferNew.ptr(), len);
225  }
226  }
227 
228  // Invalidate all the old, non-aliased block files.
229  // Aliased files will be converted at save, per comment above.
230 
231  // Commit the changes to block file array
233  (newBlockArray, mNumSamples, wxT("Sequence::ConvertToSampleFormat()"));
234 
235  // Commit the other changes
236  bSuccess = true;
237 
238  return true;
239 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
void CommitChangesIfConsistent(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
Definition: Sequence.cpp:1923
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
size_t mMinSamples
Definition: Sequence.h:235
int format
Definition: ExportPCM.cpp:56
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
sampleFormat
Definition: Types.h:188
static size_t sMaxDiskBlockSize
Definition: Sequence.h:221
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
static void Blockify(DirManager &dirManager, size_t maxSamples, sampleFormat format, BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
Definition: Sequence.cpp:1662
std::unique_ptr< Sequence > Sequence::Copy ( sampleCount  s0,
sampleCount  s1 
) const

Definition at line 390 of file Sequence.cpp.

References AppendBlock(), SeqBlock::f, FindBlock(), Get(), mBlock, mDirManager, min(), mMaxSamples, mNumSamples, mSampleFormat, SampleBuffer::ptr(), and SeqBlock::start.

391 {
392  auto dest = std::make_unique<Sequence>(mDirManager, mSampleFormat);
393  if (s0 >= s1 || s0 >= mNumSamples || s1 < 0) {
394  return dest;
395  }
396 
397  int numBlocks = mBlock.size();
398 
399  int b0 = FindBlock(s0);
400  const int b1 = FindBlock(s1 - 1);
401  wxASSERT(b0 >= 0);
402  wxASSERT(b0 < numBlocks);
403  wxASSERT(b1 < numBlocks);
404  wxUnusedVar(numBlocks);
405  wxASSERT(b0 <= b1);
406 
407  dest->mBlock.reserve(b1 - b0 + 1);
408 
409  auto bufferSize = mMaxSamples;
410  SampleBuffer buffer(bufferSize, mSampleFormat);
411 
412  int blocklen;
413 
414  // Do the first block
415 
416  const SeqBlock &block0 = mBlock[b0];
417  if (s0 != block0.start) {
418  const auto &file = block0.f;
419  // Nonnegative result is length of block0 or less:
420  blocklen =
421  ( std::min(s1, block0.start + file->GetLength()) - s0 ).as_size_t();
422  wxASSERT(file->IsAlias() || (blocklen <= (int)mMaxSamples)); // Vaughan, 2012-02-29
423  ensureSampleBufferSize(buffer, mSampleFormat, bufferSize, blocklen);
424  Get(b0, buffer.ptr(), mSampleFormat, s0, blocklen, true);
425 
426  dest->Append(buffer.ptr(), mSampleFormat, blocklen);
427  }
428  else
429  --b0;
430 
431  // If there are blocks in the middle, copy the blockfiles directly
432  for (int bb = b0 + 1; bb < b1; ++bb)
433  AppendBlock(*dest->mDirManager, dest->mBlock, dest->mNumSamples, mBlock[bb]);
434  // Increase ref count or duplicate file
435 
436  // Do the last block
437  if (b1 > b0) {
438  const SeqBlock &block = mBlock[b1];
439  const auto &file = block.f;
440  // s1 is within block:
441  blocklen = (s1 - block.start).as_size_t();
442  wxASSERT(file->IsAlias() || (blocklen <= (int)mMaxSamples)); // Vaughan, 2012-02-29
443  if (blocklen < (int)file->GetLength()) {
444  ensureSampleBufferSize(buffer, mSampleFormat, bufferSize, blocklen);
445  Get(b1, buffer.ptr(), mSampleFormat, block.start, blocklen, true);
446  dest->Append(buffer.ptr(), mSampleFormat, blocklen);
447  }
448  else
449  // Special case, copy exactly
450  AppendBlock(*dest->mDirManager, dest->mBlock, dest->mNumSamples, block);
451  // Increase ref count or duplicate file
452  }
453 
454  dest->ConsistencyCheck(wxT("Sequence::Copy()"));
455 
456  return dest;
457 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
static void AppendBlock(DirManager &dirManager, BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b)
Definition: Sequence.cpp:752
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
Definition: Sequence.cpp:1151
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
void Sequence::DebugPrintf ( const BlockArray block,
sampleCount  numSamples,
wxString *  dest 
)
static

Definition at line 1978 of file Sequence.cpp.

References sampleCount::as_long_long(), SeqBlock::f, and SeqBlock::start.

1979 {
1980  unsigned int i;
1981  decltype(mNumSamples) pos = 0;
1982 
1983  for (i = 0; i < mBlock.size(); i++) {
1984  const SeqBlock &seqBlock = mBlock[i];
1985  *dest += wxString::Format
1986  (wxT(" Block %3u: start %8lld, len %8lld, refs %ld, "),
1987  i,
1988  seqBlock.start.as_long_long(),
1989  seqBlock.f ? (long long) seqBlock.f->GetLength() : 0,
1990  seqBlock.f ? seqBlock.f.use_count() : 0);
1991 
1992  if (seqBlock.f)
1993  *dest += seqBlock.f->GetFileName().name.GetFullName();
1994  else
1995  *dest += wxT("<missing block file>");
1996 
1997  if ((pos != seqBlock.start) || !seqBlock.f)
1998  *dest += wxT(" ERROR\n");
1999  else
2000  *dest += wxT("\n");
2001 
2002  if (seqBlock.f)
2003  pos += seqBlock.f->GetLength();
2004  }
2005  if (pos != mNumSamples)
2006  *dest += wxString::Format
2007  (wxT("ERROR mNumSamples = %lld\n"), mNumSamples.as_long_long());
2008 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
long long as_long_long() const
Definition: Types.h:90
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::Delete ( sampleCount  start,
sampleCount  len 
)

Definition at line 1684 of file Sequence.cpp.

References Blockify(), CommitChangesIfConsistent(), ConsistencyCheck(), SeqBlock::f, FindBlock(), limitSampleBufferSize(), mMinSamples, mSampleFormat, DirManager::NewSimpleBlockFile(), Read(), SAMPLE_SIZE, SeqBlock::start, and THROW_INCONSISTENCY_EXCEPTION.

1686 {
1687  if (len == 0)
1688  return;
1689 
1690  if (len < 0 || start < 0 || start + len > mNumSamples)
1692 
1693  //TODO: add a ref-deref mechanism to SeqBlock/BlockArray so we don't have to make this a critical section.
1694  //On-demand threads iterate over the mBlocks and the GUI thread deletes them, so for now put a mutex here over
1695  //both functions,
1696  DeleteUpdateMutexLocker locker(*this);
1697 
1698  const unsigned int numBlocks = mBlock.size();
1699 
1700  const unsigned int b0 = FindBlock(start);
1701  unsigned int b1 = FindBlock(start + len - 1);
1702 
1703  auto sampleSize = SAMPLE_SIZE(mSampleFormat);
1704 
1705  SeqBlock *pBlock;
1706  decltype(pBlock->f->GetLength()) length;
1707 
1708  // One buffer for reuse in various branches here
1709  SampleBuffer scratch;
1710  // The maximum size that should ever be needed
1711  auto scratchSize = mMaxSamples + mMinSamples;
1712 
1713  // Special case: if the samples to DELETE are all within a single
1714  // block and the resulting length is not too small, perform the
1715  // deletion within this block:
1716  if (b0 == b1 &&
1717  (length = (pBlock = &mBlock[b0])->f->GetLength()) - len >= mMinSamples) {
1718  SeqBlock &b = *pBlock;
1719  // start is within block
1720  auto pos = ( start - b.start ).as_size_t();
1721 
1722  // Guard against failure of this anyway below with limitSampleBufferSize
1723  wxASSERT(len < length);
1724 
1725  // len must be less than length
1726  // because start + len - 1 is also in the block...
1727  auto newLen = ( length - limitSampleBufferSize( length, len ) );
1728 
1729  scratch.Allocate(scratchSize, mSampleFormat);
1730  ensureSampleBufferSize(scratch, mSampleFormat, scratchSize, newLen);
1731 
1732  Read(scratch.ptr(), mSampleFormat, b, 0, pos, true);
1733  Read(scratch.ptr() + (pos * sampleSize), mSampleFormat,
1734  b,
1735  // ... and therefore pos + len
1736  // is not more than the length of the block
1737  ( pos + len ).as_size_t(), newLen - pos, true);
1738 
1739  auto newFile =
1740  mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat);
1741 
1742  // Don't make a duplicate array. We can still give STRONG-GUARANTEE
1743  // if we modify only one block in place.
1744 
1745  // use NOFAIL-GUARANTEE in remaining steps
1746 
1747  b.f = newFile;
1748 
1749  for (unsigned int j = b0 + 1; j < numBlocks; j++)
1750  mBlock[j].start -= len;
1751 
1752  mNumSamples -= len;
1753 
1754  // This consistency check won't throw, it asserts.
1755  // Proof that we kept consistency is not hard.
1756  ConsistencyCheck(wxT("Delete - branch one"), false);
1757  return;
1758  }
1759 
1760  // Create a NEW array of blocks
1761  BlockArray newBlock;
1762  newBlock.reserve(numBlocks - (b1 - b0) + 2);
1763 
1764  // Copy the blocks before the deletion point over to
1765  // the NEW array
1766  newBlock.insert(newBlock.end(), mBlock.begin(), mBlock.begin() + b0);
1767  unsigned int i;
1768 
1769  // First grab the samples in block b0 before the deletion point
1770  // into preBuffer. If this is enough samples for its own block,
1771  // or if this would be the first block in the array, write it out.
1772  // Otherwise combine it with the previous block (splitting them
1773  // 50/50 if necessary).
1774  const SeqBlock &preBlock = mBlock[b0];
1775  // start is within preBlock
1776  auto preBufferLen = ( start - preBlock.start ).as_size_t();
1777  if (preBufferLen) {
1778  if (preBufferLen >= mMinSamples || b0 == 0) {
1779  if (!scratch.ptr())
1780  scratch.Allocate(scratchSize, mSampleFormat);
1781  ensureSampleBufferSize(scratch, mSampleFormat, scratchSize, preBufferLen);
1782  Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen, true);
1783  auto pFile =
1784  mDirManager->NewSimpleBlockFile(scratch.ptr(), preBufferLen, mSampleFormat);
1785 
1786  newBlock.push_back(SeqBlock(pFile, preBlock.start));
1787  } else {
1788  const SeqBlock &prepreBlock = mBlock[b0 - 1];
1789  const auto prepreLen = prepreBlock.f->GetLength();
1790  const auto sum = prepreLen + preBufferLen;
1791 
1792  if (!scratch.ptr())
1793  scratch.Allocate(scratchSize, mSampleFormat);
1794  ensureSampleBufferSize(scratch, mSampleFormat, scratchSize,
1795  sum);
1796 
1797  Read(scratch.ptr(), mSampleFormat, prepreBlock, 0, prepreLen, true);
1798  Read(scratch.ptr() + prepreLen*sampleSize, mSampleFormat,
1799  preBlock, 0, preBufferLen, true);
1800 
1801  newBlock.pop_back();
1802  Blockify(*mDirManager, mMaxSamples, mSampleFormat,
1803  newBlock, prepreBlock.start, scratch.ptr(), sum);
1804  }
1805  }
1806  else {
1807  // The sample where we begin deletion happens to fall
1808  // right on the beginning of a block.
1809  }
1810 
1811  // Now, symmetrically, grab the samples in block b1 after the
1812  // deletion point into postBuffer. If this is enough samples
1813  // for its own block, or if this would be the last block in
1814  // the array, write it out. Otherwise combine it with the
1815  // subsequent block (splitting them 50/50 if necessary).
1816  const SeqBlock &postBlock = mBlock[b1];
1817  // start + len - 1 lies within postBlock
1818  const auto postBufferLen = (
1819  (postBlock.start + postBlock.f->GetLength()) - (start + len)
1820  ).as_size_t();
1821  if (postBufferLen) {
1822  if (postBufferLen >= mMinSamples || b1 == numBlocks - 1) {
1823  if (!scratch.ptr())
1824  // Last use of scratch, can ask for smaller
1825  scratch.Allocate(postBufferLen, mSampleFormat);
1826  // start + len - 1 lies within postBlock
1827  auto pos = (start + len - postBlock.start).as_size_t();
1828  Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen, true);
1829  auto file =
1830  mDirManager->NewSimpleBlockFile(scratch.ptr(), postBufferLen, mSampleFormat);
1831 
1832  newBlock.push_back(SeqBlock(file, start));
1833  } else {
1834  SeqBlock &postpostBlock = mBlock[b1 + 1];
1835  const auto postpostLen = postpostBlock.f->GetLength();
1836  const auto sum = postpostLen + postBufferLen;
1837 
1838  if (!scratch.ptr())
1839  // Last use of scratch, can ask for smaller
1840  scratch.Allocate(sum, mSampleFormat);
1841  // start + len - 1 lies within postBlock
1842  auto pos = (start + len - postBlock.start).as_size_t();
1843  Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen, true);
1844  Read(scratch.ptr() + (postBufferLen * sampleSize), mSampleFormat,
1845  postpostBlock, 0, postpostLen, true);
1846 
1847  Blockify(*mDirManager, mMaxSamples, mSampleFormat,
1848  newBlock, start, scratch.ptr(), sum);
1849  b1++;
1850  }
1851  }
1852  else {
1853  // The sample where we begin deletion happens to fall
1854  // right on the end of a block.
1855  }
1856 
1857  // Copy the remaining blocks over from the old array
1858  for (i = b1 + 1; i < numBlocks; i++)
1859  newBlock.push_back(mBlock[i].Plus(-len));
1860 
1862  (newBlock, mNumSamples - len, wxT("Delete - branch two"));
1863 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
void CommitChangesIfConsistent(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
Definition: Sequence.cpp:1923
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
size_t mMinSamples
Definition: Sequence.h:235
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
#define THROW_INCONSISTENCY_EXCEPTION
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
static void Blockify(DirManager &dirManager, size_t maxSamples, sampleFormat format, BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
Definition: Sequence.cpp:1662
int Sequence::FindBlock ( sampleCount  pos) const
private

Definition at line 1080 of file Sequence.cpp.

References SeqBlock::f, min(), mNumSamples, and SeqBlock::start.

Referenced by Copy(), Delete(), Get(), GetBestBlockSize(), GetBlockStart(), GetMinMax(), GetRMS(), GetWaveDisplay(), Paste(), and SetSamples().

1081 {
1082  wxASSERT(pos >= 0 && pos < mNumSamples);
1083 
1084  if (pos == 0)
1085  return 0;
1086 
1087  int numBlocks = mBlock.size();
1088 
1089  size_t lo = 0, hi = numBlocks, guess;
1090  sampleCount loSamples = 0, hiSamples = mNumSamples;
1091 
1092  while (true) {
1093  //this is not a binary search, but a
1094  //dictionary search where we guess something smarter than the binary division
1095  //of the unsearched area, since samples are usually proportional to block file number.
1096  const double frac = (pos - loSamples).as_double() /
1097  (hiSamples - loSamples).as_double();
1098  guess = std::min(hi - 1, lo + size_t(frac * (hi - lo)));
1099  const SeqBlock &block = mBlock[guess];
1100 
1101  wxASSERT(block.f->GetLength() > 0);
1102  wxASSERT(lo <= guess && guess < hi && lo < hi);
1103 
1104  if (pos < block.start) {
1105  wxASSERT(lo != guess);
1106  hi = guess;
1107  hiSamples = block.start;
1108  }
1109  else {
1110  const sampleCount nextStart = block.start + block.f->GetLength();
1111  if (pos < nextStart)
1112  break;
1113  else {
1114  wxASSERT(guess < hi - 1);
1115  lo = guess + 1;
1116  loSamples = nextStart;
1117  }
1118  }
1119  }
1120 
1121  const int rval = guess;
1122  wxASSERT(rval >= 0 && rval < numBlocks &&
1123  pos >= mBlock[rval].start &&
1124  pos < mBlock[rval].start + mBlock[rval].f->GetLength());
1125 
1126  return rval;
1127 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
bool Sequence::Get ( samplePtr  buffer,
sampleFormat  format,
sampleCount  start,
size_t  len,
bool  mayThrow 
) const

Definition at line 1151 of file Sequence.cpp.

References ClearSamples(), FindBlock(), floatSample, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Copy(), and Paste().

1153 {
1154  if (start == mNumSamples) {
1155  return len == 0;
1156  }
1157 
1158  if (start < 0 || start + len > mNumSamples) {
1159  if (mayThrow)
1161  ClearSamples( buffer, floatSample, 0, len );
1162  return false;
1163  }
1164  int b = FindBlock(start);
1165 
1166  return Get(b, buffer, format, start, len, mayThrow);
1167 }
sampleCount mNumSamples
Definition: Sequence.h:233
#define THROW_INCONSISTENCY_EXCEPTION
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
int format
Definition: ExportPCM.cpp:56
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
Definition: Sequence.cpp:1151
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
bool Sequence::Get ( int  b,
samplePtr  buffer,
sampleFormat  format,
sampleCount  start,
size_t  len,
bool  mayThrow 
) const
private

Definition at line 1169 of file Sequence.cpp.

References SeqBlock::f, min(), Read(), SAMPLE_SIZE, and SeqBlock::start.

1171 {
1172  bool result = true;
1173  while (len) {
1174  const SeqBlock &block = mBlock[b];
1175  // start is in block
1176  const auto bstart = (start - block.start).as_size_t();
1177  // bstart is not more than block length
1178  const auto blen = std::min(len, block.f->GetLength() - bstart);
1179 
1180  if (! Read(buffer, format, block, bstart, blen, mayThrow) )
1181  result = false;
1182 
1183  len -= blen;
1184  buffer += (blen * SAMPLE_SIZE(format));
1185  b++;
1186  start += blen;
1187  }
1188  return result;
1189 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
int format
Definition: ExportPCM.cpp:56
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
size_t Sequence::GetBestBlockSize ( sampleCount  start) const

Definition at line 792 of file Sequence.cpp.

References SeqBlock::f, FindBlock(), mMaxSamples, mMinSamples, and SeqBlock::start.

Referenced by WaveTrack::GetBestBlockSize().

793 {
794  // This method returns a nice number of samples you should try to grab in
795  // one big chunk in order to land on a block boundary, based on the starting
796  // sample. The value returned will always be nonzero and will be no larger
797  // than the value of GetMaxBlockSize()
798 
799  if (start < 0 || start >= mNumSamples)
800  return mMaxSamples;
801 
802  int b = FindBlock(start);
803  int numBlocks = mBlock.size();
804 
805  const SeqBlock &block = mBlock[b];
806  // start is in block:
807  auto result = (block.start + block.f->GetLength() - start).as_size_t();
808 
809  decltype(result) length;
810  while(result < mMinSamples && b+1<numBlocks &&
811  ((length = mBlock[b+1].f->GetLength()) + result) <= mMaxSamples) {
812  b++;
813  result += length;
814  }
815 
816  wxASSERT(result > 0 && result <= mMaxSamples);
817 
818  return result;
819 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
size_t mMinSamples
Definition: Sequence.h:235
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
BlockArray& Sequence::GetBlockArray ( )
inline

Definition at line 194 of file Sequence.h.

Referenced by GetAllSeqBlocks().

194 {return mBlock;}
BlockArray mBlock
Definition: Sequence.h:229
sampleCount Sequence::GetBlockStart ( sampleCount  position) const

Definition at line 786 of file Sequence.cpp.

References FindBlock().

Referenced by WaveTrack::GetBlockStart().

787 {
788  int b = FindBlock(position);
789  return mBlock[b].start;
790 }
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
BlockArray mBlock
Definition: Sequence.h:229
const std::shared_ptr<DirManager>& Sequence::GetDirManager ( )
inline

Definition at line 134 of file Sequence.h.

134 { return mDirManager; }
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
bool Sequence::GetErrorOpening ( )
inline

Definition at line 145 of file Sequence.h.

Referenced by WaveTrack::GetErrorOpening().

145 { return mErrorOpening; }
bool mErrorOpening
Definition: Sequence.h:238
size_t Sequence::GetIdealAppendLen ( ) const

Definition at line 1550 of file Sequence.cpp.

References GetMaxBlockSize().

1551 {
1552  int numBlocks = mBlock.size();
1553  const auto max = GetMaxBlockSize();
1554 
1555  if (numBlocks == 0)
1556  return max;
1557 
1558  const auto lastBlockLen = mBlock.back().f->GetLength();
1559  if (lastBlockLen >= max)
1560  return max;
1561  else
1562  return max - lastBlockLen;
1563 }
size_t GetMaxBlockSize() const
Definition: Sequence.cpp:83
BlockArray mBlock
Definition: Sequence.h:229
size_t Sequence::GetIdealBlockSize ( ) const

Definition at line 88 of file Sequence.cpp.

References mMaxSamples.

Referenced by Append(), WaveTrack::GetIdealBlockSize(), and InsertSilence().

89 {
90  return mMaxSamples;
91 }
size_t mMaxSamples
Definition: Sequence.h:236
size_t Sequence::GetMaxBlockSize ( ) const

Definition at line 83 of file Sequence.cpp.

References mMaxSamples.

Referenced by GetIdealAppendLen(), and WaveTrack::GetMaxBlockSize().

84 {
85  return mMaxSamples;
86 }
size_t mMaxSamples
Definition: Sequence.h:236
size_t Sequence::GetMaxDiskBlockSize ( )
static

Definition at line 2016 of file Sequence.cpp.

References sMaxDiskBlockSize.

Referenced by BenchmarkDialog::OnRun().

2017 {
2018  return sMaxDiskBlockSize;
2019 }
static size_t sMaxDiskBlockSize
Definition: Sequence.h:221
std::pair< float, float > Sequence::GetMinMax ( sampleCount  start,
sampleCount  len,
bool  mayThrow 
) const

Definition at line 241 of file Sequence.cpp.

References SeqBlock::f, FindBlock(), limitSampleBufferSize(), mBlock, min(), mMaxSamples, and SeqBlock::start.

243 {
244  if (len == 0 || mBlock.size() == 0) {
245  return {
246  0.f,
247  // FLT_MAX? So it doesn't look like a spurious '0' to a caller?
248 
249  0.f
250  // -FLT_MAX? So it doesn't look like a spurious '0' to a caller?
251  };
252  }
253 
254  float min = FLT_MAX;
255  float max = -FLT_MAX;
256 
257  unsigned int block0 = FindBlock(start);
258  unsigned int block1 = FindBlock(start + len - 1);
259 
260  // First calculate the min/max of the blocks in the middle of this region;
261  // this is very fast because we have the min/max of every entire block
262  // already in memory.
263 
264  for (unsigned b = block0 + 1; b < block1; ++b) {
265  auto results = mBlock[b].f->GetMinMaxRMS(mayThrow);
266 
267  if (results.min < min)
268  min = results.min;
269  if (results.max > max)
270  max = results.max;
271  }
272 
273  // Now we take the first and last blocks into account, noting that the
274  // selection may only partly overlap these blocks. If the overall min/max
275  // of either of these blocks is within min...max, then we can ignore them.
276  // If not, we need read some samples and summaries from disk.
277  {
278  const SeqBlock &theBlock = mBlock[block0];
279  const auto &theFile = theBlock.f;
280  auto results = theFile->GetMinMaxRMS(mayThrow);
281 
282  if (results.min < min || results.max > max) {
283  // start lies within theBlock:
284  auto s0 = ( start - theBlock.start ).as_size_t();
285  const auto maxl0 = (
286  // start lies within theBlock:
287  theBlock.start + theFile->GetLength() - start
288  ).as_size_t();
289  wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19
290  const auto l0 = limitSampleBufferSize ( maxl0, len );
291 
292  results = theFile->GetMinMaxRMS(s0, l0, mayThrow);
293  if (results.min < min)
294  min = results.min;
295  if (results.max > max)
296  max = results.max;
297  }
298  }
299 
300  if (block1 > block0)
301  {
302  const SeqBlock &theBlock = mBlock[block1];
303  const auto &theFile = theBlock.f;
304  auto results = theFile->GetMinMaxRMS(mayThrow);
305 
306  if (results.min < min || results.max > max) {
307 
308  // start + len - 1 lies in theBlock:
309  const auto l0 = ( start + len - theBlock.start ).as_size_t();
310  wxASSERT(l0 <= mMaxSamples); // Vaughan, 2011-10-19
311 
312  results = theFile->GetMinMaxRMS(0, l0, mayThrow);
313  if (results.min < min)
314  min = results.min;
315  if (results.max > max)
316  max = results.max;
317  }
318  }
319 
320  return { min, max };
321 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleCount Sequence::GetNumSamples ( ) const
inline

Definition at line 85 of file Sequence.h.

85 { return mNumSamples; }
sampleCount mNumSamples
Definition: Sequence.h:233
unsigned int Sequence::GetODFlags ( )

gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.

Definition at line 773 of file Sequence.cpp.

References ODTask::eODPCMSummary.

Referenced by WaveTrack::GetODFlags().

774 {
775  unsigned int ret = 0;
776  for (unsigned int i = 0; i < mBlock.size(); i++) {
777  const auto &file = mBlock[i].f;
778  if(!file->IsDataAvailable())
779  ret |= (static_cast< ODDecodeBlockFile * >( &*file ))->GetDecodeType();
780  else if(!file->IsSummaryAvailable())
781  ret |= ODTask::eODPCMSummary;
782  }
783  return ret;
784 }
BlockArray mBlock
Definition: Sequence.h:229
float Sequence::GetRMS ( sampleCount  start,
sampleCount  len,
bool  mayThrow 
) const

Definition at line 323 of file Sequence.cpp.

References sampleCount::as_double(), SeqBlock::f, FindBlock(), limitSampleBufferSize(), mBlock, mMaxSamples, and SeqBlock::start.

324 {
325  // len is the number of samples that we want the rms of.
326  // it may be longer than a block, and the code is carefully set up to handle that.
327  if (len == 0 || mBlock.size() == 0)
328  return 0.f;
329 
330  double sumsq = 0.0;
331  sampleCount length = 0; // this is the cumulative length of the bits we have the ms of so far, and should end up == len
332 
333  unsigned int block0 = FindBlock(start);
334  unsigned int block1 = FindBlock(start + len - 1);
335 
336  // First calculate the rms of the blocks in the middle of this region;
337  // this is very fast because we have the rms of every entire block
338  // already in memory.
339  for (unsigned b = block0 + 1; b < block1; b++) {
340  const SeqBlock &theBlock = mBlock[b];
341  const auto &theFile = theBlock.f;
342  auto results = theFile->GetMinMaxRMS(mayThrow);
343 
344  const auto fileLen = theFile->GetLength();
345  const auto blockRMS = results.RMS;
346  sumsq += blockRMS * blockRMS * fileLen;
347  length += fileLen;
348  }
349 
350  // Now we take the first and last blocks into account, noting that the
351  // selection may only partly overlap these blocks.
352  // If not, we need read some samples and summaries from disk.
353  {
354  const SeqBlock &theBlock = mBlock[block0];
355  const auto &theFile = theBlock.f;
356  // start lies within theBlock
357  auto s0 = ( start - theBlock.start ).as_size_t();
358  // start lies within theBlock
359  const auto maxl0 =
360  (theBlock.start + theFile->GetLength() - start).as_size_t();
361  wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19
362  const auto l0 = limitSampleBufferSize( maxl0, len );
363 
364  auto results = theFile->GetMinMaxRMS(s0, l0, mayThrow);
365  const auto partialRMS = results.RMS;
366  sumsq += partialRMS * partialRMS * l0;
367  length += l0;
368  }
369 
370  if (block1 > block0) {
371  const SeqBlock &theBlock = mBlock[block1];
372  const auto &theFile = theBlock.f;
373 
374  // start + len - 1 lies within theBlock
375  const auto l0 = ( start + len - theBlock.start ).as_size_t();
376  wxASSERT(l0 <= mMaxSamples); // PRL: I think Vaughan missed this
377 
378  auto results = theFile->GetMinMaxRMS(0, l0, mayThrow);
379  const auto partialRMS = results.RMS;
380  sumsq += partialRMS * partialRMS * l0;
381  length += l0;
382  }
383 
384  // PRL: catch bugs like 1320:
385  wxASSERT(length == len);
386 
387  return sqrt(sumsq / length.as_double() );
388 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
double as_double() const
Definition: Types.h:88
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat Sequence::GetSampleFormat ( ) const

Definition at line 117 of file Sequence.cpp.

References mSampleFormat.

Referenced by RecordingRecoveryHandler::HandleXMLTag().

118 {
119  return mSampleFormat;
120 }
sampleFormat mSampleFormat
Definition: Sequence.h:230
bool Sequence::GetWaveDisplay ( float *  min,
float *  max,
float *  rms,
int *  bl,
size_t  len,
const sampleCount where 
) const

Definition at line 1343 of file Sequence.cpp.

References SeqBlock::f, FindBlock(), floatSample, min(), mMaxSamples, Read(), and SeqBlock::start.

Referenced by WaveCache::LoadInvalidRegion().

1345 {
1346  wxASSERT(len > 0);
1347  const auto s0 = std::max(sampleCount(0), where[0]);
1348  if (s0 >= mNumSamples)
1349  // None of the samples asked for are in range. Abandon.
1350  return false;
1351 
1352  // In case where[len - 1] == where[len], raise the limit by one,
1353  // so we load at least one pixel for column len - 1
1354  // ... unless the mNumSamples ceiling applies, and then there are other defenses
1355  const auto s1 =
1356  std::min(mNumSamples, std::max(1 + where[len - 1], where[len]));
1357  Floats temp{ mMaxSamples };
1358 
1359  decltype(len) pixel = 0;
1360 
1361  auto srcX = s0;
1362  decltype(srcX) nextSrcX = 0;
1363  int lastRmsDenom = 0;
1364  int lastDivisor = 0;
1365  auto whereNow = std::min(s1 - 1, where[0]);
1366  decltype(whereNow) whereNext = 0;
1367  // Loop over block files, opening and reading and closing each
1368  // not more than once
1369  unsigned nBlocks = mBlock.size();
1370  const unsigned int block0 = FindBlock(s0);
1371  for (unsigned int b = block0; b < nBlocks; ++b) {
1372  if (b > block0)
1373  srcX = nextSrcX;
1374  if (srcX >= s1)
1375  break;
1376 
1377  // Find the range of sample values for this block that
1378  // are in the display.
1379  const SeqBlock &seqBlock = mBlock[b];
1380  const auto start = seqBlock.start;
1381  nextSrcX = std::min(s1, start + seqBlock.f->GetLength());
1382 
1383  // The column for pixel p covers samples from
1384  // where[p] up to but excluding where[p + 1].
1385 
1386  // Find the range of pixels covered by the current block file
1387  // (Their starting samples covered by it, to be exact)
1388  decltype(len) nextPixel;
1389  if (nextSrcX >= s1)
1390  // last pass
1391  nextPixel = len;
1392  else {
1393  nextPixel = pixel;
1394  // Taking min with s1 - 1, here and elsewhere, is another defense
1395  // to be sure the last pixel column gets at least one sample
1396  while (nextPixel < len &&
1397  (whereNext = std::min(s1 - 1, where[nextPixel])) < nextSrcX)
1398  ++nextPixel;
1399  }
1400  if (nextPixel == pixel)
1401  // The entire block's samples fall within one pixel column.
1402  // Either it's a rare odd block at the end, or else,
1403  // we must be really zoomed out!
1404  // Omit the entire block's contents from min/max/rms
1405  // calculation, which is not correct, but correctness might not
1406  // be worth the compute time if this happens every pixel
1407  // column. -- PRL
1408  continue;
1409  if (nextPixel == len)
1410  whereNext = s1;
1411 
1412  // Decide the summary level
1413  const double samplesPerPixel =
1414  (whereNext - whereNow).as_double() / (nextPixel - pixel);
1415  const int divisor =
1416  (samplesPerPixel >= 65536) ? 65536
1417  : (samplesPerPixel >= 256) ? 256
1418  : 1;
1419 
1420  int blockStatus = b;
1421 
1422  // How many samples or triples are needed?
1423 
1424  const size_t startPosition =
1425  // srcX and start are in the same block
1426  std::max(sampleCount(0), (srcX - start) / divisor).as_size_t();
1427  const size_t inclusiveEndPosition =
1428  // nextSrcX - 1 and start are in the same block
1429  std::min((sampleCount(mMaxSamples) / divisor) - 1,
1430  (nextSrcX - 1 - start) / divisor).as_size_t();
1431  const auto num = 1 + inclusiveEndPosition - startPosition;
1432  if (num <= 0) {
1433  // What? There was a zero length block file?
1434  wxASSERT(false);
1435  // Do some defense against this case anyway
1436  while (pixel < nextPixel) {
1437  min[pixel] = max[pixel] = rms[pixel] = 0;
1438  bl[pixel] = blockStatus;//MC
1439  ++pixel;
1440  }
1441  continue;
1442  }
1443 
1444  // Read from the block file or its summary
1445  switch (divisor) {
1446  default:
1447  case 1:
1448  // Read samples
1449  // no-throw for display operations!
1450  Read((samplePtr)temp.get(), floatSample, seqBlock, startPosition, num, false);
1451  break;
1452  case 256:
1453  // Read triples
1454  //check to see if summary data has been computed
1455  if (seqBlock.f->IsSummaryAvailable())
1456  // Ignore the return value.
1457  // This function fills with zeroes if read fails
1458  seqBlock.f->Read256(temp.get(), startPosition, num);
1459  else
1460  //otherwise, mark the display as not yet computed
1461  blockStatus = -1 - b;
1462  break;
1463  case 65536:
1464  // Read triples
1465  //check to see if summary data has been computed
1466  if (seqBlock.f->IsSummaryAvailable())
1467  // Ignore the return value.
1468  // This function fills with zeroes if read fails
1469  seqBlock.f->Read64K(temp.get(), startPosition, num);
1470  else
1471  //otherwise, mark the display as not yet computed
1472  blockStatus = -1 - b;
1473  break;
1474  }
1475 
1476  auto filePosition = startPosition;
1477 
1478  // The previous pixel column might straddle blocks.
1479  // If so, impute some of the data to it.
1480  if (b > block0 && pixel > 0) {
1481  // whereNow and start are in the same block
1482  auto midPosition = ((whereNow - start) / divisor).as_size_t();
1483  int diff(midPosition - filePosition);
1484  if (diff > 0) {
1485  MinMaxSumsq values(temp.get(), diff, divisor);
1486  const int lastPixel = pixel - 1;
1487  float &lastMin = min[lastPixel];
1488  lastMin = std::min(lastMin, values.min);
1489  float &lastMax = max[lastPixel];
1490  lastMax = std::max(lastMax, values.max);
1491  float &lastRms = rms[lastPixel];
1492  int lastNumSamples = lastRmsDenom * lastDivisor;
1493  lastRms = sqrt(
1494  (lastRms * lastRms * lastNumSamples + values.sumsq * divisor) /
1495  (lastNumSamples + diff * divisor)
1496  );
1497 
1498  filePosition = midPosition;
1499  }
1500  }
1501 
1502  // Loop over file positions
1503  int rmsDenom = 0;
1504  for (; filePosition <= inclusiveEndPosition;) {
1505  // Find range of pixel columns for this file position
1506  // (normally just one, but maybe more when zoomed very close)
1507  // and the range of positions for those columns
1508  // (normally one or more, for that one column)
1509  auto pixelX = pixel + 1;
1510  decltype(filePosition) positionX = 0;
1511  while (pixelX < nextPixel &&
1512  filePosition ==
1513  (positionX = (
1514  // s1 - 1 or where[pixelX] and start are in the same block
1515  (std::min(s1 - 1, where[pixelX]) - start) / divisor).as_size_t() )
1516  )
1517  ++pixelX;
1518  if (pixelX >= nextPixel)
1519  positionX = 1 + inclusiveEndPosition;
1520 
1521  // Find results to assign
1522  rmsDenom = (positionX - filePosition);
1523  wxASSERT(rmsDenom > 0);
1524  const float *const pv =
1525  temp.get() + (filePosition - startPosition) * (divisor == 1 ? 1 : 3);
1526  MinMaxSumsq values(pv, std::max(0, rmsDenom), divisor);
1527 
1528  // Assign results
1529  std::fill(&min[pixel], &min[pixelX], values.min);
1530  std::fill(&max[pixel], &max[pixelX], values.max);
1531  std::fill(&bl[pixel], &bl[pixelX], blockStatus);
1532  std::fill(&rms[pixel], &rms[pixelX], (float)sqrt(values.sumsq / rmsDenom));
1533 
1534  pixel = pixelX;
1535  filePosition = positionX;
1536  }
1537 
1538  wxASSERT(pixel == nextPixel);
1539  whereNow = whereNext;
1540  pixel = nextPixel;
1541  lastDivisor = divisor;
1542  lastRmsDenom = rmsDenom;
1543  } // for each block file
1544 
1545  wxASSERT(pixel == len);
1546 
1547  return true;
1548 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
char * samplePtr
Definition: Types.h:203
if(pTrack &&pTrack->GetDisplay()!=WaveTrack::Spectrum)
int min(int a, int b)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
XMLTagHandler * Sequence::HandleXMLChild ( const wxChar *  tag)
overridevirtual

Implements XMLTagHandler.

Definition at line 1024 of file Sequence.cpp.

References mSampleFormat, and DirManager::SetLoadingFormat().

1025 {
1026  if (!wxStrcmp(tag, wxT("waveblock")))
1027  return this;
1028  else {
1029  mDirManager->SetLoadingFormat(mSampleFormat);
1030  return mDirManager.get();
1031  }
1032 }
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
sampleFormat mSampleFormat
Definition: Sequence.h:230
void Sequence::HandleXMLEndTag ( const wxChar *  tag)
override

Definition at line 954 of file Sequence.cpp.

References sampleCount::as_double(), sampleCount::as_size_t(), SeqBlock::f, mErrorOpening, mMaxSamples, SeqBlock::start, and Internat::ToString().

955 {
956  if (wxStrcmp(tag, wxT("sequence")) != 0)
957  return;
958 
959  // Make sure that the sequence is valid.
960  // First, replace missing blockfiles with SilentBlockFiles
961  for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) {
962  SeqBlock &block = mBlock[b];
963  if (!block.f) {
964  sampleCount len;
965 
966  if (b < nn - 1)
967  len = mBlock[b+1].start - block.start;
968  else
969  len = mNumSamples - block.start;
970 
971  if (len > mMaxSamples)
972  {
973  // This could be why the blockfile failed, so limit
974  // the silent replacement to mMaxSamples.
975  wxLogWarning(
976  wxT(" Sequence has missing block file with length %s > mMaxSamples %s.\n Setting length to mMaxSamples. This will likely cause some block files to be considered orphans."),
977  // PRL: Why bother with Internat when the above is just wxT?
978  Internat::ToString(len.as_double(), 0),
979  Internat::ToString((double)mMaxSamples, 0));
980  len = mMaxSamples;
981  }
982  // len is at most mMaxSamples:
983  block.f = make_blockfile<SilentBlockFile>( len.as_size_t() );
984  wxLogWarning(
985  wxT("Gap detected in project file. Replacing missing block file with silence."));
986  mErrorOpening = true;
987  }
988  }
989 
990  // Next, make sure that start times and lengths are consistent
991  sampleCount numSamples = 0;
992  for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) {
993  SeqBlock &block = mBlock[b];
994  if (block.start != numSamples) {
995  wxString sFileAndExtension = block.f->GetFileName().name.GetFullName();
996  if (sFileAndExtension.IsEmpty())
997  sFileAndExtension = wxT("(replaced with silence)");
998  else
999  sFileAndExtension = wxT("\"") + sFileAndExtension + wxT("\"");
1000  wxLogWarning(
1001  wxT("Gap detected in project file.\n")
1002  wxT(" Start (%s) for block file %s is not one sample past end of previous block (%s).\n")
1003  wxT(" Moving start so blocks are contiguous."),
1004  // PRL: Why bother with Internat when the above is just wxT?
1005  Internat::ToString(block.start.as_double(), 0),
1006  sFileAndExtension,
1007  Internat::ToString(numSamples.as_double(), 0));
1008  block.start = numSamples;
1009  mErrorOpening = true;
1010  }
1011  numSamples += block.f->GetLength();
1012  }
1013  if (mNumSamples != numSamples) {
1014  wxLogWarning(
1015  wxT("Gap detected in project file. Correcting sequence sample count from %s to %s."),
1016  // PRL: Why bother with Internat when the above is just wxT?
1018  Internat::ToString(numSamples.as_double(), 0));
1019  mNumSamples = numSamples;
1020  mErrorOpening = true;
1021  }
1022 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
bool mErrorOpening
Definition: Sequence.h:238
double as_double() const
Definition: Types.h:88
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
Definition: Internat.cpp:138
A BlockFile containing nothing but silence. Saves disk space.
std::shared_ptr< Result > make_blockfile(Args &&...args)
Definition: BlockFile.h:51
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
bool Sequence::HandleXMLTag ( const wxChar *  tag,
const wxChar **  attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 821 of file Sequence.cpp.

References XMLValueChecker::IsGoodInt(), XMLValueChecker::IsGoodInt64(), XMLValueChecker::IsValidSampleFormat(), mErrorOpening, mMaxSamples, mSampleFormat, DirManager::SetLoadingBlockLength(), DirManager::SetLoadingMaxSamples(), DirManager::SetLoadingTarget(), and SeqBlock::start.

822 {
823  /* handle waveblock tag and its attributes */
824  if (!wxStrcmp(tag, wxT("waveblock"))) {
825  SeqBlock wb;
826 
827  // loop through attrs, which is a null-terminated list of
828  // attribute-value pairs
829  while(*attrs) {
830  const wxChar *attr = *attrs++;
831  const wxChar *value = *attrs++;
832 
833  long long nValue = 0;
834 
835  if (!value)
836  break;
837 
838  // Both these attributes have non-negative integer counts of samples, so
839  // we can test & convert here, making sure that values > 2^31 are OK
840  // because long clips will need them.
841  const wxString strValue = value;
842  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&nValue) || (nValue < 0))
843  {
844  mErrorOpening = true;
845  wxLogWarning(
846  wxT(" Sequence has bad %s attribute value, %s, that should be a positive integer."),
847  attr, strValue);
848  return false;
849  }
850 
851  if (!wxStrcmp(attr, wxT("start")))
852  wb.start = nValue;
853 
854  // Vaughan, 2011-10-10: I don't think we ever write a "len" attribute for "waveblock" tag,
855  // so I think this is actually legacy code, or something intended, but not completed.
856  // Anyway, might as well leave this code in, especially now that it has the check
857  // against mMaxSamples.
858  if (!wxStrcmp(attr, wxT("len")))
859  {
860  // mMaxSamples should already have been set by calls to the "sequence" clause below.
861  // The check intended here was already done in DirManager::HandleXMLTag(), where
862  // it let the block be built, then checked against mMaxSamples, and deleted the block
863  // if the size of the block is bigger than mMaxSamples.
864  if (static_cast<unsigned long long>(nValue) > mMaxSamples)
865  {
866  mErrorOpening = true;
867  return false;
868  }
869  mDirManager->SetLoadingBlockLength(nValue);
870  }
871  } // while
872 
873  mBlock.push_back(wb);
874  mDirManager->SetLoadingTarget(&mBlock, mBlock.size() - 1);
875 
876  return true;
877  }
878 
879  /* handle sequence tag and its attributes */
880  if (!wxStrcmp(tag, wxT("sequence"))) {
881  while(*attrs) {
882  const wxChar *attr = *attrs++;
883  const wxChar *value = *attrs++;
884 
885  if (!value)
886  break;
887 
888  long long nValue = 0;
889 
890  const wxString strValue = value; // promote string, we need this for all
891 
892  if (!wxStrcmp(attr, wxT("maxsamples")))
893  {
894  // This attribute is a sample count, so can be 64bit
895  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&nValue) || (nValue < 0))
896  {
897  mErrorOpening = true;
898  return false;
899  }
900  // Dominic, 12/10/2006:
901  // Let's check that maxsamples is >= 1024 and <= 64 * 1024 * 1024
902  // - that's a pretty wide range of reasonable values.
903  if ((nValue < 1024) || (nValue > 64 * 1024 * 1024))
904  {
905  mErrorOpening = true;
906  return false;
907  }
908 
909  // nValue is now safe for size_t
910  mMaxSamples = nValue;
911 
912  // PRL: Is the following really okay? DirManager might be shared across projects!
913  // PRL: Yes, because it only affects DirManager's behavior in opening the project.
914  mDirManager->SetLoadingMaxSamples(mMaxSamples);
915  }
916  else if (!wxStrcmp(attr, wxT("sampleformat")))
917  {
918  // This attribute is a sample format, normal int
919  long fValue;
920  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&fValue) || (fValue < 0) || !XMLValueChecker::IsValidSampleFormat(fValue))
921  {
922  mErrorOpening = true;
923  return false;
924  }
925  mSampleFormat = (sampleFormat)fValue;
926  }
927  else if (!wxStrcmp(attr, wxT("numsamples")))
928  {
929  // This attribute is a sample count, so can be 64bit
930  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&nValue) || (nValue < 0))
931  {
932  mErrorOpening = true;
933  return false;
934  }
935  mNumSamples = nValue;
936  }
937  } // while
938 
941  //if ((mMinSamples != sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2) ||
942  // (mMaxSamples != mMinSamples * 2))
943  //{
944  // mErrorOpening = true;
945  // return false;
946  //}
947 
948  return true;
949  }
950 
951  return false;
952 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
static bool IsGoodInt64(const wxString &strInt)
Check that the supplied string can be converted to a 64bit integer.
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
bool mErrorOpening
Definition: Sequence.h:238
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
sampleFormat
Definition: Types.h:188
static bool IsValidSampleFormat(const int nValue)
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
void Sequence::InsertSilence ( sampleCount  s0,
sampleCount  len 
)

Definition at line 668 of file Sequence.cpp.

References sampleCount::as_double(), sampleCount::as_size_t(), GetIdealBlockSize(), mBlock, mDirManager, mNumSamples, mSampleFormat, Paste(), and THROW_INCONSISTENCY_EXCEPTION.

670 {
671  // Quick check to make sure that it doesn't overflow
672  if (Overflows((mNumSamples.as_double()) + (len.as_double())))
674 
675  if (len <= 0)
676  return;
677 
678  // Create a NEW track containing as much silence as we
679  // need to insert, and then call Paste to do the insertion.
680  // We make use of a SilentBlockFile, which takes up no
681  // space on disk.
682 
684 
685  auto idealSamples = GetIdealBlockSize();
686 
687  sampleCount pos = 0;
688 
689  // Could nBlocks overflow a size_t? Not very likely. You need perhaps
690  // 2 ^ 52 samples which is over 3000 years at 44.1 kHz.
691  auto nBlocks = (len + idealSamples - 1) / idealSamples;
692  sTrack.mBlock.reserve(nBlocks.as_size_t());
693 
694  BlockFilePtr silentFile {};
695  if (len >= idealSamples)
696  silentFile = make_blockfile<SilentBlockFile>(idealSamples);
697  while (len >= idealSamples) {
698  sTrack.mBlock.push_back(SeqBlock(silentFile, pos));
699 
700  pos += idealSamples;
701  len -= idealSamples;
702  }
703  if (len != 0) {
704  sTrack.mBlock.push_back(SeqBlock(
705  // len is not more than idealSamples:
706  make_blockfile<SilentBlockFile>( len.as_size_t() ), pos));
707  pos += len;
708  }
709 
710  sTrack.mNumSamples = pos;
711 
712  // use STRONG-GUARANTEE
713  Paste(s0, &sTrack);
714 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:54
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
double as_double() const
Definition: Types.h:88
#define THROW_INCONSISTENCY_EXCEPTION
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
void Paste(sampleCount s0, const Sequence *src)
Definition: Sequence.cpp:466
size_t as_size_t() const
Definition: Types.h:92
size_t GetIdealBlockSize() const
Definition: Sequence.cpp:88
sampleFormat mSampleFormat
Definition: Sequence.h:230
bool Sequence::Lock ( )

Definition at line 93 of file Sequence.cpp.

References mBlock.

94 {
95  for (unsigned int i = 0; i < mBlock.size(); i++)
96  mBlock[i].f->Lock();
97 
98  return true;
99 }
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::LockDeleteUpdateMutex ( )
inline

Definition at line 197 of file Sequence.h.

Referenced by ODDecodeTask::Update().

197 {mDeleteUpdateMutex.Lock();}
ODLock mDeleteUpdateMutex
To block the Delete() method against the ODCalcSummaryTask::Update() method.
Definition: Sequence.h:241
Sequence& Sequence::operator= ( const Sequence )
void Sequence::Paste ( sampleCount  s0,
const Sequence src 
)

Definition at line 466 of file Sequence.cpp.

References AppendBlock(), sampleCount::as_double(), Blockify(), CommitChangesIfConsistent(), ConsistencyCheck(), SeqBlock::f, FindBlock(), Get(), GetSampleFormatStr(), mBlock, mDirManager, mMaxSamples, mMinSamples, mNumSamples, mSampleFormat, SampleBuffer::ptr(), Read(), SAMPLE_SIZE, SeqBlock::start, THROW_INCONSISTENCY_EXCEPTION, and Internat::ToString().

Referenced by InsertSilence(), and Sequence().

468 {
469  if ((s < 0) || (s > mNumSamples))
470  {
471  wxLogError(
472  wxT("Sequence::Paste: sampleCount s %s is < 0 or > mNumSamples %s)."),
473  // PRL: Why bother with Internat when the above is just wxT?
474  Internat::ToString(s.as_double(), 0),
477  }
478 
479  // Quick check to make sure that it doesn't overflow
480  if (Overflows((mNumSamples.as_double()) + (src->mNumSamples.as_double())))
481  {
482  wxLogError(
483  wxT("Sequence::Paste: mNumSamples %s + src->mNumSamples %s would overflow."),
484  // PRL: Why bother with Internat when the above is just wxT?
488  }
489 
490  if (src->mSampleFormat != mSampleFormat)
491  {
492  wxLogError(
493  wxT("Sequence::Paste: Sample format to be pasted, %s, does not match destination format, %s."),
496  }
497 
498  const BlockArray &srcBlock = src->mBlock;
499  auto addedLen = src->mNumSamples;
500  const unsigned int srcNumBlocks = srcBlock.size();
501  auto sampleSize = SAMPLE_SIZE(mSampleFormat);
502 
503  if (addedLen == 0 || srcNumBlocks == 0)
504  return;
505 
506  const size_t numBlocks = mBlock.size();
507 
508  if (numBlocks == 0 ||
509  (s == mNumSamples && mBlock.back().f->GetLength() >= mMinSamples)) {
510  // Special case: this track is currently empty, or it's safe to append
511  // onto the end because the current last block is longer than the
512  // minimum size
513 
514  // Build and swap a copy so there is a strong exception safety guarantee
515  BlockArray newBlock{ mBlock };
516  sampleCount samples = mNumSamples;
517  for (unsigned int i = 0; i < srcNumBlocks; i++)
518  // AppendBlock may throw for limited disk space, if pasting from
519  // one project into another.
520  AppendBlock(*mDirManager, newBlock, samples, srcBlock[i]);
521  // Increase ref count or duplicate file
522 
524  (newBlock, samples, wxT("Paste branch one"));
525  return;
526  }
527 
528  const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s);
529  wxASSERT((b >= 0) && (b < (int)numBlocks));
530  SeqBlock *const pBlock = &mBlock[b];
531  const auto length = pBlock->f->GetLength();
532  const auto largerBlockLen = addedLen + length;
533  // PRL: when insertion point is the first sample of a block,
534  // and the following test fails, perhaps we could test
535  // whether coalescence with the previous block is possible.
536  if (largerBlockLen <= mMaxSamples) {
537  // Special case: we can fit all of the NEW samples inside of
538  // one block!
539 
540  SeqBlock &block = *pBlock;
541  // largerBlockLen is not more than mMaxSamples...
542  SampleBuffer buffer(largerBlockLen.as_size_t(), mSampleFormat);
543 
544  // ...and addedLen is not more than largerBlockLen
545  auto sAddedLen = addedLen.as_size_t();
546  // s lies within block:
547  auto splitPoint = ( s - block.start ).as_size_t();
548  Read(buffer.ptr(), mSampleFormat, block, 0, splitPoint, true);
549  src->Get(0, buffer.ptr() + splitPoint*sampleSize,
550  mSampleFormat, 0, sAddedLen, true);
551  Read(buffer.ptr() + (splitPoint + sAddedLen) * sampleSize,
552  mSampleFormat, block,
553  splitPoint, length - splitPoint, true);
554 
555  auto file =
556  mDirManager->NewSimpleBlockFile(
557  // largerBlockLen is not more than mMaxSamples...
558  buffer.ptr(), largerBlockLen.as_size_t(), mSampleFormat);
559 
560  // Don't make a duplicate array. We can still give STRONG-GUARANTEE
561  // if we modify only one block in place.
562 
563  // use NOFAIL-GUARANTEE in remaining steps
564  block.f = file;
565 
566  for (unsigned int i = b + 1; i < numBlocks; i++)
567  mBlock[i].start += addedLen;
568 
569  mNumSamples += addedLen;
570 
571  // This consistency check won't throw, it asserts.
572  // Proof that we kept consistency is not hard.
573  ConsistencyCheck(wxT("Paste branch two"), false);
574  return;
575  }
576 
577  // Case three: if we are inserting four or fewer blocks,
578  // it's simplest to just lump all the data together
579  // into one big block along with the split block,
580  // then resplit it all
581  BlockArray newBlock;
582  newBlock.reserve(numBlocks + srcNumBlocks + 2);
583  newBlock.insert(newBlock.end(), mBlock.begin(), mBlock.begin() + b);
584 
585  SeqBlock &splitBlock = mBlock[b];
586  auto splitLen = splitBlock.f->GetLength();
587  // s lies within splitBlock
588  auto splitPoint = ( s - splitBlock.start ).as_size_t();
589 
590  unsigned int i;
591  if (srcNumBlocks <= 4) {
592 
593  // addedLen is at most four times maximum block size
594  auto sAddedLen = addedLen.as_size_t();
595  const auto sum = splitLen + sAddedLen;
596 
597  SampleBuffer sumBuffer(sum, mSampleFormat);
598  Read(sumBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint, true);
599  src->Get(0, sumBuffer.ptr() + splitPoint * sampleSize,
601  0, sAddedLen, true);
602  Read(sumBuffer.ptr() + (splitPoint + sAddedLen) * sampleSize, mSampleFormat,
603  splitBlock, splitPoint,
604  splitLen - splitPoint, true);
605 
606  Blockify(*mDirManager, mMaxSamples, mSampleFormat,
607  newBlock, splitBlock.start, sumBuffer.ptr(), sum);
608  } else {
609 
610  // The final case is that we're inserting at least five blocks.
611  // We divide these into three groups: the first two get merged
612  // with the first half of the split block, the middle ones get
613  // copied in as is, and the last two get merged with the last
614  // half of the split block.
615 
616  const auto srcFirstTwoLen =
617  srcBlock[0].f->GetLength() + srcBlock[1].f->GetLength();
618  const auto leftLen = splitPoint + srcFirstTwoLen;
619 
620  const SeqBlock &penultimate = srcBlock[srcNumBlocks - 2];
621  const auto srcLastTwoLen =
622  penultimate.f->GetLength() +
623  srcBlock[srcNumBlocks - 1].f->GetLength();
624  const auto rightSplit = splitBlock.f->GetLength() - splitPoint;
625  const auto rightLen = rightSplit + srcLastTwoLen;
626 
627  SampleBuffer sampleBuffer(std::max(leftLen, rightLen), mSampleFormat);
628 
629  Read(sampleBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint, true);
630  src->Get(0, sampleBuffer.ptr() + splitPoint*sampleSize,
631  mSampleFormat, 0, srcFirstTwoLen, true);
632 
633  Blockify(*mDirManager, mMaxSamples, mSampleFormat,
634  newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen);
635 
636  for (i = 2; i < srcNumBlocks - 2; i++) {
637  const SeqBlock &block = srcBlock[i];
638  auto file = mDirManager->CopyBlockFile(block.f);
639  // We can assume file is not null
640  newBlock.push_back(SeqBlock(file, block.start + s));
641  }
642 
643  auto lastStart = penultimate.start;
644  src->Get(srcNumBlocks - 2, sampleBuffer.ptr(), mSampleFormat,
645  lastStart, srcLastTwoLen, true);
646  Read(sampleBuffer.ptr() + srcLastTwoLen * sampleSize, mSampleFormat,
647  splitBlock, splitPoint, rightSplit, true);
648 
649  Blockify(*mDirManager, mMaxSamples, mSampleFormat,
650  newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
651  }
652 
653  // Copy remaining blocks to NEW block array and
654  // swap the NEW block array in for the old
655  for (i = b + 1; i < numBlocks; i++)
656  newBlock.push_back(mBlock[i].Plus(addedLen));
657 
659  (newBlock, mNumSamples + addedLen, wxT("Paste branch three"));
660 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
void CommitChangesIfConsistent(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
Definition: Sequence.cpp:1923
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
double as_double() const
Definition: Types.h:88
size_t mMinSamples
Definition: Sequence.h:235
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
Definition: Sequence.cpp:1865
#define THROW_INCONSISTENCY_EXCEPTION
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
Definition: Internat.cpp:138
static void AppendBlock(DirManager &dirManager, BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b)
Definition: Sequence.cpp:752
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
Definition: Sequence.cpp:1151
const wxChar * GetSampleFormatStr(sampleFormat format)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
static void Blockify(DirManager &dirManager, size_t maxSamples, sampleFormat format, BlockArray &list, sampleCount start, samplePtr buffer, size_t len)
Definition: Sequence.cpp:1662
bool Sequence::Read ( samplePtr  buffer,
sampleFormat  format,
const SeqBlock b,
size_t  blockRelativeStart,
size_t  len,
bool  mayThrow 
)
staticprivate

Definition at line 1130 of file Sequence.cpp.

References SeqBlock::f.

Referenced by Append(), ConvertToSampleFormat(), Delete(), Get(), GetWaveDisplay(), Paste(), and SetSamples().

1133 {
1134  const auto &f = b.f;
1135 
1136  wxASSERT(blockRelativeStart + len <= f->GetLength());
1137 
1138  // Either throws, or of !mayThrow, tells how many were really read
1139  auto result = f->ReadData(buffer, format, blockRelativeStart, len, mayThrow);
1140 
1141  if (result != len)
1142  {
1143  wxLogWarning(wxT("Expected to read %ld samples, got %ld samples."),
1144  len, result);
1145  return false;
1146  }
1147 
1148  return true;
1149 }
int format
Definition: ExportPCM.cpp:56
BlockFilePtr f
Definition: Sequence.h:33
void Sequence::SetMaxDiskBlockSize ( size_t  bytes)
static

Definition at line 2011 of file Sequence.cpp.

References sMaxDiskBlockSize.

Referenced by AudacityApp::OnInit(), and BenchmarkDialog::OnRun().

2012 {
2013  sMaxDiskBlockSize = bytes;
2014 }
static size_t sMaxDiskBlockSize
Definition: Sequence.h:221
void Sequence::SetSamples ( samplePtr  buffer,
sampleFormat  format,
sampleCount  start,
sampleCount  len 
)

Definition at line 1192 of file Sequence.cpp.

References SampleBuffer::Allocate(), ClearSamples(), CommitChangesIfConsistent(), CopySamples(), SeqBlock::f, FindBlock(), limitSampleBufferSize(), min(), mMaxSamples, mSampleFormat, DirManager::NewSimpleBlockFile(), SampleBuffer::ptr(), Read(), SAMPLE_SIZE, SeqBlock::start, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by SetSilence().

1195 {
1196  const auto size = mBlock.size();
1197 
1198  if (start < 0 || start + len > mNumSamples)
1200 
1201  size_t tempSize = mMaxSamples;
1202  // to do: allocate this only on demand
1203  SampleBuffer scratch(tempSize, mSampleFormat);
1204 
1205  SampleBuffer temp;
1206  if (buffer && format != mSampleFormat) {
1207  temp.Allocate(tempSize, mSampleFormat);
1208  }
1209 
1210  int b = FindBlock(start);
1211  BlockArray newBlock;
1212  std::copy( mBlock.begin(), mBlock.begin() + b, std::back_inserter(newBlock) );
1213 
1214  while (len > 0
1215  // Redundant termination condition,
1216  // but it guards against infinite loop in case of inconsistencies
1217  // (too-small files, not yet seen?)
1218  // that cause the loop to make no progress because blen == 0
1219  && b < (int)size
1220  ) {
1221  newBlock.push_back( mBlock[b] );
1222  SeqBlock &block = newBlock.back();
1223  // start is within block
1224  const auto bstart = ( start - block.start ).as_size_t();
1225  const auto fileLength = block.f->GetLength();
1226 
1227  // the std::min is a guard against inconsistent Sequence
1228  const auto blen =
1229  limitSampleBufferSize( fileLength - std::min( bstart, fileLength ),
1230  len );
1231  wxASSERT(blen == 0 || bstart + blen <= fileLength);
1232 
1233 #if 0
1234  // PRL: This inconsistency (too-big file) has been seen in "the wild"
1235  // in 2.2.0. It is the least problematic kind of inconsistency.
1236  // We will tolerate it for 2.2.1.
1237  // Not known whether it is only in projects saved in earlier versions.
1238  // After 2.2.1, we should detect and correct it at file loading time.
1239  if (fileLength > mMaxSamples) {
1241  }
1242 #endif
1243 
1244  ensureSampleBufferSize(scratch, mSampleFormat, tempSize, fileLength,
1245  &temp);
1246 
1247  samplePtr useBuffer = buffer;
1248  if (buffer && format != mSampleFormat)
1249  {
1250  // To do: remove the extra movement.
1251  // Note: we ensured temp can hold fileLength. blen is not more
1252  CopySamples(buffer, format, temp.ptr(), mSampleFormat, blen);
1253  useBuffer = temp.ptr();
1254  }
1255 
1256  // We don't ever write to an existing block; to support Undo,
1257  // we copy the old block entirely into memory, dereference it,
1258  // make the change, and then write the NEW block to disk.
1259 
1260  if ( bstart > 0 || blen < fileLength ) {
1261  // First or last block is only partially overwritten
1262  Read(scratch.ptr(), mSampleFormat, block, 0, fileLength, true);
1263 
1264  if (useBuffer) {
1265  auto sampleSize = SAMPLE_SIZE(mSampleFormat);
1266  memcpy(scratch.ptr() +
1267  bstart * sampleSize, useBuffer, blen * sampleSize);
1268  }
1269  else
1270  ClearSamples(scratch.ptr(), mSampleFormat, bstart, blen);
1271 
1272  block.f = mDirManager->NewSimpleBlockFile(
1273  scratch.ptr(), fileLength, mSampleFormat);
1274  }
1275  else {
1276  // Avoid reading the disk when the replacement is total
1277  if (useBuffer)
1278  block.f = mDirManager->NewSimpleBlockFile(
1279  useBuffer, fileLength, mSampleFormat);
1280  else
1281  block.f = make_blockfile<SilentBlockFile>(fileLength);
1282  }
1283 
1284  // blen might be zero for inconsistent Sequence...
1285  if( buffer )
1286  buffer += (blen * SAMPLE_SIZE(format));
1287 
1288  len -= blen;
1289  start += blen;
1290 
1291  // ... but this, at least, always guarantees some loop progress:
1292  b++;
1293  }
1294 
1295  std::copy( mBlock.begin() + b, mBlock.end(), std::back_inserter(newBlock) );
1296 
1297  CommitChangesIfConsistent( newBlock, mNumSamples, wxT("SetSamples") );
1298 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
void CommitChangesIfConsistent(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
Definition: Sequence.cpp:1923
std::shared_ptr< DirManager > mDirManager
Definition: Sequence.h:227
size_t mMaxSamples
Definition: Sequence.h:236
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
SampleBuffer & Allocate(size_t count, sampleFormat format)
Definition: SampleFormat.h:67
#define THROW_INCONSISTENCY_EXCEPTION
int FindBlock(sampleCount pos) const
Definition: Sequence.cpp:1080
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: Types.h:178
int format
Definition: ExportPCM.cpp:56
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
Definition: Sequence.cpp:1130
char * samplePtr
Definition: Types.h:203
int min(int a, int b)
samplePtr ptr() const
Definition: SampleFormat.h:81
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230
void Sequence::SetSilence ( sampleCount  s0,
sampleCount  len 
)

Definition at line 662 of file Sequence.cpp.

References mSampleFormat, and SetSamples().

Referenced by WaveTrack::Silence().

664 {
665  SetSamples(NULL, mSampleFormat, s0, len);
666 }
sampleFormat mSampleFormat
Definition: Sequence.h:230
void SetSamples(samplePtr buffer, sampleFormat format, sampleCount start, sampleCount len)
Definition: Sequence.cpp:1192
bool Sequence::Unlock ( )

Definition at line 109 of file Sequence.cpp.

References mBlock.

110 {
111  for (unsigned int i = 0; i < mBlock.size(); i++)
112  mBlock[i].f->Unlock();
113 
114  return true;
115 }
BlockArray mBlock
Definition: Sequence.h:229
void Sequence::UnlockDeleteUpdateMutex ( )
inline

Definition at line 198 of file Sequence.h.

Referenced by ODDecodeTask::Update().

198 {mDeleteUpdateMutex.Unlock();}
ODLock mDeleteUpdateMutex
To block the Delete() method against the ODCalcSummaryTask::Update() method.
Definition: Sequence.h:241
void Sequence::WriteXML ( XMLWriter xmlFile) const

Definition at line 1035 of file Sequence.cpp.

References _(), sampleCount::as_long_long(), AudacityMessageBox(), SeqBlock::f, SeqBlock::start, and Internat::ToString().

1037 {
1038  unsigned int b;
1039 
1040  xmlFile.StartTag(wxT("sequence"));
1041 
1042  xmlFile.WriteAttr(wxT("maxsamples"), mMaxSamples);
1043  xmlFile.WriteAttr(wxT("sampleformat"), (size_t)mSampleFormat);
1044  xmlFile.WriteAttr(wxT("numsamples"), mNumSamples.as_long_long() );
1045 
1046  for (b = 0; b < mBlock.size(); b++) {
1047  const SeqBlock &bb = mBlock[b];
1048 
1049  // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451.
1050  // Also, don't check against mMaxSamples for AliasBlockFiles, because if you convert sample format,
1051  // mMaxSample gets changed to match the format, but the number of samples in the aliased file
1052  // has not changed (because sample format conversion was not actually done in the aliased file).
1053  if (!bb.f->IsAlias() && (bb.f->GetLength() > mMaxSamples))
1054  {
1055  // PRL: Bill observed this error. Not sure how it was caused.
1056  // I have added code in ConsistencyCheck that should abort the
1057  // editing operation that caused this, not fixing
1058  // the problem but moving the point of detection earlier if we
1059  // find a reproducible case.
1060  wxString sMsg =
1061  wxString::Format(
1062  _("Sequence has block file exceeding maximum %s samples per block.\nTruncating to this maximum length."),
1063  Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0));
1064  AudacityMessageBox(sMsg, _("Warning - Truncating Overlong Block File"), wxICON_EXCLAMATION | wxOK);
1065  wxLogWarning(sMsg);
1066  bb.f->SetLength(mMaxSamples);
1067  }
1068 
1069  xmlFile.StartTag(wxT("waveblock"));
1070  xmlFile.WriteAttr(wxT("start"), bb.start.as_long_long() );
1071 
1072  bb.f->SaveXML(xmlFile);
1073 
1074  xmlFile.EndTag(wxT("waveblock"));
1075  }
1076 
1077  xmlFile.EndTag(wxT("sequence"));
1078 }
Data structure containing pointer to a BlockFile and a start time. Element of a BlockArray.
Definition: Sequence.h:31
sampleCount mNumSamples
Definition: Sequence.h:233
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:78
virtual void WriteAttr(const wxString &name, const wxString &value)
Definition: XMLWriter.cpp:131
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:101
size_t mMaxSamples
Definition: Sequence.h:236
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:35
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
Definition: Internat.cpp:138
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
long long as_long_long() const
Definition: Types.h:90
BlockFilePtr f
Definition: Sequence.h:33
BlockArray mBlock
Definition: Sequence.h:229
sampleFormat mSampleFormat
Definition: Sequence.h:230

Member Data Documentation

BlockArray Sequence::mBlock
private
ODLock Sequence::mDeleteUpdateMutex
private

To block the Delete() method against the ODCalcSummaryTask::Update() method.

Definition at line 241 of file Sequence.h.

std::shared_ptr<DirManager> Sequence::mDirManager
private

Definition at line 227 of file Sequence.h.

Referenced by AppendAlias(), AppendCoded(), ConvertToSampleFormat(), Copy(), InsertSilence(), and Paste().

bool Sequence::mErrorOpening { false }
private

Definition at line 238 of file Sequence.h.

Referenced by HandleXMLEndTag(), and HandleXMLTag().

size_t Sequence::mMaxSamples
private
size_t Sequence::mMinSamples
private

Definition at line 235 of file Sequence.h.

Referenced by Append(), ConvertToSampleFormat(), Delete(), GetBestBlockSize(), and Paste().

sampleCount Sequence::mNumSamples { 0 }
private
sampleFormat Sequence::mSampleFormat
private
size_t Sequence::sMaxDiskBlockSize = 1048576
staticprivate

Definition at line 221 of file Sequence.h.

Referenced by ConvertToSampleFormat(), GetMaxDiskBlockSize(), and SetMaxDiskBlockSize().


The documentation for this class was generated from the following files: