Exemple #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();
}
Exemple #2
0
void ChangePitchDialog::OnText_FromFrequency(wxCommandEvent & event)
{
   if (m_bLoopDetect)
      return;

   if (m_pTextCtrl_FromFrequency) {
      wxString str = m_pTextCtrl_FromFrequency->GetValue();
      double newDouble;
      str.ToDouble(&newDouble);
      m_FromFrequency = newDouble;

      m_FromPitchIndex = PitchIndex(FreqToMIDInoteNumber(m_FromFrequency));
      this->Calc_ToFrequency();
      m_bWantPitchDown = (m_ToFrequency < m_FromFrequency);
      this->Calc_ToPitchIndex(); // Call *after* m_bWantPitchDown is updated.

      m_bLoopDetect = true;
      this->Update_RadioButton_PitchUpDown();
      if (m_pTextCtrl_FromFrequency->IsModified())
         // See note at implementation of Update_RadioButton_PitchUpDown.
         m_pTextCtrl_FromFrequency->SetFocus(); 
      this->Update_Choice_ToPitch();
      this->Update_Text_ToFrequency();
      m_bLoopDetect = false;
   }
}
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);
}
Exemple #4
0
// DeduceFrequencies is Dominic's extremely cool trick (Vaughan sez so!) 
// to set deduce m_FromFrequency from the samples at the beginning of 
// the selection. Then we 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) {
      const int windowSize = 1024;
      const int analyzeSize = 8192;
      const int numWindows = analyzeSize / windowSize;
      double trackStart = track->GetStartTime();
      double t0 = mT0 < trackStart? trackStart: mT0;
      sampleCount start = track->TimeToLongSamples(t0);
      double rate = track->GetRate();
      float buffer[analyzeSize];
      float freq[windowSize/2];
      float freqa[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;
      lag = (windowSize/2 - 1) - argmax;
      m_FromFrequency = rate / lag;
      m_ToFrequency = (m_FromFrequency * (100.0 + m_PercentChange)) / 100.0;

      // Now we can set the pitch control values. 
      m_FromPitchIndex = PitchIndex(FreqToMIDInoteNumber(m_FromFrequency));
      m_bWantPitchDown = (m_ToFrequency < m_FromFrequency);
      m_ToPitchIndex = PitchIndex(FreqToMIDInoteNumber(m_ToFrequency));
   }
}
Exemple #5
0
// PitchName takes pitchNum (as per result from 
// Freq2Pitch) and returns a standard pitch/note name [C, C#, etc.). 
// Sharps are the default, unless, bWantFlats is true.
char * PitchName(float pitchNum, bool bWantFlats /* = false */)
{
   p_PitchName = gPitchName;

   switch (PitchIndex(pitchNum)) {
   case 0:
      *p_PitchName++ = 'C';
      break;
   case 1:
      if (bWantFlats) {
         *p_PitchName++ = 'D';
         *p_PitchName++ = 'b';
      } else {
         *p_PitchName++ = 'C';
         *p_PitchName++ = '#';
      }
      break;
   case 2:
      *p_PitchName++ = 'D';
      break;
   case 3:
      if (bWantFlats) {
         *p_PitchName++ = 'E';
         *p_PitchName++ = 'b';
      } else {
         *p_PitchName++ = 'D';
         *p_PitchName++ = '#';
      }
      break;
   case 4:
      *p_PitchName++ = 'E';
      break;
   case 5:
      *p_PitchName++ = 'F';
      break;
   case 6:
      if (bWantFlats) {
         *p_PitchName++ = 'G';
         *p_PitchName++ = 'b';
      } else {
         *p_PitchName++ = 'F';
         *p_PitchName++ = '#';
      }
      break;
   case 7:
      *p_PitchName++ = 'G';
      break;
   case 8:
      if (bWantFlats) {
         *p_PitchName++ = 'A';
         *p_PitchName++ = 'b';
      } else {
         *p_PitchName++ = 'G';
         *p_PitchName++ = '#';
      }
      break;
   case 9:
      *p_PitchName++ = 'A';
      break;
   case 10:
      if (bWantFlats) {
         *p_PitchName++ = 'B';
         *p_PitchName++ = 'b';
      } else {
         *p_PitchName++ = 'A';
         *p_PitchName++ = '#';
      }
      break;
   case 11:
      *p_PitchName++ = 'B';
      break;
   }

	*p_PitchName = '\0';

   return gPitchName;
}
// 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();
}
Exemple #7
0
// PitchName takes pitchNum (as per result from 
// Freq2Pitch) and returns a standard pitch/note name [C, C#, etc.). 
// Sharps are the default, unless, bWantFlats is true.
wxChar * PitchName(float pitchNum, bool bWantFlats /* = false */)
{
   p_PitchName = gPitchName;

   switch (PitchIndex(pitchNum)) {
   case 0:
      *p_PitchName++ = wxT('C');
      break;
   case 1:
      if (bWantFlats) {
         *p_PitchName++ = wxT('D');
         *p_PitchName++ = wxT('b');
      } else {
         *p_PitchName++ = wxT('C');
         *p_PitchName++ = wxT('#');
      }
      break;
   case 2:
      *p_PitchName++ = wxT('D');
      break;
   case 3:
      if (bWantFlats) {
         *p_PitchName++ = wxT('E');
         *p_PitchName++ = wxT('b');
      } else {
         *p_PitchName++ = wxT('D');
         *p_PitchName++ = wxT('#');
      }
      break;
   case 4:
      *p_PitchName++ = wxT('E');
      break;
   case 5:
      *p_PitchName++ = wxT('F');
      break;
   case 6:
      if (bWantFlats) {
         *p_PitchName++ = wxT('G');
         *p_PitchName++ = wxT('b');
      } else {
         *p_PitchName++ = wxT('F');
         *p_PitchName++ = wxT('#');
      }
      break;
   case 7:
      *p_PitchName++ = wxT('G');
      break;
   case 8:
      if (bWantFlats) {
         *p_PitchName++ = wxT('A');
         *p_PitchName++ = wxT('b');
      } else {
         *p_PitchName++ = wxT('G');
         *p_PitchName++ = wxT('#');
      }
      break;
   case 9:
      *p_PitchName++ = wxT('A');
      break;
   case 10:
      if (bWantFlats) {
         *p_PitchName++ = wxT('B');
         *p_PitchName++ = wxT('b');
      } else {
         *p_PitchName++ = wxT('A');
         *p_PitchName++ = wxT('#');
      }
      break;
   case 11:
      *p_PitchName++ = wxT('B');
      break;
   }

	*p_PitchName = wxT('\0');

   return gPitchName;
}