bool EffectSoundTouch::Process()
{
   // Assumes that mSoundTouch has already been initialized
   // by the subclass for subclass-specific parameters.

   //Iterate over each track
   TrackListIterator iter(mWaveTracks);
   WaveTrack* leftTrack = (WaveTrack*)(iter.First());
   WaveTrack* rightTrack = NULL;
   mCurTrackNum = 0;
	m_maxNewLength = 0.0;
   while (leftTrack) {
      //Get start and end times from track
      double trackStart = leftTrack->GetStartTime();
      double trackEnd = leftTrack->GetEndTime();

      //Set the current bounds to whichever left marker is
      //greater and whichever right marker is less:
      mCurT0 = mT0 < trackStart? trackStart: mT0;
      mCurT1 = mT1 > trackEnd? trackEnd: mT1;

      // Process only if the right marker is to the right of the left marker
      if (mCurT1 > mCurT0) {

         //Transform the marker timepoints to samples
         longSampleCount start = leftTrack->TimeToLongSamples(mCurT0);
         longSampleCount end = leftTrack->TimeToLongSamples(mCurT1);
         
         rightTrack = NULL; 
         if (leftTrack->GetLinked()) {
            rightTrack = (WaveTrack*)(iter.Next());
            mSoundTouch->setChannels(2);
            if (!ProcessStereo(leftTrack, rightTrack, start, end))
               return false;
            mCurTrackNum++; // Increment for rightTrack, too.
         } else {
            mSoundTouch->setChannels(1);
            //ProcessOne() (implemented below) processes a single track
            if (!ProcessOne(leftTrack, start, end))
               return false;
         }
      }
      
      //Iterate to the next track
      leftTrack = (WaveTrack*)(iter.Next());
      mCurTrackNum++;
   }

   delete mSoundTouch;
   mSoundTouch = NULL;

	mT1 = mT0 + m_maxNewLength; // Update selection.
   return true;
}
Exemple #2
0
//TODO: There are a lot of places where a track is being checked
//      to see if it is stereo. Consolidate these
bool EffectStereoToMono::CheckWhetherSkipEffect()
{
   TrackListIterator iter(mWaveTracks);
   WaveTrack *t = (WaveTrack*)iter.First();
   while (t) {
      if (t->GetLinked()) {
         return false;
      }
      t = (WaveTrack *)iter.Next();
   }

   return true;
}
Exemple #3
0
bool VSTEffect::Init()
{
   if (!mAEffect) {
      Load();
   }

   if (!mAEffect) {
      return false;
   }

   mBlockSize = 0;

   TrackListIterator iter(mOutputTracks);
   WaveTrack *left = (WaveTrack *) iter.First();
   while (left) {
      sampleCount lstart;
      sampleCount llen;

      GetSamples(left, &lstart, &llen);
      
      if (left->GetLinked()) {
         WaveTrack *right = (WaveTrack *) iter.Next();
         sampleCount rstart;
         sampleCount rlen;

         GetSamples(right, &rstart, &rlen);         

         if (left->GetRate() != right->GetRate()) {
            wxMessageBox(_("Both channels of a stereo track must be the same sample rate."));
            return false;
         }

         if (llen != rlen) {
            wxMessageBox(_("Both channels of a stereo track must be the same length."));
            return false;
         }
      }
      
      left = (WaveTrack *) iter.Next();
   }

   return true;
}
Exemple #4
0
bool VampEffect::Init()
{
   Vamp::HostExt::PluginLoader *loader =
      Vamp::HostExt::PluginLoader::getInstance();
   
   delete mPlugin;
   mPlugin = 0;

   TrackListIterator iter(mWaveTracks);
   WaveTrack *left = (WaveTrack *)iter.First();

   mRate = 0.0;

   while (left) {

      if (mRate == 0.0) mRate = left->GetRate();
      
      if (left->GetLinked()) {

         WaveTrack *right = (WaveTrack *)iter.Next();
         
         if (left->GetRate() != right->GetRate()) {
            wxMessageBox(_("Sorry, Vamp Plug-ins cannot be run on stereo tracks where the individual channels of the track do not match."));
            return false;
         }
      }
      
      left = (WaveTrack *)iter.Next();
   }

   if (mRate <= 0.0) mRate = mProjectRate;

   mPlugin = loader->loadPlugin
      (mKey, mRate, Vamp::HostExt::PluginLoader::ADAPT_ALL);

   if (!mPlugin) {
      wxMessageBox(_("Sorry, failed to load Vamp Plug-in."));
      return false;
   }

   return true;
}
Exemple #5
0
bool EffectNormalize::Process()
{
   if (mGain == false && mDC == false)
      return true;

   float ratio;
   if( mGain )
      ratio = pow(10.0,TrapDouble(mLevel, // same value used for all tracks
                               NORMALIZE_DB_MIN,
                               NORMALIZE_DB_MAX)/20.0);
   else
      ratio = 1.0;

   //Iterate over each track
   this->CopyInputTracks(); // Set up mOutputTracks.
   bool bGoodResult = true;
   SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks);
   WaveTrack *track = (WaveTrack *) iter.First();
   WaveTrack *prevTrack;
   prevTrack = track;
   mCurTrackNum = 0;
   wxString topMsg;
   if(mDC & mGain)
      topMsg = _("Removing DC offset and Normalizing...\n");
   else if(mDC & !mGain)
      topMsg = _("Removing DC offset...\n");
   else if(!mDC & mGain)
      topMsg = _("Normalizing without removing DC offset...\n");
   else if(!mDC & !mGain)
      topMsg = wxT("Not doing anything)...\n");   // shouldn't get here

   while (track) {
      //Get start and end times from track
      double trackStart = track->GetStartTime();
      double trackEnd = track->GetEndTime();

      //Set the current bounds to whichever left marker is
      //greater and whichever right marker is less:
      mCurT0 = mT0 < trackStart? trackStart: mT0;
      mCurT1 = mT1 > trackEnd? trackEnd: mT1;

      // Process only if the right marker is to the right of the left marker
      if (mCurT1 > mCurT0) {
         wxString msg;
         wxString trackName = track->GetName();

         if(!track->GetLinked() || mStereoInd)
            msg = topMsg + _("Analyzing: ") + trackName;
         else
            msg = topMsg + _("Analyzing first track of stereo pair: ") + trackName;
         AnalyseTrack(track, msg);  // sets mOffset and offset-adjusted mMin and mMax
         if(!track->GetLinked() || mStereoInd) {   // mono or 'stereo tracks independently'
            float extent = wxMax(fabs(mMax), fabs(mMin));
            if( (extent > 0) && mGain )
               mMult = ratio / extent;
            else
               mMult = 1.0;
            msg = topMsg + _("Processing: ") + trackName;
            if(track->GetLinked() || prevTrack->GetLinked())  // only get here if there is a linked track but we are processing independently
               msg = topMsg + _("Processing stereo channels independently: ") + trackName;

            if (!ProcessOne(track, msg))
            {
               bGoodResult = false;
               break;
            }
         }
         else
         {
            // we have a linked stereo track
            // so we need to find it's min, max and offset
            // as they are needed to calc the multiplier for both tracks
            float offset1 = mOffset;   // remember ones from first track
            float min1 = mMin;
            float max1 = mMax;
            track = (WaveTrack *) iter.Next();  // get the next one
            mCurTrackNum++;   // keeps progress bar correct
            msg = topMsg + _("Analyzing second track of stereo pair: ") + trackName;
            AnalyseTrack(track, msg);  // sets mOffset and offset-adjusted mMin and mMax
            float offset2 = mOffset;   // ones for second track
            float min2 = mMin;
            float max2 = mMax;
            float extent = wxMax(fabs(min1), fabs(max1));
            extent = wxMax(extent, fabs(min2));
            extent = wxMax(extent, fabs(max2));
            if( (extent > 0) && mGain )
               mMult = ratio / extent; // we need to use this for both linked tracks
            else
               mMult = 1.0;
            mOffset = offset1;
            track = (WaveTrack *) iter.Prev();  // go back to the first linked one
            mCurTrackNum--;   // keeps progress bar correct
            msg = topMsg + _("Processing first track of stereo pair: ") + trackName;
            if (!ProcessOne(track, msg))
            {
               bGoodResult = false;
               break;
            }
            mOffset = offset2;
            track = (WaveTrack *) iter.Next();  // go to the second linked one
            mCurTrackNum++;   // keeps progress bar correct
            msg = topMsg + _("Processing second track of stereo pair: ") + trackName;
            if (!ProcessOne(track, msg))
            {
               bGoodResult = false;
               break;
            }
         }
      }
      
      //Iterate to the next track
      prevTrack = track;
      track = (WaveTrack *) iter.Next();
      mCurTrackNum++;
   }

   this->ReplaceProcessedTracks(bGoodResult); 
   return bGoodResult;
}
Exemple #6
0
bool VampEffect::Process()
{
   if (!mPlugin) return false;

   TrackListIterator iter(mWaveTracks);

   int count = 0;

   WaveTrack *left = (WaveTrack *)iter.First();

   bool multiple = false;
   int prevTrackChannels = 0;

   TrackListIterator scooter(iter);
   if (left->GetLinked()) scooter.Next();      
   if (scooter.Next()) {
      // if there is another track beyond this one and any linked one,
      // then we're processing more than one track.  That means we
      // should use the originating track name in each new label
      // track's name, to make clear which is which
      multiple = true;
   }

   while (left) {

      sampleCount lstart, rstart;
      sampleCount len;
      GetSamples(left, &lstart, &len);
      
      WaveTrack *right = NULL;
      int channels = 1;

      if (left->GetLinked()) {
         right = (WaveTrack *)iter.Next();
         channels = 2;
         GetSamples(right, &rstart, &len);
      }

      size_t step = mPlugin->getPreferredStepSize();
      size_t block = mPlugin->getPreferredBlockSize();

      bool initialiseRequired = true;

      if (block == 0) {
         if (step != 0) block = step;
         else block = 1024;
      }
      if (step == 0) {
         step = block;
      }

      if (prevTrackChannels > 0) {
         // Plugin has already been initialised, so if the number of
         // channels remains the same, we only need to do a reset.
         // Otherwise we need to re-construct the whole plugin,
         // because a Vamp plugin can't be re-initialised.
         if (prevTrackChannels == channels) {
            mPlugin->reset();
            initialiseRequired = false;
         } else {
            //!!! todo: retain parameters previously set
            Init();
         }
      }

      if (initialiseRequired) {
         if (!mPlugin->initialise(channels, step, block)) {
            wxMessageBox(_("Sorry, Vamp Plug-in failed to initialize."));
            return false;
         }
      }

      LabelTrack *ltrack = mFactory->NewLabelTrack();

      if (!multiple) {
         ltrack->SetName(GetEffectName());
      } else {
         ltrack->SetName(wxString::Format(wxT("%s: %s"),
                                          left->GetName().c_str(),
                                          GetEffectName().c_str()));
      }

      mTracks->Add(ltrack);

      float **data = new float*[channels];
      for (int c = 0; c < channels; ++c) data[c] = new float[block];

      sampleCount originalLen = len;
      sampleCount ls = lstart;
      sampleCount rs = rstart;

      while (len) {
         
         int request = block;
         if (request > len) request = len;

         if (left) left->Get((samplePtr)data[0], floatSample, ls, request);
         if (right) right->Get((samplePtr)data[1], floatSample, rs, request);

         if (request < (int)block) {
            for (int c = 0; c < channels; ++c) {
               for (int i = request; i < (int)block; ++i) {
                  data[c][i] = 0.f;
               }
            }
         }

         Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime
            (ls, (int)(mRate + 0.5));

         Vamp::Plugin::FeatureSet features = mPlugin->process(data, timestamp);
         AddFeatures(ltrack, features);

         if (len > (int)step) len -= step;
         else len = 0;

         ls += step;
         rs += step;

         if (channels > 1) {
            if (TrackGroupProgress(count, (ls - lstart) / double(originalLen)))
               return false;
         } else {
            if (TrackProgress(count, (ls - lstart) / double(originalLen)))
               return false;
         }
      }

      Vamp::Plugin::FeatureSet features = mPlugin->getRemainingFeatures();
      AddFeatures(ltrack, features);

      prevTrackChannels = channels;

      left = (WaveTrack *)iter.Next();
   }

   return true;
}
Exemple #7
0
bool ContrastDialog::GetDB(float &dB)
{
   float rms = float(0.0);
   int numberSelecteTracks = 0;

   // For stereo tracks: sqrt((mean(L)+mean(R))/2)
   bool isStereo = false;
   double meanSq = 0.0;

   AudacityProject *p = GetActiveProject();
   SelectedTrackListOfKindIterator iter(Track::Wave, p->GetTracks());
   WaveTrack *t = (WaveTrack *) iter.First();
   while (t) {
      numberSelecteTracks++;
      if (numberSelecteTracks > 1 && !isStereo) {
         AudacityMessageDialog m(NULL, _("You can only measure one track at a time."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }
      isStereo = t->GetLinked();

      wxASSERT(mT0 <= mT1);

      // Ignore whitespace beyond ends of track.
      if(mT0 < t->GetStartTime())
         mT0 = t->GetStartTime();
      if(mT1 > t->GetEndTime())
         mT1 = t->GetEndTime();

      auto SelT0 = t->TimeToLongSamples(mT0);
      auto SelT1 = t->TimeToLongSamples(mT1);

      if(SelT0 > SelT1)
      {
         AudacityMessageDialog m(NULL, _("Invalid audio selection.\nPlease ensure that audio is selected."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }

      if(SelT0 == SelT1)
      {
         AudacityMessageDialog m(NULL, _("Nothing to measure.\nPlease select a section of a track."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }

      // Don't throw in this analysis dialog
      rms = ((WaveTrack *)t)->GetRMS(mT0, mT1, false);
      meanSq += rms * rms;
      t = (WaveTrack *) iter.Next();
   }
   // TODO: This works for stereo, provided the audio clips are in both channels.
   // We should really count gaps between clips as silence.
   rms = (meanSq > 0.0)? sqrt(meanSq/(double)numberSelecteTracks) : 0.0;

   if(numberSelecteTracks == 0) {
      AudacityMessageDialog m(NULL, _("Please select an audio track."), _("Error"), wxOK);
      m.ShowModal();
      return false;
   }
   // Gives warning C4056, Overflow in floating-point constant arithmetic
   // -INFINITY is intentional here.
   // Looks like we are stuck with this warning, as 
   // #pragma warning( disable : 4056)
   // even around the whole function does not disable it successfully.

   dB = (rms == 0.0)? -INFINITY : LINEAR_TO_DB(rms);
   return true;
}
Exemple #8
0
bool VSTEffect::Process()
{
   CopyInputTracks();
   bool bGoodResult = true;

   mInBuffer = NULL;
   mOutBuffer = NULL;

   TrackListIterator iter(mOutputTracks);
   int count = 0;
   bool clear = false;
   WaveTrack *left = (WaveTrack *) iter.First();
   while (left) {
      WaveTrack *right;
      sampleCount len;
      sampleCount lstart;
      sampleCount rstart;

      GetSamples(left, &lstart, &len);

      mChannels = 1;

      right = NULL;
      rstart = 0;
      if (left->GetLinked() && mInputs > 1) {
         right = (WaveTrack *) iter.Next();         
         GetSamples(right, &rstart, &len);
         clear = false;
         mChannels = 2;
      }

      if (mBlockSize == 0) {
         mBlockSize = left->GetMaxBlockSize() * 2;

         // Some VST effects (Antress Modern is an example), do not like
         // overly large block sizes.  Unfortunately, I have not found a
         // way to determine if the effect has a maximum it will support,
         // so just limit to small value for now.  This will increase
         // processing time and, it's a shame, because most plugins seem
         // to be able to handle much larger sizes.
         if (mBlockSize > 8192) { // The Antress limit
            mBlockSize = 8192;
         }

         mInBuffer = new float *[mInputs];
         for (int i = 0; i < mInputs; i++) {
            mInBuffer[i] = new float[mBlockSize];
         }

         mOutBuffer = new float *[mOutputs];
         for (int i = 0; i < mOutputs; i++) {
            mOutBuffer[i] = new float[mBlockSize];
         }

         // Turn the power off
         callDispatcher(effMainsChanged, 0, 0, NULL, 0.0);

         // Set processing parameters
         callDispatcher(effSetSampleRate, 0, 0, NULL, left->GetRate());
         callDispatcher(effSetBlockSize, 0, mBlockSize, NULL, 0.0);
      }

      // Clear unused input buffers
      if (!right && !clear) {
         for (int i = 1; i < mInputs; i++) {
            for (int j = 0; j < mBlockSize; j++) {
               mInBuffer[i][j] = 0.0;
            }
         }
         clear = true;
      }

      bGoodResult = ProcessStereo(count, left, right, lstart, rstart, len);
      if (!bGoodResult) {
         break;
      }

      left = (WaveTrack *) iter.Next();
      count++;
   }

   if (mOutBuffer) {
      for (int i = 0; i < mOutputs; i++) {
         delete mOutBuffer[i];
      }
      delete [] mOutBuffer;
      mOutBuffer = NULL;
   }

   if (mInBuffer) {
      for (int i = 0; i < mInputs; i++) {
         delete mInBuffer[i];
      }
      delete [] mInBuffer;
      mInBuffer = NULL;
   }

   ReplaceProcessedTracks(bGoodResult); 
   return bGoodResult;
}
Exemple #9
0
bool ContrastDialog::GetDB(float &dB)
{
   float rms = float(0.0);
   int numberSelecteTracks = 0;

   // For stereo tracks: sqrt((mean(L)+mean(R))/2)
   bool isStereo = false;
   double meanSq = 0.0;

   AudacityProject *p = GetActiveProject();
   SelectedTrackListOfKindIterator iter(Track::Wave, p->GetTracks());
   WaveTrack *t = (WaveTrack *) iter.First();
   while (t) {
      numberSelecteTracks++;
      if (numberSelecteTracks > 1 && !isStereo) {
         wxMessageDialog m(NULL, _("You can only measure one track at a time."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }
      isStereo = t->GetLinked();

      wxASSERT(mT0 <= mT1);

      // Ignore whitespace beyond ends of track.
      if(mT0 < t->GetStartTime())
         mT0 = t->GetStartTime();
      if(mT1 > t->GetEndTime())
         mT1 = t->GetEndTime();

      sampleCount SelT0 = t->TimeToLongSamples(mT0);
      sampleCount SelT1 = t->TimeToLongSamples(mT1);

      if(SelT0 > SelT1)
      {
         wxMessageDialog m(NULL, _("Invalid audio selection.\nPlease ensure that audio is selected."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }

      if(SelT0 == SelT1)
      {
         wxMessageDialog m(NULL, _("Nothing to measure.\nPlease select a section of a track."), _("Error"), wxOK);
         m.ShowModal();
         return false;
      }

      ((WaveTrack *)t)->GetRMS(&rms, mT0, mT1);
      meanSq += rms * rms;
      t = (WaveTrack *) iter.Next();
   }
   // TODO: This works for stereo, provided the audio clips are in both channels.
   // We should really count gaps between clips as silence.
   rms = (meanSq > 0.0)? sqrt(meanSq/(double)numberSelecteTracks) : 0.0;

   if(numberSelecteTracks == 0) {
      wxMessageDialog m(NULL, _("Please select an audio track."), _("Error"), wxOK);
      m.ShowModal();
      return false;
   }

   dB = (rms == 0.0)? -INFINITY : LINEAR_TO_DB(rms);
   return true;
}
Exemple #10
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;
}
bool EffectSoundTouch::Process()
{
   // Assumes that mSoundTouch has already been initialized
   // by the subclass for subclass-specific parameters. The
   // time warper should also be set.

   // Check if this effect will alter the selection length; if so, we need
   // to operate on sync-lock selected tracks.
   bool mustSync = true;
   if (mT1 == GetTimeWarper()->Warp(mT1)) {
      mustSync = false;
   }

   //Iterate over each track
   // Needs Track::All for sync-lock grouping.
   this->CopyInputTracks(Track::All);
   bool bGoodResult = true;

   TrackListIterator iter(mOutputTracks);
   Track* t;
   mCurTrackNum = 0;
   m_maxNewLength = 0.0;

   t = iter.First();
   while (t != NULL) {
      if (t->GetKind() == Track::Label &&
            (t->GetSelected() || (mustSync && t->IsSyncLockSelected())) )
      {
         if (!ProcessLabelTrack(t))
         {
            bGoodResult = false;
            break;
         }
      }
#ifdef USE_MIDI
      else if (t->GetKind() == Track::Note &&
               (t->GetSelected() || (mustSync && t->IsSyncLockSelected())))
      {
         if (!ProcessNoteTrack(t))
         {
            bGoodResult = false;
            break;
         }
      }
#endif
      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, end;

            if (leftTrack->GetLinked()) {
               double t;
               WaveTrack* 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);

               //Inform soundtouch there's 2 channels
               mSoundTouch->setChannels(2);

               //ProcessStereo() (implemented below) processes a stereo track
               if (!ProcessStereo(leftTrack, rightTrack, start, end))
               {
                  bGoodResult = false;
                  break;
               }
               mCurTrackNum++; // Increment for rightTrack, too.
            } else {
               //Transform the marker timepoints to samples
               start = leftTrack->TimeToLongSamples(mCurT0);
               end = leftTrack->TimeToLongSamples(mCurT1);

               //Inform soundtouch there's a single channel
               mSoundTouch->setChannels(1);

               //ProcessOne() (implemented below) processes a single track
               if (!ProcessOne(leftTrack, start, end))
               {
                  bGoodResult = false;
                  break;
               }
            }
         }
         mCurTrackNum++;
      }
      else if (mustSync && t->IsSyncLockSelected()) {
         t->SyncLockAdjust(mT1, GetTimeWarper()->Warp(mT1));
      }

      //Iterate to the next track
      t = iter.Next();
   }

   if (bGoodResult)
      ReplaceProcessedTracks(bGoodResult);

   delete mSoundTouch;
   mSoundTouch = NULL;

//   mT0 = mCurT0;
//   mT1 = mCurT0 + m_maxNewLength; // Update selection.

   return bGoodResult;
}
Exemple #12
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;
}
Exemple #13
0
bool EffectNormalize::Process()
{
   bool wasLinked = false; // set when a track has a linked (stereo) track

   if (mGain == false &&
       mDC == false)
      return true;

   //Iterate over each track
   this->CopyInputTracks(); // Set up mOutputTracks.
   bool bGoodResult = true;

   SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks);
   WaveTrack *track = (WaveTrack *) iter.First();
   mCurTrackNum = 0;
   while (track) {
      //Get start and end times from track
      double trackStart = track->GetStartTime();
      double trackEnd = track->GetEndTime();

      //Set the current bounds to whichever left marker is
      //greater and whichever right marker is less:
      mCurT0 = mT0 < trackStart? trackStart: mT0;
      mCurT1 = mT1 > trackEnd? trackEnd: mT1;

      // Process only if the right marker is to the right of the left marker
      if (mCurT1 > mCurT0) {

         //Transform the marker timepoints to samples
         sampleCount start = track->TimeToLongSamples(mCurT0);
         sampleCount end = track->TimeToLongSamples(mCurT1);
         
         //Get the track rate and samples
         mCurRate = track->GetRate();
         mCurChannel = track->GetChannel();

         if(mStereoInd) // do stereo tracks independently (the easy way)
            track->GetMinMax(&mMin, &mMax, mCurT0, mCurT1);
         else
         {
            if(!wasLinked) // new mono track or first of a stereo pair
            {
               track->GetMinMax(&mMin, &mMax, mCurT0, mCurT1);
               if(track->GetLinked())
               {
                  wasLinked = true; // so we use these values for the next (linked) track
                  track = (WaveTrack *) iter.Next();  // get the next one for the max/min
                  float min, max;
                  track->GetMinMax(&min, &max, mCurT0, mCurT1);
                  mMin = min < mMin ? min : mMin;
                  mMax = max > mMax ? max : mMax;
                  track = (WaveTrack *) iter.Prev();  // back to the one we are on
               }
            }
            else
               wasLinked = false;   // second of the stereo pair, next one is mono or first
         }

         //ProcessOne() (implemented below) processes a single track
         if (!ProcessOne(track, start, end))
         {
            bGoodResult = false;
            break;
         }
      }
      
      //Iterate to the next track
      track = (WaveTrack *) iter.Next();
      mCurTrackNum++;
   }

   this->ReplaceProcessedTracks(bGoodResult); 
   return bGoodResult;
}