Ejemplo n.º 1
0
bool EffectReverse::ProcessOneWave(int count, WaveTrack * track, sampleCount start, sampleCount len)
{
   bool rValue = true; // return value

   sampleCount end = (sampleCount) start + len; // start, end, len refer to the selected reverse region

   // STEP 1:
   // If a reverse selection begins and/or ends at the inside of a clip
   // perform a split at the start and/or end of the reverse selection
   WaveClipList::compatibility_iterator node = track->GetClipIterator();
   while (node) {
      WaveClip *clip = node->GetData();
      sampleCount clipStart = clip->GetStartSample();
      sampleCount clipEnd = clip->GetEndSample();
      if (clipStart < start && clipEnd > start && clipEnd <= end) { // the reverse selection begins at the inside of a clip
         double splitTime = track->LongSamplesToTime(start);
         track->SplitAt(splitTime);
      }
      else if (clipStart >= start && clipStart < end && clipEnd > end) { // the reverse selection ends at the inside of a clip
         double splitTime = track->LongSamplesToTime(end);
         track->SplitAt(splitTime);
      }
      else if (clipStart < start && clipEnd > end) { // the selection begins AND ends at the inside of a clip
         double splitTime = track->LongSamplesToTime(start);
         track->SplitAt(splitTime);
         splitTime = track->LongSamplesToTime(end);
         track->SplitAt(splitTime);
      }
      node = node->GetNext();
   }

   //STEP 2:
   // Individually reverse each clip inside the selected region
   // and apply the appropriate offset after detaching them from the track

   bool checkedFirstClip = false;
   
   // used in calculating the offset of clips to rearrange
   // holds the new end position of the current clip
   sampleCount currentEnd = (sampleCount)end;
   
   WaveClipList revClips; // holds the reversed clips
   WaveClipList otherClips; // holds the clips that appear after the reverse selection region
   WaveClipArray clipArray;
   track->FillSortedClipArray(clipArray);
   size_t i;
   for (i=0; i < clipArray.Count(); i++) {
      
      WaveClip *clip = clipArray.Item(i);
      sampleCount clipStart = clip->GetStartSample();
      sampleCount clipEnd = clip->GetEndSample();
            
      if (clipStart >= start && clipEnd <= end) { // if the clip is inside the selected region
         
         // this is used to check if the selected region begins with a whitespace.
         // if yes then clipStart (of the first clip) and start are not the same.
         // adjust currentEnd accordingly and set endMerge to false
         if(checkedFirstClip == false && clipStart > start) { 
            checkedFirstClip = true;
            if(i > 0) {
               if (clipArray.Item(i-1)->GetEndSample() <= start) {
                  currentEnd -= (clipStart - start);
               }
            }
            else {
               currentEnd -= (clipStart - start);
            }
         }
         
         sampleCount revStart = (clipStart >= start)? clipStart: start;
         sampleCount revEnd = (clipEnd >= end)? end: clipEnd;
         sampleCount revLen = (sampleCount)revEnd-revStart;
         if (revEnd >= revStart) {
            if(!ProcessOneClip(count, track, revStart, revLen, start, end)) // reverse the clip
            {
               rValue = false;
               break;
            }

            sampleCount clipOffsetStart = (sampleCount)(currentEnd - (clipEnd-clipStart)); // calculate the offset required
            double offsetStartTime = track->LongSamplesToTime(clipOffsetStart);
            if(i+1 < clipArray.Count()) // update currentEnd if there is a clip to process next
            {
               sampleCount nextClipStart = clipArray.Item(i+1)->GetStartSample();
               currentEnd = (sampleCount)(currentEnd - (clipEnd - clipStart) - (nextClipStart - clipEnd));
            }

            clip = track->RemoveAndReturnClip(clip); // detach the clip from track
            clip->SetOffset(track->LongSamplesToTime(track->TimeToLongSamples(offsetStartTime))); // align time to a sample and set offset
            revClips.Append(clip);
            
         }
      }
      else if (clipStart >= end) { // clip is after the selection region
         clip = track->RemoveAndReturnClip(clip); // simply remove and append to otherClips
         otherClips.Append(clip);
      }
   }
   
   // STEP 3: Append the clips from
   // revClips and otherClips back to the track
   size_t revClipsCount = revClips.GetCount();
   for (i = 0; i < revClipsCount; i++) {
      WaveClipList::compatibility_iterator node = revClips.Item(revClipsCount - 1 - i); // the last clip of revClips is appended to the track first
      WaveClip *clip = node->GetData();
      track->AddClip(clip);
   }

   for (i = 0; i < otherClips.GetCount(); i++) {
      WaveClipList::compatibility_iterator node = otherClips.Item(i);
      track->AddClip(node->GetData());
   }

   return rValue;
}
Ejemplo n.º 2
0
bool EffectReverse::ProcessOneWave(int count, WaveTrack * track, sampleCount start, sampleCount len)
{
   bool rValue = true; // return value

   auto end = start + len; // start, end, len refer to the selected reverse region

   // STEP 1:
   // If a reverse selection begins and/or ends at the inside of a clip
   // perform a split at the start and/or end of the reverse selection
   const auto &clips = track->GetClips();
   // Beware, the array grows as we loop over it.  Use integer subscripts, not iterators.
   for (int ii = 0; ii < clips.size(); ++ii) {
      const auto &clip = clips[ii].get();
      auto clipStart = clip->GetStartSample();
      auto clipEnd = clip->GetEndSample();
      if (clipStart < start && clipEnd > start && clipEnd <= end) { // the reverse selection begins at the inside of a clip
         double splitTime = track->LongSamplesToTime(start);
         track->SplitAt(splitTime);
      }
      else if (clipStart >= start && clipStart < end && clipEnd > end) { // the reverse selection ends at the inside of a clip
         double splitTime = track->LongSamplesToTime(end);
         track->SplitAt(splitTime);
      }
      else if (clipStart < start && clipEnd > end) { // the selection begins AND ends at the inside of a clip
         double splitTime = track->LongSamplesToTime(start);
         track->SplitAt(splitTime);
         splitTime = track->LongSamplesToTime(end);
         track->SplitAt(splitTime);
      }
   }

   //STEP 2:
   // Individually reverse each clip inside the selected region
   // and apply the appropriate offset after detaching them from the track

   bool checkedFirstClip = false;

   // used in calculating the offset of clips to rearrange
   // holds the NEW end position of the current clip
   auto currentEnd = end;

   WaveClipHolders revClips; // holds the reversed clips
   WaveClipHolders otherClips; // holds the clips that appear after the reverse selection region
   auto clipArray = track->SortedClipArray();
   size_t i;
   for (i=0; i < clipArray.size(); i++) {

      WaveClip *clip = clipArray[i];
      auto clipStart = clip->GetStartSample();
      auto clipEnd = clip->GetEndSample();

      if (clipStart >= start && clipEnd <= end) { // if the clip is inside the selected region

         // this is used to check if the selected region begins with a whitespace.
         // if yes then clipStart (of the first clip) and start are not the same.
         // adjust currentEnd accordingly and set endMerge to false
         if(checkedFirstClip == false && clipStart > start) {
            checkedFirstClip = true;
            if(i > 0) {
               if (clipArray[i-1]->GetEndSample() <= start) {
                  currentEnd -= (clipStart - start);
               }
            }
            else {
               currentEnd -= (clipStart - start);
            }
         }

         auto revStart = (clipStart >= start)? clipStart: start;
         auto revEnd = (clipEnd >= end)? end: clipEnd;
         auto revLen = revEnd - revStart;
         if (revEnd >= revStart) {
            if(!ProcessOneClip(count, track, revStart, revLen, start, end)) // reverse the clip
            {
               rValue = false;
               break;
            }

            auto clipOffsetStart = currentEnd - (clipEnd - clipStart); // calculate the offset required
            double offsetStartTime = track->LongSamplesToTime(clipOffsetStart);
            if(i+1 < clipArray.size()) // update currentEnd if there is a clip to process next
            {
               auto nextClipStart = clipArray[i+1]->GetStartSample();
               currentEnd = currentEnd - (clipEnd - clipStart) - (nextClipStart - clipEnd);
            }

            revClips.push_back(track->RemoveAndReturnClip(clip)); // detach the clip from track
            revClips.back()->SetOffset(track->LongSamplesToTime(track->TimeToLongSamples(offsetStartTime))); // align time to a sample and set offset
         }
      }
      else if (clipStart >= end) { // clip is after the selection region
         otherClips.push_back(track->RemoveAndReturnClip(clip)); // simply remove and append to otherClips
      }
   }

   // STEP 3: Append the clips from
   // revClips and otherClips back to the track
   // the last clip of revClips is appended to the track first
   // PRL:  I don't think that matters, the sequence of storage of clips in the track
   // is not elsewhere assumed to be by time
   for (auto it = revClips.rbegin(), end = revClips.rend(); it != end; ++it)
      track->AddClip(std::move(*it));

   for (auto &clip : otherClips)
      track->AddClip(std::move(clip));

   return rValue;
}