bool SetClipCommand::ApplyInner( const CommandContext & context, Track * t ) { static_cast<void>(context); // if no 'At' is specified, then any clip in any selected track will be set. t->TypeSwitch([&](WaveTrack *waveTrack) { WaveClipPointers ptrs( waveTrack->SortedClipArray()); for(auto it = ptrs.begin(); (it != ptrs.end()); it++ ){ WaveClip * pClip = *it; bool bFound = !bHasContainsTime || ( ( pClip->GetStartTime() <= mContainsTime ) && ( pClip->GetEndTime() >= mContainsTime ) ); if( bFound ) { // Inside this IF is where we actually apply the command if( bHasColour ) pClip->SetColourIndex(mColour); // No validation of overlap yet. We assume the user is sensible! if( bHasT0 ) pClip->SetOffset(mT0); // \todo Use SetClip to move a clip between tracks too. } } } ); return true; }
WaveClip::WaveClip(WaveClip& orig, DirManager *projDirManager) { // essentially a copy constructor - but you must pass in the // current project's DirManager, because we might be copying // from one project to another mOffset = orig.mOffset; mRate = orig.mRate; mSequence = new Sequence(*orig.mSequence, projDirManager); mEnvelope = new Envelope(); mEnvelope->Paste(0.0, orig.mEnvelope); mEnvelope->SetOffset(orig.GetOffset()); mEnvelope->SetTrackLen(((double)orig.mSequence->GetNumSamples()) / orig.mRate); mWaveCache = new WaveCache(1); #ifdef EXPERIMENTAL_USE_REALFFTF mWindowType = -1; mWindowSize = -1; hFFT = NULL; mWindow = NULL; #endif mSpecCache = new SpecCache(1, 1, false); mSpecPxCache = new SpecPxCache(1); for (WaveClipList::compatibility_iterator it=orig.mCutLines.GetFirst(); it; it=it->GetNext()) mCutLines.Append(new WaveClip(*it->GetData(), projDirManager)); mAppendBuffer = NULL; mAppendBufferLen = 0; mDirty = 0; mIsPlaceholder = orig.GetIsPlaceholder(); }
bool WaveTrack::SplitAt(double t) { for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* c = it->GetData(); if (t > c->GetStartTime() && t < c->GetEndTime()) { WaveClip* newClip = new WaveClip(*c, mDirManager); if (!c->Clear(t, c->GetEndTime())) { delete newClip; return false; } if (!newClip->Clear(c->GetStartTime(), t)) { delete newClip; return false; } newClip->Offset(t - c->GetStartTime()); mClips.Append(newClip); return true; } } return true; }
///by default creates the order of the wavetrack to load. void ODDecodeTask::Update() { std::vector<ODDecodeBlockFile*> tempBlocks; mWaveTrackMutex.Lock(); for(size_t j=0;j<mWaveTracks.size();j++) { if(mWaveTracks[j]) { WaveClip *clip; BlockArray *blocks; Sequence *seq; //gather all the blockfiles that we should process in the wavetrack. WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator(); while(node) { clip = node->GetData(); seq = clip->GetSequence(); //TODO:this lock is way to big since the whole file is one sequence. find a way to break it down. seq->LockDeleteUpdateMutex(); //See Sequence::Delete() for why need this for now.. blocks = clip->GetSequenceBlockArray(); int i; int insertCursor; insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n) for(i=0; i<(int)blocks->GetCount(); i++) { //since we have more than one ODBlockFile, we will need type flags to cast. if(!blocks->Item(i)->f->IsDataAvailable() && ((ODDecodeBlockFile*)blocks->Item(i)->f)->GetDecodeType()==this->GetODType()) { blocks->Item(i)->f->Ref(); ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start); ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); //these will always be linear within a sequence-lets take advantage of this by keeping a cursor. while(insertCursor<(int)tempBlocks.size()&& (sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) < (sampleCount)(((ODDecodeBlockFile*)blocks->Item(i)->f)->GetStart()+((ODDecodeBlockFile*)blocks->Item(i)->f)->GetClipOffset())) insertCursor++; tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODDecodeBlockFile*)blocks->Item(i)->f); } } seq->UnlockDeleteUpdateMutex(); node = node->GetNext(); } } } mWaveTrackMutex.Unlock(); //get the new order. OrderBlockFiles(tempBlocks); }
Sequence* WaveTrack::GetSequenceAtX(int xcoord) { WaveClip* clip = GetClipAtX(xcoord); if (clip) return clip->GetSequence(); else return NULL; }
Envelope* WaveTrack::GetEnvelopeAtX(int xcoord) { WaveClip* clip = GetClipAtX(xcoord); if (clip) return clip->GetEnvelope(); else return NULL; }
bool WaveClip::Clear(double t0, double t1) { sampleCount s0, s1; TimeToSamplesClip(t0, &s0); TimeToSamplesClip(t1, &s1); if (GetSequence()->Delete(s0, s1-s0)) { // msmeyer // // Delete all cutlines that are within the given area, if any. // // Note that when cutlines are active, two functions are used: // Clear() and ClearAndAddCutLine(). ClearAndAddCutLine() is called // whenever the user directly calls a command that removes some audio, e.g. // "Cut" or "Clear" from the menu. This command takes care about recursive // preserving of cutlines within clips. Clear() is called when internal // operations want to remove audio. In the latter case, it is the right // thing to just remove all cutlines within the area. // double clip_t0 = t0; double clip_t1 = t1; if (clip_t0 < GetStartTime()) clip_t0 = GetStartTime(); if (clip_t1 > GetEndTime()) clip_t1 = GetEndTime(); WaveClipList::compatibility_iterator nextIt; for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=nextIt) { nextIt = it->GetNext(); WaveClip* clip = it->GetData(); double cutlinePosition = mOffset + clip->GetOffset(); if (cutlinePosition >= t0 && cutlinePosition <= t1) { // This cutline is within the area, delete it delete clip; mCutLines.DeleteNode(it); } else if (cutlinePosition >= t1) { clip->Offset(clip_t0-clip_t1); } } // Collapse envelope GetEnvelope()->CollapseRegion(t0, t1); if (t0 < GetStartTime()) Offset(-(GetStartTime() - t0)); MarkChanged(); return true; } return false; }
void WaveClip::OffsetCutLines(double t0, double len) { for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=it->GetNext()) { WaveClip* cutLine = it->GetData(); if (mOffset + cutLine->GetOffset() >= t0) cutLine->Offset(len); } }
WaveClip* WaveTrack::GetLastOrCreateClip() { if (mClips.IsEmpty()) { WaveClip *clip = CreateClip(); clip->SetOffset(mOffset); return clip; } else return mClips.GetLast()->GetData(); }
void WaveTrack::GetEnvelopeValues(double *buffer, int bufferLen, double t0, double tstep) { memset(buffer, 0, sizeof(double)*bufferLen); double startTime = t0; double endTime = t0+tstep*bufferLen; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); if (clip->GetStartTime() < endTime && clip->GetEndTime() > startTime) { double* rbuf = buffer; int rlen = bufferLen; double rt0 = t0; if (rt0 < clip->GetStartTime()) { int dx = (int) floor((clip->GetStartTime() - rt0) / tstep + 0.5); rbuf += dx; rlen -= dx; rt0 = clip->GetStartTime(); } if (rt0+rlen*tstep > clip->GetEndTime()) { rlen = (int) ((clip->GetEndTime()-rt0) / tstep); } clip->GetEnvelope()->GetValues(rbuf, rlen, rt0, tstep); } } }
bool WaveTrack::CanInsertClip(WaveClip* clip) { for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* c = it->GetData(); if (c->GetStartTime() < clip->GetEndTime() && c->GetEndTime() > clip->GetStartTime()) return false; // clips overlap } return true; }
void WaveTrack::SetOffset(double o) { double delta = o - GetOffset(); for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); clip->SetOffset(clip->GetOffset() + delta); } mOffset = o; }
// Find out how much additional space was used to execute // this operation. // // Computed by getting a list of all blocks referenced by // *this* TrackList and removing all blocks referenced by // any previous TrackList. wxLongLong TrackList::GetAdditionalSpaceUsage(UndoStack *stack) { TrackListNode *p; // get a map of all blocks referenced in this TrackList std::map<BlockFile*,wxLongLong> curBlockFiles; for (p = head; p; p = p->next) { if (p->t->GetKind() == Track::Wave) { WaveTrack* track = ((WaveTrack*)p->t); for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); BlockArray *blocks = clip->GetSequenceBlockArray(); for (unsigned int i = 0; i < blocks->GetCount(); i++) curBlockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage(); } } } // get a set of all blocks referenced in all prev TrackList std::set<BlockFile*> prevBlockFiles; unsigned int undoStackIdx = 0; for (; undoStackIdx < stack->GetCount(); undoStackIdx++) { UndoStackElem *stackElem = stack->Item(undoStackIdx); if (stackElem->tracks == this) break; for (p = stackElem->tracks->head; p; p = p->next) { if (p->t->GetKind() == Track::Wave) { WaveTrack* track = ((WaveTrack*)p->t); for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); BlockArray *blocks = clip->GetSequenceBlockArray(); for (unsigned int i = 0; i < blocks->GetCount(); i++) prevBlockFiles.insert(blocks->Item(i)->f); } } } } // remove all blocks in prevBlockFiles from curBlockFiles std::set<BlockFile*>::const_iterator prevIter = prevBlockFiles.begin(); for (; prevIter != prevBlockFiles.end(); prevIter++) curBlockFiles.erase(*prevIter); // sum the sizes of the blocks remaining in curBlockFiles; std::map<BlockFile*,wxLongLong>::const_iterator curBfIter = curBlockFiles.begin(); wxLongLong bytes = 0; for (;curBfIter != curBlockFiles.end(); curBfIter++) bytes += curBfIter->second; return bytes; }
bool WaveTrack::Get(samplePtr buffer, sampleFormat format, longSampleCount start, sampleCount len) { // Simple optimization: When this buffer is completely contained within one clip, // don't clear anything (because we never won't have to). Otherwise, just clear // everything to be on the safe side. WaveClipList::Node* it; bool doClear = true; for (it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); if (start >= clip->GetStartSample() && start+len <= clip->GetEndSample()) { doClear = false; break; } } if (doClear) ClearSamples(buffer, format, 0, len); for (it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); longSampleCount clipStart = clip->GetStartSample(); longSampleCount clipEnd = clip->GetEndSample(); if (clipEnd > start && clipStart < start+len) { // Clip sample region and Get/Put sample region overlap sampleCount samplesToCopy = start+len - clipStart; if (samplesToCopy > clip->GetNumSamples()) samplesToCopy = clip->GetNumSamples(); longSampleCount inclipDelta = 0; longSampleCount startDelta = clipStart - start; if (startDelta < 0) { inclipDelta = -startDelta; // make positive value samplesToCopy -= inclipDelta; startDelta = 0; } if (!clip->GetSamples((samplePtr)(((char*)buffer)+startDelta*SAMPLE_SIZE(format)), format, inclipDelta, samplesToCopy)) { wxASSERT(false); // should always work return false; } } } return true; }
bool WaveClip::ExpandCutLine(double cutLinePosition) { for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=it->GetNext()) { WaveClip* cutline = it->GetData(); if (fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001) { if (!Paste(mOffset+cutline->GetOffset(), cutline)) return false; delete cutline; mCutLines.DeleteNode(it); return true; } } return false; }
bool WaveTrack::InsertSilence(double t, double len) { if (len <= 0) return false; if (mClips.IsEmpty()) { // Special case if there is no clip yet WaveClip* clip = CreateClip(); return clip->InsertSilence(0, len); } for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); if (clip->GetStartTime() > t) clip->Offset(len); else if (clip->GetEndTime() > t) { return clip->InsertSilence(t, len); } } return true; }
void WaveTrack::UpdateLocationsCache() { WaveClipList::Node *it, *jt; mDisplayNumLocations = 0; for (it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); mDisplayNumLocations += clip->GetCutLines()->GetCount(); for (jt=GetClipIterator(); jt; jt=jt->GetNext()) { WaveClip* clip2 = jt->GetData(); if (clip != clip2 && fabs(clip->GetEndTime()-clip2->GetStartTime()) < WAVETRACK_MERGE_POINT_TOLERANCE) mDisplayNumLocations++; } } if (mDisplayNumLocations == 0) return; if (mDisplayNumLocations > mDisplayNumLocationsAllocated) { // Only realloc, if we need more space than before. Otherwise // just use block from before. if (mDisplayLocations) delete[] mDisplayLocations; mDisplayLocations = new Location[mDisplayNumLocations]; mDisplayNumLocationsAllocated = mDisplayNumLocations; } int curpos = 0; for (it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); WaveClipList* cutlines = clip->GetCutLines(); for (jt = cutlines->GetFirst(); jt; jt=jt->GetNext()) { mDisplayLocations[curpos].typ = locationCutLine; mDisplayLocations[curpos].pos = jt->GetData()->GetOffset() + it->GetData()->GetOffset(); curpos++; } for (jt=GetClipIterator(); jt; jt=jt->GetNext()) { WaveClip* clip2 = jt->GetData(); if (clip != clip2 && fabs(clip->GetEndTime()-clip2->GetStartTime()) < WAVETRACK_MERGE_POINT_TOLERANCE) { mDisplayLocations[curpos].typ = locationMergePoint; mDisplayLocations[curpos].pos = clip->GetEndTime(); mDisplayLocations[curpos].clipidx1 = mClips.IndexOf(clip); mDisplayLocations[curpos].clipidx2 = mClips.IndexOf(clip2); curpos++; } } } }
sampleCount WaveTrack::GetBestBlockSize(longSampleCount s) { sampleCount bestBlockSize = GetMaxBlockSize(); for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); longSampleCount startSample = (longSampleCount)floor(clip->GetStartTime()*mRate + 0.5); longSampleCount endSample = startSample + clip->GetNumSamples(); if (s >= startSample && s < endSample) { bestBlockSize = clip->GetSequence()->GetMaxBlockSize(); break; } } return bestBlockSize; }
///by default creates the order of the wavetrack to load. void ODComputeSummaryTask::Update() { std::vector<ODPCMAliasBlockFile*> tempBlocks; mWaveTrackMutex.Lock(); if(mWaveTrack) { WaveClip *clip; BlockArray *blocks; Sequence *seq; //gather all the blockfiles that we should process in the wavetrack. WaveClipList::Node* node = mWaveTrack->GetClipIterator(); while(node) { clip = node->GetData(); seq = clip->GetSequence(); //TODO:this lock is way to big since the whole file is one sequence. find a way to break it down. seq->LockDeleteUpdateMutex(); //See Sequence::Delete() for why need this for now.. blocks = clip->GetSequenceBlockArray(); int i; for(i=0; i<(int)blocks->GetCount(); i++) { //in the future if we have more than one ODBlockFile, we will need type flags to cast. if(!blocks->Item(i)->f->IsSummaryAvailable()) { blocks->Item(i)->f->Ref(); ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start); tempBlocks.push_back((ODPCMAliasBlockFile*)blocks->Item(i)->f); } } seq->UnlockDeleteUpdateMutex(); node = node->GetNext(); } } mWaveTrackMutex.Unlock(); //get the new order. OrderBlockFiles(tempBlocks); }
bool WaveClip::FindCutLine(double cutLinePosition, double* cutlineStart /* = NULL */, double* cutlineEnd /* = NULL */) { for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=it->GetNext()) { WaveClip* cutline = it->GetData(); if (fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001) { if (cutlineStart) *cutlineStart = mOffset+cutline->GetStartTime(); if (cutlineEnd) *cutlineEnd = mOffset+cutline->GetEndTime(); return true; } } return false; }
bool WaveClip::Paste(double t0, WaveClip* other) { WaveClip* pastedClip; bool clipNeedsResampling = other->mRate != mRate; if (clipNeedsResampling) { // The other clip's rate is different to our's, so resample pastedClip = new WaveClip(*other, mSequence->GetDirManager()); if (!pastedClip->Resample(mRate)) { delete pastedClip; return false; } } else { // No resampling needed, just use original clip without making a copy pastedClip = other; } sampleCount s0; TimeToSamplesClip(t0, &s0); // Force sample formats to match. if (pastedClip->mSequence->GetSampleFormat() != mSequence->GetSampleFormat()) pastedClip->ConvertToSampleFormat(mSequence->GetSampleFormat()); bool result = false; if (mSequence->Paste(s0, pastedClip->mSequence)) { MarkChanged(); mEnvelope->Paste((double)s0/mRate + mOffset, pastedClip->mEnvelope); mEnvelope->RemoveUnneededPoints(); OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime()); // Paste cut lines contained in pasted clip for (WaveClipList::compatibility_iterator it = pastedClip->mCutLines.GetFirst(); it; it=it->GetNext()) { WaveClip* cutline = it->GetData(); WaveClip* newCutLine = new WaveClip(*cutline, mSequence->GetDirManager()); newCutLine->Offset(t0 - mOffset); mCutLines.Append(newCutLine); } result = true; } if (clipNeedsResampling) { // Clip was constructed as a copy, so delete it delete pastedClip; } return result; }
// Given a project, returns a single array of all SeqBlocks // in the current set of tracks. Enumerating that array allows // you to process all block files in the current set. void GetAllSeqBlocks(AudacityProject *project, BlockArray *outBlocks) { TrackList *tracks = project->GetTracks(); TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { if (t->GetKind() == Track::Wave) { WaveTrack *waveTrack = (WaveTrack *)t; WaveClipList::compatibility_iterator node = waveTrack->GetClipIterator(); while(node) { WaveClip *clip = node->GetData(); Sequence *sequence = clip->GetSequence(); BlockArray *blocks = sequence->GetBlockArray(); int i; for (i = 0; i < (int)blocks->GetCount(); i++) outBlocks->Add(blocks->Item(i)); node = node->GetNext(); } } t = iter.Next(); } }
bool WaveTrack::IsEmpty(double t0, double t1) { WaveClipList::Node* it; //printf("Searching for overlap in %.6f...%.6f\n", t0, t1); for (it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); if (clip->GetStartTime() < t1-(1.0/mRate) && clip->GetEndTime()-(1.0/mRate) > t0) { //printf("Overlapping clip: %.6f...%.6f\n", // clip->GetStartTime(), // clip->GetEndTime()); // We found a clip that overlaps this region return false; } } //printf("No overlap found\n"); // Otherwise, no clips overlap this region return true; }
sampleCount WaveTrack::GetMaxBlockSize() { int maxblocksize = 0; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); if (clip->GetSequence()->GetMaxBlockSize() > maxblocksize) maxblocksize = clip->GetSequence()->GetMaxBlockSize(); } if (maxblocksize == 0) { // We really need the maximum block size, so create a // temporary sequence to get it. Sequence *tempseq = new Sequence(mDirManager, mFormat); maxblocksize = tempseq->GetMaxBlockSize(); delete tempseq; } wxASSERT(maxblocksize > 0); return maxblocksize; }
// get the sum of the sizes of all blocks this track list // references. However, if a block is referred to multiple // times it is only counted once. Return value is in bytes wxLongLong TrackList::GetSpaceUsage() { // the map guarantees that I only count each block once std::map<BlockFile*,wxLongLong> blockFiles; for (TrackListNode *p = head; p; p = p->next) { if (p->t->GetKind() == Track::Wave) { WaveTrack* track = ((WaveTrack*)p->t); for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); BlockArray *blocks = clip->GetSequenceBlockArray(); for (unsigned int i = 0; i < blocks->GetCount(); i++) blockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage(); } } } std::map<BlockFile*,wxLongLong>::const_iterator bfIter; wxLongLong bytes = 0; for (bfIter = blockFiles.begin(); bfIter != blockFiles.end(); bfIter++) bytes += bfIter->second; return bytes; }
bool WaveTrack::GetMinMax(float *min, float *max, double t0, double t1) { *min = float(0.0); *max = float(0.0); if (t0 > t1) return false; if (t0 == t1) return true; bool result = true; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); if (t1 >= clip->GetStartTime() && t0 <= clip->GetEndTime()) { float clipmin, clipmax; if (it->GetData()->GetMinMax(&clipmin, &clipmax, t0, t1)) { if (clipmin < *min) *min = clipmin; if (clipmax > *max) *max = clipmax; } else { result = false; } } } return result; }
bool WaveTrack::CanOffsetClip(WaveClip* clip, double amount, double *allowedAmount /* = NULL */) { if (allowedAmount) *allowedAmount = amount; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip* c = it->GetData(); if (c != clip && c->GetStartTime() < clip->GetEndTime()+amount && c->GetEndTime() > clip->GetStartTime()+amount) { if (!allowedAmount) return false; // clips overlap if (amount > 0) { if (c->GetStartTime()-clip->GetEndTime() < *allowedAmount) *allowedAmount = c->GetStartTime()-clip->GetEndTime(); if (*allowedAmount < 0) *allowedAmount = 0; } else { if (c->GetEndTime()-clip->GetStartTime() > *allowedAmount) *allowedAmount = c->GetEndTime()-clip->GetStartTime(); if (*allowedAmount > 0) *allowedAmount = 0; } } } if (allowedAmount) { if (*allowedAmount == amount) return true; // Check if the new calculated amount would not violate // any other constraint if (!CanOffsetClip(clip, *allowedAmount, NULL)) { *allowedAmount = 0; // play safe and don't allow anything return false; } else return true; } else return true; }
bool WaveTrack::Silence(double t0, double t1) { if (t1 < t0) return false; longSampleCount start = (longSampleCount)floor(t0 * mRate + 0.5); longSampleCount len = (longSampleCount)floor(t1 * mRate + 0.5) - start; bool result = true; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); longSampleCount clipStart = clip->GetStartSample(); longSampleCount clipEnd = clip->GetEndSample(); if (clipEnd > start && clipStart < start+len) { // Clip sample region and Get/Put sample region overlap sampleCount samplesToCopy = start+len - clipStart; if (samplesToCopy > clip->GetNumSamples()) samplesToCopy = clip->GetNumSamples(); longSampleCount inclipDelta = 0; longSampleCount startDelta = clipStart - start; if (startDelta < 0) { inclipDelta = -startDelta; // make positive value samplesToCopy -= inclipDelta; startDelta = 0; } if (!clip->GetSequence()->SetSilence(inclipDelta, samplesToCopy)) { wxASSERT(false); // should always work return false; } clip->MarkChanged(); } } return result; }
bool WaveTrack::Set(samplePtr buffer, sampleFormat format, longSampleCount start, sampleCount len) { bool result = true; for (WaveClipList::Node* it=GetClipIterator(); it; it=it->GetNext()) { WaveClip *clip = it->GetData(); longSampleCount clipStart = clip->GetStartSample(); longSampleCount clipEnd = clip->GetEndSample(); if (clipEnd > start && clipStart < start+len) { // Clip sample region and Get/Put sample region overlap sampleCount samplesToCopy = start+len - clipStart; if (samplesToCopy > clip->GetNumSamples()) samplesToCopy = clip->GetNumSamples(); longSampleCount inclipDelta = 0; longSampleCount startDelta = clipStart - start; if (startDelta < 0) { inclipDelta = -startDelta; // make positive value samplesToCopy -= inclipDelta; startDelta = 0; } if (!clip->SetSamples((samplePtr)(((char*)buffer)+startDelta*SAMPLE_SIZE(format)), format, inclipDelta, samplesToCopy)) { wxASSERT(false); // should always work return false; } clip->MarkChanged(); } } return result; }
bool WaveClip::ClearAndAddCutLine(double t0, double t1) { if (t0 > GetEndTime() || t1 < GetStartTime()) return true; // time out of bounds WaveClip *newClip = new WaveClip(mSequence->GetDirManager(), mSequence->GetSampleFormat(), mRate); double clip_t0 = t0; double clip_t1 = t1; if (clip_t0 < GetStartTime()) clip_t0 = GetStartTime(); if (clip_t1 > GetEndTime()) clip_t1 = GetEndTime(); if (!newClip->CreateFromCopy(clip_t0, clip_t1, this)) return false; newClip->SetOffset(clip_t0-mOffset); // Sort out cutlines that belong to the new cutline WaveClipList::compatibility_iterator nextIt; for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=nextIt) { nextIt = it->GetNext(); WaveClip* clip = it->GetData(); double cutlinePosition = mOffset + clip->GetOffset(); if (cutlinePosition >= t0 && cutlinePosition <= t1) { clip->SetOffset(cutlinePosition - newClip->GetOffset() - mOffset); newClip->mCutLines.Append(clip); mCutLines.DeleteNode(it); } else if (cutlinePosition >= t1) { clip->Offset(clip_t0-clip_t1); } } // Clear actual audio data sampleCount s0, s1; TimeToSamplesClip(t0, &s0); TimeToSamplesClip(t1, &s1); if (GetSequence()->Delete(s0, s1-s0)) { // Collapse envelope GetEnvelope()->CollapseRegion(t0, t1); if (t0 < GetStartTime()) Offset(-(GetStartTime() - t0)); MarkChanged(); mCutLines.Append(newClip); return true; } else { delete newClip; return false; } }