Update of /cvsroot/audacity/audacity-src/src/effects
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv19825/src/effects

Added Files:
        SBSMSEffect.cpp SBSMSEffect.h TimeScale.cpp TimeScale.h 
Log Message:
Added sbsms and a sliding time scale/pitch shift effect.  Modified 
configuration for unix/win build to include sbsms.


--- NEW FILE: TimeScale.h ---
/**********************************************************************

  Audacity: A Digital Audio Editor

  TimeScale.h

  Clayton Otey

**********************************************************************/

#include "../Audacity.h"

#if USE_SBSMS

#ifndef __AUDACITY_EFFECT_TIMESCALE__
#define __AUDACITY_EFFECT_TIMESCALE__

#include "SBSMSEffect.h"

#include <wx/intl.h>
#include <wx/dialog.h>
#include <wx/slider.h>

class wxString;
class wxTextCtrl;

class EffectTimeScale : public EffectSBSMS {

 public:
   EffectTimeScale();

   virtual wxString GetEffectName() {
      return wxString(_("Sliding Time Scale/Pitch Shift..."));
   }

   virtual std::set<wxString> GetEffectCategories() {
     std::set<wxString> result;
     result.insert(wxT("http://audacityteam.org/namespace#PitchAndTempo";));
     return result;
   }

   virtual wxString GetEffectIdentifier() {
     return wxString(wxT("TimeScale"));
   }

   virtual wxString GetEffectAction() {
     return wxString(_("Changing Tempo/Pitch"));
   }
   
   // Useful only after PromptUser values have been set. 
   virtual wxString GetEffectDescription(); 

   virtual bool Init();

   virtual bool PromptUser();
   virtual bool TransferParameters( Shuttle & shuttle );
   virtual bool Process();
  
 private:
   double m_RateStart;
   double m_RateEnd;
   double m_HalfStepsStart;
   double m_HalfStepsEnd;
   double m_CentsStart;
   double m_CentsEnd;
   int m_Quality;
   bool m_PreAnalyze;

   friend class TimeScaleDialog;
};

//----------------------------------------------------------------------------
// TimeScaleDialog
//----------------------------------------------------------------------------

class TimeScaleDialog:public EffectDialog {
 public:
  TimeScaleDialog(EffectTimeScale * effect, 
                  wxWindow * parent);

  void PopulateOrExchange(ShuttleGui & S);
  bool TransferDataToWindow();
  bool TransferDataFromWindow();

 private:
  // handlers
  void OnText_RateStart(wxCommandEvent & event);
  void OnText_RateEnd(wxCommandEvent & event);
  void OnText_HalfStepsStart(wxCommandEvent & event);
  void OnText_HalfStepsEnd(wxCommandEvent & event);
  void OnText_CentsStart(wxCommandEvent & event);
  void OnText_CentsEnd(wxCommandEvent & event);
  void OnSlider_RateStart(wxCommandEvent & event);
  void OnSlider_RateEnd(wxCommandEvent & event);
  void OnSlider_Quality(wxCommandEvent & event);
  void OnCheckBox_PreAnalyze(wxCommandEvent & event);
  
  // helper fns
  void Update_Text_RateStart();
  void Update_Text_RateEnd();
  void Update_Text_HalfStepsStart();
  void Update_Text_HalfStepsEnd();
  void Update_Text_CentsStart();
  void Update_Text_CentsEnd();
  void Update_Slider_RateStart();
  void Update_Slider_RateEnd();
  void Update_Slider_Quality();
  void Update_CheckBox_PreAnalyze();

 private:
  EffectTimeScale *mEffect;
  bool m_bLoopDetect;

  // controls
  wxTextCtrl *m_pTextCtrl_RateStart;
  wxSlider *m_pSlider_RateStart;
  wxTextCtrl *m_pTextCtrl_RateEnd;
  wxSlider *m_pSlider_RateEnd;
  wxTextCtrl *m_pTextCtrl_HalfStepsStart;
  wxTextCtrl *m_pTextCtrl_HalfStepsEnd;
  wxTextCtrl *m_pTextCtrl_CentsStart;
  wxTextCtrl *m_pTextCtrl_CentsEnd;
  wxSlider *m_pSlider_Quality;
  wxCheckBox *m_pCheckBox_PreAnalyze;

 public:
   double m_RateStart;
   double m_RateEnd;
   double m_HalfStepsStart;
   double m_HalfStepsEnd;
   double m_CentsStart;
   double m_CentsEnd;
   int m_Quality;
   bool m_PreAnalyze;

 private:
   DECLARE_EVENT_TABLE()
};

#endif // __AUDACITY_EFFECT_TIMESCALE

#endif // USE_SBSMS

--- NEW FILE: SBSMSEffect.cpp ---
/**********************************************************************

Audacity: A Digital Audio Editor

SBSMSEffect.cpp

Clayton Otey

This abstract class contains all of the common code for an
effect that uses SBSMS to do its processing (TimeScale)

**********************************************************************/

#include "../Audacity.h"

#if USE_SBSMS

#include <math.h>

#include "SBSMSEffect.h"
#include "../WaveTrack.h"
#include "../Project.h"

struct resampleBuf {
  audio *buf;
  double ratio;
  sampleCount samplesIn;
  sampleCount block;
  sampleCount offset;
  sampleCount end;
  float *leftBuffer;
  float *rightBuffer;
  WaveTrack *leftTrack;
  WaveTrack *rightTrack;
};

long samplesCB(audio *chdata, long numFrames, void *userData)
{ 
  sbsmsInfo *si = (sbsmsInfo*) userData;
  long n_read = si->rs->read(chdata, numFrames);
  return n_read;
}

real stretchCB(long nProcessed, void *userData)
{
  sbsmsInfo *si = (sbsmsInfo*) userData;
  real t0 = (real)nProcessed/(real)si->samplesToProcess;
  real stretch = si->stretch0 + (si->stretch1-si->stretch0)*t0;
  return stretch;
}

real ratioCB(long nProcessed, void *userData)
{
  sbsmsInfo *si = (sbsmsInfo*) userData;
  real t0 = (real)nProcessed/(real)si->samplesToProcess;
  real stretch = si->stretch0 + (si->stretch1-si->stretch0)*t0;
  real t1;
  if(stretch == si->stretch0)
    t1 = 1.0/stretch;
  else
    t1 = log(stretch/si->stretch0)/(stretch-si->stretch0);

  real ratio = si->ratio0 + 
(si->ratio1-si->ratio0)*t1*(real)nProcessed/(real)si->samplesToGenerate;
  
  return ratio;
}

void EffectSBSMS :: setParameters(double rateStart, double rateEnd, double 
pitchStart, double pitchEnd, int quality, bool bPreAnalyze)
{
  this->rateStart = rateStart;
  this->rateEnd = rateEnd;
  this->pitchStart = pitchStart;
  this->pitchEnd = pitchEnd;
  this->quality = quality;
  this->bPreAnalyze = bPreAnalyze;
}

bool EffectSBSMS :: bInit = FALSE;

long resampleCB(void *cb_data, sbsms_resample_frame *data) 
{
  resampleBuf *r = (resampleBuf*) cb_data;
  
  long blockSize = r->leftTrack->GetBestBlockSize(r->offset);
  
  //Adjust the block size if it is the final block in the track
  if (r->offset + blockSize > r->end)
    blockSize = r->end - r->offset;
      
  // Get the samples from the tracks and put them in the buffers.
  r->leftTrack->Get((samplePtr)(r->leftBuffer), floatSample, r->offset, 
blockSize);
  r->rightTrack->Get((samplePtr)(r->rightBuffer), floatSample, r->offset, 
blockSize);
      
  // convert to sbsms audio format
  for(int i=0; i<blockSize; i++) {
    r->buf[i][0] = r->leftBuffer[i];
    r->buf[i][1] = r->rightBuffer[i];
  }

  r->offset += blockSize;
  r->samplesIn += blockSize;
  data->in = r->buf;
  data->size = blockSize;
  data->ratio = r->ratio;

  return blockSize;
}

bool EffectSBSMS::Process()
{
  if(!bInit) {
    sbsms_init(4096);
    bInit = TRUE;
  }

  bool bGoodResult = true;
  
  //Iterate over each track
  this->CopyInputWaveTracks(); // Set up mOutputWaveTracks.
  TrackListIterator iter(mOutputWaveTracks);
  WaveTrack* leftTrack = (WaveTrack*)(iter.First());
  mCurTrackNum = 0;
   
  while (leftTrack != NULL) {
    //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.       
      }

      // 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;
      rb.samplesIn = 0;
      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 = end;
      rb.ratio = srSBSMS/srIn;
      Resampler *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
      real stretch2;
      if(rateStart == rateEnd)
        stretch2 = 1.0/rateStart;
      else
        stretch2 = 1.0/(rateEnd-rateStart)*log(rateEnd/rateStart);
      sampleCount samplesToGenerate = (sampleCount) ((real)samplesToProcess * 
stretch2);
      sampleCount samplesOut = (sampleCount) ((real)samplesIn * stretch2);

      sbsmsInfo si;
      si.rs = resampler;
      si.samplesToProcess = samplesToProcess;
      si.samplesToGenerate = samplesToGenerate;
      si.stretch0 = rateStart;
      si.stretch1 = rateEnd;
      si.ratio0 = pitchStart;
      si.ratio1 = pitchEnd;

      sbsms *sbsmser = 
sbsms_create(&samplesCB,&stretchCB,&ratioCB,rightTrack?2:1,quality,bPreAnalyze,true);
      pitcher *pitch = pitch_create(sbsmser,&si,srIn/srSBSMS);

      WaveTrack* outputLeftTrack = 
mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
                                                          leftTrack->GetRate());
      WaveTrack* outputRightTrack = 
rightTrack?mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
                                                                      
rightTrack->GetRate()):NULL;
   

      sampleCount blockSize = SBSMS_FRAME_SIZE[quality];
      audio *outBuf = (audio*)calloc(blockSize,sizeof(audio));
      float *outputLeftBuffer = (float*)calloc(blockSize*2,sizeof(float));
      float *outputRightBuffer = 
rightTrack?(float*)calloc(blockSize*2,sizeof(float)):NULL;

      long pos = 0;
      long outputCount = -1;

      while(pos<samplesOut && outputCount) {
        long frames;
        if(pos+blockSize>samplesOut) {
          frames = samplesOut - pos;
        } else {
          frames = blockSize;
        }

        outputCount = pitch_process(outBuf, frames, pitch);
        for(int i = 0; i < outputCount; i++) {
          outputLeftBuffer[i] = outBuf[i][0];
          if(rightTrack) outputRightBuffer[i] = outBuf[i][1];
        }
        pos += outputCount;
        outputLeftTrack->Append((samplePtr)outputLeftBuffer, floatSample, 
outputCount);
        if(rightTrack) outputRightTrack->Append((samplePtr)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, frac))
          return false;
      }
      outputLeftTrack->Flush();
      if(rightTrack) outputRightTrack->Flush();

      leftTrack->HandleClear(mCurT0, mCurT1, false, false);
      leftTrack->HandlePaste(mCurT0, outputLeftTrack);
      if(rightTrack) {
        rightTrack->HandleClear(mCurT0, mCurT1, false, false);
        rightTrack->HandlePaste(mCurT0, outputRightTrack);
      }

      delete outputLeftTrack;
      if(rightTrack) delete outputRightTrack;
      free(outputLeftBuffer);
      if(rightTrack) free(outputRightBuffer);
      free(outBuf);
      free(rb.leftBuffer);
      free(rb.rightBuffer);
      free(rb.buf);
      delete resampler;
      sbsms_destroy(sbsmser);
      pitch_destroy(pitch);
    }
  
    //Iterate to the next track
    leftTrack = (WaveTrack*)(iter.Next());
    mCurTrackNum++;
  }
   
  this->ReplaceProcessedWaveTracks(bGoodResult); 
    
  return bGoodResult;
}

#endif

--- NEW FILE: SBSMSEffect.h ---
/**********************************************************************

  Audacity: A Digital Audio Editor

  SBSMSEffect.h

  ClaytonOtey

  This abstract class contains all of the common code for an
  effect that uses SBSMS to do its processing (TimeScale)

**********************************************************************/

#if USE_SBSMS

#ifndef __AUDACITY_EFFECT_SBSMS__
#define __AUDACITY_EFFECT_SBSMS__

#include "Effect.h"

// Soundtouch defines these as well, so get rid of them before including 
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#undef PACKAGE_BUGREPORT

#include "sbsms.h"

class WaveTrack;

class EffectSBSMS : public Effect {
 public:
   static bool bInit;
   virtual bool Process();
   void setParameters(double rateStart, double rateEnd, double pitchStart, 
double pitchEnd, int quality, bool bPreAnalyze);

 private:
   double rateStart, rateEnd, pitchStart, pitchEnd;
   int quality;
   bool bPreAnalyze;
   int mCurTrackNum;
   double mCurT0;
   double mCurT1;   
};

#endif

#endif

--- NEW FILE: TimeScale.cpp ---
/**********************************************************************

  Audacity: A Digital Audio Editor

  TimeScale.cpp

  Clayton Otey

*******************************************************************//**

\class EffectTimeScale
\brief An EffectTimeScale does high quality sliding time scaling/pitch shifting

*//****************************************************************//**

\class TimeScaleDialog
\brief Dialog used with EffectTimeScale

*//*******************************************************************/

#include "../Audacity.h" // for USE_SBSMS

#if USE_SBSMS

#include "TimeScale.h"

#include "../ShuttleGui.h"

#include <math.h>

#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/checkbox.h>
#include <wx/valtext.h>

//
// EffectTimeScale
//

EffectTimeScale::EffectTimeScale()
{
   m_RateStart = 0;
   m_RateEnd = 0;
   m_HalfStepsStart = 0;
   m_HalfStepsEnd = 0;
   m_CentsStart = 0;
   m_CentsEnd = 0;
   m_Quality = 0;
}

wxString EffectTimeScale::GetEffectDescription() { 
   // Note: This is useful only after change amount has been set. 
   return wxString::Format(_("Applied effect: %s"), 
this->GetEffectName().c_str()); 
} 

bool EffectTimeScale::Init()
{
  return true;
}

bool EffectTimeScale::PromptUser()
{
   TimeScaleDialog dlog(this, mParent);
   dlog.m_RateStart = m_RateStart;
   dlog.m_RateEnd = m_RateEnd;
   dlog.m_HalfStepsStart = m_HalfStepsStart;
   dlog.m_HalfStepsEnd = m_HalfStepsEnd;
   dlog.m_CentsStart = m_CentsStart;
   dlog.m_CentsEnd = m_CentsEnd;
   dlog.m_Quality = m_Quality;

   // 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();
   dlog.CentreOnParent();
   dlog.ShowModal();

  if (dlog.GetReturnCode() == wxID_CANCEL)
     return false;
  
   m_RateStart = dlog.m_RateStart;
   m_RateEnd = dlog.m_RateEnd;
   m_HalfStepsStart = dlog.m_HalfStepsStart;
   m_HalfStepsEnd = dlog.m_HalfStepsEnd;
   m_CentsStart = dlog.m_CentsStart;
   m_CentsEnd = dlog.m_CentsEnd;
   m_Quality = dlog.m_Quality;

   return true;
}

bool EffectTimeScale::TransferParameters( Shuttle & shuttle )
{
  shuttle.TransferDouble(wxT("RateStart"),m_RateStart,0.0);
  shuttle.TransferDouble(wxT("RateEnd"),m_RateEnd,0.0);
  shuttle.TransferDouble(wxT("HalfStepsStart"),m_HalfStepsStart,0.0);
  shuttle.TransferDouble(wxT("HalfStepsEnd"),m_HalfStepsEnd,0.0);
  shuttle.TransferDouble(wxT("CentsStart"),m_CentsStart,0.0);
  shuttle.TransferDouble(wxT("CentsEnd"),m_CentsEnd,0.0);
  shuttle.TransferInt(wxT("Quality"),m_Quality,0);
  return true;
}

bool EffectTimeScale::Process()
{
  double pitchStart = pow(2.0,-(m_HalfStepsStart+0.01*m_CentsStart)/12.0);
  double pitchEnd = pow(2.0,-(m_HalfStepsEnd+0.01*m_CentsEnd)/12.0);
  double rateStart = (100.0+m_RateStart)/100.0;
  double rateEnd = (100.0+m_RateEnd)/100.0;
  int quality = m_Quality + 1;
  
this->EffectSBSMS::setParameters(rateStart,rateEnd,pitchStart,pitchEnd,quality,m_PreAnalyze);
  return this->EffectSBSMS::Process();
}

//----------------------------------------------------------------------------
// TimeScaleDialog
//----------------------------------------------------------------------------

#define RATE_MAX 150
#define RATE_DEFAULT 0
#define RATE_MIN -80
#define HALFSTEPS_MIN -12
#define HALFSTEPS_MAX 12
#define CENTS_MIN -50
#define CENTS_MAX 50

#define ID_TEXT_RATE_START 10001
#define ID_TEXT_RATE_END 10002
#define ID_TEXT_HALFSTEPS_START 10003
#define ID_TEXT_HALFSTEPS_END 10004
#define ID_TEXT_CENTS_START 10005
#define ID_TEXT_CENTS_END 10006
#define ID_SLIDER_RATE_START 10007
#define ID_SLIDER_RATE_END 10008
#define ID_SLIDER_QUALITY 10009
#define ID_CHECKBOX_PREANALYZE 10010

// event table for TimeScaleDialog

BEGIN_EVENT_TABLE(TimeScaleDialog, EffectDialog)
   EVT_TEXT(ID_TEXT_RATE_START, TimeScaleDialog::OnText_RateStart)
   EVT_TEXT(ID_TEXT_RATE_END, TimeScaleDialog::OnText_RateEnd)
   EVT_TEXT(ID_TEXT_HALFSTEPS_START, TimeScaleDialog::OnText_HalfStepsStart)
   EVT_TEXT(ID_TEXT_HALFSTEPS_END, TimeScaleDialog::OnText_HalfStepsEnd)
   EVT_TEXT(ID_TEXT_CENTS_START, TimeScaleDialog::OnText_CentsStart)
   EVT_TEXT(ID_TEXT_CENTS_END, TimeScaleDialog::OnText_CentsEnd)
   EVT_SLIDER(ID_SLIDER_RATE_START, TimeScaleDialog::OnSlider_RateStart)
   EVT_SLIDER(ID_SLIDER_RATE_END, TimeScaleDialog::OnSlider_RateEnd)
   EVT_SLIDER(ID_SLIDER_QUALITY, TimeScaleDialog::OnSlider_Quality)
   EVT_CHECKBOX(ID_CHECKBOX_PREANALYZE, TimeScaleDialog::OnCheckBox_PreAnalyze)
END_EVENT_TABLE()

TimeScaleDialog::TimeScaleDialog(EffectTimeScale *effect, wxWindow *parent)
:  EffectDialog(parent, _("Time Scale"), PROCESS_EFFECT),
   mEffect(effect)
{
   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_pTextCtrl_RateStart = NULL;
   m_pTextCtrl_RateEnd = NULL;
   m_pSlider_RateStart = NULL;
   m_pSlider_RateEnd = NULL; 
   m_pTextCtrl_HalfStepsStart = NULL;
   m_pTextCtrl_HalfStepsEnd = NULL;
   m_pTextCtrl_CentsStart = NULL;
   m_pTextCtrl_CentsEnd = NULL;
   m_pSlider_Quality = NULL;
   m_pCheckBox_PreAnalyze = NULL;

   // effect parameters
   m_RateStart = 0;
   m_RateEnd = 0;
   m_HalfStepsStart = 0;
   m_HalfStepsEnd = 0;
   m_CentsStart = 0;
   m_CentsEnd = 0;
   m_Quality = 0;
   m_PreAnalyze = false;

   Init();
}

void TimeScaleDialog::PopulateOrExchange(ShuttleGui & S)
{

   wxTextValidator nullvld(wxFILTER_INCLUDE_CHAR_LIST);
   wxTextValidator numvld(wxFILTER_NUMERIC);

   S.SetBorder(10);
   S.StartHorizontalLay(wxCENTER, false);
   {
      S.AddTitle(_("Sliding Time Scale/Pitch Shift") +
                 wxString(wxT("\n\n")) +
                 _("by Clayton Otey") +
                 wxString(wxT("\n")) + 
                 _("using SBSMS, by Clayton Otey"));
   }
   S.EndHorizontalLay();
   S.SetBorder(5);

   // Rate Text
   S.StartMultiColumn(2, wxCENTER);
   {
      m_pTextCtrl_RateStart = S.Id(ID_TEXT_RATE_START)
         .AddTextBox(_("Start Rate Change (%):"), wxT(""), 12);
      m_pTextCtrl_RateStart->SetValidator(numvld);

      m_pTextCtrl_RateEnd = S.Id(ID_TEXT_RATE_END)
         .AddTextBox(_("End Rate Change (%):"), wxT(""), 12);
      m_pTextCtrl_RateEnd->SetValidator(numvld);
   }
   S.EndMultiColumn();

   // Rate Slider
   S.StartHorizontalLay(wxEXPAND);
   {
      S.SetStyle(wxSL_HORIZONTAL);
      m_pSlider_RateStart = S.Id(ID_SLIDER_RATE_START)
         .AddSlider(wxT(""), (int)RATE_DEFAULT, (int)RATE_MAX, (int)RATE_MIN);
      m_pSlider_RateStart->SetName(_("Start Rate Change (%)"));
   }
   S.EndHorizontalLay();

   S.StartHorizontalLay(wxEXPAND);
   {
      S.SetStyle(wxSL_HORIZONTAL);
      m_pSlider_RateEnd = S.Id(ID_SLIDER_RATE_END)
         .AddSlider(wxT(""), (int)RATE_DEFAULT, (int)RATE_MAX, (int)RATE_MIN);
      m_pSlider_RateEnd->SetName(_("End Rate Change (%)"));
   }
   S.EndHorizontalLay();

   // HalfStep Text
   S.StartMultiColumn(2, wxCENTER);
   {
      m_pTextCtrl_HalfStepsStart = S.Id(ID_TEXT_HALFSTEPS_START)
         .AddTextBox(_("Initial Pitch Shift (half steps) [-12:12]:"), wxT(""), 
12);
      m_pTextCtrl_HalfStepsStart->SetValidator(numvld);

      m_pTextCtrl_HalfStepsEnd = S.Id(ID_TEXT_HALFSTEPS_END)
         .AddTextBox(_("Final Pitch Shift (half steps) [-12:12]:"), wxT(""), 
12);
      m_pTextCtrl_HalfStepsEnd->SetValidator(numvld);
   }
   S.EndMultiColumn();

   // Cents Text
   S.StartMultiColumn(2, wxCENTER);
   {
      m_pTextCtrl_CentsStart = S.Id(ID_TEXT_CENTS_START)
         .AddTextBox(_("Initial Pitch Shift (cents) [-50:50]:"), wxT(""), 12);
      m_pTextCtrl_CentsStart->SetValidator(numvld);

      m_pTextCtrl_CentsEnd = S.Id(ID_TEXT_CENTS_END)
         .AddTextBox(_("Final Pitch Shift (cents) [-50:50]:"), wxT(""), 12);
      m_pTextCtrl_CentsEnd->SetValidator(numvld);
   }
   S.EndMultiColumn();

   S.AddFixedText(_("Quality"),false);
   // Quality Slider
   S.StartHorizontalLay(wxEXPAND);
   {
      S.SetStyle(wxSL_HORIZONTAL);
      m_pSlider_Quality = S.Id(ID_SLIDER_QUALITY)
         .AddSlider(wxT(""), 0, 1, -1);
      m_pSlider_Quality->SetName(_("Quality"));
   }
   m_pCheckBox_PreAnalyze = S.Id(ID_CHECKBOX_PREANALYZE)
     .AddCheckBox(wxT("Dynamic Transient Sharpening"), wxT("Dynamic Transient 
Sharpening"));
   S.EndHorizontalLay();

   return;
}

bool TimeScaleDialog::TransferDataToWindow()
{
   m_bLoopDetect = true;

   this->Update_Text_RateStart();
   this->Update_Slider_RateStart();
   this->Update_Text_RateEnd();
   this->Update_Slider_RateEnd();
   this->Update_Text_HalfStepsStart();
   this->Update_Text_HalfStepsEnd();
   this->Update_Text_CentsStart();
   this->Update_Text_CentsEnd();
   this->Update_Slider_Quality();
   this->Update_CheckBox_PreAnalyze();

   m_bLoopDetect = false;
   
   return true;
}

bool TimeScaleDialog::TransferDataFromWindow()
{
   wxString str;

   if (m_pTextCtrl_RateStart) {
      str = m_pTextCtrl_RateStart->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_RateStart = newValue;
   }

   if (m_pTextCtrl_RateEnd) {
      str = m_pTextCtrl_RateEnd->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_RateEnd = newValue;
   }

   if (m_pTextCtrl_HalfStepsStart) {
      str = m_pTextCtrl_HalfStepsStart->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_HalfStepsStart = newValue;
   }

   if (m_pTextCtrl_HalfStepsEnd) {
      str = m_pTextCtrl_HalfStepsEnd->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_HalfStepsEnd = newValue;
   }

   if (m_pTextCtrl_CentsStart) {
      str = m_pTextCtrl_CentsStart->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_CentsStart = newValue;
   }

   if (m_pTextCtrl_CentsEnd) {
      str = m_pTextCtrl_CentsEnd->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_CentsEnd = newValue;
   }

   if (m_pSlider_Quality) {
     m_Quality = m_pSlider_Quality->GetValue();
   }

   if(m_pCheckBox_PreAnalyze) {
     m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
   }

   return true;
}

// handler implementations for TimeScaleDialog

void TimeScaleDialog::OnText_RateStart(wxCommandEvent & event)
{
   if (m_bLoopDetect)
      return;

   if (m_pTextCtrl_RateStart) {
      wxString str = m_pTextCtrl_RateStart->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_RateStart = newValue;

      m_bLoopDetect = true;
      this->Update_Slider_RateStart();
      m_bLoopDetect = false;

      FindWindow(wxID_OK)->Enable(m_RateStart >= -80.0 && m_RateStart <= 300.0);
   }
}

void TimeScaleDialog::OnText_RateEnd(wxCommandEvent & event)
{
   if (m_bLoopDetect)
      return;

   if (m_pTextCtrl_RateEnd) {
      wxString str = m_pTextCtrl_RateEnd->GetValue();
      double newValue = 0;
      str.ToDouble(&newValue);
      m_RateEnd = newValue;

      m_bLoopDetect = true;
      this->Update_Slider_RateEnd();
      m_bLoopDetect = false;
      
      FindWindow(wxID_OK)->Enable(m_RateEnd >= -80.0 && m_RateEnd <= 300.0);
   }
}

void TimeScaleDialog::OnSlider_RateStart(wxCommandEvent & event)
{
   if (m_bLoopDetect)
      return;

   if (m_pSlider_RateStart) {
      m_RateStart = (double)(m_pSlider_RateStart->GetValue()); 
      
      m_bLoopDetect = true;
      this->Update_Text_RateStart();
      m_bLoopDetect = false;
   }
}

void TimeScaleDialog::OnSlider_RateEnd(wxCommandEvent & event)
{
   if (m_bLoopDetect)
      return;

   if (m_pSlider_RateEnd) {
      m_RateEnd = (double)(m_pSlider_RateEnd->GetValue()); 
      
      m_bLoopDetect = true;
      this->Update_Text_RateEnd();
      m_bLoopDetect = false;
   }
}

void TimeScaleDialog::OnText_HalfStepsStart(wxCommandEvent & event)
{
  if (m_pTextCtrl_HalfStepsStart) {
    wxString str = m_pTextCtrl_HalfStepsStart->GetValue();
    double newValue = 0;
    str.ToDouble(&newValue);
    m_HalfStepsStart = newValue;

    FindWindow(wxID_OK)->Enable(m_HalfStepsStart >= -12 && m_HalfStepsStart 
<=12);
  }
}

void TimeScaleDialog::OnText_HalfStepsEnd(wxCommandEvent & event)
{
  if (m_pTextCtrl_HalfStepsEnd) {
    wxString str = m_pTextCtrl_HalfStepsEnd->GetValue();
    double newValue = 0;
    str.ToDouble(&newValue);
    m_HalfStepsEnd = newValue;

    FindWindow(wxID_OK)->Enable(m_HalfStepsEnd >= -12 && m_HalfStepsEnd <=12);
  }
}

void TimeScaleDialog::OnText_CentsStart(wxCommandEvent & event)
{
  if (m_pTextCtrl_CentsStart) {
    wxString str = m_pTextCtrl_CentsStart->GetValue();
    double newValue = 0;
    str.ToDouble(&newValue);
    m_CentsStart = newValue;

    FindWindow(wxID_OK)->Enable(m_CentsStart >= -50 && m_CentsStart <=50);
  }
}

void TimeScaleDialog::OnText_CentsEnd(wxCommandEvent & event)
{
  if (m_pTextCtrl_CentsEnd) {
    wxString str = m_pTextCtrl_CentsEnd->GetValue();
    double newValue = 0;
    str.ToDouble(&newValue);
    m_CentsEnd = newValue;

    FindWindow(wxID_OK)->Enable(m_CentsEnd >= -50 && m_CentsEnd <=50);
  }
}

void TimeScaleDialog::OnSlider_Quality(wxCommandEvent & event)
{
  if (m_pSlider_Quality) {
    m_Quality = (m_pSlider_Quality->GetValue()); 
  }
}

void TimeScaleDialog::OnCheckBox_PreAnalyze(wxCommandEvent & event)
{
  if (m_pCheckBox_PreAnalyze) {
    m_PreAnalyze = m_pCheckBox_PreAnalyze->GetValue();
  }
}

void TimeScaleDialog::Update_Text_RateStart()
{
   if (m_pTextCtrl_RateStart) {
      wxString str;
      str.Printf(wxT("%.3f"), m_RateStart);
      m_pTextCtrl_RateStart->SetValue(str);
   }
}

void TimeScaleDialog::Update_Text_RateEnd()
{
   if (m_pTextCtrl_RateEnd) {
      wxString str;
      str.Printf(wxT("%.3f"), m_RateEnd);
      m_pTextCtrl_RateEnd->SetValue(str);
   }
}

void TimeScaleDialog::Update_Slider_RateStart()
{
   if (m_pSlider_RateStart) {
      m_pSlider_RateStart->SetValue((int)(m_RateStart + 0.5)); 
   }
}

void TimeScaleDialog::Update_Slider_RateEnd()
{
   if (m_pSlider_RateEnd) {
      m_pSlider_RateEnd->SetValue((int)(m_RateEnd + 0.5)); 
   }
}

void TimeScaleDialog::Update_Text_HalfStepsStart()
{
   if (m_pTextCtrl_HalfStepsStart) {
      wxString str;
      str.Printf(wxT("%.3f"), m_HalfStepsStart);
      m_pTextCtrl_HalfStepsStart->SetValue(str);
   }
}

void TimeScaleDialog::Update_Text_HalfStepsEnd()
{
   if (m_pTextCtrl_HalfStepsEnd) {
      wxString str;
      str.Printf(wxT("%.3f"), m_HalfStepsEnd);
      m_pTextCtrl_HalfStepsEnd->SetValue(str);
   }
}

void TimeScaleDialog::Update_Text_CentsStart()
{
   if (m_pTextCtrl_CentsStart) {
      wxString str;
      str.Printf(wxT("%.3f"), m_CentsStart);
      m_pTextCtrl_CentsStart->SetValue(str);
   }
}

void TimeScaleDialog::Update_Text_CentsEnd()
{
   if (m_pTextCtrl_CentsEnd) {
      wxString str;
      str.Printf(wxT("%.3f"), m_CentsEnd);
      m_pTextCtrl_CentsEnd->SetValue(str);
   }
}

void TimeScaleDialog::Update_Slider_Quality()
{
  if (m_pSlider_Quality) {
      m_pSlider_Quality->SetValue(m_Quality);
  }
}

void TimeScaleDialog::Update_CheckBox_PreAnalyze()
{
  if (m_pCheckBox_PreAnalyze) {
    m_pCheckBox_PreAnalyze->SetValue(m_PreAnalyze);
  }
}

#endif


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to