57 mSampleFormats{ formats },
58 mMinSamples(sMaxDiskBlockSize /
SAMPLE_SIZE(mSampleFormats.Stored()) / 2),
59 mMaxSamples(mMinSamples * 2)
69 mSampleFormats{ orig.mSampleFormats },
70 mMinSamples(orig.mMinSamples),
71 mMaxSamples(orig.mMaxSamples)
92 for (
unsigned int i = 0; i <
mBlock.size(); i++)
116 size_t &
size,
size_t required,
122 if (
size < required) {
125 if (pSecondBuffer && pSecondBuffer->ptr())
127 if (!buffer.
ptr() || (pSecondBuffer && !pSecondBuffer->ptr())) {
141 const std::function<
void(
size_t)> & progressReport)
166 bool bSuccess =
false;
167 auto cleanup =
finally( [&] {
179 newBlockArray.reserve
183 size_t oldSize = oldMaxSamples;
185 size_t newSize = oldMaxSamples;
188 for (
size_t i = 0, nn =
mBlock.size(); i < nn; i++)
191 const auto &oldBlockFile = oldSeqBlock.
sb;
192 const auto len = oldBlockFile->GetSampleCount();
196 Read(bufferOld.
ptr(), oldFormats.Stored(), oldSeqBlock, 0, len,
true);
201 bufferOld.
ptr(), oldFormats.Stored(), bufferNew.
ptr(),
format, len,
205 format < oldFormats.Effective()
219 const auto blockstart = oldSeqBlock.
start;
221 newBlockArray, blockstart, bufferNew.
ptr(), len);
233 (newBlockArray,
mNumSamples,
wxT(
"Sequence::ConvertToSampleFormat()"));
244 if (len == 0 ||
mBlock.size() == 0) {
255 float max = -FLT_MAX;
258 unsigned int block1 =
FindBlock(start + len - 1);
264 for (
unsigned b = block0 + 1; b < block1; ++b) {
265 auto results =
mBlock[b].sb->GetMinMaxRMS(mayThrow);
267 if (results.min <
min)
269 if (results.max > max)
279 const auto &theFile = theBlock.
sb;
280 auto results = theFile->GetMinMaxRMS(mayThrow);
282 if (results.min <
min || results.max > max) {
284 auto s0 = ( start - theBlock.
start ).as_size_t();
287 theBlock.
start + theFile->GetSampleCount() - start
292 results = theFile->GetMinMaxRMS(s0, l0, mayThrow);
293 if (results.min <
min)
295 if (results.max > max)
303 const auto &theFile = theBlock.
sb;
304 auto results = theFile->GetMinMaxRMS(mayThrow);
306 if (results.min <
min || results.max > max) {
309 const auto l0 = ( start + len - theBlock.
start ).as_size_t();
312 results = theFile->GetMinMaxRMS(0, l0, mayThrow);
313 if (results.min <
min)
315 if (results.max > max)
327 if (len == 0 ||
mBlock.size() == 0)
334 unsigned int block1 =
FindBlock(start + len - 1);
339 for (
unsigned b = block0 + 1; b < block1; b++) {
341 const auto &sb = theBlock.
sb;
342 auto results = sb->GetMinMaxRMS(mayThrow);
344 const auto fileLen = sb->GetSampleCount();
345 const auto blockRMS = results.RMS;
346 sumsq += blockRMS * blockRMS * fileLen;
355 const auto &sb = theBlock.
sb;
357 auto s0 = ( start - theBlock.
start ).as_size_t();
360 (theBlock.
start + sb->GetSampleCount() - start).as_size_t();
364 auto results = sb->GetMinMaxRMS(s0, l0, mayThrow);
365 const auto partialRMS = results.RMS;
366 sumsq += partialRMS * partialRMS * l0;
370 if (block1 > block0) {
372 const auto &sb = theBlock.
sb;
375 const auto l0 = ( start + len - theBlock.
start ).as_size_t();
378 auto results = sb->GetMinMaxRMS(0, l0, mayThrow);
379 const auto partialRMS = results.RMS;
380 sumsq += partialRMS * partialRMS * l0;
385 wxASSERT(length == len);
403 auto pUseFactory = (pFactory ==
mpFactory) ?
nullptr : pFactory.get();
405 int numBlocks =
mBlock.size();
410 wxASSERT(b0 < numBlocks);
411 wxASSERT(b1 < numBlocks);
412 wxUnusedVar(numBlocks);
415 dest->mBlock.reserve(b1 - b0 + 1);
426 if (s0 != block0.
start) {
427 const auto &sb = block0.
sb;
430 (
std::min(s1, block0.
start + sb->GetSampleCount()) - s0 ).as_size_t();
443 for (
int bb = b0 + 1; bb < b1; ++bb)
445 dest->mBlock, dest->mNumSamples,
mBlock[bb]);
452 const auto &sb = block.
sb;
454 blocklen = (s1 - block.
start).as_size_t();
456 if (blocklen < (
int)sb->GetSampleCount()) {
466 dest->mBlock, dest->mNumSamples, block);
470 dest->ConsistencyCheck(
wxT(
"Sequence::Copy()"));
478 return numSamples > wxLL(9223372036854775807);
504 wxT(
"Sequence::Paste: sampleCount s %s is < 0 or > mNumSamples %s)."),
515 wxT(
"Sequence::Paste: mNumSamples %s + src->mNumSamples %s would overflow."),
526 wxT(
"Sequence::Paste: Sample format to be pasted, %s, does not match destination format, %s."),
534 const unsigned int srcNumBlocks = srcBlock.size();
537 if (addedLen == 0 || srcNumBlocks == 0)
540 const size_t numBlocks =
mBlock.size();
547 if (numBlocks == 0 ||
556 for (
unsigned int i = 0; i < srcNumBlocks; i++)
560 newBlock, samples, srcBlock[i]);
563 (newBlock, samples,
wxT(
"Paste branch one"));
569 wxASSERT((b >= 0) && (b < (
int)numBlocks));
571 const auto length = pBlock->
sb->GetSampleCount();
572 const auto largerBlockLen = addedLen + length;
585 auto sAddedLen = addedLen.as_size_t();
587 auto splitPoint = ( s - block.
start ).as_size_t();
589 src->
Get(0, buffer.
ptr() + splitPoint*sampleSize,
590 format, 0, sAddedLen,
true);
591 Read(buffer.
ptr() + (splitPoint + sAddedLen) * sampleSize,
593 splitPoint, length - splitPoint,
true);
598 largerBlockLen.as_size_t(),
605 for (
unsigned int i = b + 1; i < numBlocks; i++)
606 mBlock[i].start += addedLen;
622 newBlock.reserve(numBlocks + srcNumBlocks + 2);
623 newBlock.insert(newBlock.end(),
mBlock.begin(),
mBlock.begin() + b);
626 auto splitLen = splitBlock.
sb->GetSampleCount();
628 auto splitPoint = ( s - splitBlock.
start ).as_size_t();
631 if (srcNumBlocks <= 4) {
634 auto sAddedLen = addedLen.as_size_t();
635 const auto sum = splitLen + sAddedLen;
638 Read(sumBuffer.
ptr(),
format, splitBlock, 0, splitPoint,
true);
639 src->
Get(0, sumBuffer.
ptr() + splitPoint * sampleSize,
642 Read(sumBuffer.
ptr() + (splitPoint + sAddedLen) * sampleSize,
format,
643 splitBlock, splitPoint,
644 splitLen - splitPoint,
true);
647 newBlock, splitBlock.
start, sumBuffer.
ptr(), sum);
656 const auto srcFirstTwoLen =
657 srcBlock[0].sb->GetSampleCount() + srcBlock[1].sb->GetSampleCount();
658 const auto leftLen = splitPoint + srcFirstTwoLen;
660 const SeqBlock &penultimate = srcBlock[srcNumBlocks - 2];
661 const auto srcLastTwoLen =
662 penultimate.
sb->GetSampleCount() +
663 srcBlock[srcNumBlocks - 1].sb->GetSampleCount();
664 const auto rightSplit = splitBlock.
sb->GetSampleCount() - splitPoint;
665 const auto rightLen = rightSplit + srcLastTwoLen;
669 Read(sampleBuffer.
ptr(),
format, splitBlock, 0, splitPoint,
true);
670 src->
Get(0, sampleBuffer.
ptr() + splitPoint*sampleSize,
671 format, 0, srcFirstTwoLen,
true);
674 newBlock, splitBlock.
start, sampleBuffer.
ptr(), leftLen);
676 for (i = 2; i < srcNumBlocks - 2; i++) {
677 const SeqBlock &block = srcBlock[i];
683 auto lastStart = penultimate.
start;
685 lastStart, srcLastTwoLen,
true);
686 Read(sampleBuffer.
ptr() + srcLastTwoLen * sampleSize,
format,
687 splitBlock, splitPoint, rightSplit,
true);
690 newBlock, s + lastStart, sampleBuffer.
ptr(), rightLen);
695 for (i = b + 1; i < numBlocks; i++)
696 newBlock.push_back(
mBlock[i].Plus(addedLen));
734 auto nBlocks = (len + idealSamples - 1) / idealSamples;
735 sTrack.mBlock.reserve(nBlocks.as_size_t());
738 if (len >= idealSamples) {
739 auto silentFile =
factory.CreateSilent(
742 while (len >= idealSamples) {
743 sTrack.mBlock.push_back(
SeqBlock(silentFile, pos));
756 sTrack.mNumSamples = pos;
774 mBlock.push_back(newBlock);
798 int numBlocks =
mBlock.size();
802 auto result = (block.
start + block.
sb->GetSampleCount() - start).as_size_t();
804 decltype(result) length;
833 if (wb.
sb ==
nullptr)
840 for (
auto pair : attrs)
842 auto attr = pair.first;
843 auto value = pair.second;
850 if (!value.TryGet(start))
868 std::optional<sampleFormat> effective;
870 for (
auto pair : attrs)
872 auto attr = pair.first;
873 auto value = pair.second;
875 long long nValue = 0;
880 if (!value.TryGet(nValue))
889 if ((nValue < 1024) || (nValue > 64 * 1024 * 1024))
925 if (!value.TryGet(nValue) || (nValue < 0))
962 for (
unsigned b = 0, nn =
mBlock.size(); b < nn; b++)
965 if (block.
start != numSamples)
968 wxT(
"Gap detected in project file.\n")
969 wxT(
" Start (%s) for block file %lld is not one sample past end of previous block (%s).\n")
970 wxT(
" Moving start so blocks are contiguous."),
973 block.
sb->GetBlockID(),
975 block.
start = numSamples;
978 numSamples += block.
sb->GetSampleCount();
984 wxT(
"Gap detected in project file. Correcting sequence sample count from %s to %s."),
1009 xmlFile.StartTag(Sequence_tag);
1013 static_cast<size_t>( mSampleFormats.Stored() ) );
1016 static_cast<size_t>( mSampleFormats.Effective() ));
1019 for (b = 0; b < mBlock.size(); b++) {
1023 if (bb.
sb->GetSampleCount() > mMaxSamples)
1032 XO(
"Sequence has block file exceeding maximum %s samples per block.\nTruncating to this maximum length.")
1037 .
Caption(
XO(
"Warning - Truncating Overlong Block File"))
1038 .IconStyle(Icon::Warning)
1039 .ButtonStyle(Button::Ok));
1040 wxLogWarning(sMsg.Translation());
1044 xmlFile.StartTag(WaveBlock_tag);
1047 bb.
sb->SaveXML(xmlFile);
1049 xmlFile.EndTag(WaveBlock_tag);
1052 xmlFile.EndTag(Sequence_tag);
1062 int numBlocks =
mBlock.size();
1064 size_t lo = 0, hi = numBlocks, guess;
1071 const double frac = (pos - loSamples).as_double() /
1072 (hiSamples - loSamples).as_double();
1073 guess =
std::min(hi - 1, lo +
size_t(frac * (hi - lo)));
1076 wxASSERT(block.
sb->GetSampleCount() > 0);
1077 wxASSERT(lo <= guess && guess < hi && lo < hi);
1079 if (pos < block.
start) {
1080 wxASSERT(lo != guess);
1082 hiSamples = block.
start;
1086 if (pos < nextStart)
1089 wxASSERT(guess < hi - 1);
1091 loSamples = nextStart;
1096 const int rval = guess;
1097 wxASSERT(rval >= 0 && rval < numBlocks &&
1098 pos >=
mBlock[rval].start &&
1099 pos <
mBlock[rval].start +
mBlock[rval].sb->GetSampleCount());
1106 const SeqBlock &b,
size_t blockRelativeStart,
size_t len,
1109 const auto &sb = b.
sb;
1111 wxASSERT(blockRelativeStart + len <= sb->GetSampleCount());
1114 auto result = sb->GetSamples(buffer,
format, blockRelativeStart, len, mayThrow);
1118 wxLogWarning(
wxT(
"Expected to read %ld samples, got %ld samples."),
1127 sampleCount start,
size_t length,
bool mayThrow)
const
1131 std::vector<BlockSampleView> blockViews;
1134 const auto sequenceOffset = (start -
GetBlockStart(start)).as_size_t();
1135 auto cursor = start;
1136 while (cursor < start + length)
1140 blockViews.push_back(block.
sb->GetFloatSampleView(mayThrow));
1141 cursor = block.
start + block.
sb->GetSampleCount();
1143 return { std::move(blockViews), sequenceOffset, length };
1147 sampleCount start,
size_t len,
bool mayThrow)
const
1150 bool outOfBounds =
false;
1158 buffer += fillLen * sampleSize;
1172 const auto excess = (start + len -
mNumSamples).as_size_t();
1181 return Get(b, buffer,
format, start, len, mayThrow) &&
1186 sampleCount start,
size_t len,
bool mayThrow)
const
1192 const auto bstart = (start - block.
start).as_size_t();
1194 const auto blen =
std::min(len, block.
sb->GetSampleCount() - bstart);
1196 if (!
Read(buffer,
format, block, bstart, blen, mayThrow) )
1226 if (buffer &&
format != dstFormat) {
1227 temp.
Allocate(tempSize, dstFormat);
1241 newBlock.push_back(
mBlock[b] );
1244 const auto bstart = ( start - block.
start ).as_size_t();
1245 const auto fileLength = block.
sb->GetSampleCount();
1251 wxASSERT(blen == 0 || bstart + blen <= fileLength);
1267 auto useBuffer = buffer;
1268 if (buffer &&
format != dstFormat)
1273 (dstFormat < effectiveFormat
1275 useBuffer = temp.
ptr();
1282 if ( bstart > 0 || blen < fileLength ) {
1284 Read(scratch.
ptr(), dstFormat, block, 0, fileLength,
true);
1288 memcpy(scratch.
ptr() +
1289 bstart * sampleSize, useBuffer, blen * sampleSize);
1302 block.
sb =
factory.Create(useBuffer, fileLength, dstFormat);
1304 block.
sb =
factory.CreateSilent(fileLength, dstFormat);
1327 int numBlocks =
mBlock.size();
1333 const auto lastBlockLen =
mBlock.back().sb->GetSampleCount();
1334 if (lastBlockLen >= max)
1337 return max - lastBlockLen;
1354 auto len = pBlock->GetSampleCount();
1365 newNumSamples,
wxT(
"Append"));
1370#ifdef VERY_SLOW_CHECKING
1385 bool result =
false;
1449 int numBlocks =
mBlock.size();
1451 decltype(pLastBlock->
sb->GetSampleCount()) length;
1455 bool replaceLast =
false;
1461 const SeqBlock &lastBlock = *pLastBlock;
1465 Read(buffer2.
ptr(), dstFormat, lastBlock, 0, length,
true);
1473 const auto newLastBlockLen = length + addLen;
1480 newBlock.push_back( newLastBlock );
1483 newNumSamples += addLen;
1491 const auto addedLen =
std::min(idealSamples, len);
1493 if (
format == dstFormat) {
1494 pBlock =
factory.Create(buffer, addedLen, dstFormat);
1497 wxASSERT( coalesce || !result );
1503 pBlock =
factory.Create(buffer2.
ptr(), addedLen, dstFormat);
1506 newBlock.push_back(
SeqBlock(pBlock, newNumSamples));
1509 newNumSamples += addedLen;
1514 newNumSamples,
wxT(
"Append"));
1519#ifdef VERY_SLOW_CHECKING
1535 auto cleanup =
finally( [&] {
1562 list.reserve(list.size() + num);
1564 for (
decltype(num) i = 0; i < num; i++) {
1567 const auto offset = i * len / num;
1568 b.
start = start + offset;
1569 int newLen = ((i + 1) * len / num) - offset;
1570 auto bufStart = buffer + (offset *
SAMPLE_SIZE(mSampleFormat));
1572 b.
sb =
factory.Create(bufStart, newLen, mSampleFormat);
1584 if (len < 0 || start < 0 || start + len >
mNumSamples)
1589 const unsigned int numBlocks =
mBlock.size();
1591 const unsigned int b0 =
FindBlock(start);
1592 unsigned int b1 =
FindBlock(start + len - 1);
1598 decltype(pBlock->
sb->GetSampleCount()) length;
1612 auto pos = ( start - b.
start ).as_size_t();
1615 wxASSERT(len < length);
1629 ( pos + len ).as_size_t(), newLen - pos,
true);
1638 for (
unsigned int j = b0 + 1; j < numBlocks; j++)
1651 newBlock.reserve(numBlocks - (b1 - b0) + 2);
1655 newBlock.insert(newBlock.end(),
mBlock.begin(),
mBlock.begin() + b0);
1665 auto preBufferLen = ( start - preBlock.
start ).as_size_t();
1671 Read(scratch.
ptr(),
format, preBlock, 0, preBufferLen,
true);
1678 const auto prepreLen = prepreBlock.
sb->GetSampleCount();
1679 const auto sum = prepreLen + preBufferLen;
1686 Read(scratch.
ptr(),
format, prepreBlock, 0, prepreLen,
true);
1688 preBlock, 0, preBufferLen,
true);
1690 newBlock.pop_back();
1692 newBlock, prepreBlock.
start, scratch.
ptr(), sum);
1707 const auto postBufferLen = (
1708 (postBlock.
start + postBlock.
sb->GetSampleCount()) - (start + len)
1710 if (postBufferLen) {
1711 if (postBufferLen >=
mMinSamples || b1 == numBlocks - 1) {
1716 auto pos = (start + len - postBlock.
start).as_size_t();
1717 Read(scratch.
ptr(),
format, postBlock, pos, postBufferLen,
true);
1721 newBlock.push_back(
SeqBlock(file, start));
1724 const auto postpostLen = postpostBlock.
sb->GetSampleCount();
1725 const auto sum = postpostLen + postBufferLen;
1731 auto pos = (start + len - postBlock.
start).as_size_t();
1732 Read(scratch.
ptr(),
format, postBlock, pos, postBufferLen,
true);
1734 postpostBlock, 0, postpostLen,
true);
1737 newBlock, start, scratch.
ptr(), sum);
1747 for (i = b1 + 1; i < numBlocks; i++)
1748 newBlock.push_back(
mBlock[i].Plus(-len));
1760 (
const BlockArray &mBlock,
size_t maxSamples,
size_t from,
1762 bool WXUNUSED(mayThrow))
1766 std::optional<InconsistencyException> ex;
1768 unsigned int numBlocks =
mBlock.size();
1772 if ( from == 0 && pos != 0 )
1775 for (i = from; !ex && i < numBlocks; i++) {
1777 if (pos != seqBlock.
start)
1780 if ( seqBlock.
sb ) {
1781 const auto length = seqBlock.
sb->GetSampleCount();
1782 if (length > maxSamples)
1794 wxLogError(
wxT(
"*** Consistency check failed at %d after %s. ***"),
1795 ex->GetLine(), whereStr);
1798 wxLogError(
wxT(
"%s"),
str);
1799 wxLogError(
wxT(
"*** Please report this error to https://forum.audacityteam.org/. ***\n\n")
1800 wxT(
"Recommended course of action:\n")
1801 wxT(
"Undo the failed operation(s), then export or save your work and quit."));
1823(
BlockArray &additionalBlocks,
bool replaceLast,
1829 if (additionalBlocks.empty())
1832 bool tmpValid =
false;
1835 if ( replaceLast && !
mBlock.empty() ) {
1836 tmp =
mBlock.back(), tmpValid =
true;
1840 auto prevSize =
mBlock.size();
1842 bool consistent =
false;
1843 auto cleanup =
finally( [&] {
1844 if ( !consistent ) {
1845 mBlock.resize( prevSize );
1851 std::copy( additionalBlocks.begin(), additionalBlocks.end(),
1852 std::back_inserter(
mBlock ) );
1871 for (i = 0; i <
mBlock.size(); i++) {
1873 *dest += wxString::Format
1874 (
wxT(
" Block %3u: start %8lld, len %8lld, refs %ld, id %lld"),
1877 seqBlock.
sb ? (
long long) seqBlock.
sb->GetSampleCount() : 0,
1878 seqBlock.
sb ? seqBlock.
sb.use_count() : 0,
1879 seqBlock.
sb ? (
long long) seqBlock.
sb->GetBlockID() : 0);
1881 if ((pos != seqBlock.
start) || !seqBlock.
sb)
1882 *dest +=
wxT(
" ERROR\n");
1887 pos += seqBlock.
sb->GetSampleCount();
1890 *dest += wxString::Format
Toolkit-neutral facade for basic user interface services.
std::shared_ptr< SampleBlock > SampleBlockPtr
MessageBoxException for violation of preconditions or assertions.
#define CONSTRUCT_INCONSISTENCY_EXCEPTION
Construct InconsistencyException, using C++ preprocessor to identify the source code location.
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
std::shared_ptr< SampleBlockFactory > SampleBlockFactoryPtr
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
static constexpr auto Start_attr
static constexpr auto NumSamples_attr
static constexpr auto SampleFormat_attr
static constexpr auto EffectiveSampleFormat_attr
static constexpr auto MaxSamples_attr
std::vector< Attribute > AttributesList
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
abstract base class with methods to produce SampleBlock objects
SampleBlockPtr Create(constSamplePtr src, size_t numsamples, sampleFormat srcformat)
SampleBuffer & Allocate(size_t count, sampleFormat format)
Data structure containing pointer to a sample block and a start time. Element of a BlockArray.
sampleCount start
the sample in the global wavetrack that this block starts at.
std::shared_ptr< SampleBlock > SampleBlockPtr
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
AudioSegmentSampleView GetFloatSampleView(sampleCount start, size_t len, bool mayThrow) const
static void SetMaxDiskBlockSize(size_t bytes)
void AppendBlocksIfConsistent(BlockArray &additionalBlocks, bool replaceLast, sampleCount numSamples, const wxChar *whereStr)
void AppendSharedBlock(const SeqBlock::SampleBlockPtr &pBlock)
Append a complete block, not coalescing.
size_t GetMaxBlockSize() const
SampleFormats GetSampleFormats() const
size_t GetBestBlockSize(sampleCount start) const
bool ConvertToSampleFormat(sampleFormat format, const std::function< void(size_t)> &progressReport={})
Sequence(const SampleBlockFactoryPtr &pFactory, SampleFormats formats)
void HandleXMLEndTag(const std::string_view &tag) override
SeqBlock::SampleBlockPtr AppendNewBlock(constSamplePtr buffer, sampleFormat format, size_t len)
void Delete(sampleCount start, sampleCount len)
void SetSamples(constSamplePtr buffer, sampleFormat format, sampleCount start, sampleCount len, sampleFormat effectiveFormat)
Pass nullptr to set silence.
void Paste(sampleCount s0, const Sequence *src)
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
std::unique_ptr< Sequence > Copy(const SampleBlockFactoryPtr &pFactory, sampleCount s0, sampleCount s1) const
void CommitChangesIfConsistent(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr)
size_t GetIdealBlockSize() const
void ConsistencyCheck(const wxChar *whereStr, bool mayThrow=true) const
bool Get(samplePtr buffer, sampleFormat format, sampleCount start, size_t len, bool mayThrow) const
Get a range of samples from the sequence.
SampleBlockFactoryPtr mpFactory
static size_t sMaxDiskBlockSize
static const char * Sequence_tag
sampleFormat mAppendEffectiveFormat
void InsertSilence(sampleCount s0, sampleCount len)
void SetSilence(sampleCount s0, sampleCount len)
static void AppendBlock(SampleBlockFactory *pFactory, sampleFormat format, BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b)
static size_t GetMaxDiskBlockSize()
sampleCount GetBlockStart(sampleCount position) const
static const char * WaveBlock_tag
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
static bool IsValidSampleFormat(const int nValue)
true if nValue is one of the sampleFormat enum values
static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow)
float GetRMS(sampleCount start, sampleCount len, bool mayThrow) const
static void DebugPrintf(const BlockArray &block, sampleCount numSamples, wxString *dest)
SeqBlock::SampleBlockPtr DoAppend(constSamplePtr buffer, sampleFormat format, size_t len, bool coalesce)
Does not do any dithering.
bool Append(constSamplePtr buffer, sampleFormat format, size_t len, size_t stride, sampleFormat effectiveFormat)
int FindBlock(sampleCount pos) const
static void Blockify(SampleBlockFactory &factory, size_t maxSamples, sampleFormat format, BlockArray &list, sampleCount start, constSamplePtr buffer, size_t len)
void WriteXML(XMLWriter &xmlFile) const
std::pair< float, float > GetMinMax(sampleCount start, sampleCount len, bool mayThrow) const
size_t GetIdealAppendLen() const
SampleBuffer mAppendBuffer
SampleFormats mSampleFormats
bool CloseLock() noexcept
Should be called upon project close. Not balanced by unlocking calls.
wxString Debug() const
Format as an English string for debugging logs and developers' eyes, not for end users.
This class is an interface which should be implemented by classes which wish to be able to load and s...
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Positions or offsets within audio files need a wide type.
long long as_long_long() const
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
void ensureSampleBufferSize(SampleBuffer &buffer, sampleFormat format, size_t &size, size_t required, SampleBuffer *pSecondBuffer=nullptr)
bool Overflows(double numSamples)
SampleBlockPtr ShareOrCopySampleBlock(SampleBlockFactory *pFactory, sampleFormat format, SampleBlockPtr sb)
__finl float_x4 __vecc sqrt(const float_x4 &a)
void copy(const T *src, T *dst, int32_t n)
MessageBoxOptions && Caption(TranslatableString caption_) &&