54 mSampleFormats{ formats },
55 mMinSamples(sMaxDiskBlockSize /
SAMPLE_SIZE(mSampleFormats.Stored()) / 2),
56 mMaxSamples(mMinSamples * 2)
66 mSampleFormats{ orig.mSampleFormats },
67 mMinSamples(orig.mMinSamples),
68 mMaxSamples(orig.mMaxSamples)
89 for (
unsigned int i = 0; i <
mBlock.size(); i++)
113 size_t &
size,
size_t required,
119 if (
size < required) {
122 if (pSecondBuffer && pSecondBuffer->ptr())
124 if (!buffer.
ptr() || (pSecondBuffer && !pSecondBuffer->ptr())) {
138 const std::function<
void(
size_t)> & progressReport)
163 bool bSuccess =
false;
164 auto cleanup =
finally( [&] {
176 newBlockArray.reserve
180 size_t oldSize = oldMaxSamples;
182 size_t newSize = oldMaxSamples;
185 for (
size_t i = 0, nn =
mBlock.size(); i < nn; i++)
188 const auto &oldBlockFile = oldSeqBlock.
sb;
189 const auto len = oldBlockFile->GetSampleCount();
193 Read(bufferOld.
ptr(), oldFormats.Stored(), oldSeqBlock, 0, len,
true);
198 bufferOld.
ptr(), oldFormats.Stored(), bufferNew.
ptr(),
format, len,
202 format < oldFormats.Effective()
216 const auto blockstart = oldSeqBlock.
start;
218 newBlockArray, blockstart, bufferNew.
ptr(), len);
230 (newBlockArray,
mNumSamples,
wxT(
"Sequence::ConvertToSampleFormat()"));
241 if (len == 0 ||
mBlock.size() == 0) {
252 float max = -FLT_MAX;
255 unsigned int block1 =
FindBlock(start + len - 1);
261 for (
unsigned b = block0 + 1; b < block1; ++b) {
262 auto results =
mBlock[b].sb->GetMinMaxRMS(mayThrow);
264 if (results.min <
min)
266 if (results.max > max)
276 const auto &theFile = theBlock.
sb;
277 auto results = theFile->GetMinMaxRMS(mayThrow);
279 if (results.min <
min || results.max > max) {
281 auto s0 = ( start - theBlock.
start ).as_size_t();
284 theBlock.
start + theFile->GetSampleCount() - start
289 results = theFile->GetMinMaxRMS(s0, l0, mayThrow);
290 if (results.min <
min)
292 if (results.max > max)
300 const auto &theFile = theBlock.
sb;
301 auto results = theFile->GetMinMaxRMS(mayThrow);
303 if (results.min <
min || results.max > max) {
306 const auto l0 = ( start + len - theBlock.
start ).as_size_t();
309 results = theFile->GetMinMaxRMS(0, l0, mayThrow);
310 if (results.min <
min)
312 if (results.max > max)
324 if (len == 0 ||
mBlock.size() == 0)
331 unsigned int block1 =
FindBlock(start + len - 1);
336 for (
unsigned b = block0 + 1; b < block1; b++) {
338 const auto &sb = theBlock.
sb;
339 auto results = sb->GetMinMaxRMS(mayThrow);
341 const auto fileLen = sb->GetSampleCount();
342 const auto blockRMS = results.RMS;
343 sumsq += blockRMS * blockRMS * fileLen;
352 const auto &sb = theBlock.
sb;
354 auto s0 = ( start - theBlock.
start ).as_size_t();
357 (theBlock.
start + sb->GetSampleCount() - start).as_size_t();
361 auto results = sb->GetMinMaxRMS(s0, l0, mayThrow);
362 const auto partialRMS = results.RMS;
363 sumsq += partialRMS * partialRMS * l0;
367 if (block1 > block0) {
369 const auto &sb = theBlock.
sb;
372 const auto l0 = ( start + len - theBlock.
start ).as_size_t();
375 auto results = sb->GetMinMaxRMS(0, l0, mayThrow);
376 const auto partialRMS = results.RMS;
377 sumsq += partialRMS * partialRMS * l0;
382 wxASSERT(length == len);
384 return sqrt(sumsq / length.
as_double() );
400 auto pUseFactory = (pFactory ==
mpFactory) ?
nullptr : pFactory.get();
402 int numBlocks =
mBlock.size();
407 wxASSERT(b0 < numBlocks);
408 wxASSERT(b1 < numBlocks);
409 wxUnusedVar(numBlocks);
412 dest->mBlock.reserve(b1 - b0 + 1);
423 if (s0 != block0.
start) {
424 const auto &sb = block0.
sb;
427 (
std::min(s1, block0.
start + sb->GetSampleCount()) - s0 ).as_size_t();
439 for (
int bb = b0 + 1; bb < b1; ++bb)
441 dest->mBlock, dest->mNumSamples,
mBlock[bb]);
448 const auto &sb = block.
sb;
450 blocklen = (s1 - block.
start).as_size_t();
452 if (blocklen < (
int)sb->GetSampleCount()) {
461 dest->mBlock, dest->mNumSamples, block);
465 dest->ConsistencyCheck(
wxT(
"Sequence::Copy()"));
473 return numSamples > wxLL(9223372036854775807);
499 wxT(
"Sequence::Paste: sampleCount s %s is < 0 or > mNumSamples %s)."),
510 wxT(
"Sequence::Paste: mNumSamples %s + src->mNumSamples %s would overflow."),
521 wxT(
"Sequence::Paste: Sample format to be pasted, %s, does not match destination format, %s."),
529 const unsigned int srcNumBlocks = srcBlock.size();
532 if (addedLen == 0 || srcNumBlocks == 0)
535 const size_t numBlocks =
mBlock.size();
542 if (numBlocks == 0 ||
551 for (
unsigned int i = 0; i < srcNumBlocks; i++)
555 newBlock, samples, srcBlock[i]);
558 (newBlock, samples,
wxT(
"Paste branch one"));
564 wxASSERT((b >= 0) && (b < (
int)numBlocks));
566 const auto length = pBlock->
sb->GetSampleCount();
567 const auto largerBlockLen = addedLen + length;
580 auto sAddedLen = addedLen.as_size_t();
582 auto splitPoint = ( s - block.
start ).as_size_t();
584 src->
Get(0, buffer.
ptr() + splitPoint*sampleSize,
585 format, 0, sAddedLen,
true);
586 Read(buffer.
ptr() + (splitPoint + sAddedLen) * sampleSize,
588 splitPoint, length - splitPoint,
true);
593 largerBlockLen.as_size_t(),
600 for (
unsigned int i = b + 1; i < numBlocks; i++)
601 mBlock[i].start += addedLen;
617 newBlock.reserve(numBlocks + srcNumBlocks + 2);
618 newBlock.insert(newBlock.end(),
mBlock.begin(),
mBlock.begin() + b);
621 auto splitLen = splitBlock.
sb->GetSampleCount();
623 auto splitPoint = ( s - splitBlock.
start ).as_size_t();
626 if (srcNumBlocks <= 4) {
629 auto sAddedLen = addedLen.as_size_t();
630 const auto sum = splitLen + sAddedLen;
633 Read(sumBuffer.
ptr(),
format, splitBlock, 0, splitPoint,
true);
634 src->
Get(0, sumBuffer.
ptr() + splitPoint * sampleSize,
637 Read(sumBuffer.
ptr() + (splitPoint + sAddedLen) * sampleSize,
format,
638 splitBlock, splitPoint,
639 splitLen - splitPoint,
true);
642 newBlock, splitBlock.
start, sumBuffer.
ptr(), sum);
651 const auto srcFirstTwoLen =
652 srcBlock[0].sb->GetSampleCount() + srcBlock[1].sb->GetSampleCount();
653 const auto leftLen = splitPoint + srcFirstTwoLen;
655 const SeqBlock &penultimate = srcBlock[srcNumBlocks - 2];
656 const auto srcLastTwoLen =
657 penultimate.
sb->GetSampleCount() +
658 srcBlock[srcNumBlocks - 1].sb->GetSampleCount();
659 const auto rightSplit = splitBlock.
sb->GetSampleCount() - splitPoint;
660 const auto rightLen = rightSplit + srcLastTwoLen;
664 Read(sampleBuffer.
ptr(),
format, splitBlock, 0, splitPoint,
true);
665 src->
Get(0, sampleBuffer.
ptr() + splitPoint*sampleSize,
666 format, 0, srcFirstTwoLen,
true);
669 newBlock, splitBlock.
start, sampleBuffer.
ptr(), leftLen);
671 for (i = 2; i < srcNumBlocks - 2; i++) {
672 const SeqBlock &block = srcBlock[i];
678 auto lastStart = penultimate.
start;
680 lastStart, srcLastTwoLen,
true);
681 Read(sampleBuffer.
ptr() + srcLastTwoLen * sampleSize,
format,
682 splitBlock, splitPoint, rightSplit,
true);
685 newBlock, s + lastStart, sampleBuffer.
ptr(), rightLen);
690 for (i = b + 1; i < numBlocks; i++)
691 newBlock.push_back(
mBlock[i].Plus(addedLen));
729 auto nBlocks = (len + idealSamples - 1) / idealSamples;
730 sTrack.mBlock.reserve(nBlocks.as_size_t());
733 if (len >= idealSamples) {
734 auto silentFile =
factory.CreateSilent(
737 while (len >= idealSamples) {
738 sTrack.mBlock.push_back(
SeqBlock(silentFile, pos));
751 sTrack.mNumSamples = pos;
769 mBlock.push_back(newBlock);
793 int numBlocks =
mBlock.size();
797 auto result = (block.
start + block.
sb->GetSampleCount() - start).as_size_t();
799 decltype(result) length;
816 if (tag ==
"waveblock")
822 if (wb.
sb ==
nullptr)
829 for (
auto pair : attrs)
831 auto attr = pair.first;
832 auto value = pair.second;
839 if (!value.TryGet(start))
855 if (tag ==
"sequence")
858 for (
auto pair : attrs)
860 auto attr = pair.first;
861 auto value = pair.second;
863 long long nValue = 0;
865 if (attr ==
"maxsamples")
868 if (!value.TryGet(nValue))
877 if ((nValue < 1024) || (nValue > 64 * 1024 * 1024))
886 else if (attr ==
"sampleformat")
898 else if (attr ==
"effectivesampleformat")
910 else if (attr ==
"numsamples")
913 if (!value.TryGet(nValue) || (nValue < 0))
939 if (tag !=
"sequence" != 0)
948 for (
unsigned b = 0, nn =
mBlock.size(); b < nn; b++)
951 if (block.
start != numSamples)
954 wxT(
"Gap detected in project file.\n")
955 wxT(
" Start (%s) for block file %lld is not one sample past end of previous block (%s).\n")
956 wxT(
" Moving start so blocks are contiguous."),
959 block.
sb->GetBlockID(),
961 block.
start = numSamples;
964 numSamples += block.
sb->GetSampleCount();
970 wxT(
"Gap detected in project file. Correcting sequence sample count from %s to %s."),
981 if (tag ==
"waveblock")
995 xmlFile.StartTag(
wxT(
"sequence"));
997 xmlFile.WriteAttr(
wxT(
"maxsamples"), mMaxSamples);
998 xmlFile.WriteAttr(
wxT(
"sampleformat"),
999 static_cast<size_t>( mSampleFormats.Stored() ) );
1001 xmlFile.WriteAttr(
wxT(
"effectivesampleformat"),
1002 static_cast<size_t>( mSampleFormats.Effective() ));
1003 xmlFile.WriteAttr(
wxT(
"numsamples"), mNumSamples.as_long_long() );
1005 for (b = 0; b < mBlock.size(); b++) {
1009 if (bb.
sb->GetSampleCount() > mMaxSamples)
1018 XO(
"Sequence has block file exceeding maximum %s samples per block.\nTruncating to this maximum length.")
1023 .
Caption(
XO(
"Warning - Truncating Overlong Block File"))
1024 .IconStyle(Icon::Warning)
1025 .ButtonStyle(Button::Ok));
1026 wxLogWarning(sMsg.Translation());
1030 xmlFile.StartTag(
wxT(
"waveblock"));
1033 bb.
sb->SaveXML(xmlFile);
1035 xmlFile.EndTag(
wxT(
"waveblock"));
1038 xmlFile.EndTag(
wxT(
"sequence"));
1048 int numBlocks =
mBlock.size();
1050 size_t lo = 0, hi = numBlocks, guess;
1057 const double frac = (pos - loSamples).as_double() /
1058 (hiSamples - loSamples).as_double();
1059 guess =
std::min(hi - 1, lo +
size_t(frac * (hi - lo)));
1062 wxASSERT(block.
sb->GetSampleCount() > 0);
1063 wxASSERT(lo <= guess && guess < hi && lo < hi);
1065 if (pos < block.
start) {
1066 wxASSERT(lo != guess);
1068 hiSamples = block.
start;
1072 if (pos < nextStart)
1075 wxASSERT(guess < hi - 1);
1077 loSamples = nextStart;
1082 const int rval = guess;
1083 wxASSERT(rval >= 0 && rval < numBlocks &&
1084 pos >=
mBlock[rval].start &&
1085 pos <
mBlock[rval].start +
mBlock[rval].sb->GetSampleCount());
1092 const SeqBlock &b,
size_t blockRelativeStart,
size_t len,
1095 const auto &sb = b.
sb;
1097 wxASSERT(blockRelativeStart + len <= sb->GetSampleCount());
1100 auto result = sb->GetSamples(buffer,
format, blockRelativeStart, len, mayThrow);
1104 wxLogWarning(
wxT(
"Expected to read %ld samples, got %ld samples."),
1113 sampleCount start,
size_t len,
bool mayThrow)
const
1127 return Get(b, buffer,
format, start, len, mayThrow);
1131 sampleCount start,
size_t len,
bool mayThrow)
const
1137 const auto bstart = (start - block.
start).as_size_t();
1139 const auto blen =
std::min(len, block.
sb->GetSampleCount() - bstart);
1141 if (!
Read(buffer,
format, block, bstart, blen, mayThrow) )
1171 if (buffer &&
format != dstFormat) {
1172 temp.
Allocate(tempSize, dstFormat);
1177 std::copy(
mBlock.begin(),
mBlock.begin() + b, std::back_inserter(newBlock) );
1186 newBlock.push_back(
mBlock[b] );
1189 const auto bstart = ( start - block.
start ).as_size_t();
1190 const auto fileLength = block.
sb->GetSampleCount();
1196 wxASSERT(blen == 0 || bstart + blen <= fileLength);
1212 auto useBuffer = buffer;
1213 if (buffer &&
format != dstFormat)
1218 (dstFormat < effectiveFormat
1220 useBuffer = temp.
ptr();
1227 if ( bstart > 0 || blen < fileLength ) {
1229 Read(scratch.
ptr(), dstFormat, block, 0, fileLength,
true);
1233 memcpy(scratch.
ptr() +
1234 bstart * sampleSize, useBuffer, blen * sampleSize);
1247 block.
sb =
factory.Create(useBuffer, fileLength, dstFormat);
1249 block.
sb =
factory.CreateSilent(fileLength, dstFormat);
1263 std::copy(
mBlock.begin() + b,
mBlock.end(), std::back_inserter(newBlock) );
1272 int numBlocks =
mBlock.size();
1278 const auto lastBlockLen =
mBlock.back().sb->GetSampleCount();
1279 if (lastBlockLen >= max)
1282 return max - lastBlockLen;
1299 auto len = pBlock->GetSampleCount();
1310 newNumSamples,
wxT(
"Append"));
1315#ifdef VERY_SLOW_CHECKING
1330 bool result =
false;
1394 int numBlocks =
mBlock.size();
1396 decltype(pLastBlock->
sb->GetSampleCount()) length;
1400 bool replaceLast =
false;
1406 const SeqBlock &lastBlock = *pLastBlock;
1410 Read(buffer2.
ptr(), dstFormat, lastBlock, 0, length,
true);
1418 const auto newLastBlockLen = length + addLen;
1425 newBlock.push_back( newLastBlock );
1428 newNumSamples += addLen;
1436 const auto addedLen =
std::min(idealSamples, len);
1438 if (
format == dstFormat) {
1439 pBlock =
factory.Create(buffer, addedLen, dstFormat);
1442 wxASSERT( coalesce || !result );
1448 pBlock =
factory.Create(buffer2.
ptr(), addedLen, dstFormat);
1451 newBlock.push_back(
SeqBlock(pBlock, newNumSamples));
1454 newNumSamples += addedLen;
1459 newNumSamples,
wxT(
"Append"));
1464#ifdef VERY_SLOW_CHECKING
1480 auto cleanup =
finally( [&] {
1507 list.reserve(list.size() + num);
1509 for (
decltype(num) i = 0; i < num; i++) {
1512 const auto offset = i * len / num;
1513 b.
start = start + offset;
1514 int newLen = ((i + 1) * len / num) - offset;
1515 auto bufStart = buffer + (offset *
SAMPLE_SIZE(mSampleFormat));
1517 b.
sb =
factory.Create(bufStart, newLen, mSampleFormat);
1529 if (len < 0 || start < 0 || start + len >
mNumSamples)
1534 const unsigned int numBlocks =
mBlock.size();
1536 const unsigned int b0 =
FindBlock(start);
1537 unsigned int b1 =
FindBlock(start + len - 1);
1543 decltype(pBlock->
sb->GetSampleCount()) length;
1557 auto pos = ( start - b.
start ).as_size_t();
1560 wxASSERT(len < length);
1574 ( pos + len ).as_size_t(), newLen - pos,
true);
1583 for (
unsigned int j = b0 + 1; j < numBlocks; j++)
1596 newBlock.reserve(numBlocks - (b1 - b0) + 2);
1600 newBlock.insert(newBlock.end(),
mBlock.begin(),
mBlock.begin() + b0);
1610 auto preBufferLen = ( start - preBlock.
start ).as_size_t();
1616 Read(scratch.
ptr(),
format, preBlock, 0, preBufferLen,
true);
1623 const auto prepreLen = prepreBlock.
sb->GetSampleCount();
1624 const auto sum = prepreLen + preBufferLen;
1631 Read(scratch.
ptr(),
format, prepreBlock, 0, prepreLen,
true);
1633 preBlock, 0, preBufferLen,
true);
1635 newBlock.pop_back();
1637 newBlock, prepreBlock.
start, scratch.
ptr(), sum);
1652 const auto postBufferLen = (
1653 (postBlock.
start + postBlock.
sb->GetSampleCount()) - (start + len)
1655 if (postBufferLen) {
1656 if (postBufferLen >=
mMinSamples || b1 == numBlocks - 1) {
1661 auto pos = (start + len - postBlock.
start).as_size_t();
1662 Read(scratch.
ptr(),
format, postBlock, pos, postBufferLen,
true);
1666 newBlock.push_back(
SeqBlock(file, start));
1669 const auto postpostLen = postpostBlock.
sb->GetSampleCount();
1670 const auto sum = postpostLen + postBufferLen;
1676 auto pos = (start + len - postBlock.
start).as_size_t();
1677 Read(scratch.
ptr(),
format, postBlock, pos, postBufferLen,
true);
1679 postpostBlock, 0, postpostLen,
true);
1682 newBlock, start, scratch.
ptr(), sum);
1692 for (i = b1 + 1; i < numBlocks; i++)
1693 newBlock.push_back(
mBlock[i].Plus(-len));
1705 (
const BlockArray &mBlock,
size_t maxSamples,
size_t from,
1707 bool WXUNUSED(mayThrow))
1711 std::optional<InconsistencyException> ex;
1713 unsigned int numBlocks =
mBlock.size();
1717 if ( from == 0 && pos != 0 )
1720 for (i = from; !ex && i < numBlocks; i++) {
1722 if (pos != seqBlock.
start)
1725 if ( seqBlock.
sb ) {
1726 const auto length = seqBlock.
sb->GetSampleCount();
1727 if (length > maxSamples)
1739 wxLogError(
wxT(
"*** Consistency check failed at %d after %s. ***"),
1740 ex->GetLine(), whereStr);
1743 wxLogError(
wxT(
"%s"),
str);
1744 wxLogError(
wxT(
"*** Please report this error to https://forum.audacityteam.org/. ***\n\n")
1745 wxT(
"Recommended course of action:\n")
1746 wxT(
"Undo the failed operation(s), then export or save your work and quit."));
1768(
BlockArray &additionalBlocks,
bool replaceLast,
1774 if (additionalBlocks.empty())
1777 bool tmpValid =
false;
1780 if ( replaceLast && !
mBlock.empty() ) {
1781 tmp =
mBlock.back(), tmpValid =
true;
1785 auto prevSize =
mBlock.size();
1787 bool consistent =
false;
1788 auto cleanup =
finally( [&] {
1789 if ( !consistent ) {
1790 mBlock.resize( prevSize );
1796 std::copy( additionalBlocks.begin(), additionalBlocks.end(),
1797 std::back_inserter(
mBlock ) );
1816 for (i = 0; i <
mBlock.size(); i++) {
1818 *dest += wxString::Format
1819 (
wxT(
" Block %3u: start %8lld, len %8lld, refs %ld, id %lld"),
1822 seqBlock.
sb ? (
long long) seqBlock.
sb->GetSampleCount() : 0,
1823 seqBlock.
sb ? seqBlock.
sb.use_count() : 0,
1824 seqBlock.
sb ? (
long long) seqBlock.
sb->GetBlockID() : 0);
1826 if ((pos != seqBlock.
start) || !seqBlock.
sb)
1827 *dest +=
wxT(
" ERROR\n");
1832 pos += seqBlock.
sb->GetSampleCount();
1835 *dest += wxString::Format
Toolkit-neutral facade for basic user interface services.
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< SampleBlock > SampleBlockPtr
std::shared_ptr< SampleBlockFactory > SampleBlockFactoryPtr
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
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...
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
SampleBlockFactoryPtr mpFactory
static size_t sMaxDiskBlockSize
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
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
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)
static RegisteredToolbarFactory factory
MessageBoxOptions && Caption(TranslatableString caption_) &&