winamp/Src/external_dependencies/openmpt-trunk/mptrack/PSRatioCalc.cpp

184 lines
4.3 KiB
C++

/*
* PSRatioCalc.cpp
* ---------------
* Purpose: Dialog for calculating sample pitch shift ratios in the sample editor.
* Notes : (currently none)
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
#include "stdafx.h"
#include "Mptrack.h"
#include "Mainfrm.h"
#include "PSRatioCalc.h"
OPENMPT_NAMESPACE_BEGIN
// CPSRatioCalc dialog
IMPLEMENT_DYNAMIC(CPSRatioCalc, CDialog)
CPSRatioCalc::CPSRatioCalc(const CSoundFile &sndFile, SAMPLEINDEX sample, double ratio, CWnd* pParent /*=NULL*/)
: CDialog(IDD_PITCHSHIFT, pParent)
, m_dRatio(ratio)
, sndFile(sndFile)
, sampleIndex(sample)
{
// Calculate/verify samplerate at C5.
const ModSample &smp = sndFile.GetSample(sampleIndex);
uint32 sampleRate = smp.GetSampleRate(sndFile.GetType());
if(sampleRate <= 0)
sampleRate = 8363;
m_nSpeed = sndFile.m_PlayState.m_nMusicSpeed;
m_nTempo = sndFile.m_PlayState.m_nMusicTempo;
// Sample rate will not change. We can calculate original duration once and disgard sampleRate.
m_lMsOrig = static_cast<ULONGLONG>(1000.0 * ((double)smp.nLength / sampleRate));
CalcSamples();
CalcMs();
CalcRows();
}
void CPSRatioCalc::DoDataExchange(CDataExchange* pDX)
{
CWnd* hasFocus = GetFocus();
CDialog::DoDataExchange(pDX);
SmpLength origLength = sndFile.GetSample(sampleIndex).nLength;
DDX_Text(pDX, IDC_SAMPLE_LENGTH_ORIGINAL, origLength);
DDX_Text(pDX, IDC_SAMPLE_LENGTH_NEW, m_lSamplesNew);
DDX_Text(pDX, IDC_MS_LENGTH_ORIGINAL2, m_lMsOrig);
DDX_Text(pDX, IDC_MS_LENGTH_NEW, m_lMsNew);
DDX_Text(pDX, IDC_SPEED, m_nSpeed);
DDX_Text(pDX, IDC_ROW_LENGTH_ORIGINAL, m_dRowsOrig);
//These 2 CEdits must only be updated if they don't have focus (to preserve trailing . and 0s etc..)
if (pDX->m_bSaveAndValidate || hasFocus != GetDlgItem(IDC_ROW_LENGTH_NEW2))
DDX_Text(pDX, IDC_ROW_LENGTH_NEW2, m_dRowsNew);
if (pDX->m_bSaveAndValidate || hasFocus != GetDlgItem(IDC_PSRATIO))
DDX_Text(pDX, IDC_PSRATIO, m_dRatio);
}
BEGIN_MESSAGE_MAP(CPSRatioCalc, CDialog)
ON_EN_UPDATE(IDC_SAMPLE_LENGTH_NEW, &CPSRatioCalc::OnEnChangeSamples)
ON_EN_UPDATE(IDC_MS_LENGTH_NEW, &CPSRatioCalc::OnEnChangeMs)
ON_EN_UPDATE(IDC_SPEED, &CPSRatioCalc::OnEnChangeSpeed)
ON_EN_UPDATE(IDC_TEMPO, &CPSRatioCalc::OnEnChangeSpeed)
ON_EN_UPDATE(IDC_ROW_LENGTH_NEW2, &CPSRatioCalc::OnEnChangeRows)
ON_EN_UPDATE(IDC_PSRATIO, &CPSRatioCalc::OnEnChangeratio)
ON_BN_CLICKED(IDOK, &CPSRatioCalc::OnBnClickedOk)
END_MESSAGE_MAP()
BOOL CPSRatioCalc::OnInitDialog()
{
CDialog::OnInitDialog();
m_EditTempo.SubclassDlgItem(IDC_TEMPO, this);
m_EditTempo.AllowNegative(false);
m_EditTempo.SetTempoValue(m_nTempo);
return TRUE;
}
// CPSRatioCalc message handlers
void CPSRatioCalc::OnEnChangeSamples()
{
UpdateData();
if (m_lSamplesNew && sndFile.GetSample(sampleIndex).nLength)
{
m_dRatio = (double)m_lSamplesNew / (double)sndFile.GetSample(sampleIndex).nLength * 100;
CalcMs();
CalcRows();
UpdateData(FALSE);
}
}
void CPSRatioCalc::OnEnChangeMs()
{
UpdateData();
if (m_lMsOrig && m_lMsNew)
{
m_dRatio = (double)m_lMsNew / (double)m_lMsOrig * 100;
CalcSamples();
CalcRows();
UpdateData(FALSE);
}
}
void CPSRatioCalc::OnEnChangeRows()
{
UpdateData();
if (m_dRowsOrig && m_dRowsNew)
{
m_dRatio = m_dRowsNew / m_dRowsOrig * 100.0;
CalcSamples();
CalcMs();
UpdateData(FALSE);
}
}
void CPSRatioCalc::OnEnChangeSpeed()
{
UpdateData();
m_nTempo = m_EditTempo.GetTempoValue();
if (m_nTempo < TEMPO(1, 0)) m_nTempo = TEMPO(1, 0);
if (m_nSpeed < 1) m_nSpeed = 1;
CalcRows();
UpdateData(FALSE);
}
void CPSRatioCalc::OnEnChangeratio()
{
UpdateData();
if (m_dRatio)
{
CalcSamples();
CalcMs();
CalcRows();
UpdateData(FALSE);
}
}
// CPSRatioCalc Internal Calculations:
void CPSRatioCalc::CalcSamples()
{
m_lSamplesNew = static_cast<ULONGLONG>(sndFile.GetSample(sampleIndex).nLength * (m_dRatio / 100.0));
return;
}
void CPSRatioCalc::CalcMs()
{
m_lMsNew = static_cast<ULONGLONG>(m_lMsOrig * (m_dRatio / 100.0));
return;
}
void CPSRatioCalc::CalcRows()
{
double rowTime = sndFile.GetRowDuration(m_nTempo, m_nSpeed);
m_dRowsOrig = (double)m_lMsOrig / rowTime;
m_dRowsNew = m_dRowsOrig * (m_dRatio / 100);
return;
}
void CPSRatioCalc::OnBnClickedOk()
{
if (m_dRatio<50.0 || m_dRatio>200.0)
{
Reporting::Error("Error: ratio must be between 50% and 200%.");
return;
}
OnOK();
}
OPENMPT_NAMESPACE_END