mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-03 23:53:55 +01:00 
			
		
		
		
	Improvements in Change Pitch effect.
* from and to octave spin controls and cross-updating * new conversion utilities in PitchName.* * code simplification, new documentation * stop a few compiler warnings in FreqWindow.cpp on unused params
This commit is contained in:
		@@ -440,7 +440,7 @@ void FreqWindow::GetAudio()
 | 
			
		||||
   //wxLogDebug(wxT("Leaving FreqWindow::GetAudio()"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqWindow::OnSize(wxSizeEvent & event)
 | 
			
		||||
void FreqWindow::OnSize(wxSizeEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   Layout();
 | 
			
		||||
 | 
			
		||||
@@ -616,7 +616,7 @@ void FreqWindow::PlotMouseEvent(wxMouseEvent & event)
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqWindow::OnAlgChoice(wxCommandEvent & event)
 | 
			
		||||
void FreqWindow::OnAlgChoice(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   // Log-frequency axis works for spectrum plots only.
 | 
			
		||||
   if (mAlgChoice->GetSelection() == 0) {
 | 
			
		||||
@@ -630,17 +630,17 @@ void FreqWindow::OnAlgChoice(wxCommandEvent & event)
 | 
			
		||||
   Recalc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqWindow::OnSizeChoice(wxCommandEvent & event)
 | 
			
		||||
void FreqWindow::OnSizeChoice(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   Recalc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqWindow::OnFuncChoice(wxCommandEvent & event)
 | 
			
		||||
void FreqWindow::OnFuncChoice(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   Recalc();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqWindow::OnAxisChoice(wxCommandEvent & event)
 | 
			
		||||
void FreqWindow::OnAxisChoice(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   mLogAxis = (mAxisChoice->GetSelection())?true:false;
 | 
			
		||||
 | 
			
		||||
@@ -868,8 +868,8 @@ void FreqWindow::PlotPaint(wxPaintEvent & evt)
 | 
			
		||||
      const wxChar *pp;
 | 
			
		||||
 | 
			
		||||
      if (alg == 0) {
 | 
			
		||||
         xpitch = PitchName_Absolute(FreqToMIDInoteNumber(xPos));
 | 
			
		||||
         peakpitch = PitchName_Absolute(FreqToMIDInoteNumber(bestpeak));
 | 
			
		||||
         xpitch = PitchName_Absolute(FreqToMIDInote(xPos));
 | 
			
		||||
         peakpitch = PitchName_Absolute(FreqToMIDInote(bestpeak));
 | 
			
		||||
         xp = xpitch.c_str();
 | 
			
		||||
         pp = peakpitch.c_str();
 | 
			
		||||
         /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#*/
 | 
			
		||||
@@ -878,8 +878,8 @@ void FreqWindow::PlotPaint(wxPaintEvent & evt)
 | 
			
		||||
               int (value + 0.5), int (bestpeak + 0.5),
 | 
			
		||||
               pp, bestValue);
 | 
			
		||||
      } else if (xPos > 0.0 && bestpeak > 0.0) {
 | 
			
		||||
         xpitch = PitchName_Absolute(FreqToMIDInoteNumber(1.0 / xPos));
 | 
			
		||||
         peakpitch = PitchName_Absolute(FreqToMIDInoteNumber(1.0 / bestpeak));
 | 
			
		||||
         xpitch = PitchName_Absolute(FreqToMIDInote(1.0 / xPos));
 | 
			
		||||
         peakpitch = PitchName_Absolute(FreqToMIDInote(1.0 / bestpeak));
 | 
			
		||||
         xp = xpitch.c_str();
 | 
			
		||||
         pp = peakpitch.c_str();
 | 
			
		||||
         /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#
 | 
			
		||||
@@ -1287,7 +1287,7 @@ FreqPlot::FreqPlot(wxWindow * parent, wxWindowID id,
 | 
			
		||||
   freqWindow = (FreqWindow *) parent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FreqPlot::OnErase(wxEraseEvent &evt)
 | 
			
		||||
void FreqPlot::OnErase(wxEraseEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   // Ignore it to prevent flashing
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,42 +23,36 @@
 | 
			
		||||
#include "PitchName.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// FreqToMIDInoteNumber takes a frequency in Hz (exponential scale relative to 
 | 
			
		||||
// alphabetic pitch names) and returns a pitch ID number (linear 
 | 
			
		||||
// scale), such that A440 (A4) is 69, middle C (C4) is 60, etc.
 | 
			
		||||
// Each register starts with C (e.g., for middle C and A440, 
 | 
			
		||||
// it's register 4).
 | 
			
		||||
double FreqToMIDInoteNumber(double freq)
 | 
			
		||||
double FreqToMIDInote(const double freq)
 | 
			
		||||
{
 | 
			
		||||
   // Make the calculation relative to A440 (A4), note number 69. 
 | 
			
		||||
   return (69.0 + (12.0 * (log(freq / 440.0) / log(2.0))));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PitchIndex returns the [0,11] index for a double pitchNum, 
 | 
			
		||||
// as per result from FreqToMIDInoteNumber, corresponding to modulo 12 
 | 
			
		||||
// of the integer part of (pitchNum + 0.5), so 0=C, 1=C#, etc.
 | 
			
		||||
unsigned int PitchIndex(double pitchNum)
 | 
			
		||||
unsigned int PitchIndex(const double dMIDInote)
 | 
			
		||||
{
 | 
			
		||||
   int nPitchIndex = ((int)(pitchNum + 0.5) % 12);
 | 
			
		||||
   // MIDI numbers (pitchNum) can be negative.
 | 
			
		||||
   int nPitchIndex = ((int)(dMIDInote + 0.5) % 12);
 | 
			
		||||
   // MIDI numbers can be negative.
 | 
			
		||||
   // Because of the modulo, we know we're within 12 of positive. 
 | 
			
		||||
   if (nPitchIndex < 0)
 | 
			
		||||
      nPitchIndex += 12;
 | 
			
		||||
   return nPitchIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int PitchOctave(const double dMIDInote)
 | 
			
		||||
{
 | 
			
		||||
   return ((int)((dMIDInote + 0.5) / 12) - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
wxChar gPitchName[10];
 | 
			
		||||
wxChar * pPitchName;
 | 
			
		||||
 | 
			
		||||
// PitchName takes pitchNum (as per result from 
 | 
			
		||||
// FreqToMIDInoteNumber) and returns a standard pitch/note name [C, C#, etc.). 
 | 
			
		||||
// Sharps are the default, unless, bWantFlats is true.
 | 
			
		||||
wxChar * PitchName(double pitchNum, bool bWantFlats /* = false */)
 | 
			
		||||
wxChar * PitchName(const double dMIDInote, const bool bWantFlats /* = false */)
 | 
			
		||||
{
 | 
			
		||||
   pPitchName = gPitchName;
 | 
			
		||||
 | 
			
		||||
   switch (PitchIndex(pitchNum)) {
 | 
			
		||||
   switch (PitchIndex(dMIDInote)) {
 | 
			
		||||
   case 0:
 | 
			
		||||
      *pPitchName++ = wxT('C');
 | 
			
		||||
      break;
 | 
			
		||||
@@ -132,20 +126,23 @@ wxChar * PitchName(double pitchNum, bool bWantFlats /* = false */)
 | 
			
		||||
   return gPitchName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PitchName_Absolute does the same thing as PitchName, but appends 
 | 
			
		||||
// the octave number, e.g., instead of "C" it will return "C4" 
 | 
			
		||||
// if the pitchNum corresonds to middle C, i.e., is 60. 
 | 
			
		||||
// ("Scientific Pitch Notation")
 | 
			
		||||
// Sharps are the default, unless, bWantFlats is true.
 | 
			
		||||
wxChar * PitchName_Absolute(double pitchNum, bool bWantFlats /* = false */)
 | 
			
		||||
wxChar * PitchName_Absolute(const double dMIDInote, const bool bWantFlats /* = false */)
 | 
			
		||||
{
 | 
			
		||||
   PitchName(pitchNum, bWantFlats);
 | 
			
		||||
   PitchName(dMIDInote, bWantFlats);
 | 
			
		||||
 | 
			
		||||
   // PitchName sets pPitchName to the next available char in gPitchName,
 | 
			
		||||
   // so it's ready to append the register number.
 | 
			
		||||
   int octaveNum = ((int)((pitchNum + 0.5) / 12) - 1);
 | 
			
		||||
   wxSnprintf(pPitchName, 8, wxT("%d"), octaveNum);
 | 
			
		||||
   wxSnprintf(pPitchName, 8, wxT("%d"), PitchOctave(dMIDInote));
 | 
			
		||||
 | 
			
		||||
   return gPitchName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double PitchToMIDInote(const unsigned int nPitchIndex, const int nPitchOctave)
 | 
			
		||||
{
 | 
			
		||||
   return ((double)nPitchIndex + (((double)nPitchOctave + 1.0) * 12.0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double PitchToFreq(const unsigned int nPitchIndex, const int nPitchOctave)
 | 
			
		||||
{
 | 
			
		||||
   return (440.0 * pow(2.0, (PitchToMIDInote(nPitchIndex, nPitchOctave) - 69) / 12.0));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,56 +1,55 @@
 | 
			
		||||
/**********************************************************************
 | 
			
		||||
 | 
			
		||||
  Audacity: A Digital Audio Editor
 | 
			
		||||
   Audacity: A Digital Audio Editor
 | 
			
		||||
   Audacity(R) is copyright (c) 1999-2013 Audacity Team.
 | 
			
		||||
   License: GPL v2.  See License.txt.
 | 
			
		||||
 | 
			
		||||
  PitchName.h
 | 
			
		||||
   PitchName.h
 | 
			
		||||
   Vaughan Johnson, Dominic Mazzoni
 | 
			
		||||
 | 
			
		||||
  Copyright 2005-9, Vaughan Johnson and Dominic Mazzoni. 
 | 
			
		||||
  All rights reserved.
 | 
			
		||||
******************************************************************//**
 | 
			
		||||
 | 
			
		||||
  Utilities for converting from frequency to pitch 
 | 
			
		||||
  and from pitch to absolute (e.g., C4 for middle C) 
 | 
			
		||||
  or nominal (A through G#) pitch name.
 | 
			
		||||
   utilities for converting among frequency, MIDI note number, 
 | 
			
		||||
   pitch index, pitch name
 | 
			
		||||
 | 
			
		||||
*//*******************************************************************/
 | 
			
		||||
 | 
			
		||||
**********************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __AUDACITY_PITCHNAME__
 | 
			
		||||
#define __AUDACITY_PITCHNAME__
 | 
			
		||||
 | 
			
		||||
#include <wx/defs.h>
 | 
			
		||||
 | 
			
		||||
// FreqToMIDInoteNumber takes a frequency in Hz (exponential scale relative to 
 | 
			
		||||
// FreqToMIDInote takes a frequency in Hz (exponential scale relative to 
 | 
			
		||||
// alphabetic pitch names) and returns a pitch ID number (linear 
 | 
			
		||||
// scale), such that A440 (A4) is 69, middle C (C4) is 60, etc.
 | 
			
		||||
// Each register starts with C (e.g., for middle C and A440, 
 | 
			
		||||
// it's register 4).
 | 
			
		||||
double FreqToMIDInoteNumber(double freq);
 | 
			
		||||
// MIDI note number 0 is C-1 in Scientific pitch notation.
 | 
			
		||||
double FreqToMIDInote(const double freq);
 | 
			
		||||
 | 
			
		||||
// PitchIndex returns the [0,11] index for a double pitchNum, 
 | 
			
		||||
// as per result from FreqToMIDInoteNumber, corresponding to modulo 12 
 | 
			
		||||
// of the integer part of (pitchNum + 0.5), so 0=C, 1=C#, etc.
 | 
			
		||||
unsigned int PitchIndex(double pitchNum);
 | 
			
		||||
// PitchIndex returns the [0,11] index for a double MIDI note number, 
 | 
			
		||||
// per result from FreqToMIDInote, corresponding to modulo 12 
 | 
			
		||||
// of the integer part of (dMIDInote + 0.5), so 0=C, 1=C#, etc.
 | 
			
		||||
unsigned int PitchIndex(const double dMIDInote);
 | 
			
		||||
 | 
			
		||||
// PitchName takes pitchNum (as per result from 
 | 
			
		||||
// FreqToMIDInoteNumber) and returns a standard pitch/note name [C, C#, etc.). 
 | 
			
		||||
// PitchOctave returns the octave index for a double dMIDInote note number, 
 | 
			
		||||
// per result from FreqToMIDInote.
 | 
			
		||||
// MIDI note number 0 is C-1 in Scientific pitch notation.
 | 
			
		||||
int PitchOctave(const double dMIDInote);
 | 
			
		||||
 | 
			
		||||
// PitchName takes dMIDInote (per result from 
 | 
			
		||||
// FreqToMIDInote) and returns a standard pitch/note name [C, C#, etc.). 
 | 
			
		||||
// Sharps are the default, unless, bWantFlats is true.
 | 
			
		||||
wxChar * PitchName(double pitchNum, bool bWantFlats = false);
 | 
			
		||||
wxChar * PitchName(const double dMIDInote, const bool bWantFlats = false);
 | 
			
		||||
 | 
			
		||||
// PitchName_Absolute does the same thing as PitchName, but appends 
 | 
			
		||||
// the register number, e.g., instead of "C" it will return "C4" 
 | 
			
		||||
// if the pitchNum corresonds to middle C.
 | 
			
		||||
// Sharps are the default, unless, bWantFlats is true.
 | 
			
		||||
wxChar * PitchName_Absolute(double pitchNum, bool bWantFlats = false);
 | 
			
		||||
// the octave number, e.g., instead of "C" it will return "C4" 
 | 
			
		||||
// if the dMIDInote corresonds to middle C, i.e., is 60. 
 | 
			
		||||
wxChar * PitchName_Absolute(const double dMIDInote, const bool bWantFlats = false);
 | 
			
		||||
 | 
			
		||||
double PitchToMIDInote(const unsigned int nPitchIndex, const int nPitchOctave);
 | 
			
		||||
 | 
			
		||||
double PitchToFreq(const unsigned int nPitchIndex, const int nPitchOctave);
 | 
			
		||||
 | 
			
		||||
#endif	// __AUDACITY_PITCHNAME__
 | 
			
		||||
 | 
			
		||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
 | 
			
		||||
// version control system. Please do not modify past this point.
 | 
			
		||||
//
 | 
			
		||||
// Local Variables:
 | 
			
		||||
// c-basic-offset: 3
 | 
			
		||||
// indent-tabs-mode: nil
 | 
			
		||||
// End:
 | 
			
		||||
//
 | 
			
		||||
// vim: et sts=3 sw=3
 | 
			
		||||
// arch-tag: 1cd2b819-63b6-4051-9991-37165f236037
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,6 @@
 | 
			
		||||
 | 
			
		||||
#include "ChangePitch.h"
 | 
			
		||||
 | 
			
		||||
#include "../ShuttleGui.h"
 | 
			
		||||
#include "../PitchName.h"
 | 
			
		||||
#include "../Spectrum.h"
 | 
			
		||||
#include "../WaveTrack.h"
 | 
			
		||||
#include "TimeWarper.h"
 | 
			
		||||
 | 
			
		||||
#include <float.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
@@ -34,25 +28,31 @@
 | 
			
		||||
#include <wx/textctrl.h>
 | 
			
		||||
#include <wx/valtext.h>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
#include "../ShuttleGui.h"
 | 
			
		||||
#include "../PitchName.h"
 | 
			
		||||
#include "../Spectrum.h"
 | 
			
		||||
#include "../WaveTrack.h"
 | 
			
		||||
#include "TimeWarper.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// EffectChangePitch
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
EffectChangePitch::EffectChangePitch()
 | 
			
		||||
{
 | 
			
		||||
   m_FromPitchIndex = -1;		// -1 => uninitialized
 | 
			
		||||
   m_ToPitchIndex = -1;			// -1 => uninitialized
 | 
			
		||||
   m_nFromPitch = -1; // -1 => uninitialized
 | 
			
		||||
   m_nToPitch = -1;   // -1 => uninitialized
 | 
			
		||||
 | 
			
		||||
   m_SemitonesChange = 0.0;
 | 
			
		||||
 | 
			
		||||
   m_FromFrequency = 0.0;		// 0.0 => uninitialized
 | 
			
		||||
   m_ToFrequency = 0.0;			// 0.0 => uninitialized
 | 
			
		||||
   m_FromFrequency = 0.0; // 0.0 => uninitialized
 | 
			
		||||
   m_ToFrequency = 0.0;   // 0.0 => uninitialized
 | 
			
		||||
 | 
			
		||||
   m_PercentChange = 0.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wxString EffectChangePitch::GetEffectDescription() { 
 | 
			
		||||
   // Note: This is useful only after change amount has been set. 
 | 
			
		||||
wxString EffectChangePitch::GetEffectDescription() 
 | 
			
		||||
{ 
 | 
			
		||||
   // This is useful only after m_SemitonesChange has been set. 
 | 
			
		||||
   return wxString::Format(_("Applied effect: %s %.2f semitones"), 
 | 
			
		||||
                           this->GetEffectName().c_str(), 
 | 
			
		||||
                           m_SemitonesChange); 
 | 
			
		||||
@@ -64,9 +64,8 @@ bool EffectChangePitch::Init()
 | 
			
		||||
   return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
// 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
 | 
			
		||||
@@ -125,8 +124,8 @@ void EffectChangePitch::DeduceFrequencies()
 | 
			
		||||
      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_ToPitchIndex = PitchIndex(FreqToMIDInoteNumber(m_ToFrequency));
 | 
			
		||||
      m_nFromPitch = PitchIndex(FreqToMIDInote(m_FromFrequency));
 | 
			
		||||
      m_nToPitch = PitchIndex(FreqToMIDInote(m_ToFrequency));
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -135,24 +134,26 @@ bool EffectChangePitch::PromptUser()
 | 
			
		||||
   this->DeduceFrequencies(); // Set frequency-related control values based on sample.
 | 
			
		||||
 | 
			
		||||
   ChangePitchDialog dlog(this, mParent);
 | 
			
		||||
   dlog.m_FromPitchIndex = m_FromPitchIndex;
 | 
			
		||||
   dlog.m_ToPitchIndex = m_ToPitchIndex;
 | 
			
		||||
   dlog.m_nFromPitch = m_nFromPitch;
 | 
			
		||||
   dlog.m_nFromOctave = PitchOctave(FreqToMIDInote(m_FromFrequency));
 | 
			
		||||
   dlog.m_nToPitch = m_nToPitch;
 | 
			
		||||
   dlog.m_nToOctave = PitchOctave(FreqToMIDInote(m_ToFrequency));
 | 
			
		||||
   dlog.m_SemitonesChange = m_SemitonesChange;
 | 
			
		||||
   dlog.m_FromFrequency = m_FromFrequency;
 | 
			
		||||
   dlog.m_ToFrequency = m_ToFrequency;
 | 
			
		||||
   dlog.m_PercentChange = m_PercentChange;
 | 
			
		||||
   // Don't need to call TransferDataToWindow, although other 
 | 
			
		||||
   //	Audacity dialogs (from which I derived this one) do it, because 
 | 
			
		||||
   //	ShowModal calls stuff that eventually calls wxWindowBase::OnInitDialog, 
 | 
			
		||||
   //	which calls dlog.TransferDataToWindow();
 | 
			
		||||
   //   Audacity dialogs (from which I derived this one) do it, because 
 | 
			
		||||
   //   ShowModal calls stuff that eventually calls wxWindowBase::OnInitDialog, 
 | 
			
		||||
   //   which calls dlog.TransferDataToWindow();
 | 
			
		||||
   dlog.CentreOnParent();
 | 
			
		||||
   dlog.ShowModal();
 | 
			
		||||
 | 
			
		||||
  if (dlog.GetReturnCode() == wxID_CANCEL)
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
   m_FromPitchIndex = dlog.m_FromPitchIndex;
 | 
			
		||||
   m_ToPitchIndex = dlog.m_ToPitchIndex;
 | 
			
		||||
   m_nFromPitch = dlog.m_nFromPitch;
 | 
			
		||||
   m_nToPitch = dlog.m_nToPitch;
 | 
			
		||||
   m_SemitonesChange = dlog.m_SemitonesChange;
 | 
			
		||||
   m_FromFrequency = dlog.m_FromFrequency;
 | 
			
		||||
   m_ToFrequency = dlog.m_ToFrequency;
 | 
			
		||||
@@ -162,6 +163,8 @@ bool EffectChangePitch::PromptUser()
 | 
			
		||||
 | 
			
		||||
bool EffectChangePitch::TransferParameters( Shuttle & shuttle )
 | 
			
		||||
{  
 | 
			
		||||
   // Vaughan: Long lost to history, I don't see why m_PercentChange was chosen to be shuttled. 
 | 
			
		||||
   // Only m_SemitonesChange is used in Process(). 
 | 
			
		||||
   shuttle.TransferDouble(wxT("Percentage"),m_PercentChange,0.0);
 | 
			
		||||
   m_SemitonesChange = (12.0 * log((100.0 + m_PercentChange) / 100.0)) / log(2.0);
 | 
			
		||||
   return true;
 | 
			
		||||
@@ -197,7 +200,9 @@ enum {
 | 
			
		||||
   ID_TEXT_PERCENTCHANGE = 10001,
 | 
			
		||||
   ID_SLIDER_PERCENTCHANGE,
 | 
			
		||||
   ID_CHOICE_FROMPITCH,
 | 
			
		||||
   ID_CHOICE_FROMOCTAVE,
 | 
			
		||||
   ID_CHOICE_TOPITCH,
 | 
			
		||||
   ID_CHOICE_TOOCTAVE,
 | 
			
		||||
   ID_TEXT_SEMITONESCHANGE,
 | 
			
		||||
   ID_TEXT_FROMFREQUENCY,
 | 
			
		||||
   ID_TEXT_TOFREQUENCY
 | 
			
		||||
@@ -207,7 +212,9 @@ enum {
 | 
			
		||||
 | 
			
		||||
BEGIN_EVENT_TABLE(ChangePitchDialog, EffectDialog)
 | 
			
		||||
   EVT_CHOICE(ID_CHOICE_FROMPITCH, ChangePitchDialog::OnChoice_FromPitch)
 | 
			
		||||
   EVT_TEXT(ID_CHOICE_FROMOCTAVE, ChangePitchDialog::OnSpin_FromOctave)
 | 
			
		||||
   EVT_CHOICE(ID_CHOICE_TOPITCH, ChangePitchDialog::OnChoice_ToPitch)
 | 
			
		||||
   EVT_TEXT(ID_CHOICE_TOOCTAVE, ChangePitchDialog::OnSpin_ToOctave)
 | 
			
		||||
 | 
			
		||||
   EVT_TEXT(ID_TEXT_SEMITONESCHANGE, ChangePitchDialog::OnText_SemitonesChange)
 | 
			
		||||
 | 
			
		||||
@@ -224,14 +231,15 @@ ChangePitchDialog::ChangePitchDialog(EffectChangePitch *effect, wxWindow *parent
 | 
			
		||||
:  EffectDialog(parent, _("Change Pitch"), PROCESS_EFFECT),
 | 
			
		||||
   mEffect(effect)
 | 
			
		||||
{
 | 
			
		||||
   m_bLoopDetect = false;
 | 
			
		||||
   m_bLoopDetect = false; 
 | 
			
		||||
 | 
			
		||||
   // NULL out these control members because there are some cases where the 
 | 
			
		||||
   // event table handlers get called during this method, and those handlers that 
 | 
			
		||||
   // can cause trouble check for NULL.
 | 
			
		||||
   m_pChoice_FromPitch = NULL;
 | 
			
		||||
   m_pRadioButton_PitchDown = NULL;
 | 
			
		||||
   m_pSpin_FromOctave = NULL;
 | 
			
		||||
   m_pChoice_ToPitch = NULL;
 | 
			
		||||
   m_pSpin_ToOctave = NULL;
 | 
			
		||||
   
 | 
			
		||||
   m_pTextCtrl_SemitonesChange = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -242,13 +250,15 @@ ChangePitchDialog::ChangePitchDialog(EffectChangePitch *effect, wxWindow *parent
 | 
			
		||||
   m_pSlider_PercentChange = NULL;
 | 
			
		||||
 | 
			
		||||
   // effect parameters
 | 
			
		||||
   m_FromPitchIndex = -1;		// -1 => uninitialized
 | 
			
		||||
   m_ToPitchIndex = -1;			// -1 => uninitialized
 | 
			
		||||
   m_nFromPitch = -1;  // -1 => uninitialized
 | 
			
		||||
   m_nFromOctave = -1; // -1 => uninitialized
 | 
			
		||||
   m_nToPitch = -1;    // -1 => uninitialized
 | 
			
		||||
   m_nToOctave = -1;   // -1 => uninitialized
 | 
			
		||||
 | 
			
		||||
   m_SemitonesChange = 0.0;
 | 
			
		||||
 | 
			
		||||
   m_FromFrequency = 0.0;		// 0.0 => uninitialized
 | 
			
		||||
   m_ToFrequency = 0.0;			// 0.0 => uninitialized
 | 
			
		||||
   m_FromFrequency = 0.0;      // 0.0 => uninitialized
 | 
			
		||||
   m_ToFrequency = 0.0;         // 0.0 => uninitialized
 | 
			
		||||
 | 
			
		||||
   m_PercentChange = 0.0;
 | 
			
		||||
 | 
			
		||||
@@ -294,7 +304,7 @@ void ChangePitchDialog::PopulateOrExchange(ShuttleGui & S)
 | 
			
		||||
   {
 | 
			
		||||
      S.AddTitle(_("Change Pitch without Changing Tempo") +
 | 
			
		||||
                 wxString(wxT("\n\n")) +
 | 
			
		||||
                 _("by Vaughan Johnson && Dominic Mazzoni") +
 | 
			
		||||
                 _("by Vaughan Johnson, Dominic Mazzoni, && Steve Daulton") +
 | 
			
		||||
                 wxString(wxT("\n")) +
 | 
			
		||||
                 _("using SoundTouch, by Olli Parviainen"));
 | 
			
		||||
   }
 | 
			
		||||
@@ -312,9 +322,19 @@ void ChangePitchDialog::PopulateOrExchange(ShuttleGui & S)
 | 
			
		||||
            m_pChoice_FromPitch->SetName(_("From Pitch"));
 | 
			
		||||
            m_pChoice_FromPitch->SetSizeHints(80, -1);
 | 
			
		||||
 | 
			
		||||
            m_pSpin_FromOctave = 
 | 
			
		||||
               S.Id(ID_CHOICE_FROMOCTAVE).AddSpinCtrl(wxT(""), m_nFromOctave, INT_MAX, INT_MIN); 
 | 
			
		||||
            m_pSpin_FromOctave->SetName(_("From Octave"));
 | 
			
		||||
            m_pSpin_FromOctave->SetSizeHints(50, -1);
 | 
			
		||||
 | 
			
		||||
            m_pChoice_ToPitch = S.Id(ID_CHOICE_TOPITCH).AddChoice(_("to"), wxT(""), &pitch);
 | 
			
		||||
            m_pChoice_ToPitch->SetName(_("To Pitch"));
 | 
			
		||||
            m_pChoice_ToPitch->SetSizeHints(80, -1);
 | 
			
		||||
 | 
			
		||||
            m_pSpin_ToOctave = 
 | 
			
		||||
               S.Id(ID_CHOICE_TOOCTAVE).AddSpinCtrl(wxT(""), m_nToOctave, INT_MAX, INT_MIN); 
 | 
			
		||||
            m_pSpin_ToOctave->SetName(_("From Octave"));
 | 
			
		||||
            m_pSpin_ToOctave->SetSizeHints(50, -1);
 | 
			
		||||
         }
 | 
			
		||||
         S.EndHorizontalLay();
 | 
			
		||||
      }
 | 
			
		||||
@@ -377,15 +397,15 @@ bool ChangePitchDialog::TransferDataToWindow()
 | 
			
		||||
 | 
			
		||||
   // from/to pitch controls
 | 
			
		||||
   if (m_pChoice_FromPitch) 
 | 
			
		||||
      m_pChoice_FromPitch->SetSelection(m_FromPitchIndex);
 | 
			
		||||
 | 
			
		||||
   this->Update_Choice_ToPitch();
 | 
			
		||||
 | 
			
		||||
      m_pChoice_FromPitch->SetSelection(m_nFromPitch);
 | 
			
		||||
   if (m_pSpin_FromOctave)
 | 
			
		||||
      m_pSpin_FromOctave->SetValue(m_nFromOctave); 
 | 
			
		||||
   this->Update_Choice_ToPitch(); 
 | 
			
		||||
   this->Update_Spin_ToOctave(); 
 | 
			
		||||
 | 
			
		||||
   // semitones change control
 | 
			
		||||
   this->Update_Text_SemitonesChange();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   // from/to frequency controls
 | 
			
		||||
   if (m_pTextCtrl_FromFrequency) {
 | 
			
		||||
      wxString str;
 | 
			
		||||
@@ -398,12 +418,10 @@ bool ChangePitchDialog::TransferDataToWindow()
 | 
			
		||||
 | 
			
		||||
   this->Update_Text_ToFrequency();
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
   // percent change controls
 | 
			
		||||
   this->Update_Text_PercentChange();
 | 
			
		||||
   this->Update_Slider_PercentChange();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   m_bLoopDetect = false;
 | 
			
		||||
 | 
			
		||||
   return true;
 | 
			
		||||
@@ -417,10 +435,12 @@ bool ChangePitchDialog::TransferDataFromWindow()
 | 
			
		||||
 | 
			
		||||
   // from/to pitch controls
 | 
			
		||||
   if (m_pChoice_FromPitch) 
 | 
			
		||||
      m_FromPitchIndex = m_pChoice_FromPitch->GetSelection(); 
 | 
			
		||||
      m_nFromPitch = m_pChoice_FromPitch->GetSelection(); 
 | 
			
		||||
   if (m_pSpin_FromOctave) 
 | 
			
		||||
      m_nFromOctave = m_pSpin_FromOctave->GetValue();
 | 
			
		||||
 | 
			
		||||
   if (m_pChoice_ToPitch) 
 | 
			
		||||
      m_ToPitchIndex = m_pChoice_ToPitch->GetSelection();
 | 
			
		||||
      m_nToPitch = m_pChoice_ToPitch->GetSelection();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   // semitones change control
 | 
			
		||||
@@ -462,18 +482,24 @@ bool ChangePitchDialog::TransferDataFromWindow()
 | 
			
		||||
 | 
			
		||||
// calculations
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Calc_ToPitchIndex()
 | 
			
		||||
void ChangePitchDialog::Calc_ToPitch() 
 | 
			
		||||
{
 | 
			
		||||
   int nSemitonesChange = 
 | 
			
		||||
      (int)(m_SemitonesChange + ((m_SemitonesChange < 0.0) ? -0.5 : 0.5));
 | 
			
		||||
   m_ToPitchIndex = (m_FromPitchIndex + nSemitonesChange) % 12;
 | 
			
		||||
   if (m_ToPitchIndex < 0)
 | 
			
		||||
      m_ToPitchIndex += 12;
 | 
			
		||||
   m_nToPitch = (m_nFromPitch + nSemitonesChange) % 12;
 | 
			
		||||
   if (m_nToPitch < 0)
 | 
			
		||||
      m_nToPitch += 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Calc_ToOctave()
 | 
			
		||||
{
 | 
			
		||||
   m_nToOctave = PitchOctave(FreqToMIDInote(m_ToFrequency));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Calc_SemitonesChange_fromPitches()
 | 
			
		||||
{
 | 
			
		||||
   m_SemitonesChange = m_ToPitchIndex - m_FromPitchIndex;
 | 
			
		||||
   m_SemitonesChange = 
 | 
			
		||||
      PitchToMIDInote(m_nToPitch, m_nToOctave) - PitchToMIDInote(m_nFromPitch, m_nFromOctave);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Calc_SemitonesChange_fromPercentChange()
 | 
			
		||||
@@ -502,12 +528,43 @@ void ChangePitchDialog::OnChoice_FromPitch(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
   if (m_pChoice_FromPitch) {
 | 
			
		||||
      m_FromPitchIndex = m_pChoice_FromPitch->GetSelection();
 | 
			
		||||
      m_nFromPitch = m_pChoice_FromPitch->GetSelection();
 | 
			
		||||
      m_FromFrequency = PitchToFreq(m_nFromPitch, m_nFromOctave);
 | 
			
		||||
 | 
			
		||||
      this->Calc_ToPitchIndex();
 | 
			
		||||
      this->Calc_ToPitch();
 | 
			
		||||
      this->Calc_ToFrequency();
 | 
			
		||||
      this->Calc_ToOctave(); // Call after Calc_ToFrequency().
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Spin_ToOctave();
 | 
			
		||||
         this->Update_Text_FromFrequency();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::OnSpin_FromOctave(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   if (m_bLoopDetect)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
   if (m_pSpin_FromOctave) 
 | 
			
		||||
   {
 | 
			
		||||
      m_nFromOctave = m_pSpin_FromOctave->GetValue();
 | 
			
		||||
      m_FromFrequency = PitchToFreq(m_nFromPitch, m_nFromOctave);
 | 
			
		||||
 | 
			
		||||
      this->Calc_ToFrequency();
 | 
			
		||||
      this->Calc_ToOctave(); // Call after Calc_ToFrequency().
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Spin_ToOctave();
 | 
			
		||||
         this->Update_Text_FromFrequency();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
@@ -517,18 +574,55 @@ void ChangePitchDialog::OnChoice_ToPitch(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
   if (m_bLoopDetect)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
   if (m_pChoice_ToPitch) {
 | 
			
		||||
      m_ToPitchIndex = m_pChoice_ToPitch->GetSelection();
 | 
			
		||||
   if (m_pChoice_ToPitch) 
 | 
			
		||||
   {
 | 
			
		||||
      m_nToPitch = m_pChoice_ToPitch->GetSelection();
 | 
			
		||||
 | 
			
		||||
      this->Calc_SemitonesChange_fromPitches();
 | 
			
		||||
      this->Calc_PercentChange(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToFrequency(); // Call *after* m_PercentChange is updated.
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Text_SemitonesChange();
 | 
			
		||||
      this->Update_Text_ToFrequency();
 | 
			
		||||
      this->Update_Text_PercentChange();
 | 
			
		||||
      this->Update_Slider_PercentChange();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Text_SemitonesChange();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
         this->Update_Text_PercentChange();
 | 
			
		||||
         this->Update_Slider_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::OnSpin_ToOctave(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
   if (m_bLoopDetect)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
   if (m_pSpin_ToOctave) 
 | 
			
		||||
   {
 | 
			
		||||
      int nNewValue = m_pSpin_ToOctave->GetValue();
 | 
			
		||||
      // Validation: Rather than set a range for octave numbers, enforce a range that 
 | 
			
		||||
      // keeps below 90% m_PercentChange. 
 | 
			
		||||
      if ((nNewValue + 3) < m_nFromOctave)
 | 
			
		||||
      {
 | 
			
		||||
         ::wxBell();
 | 
			
		||||
         m_pSpin_ToOctave->SetValue(m_nFromOctave - 3);
 | 
			
		||||
         return;
 | 
			
		||||
      }
 | 
			
		||||
      m_nToOctave = nNewValue;
 | 
			
		||||
 | 
			
		||||
      m_ToFrequency = PitchToFreq(m_nToPitch, m_nToOctave);
 | 
			
		||||
 | 
			
		||||
      this->Calc_SemitonesChange_fromPitches();
 | 
			
		||||
      this->Calc_PercentChange(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Text_SemitonesChange();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
         this->Update_Text_PercentChange();
 | 
			
		||||
         this->Update_Slider_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
@@ -551,13 +645,15 @@ void ChangePitchDialog::OnText_SemitonesChange(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
 | 
			
		||||
      this->Calc_PercentChange();
 | 
			
		||||
      this->Calc_ToFrequency(); // Call *after* m_PercentChange is updated.
 | 
			
		||||
      this->Calc_ToPitchIndex();
 | 
			
		||||
      this->Calc_ToPitch();
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      this->Update_Text_ToFrequency();
 | 
			
		||||
      this->Update_Text_PercentChange();
 | 
			
		||||
      this->Update_Slider_PercentChange();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
         this->Update_Text_PercentChange();
 | 
			
		||||
         this->Update_Slider_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
 | 
			
		||||
      // If m_SemitonesChange is a big enough negative, we can go to or below 0 freq. 
 | 
			
		||||
@@ -589,14 +685,16 @@ void ChangePitchDialog::OnText_FromFrequency(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
      }
 | 
			
		||||
      m_FromFrequency = newDouble;
 | 
			
		||||
 | 
			
		||||
      m_FromPitchIndex = PitchIndex(FreqToMIDInoteNumber(m_FromFrequency));
 | 
			
		||||
      m_nFromPitch = PitchIndex(FreqToMIDInote(m_FromFrequency));
 | 
			
		||||
      this->Calc_ToFrequency();
 | 
			
		||||
      this->Calc_ToPitchIndex();
 | 
			
		||||
      this->Calc_ToPitch();
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_FromPitch();
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      this->Update_Text_ToFrequency();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_FromPitch();
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
 | 
			
		||||
      // Success. Make sure OK and Preview are enabled, in case we disabled above during editing. 
 | 
			
		||||
@@ -629,13 +727,15 @@ void ChangePitchDialog::OnText_ToFrequency(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
                           (double)(m_FromFrequency)) - 100.0;
 | 
			
		||||
 | 
			
		||||
      this->Calc_SemitonesChange_fromPercentChange();
 | 
			
		||||
      this->Calc_ToPitchIndex(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToPitch(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      this->Update_Text_SemitonesChange();
 | 
			
		||||
      this->Update_Text_PercentChange();
 | 
			
		||||
      this->Update_Slider_PercentChange();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Text_SemitonesChange();
 | 
			
		||||
         this->Update_Text_PercentChange();
 | 
			
		||||
         this->Update_Slider_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   
 | 
			
		||||
      // Success. Make sure OK and Preview are enabled, in case we disabled above during editing. 
 | 
			
		||||
@@ -668,14 +768,16 @@ void ChangePitchDialog::OnText_PercentChange(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
      m_PercentChange = newValue;
 | 
			
		||||
 | 
			
		||||
      this->Calc_SemitonesChange_fromPercentChange();
 | 
			
		||||
      this->Calc_ToPitchIndex(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToPitch(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToFrequency();
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      this->Update_Text_SemitonesChange();
 | 
			
		||||
      this->Update_Text_ToFrequency();
 | 
			
		||||
      this->Update_Slider_PercentChange();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Text_SemitonesChange();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
         this->Update_Slider_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
 | 
			
		||||
      // Success. Make sure OK and Preview are enabled, in case we disabled above during editing. 
 | 
			
		||||
@@ -696,14 +798,16 @@ void ChangePitchDialog::OnSlider_PercentChange(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
         m_PercentChange = pow(m_PercentChange, PERCENTCHANGE_SLIDER_WARP);
 | 
			
		||||
 | 
			
		||||
      this->Calc_SemitonesChange_fromPercentChange();
 | 
			
		||||
      this->Calc_ToPitchIndex(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToPitch(); // Call *after* m_SemitonesChange is updated.
 | 
			
		||||
      this->Calc_ToFrequency();
 | 
			
		||||
 | 
			
		||||
      m_bLoopDetect = true;
 | 
			
		||||
      this->Update_Choice_ToPitch();
 | 
			
		||||
      this->Update_Text_SemitonesChange();
 | 
			
		||||
      this->Update_Text_ToFrequency();
 | 
			
		||||
      this->Update_Text_PercentChange();
 | 
			
		||||
      {
 | 
			
		||||
         this->Update_Choice_ToPitch();
 | 
			
		||||
         this->Update_Text_SemitonesChange();
 | 
			
		||||
         this->Update_Text_ToFrequency();
 | 
			
		||||
         this->Update_Text_PercentChange();
 | 
			
		||||
      }
 | 
			
		||||
      m_bLoopDetect = false;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
@@ -729,13 +833,25 @@ void ChangePitchDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
 | 
			
		||||
void ChangePitchDialog::Update_Choice_FromPitch() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pChoice_FromPitch) 
 | 
			
		||||
      m_pChoice_FromPitch->SetSelection(m_FromPitchIndex);
 | 
			
		||||
      m_pChoice_FromPitch->SetSelection(m_nFromPitch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Spin_FromOctave() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pSpin_FromOctave) 
 | 
			
		||||
      m_pSpin_FromOctave->SetValue(m_nFromOctave); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Choice_ToPitch() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pChoice_ToPitch) 
 | 
			
		||||
      m_pChoice_ToPitch->SetSelection(m_ToPitchIndex);
 | 
			
		||||
      m_pChoice_ToPitch->SetSelection(m_nToPitch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Spin_ToOctave() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pSpin_ToOctave) 
 | 
			
		||||
      m_pSpin_ToOctave->SetValue(m_nToOctave); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Text_SemitonesChange()
 | 
			
		||||
@@ -747,6 +863,18 @@ void ChangePitchDialog::Update_Text_SemitonesChange()
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Text_FromFrequency() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pTextCtrl_FromFrequency) {
 | 
			
		||||
      wxString str;
 | 
			
		||||
      if ((m_FromFrequency > 0.0) && (m_FromFrequency <= DBL_MAX))
 | 
			
		||||
         str.Printf(wxT("%.3f"), m_FromFrequency);
 | 
			
		||||
      else
 | 
			
		||||
         str = wxT("");
 | 
			
		||||
      m_pTextCtrl_FromFrequency->SetValue(str);
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangePitchDialog::Update_Text_ToFrequency() 
 | 
			
		||||
{
 | 
			
		||||
   if (m_pTextCtrl_ToFrequency) {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
#include <wx/dialog.h>
 | 
			
		||||
#include <wx/intl.h>
 | 
			
		||||
#include <wx/slider.h>
 | 
			
		||||
#include <wx/spinctrl.h>
 | 
			
		||||
 | 
			
		||||
class EffectChangePitch : public EffectSoundTouch {
 | 
			
		||||
 | 
			
		||||
@@ -51,9 +52,8 @@ class EffectChangePitch : public EffectSoundTouch {
 | 
			
		||||
 | 
			
		||||
   virtual bool Init();
 | 
			
		||||
 | 
			
		||||
   // 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.
 | 
			
		||||
   // Deduce m_FromFrequency from the samples at the beginning of 
 | 
			
		||||
   // the selection. Then set some other params accordingly.
 | 
			
		||||
   virtual void DeduceFrequencies();
 | 
			
		||||
 | 
			
		||||
   virtual bool PromptUser();
 | 
			
		||||
@@ -63,8 +63,8 @@ class EffectChangePitch : public EffectSoundTouch {
 | 
			
		||||
   virtual bool Process();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
   int            m_FromPitchIndex;    // pitch index, per PitchIndex
 | 
			
		||||
   int            m_ToPitchIndex;      // pitch index, per PitchIndex
 | 
			
		||||
   int            m_nFromPitch;    // per PitchIndex()
 | 
			
		||||
   int            m_nToPitch;      // per PitchIndex()
 | 
			
		||||
 | 
			
		||||
   double         m_SemitonesChange;   // how many semitones to change pitch
 | 
			
		||||
 | 
			
		||||
@@ -95,15 +95,19 @@ class ChangePitchDialog:public EffectDialog {
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
   // calculations
 | 
			
		||||
   void Calc_ToPitchIndex(); // Update m_ToPitchIndex from new m_SemitonesChange.
 | 
			
		||||
   void Calc_SemitonesChange_fromPitches(); // Update m_SemitonesChange from new m_*PitchIndex-es.
 | 
			
		||||
   void Calc_SemitonesChange_fromPercentChange(); // Update m_SemitonesChange from new m_PercentChange.
 | 
			
		||||
   void Calc_ToPitch(); // Update m_nToPitch from new m_SemitonesChange.
 | 
			
		||||
   void Calc_ToOctave(); 
 | 
			
		||||
   void Calc_SemitonesChange_fromPitches();
 | 
			
		||||
   void Calc_SemitonesChange_fromOctaveChange();
 | 
			
		||||
   void Calc_SemitonesChange_fromPercentChange();
 | 
			
		||||
   void Calc_ToFrequency(); // Update m_ToFrequency from m_FromFrequency & m_PercentChange.
 | 
			
		||||
   void Calc_PercentChange(); // Update m_PercentChange based on new m_SemitonesChange.
 | 
			
		||||
 | 
			
		||||
   // handlers
 | 
			
		||||
   void OnChoice_FromPitch(wxCommandEvent & event);
 | 
			
		||||
   void OnSpin_FromOctave(wxCommandEvent & event);
 | 
			
		||||
   void OnChoice_ToPitch(wxCommandEvent & event);
 | 
			
		||||
   void OnSpin_ToOctave(wxCommandEvent & event);
 | 
			
		||||
 | 
			
		||||
   void OnText_SemitonesChange(wxCommandEvent & event);
 | 
			
		||||
 | 
			
		||||
@@ -117,10 +121,13 @@ class ChangePitchDialog:public EffectDialog {
 | 
			
		||||
 | 
			
		||||
   // helper fns for controls
 | 
			
		||||
   void Update_Choice_FromPitch();
 | 
			
		||||
   void Update_Spin_FromOctave();
 | 
			
		||||
   void Update_Choice_ToPitch();
 | 
			
		||||
   void Update_Spin_ToOctave();
 | 
			
		||||
 | 
			
		||||
   void Update_Text_SemitonesChange();
 | 
			
		||||
 | 
			
		||||
   void Update_Text_FromFrequency();
 | 
			
		||||
   void Update_Text_ToFrequency();
 | 
			
		||||
 | 
			
		||||
   void Update_Text_PercentChange(); // Update control per current m_PercentChange.
 | 
			
		||||
@@ -128,25 +135,26 @@ class ChangePitchDialog:public EffectDialog {
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
   EffectChangePitch * mEffect;
 | 
			
		||||
   bool m_bLoopDetect;
 | 
			
		||||
   bool m_bLoopDetect; // Used to avoid loops in initialization and in event handling. 
 | 
			
		||||
 | 
			
		||||
   // controls
 | 
			
		||||
   wxChoice *     m_pChoice_FromPitch;
 | 
			
		||||
   wxRadioButton *m_pRadioButton_PitchDown;
 | 
			
		||||
   wxSpinCtrl *   m_pSpin_FromOctave;
 | 
			
		||||
   wxChoice *     m_pChoice_ToPitch;
 | 
			
		||||
 | 
			
		||||
   wxSpinCtrl *   m_pSpin_ToOctave;
 | 
			
		||||
   wxTextCtrl *   m_pTextCtrl_SemitonesChange;
 | 
			
		||||
 | 
			
		||||
   wxTextCtrl *   m_pTextCtrl_FromFrequency;
 | 
			
		||||
   wxTextCtrl *   m_pTextCtrl_ToFrequency;
 | 
			
		||||
 | 
			
		||||
   wxTextCtrl *   m_pTextCtrl_PercentChange;
 | 
			
		||||
   wxSlider *     m_pSlider_PercentChange;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
   // effect parameters
 | 
			
		||||
   int      m_FromPitchIndex;    // pitch index, per PitchIndex
 | 
			
		||||
   int      m_ToPitchIndex;      // pitch index, per PitchIndex
 | 
			
		||||
   int      m_nFromPitch;    // per PitchIndex()
 | 
			
		||||
   int      m_nFromOctave;   // per PitchOctave()
 | 
			
		||||
   int      m_nToPitch;      // per PitchIndex()
 | 
			
		||||
   int      m_nToOctave;     // per PitchOctave()
 | 
			
		||||
 | 
			
		||||
   double   m_SemitonesChange;   // how many semitones to change pitch
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@ void EffectReverb::Delete()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Most of what follows should really be provided by Audacity framework classes:
 | 
			
		||||
//vvvvv Not sure what you mean by that, Rob. A la EffectSimpleMono, e.g.?
 | 
			
		||||
//vvv Not sure what you mean by that, Rob. A la EffectSimpleMono, e.g.?
 | 
			
		||||
 | 
			
		||||
bool EffectReverb::ProcessOneTrack(size_t n, WaveTrack * track, WaveTrack * track2, wxString const & msg)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user