void WaveTrack::InsertSilence(double t, double lenSecs) { // Create a new track containing as much silence as we // need to insert, and then call Paste to do the insertion sampleCount len = (sampleCount) (lenSecs * rate + 0.5); WaveTrack *sTrack = new WaveTrack(dirManager); sTrack->rate = rate; sampleCount idealSamples = GetIdealBlockSize(); sampleType *buffer = new sampleType[idealSamples]; sampleCount i; for (i = 0; i < idealSamples; i++) buffer[i] = 0; sampleCount pos = 0; BlockFile *firstBlockFile = NULL; while (len) { sampleCount l = (len > idealSamples ? idealSamples : len); WaveBlock *w = new WaveBlock(); w->start = pos; w->len = l; w->min = 0; w->max = 0; if (pos == 0 || len == l) { w->f = dirManager->NewBlockFile(); firstBlockFile = w->f; bool inited = InitBlock(w); wxASSERT(inited); FirstWrite(buffer, w, l); } else { w->f = dirManager->CopyBlockFile(firstBlockFile); if (!w->f) { wxMessageBox("Could not paste! (Out of disk space?)"); } } sTrack->block->Add(w); pos += l; len -= l; } sTrack->numSamples = pos; Paste(t, sTrack); delete sTrack; ConsistencyCheck("InsertSilence"); }
bool Sequence::InsertSilence(sampleCount s0, sampleCount len) { // Create a new track containing as much silence as we // need to insert, and then call Paste to do the insertion Sequence *sTrack = new Sequence(mDirManager, mSampleFormat); sampleCount idealSamples = GetIdealBlockSize(); // Allocate a zeroed buffer samplePtr buffer = NewSamples(idealSamples, mSampleFormat); ClearSamples(buffer, mSampleFormat, 0, idealSamples); sampleCount pos = 0; BlockFile *firstBlockFile = NULL; while (len) { sampleCount l = (len > idealSamples ? idealSamples : len); SeqBlock *w = new SeqBlock(); w->start = pos; w->len = l; w->min = float(0.0); w->max = float(0.0); w->rms = float(0.0); if (pos == 0 || len == l) { w->f = mDirManager->NewBlockFile(mSummary->totalSummaryBytes); firstBlockFile = w->f; FirstWrite(buffer, w, l); } else { w->f = mDirManager->CopyBlockFile(firstBlockFile); if (!w->f) { // TODO set error message return false; } } sTrack->mBlock->Add(w); pos += l; len -= l; } sTrack->mNumSamples = pos; Paste(s0, sTrack); delete sTrack; DeleteSamples(buffer); return ConsistencyCheck("InsertSilence"); }
void setup() { lcd.begin(LCDWIDTH, LCDHEIGHT); lcd.clear(); BootWrite(); Serial.begin(9600); while (!Serial); sensor.begin(); initialize(mode); FirstWrite(); timer.setTimeout(DLY); timerJSON.setTimeout(JSON * DLY); timer.restart(); timerJSON.restart(); }
BlockArray *WaveTrack::Blockify(sampleType * buffer, sampleCount len) { BlockArray *list = new BlockArray(); list->Alloc(10); if (len == 0) return list; int num = (len + (maxSamples - 1)) / maxSamples; for (int i = 0; i < num; i++) { WaveBlock *b = NewInitedWaveBlock(); b->start = i * len / num; b->len = ((i + 1) * len / num) - b->start; FirstWrite(&buffer[b->start], b, b->len); list->Add(b); } return list; }
BlockArray *Sequence::Blockify(samplePtr buffer, sampleCount len) { BlockArray *list = new BlockArray(); list->Alloc(10); if (len == 0) return list; int num = (len + (mMaxSamples - 1)) / mMaxSamples; for (int i = 0; i < num; i++) { SeqBlock *b = NewInitedSeqBlock(); b->start = i * len / num; b->len = ((i + 1) * len / num) - b->start; FirstWrite(buffer + (b->start * SAMPLE_SIZE(mSampleFormat)), b, b->len); list->Add(b); } return list; }
bool Sequence::Paste(sampleCount s, const Sequence *src) { if (s < 0) s = 0; if (s >= mNumSamples) s = mNumSamples; BlockArray *srcBlock = src->mBlock; int addedLen = src->mNumSamples; unsigned int srcNumBlocks = srcBlock->Count(); int sampleSize = SAMPLE_SIZE(mSampleFormat); if (addedLen == 0 || srcNumBlocks == 0) return true; unsigned int b = FindBlock(s); unsigned int numBlocks = mBlock->Count(); if (numBlocks == 0) { // Special case: this track is currently empty. for (unsigned int i = 0; i < srcNumBlocks; i++) AppendBlock(srcBlock->Item(i)); return ConsistencyCheck("Paste branch one"); } if (b >= 0 && b < numBlocks && mBlock->Item(b)->len + addedLen < mMaxSamples) { // Special case: we can fit all of the new samples inside of // one block! samplePtr buffer = NewSamples(mMaxSamples, mSampleFormat); int splitPoint = s - mBlock->Item(b)->start; Read(buffer, mSampleFormat, mBlock->Item(b), 0, splitPoint); src->Get(buffer + splitPoint*sampleSize, mSampleFormat, 0, addedLen); Read(buffer + (splitPoint + addedLen)*sampleSize, mSampleFormat, mBlock->Item(b), splitPoint, mBlock->Item(b)->len - splitPoint); SeqBlock *largerBlock = new SeqBlock(); largerBlock->start = mBlock->Item(b)->start; largerBlock->len = mBlock->Item(b)->len + addedLen; largerBlock->f = mDirManager->NewBlockFile(mSummary->totalSummaryBytes); FirstWrite(buffer, largerBlock, largerBlock->len); mDirManager->Deref(mBlock->Item(b)->f); delete mBlock->Item(b); mBlock->Item(b) = largerBlock; for (unsigned int i = b + 1; i < numBlocks; i++) mBlock->Item(i)->start += addedLen; mNumSamples += addedLen; DeleteSamples(buffer); return ConsistencyCheck("Paste branch two"); } // Case two: if we are inserting four or fewer blocks, // it's simplest to just lump all the data together // into one big block along with the split block, // then resplit it all unsigned int i; BlockArray *newBlock = new BlockArray(); newBlock->Alloc(numBlocks + srcNumBlocks + 2); int newNumBlocks = 0; for (i = 0; i < b; i++) { newBlock->Add(mBlock->Item(i)); newNumBlocks++; } SeqBlock *splitBlock = mBlock->Item(b); sampleCount splitLen = mBlock->Item(b)->len; int splitPoint = s - splitBlock->start; if (srcNumBlocks <= 4) { sampleCount sum = splitLen + addedLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); Read(sumBuffer, mSampleFormat, splitBlock, 0, splitPoint); src->Get(sumBuffer + splitPoint * sampleSize, mSampleFormat, 0, addedLen); Read(sumBuffer + (splitPoint + addedLen) * sampleSize, mSampleFormat, splitBlock, splitPoint, splitBlock->len - splitPoint); BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += splitBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; DeleteSamples(sumBuffer); } else { // The final case is that we're inserting at least five blocks. // We divide these into three groups: the first two get merged // with the first half of the split block, the middle ones get // copied in as is, and the last two get merged with the last // half of the split block. sampleCount srcFirstTwoLen = srcBlock->Item(0)->len + srcBlock->Item(1)->len; sampleCount leftLen = splitPoint + srcFirstTwoLen; samplePtr leftBuffer = NewSamples(leftLen, mSampleFormat); Read(leftBuffer, mSampleFormat, splitBlock, 0, splitPoint); src->Get(leftBuffer + splitPoint*sampleSize, mSampleFormat, 0, srcFirstTwoLen); BlockArray *split = Blockify(leftBuffer, leftLen); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += splitBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; DeleteSamples(leftBuffer); for (i = 2; i < srcNumBlocks - 2; i++) { SeqBlock *insertBlock = new SeqBlock(); insertBlock->start = srcBlock->Item(i)->start + s; insertBlock->len = srcBlock->Item(i)->len; insertBlock->min = srcBlock->Item(i)->min; insertBlock->max = srcBlock->Item(i)->max; insertBlock->rms = srcBlock->Item(i)->rms; insertBlock->f = mDirManager->CopyBlockFile(srcBlock->Item(i)->f); if (!insertBlock->f) { // TODO error: Could not paste! (Out of disk space?) return false; } newBlock->Add(insertBlock); newNumBlocks++; } sampleCount srcLastTwoLen = srcBlock->Item(srcNumBlocks - 2)->len + srcBlock->Item(srcNumBlocks - 1)->len; sampleCount rightSplit = splitBlock->len - splitPoint; sampleCount rightLen = rightSplit + srcLastTwoLen; samplePtr rightBuffer = NewSamples(rightLen, mSampleFormat); sampleCount lastStart = srcBlock->Item(srcNumBlocks - 2)->start; src->Get(rightBuffer, mSampleFormat, lastStart, srcLastTwoLen); Read(rightBuffer + srcLastTwoLen * sampleSize, mSampleFormat, splitBlock, splitPoint, rightSplit); sampleCount pos = s + lastStart; split = Blockify(rightBuffer, rightLen); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += pos; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; DeleteSamples(rightBuffer); } mDirManager->Deref(splitBlock->f); delete splitBlock; // Copy remaining blocks to new block array and // swap the new block array in for the old for (i = b + 1; i < numBlocks; i++) { mBlock->Item(i)->start += addedLen; newBlock->Add(mBlock->Item(i)); newNumBlocks++; } delete mBlock; mBlock = newBlock; mNumSamples += addedLen; return ConsistencyCheck("Paste branch three"); }
bool Sequence::Delete(sampleCount start, sampleCount len) { if (len == 0) return true; if (len < 0 || start < 0 || start >= mNumSamples) return false; unsigned int numBlocks = mBlock->Count(); unsigned int newNumBlocks = 0; unsigned int b0 = FindBlock(start); unsigned int b1 = FindBlock(start + len - 1); int sampleSize = SAMPLE_SIZE(mSampleFormat); // Special case: if the samples to delete are all within a single // block and the resulting length is not too small, perform the // deletion within this block: if (b0 == b1 && mBlock->Item(b0)->len - len >= mMinSamples) { SeqBlock *b = mBlock->Item(b0); sampleCount pos = start - b->start; sampleCount newLen = b->len - len; samplePtr buffer = NewSamples(newLen, mSampleFormat); Read(buffer, mSampleFormat, b, 0, pos); Read(buffer + (pos * sampleSize), mSampleFormat, b, pos + len, newLen - pos); SeqBlock *newBlock = NewInitedSeqBlock(); newBlock->start = b->start; newBlock->len = newLen; FirstWrite(buffer, newBlock, newLen); mBlock->Item(b0) = newBlock; for (unsigned int j = b0 + 1; j < numBlocks; j++) mBlock->Item(j)->start -= len; DeleteSamples(buffer); mDirManager->Deref(b->f); delete b; mNumSamples -= len; return ConsistencyCheck("Delete - branch one"); } // Create a new array of blocks BlockArray *newBlock = new BlockArray(); newBlock->Alloc(numBlocks - (b1 - b0) + 2); // Copy the blocks before the deletion point over to // the new array unsigned int i; for (i = 0; i < b0; i++) { newBlock->Add(mBlock->Item(i)); newNumBlocks++; } // First grab the samples in block b0 before the deletion point // into preBuffer. If this is enough samples for its own block, // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). SeqBlock *preBlock = mBlock->Item(b0); sampleCount preBufferLen = start - preBlock->start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { SeqBlock *insBlock = NewInitedSeqBlock(); insBlock->len = preBufferLen; insBlock->start = preBlock->start; samplePtr preBuffer = NewSamples(preBufferLen, mSampleFormat); Read(preBuffer, mSampleFormat, preBlock, 0, preBufferLen); FirstWrite(preBuffer, insBlock, preBufferLen); DeleteSamples(preBuffer); newBlock->Add(insBlock); newNumBlocks++; if (b0 != b1) { mDirManager->Deref(preBlock->f); delete preBlock; } } else { SeqBlock *prepreBlock = mBlock->Item(b0 - 1); sampleCount prepreLen = prepreBlock->len; sampleCount sum = prepreLen + preBufferLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); Read(sumBuffer, mSampleFormat, prepreBlock, 0, prepreLen); Read(sumBuffer + prepreLen*sampleSize, mSampleFormat, preBlock, 0, preBufferLen); BlockArray *split = Blockify(sumBuffer, sum); split->Item(0)->start += prepreBlock->start; newBlock->Item(b0 - 1) = split->Item(0); for (i = 1; i < split->Count(); i++) { split->Item(i)->start += prepreBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; DeleteSamples(sumBuffer); mDirManager->Deref(prepreBlock->f); delete prepreBlock; if (b0 != b1) { mDirManager->Deref(preBlock->f); delete preBlock; } } } else { // The sample where we begin deletion happens to fall // right on the beginning of a block. if (b0 != b1) { mDirManager->Deref(mBlock->Item(b0)->f); delete mBlock->Item(b0); } } // Next, delete blocks strictly between b0 and b1 for (i = b0 + 1; i < b1; i++) { mDirManager->Deref(mBlock->Item(i)->f); delete mBlock->Item(i); } // Now, symmetrically, grab the samples in block b1 after the // deletion point into postBuffer. If this is enough samples // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). SeqBlock *postBlock = mBlock->Item(b1); sampleCount postBufferLen = (postBlock->start + postBlock->len) - (start + len); if (postBufferLen) { if (postBufferLen >= mMinSamples || b1 == numBlocks - 1) { SeqBlock *insBlock = NewInitedSeqBlock(); insBlock->len = postBufferLen; insBlock->start = start; samplePtr postBuffer = NewSamples(postBufferLen, mSampleFormat); sampleCount pos = (start + len) - postBlock->start; Read(postBuffer, mSampleFormat, postBlock, pos, postBufferLen); FirstWrite(postBuffer, insBlock, postBufferLen); DeleteSamples(postBuffer); newBlock->Add(insBlock); newNumBlocks++; mDirManager->Deref(postBlock->f); delete postBlock; } else { SeqBlock *postpostBlock = mBlock->Item(b1 + 1); sampleCount postpostLen = postpostBlock->len; sampleCount sum = postpostLen + postBufferLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); sampleCount pos = (start + len) - postBlock->start; Read(sumBuffer, mSampleFormat, postBlock, pos, postBufferLen); Read(sumBuffer + (postBufferLen * sampleSize), mSampleFormat, postpostBlock, 0, postpostLen); BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; b1++; DeleteSamples(sumBuffer); mDirManager->Deref(postpostBlock->f); delete postpostBlock; mDirManager->Deref(postBlock->f); delete postBlock; } } else { // The sample where we begin deletion happens to fall // right on the end of a block. if (b0 != b1) { mDirManager->Deref(mBlock->Item(b1)->f); delete mBlock->Item(b1); } } // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) { mBlock->Item(i)->start -= len; newBlock->Add(mBlock->Item(i)); newNumBlocks++; } // Substitute our new array for the old one delete mBlock; mBlock = newBlock; // Update total number of samples and do a consistency check. mNumSamples -= len; return ConsistencyCheck("Delete - branch two"); }
bool Sequence::Append(samplePtr buffer, sampleFormat format, sampleCount len) { samplePtr temp = NULL; if (format != mSampleFormat) { temp = NewSamples(mMaxSamples, mSampleFormat); wxASSERT(temp); } // If the last block is not full, we need to add samples to it int numBlocks = mBlock->Count(); if (numBlocks > 0 && mBlock->Item(numBlocks - 1)->len < mMinSamples) { SeqBlock *lastBlock = mBlock->Item(numBlocks - 1); sampleCount addLen; if (lastBlock->len + len < mMaxSamples) addLen = len; else addLen = GetIdealBlockSize() - lastBlock->len; SeqBlock *newLastBlock = NewInitedSeqBlock(); samplePtr buffer2 = NewSamples((lastBlock->len + addLen), mSampleFormat); Read(buffer2, mSampleFormat, lastBlock, 0, lastBlock->len); if (format == mSampleFormat) memcpy(buffer2 + lastBlock->len * SAMPLE_SIZE(format), buffer, addLen * SAMPLE_SIZE(format)); else { CopySamples(buffer, format, temp, mSampleFormat, addLen); memcpy(buffer2 + lastBlock->len * SAMPLE_SIZE(format), temp, addLen * SAMPLE_SIZE(format)); } newLastBlock->start = lastBlock->start; newLastBlock->len = lastBlock->len + addLen; FirstWrite(buffer2, newLastBlock, lastBlock->len + addLen); DeleteSamples(buffer2); mDirManager->Deref(lastBlock->f); delete lastBlock; mBlock->Item(numBlocks - 1) = newLastBlock; len -= addLen; mNumSamples += addLen; buffer += addLen * SAMPLE_SIZE(format); } // Append the rest as new blocks while (len) { sampleCount idealSamples = GetIdealBlockSize(); sampleCount l = (len > idealSamples ? idealSamples : len); SeqBlock *w = new SeqBlock(); w->f = mDirManager->NewBlockFile(mSummary->totalSummaryBytes); w->start = mNumSamples; w->len = l; if (format == mSampleFormat) FirstWrite(buffer, w, l); else { CopySamples(buffer, format, temp, mSampleFormat, l); FirstWrite(temp, w, l); } mBlock->Add(w); buffer += l * SAMPLE_SIZE(format); mNumSamples += l; len -= l; } if (format != mSampleFormat) DeleteSamples(temp); ConsistencyCheck("Append"); return true; }
void WaveTrack::Paste(double t, VTrack * src) { wxASSERT(src->GetKind() == WaveTrack::Wave); envelope.ExpandRegion(t, src->GetMaxLen()); #if wxUSE_THREADS wxMutexLocker lock(*blockMutex); #endif sampleCount s = (sampleCount) ((t - tOffset) * rate + 0.5); if (s < 0) s = 0; if (s >= numSamples) s = numSamples; BlockArray *srcBlock = ((WaveTrack *) src)->GetBlockArray(); int addedLen = ((WaveTrack *) src)->numSamples; int srcNumBlocks = srcBlock->Count(); if (addedLen == 0 || srcNumBlocks == 0) return; int b = FindBlock(s); int numBlocks = block->Count(); if (numBlocks == 0) { // Special case: this track is currently empty. for (int i = 0; i < srcNumBlocks; i++) AppendBlock(srcBlock->Item(i)); envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Paste branch one"); return; } if (b >= 0 && b < numBlocks && block->Item(b)->len + addedLen < maxSamples) { // Special case: we can fit all of the new samples inside of // one block! sampleType *buffer = new sampleType[maxSamples]; int splitPoint = s - block->Item(b)->start; Read(buffer, block->Item(b), 0, splitPoint); ((WaveTrack *) src)->Get(&buffer[splitPoint], 0, addedLen); Read(&buffer[splitPoint + addedLen], block->Item(b), splitPoint, block->Item(b)->len - splitPoint); WaveBlock *largerBlock = new WaveBlock(); largerBlock->start = block->Item(b)->start; largerBlock->len = block->Item(b)->len + addedLen; largerBlock->f = dirManager->NewBlockFile(); bool inited = InitBlock(largerBlock); wxASSERT(inited); FirstWrite(buffer, largerBlock, largerBlock->len); dirManager->Deref(block->Item(b)->f); delete block->Item(b); block->Item(b) = largerBlock; for (int i = b + 1; i < numBlocks; i++) block->Item(i)->start += addedLen; numSamples += addedLen; delete[]buffer; envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Paste branch two"); return; } // Case two: if we are inserting four or fewer blocks, // it's simplest to just lump all the data together // into one big block along with the split block, // then resplit it all int i; BlockArray *newBlock = new BlockArray(); newBlock->Alloc(numBlocks + srcNumBlocks + 2); int newNumBlocks = 0; for (i = 0; i < b; i++) { newBlock->Add(block->Item(i)); newNumBlocks++; } WaveBlock *splitBlock = block->Item(b); sampleCount splitLen = block->Item(b)->len; int splitPoint = s - splitBlock->start; if (srcNumBlocks <= 4) { sampleCount sum = splitLen + addedLen; sampleType *sumBuffer = new sampleType[sum]; Read(sumBuffer, splitBlock, 0, splitPoint); ((WaveTrack *) src)->Get(&sumBuffer[splitPoint], 0, addedLen); Read(&sumBuffer[splitPoint + addedLen], splitBlock, splitPoint, splitBlock->len - splitPoint); BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += splitBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; delete[]sumBuffer; } else { // The final case is that we're inserting at least five blocks. // We divide these into three groups: the first two get merged // with the first half of the split block, the middle ones get // copied in as is, and the last two get merged with the last // half of the split block. sampleCount srcFirstTwoLen = srcBlock->Item(0)->len + srcBlock->Item(1)->len; sampleCount leftLen = splitPoint + srcFirstTwoLen; sampleType *leftBuffer = new sampleType[leftLen]; Read(leftBuffer, splitBlock, 0, splitPoint); ((WaveTrack *) src)->Get(&leftBuffer[splitPoint], 0, srcFirstTwoLen); BlockArray *split = Blockify(leftBuffer, leftLen); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += splitBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; delete[]leftBuffer; for (i = 2; i < srcNumBlocks - 2; i++) { WaveBlock *insertBlock = new WaveBlock(); insertBlock->start = srcBlock->Item(i)->start + s; insertBlock->len = srcBlock->Item(i)->len; insertBlock->min = srcBlock->Item(i)->min; insertBlock->max = srcBlock->Item(i)->max; insertBlock->f = dirManager->CopyBlockFile(srcBlock->Item(i)->f); if (!insertBlock->f) { wxMessageBox("Could not paste! (Out of disk space?)"); } newBlock->Add(insertBlock); newNumBlocks++; } sampleCount srcLastTwoLen = srcBlock->Item(srcNumBlocks - 2)->len + srcBlock->Item(srcNumBlocks - 1)->len; sampleCount rightSplit = splitBlock->len - splitPoint; sampleCount rightLen = rightSplit + srcLastTwoLen; sampleType *rightBuffer = new sampleType[rightLen]; sampleCount lastStart = srcBlock->Item(srcNumBlocks - 2)->start; ((WaveTrack *) src)->Get(rightBuffer, lastStart, srcLastTwoLen); Read(&rightBuffer[srcLastTwoLen], splitBlock, splitPoint, rightSplit); sampleCount pos = s + lastStart; split = Blockify(rightBuffer, rightLen); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += pos; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; delete[]rightBuffer; } dirManager->Deref(splitBlock->f); delete splitBlock; // Copy remaining blocks to new block array and // swap the new block array in for the old for (i = b + 1; i < numBlocks; i++) { block->Item(i)->start += addedLen; newBlock->Add(block->Item(i)); newNumBlocks++; } delete block; block = newBlock; numSamples += addedLen; envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Paste branch three"); }
void WaveTrack::Delete(sampleCount start, sampleCount len) { if (len == 0) return; int numBlocks = block->Count(); int newNumBlocks = 0; #if wxUSE_THREADS wxMutexLocker lock(*blockMutex); #endif int b0 = FindBlock(start); int b1 = FindBlock(start + len - 1); // Special case: if the samples to delete are all within a single // block and the resulting length is not too small, perform the // deletion within this block: if (b0 == b1 && block->Item(b0)->len - len >= minSamples) { WaveBlock *b = block->Item(b0); sampleCount pos = start - b->start; sampleCount newLen = b->len - len; sampleType *buffer = new sampleType[newLen]; Read(buffer, b, 0, pos); Read(&buffer[pos], b, pos + len, newLen - pos); WaveBlock *newBlock = NewInitedWaveBlock(); newBlock->start = b->start; newBlock->len = newLen; FirstWrite(buffer, newBlock, newLen); block->Item(b0) = newBlock; for (int j = b0 + 1; j < numBlocks; j++) block->Item(j)->start -= len; delete[]buffer; dirManager->Deref(b->f); delete b; numSamples -= len; envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Delete - branch one"); return; } // Create a new array of blocks BlockArray *newBlock = new BlockArray(); newBlock->Alloc(numBlocks - (b1 - b0) + 2); // Copy the blocks before the deletion point over to // the new array int i; for (i = 0; i < b0; i++) { newBlock->Add(block->Item(i)); newNumBlocks++; } // First grab the samples in block b0 before the deletion point // into preBuffer. If this is enough samples for its own block, // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). WaveBlock *preBlock = block->Item(b0); sampleCount preBufferLen = start - preBlock->start; if (preBufferLen) { if (preBufferLen >= minSamples || b0 == 0) { WaveBlock *insBlock = NewInitedWaveBlock(); insBlock->len = preBufferLen; insBlock->start = preBlock->start; sampleType *preBuffer = new sampleType[preBufferLen]; Read(preBuffer, preBlock, 0, preBufferLen); FirstWrite(preBuffer, insBlock, preBufferLen); delete[]preBuffer; newBlock->Add(insBlock); newNumBlocks++; if (b0 != b1) { dirManager->Deref(preBlock->f); delete preBlock; } } else { WaveBlock *prepreBlock = block->Item(b0 - 1); sampleCount prepreLen = prepreBlock->len; sampleCount sum = prepreLen + preBufferLen; sampleType *sumBuffer = new sampleType[sum]; Read(sumBuffer, prepreBlock, 0, prepreLen); Read(&sumBuffer[prepreLen], preBlock, 0, preBufferLen); BlockArray *split = Blockify(sumBuffer, sum); split->Item(0)->start += prepreBlock->start; newBlock->Item(b0 - 1) = split->Item(0); for (i = 1; i < split->Count(); i++) { split->Item(i)->start += prepreBlock->start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; delete[]sumBuffer; dirManager->Deref(prepreBlock->f); delete prepreBlock; if (b0 != b1) { dirManager->Deref(preBlock->f); delete preBlock; } } } else { // The sample where we begin deletion happens to fall // right on the beginning of a block. if (b0 != b1) { dirManager->Deref(block->Item(b0)->f); delete block->Item(b0); } } // Next, delete blocks strictly between b0 and b1 for (i = b0 + 1; i < b1; i++) { dirManager->Deref(block->Item(i)->f); delete block->Item(i); } // Now, symmetrically, grab the samples in block b1 after the // deletion point into postBuffer. If this is enough samples // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). WaveBlock *postBlock = block->Item(b1); sampleCount postBufferLen = (postBlock->start + postBlock->len) - (start + len); if (postBufferLen) { if (postBufferLen >= minSamples || b1 == numBlocks - 1) { WaveBlock *insBlock = NewInitedWaveBlock(); insBlock->len = postBufferLen; insBlock->start = start; sampleType *postBuffer = new sampleType[postBufferLen]; sampleCount pos = (start + len) - postBlock->start; Read(postBuffer, postBlock, pos, postBufferLen); FirstWrite(postBuffer, insBlock, postBufferLen); delete[]postBuffer; newBlock->Add(insBlock); newNumBlocks++; dirManager->Deref(postBlock->f); delete postBlock; } else { WaveBlock *postpostBlock = block->Item(b1 + 1); sampleCount postpostLen = postpostBlock->len; sampleCount sum = postpostLen + postBufferLen; sampleType *sumBuffer = new sampleType[sum]; sampleCount pos = (start + len) - postBlock->start; Read(sumBuffer, postBlock, pos, postBufferLen); Read(&sumBuffer[postBufferLen], postpostBlock, 0, postpostLen); BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->Count(); i++) { split->Item(i)->start += start; newBlock->Add(split->Item(i)); newNumBlocks++; } delete split; b1++; delete[]sumBuffer; dirManager->Deref(postpostBlock->f); delete postpostBlock; dirManager->Deref(postBlock->f); delete postBlock; } } else { // The sample where we begin deletion happens to fall // right on the end of a block. if (b0 != b1) { dirManager->Deref(block->Item(b1)->f); delete block->Item(b1); } } // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) { block->Item(i)->start -= len; newBlock->Add(block->Item(i)); newNumBlocks++; } // Substitute our new array for the old one delete block; block = newBlock; // Update total number of samples, update the envelope, // and do a consistency check. numSamples -= len; envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Delete - branch two"); }
void WaveTrack::Append(sampleType * buffer, sampleCount len) { #if wxUSE_THREADS wxMutexLocker lock(*blockMutex); #endif // If the last block is not full, we need to add samples to it int numBlocks = block->Count(); if (numBlocks > 0 && block->Item(numBlocks - 1)->len < minSamples) { WaveBlock *lastBlock = block->Item(numBlocks - 1); sampleCount addLen; if (lastBlock->len + len < maxSamples) addLen = len; else addLen = GetIdealBlockSize() - lastBlock->len; sampleCount pos = lastBlock->len; WaveBlock *newLastBlock = NewInitedWaveBlock(); sampleType *buffer2 = new sampleType[lastBlock->len + addLen]; Read(buffer2, lastBlock, 0, lastBlock->len); for (int j = 0; j < addLen; j++) buffer2[lastBlock->len + j] = buffer[j]; newLastBlock->start = lastBlock->start; newLastBlock->len = lastBlock->len + addLen; FirstWrite(buffer2, newLastBlock, lastBlock->len + addLen); delete[]buffer2; dirManager->Deref(lastBlock->f); delete lastBlock; block->Item(numBlocks - 1) = newLastBlock; len -= addLen; numSamples += addLen; buffer += addLen; } // Append the rest as new blocks while (len) { sampleCount idealSamples = GetIdealBlockSize(); sampleCount l = (len > idealSamples ? idealSamples : len); WaveBlock *w = new WaveBlock(); w->f = dirManager->NewBlockFile(); w->start = numSamples; w->len = l; bool inited = InitBlock(w); wxASSERT(inited); FirstWrite(buffer, w, l); block->Add(w); buffer += l; numSamples += l; len -= l; } envelope.SetTrackLen(numSamples / rate); ConsistencyCheck("Append"); }