Пример #1
0
// 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();
}
Пример #2
0
void EffectChangePitch::OnText_FromFrequency(wxCommandEvent & WXUNUSED(evt))
{
   if (m_bLoopDetect)
      return;

   // Empty string causes unpredictable results with ToDouble() and later calculations.
   // Non-positive frequency makes no sense, but user might still be editing,
   // so it's not an error, but we do not want to update the values/controls.
   if (!m_pTextCtrl_FromFrequency->GetValidator()->TransferFromWindow())
   {
      EnableApply(false);
      return;
   }

   double newFromMIDInote = FreqToMIDInote(m_FromFrequency);
   m_nFromPitch = PitchIndex(newFromMIDInote);
   m_nFromOctave = PitchOctave(newFromMIDInote);
   Calc_ToPitch();
   Calc_ToFrequency();
   Calc_ToOctave(); // Call after Calc_ToFrequency().

   m_bLoopDetect = true;
   {
      Update_Choice_FromPitch();
      Update_Spin_FromOctave();
      Update_Choice_ToPitch();
      Update_Spin_ToOctave();
      Update_Text_ToFrequency();
   }
   m_bLoopDetect = false;

   // Success. Make sure OK and Preview are enabled, in case we disabled above during editing.
   EnableApply(true);
}
Пример #3
0
void EffectChangePitch::Calc_ToOctave()
{
   m_nToOctave = PitchOctave(FreqToMIDInote(m_ToFrequency));
}
Пример #4
0
// 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, mTracks);
   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.
      int windowSize = wxRound(pow(2.0, floor((log(rate / 20.0)/log(2.0)) + 0.5)));
      // windowSize < 256 too inaccurate
      windowSize = (windowSize > 256)? windowSize : 256;

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

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

      int analyzeSize = windowSize * numWindows;
      float * buffer;
      buffer = new float[analyzeSize];

      float * freq;
      freq = new float[windowSize/2];

      float * freqa;
      freqa = new float[windowSize/2];

      int i, j, argmax;
      int lag;

      for(j=0; j<windowSize/2; j++)
         freqa[j] = 0;

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

      delete [] freq;
      delete [] freqa;
      delete [] buffer;

      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();
}