コード例 #1
0
ファイル: Compressor.cpp プロジェクト: rbuj/audacity
bool EffectCompressor::InitPass1()
{
   mMax=0.0;
   if (!mNormalize)
      DisableSecondPass();

   // Find the maximum block length required for any track
   size_t maxlen = 0;
   SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());
   WaveTrack *track = (WaveTrack *) iter.First();
   while (track) {
      maxlen = std::max(maxlen, track->GetMaxBlockSize());
      //Iterate to the next track
      track = (WaveTrack *) iter.Next();
   }
   mFollow1.reset();
   mFollow2.reset();
   // Allocate buffers for the envelope
   if(maxlen > 0) {
      mFollow1.reinit(maxlen);
      mFollow2.reinit(maxlen);
   }
   mFollowLen = maxlen;

   return true;
}
コード例 #2
0
ファイル: TruncSilence.cpp プロジェクト: rbuj/audacity
double EffectTruncSilence::CalcPreviewInputLength(double /* previewLength */)
{
   double inputLength = mT1 - mT0;
   double minInputLength = inputLength;

   // Master list of silent regions
   RegionList silences;

   // Start with the whole selection silent
   silences.push_back(Region(mT0, mT1));

   SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());
   int whichTrack = 0;

   for (Track *t = iter.First(); t; t = iter.Next()) {
      WaveTrack *const wt = static_cast<WaveTrack *>(t);

      RegionList trackSilences;

      auto index = wt->TimeToLongSamples(mT0);
      sampleCount silentFrame = 0; // length of the current silence

      Analyze(silences, trackSilences, wt, &silentFrame, &index, whichTrack, &inputLength, &minInputLength);

      whichTrack++;
   }
   return inputLength;
}
コード例 #3
0
ファイル: ScienFilter.cpp プロジェクト: finefin/audacity
bool EffectScienFilter::Init()
{
   int selcount = 0;
   double rate = 0.0;

   TrackListOfKindIterator iter(Track::Wave, inputTracks());
   WaveTrack *t = (WaveTrack *) iter.First();

   mNyquist = (t ? t->GetRate() : GetActiveProject()->GetRate()) / 2.0;

   while (t)
   {
      if (t->GetSelected())
      {
         if (selcount == 0)
         {
            rate = t->GetRate();
         }
         else
         {
            if (t->GetRate() != rate)
            {
               Effect::MessageBox(_("To apply a filter, all selected tracks must have the same sample rate."));
               return false;
            }
         }
         selcount++;
      }
      t = (WaveTrack *) iter.Next();
   }

   return true;
}
コード例 #4
0
ファイル: ChangePitch.cpp プロジェクト: MindFy/audacity
// Deduce m_FromFrequency from the samples at the beginning of
// the selection. Then set some other params accordingly.
void EffectChangePitch::DeduceFrequencies()
{
   // As a neat trick, attempt to get the frequency of the note at the
   // beginning of the selection.
   SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());
   WaveTrack *track = (WaveTrack *) iter.First();
   if (track) {
      double rate = track->GetRate();

      // Auto-size window -- high sample rates require larger windowSize.
      // Aim for around 2048 samples at 44.1 kHz (good down to about 100 Hz).
      // To detect single notes, analysis period should be about 0.2 seconds.
      // windowSize must be a power of 2.
      const size_t windowSize =
         // windowSize < 256 too inaccurate
         std::max(256, wxRound(pow(2.0, floor((log(rate / 20.0)/log(2.0)) + 0.5))));

      // we want about 0.2 seconds to catch the first note.
      // number of windows rounded to nearest integer >= 1.
      const unsigned numWindows =
         std::max(1, wxRound((double)(rate / (5.0f * windowSize))));

      double trackStart = track->GetStartTime();
      double t0 = mT0 < trackStart? trackStart: mT0;
      auto start = track->TimeToLongSamples(t0);

      auto analyzeSize = windowSize * numWindows;
      Floats buffer{ analyzeSize };

      Floats freq{ windowSize / 2 };
      Floats freqa{ windowSize / 2, true };

      track->Get((samplePtr) buffer.get(), floatSample, start, analyzeSize);
      for(unsigned i = 0; i < numWindows; i++) {
         ComputeSpectrum(buffer.get() + i * windowSize, windowSize,
                         windowSize, rate, freq.get(), true);
         for(size_t j = 0; j < windowSize / 2; j++)
            freqa[j] += freq[j];
      }
      size_t argmax = 0;
      for(size_t j = 1; j < windowSize / 2; j++)
         if (freqa[j] > freqa[argmax])
            argmax = j;

      auto lag = (windowSize / 2 - 1) - argmax;
      m_dStartFrequency = rate / lag;
   }

   double dFromMIDInote = FreqToMIDInote(m_dStartFrequency);
   double dToMIDInote = dFromMIDInote + m_dSemitonesChange;
   m_nFromPitch = PitchIndex(dFromMIDInote);
   m_nFromOctave = PitchOctave(dFromMIDInote);
   m_nToPitch = PitchIndex(dToMIDInote);
   m_nToOctave = PitchOctave(dToMIDInote);

   m_FromFrequency = m_dStartFrequency;
   Calc_PercentChange();
   Calc_ToFrequency();
}
コード例 #5
0
ファイル: AutoDuck.cpp プロジェクト: MindFy/audacity
bool EffectAutoDuck::Init()
{
   mControlTrack = NULL;

   TrackListIterator iter(inputTracks());
   Track *t = iter.First();

   bool lastWasSelectedWaveTrack = false;
   const WaveTrack *controlTrackCandidate = NULL;

   while(t)
   {
      if (lastWasSelectedWaveTrack && !t->GetSelected() &&
          t->GetKind() == Track::Wave)
      {
         // This could be the control track, so remember it
         controlTrackCandidate = (WaveTrack*)t;
      }

      lastWasSelectedWaveTrack = false;

      if (t->GetSelected())
      {
         if (t->GetKind() == Track::Wave)
         {
            lastWasSelectedWaveTrack = true;
         }
         else
         {
            Effect::MessageBox(
               _("You selected a track which does not contain audio. AutoDuck can only process audio tracks."),
               /* i18n-hint: Auto duck is the name of an effect that 'ducks' (reduces the volume)
                * of the audio automatically when there is sound on another track.  Not as
                * in 'Donald-Duck'!*/
               wxICON_ERROR);
            return false;
         }
      }

      t = iter.Next();
   }

   if (!controlTrackCandidate)
   {
      Effect::MessageBox(
         _("Auto Duck needs a control track which must be placed below the selected track(s)."),
         wxICON_ERROR);
      return false;
   }

   mControlTrack = controlTrackCandidate;

   return true;
}
コード例 #6
0
ファイル: TruncSilence.cpp プロジェクト: rbuj/audacity
bool EffectTruncSilence::ProcessAll()
{
   // Copy tracks
   CopyInputTracks(Track::All);

   // Master list of silent regions.
   // This list should always be kept in order.
   RegionList silences;

   SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());
   if (FindSilences(silences, inputTracks(), iter.First(), iter.Last())) {
      TrackListIterator iterOut(mOutputTracks.get());
      double totalCutLen = 0.0;
      Track *const first = iterOut.First();
      if (DoRemoval(silences, 0, 1, first, iterOut.Last(), totalCutLen)) {
         mT1 -= totalCutLen;
         return true;
      }
   }

   return false;
}
コード例 #7
0
ファイル: VampEffect.cpp プロジェクト: SteveDaulton/audacity
bool VampEffect::Init()
{
   mRate = 0.0;

   // PRL: this loop checked that channels of a track have the same rate,
   // but there was no check that all tracks have one rate, and only the first
   // is remembered in mRate.  Is that correct?

   for (auto leader : inputTracks()->Leaders<const WaveTrack>()) {
      auto channelGroup = TrackList::Channels( leader );
      auto rate = (*channelGroup.first++) -> GetRate();
      for(auto channel : channelGroup) {
         if (rate != channel->GetRate())
         // PRL:  Track rate might not match individual clip rates.
         // So is this check not adequate?
          {
             // TODO: more-than-two-channels-message
             Effect::MessageBox(_("Sorry, Vamp Plug-ins cannot be run on stereo tracks where the individual channels of the track do not match."));
             return false;
         }
      }
      if (mRate == 0.0)
         mRate = rate;
   }

   if (mRate <= 0.0)
   {
      mRate = mProjectRate;
   }

   // The plugin must be reloaded to allow changing parameters

   Vamp::HostExt::PluginLoader *loader = Vamp::HostExt::PluginLoader::getInstance();
   mPlugin.reset(loader->loadPlugin(mKey, mRate, Vamp::HostExt::PluginLoader::ADAPT_ALL));
   if (!mPlugin)
   {
      Effect::MessageBox(_("Sorry, failed to load Vamp Plug-in."));
      return false;
   }

   return true;
}
コード例 #8
0
ファイル: Amplify.cpp プロジェクト: MindFy/audacity
bool EffectAmplify::Init()
{
   mPeak = 0.0;

   SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());

   for (Track *t = iter.First(); t; t = iter.Next())
   {
      auto pair = ((WaveTrack *)t)->GetMinMax(mT0, mT1); // may throw
      const float min = pair.first, max = pair.second;
      float newpeak = (fabs(min) > fabs(max) ? fabs(min) : fabs(max));

      if (newpeak > mPeak)
      {
         mPeak = newpeak;
      }
   }

   return true;
}
コード例 #9
0
ファイル: TruncSilence.cpp プロジェクト: rbuj/audacity
bool EffectTruncSilence::ProcessIndependently()
{
   unsigned nGroups = 0;

   const bool syncLock = ::GetActiveProject()->IsSyncLocked();

   // Check if it's permissible
   {
      SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks());
      for (Track *track = iter.First(); track;
         track = iter.Next(true) // skip linked tracks
      ) {
         if (syncLock) {
            Track *const link = track->GetLink();
            SyncLockedTracksIterator syncIter(inputTracks());
            for (Track *track2 = syncIter.StartWith(track); track2; track2 = syncIter.Next()) {
               if (track2->GetKind() == Track::Wave &&
                  !(track2 == track || track2 == link) &&
                  track2->GetSelected()) {
                  ::wxMessageBox(_("When truncating independently, there may only be one selected audio track in each Sync-Locked Track Group."));
                  return false;
               }
            }
         }

         ++nGroups;
      }
   }

   if (nGroups == 0)
      // nothing to do
      return true;

   // Now do the work

   // Copy tracks
   CopyInputTracks(Track::All);
   double newT1 = 0.0;

   {
      unsigned iGroup = 0;
      SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
      for (Track *track = iter.First(); track;
         ++iGroup, track = iter.Next(true) // skip linked tracks
      ) {
         Track *const link = track->GetLink();
         Track *const last = link ? link : track;

         RegionList silences;

         if (!FindSilences(silences, mOutputTracks.get(), track, last))
            return false;
         // Treat tracks in the sync lock group only
         Track *groupFirst, *groupLast;
         if (syncLock) {
            SyncLockedTracksIterator syncIter(mOutputTracks.get());
            groupFirst = syncIter.StartWith(track);
            groupLast = syncIter.Last();
         }
         else {
            groupFirst = track;
            groupLast = last;
         }
         double totalCutLen = 0.0;
         if (!DoRemoval(silences, iGroup, nGroups, groupFirst, groupLast, totalCutLen))
            return false;
         newT1 = std::max(newT1, mT1 - totalCutLen);
      }
   }

   mT1 = newT1;

   return true;
}
コード例 #10
0
ファイル: VampEffect.cpp プロジェクト: SteveDaulton/audacity
bool VampEffect::Process()
{
   if (!mPlugin)
   {
      return false;
   }

   int count = 0;

   bool multiple = false;
   unsigned prevTrackChannels = 0;

   if (GetNumWaveGroups() > 1)
   {
      // 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;
   }

   std::vector<std::shared_ptr<Effect::AddedAnalysisTrack>> addedTracks;

   for (auto leader : inputTracks()->Leaders<const WaveTrack>())
   {
      auto channelGroup = TrackList::Channels(leader);
      auto left = *channelGroup.first++;

      sampleCount lstart, rstart = 0;
      sampleCount len;
      GetSamples(left, &lstart, &len);

      unsigned channels = 1;

      // channelGroup now contains all but the first channel
      const WaveTrack *right =
         channelGroup.size() ? *channelGroup.first++ : nullptr;
      if (right)
      {
         channels = 2;
         GetSamples(right, &rstart, &len);
      }

      // TODO: more-than-two-channels

      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))
         {
            Effect::MessageBox(_("Sorry, Vamp Plug-in failed to initialize."));
            return false;
         }
      }

      const auto effectName = GetSymbol().Translation();
      addedTracks.push_back(AddAnalysisTrack(
         multiple
         ? wxString::Format( _("%s: %s"), left->GetName(), effectName )
         : effectName
      ));
      LabelTrack *ltrack = addedTracks.back()->get();

      FloatBuffers data{ channels, block };

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

      while (len != 0)
      {
         const auto request = limitSampleBufferSize( block, len );

         if (left)
         {
            left->Get((samplePtr)data[0].get(), floatSample, ls, request);
         }

         if (right)
         {
            right->Get((samplePtr)data[1].get(), floatSample, rs, request);
         }

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

         // UNSAFE_SAMPLE_COUNT_TRUNCATION
         // Truncation in case of very long tracks!
         Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(
            long( ls.as_long_long() ),
            (int)(mRate + 0.5)
         );

         Vamp::Plugin::FeatureSet features = mPlugin->process(
            reinterpret_cast< float** >( data.get() ), 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).as_double() /
                  originalLen.as_double() ))
            {
               return false;
            }
         }
         else
         {
            if (TrackProgress(count,
                  (ls - lstart).as_double() /
                  originalLen.as_double() ))
            {
               return false;
            }
         }
      }

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

      prevTrackChannels = channels;
   }

   // All completed without cancellation, so commit the addition of tracks now
   for (auto &addedTrack : addedTracks)
      addedTrack->Commit();

   return true;
}