From: <rel...@us...> - 2009-06-14 21:49:09
|
Revision: 269 http://modplug.svn.sourceforge.net/modplug/?rev=269&view=rev Author: relabsoluness Date: 2009-06-14 21:48:05 +0000 (Sun, 14 Jun 2009) Log Message: ----------- (Patch from coda, merged somewhat modified with related refactoring) + Sample tab: Sample drawing. + Sample tab: Add silence to sample. Modified Paths: -------------- trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/View_smp.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/smptoolb.bmp trunk/OpenMPT/mptrack/resource.h Added Paths: ----------- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp trunk/OpenMPT/soundlib/modsmp_ctrl.h Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-14 21:48:05 UTC (rev 269) @@ -7,6 +7,7 @@ #include "moddoc.h" #include "dlg_misc.h" #include "dlsbank.h" +#include "modsmp_ctrl.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" @@ -995,84 +996,13 @@ BOOL CModDoc::AdjustEndOfSample(UINT nSample) //------------------------------------------- { - const MODINSTRUMENT *pins; + MODINSTRUMENT *pins; if (nSample >= MAX_SAMPLES) return FALSE; pins = &m_SndFile.Ins[nSample]; if ((!pins->nLength) || (!pins->pSample)) return FALSE; - BEGIN_CRITICAL(); - UINT len = pins->nLength; - if (pins->uFlags & CHN_16BIT) - { - signed short *p = (signed short *)pins->pSample; - if (pins->uFlags & CHN_STEREO) - { - p[(len+3)*2] = p[(len+2)*2] = p[(len+1)*2] = p[(len)*2] = p[(len-1)*2]; - p[(len+3)*2+1] = p[(len+2)*2+1] = p[(len+1)*2+1] = p[(len)*2+1] = p[(len-1)*2+1]; - } else - { - p[len+4] = p[len+3] = p[len+2] = p[len+1] = p[len] = p[len-1]; - } - if (((pins->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - && (pins->nLoopEnd == pins->nLength) - && (pins->nLoopEnd > pins->nLoopStart) && (pins->nLength > 2)) - { - p[len] = p[pins->nLoopStart]; - p[len+1] = p[pins->nLoopStart+1]; - p[len+2] = p[pins->nLoopStart+2]; - p[len+3] = p[pins->nLoopStart+3]; - p[len+4] = p[pins->nLoopStart+4]; - } - } else - { - signed char *p = (signed char *)pins->pSample; - if (pins->uFlags & CHN_STEREO) - { - p[(len+3)*2] = p[(len+2)*2] = p[(len+1)*2] = p[(len)*2] = p[(len-1)*2]; - p[(len+3)*2+1] = p[(len+2)*2+1] = p[(len+1)*2+1] = p[(len)*2+1] = p[(len-1)*2+1]; - } else - { - p[len+4] = p[len+3] = p[len+2] = p[len+1] = p[len] = p[len-1]; - } - if (((pins->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) - && (pins->nLoopEnd == pins->nLength) - && (pins->nLoopEnd > pins->nLoopStart) && (pins->nLength > 2)) - { - p[len] = p[pins->nLoopStart]; - p[len+1] = p[pins->nLoopStart+1]; - p[len+2] = p[pins->nLoopStart+2]; - p[len+3] = p[pins->nLoopStart+3]; - p[len+4] = p[pins->nLoopStart+4]; - } - } - // Update channels with new loop values - { - for (UINT i=0; i<MAX_CHANNELS; i++) if ((m_SndFile.Chn[i].pInstrument == pins) && (m_SndFile.Chn[i].nLength)) - { - if ((pins->nLoopStart + 3 < pins->nLoopEnd) && (pins->nLoopEnd <= pins->nLength)) - { - m_SndFile.Chn[i].nLoopStart = pins->nLoopStart; - m_SndFile.Chn[i].nLoopEnd = pins->nLoopEnd; - m_SndFile.Chn[i].nLength = pins->nLoopEnd; - if (m_SndFile.Chn[i].nPos > m_SndFile.Chn[i].nLength) - { - m_SndFile.Chn[i].nPos = m_SndFile.Chn[i].nLoopStart; - m_SndFile.Chn[i].dwFlags &= ~CHN_PINGPONGFLAG; - } - DWORD d = m_SndFile.Chn[i].dwFlags & ~(CHN_PINGPONGLOOP|CHN_LOOP); - if (pins->uFlags & CHN_LOOP) - { - d |= CHN_LOOP; - if (pins->uFlags & CHN_PINGPONGLOOP) d |= CHN_PINGPONGLOOP; - } - m_SndFile.Chn[i].dwFlags = d; - } else - if (!(pins->uFlags & CHN_LOOP)) - { - m_SndFile.Chn[i].dwFlags &= ~(CHN_PINGPONGLOOP|CHN_LOOP); - } - } - } - END_CRITICAL(); + + ctrlSmp::AdjustEndOfSample(*pins, &m_SndFile); + return TRUE; } Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-14 21:48:05 UTC (rev 269) @@ -19,7 +19,7 @@ #include <shlwapi.h> // rewbs.memLeak -#define CRTDBG_MAP_ALLOC +#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include ".\mptrack.h" @@ -1686,6 +1686,8 @@ "http://www.hermannseib.com/english/vsthost.htm|" "Ian Luck for UNMO3|" "http://www.un4seen.com/mo3.html|" + "coda for sample drawing code|" + "http://coda.s3m.us/|" "Pel K. Txnder for the scrolling credits control :)|" "http://tinyurl.com/4yze8|" "The people at Modplug forums for crucial contribution|" Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2009-06-14 21:48:05 UTC (rev 269) @@ -9,7 +9,13 @@ #include "channelManagerDlg.h" #include "view_smp.h" #include "midi.h" +#include "dlg_misc.h" +#include "modsmp_ctrl.h" +#define new DEBUG_NEW + + + // Non-client toolbar #define SMP_LEFTBAR_CY 29 #define SMP_LEFTBAR_CXSEP 14 @@ -31,6 +37,8 @@ ID_SAMPLE_ZOOMUP, ID_SAMPLE_ZOOMDOWN, ID_SEPARATOR, + ID_SAMPLE_DRAW, + ID_SAMPLE_ADDSILENCE, }; @@ -75,6 +83,8 @@ ON_COMMAND(ID_SAMPLE_SETSUSTAINEND, OnSetSustainEnd) ON_COMMAND(ID_SAMPLE_ZOOMUP, OnZoomUp) ON_COMMAND(ID_SAMPLE_ZOOMDOWN, OnZoomDown) + ON_COMMAND(ID_SAMPLE_DRAW, OnDrawingToggle) + ON_COMMAND(ID_SAMPLE_ADDSILENCE, OnAddSilence) ON_MESSAGE(WM_MOD_MIDIMSG, OnMidiMsg) ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) //rewbs.customKeys //}}AFX_MSG_MAP @@ -103,6 +113,7 @@ //--------------------------------- { m_dwBeginSel = m_dwEndSel = 0; + m_bDrawingEnabled = false; // sample drawing ModifyStyleEx(0, WS_EX_ACCEPTFILES); CModScrollView::OnInitialUpdate(); CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); @@ -179,6 +190,7 @@ pModDoc->SetFollowWnd(m_hWnd, MPTNOTIFY_SAMPLE|nSmp); if (nSmp == m_nSample) return FALSE; m_dwBeginSel = m_dwEndSel = 0; + m_bDrawingEnabled = false; // sample drawing CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); if (pMainFrm) pMainFrm->SetInfoText(""); m_nSample = nSmp; @@ -394,6 +406,13 @@ UpdateNcButtonState(); InvalidateSample(); } + + // sample drawing + if(dwHintMask & HINT_SAMPLEINFO) + { + m_bDrawingEnabled = false; + UpdateNcButtonState(); + } } #define YCVT(n, bits) (ymed - (((n) * yrange) >> (bits))) @@ -987,6 +1006,8 @@ { case ID_SAMPLE_ZOOMUP: nImage = 1; break; case ID_SAMPLE_ZOOMDOWN: nImage = 2; break; + case ID_SAMPLE_DRAW: nImage = (dwStyle & NCBTNS_DISABLED) ? 18 : 16; break; + case ID_SAMPLE_ADDSILENCE: nImage = 17; break; } pDC->Draw3dRect(rect.left-1, rect.top-1, SMP_LEFTBAR_CXBTN+2, SMP_LEFTBAR_CYBTN+2, c3, c4); pDC->Draw3dRect(rect.left, rect.top, SMP_LEFTBAR_CXBTN, SMP_LEFTBAR_CYBTN, c1, c2); @@ -1061,6 +1082,15 @@ dwStyle |= NCBTNS_MOUSEOVER; if (m_dwStatus & SMPSTATUS_NCLBTNDOWN) dwStyle |= NCBTNS_PUSHED; } + + switch(cLeftBarButtons[i]) + { + case ID_SAMPLE_DRAW: + if(m_bDrawingEnabled) dwStyle |= NCBTNS_CHECKED; + if(pSndFile->Ins[m_nSample].GetNumChannels() > 1) dwStyle |= NCBTNS_DISABLED; + break; + } + if (dwStyle != m_NcButtonState[i]) { m_NcButtonState[i] = dwStyle; @@ -1163,6 +1193,41 @@ } +template<class T, class uT> +T CViewSample::GetSampleValueFromPoint(const CPoint& point) +//------------------------------------------------------------ +{ + STATIC_ASSERT(sizeof(T) == sizeof(uT) && sizeof(T) <= 2); + int value = (std::numeric_limits<T>::max)() - (std::numeric_limits<uT>::max)() * point.y / (m_rcClient.bottom - m_rcClient.top); + Limit(value, (std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)()); + return static_cast<T>(value); +} + + +template<class T, class uT> +void CViewSample::SetInitialDrawPoint(void* pSample, const CPoint& point) +//----------------------------------------------------------------------- +{ + T* data = reinterpret_cast<T*>(pSample); + data[m_dwEndDrag] = GetSampleValueFromPoint<T, uT>(point); +} + + +template<class T, class uT> +void CViewSample::SetSampleData(void* pSample, const CPoint& point, const DWORD old ) +//----------------------------------------------------------------------------------- +{ + T* data = reinterpret_cast<T*>(pSample); + const int oldvalue = data[old]; + const int value = GetSampleValueFromPoint<T, uT>(point); + for(DWORD i=old; i != m_dwEndDrag; i += (m_dwEndDrag > old ? 1 : -1)) + { + data[i] = static_cast<T>((float)oldvalue + (value - oldvalue) * ((float)i - old) / ((float)m_dwEndDrag - old)); + } + data[m_dwEndDrag] = static_cast<T>(value); +} + + void CViewSample::OnMouseMove(UINT, CPoint point) //----------------------------------------------- { @@ -1212,7 +1277,7 @@ if (m_dwStatus & SMPSTATUS_MOUSEDRAG) { BOOL bAgain = FALSE; - DWORD len = pSndFile->Ins[m_nSample].nLength; + const DWORD len = pSndFile->Ins[m_nSample].nLength; if (!len) return; DWORD old = m_dwEndDrag; if (m_nZoom) @@ -1242,12 +1307,24 @@ point.x = m_rcClient.right; } } - LONG l = ScreenToSample(point.x); - if (l < 0) l = 0; - m_dwEndDrag = l; - if (m_dwEndDrag > len) m_dwEndDrag = len; - if (old != m_dwEndDrag) + m_dwEndDrag = ScreenToSample(point.x); + if(m_bDrawingEnabled) { + if(m_dwEndDrag < len) + { + if(pSndFile->Ins[m_nSample].GetElementarySampleSize() == 2) + SetSampleData<int16, uint16>(pSndFile->Ins[m_nSample].pSample, point, old); + else if(pSndFile->Ins[m_nSample].GetElementarySampleSize() == 1) + SetSampleData<int8, uint8>(pSndFile->Ins[m_nSample].pSample, point, old); + + ctrlSmp::AdjustEndOfSample(pSndFile->Ins[m_nSample], pSndFile); + + InvalidateSample(); + pModDoc->SetModified(); + } + } + else if (old != m_dwEndDrag) + { SetCurSel(m_dwBeginDrag, m_dwEndDrag); UpdateWindow(); } @@ -1275,6 +1352,17 @@ if (m_dwBeginDrag >= len) m_dwBeginDrag = len-1; m_dwEndDrag = m_dwBeginDrag; if (oldsel) SetCurSel(m_dwBeginDrag, m_dwEndDrag); + // set initial point for sample drawing + if (m_bDrawingEnabled) + { + if(pSndFile->Ins[m_nSample].GetElementarySampleSize() == 2) + SetInitialDrawPoint<int16, uint16>(pSndFile->Ins[m_nSample].pSample, point); + else if(pSndFile->Ins[m_nSample].GetElementarySampleSize() == 1) + SetInitialDrawPoint<int8, uint8>(pSndFile->Ins[m_nSample].pSample, point); + + InvalidateSample(); + pModDoc->SetModified(); + } } } @@ -1299,7 +1387,7 @@ { CSoundFile *pSndFile = pModDoc->GetSoundFile(); DWORD len = pSndFile->Ins[m_nSample].nLength; - if (len) SetCurSel(0, len); + if (len && !m_bDrawingEnabled) SetCurSel(0, len); } } @@ -2279,6 +2367,43 @@ } +void CViewSample::OnDrawingToggle() +//--------------------------------- +{ + m_bDrawingEnabled = !m_bDrawingEnabled; + UpdateNcButtonState(); +} + + +void CViewSample::OnAddSilence() +//------------------------------ +{ + CAddSilenceDlg dlg(this); + if (dlg.DoModal() != IDOK) return; + + CModDoc *pModDoc = GetDocument(); + if (!pModDoc) return; + CSoundFile *pSndFile = pModDoc->GetSoundFile(); + if (!pSndFile) return; + + const ctrlSmp::SmpLength nOldLength = pSndFile->Ins[m_nSample].nLength; + + if( MAX_SAMPLE_LENGTH - nOldLength < dlg.m_nSamples ) + { + CString str; str.Format(TEXT("Can't add silence because the new sample length would exceed maximum sample length %u."), MAX_SAMPLE_LENGTH); + AfxMessageBox(str, MB_ICONINFORMATION); + return; + } + + ctrlSmp::InsertSilence(pSndFile->Ins[m_nSample], dlg.m_nSamples, (dlg.m_bAddAtEnd) ? pSndFile->Ins[m_nSample].nLength : 0, pSndFile); + + if(nOldLength != pSndFile->Ins[m_nSample].nLength) + { + pModDoc->SetModified(); + pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); + } +} + LRESULT CViewSample::OnMidiMsg(WPARAM dwMidiDataParam, LPARAM) //------------------------------------------------------- { Modified: trunk/OpenMPT/mptrack/View_smp.h =================================================================== --- trunk/OpenMPT/mptrack/View_smp.h 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/View_smp.h 2009-06-14 21:48:05 UTC (rev 269) @@ -5,7 +5,7 @@ #define SMPSTATUS_KEYDOWN 0x02 #define SMPSTATUS_NCLBTNDOWN 0x04 -#define SMP_LEFTBAR_BUTTONS 3 +#define SMP_LEFTBAR_BUTTONS 5 //====================================== class CViewSample: public CModScrollView @@ -20,6 +20,7 @@ DWORD m_dwMenuParam; DWORD m_NcButtonState[SMP_LEFTBAR_BUTTONS]; DWORD m_dwNotifyPos[MAX_CHANNELS]; + bool m_bDrawingEnabled; public: CViewSample(); @@ -42,6 +43,18 @@ BOOL GetNcButtonRect(UINT nBtn, LPRECT lpRect); void UpdateNcButtonState(); + // Sets sample data on sample draw. + template<class T, class uT> + void SetSampleData(void* pSample, const CPoint& point, const DWORD old); + + // Sets initial draw point on sample draw. + template<class T, class uT> + void SetInitialDrawPoint(void* pSample, const CPoint& point); + + // Returns sample value corresponding given point in the sample view. + template<class T, class uT> + T GetSampleValueFromPoint(const CPoint& point); + public: //{{AFX_VIRTUAL(CViewSample) virtual void OnDraw(CDC *); @@ -98,6 +111,8 @@ afx_msg void OnSetSustainEnd(); afx_msg void OnZoomUp(); afx_msg void OnZoomDown(); + afx_msg void OnDrawingToggle(); + afx_msg void OnAddSilence(); afx_msg LRESULT OnMidiMsg(WPARAM, LPARAM); afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); //rewbs.customKeys //}}AFX_MSG Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-06-14 21:48:05 UTC (rev 269) @@ -1543,6 +1543,33 @@ } +// Add silence to a sample +BOOL CAddSilenceDlg::OnInitDialog() +//--------------------------------- +{ + CDialog::OnInitDialog(); + CSpinButtonCtrl *spin = (CSpinButtonCtrl *)GetDlgItem(IDC_SPIN1); + if (spin) + { + spin->SetRange(0, int16_max); + spin->SetPos(m_nSamples); + } + CButton *radio2 = (CButton *)GetDlgItem(IDC_RADIO2); + radio2->SetCheck(m_bAddAtEnd); + SetDlgItemInt(IDC_EDIT1, m_nSamples); + return TRUE; +} + + +void CAddSilenceDlg::OnOK() +//------------------------- +{ + m_nSamples = GetDlgItemInt(IDC_EDIT1); + m_bAddAtEnd = (IsDlgButtonChecked(IDC_RADIO2) != 0); + CDialog::OnOK(); +} + + //////////////////////////////////////////////////////////////////////////////// // Sound Bank Information Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2009-06-14 21:48:05 UTC (rev 269) @@ -325,7 +325,22 @@ virtual void OnOK(); }; +//=========================== +class CAddSilenceDlg: public CDialog +//=========================== +{ +public: + UINT m_nSamples; + bool m_bAddAtEnd; +public: + CAddSilenceDlg(CWnd *parent, UINT nSamples=32):CDialog(IDD_ADDSILENCE, parent) { m_nSamples = nSamples; m_bAddAtEnd = true; } + virtual BOOL OnInitDialog(); + virtual void OnOK(); +}; + + + //////////////////////////////////////////////////////////////////////// // Sound Banks Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-06-14 21:48:05 UTC (rev 269) @@ -1929,6 +1929,26 @@ LTEXT "around current",IDC_STATIC,156,84,49,8 END +IDD_ADDSILENCE DIALOGEX 0, 0, 175, 63 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Insert Silence" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,118,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,118,25,50,14 + GROUPBOX "",IDC_STATIC,7,3,106,55 + EDITTEXT IDC_EDIT1,25,14,40,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | + UDS_NOTHOUSANDS,57,15,11,14 + LTEXT "samples",IDC_STATIC,74,17,26,8 + CONTROL "At beginning of sample",IDC_RADIO1,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,32,89,10 + CONTROL "At end of sample",IDC_RADIO2,"Button", + BS_AUTORADIOBUTTON | WS_TABSTOP,11,46,70,10 +END + IDD_PATTERNRANDOMIZER_EFFECT DIALOGEX 0, 0, 235, 172 STYLE DS_SETFONT | DS_3DLOOK | DS_CONTROL | WS_CHILD FONT 8, "MS Sans Serif", 0, 0, 0x0 @@ -2212,6 +2232,15 @@ RIGHTMARGIN, 229 BOTTOMMARGIN, 169 END + + IDD_ADDSILENCE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 168 + TOPMARGIN, 7 + BOTTOMMARGIN, 56 + END + END #endif // APSTUDIO_INVOKED Modified: trunk/OpenMPT/mptrack/res/smptoolb.bmp =================================================================== (Binary files differ) Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-06-12 17:32:08 UTC (rev 268) +++ trunk/OpenMPT/mptrack/resource.h 2009-06-14 21:48:05 UTC (rev 269) @@ -105,6 +105,7 @@ #define IDS_ERR_TUNING_SERIALISATION 514 #define IDD_MIDIPARAMCONTROL 515 #define IDD_MSGBOX_HIDABLE 516 +#define IDD_ADDSILENCE 517 #define IDC_BUTTON1 1001 #define IDC_BUTTON2 1002 #define IDC_BUTTON3 1003 @@ -1056,13 +1057,15 @@ #define ID_PATTERN_DUPLICATECHANNEL 59216 #define ID_EDIT_GOTO_MENU 59220 +#define ID_SAMPLE_DRAW 59224 +#define ID_SAMPLE_ADDSILENCE 59225 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 517 -#define _APS_NEXT_COMMAND_VALUE 59221 +#define _APS_NEXT_RESOURCE_VALUE 518 +#define _APS_NEXT_COMMAND_VALUE 59226 #define _APS_NEXT_CONTROL_VALUE 2343 #define _APS_NEXT_SYMED_VALUE 901 #endif Added: trunk/OpenMPT/soundlib/modsmp_ctrl.cpp =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp (rev 0) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-06-14 21:48:05 UTC (rev 269) @@ -0,0 +1,152 @@ +/* + * MODINSTRUMENT related functions. + */ + +#include "stdafx.h" +#include "modsmp_ctrl.h" +#include "mptrack/MainFrm.h" + +#define new DEBUG_NEW + +namespace ctrlSmp +{ + +void ReplaceSample(MODINSTRUMENT& smp, const LPSTR pNewSample, const SmpLength nNewLength) +//---------------------------------------------------------------------------------------- +{ + LPSTR const pOldSmp = smp.pSample; + BEGIN_CRITICAL(); + smp.pSample = pNewSample; + smp.nLength = nNewLength; + END_CRITICAL(); + CSoundFile::FreeSample(pOldSmp); +} + + +SmpLength InsertSilence(MODINSTRUMENT& smp, const SmpLength nSilenceLength, const SmpLength nStartFrom, CSoundFile* pSndFile) +//---------------------------------------------------------------------------------------------------------------------------- +{ + if(nSilenceLength == 0 || nSilenceLength >= MAX_SAMPLE_LENGTH || smp.nLength > MAX_SAMPLE_LENGTH - nSilenceLength) + return smp.nLength; + + const SmpLength nOldBytes = smp.GetSampleSizeInBytes(); + const SmpLength nSilenceBytes = nSilenceLength * smp.GetElementarySampleSize() * smp.GetNumChannels(); + const SmpLength nNewSmpBytes = nOldBytes + nSilenceBytes; + const SmpLength nNewLength = smp.nLength + nSilenceLength; + + LPSTR pNewSmp = 0; + if( GetSampleCapacity(smp) >= nNewSmpBytes ) // If sample has room to expand. + { + AfxMessageBox("Not implemented: GetSampleCapacity(smp) >= nNewSmpBytes"); + // Not implemented, GetSampleCapacity() currently always returns length based value + // even if there is unused space in the sample. + } + else // Have to allocate new sample. + { + pNewSmp = CSoundFile::AllocateSample(nNewSmpBytes); + if(pNewSmp == 0) + return smp.nLength; //Sample allocation failed. + if(nStartFrom == 0) + { + memset(pNewSmp, 0, nSilenceBytes); + memcpy(pNewSmp + nSilenceBytes, smp.pSample, nOldBytes); + } + else if(nStartFrom == smp.nLength) + { + memcpy(pNewSmp, smp.pSample, nOldBytes); + memset(pNewSmp + nOldBytes, 0, nSilenceBytes); + } + else + AfxMessageBox(TEXT("Unsupported start position in InsertSilence.")); + } + + ReplaceSample(smp, pNewSmp, nNewLength); + AdjustEndOfSample(smp, pSndFile); + + return smp.nLength; +} + +namespace // Unnamed namespace for local implementation functions. +{ + +template <class T> +void AdjustEndOfSampleImpl(MODINSTRUMENT& smp) +//-------------------------------------------- +{ + MODINSTRUMENT* const pins = &smp; + const UINT len = pins->nLength; + T* p = reinterpret_cast<T*>(pins->pSample); + if (pins->uFlags & CHN_STEREO) + { + p[(len+3)*2] = p[(len+2)*2] = p[(len+1)*2] = p[(len)*2] = p[(len-1)*2]; + p[(len+3)*2+1] = p[(len+2)*2+1] = p[(len+1)*2+1] = p[(len)*2+1] = p[(len-1)*2+1]; + } else + { + p[len+4] = p[len+3] = p[len+2] = p[len+1] = p[len] = p[len-1]; + } + if (((pins->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) + && (pins->nLoopEnd == pins->nLength) + && (pins->nLoopEnd > pins->nLoopStart) && (pins->nLength > 2)) + { + p[len] = p[pins->nLoopStart]; + p[len+1] = p[pins->nLoopStart+1]; + p[len+2] = p[pins->nLoopStart+2]; + p[len+3] = p[pins->nLoopStart+3]; + p[len+4] = p[pins->nLoopStart+4]; + } +} + +} // unnamed namespace. + + +bool AdjustEndOfSample(MODINSTRUMENT& smp, CSoundFile* pSndFile) +//-------------------------------------------------------------- +{ + MODINSTRUMENT* const pins = &smp; + + if ((!pins->nLength) || (!pins->pSample)) + return false; + + BEGIN_CRITICAL(); + + if (pins->GetElementarySampleSize() == 2) + AdjustEndOfSampleImpl<int16>(*pins); + else if(pins->GetElementarySampleSize() == 1) + AdjustEndOfSampleImpl<int8>(*pins); + + // Update channels with new loop values + if(pSndFile != 0) + { + CSoundFile& rSndFile = *pSndFile; + for (UINT i=0; i<MAX_CHANNELS; i++) if ((rSndFile.Chn[i].pInstrument == pins) && (rSndFile.Chn[i].nLength)) + { + if ((pins->nLoopStart + 3 < pins->nLoopEnd) && (pins->nLoopEnd <= pins->nLength)) + { + rSndFile.Chn[i].nLoopStart = pins->nLoopStart; + rSndFile.Chn[i].nLoopEnd = pins->nLoopEnd; + rSndFile.Chn[i].nLength = pins->nLoopEnd; + if (rSndFile.Chn[i].nPos > rSndFile.Chn[i].nLength) + { + rSndFile.Chn[i].nPos = rSndFile.Chn[i].nLoopStart; + rSndFile.Chn[i].dwFlags &= ~CHN_PINGPONGFLAG; + } + DWORD d = rSndFile.Chn[i].dwFlags & ~(CHN_PINGPONGLOOP|CHN_LOOP); + if (pins->uFlags & CHN_LOOP) + { + d |= CHN_LOOP; + if (pins->uFlags & CHN_PINGPONGLOOP) d |= CHN_PINGPONGLOOP; + } + rSndFile.Chn[i].dwFlags = d; + } else + if (!(pins->uFlags & CHN_LOOP)) + { + rSndFile.Chn[i].dwFlags &= ~(CHN_PINGPONGLOOP|CHN_LOOP); + } + } + } + END_CRITICAL(); + return true; +} + + +} // namespace ctrlSmp Added: trunk/OpenMPT/soundlib/modsmp_ctrl.h =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.h (rev 0) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.h 2009-06-14 21:48:05 UTC (rev 269) @@ -0,0 +1,32 @@ +/* + * MODINSTRUMENT related functions. + */ + +#ifndef MODSMP_CTRL_H +#define MODSMP_CTRL_H + +#include "Sndfile.h" + +namespace ctrlSmp +{ + +typedef uintptr_t SmpLength; + +// Insert silence to given location. +// Note: Is currently implemented only for inserting silence to the beginning and to the end of the sample. +// Return: Length of the new sample. +SmpLength InsertSilence(MODINSTRUMENT& smp, const SmpLength nSilenceLength, const SmpLength nStartFrom, CSoundFile* pSndFile = 0); + +// Replaces sample in 'smp' with given sample and frees the old sample. +void ReplaceSample(MODINSTRUMENT& smp, const LPSTR pNewSample, const SmpLength nNewLength); + +bool AdjustEndOfSample(MODINSTRUMENT& smp, CSoundFile* pSndFile = 0); + +// Returns the number of bytes allocated(at least) for sample data. +// Note: Currently the return value is based on the sample length and the actual +// allocation may be more than what this function returns. +inline SmpLength GetSampleCapacity(MODINSTRUMENT& smp) {return smp.GetSampleSizeInBytes();} + +} + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |