Ejemplo n.º 1
0
bool Generator::Process()
{
   if (GetDuration() < 0.0)
      return false;


   // Set up mOutputTracks.
   // This effect needs Track::All for sync-lock grouping.
   this->CopyInputTracks(Track::All);

   // Iterate over the tracks
   bool bGoodResult = true;
   int ntrack = 0;
   TrackListIterator iter(mOutputTracks);
   Track* t = iter.First();

   while (t != NULL)
   {
      if (t->GetKind() == Track::Wave && t->GetSelected()) {
         WaveTrack* track = (WaveTrack*)t;

         bool editClipCanMove;
         gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true);

         //if we can't move clips, and we're generating into an empty space,
         //make sure there's room.
         if (!editClipCanMove &&
             track->IsEmpty(mT0, mT1+1.0/track->GetRate()) &&
             !track->IsEmpty(mT0, mT0+GetDuration()-(mT1-mT0)-1.0/track->GetRate()))
         {
            wxMessageBox(
                  _("There is not enough room available to generate the audio"),
                  _("Error"), wxICON_STOP);
            Failure();
            return false;
         }

         if (GetDuration() > 0.0)
         {
            AudacityProject *p = GetActiveProject();
            // Create a temporary track
            std::unique_ptr<WaveTrack> tmp(
               mFactory->NewWaveTrack(track->GetSampleFormat(),
               track->GetRate())
            );
            BeforeTrack(*track);
            BeforeGenerate();

            // Fill it with data
            if (!GenerateTrack(&*tmp, *track, ntrack))
               bGoodResult = false;
            else {
               // Transfer the data from the temporary track to the actual one
               tmp->Flush();
               SetTimeWarper(new StepTimeWarper(mT0+GetDuration(), GetDuration()-(mT1-mT0)));
               bGoodResult = track->ClearAndPaste(p->GetSel0(), p->GetSel1(), &*tmp, true,
                     false, GetTimeWarper());
            }

            if (!bGoodResult) {
               Failure();
               return false;
            }
         }
         else
         {
            // If the duration is zero, there's no need to actually
            // generate anything
            track->Clear(mT0, mT1);
         }

         ntrack++;
      }
      else if (t->IsSyncLockSelected()) {
         t->SyncLockAdjust(mT1, mT0 + GetDuration());
      }
      // Move on to the next track
      t = iter.Next();
   }

   Success();

   this->ReplaceProcessedTracks(bGoodResult);

   mT1 = mT0 + GetDuration(); // Update selection.

   return true;
}
Ejemplo n.º 2
0
bool EffectSBSMS::Process()
{
   bool bGoodResult = true;

   //Iterate over each track
   //Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
   this->CopyInputTracks(Track::All); // Set up mOutputTracks.
   TrackListIterator iter(mOutputTracks);
   Track* t;
   mCurTrackNum = 0;

   double maxDuration = 0.0;

   // Must sync if selection length will change
   bool mustSync = (rateStart != rateEnd);
   Slide rateSlide(rateSlideType,rateStart,rateEnd);
   Slide pitchSlide(pitchSlideType,pitchStart,pitchEnd);
   mTotalStretch = rateSlide.getTotalStretch();

   t = iter.First();
   while (t != NULL) {
      if (t->GetKind() == Track::Label &&
            (t->GetSelected() || (mustSync && t->IsSyncLockSelected())) )
      {
         if (!ProcessLabelTrack(t)) {
            bGoodResult = false;
            break;
         }
      }
      else if (t->GetKind() == Track::Wave && t->GetSelected() )
      {
         WaveTrack* leftTrack = (WaveTrack*)t;

         //Get start and end times from track
         mCurT0 = leftTrack->GetStartTime();
         mCurT1 = leftTrack->GetEndTime();

         //Set the current bounds to whichever left marker is
         //greater and whichever right marker is less
         mCurT0 = wxMax(mT0, mCurT0);
         mCurT1 = wxMin(mT1, mCurT1);

         // Process only if the right marker is to the right of the left marker
         if (mCurT1 > mCurT0) {
            sampleCount start;
            sampleCount end;
            start = leftTrack->TimeToLongSamples(mCurT0);
            end = leftTrack->TimeToLongSamples(mCurT1);

            WaveTrack* rightTrack = NULL;
            if (leftTrack->GetLinked()) {
               double t;
               rightTrack = (WaveTrack*)(iter.Next());

               //Adjust bounds by the right tracks markers
               t = rightTrack->GetStartTime();
               t = wxMax(mT0, t);
               mCurT0 = wxMin(mCurT0, t);
               t = rightTrack->GetEndTime();
               t = wxMin(mT1, t);
               mCurT1 = wxMax(mCurT1, t);

               //Transform the marker timepoints to samples
               start = leftTrack->TimeToLongSamples(mCurT0);
               end = leftTrack->TimeToLongSamples(mCurT1);

               mCurTrackNum++; // Increment for rightTrack, too.
            }
            sampleCount trackStart = leftTrack->TimeToLongSamples(leftTrack->GetStartTime());
            sampleCount trackEnd = leftTrack->TimeToLongSamples(leftTrack->GetEndTime());

            // SBSMS has a fixed sample rate - we just convert to its sample rate and then convert back
            float srTrack = leftTrack->GetRate();
            float srProcess = bLinkRatePitch?srTrack:44100.0;

            // the resampler needs a callback to supply its samples
            ResampleBuf rb;
            sampleCount maxBlockSize = leftTrack->GetMaxBlockSize();
            rb.blockSize = maxBlockSize;
            rb.buf = (audio*)calloc(rb.blockSize,sizeof(audio));
            rb.leftTrack = leftTrack;
            rb.rightTrack = rightTrack?rightTrack:leftTrack;
            rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
            rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));

            // Samples in selection
            sampleCount samplesIn = end-start;

            // Samples for SBSMS to process after resampling
            sampleCount samplesToProcess = (sampleCount) ((float)samplesIn*(srProcess/srTrack));

            SlideType outSlideType;
            SBSMSResampleCB outResampleCB;

            sampleCount processPresamples = 0;
            sampleCount trackPresamples = 0;

            if(bLinkRatePitch) {
              rb.bPitch = true;
              outSlideType = rateSlideType;
              outResampleCB = resampleCB;
              rb.offset = start;
              rb.end = end;
              rb.iface = new SBSMSInterfaceSliding(&rateSlide,&pitchSlide,
                                                       bPitchReferenceInput,
                                                       samplesToProcess,0,
                                                       NULL);
               
             
            } else {
              rb.bPitch = false;
              outSlideType = (srProcess==srTrack?SlideIdentity:SlideConstant);
              outResampleCB = postResampleCB;
              rb.ratio = srProcess/srTrack;
              rb.quality = new SBSMSQuality(&SBSMSQualityStandard);
              rb.resampler = new Resampler(resampleCB, &rb, srProcess==srTrack?SlideIdentity:SlideConstant);
              rb.sbsms = new SBSMS(rightTrack?2:1,rb.quality,true);
              rb.SBSMSBlockSize = rb.sbsms->getInputFrameSize();
              rb.SBSMSBuf = (audio*)calloc(rb.SBSMSBlockSize,sizeof(audio));

              processPresamples = wxMin(rb.quality->getMaxPresamples(),
                                        (long)((float)(start-trackStart)*(srProcess/srTrack)));
              trackPresamples = wxMin(start-trackStart,
                                      (long)((float)(processPresamples)*(srTrack/srProcess)));
              rb.offset = start - trackPresamples;
              rb.end = trackEnd;
              rb.iface = new SBSMSEffectInterface(rb.resampler,
                                                      &rateSlide,&pitchSlide,
                                                      bPitchReferenceInput,
                                                      samplesToProcess,processPresamples,
                                                      rb.quality);
            }
            
            Resampler resampler(outResampleCB,&rb,outSlideType);

            audio outBuf[SBSMSOutBlockSize];
            float outBufLeft[2*SBSMSOutBlockSize];
            float outBufRight[2*SBSMSOutBlockSize];

            // Samples in output after SBSMS
            sampleCount samplesToOutput = rb.iface->getSamplesToOutput();

            // Samples in output after resampling back
            sampleCount samplesOut = (sampleCount) ((float)samplesToOutput * (srTrack/srProcess));

            // Duration in track time
            double duration =  (mCurT1-mCurT0) * mTotalStretch;

            if(duration > maxDuration)
               maxDuration = duration;

            TimeWarper *warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
            SetTimeWarper(warper);

            rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
                                                        leftTrack->GetRate());
            if(rightTrack)
               rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
                                                            rightTrack->GetRate());
            long pos = 0;
            long outputCount = -1;

            // process
            while(pos<samplesOut && outputCount) {
               long frames;
               if(pos+SBSMSOutBlockSize>samplesOut) {
                  frames = samplesOut - pos;
               } else {
                  frames = SBSMSOutBlockSize;
               }
               outputCount = resampler.read(outBuf,frames);
               for(int i = 0; i < outputCount; i++) {
                  outBufLeft[i] = outBuf[i][0];
                  if(rightTrack)
                     outBufRight[i] = outBuf[i][1];
               }
               pos += outputCount;
               rb.outputLeftTrack->Append((samplePtr)outBufLeft, floatSample, outputCount);
               if(rightTrack)
                  rb.outputRightTrack->Append((samplePtr)outBufRight, floatSample, outputCount);

               double frac = (double)pos/(double)samplesOut;
               int nWhichTrack = mCurTrackNum;
               if(rightTrack) {
                  nWhichTrack = 2*(mCurTrackNum/2);
                  if (frac < 0.5)
                     frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
                  else {
                     nWhichTrack++;
                     frac -= 0.5;
                     frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
                  }
               }
               if (TrackProgress(nWhichTrack, frac))
                  return false;
            }
            rb.outputLeftTrack->Flush();
            if(rightTrack)
               rb.outputRightTrack->Flush();

            bool bResult =
               leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack,
                                          true, false, GetTimeWarper());
            wxASSERT(bResult); // TO DO: Actually handle this.
            wxUnusedVar(bResult);

            if(rightTrack)
            {
               bResult =
                  rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack,
                                             true, false, GetTimeWarper());
               wxASSERT(bResult); // TO DO: Actually handle this.
            }
         }
         mCurTrackNum++;
      }
      else if (mustSync && t->IsSyncLockSelected())
      {
         t->SyncLockAdjust(mCurT1, mCurT0 + (mCurT1 - mCurT0) * mTotalStretch);
      }
      //Iterate to the next track
      t = iter.Next();
   }

   if (bGoodResult)
      ReplaceProcessedTracks(bGoodResult);

   // Update selection
   mT0 = mCurT0;
   mT1 = mCurT0 + maxDuration;

   return bGoodResult;
}
Ejemplo n.º 3
0
//------------------------- Processing methods -------------------------
bool EffectSineSweepGenerator::Process()
{
   // taken `as is` from Audacity`s Generator.cpp to resolve
   // a vc++ linking problem...
   
   if (mDuration < 0.0)
      return false;

   BeforeGenerate();

   // Set up mOutputTracks. This effect needs Track::All for grouping
   this->CopyInputTracks(Track::All);

   // Iterate over the tracks
   bool bGoodResult = true;
   int ntrack = 0;
   TrackListIterator iter(mOutputTracks);
   Track* t = iter.First();

   while (t != NULL)
   {
      if (t->GetKind() == Track::Wave && t->GetSelected()) 
      {
         WaveTrack* track = (WaveTrack*)t;
         
         bool editClipCanMove = true;
         //gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true);

         //if we can't move clips, and we're generating into an empty space,
         //make sure there's room.
         if (!editClipCanMove &&
             track->IsEmpty(mT0, mT1+1.0/track->GetRate()) &&
             !track->IsEmpty(mT0, mT0+mDuration-(mT1-mT0)-1.0/track->GetRate()))
         {
             wxMessageBox(_("There is not enough room available to generate the audio"),
                          _("Error"), wxICON_STOP);   
            Failure();
            return false;
         }

         if (mDuration > 0.0)
         {
            // Create a temporary track
            WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(),
                                                    track->GetRate());
            //BeforeTrack(*track);

            // Fill it with data
            if (!GenerateTrack(tmp, *track, ntrack))
               bGoodResult = false;
            else 
            {
               // Transfer the data from the temporary track to the actual one
               tmp->Flush();
               SetTimeWarper(new AFStepTimeWarper(mT0+mDuration, mDuration-(mT1-mT0)));
               bGoodResult = track->ClearAndPaste(mT0, mT1, tmp, true,
                     false, GetTimeWarper());
               delete tmp;
            }

            if (!bGoodResult) 
            {
               Failure();
               return false;
            }
         }
         else
         {
            // If the duration is zero, there's no need to actually
            // generate anything
            track->Clear(mT0, mT1);
         }

         ntrack++;
      }
      else if (t->IsSyncLockSelected()) 
      {
         t->SyncLockAdjust(mT1, mT0 + mDuration);
      }
      // Move on to the next track
      t = iter.Next();
   }

   Success();

   this->ReplaceProcessedTracks(bGoodResult);

   mT1 = mT0 + mDuration; // Update selection.

   return true;
}
Ejemplo n.º 4
0
bool EffectSBSMS::Process()
{
   if(!bInit) {
      sbsms_init(4096);
      bInit = TRUE;
   }
   
   bool bGoodResult = true;
   
   //Iterate over each track
   //Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
   this->CopyInputTracks(Track::All); // Set up mOutputTracks.
   TrackListIterator iter(mOutputTracks);
   Track* t;
   mCurTrackNum = 0;

   double maxDuration = 0.0;

   if(rateStart == rateEnd)
      mTotalStretch = 1.0/rateStart;
   else
      mTotalStretch = 1.0/(rateEnd-rateStart)*log(rateEnd/rateStart);

   // Must sync if selection length will change
   bool mustSync = (mTotalStretch != 1.0);

   t = iter.First();
   while (t != NULL) {
      if (t->GetKind() == Track::Label && 
            (t->GetSelected() || (mustSync && t->IsSynchroSelected())) )
      {
         if (!ProcessLabelTrack(t)) {
            bGoodResult = false;
            break;
         }
      }
      else if (t->GetKind() == Track::Wave && t->GetSelected() )
      {
         WaveTrack* leftTrack = (WaveTrack*)t;

         //Get start and end times from track
         mCurT0 = leftTrack->GetStartTime();
         mCurT1 = leftTrack->GetEndTime();
         
         //Set the current bounds to whichever left marker is
         //greater and whichever right marker is less
         mCurT0 = wxMax(mT0, mCurT0);
         mCurT1 = wxMin(mT1, mCurT1);
         
         // Process only if the right marker is to the right of the left marker
         if (mCurT1 > mCurT0) {
            sampleCount start;
            sampleCount end;
            start = leftTrack->TimeToLongSamples(mCurT0);
            end = leftTrack->TimeToLongSamples(mCurT1);
            
            WaveTrack* rightTrack = NULL;
            if (leftTrack->GetLinked()) {
               double t;
               rightTrack = (WaveTrack*)(iter.Next());
               
               //Adjust bounds by the right tracks markers
               t = rightTrack->GetStartTime();
               t = wxMax(mT0, t);
               mCurT0 = wxMin(mCurT0, t);
               t = rightTrack->GetEndTime();
               t = wxMin(mT1, t);
               mCurT1 = wxMax(mCurT1, t);
               
               //Transform the marker timepoints to samples
               start = leftTrack->TimeToLongSamples(mCurT0);
               end = leftTrack->TimeToLongSamples(mCurT1);
               
               mCurTrackNum++; // Increment for rightTrack, too.	
            }
            
            sampleCount trackEnd = leftTrack->TimeToLongSamples(leftTrack->GetEndTime());

            // SBSMS has a fixed sample rate - we just convert to its sample rate and then convert back
            float srIn = leftTrack->GetRate();
            float srSBSMS = 44100.0;
            
            // the resampler needs a callback to supply its samples
            resampleBuf rb;
            sampleCount maxBlockSize = leftTrack->GetMaxBlockSize();
            rb.block = maxBlockSize;
            rb.buf = (audio*)calloc(rb.block,sizeof(audio));
            rb.leftTrack = leftTrack;
            rb.rightTrack = rightTrack?rightTrack:leftTrack;
            rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
            rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
            rb.offset = start;
            rb.end = trackEnd;
            rb.ratio = srSBSMS/srIn;
            rb.resampler = new Resampler(resampleCB, &rb);
            
            // Samples in selection
            sampleCount samplesIn = end-start;
            
            // Samples for SBSMS to process after resampling
            sampleCount samplesToProcess = (sampleCount) ((real)samplesIn*(srSBSMS/srIn));
            
            // Samples in output after resampling back
            sampleCount samplesToGenerate = (sampleCount) ((real)samplesToProcess * mTotalStretch);
            sampleCount samplesOut = (sampleCount) ((real)samplesIn * mTotalStretch);
            double duration =  (mCurT1-mCurT0) * mTotalStretch;

            if(duration > maxDuration)
               maxDuration = duration;

            TimeWarper *warper = NULL;
            if (rateStart == rateEnd)
            {
               warper = new LinearTimeWarper(mCurT0, mCurT0,
                                             mCurT1, mCurT0+maxDuration);
            } else
            {
               warper = new LogarithmicTimeWarper(mCurT0, mCurT1,
                                                  rateStart, rateEnd);
            }
            SetTimeWarper(warper);
            
            sbsmsInfo si;
            si.rs = rb.resampler;
            si.samplesToProcess = samplesToProcess;
            si.samplesToGenerate = samplesToGenerate;
            si.stretch0 = rateStart;
            si.stretch1 = rateEnd;
            si.ratio0 = pitchStart;
            si.ratio1 = pitchEnd;
            
            rb.sbsmser = sbsms_create(&samplesCB,&stretchCB,&ratioCB,rightTrack?2:1,quality,bPreAnalyze,true);
            rb.pitch = pitch_create(rb.sbsmser,&si,srIn/srSBSMS);
            
            rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
                                                        leftTrack->GetRate());
            if(rightTrack)
               rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
                                                            rightTrack->GetRate());
            
            
            sampleCount blockSize = SBSMS_FRAME_SIZE[quality];
            rb.outBuf = (audio*)calloc(blockSize,sizeof(audio));
            rb.outputLeftBuffer = (float*)calloc(blockSize*2,sizeof(float));
            if(rightTrack)
               rb.outputRightBuffer = (float*)calloc(blockSize*2,sizeof(float));
            
            long pos = 0;
            long outputCount = -1;
            
            // pre analysis
            real fracPre = 0.0f;
            if(bPreAnalyze) {
               fracPre = 0.05f;
               resampleBuf rbPre;
               rbPre.block = maxBlockSize;
               rbPre.buf = (audio*)calloc(rb.block,sizeof(audio));
               rbPre.leftTrack = leftTrack;
               rbPre.rightTrack = rightTrack?rightTrack:leftTrack;
               rbPre.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
               rbPre.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
               rbPre.offset = start;
               rbPre.end = end;
               rbPre.ratio = srSBSMS/srIn;
               rbPre.resampler = new Resampler(resampleCB, &rbPre);
               si.rs = rbPre.resampler;
               
               long pos = 0;
               long lastPos = 0;
               long ret = 0;
               while(lastPos<samplesToProcess) {
                  ret = sbsms_pre_analyze(&samplesCB,&si,rb.sbsmser);
                  lastPos = pos;
                  pos += ret;
                  real completion = (real)lastPos/(real)samplesToProcess;
                  if (TrackProgress(0,fracPre*completion))
                     return false;
               }
               sbsms_pre_analyze_complete(rb.sbsmser);
               sbsms_reset(rb.sbsmser);
               si.rs = rb.resampler;
            }
            
            // process
            while(pos<samplesOut && outputCount) {
               long frames;
               if(pos+blockSize>samplesOut) {
                  frames = samplesOut - pos;
               } else {
                  frames = blockSize;
               }
               
               outputCount = pitch_process(rb.outBuf, frames, rb.pitch);
               for(int i = 0; i < outputCount; i++) {
                  rb.outputLeftBuffer[i] = rb.outBuf[i][0];
                  if(rightTrack)
                     rb.outputRightBuffer[i] = rb.outBuf[i][1];
               }
               pos += outputCount;
               rb.outputLeftTrack->Append((samplePtr)rb.outputLeftBuffer, floatSample, outputCount);
               if(rightTrack)
                  rb.outputRightTrack->Append((samplePtr)rb.outputRightBuffer, floatSample, outputCount);
               
               double frac = (double)pos/(double)samplesOut;
               int nWhichTrack = mCurTrackNum;
               if(rightTrack) {
                  nWhichTrack = 2*(mCurTrackNum/2);
                  if (frac < 0.5)
                     frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once. 
                  else {
                     nWhichTrack++;
                     frac -= 0.5;
                     frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once. 
                  }
               }
               if (TrackProgress(nWhichTrack, fracPre + (1.0-fracPre)*frac))
                  return false;
            }
            rb.outputLeftTrack->Flush();
            if(rightTrack)
               rb.outputRightTrack->Flush();
            
            leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack,
                  true, false, GetTimeWarper());

            if(rightTrack) {
               rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack,
                     true, false, GetTimeWarper());
            }
         }
         mCurTrackNum++;
      }
      else if (mustSync && t->IsSynchroSelected())
      {
         t->SyncAdjust(mCurT1, mCurT0 + (mCurT1 - mCurT0) * mTotalStretch);
      }
      //Iterate to the next track
      t = iter.Next();
   }
   
   if (bGoodResult)
      ReplaceProcessedTracks(bGoodResult); 

   // Update selection
   mT0 = mCurT0;
   mT1 = mCurT0 + maxDuration;
   
   return bGoodResult;
}