You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
(1) |
Jul
|
Aug
(10) |
Sep
|
Oct
|
Nov
|
Dec
(3) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(1) |
Feb
(2) |
Mar
(3) |
Apr
(2) |
May
(10) |
Jun
(2) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
2008 |
Jan
(6) |
Feb
(4) |
Mar
(5) |
Apr
(2) |
May
(1) |
Jun
(1) |
Jul
(4) |
Aug
(6) |
Sep
(2) |
Oct
(9) |
Nov
(1) |
Dec
(4) |
2009 |
Jan
(9) |
Feb
(2) |
Mar
(2) |
Apr
(2) |
May
(6) |
Jun
(18) |
Jul
(33) |
Aug
(39) |
Sep
(33) |
Oct
(24) |
Nov
(23) |
Dec
(22) |
2010 |
Jan
(29) |
Feb
(32) |
Mar
(51) |
Apr
(17) |
May
(31) |
Jun
(21) |
Jul
(32) |
Aug
(28) |
Sep
(35) |
Oct
(27) |
Nov
(11) |
Dec
(13) |
2011 |
Jan
(14) |
Feb
(13) |
Mar
(27) |
Apr
(27) |
May
(28) |
Jun
(20) |
Jul
(43) |
Aug
(52) |
Sep
(66) |
Oct
(61) |
Nov
(11) |
Dec
(8) |
2012 |
Jan
(20) |
Feb
(30) |
Mar
(38) |
Apr
(21) |
May
(33) |
Jun
(21) |
Jul
(25) |
Aug
(9) |
Sep
(24) |
Oct
(42) |
Nov
(27) |
Dec
(41) |
2013 |
Jan
(20) |
Feb
(35) |
Mar
(156) |
Apr
(298) |
May
(258) |
Jun
(201) |
Jul
(105) |
Aug
(60) |
Sep
(193) |
Oct
(245) |
Nov
(280) |
Dec
(194) |
2014 |
Jan
(63) |
Feb
(202) |
Mar
(200) |
Apr
(23) |
May
(53) |
Jun
(105) |
Jul
(18) |
Aug
(26) |
Sep
(110) |
Oct
(187) |
Nov
(97) |
Dec
(74) |
2015 |
Jan
(45) |
Feb
(55) |
Mar
(116) |
Apr
(116) |
May
(193) |
Jun
(164) |
Jul
(50) |
Aug
(111) |
Sep
(98) |
Oct
(71) |
Nov
(103) |
Dec
(63) |
2016 |
Jan
(33) |
Feb
(101) |
Mar
(182) |
Apr
(139) |
May
(140) |
Jun
(103) |
Jul
(165) |
Aug
(286) |
Sep
(208) |
Oct
(127) |
Nov
(97) |
Dec
(54) |
2017 |
Jan
(64) |
Feb
(335) |
Mar
(202) |
Apr
(212) |
May
(139) |
Jun
(127) |
Jul
(294) |
Aug
(154) |
Sep
(170) |
Oct
(152) |
Nov
(156) |
Dec
(62) |
2018 |
Jan
(168) |
Feb
(237) |
Mar
(196) |
Apr
(174) |
May
(174) |
Jun
(161) |
Jul
(127) |
Aug
(88) |
Sep
(149) |
Oct
(66) |
Nov
(52) |
Dec
(135) |
2019 |
Jan
(146) |
Feb
(126) |
Mar
(104) |
Apr
(58) |
May
(60) |
Jun
(28) |
Jul
(197) |
Aug
(129) |
Sep
(141) |
Oct
(148) |
Nov
(63) |
Dec
(100) |
2020 |
Jan
(74) |
Feb
(37) |
Mar
(59) |
Apr
(154) |
May
(194) |
Jun
(133) |
Jul
(313) |
Aug
(197) |
Sep
(49) |
Oct
(162) |
Nov
(143) |
Dec
(57) |
2021 |
Jan
(120) |
Feb
(107) |
Mar
(314) |
Apr
(157) |
May
(524) |
Jun
(169) |
Jul
(72) |
Aug
(133) |
Sep
(135) |
Oct
(146) |
Nov
(198) |
Dec
(325) |
2022 |
Jan
(409) |
Feb
(249) |
Mar
(138) |
Apr
(95) |
May
(102) |
Jun
(221) |
Jul
(66) |
Aug
(120) |
Sep
(192) |
Oct
(131) |
Nov
(53) |
Dec
(171) |
2023 |
Jan
(357) |
Feb
(82) |
Mar
(168) |
Apr
(218) |
May
(196) |
Jun
(86) |
Jul
(115) |
Aug
(49) |
Sep
(190) |
Oct
(102) |
Nov
(45) |
Dec
(76) |
2024 |
Jan
(86) |
Feb
(50) |
Mar
(324) |
Apr
(209) |
May
(197) |
Jun
(232) |
Jul
(194) |
Aug
(247) |
Sep
(219) |
Oct
(266) |
Nov
(328) |
Dec
(304) |
2025 |
Jan
(191) |
Feb
(115) |
Mar
(137) |
Apr
(32) |
May
(126) |
Jun
(403) |
Jul
(202) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sag...@us...> - 2009-07-06 22:12:42
|
Revision: 284 http://modplug.svn.sourceforge.net/modplug/?rev=284&view=rev Author: saga-games Date: 2009-07-06 22:12:39 +0000 (Mon, 06 Jul 2009) Log Message: ----------- [Imp] Note properties: Completed descriptions for extended MOD/XM, fixed display of several effects. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-06 21:48:54 UTC (rev 283) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-06 22:12:39 UTC (rev 284) @@ -2634,49 +2634,95 @@ } else { wsprintf(s, "%d", param & 0x0F); - if ((gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) || (gFXInfo[ndx].dwEffect == CMD_MODCMDEX)) + if(gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) { switch(param & 0xF0) { - case 0x10: + case 0x10: // glissando control if((param & 0x0F) == 0) strcpy(s, "smooth"); else strcpy(s, "semitones"); break; - case 0x30: - case 0x40: - case 0x50: - if(gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) + case 0x30: // vibrato waveform + case 0x40: // tremolo waveform + case 0x50: // panbrello waveform + switch(param & 0x0F) { - switch(param & 0x0F) - { - case 0x00: case 0x04: case 0x08: case 0x0C: strcpy(s, "sine wave"); break; - case 0x01: case 0x05: case 0x09: case 0x0D: strcpy(s, "ramp down"); break; - case 0x02: case 0x06: case 0x0A: case 0x0E: strcpy(s, "square wave"); break; - case 0x03: case 0x07: case 0x0B: case 0x0F: strcpy(s, "random"); break; - } + case 0x00: case 0x04: case 0x08: case 0x0C: strcpy(s, "sine wave"); break; + case 0x01: case 0x05: case 0x09: case 0x0D: strcpy(s, "ramp down"); break; + case 0x02: case 0x06: case 0x0A: case 0x0E: strcpy(s, "square wave"); break; + case 0x03: case 0x07: case 0x0B: case 0x0F: strcpy(s, "random"); break; } break; - case 0x60: if (gFXInfo[ndx].dwEffect == CMD_MODCMDEX) break; - case 0xA0: + case 0x60: // fine pattern delay (ticks) + strcat(s, " rows"); + break; + + case 0xA0: // high offset wsprintf(s, "+ %u samples", 0x10000 * (param & 0x0F)); break; - case 0xB0: - if (gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) + case 0xB0: // pattern loop + if((param & 0x0F) == 0x00) + strcpy(s, "loop start"); + else + strcat(s, " times"); + break; + case 0xC0: // note cut + case 0xD0: // note delay + strcat(s, " frames"); + break; + case 0xE0: // pattern delay (rows) + strcat(s, " rows"); + break; + case 0xF0: // macro + wsprintf(s, "SF%X", param & 0x0F); break; + default: + break; + } + } + if(gFXInfo[ndx].dwEffect == CMD_MODCMDEX) + { + switch(param & 0xF0) + { + case 0x30: // glissando control + if((param & 0x0F) == 0) + strcpy(s, "smooth"); + else + strcpy(s, "semitones"); + break; + case 0x40: // vibrato waveform + case 0x70: // tremolo waveform + //todo: find proper values for XM/MOD (it's not as trivial as described here, i think) + switch(param & 0x0F) { - if((param & 0x0F) == 0x00) - strcpy(s, "loop start"); - else - strcat(s, " times"); + case 0x00: case 0x03: case 0x06: case 0x0A: case 0x0D: strcpy(s, "sine wave"); break; + case 0x01: case 0x04: case 0x07: case 0x0B: case 0x0E: strcpy(s, "ramp down"); break; + case 0x02: case 0x05: case 0x08: case 0x0C: case 0x0F: strcpy(s, "square wave"); break; } break; - case 0xC0: - case 0xD0: strcat(s, " frames"); break; - case 0xE0: strcat(s, " rows"); break; - case 0xF0: wsprintf(s, "SF%X", param & 0x0F); break; + case 0x60: // pattern loop + if((param & 0x0F) == 0x00) + strcpy(s, "loop start"); + else + strcat(s, " times"); + break; + case 0x90: // retrigger + wsprintf(s, "speed %d", param & 0x0F); + break; + case 0xC0: // note cut + case 0xD0: // note delay + strcat(s, " frames"); + break; + case 0xE0: // pattern delay (rows) + strcat(s, " rows"); + break; + case 0xF0: // macro + wsprintf(s, "SF%X", param & 0x0F); break; + default: + break; } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2009-07-06 21:49:02
|
Revision: 283 http://modplug.svn.sourceforge.net/modplug/?rev=283&view=rev Author: saga-games Date: 2009-07-06 21:48:54 +0000 (Mon, 06 Jul 2009) Log Message: ----------- [Mod] Sample editor: DC offset removal won't affect default volume, global volume won't be set when only parts of a sample are being processed [Imp] Note properties: Added description for S1x - Glissando Control Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/modsmp_ctrl.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-06 17:34:31 UTC (rev 282) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-06 21:48:54 UTC (rev 283) @@ -2638,6 +2638,12 @@ { switch(param & 0xF0) { + case 0x10: + if((param & 0x0F) == 0) + strcpy(s, "smooth"); + else + strcpy(s, "semitones"); + break; case 0x30: case 0x40: case 0x50: Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.cpp =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-07-06 17:34:31 UTC (rev 282) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-07-06 21:48:54 UTC (rev 283) @@ -279,11 +279,9 @@ else if(pins->GetElementarySampleSize() == 1) RemoveOffsetAndNormalize( reinterpret_cast<int8*>(pins->pSample) + iStart, iEnd - iStart, dOffset, dAmplify); - // step 3: adjust either global vol or default vol of this sample - if(modtype == MOD_TYPE_IT || modtype == MOD_TYPE_MPT) + // step 3: adjust global vol (if available) + if((modtype & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (iStart == 0) && (iEnd = pins->nLength)) pins->nGlobalVol = min((WORD)(pins->nGlobalVol / dAmplify), 64); - else if(modtype != MOD_TYPE_NONE) - pins->nVolume = min((WORD)(pins->nVolume / dAmplify), 256); AdjustEndOfSample(smp, pSndFile); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2009-07-06 17:34:54
|
Revision: 282 http://modplug.svn.sourceforge.net/modplug/?rev=282&view=rev Author: saga-games Date: 2009-07-06 17:34:31 +0000 (Mon, 06 Jul 2009) Log Message: ----------- Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moptions.cpp Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-07-06 15:27:09 UTC (rev 281) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-07-06 17:34:31 UTC (rev 282) @@ -2208,15 +2208,22 @@ SetDefaultDirectory(szInstrDir, DIR_INSTRUMENTS); SetDefaultDirectory(szVstDir, DIR_PLUGINS); SetDefaultDirectory(szPresetDir, DIR_PLUGINPRESETS); + return TRUE; +} - // This shouldn't be here (misc options) - m_wndToolBar.EnableFlatButtons(m_dwPatternSetup & PATTERN_FLATBUTTONS); - UpdateAllViews(HINT_MPTOPTIONS, NULL); - if (m_dwPatternSetup & PATTERN_MUTECHNMODE) +BOOL CMainFrame::SetupMiscOptions() +//--------------------------------- +{ + if (CMainFrame::m_dwPatternSetup & PATTERN_MUTECHNMODE) CSoundFile::gdwSoundSetup |= SNDMIX_MUTECHNMODE; else CSoundFile::gdwSoundSetup &= ~SNDMIX_MUTECHNMODE; - return TRUE; + + m_wndToolBar.EnableFlatButtons(m_dwPatternSetup & PATTERN_FLATBUTTONS); + + UpdateTree(NULL, HINT_MPTOPTIONS); + UpdateAllViews(HINT_MPTOPTIONS, NULL); + return true; } Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2009-07-06 15:27:09 UTC (rev 281) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2009-07-06 17:34:31 UTC (rev 282) @@ -571,6 +571,7 @@ void SwitchToActiveView(); BOOL SetupSoundCard(DWORD q, DWORD rate, UINT nbits, UINT chns, UINT bufsize, LONG wd); BOOL SetupDirectories(LPCTSTR szModDir, LPCTSTR szSampleDir, LPCTSTR szInstrDir, LPCTSTR szVstDir, LPCTSTR szPresetDir); + BOOL SetupMiscOptions(); BOOL SetupPlayer(DWORD, DWORD, BOOL bForceUpdate=FALSE); BOOL SetupMidi(DWORD d, LONG n); void SetPreAmp(UINT n); Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2009-07-06 15:27:09 UTC (rev 281) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2009-07-06 17:34:31 UTC (rev 282) @@ -782,12 +782,14 @@ if (bCheck) CMainFrame::m_dwPatternSetup |= mask; else CMainFrame::m_dwPatternSetup &= ~mask; m_CheckList.SetCheck(i, (bCheck) ? TRUE : FALSE); } + CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); if (pMainFrm) { pMainFrm->SetupDirectories(szModDir, szSmpDir, szInsDir, szVstDir, szPresetDir); - pMainFrm->UpdateTree(NULL, HINT_MPTOPTIONS); + pMainFrm->SetupMiscOptions(); } + CPropertyPage::OnOK(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-07-06 15:53:10
|
Revision: 281 http://modplug.svn.sourceforge.net/modplug/?rev=281&view=rev Author: relabsoluness Date: 2009-07-06 15:27:09 +0000 (Mon, 06 Jul 2009) Log Message: ----------- (patches from Jojo, merged somewhat modified) [New] General: New default directories: plugins and plugin presets. Includes some related refactoring. (merge edit: some changes and fixes) [Fix] Internal: Fixed buffer overrun in tree view. (merged modified) Modified Paths: -------------- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/Moptions.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/resource.h Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -115,8 +115,12 @@ CFileDialog dlg(TRUE, "fxp", NULL, OFN_HIDEREADONLY| OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_ENABLESIZING | OFN_NOREADONLYRETURN, "VST Program (*.fxp)|*.fxp||", theApp.m_pMainWnd); + dlg.m_ofn.lpstrInitialDir = CMainFrame::GetWorkingDirectory(DIR_PLUGINPRESETS); + if (!(dlg.DoModal() == IDOK)) return; + CMainFrame::SetWorkingDirectory(dlg.GetFileName(), DIR_PLUGINPRESETS, true); + //TODO: exception handling to distinguish errors at this level. if (!(m_pVstPlugin->LoadProgram(dlg.GetFileName()))) ::AfxMessageBox("Error loading preset. Are you sure it is for this plugin?"); Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -1237,7 +1237,6 @@ BOOL CCtrlInstruments::OpenInstrument(LPCSTR lpszFileName) //-------------------------------------------------------- { - CHAR szName[_MAX_FNAME], szExt[_MAX_EXT]; CMappedFile f; BOOL bFirst, bOk; DWORD len; @@ -1287,10 +1286,9 @@ INSTRUMENTHEADER *penv = m_pSndFile->Headers[m_nInstrument]; if (penv) { - CHAR szPath[_MAX_PATH], szNewPath[_MAX_PATH]; - _splitpath(lpszFileName, szNewPath, szPath, szName, szExt); - strcat(szNewPath, szPath); - strcpy(CMainFrame::m_szCurInsDir, szNewPath); + TCHAR szName[_MAX_FNAME], szExt[_MAX_EXT]; + _tsplitpath(lpszFileName, nullptr, nullptr, szName, szExt); + CMainFrame::SetWorkingDirectory(lpszFileName, DIR_INSTRUMENTS, true); if (!penv->name[0]) { @@ -1528,10 +1526,11 @@ "Impulse Tracker Instruments (*.iti)|*.iti|" "All Files (*.*)|*.*||", this); - if (CMainFrame::m_szCurInsDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurInsDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_INSTRUMENTS); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + const size_t bufferSize = 2048; //Note: This is possibly the maximum buffer size. vector<char> filenameBuffer(bufferSize, 0); dlg.GetOFN().lpstrFile = &filenameBuffer[0]; @@ -1601,10 +1600,11 @@ this); // -! BUG_FIX#0019 - if (CMainFrame::m_szCurInsDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurInsDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_INSTRUMENTS); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + if (dlg.DoModal() != IDOK) return; BeginWaitCursor(); _splitpath(dlg.GetPathName(), drive, path, NULL, ext); @@ -1625,8 +1625,11 @@ EndWaitCursor(); if (!bOk) ErrorBox(IDS_ERR_SAVEINS, this); else { - strcpy(CMainFrame::m_szCurInsDir, drive); - strcat(CMainFrame::m_szCurInsDir, path); + strcpy(szFileName, drive); + strcat(szFileName, path); + + CMainFrame::SetWorkingDirectory(szFileName, DIR_INSTRUMENTS); + // -> CODE#0023 // -> DESC="IT project files (.itp)" // m_pModDoc->UpdateAllViews(NULL, (m_nInstrument << 24) | HINT_INSTRUMENT); Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -774,30 +774,30 @@ EndWaitCursor(); if (bOk) { - CHAR szPath[_MAX_PATH], szNewPath[_MAX_PATH]; MODINSTRUMENT *pins = &m_pSndFile->Ins[m_nSample]; - _splitpath(lpszFileName, szNewPath, szPath, szName, szExt); - strcat(szNewPath, szPath); - strcpy(CMainFrame::m_szCurSmpDir, szNewPath); + CMainFrame::SetWorkingDirectory(lpszFileName, DIR_SAMPLES, true); if (!pins->name[0]) { - memset(szPath, 0, 32); - strcpy(szPath, szName); + CHAR szFullFilename[_MAX_PATH]; + _splitpath(lpszFileName, 0, 0, szName, szExt); + + memset(szFullFilename, 0, 32); + strcpy(szFullFilename, szName); if (m_pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) { // MOD/XM - strcat(szPath, szExt); - szPath[31] = 0; - memcpy(m_pSndFile->m_szNames[m_nSample], szPath, 32); + strcat(szFullFilename, szExt); + szFullFilename[31] = 0; + memcpy(m_pSndFile->m_szNames[m_nSample], szFullFilename, 32); } else { // S3M/IT - szPath[31] = 0; - if (!m_pSndFile->m_szNames[m_nSample][0]) memcpy(m_pSndFile->m_szNames[m_nSample], szPath, 32); - if (strlen(szPath) < 9) strcat(szPath, szExt); + szFullFilename[31] = 0; + if (!m_pSndFile->m_szNames[m_nSample][0]) memcpy(m_pSndFile->m_szNames[m_nSample], szFullFilename, 32); + if (strlen(szFullFilename) < 9) strcat(szFullFilename, szExt); } - szPath[21] = 0; - memcpy(pins->name, szPath, 22); + szFullFilename[21] = 0; + memcpy(pins->name, szFullFilename, 22); } if ((m_pSndFile->m_nType & MOD_TYPE_XM) && (!(pins->uFlags & CHN_PANNING))) { @@ -925,10 +925,11 @@ "Raw Samples (*.raw,*.snd,*.pcm)|*.raw;*.snd;*.pcm|" "All Files (*.*)|*.*||", this); - if (CMainFrame::m_szCurSmpDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurSmpDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_SAMPLES); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + dlg.m_ofn.nFilterIndex = nLastIndex; const size_t bufferSize = 2048; //Note: This is possibly the maximum buffer size in MFC 7(this note was written November 2006). vector<char> filenameBuffer(bufferSize, 0); @@ -992,10 +993,11 @@ "Wave File (*.wav)|*.wav|" "RAW Audio (*.raw)|*.raw||", this); - if (CMainFrame::m_szCurSmpDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurSmpDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_SAMPLES); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + if (dlg.DoModal() != IDOK) return; BeginWaitCursor(); @@ -1011,10 +1013,7 @@ ErrorBox(IDS_ERR_SAVESMP, this); } else { - CHAR drive[_MAX_DRIVE], path[_MAX_PATH]; - _splitpath(dlg.GetPathName(), drive, path, NULL, NULL); - strcpy(CMainFrame::m_szCurSmpDir, drive); - strcat(CMainFrame::m_szCurSmpDir, path); + CMainFrame::SetWorkingDirectory(dlg.GetPathName(), DIR_SAMPLES, true); } SwitchToView(); } Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -257,16 +257,12 @@ 0x00FF00, 0x00FFFF, 0x0000FF, }; -// Arrays -CHAR CMainFrame::m_szModDir[_MAX_PATH] = ""; -CHAR CMainFrame::m_szSmpDir[_MAX_PATH] = ""; -CHAR CMainFrame::m_szInsDir[_MAX_PATH] = ""; -CHAR CMainFrame::m_szKbdFile[_MAX_PATH] = ""; //rewbs.customKeys -CHAR CMainFrame::m_szCurModDir[_MAX_PATH] = ""; -CHAR CMainFrame::m_szCurSmpDir[_MAX_PATH] = ""; -CHAR CMainFrame::m_szCurInsDir[_MAX_PATH] = ""; -//CHAR CMainFrame::m_szCurKbdFile[_MAX_PATH] = ""; //rewbs.customKeys +// Directory Arrays (Default + Last) +TCHAR CMainFrame::m_szDefaultDirectory[NUM_DIRS][_MAX_PATH] = {0}; +TCHAR CMainFrame::m_szWorkingDirectory[NUM_DIRS][_MAX_PATH] = {0}; +TCHAR CMainFrame::m_szKbdFile[_MAX_PATH] = ""; //rewbs.customKeys + CInputHandler *CMainFrame::m_InputHandler = NULL; //rewbs.customKeys CAutoSaver *CMainFrame::m_pAutoSaver = NULL; //rewbs.autosave CPerformanceCounter *CMainFrame::m_pPerfCounter = NULL; @@ -318,8 +314,13 @@ m_szUserText[0] = 0; m_szInfoText[0] = 0; m_szXInfoText[0]= 0; //rewbs.xinfo - m_szPluginsDir[0] = 0; - m_szExportDir[0] = 0; + + for(UINT i = 0; i < NUM_DIRS; i++) + { + m_szDefaultDirectory[i][0] = 0; + m_szWorkingDirectory[i][0] = 0; + } + m_dTotalCPU=0; memset(gpenVuMeter, 0, sizeof(gpenVuMeter)); @@ -442,10 +443,19 @@ CSoundFile::s_DefaultPlugVolumeHandling = static_cast<uint8>(GetPrivateProfileInt("Misc", "DefaultPlugVolumeHandling", PLUGIN_VOLUMEHANDLING_IGNORE, iniFile)); if(CSoundFile::s_DefaultPlugVolumeHandling > 2) CSoundFile::s_DefaultPlugVolumeHandling = PLUGIN_VOLUMEHANDLING_IGNORE; - GetPrivateProfileString("Paths", "Songs_Directory", m_szModDir, m_szModDir, INIBUFFERSIZE, iniFile); - GetPrivateProfileString("Paths", "Samples_Directory", m_szSmpDir, m_szSmpDir, INIBUFFERSIZE, iniFile); - GetPrivateProfileString("Paths", "Instruments_Directory", m_szInsDir, m_szInsDir, INIBUFFERSIZE, iniFile); - GetPrivateProfileString("Paths", "Plugins_Directory", m_szPluginsDir, m_szPluginsDir, INIBUFFERSIZE, iniFile); + TCHAR szPath[_MAX_PATH] = ""; + GetPrivateProfileString("Paths", "Songs_Directory", GetDefaultDirectory(DIR_MODS), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_MODS); + GetPrivateProfileString("Paths", "Samples_Directory", GetDefaultDirectory(DIR_SAMPLES), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_SAMPLES); + GetPrivateProfileString("Paths", "Instruments_Directory", GetDefaultDirectory(DIR_INSTRUMENTS), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_INSTRUMENTS); + GetPrivateProfileString("Paths", "Plugins_Directory", GetDefaultDirectory(DIR_PLUGINS), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_PLUGINS); + GetPrivateProfileString("Paths", "Plugin_Presets_Directory", GetDefaultDirectory(DIR_PLUGINPRESETS), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_PLUGINPRESETS); + GetPrivateProfileString("Paths", "Export_Directory", GetDefaultDirectory(DIR_EXPORT), szPath, INIBUFFERSIZE, iniFile); + SetDefaultDirectory(szPath, DIR_EXPORT); GetPrivateProfileString("Paths", "Key_Config_File", m_szKbdFile, m_szKbdFile, INIBUFFERSIZE, iniFile); CSoundFile::m_nXBassDepth = GetPrivateProfileLong("Effects", "XBassDepth", 0, iniFile); @@ -479,7 +489,6 @@ DWORD dwREG_DWORD = REG_DWORD; DWORD dwREG_SZ = REG_SZ; DWORD dwDWORDSize = sizeof(UINT); - DWORD dwSZSIZE = sizeof(m_szModDir); DWORD dwCRSIZE = sizeof(COLORREF); @@ -524,15 +533,23 @@ RegQueryValueEx(key, "BufferLength", NULL, &dwREG_DWORD, (LPBYTE)&m_nBufferLength, &dwDWORDSize); if ((m_nBufferLength < 10) || (m_nBufferLength > 200)) m_nBufferLength = 100; RegQueryValueEx(key, "PreAmp", NULL, &dwREG_DWORD, (LPBYTE)&m_nPreAmp, &dwDWORDSize); - RegQueryValueEx(key, "Songs_Directory", NULL, &dwREG_SZ, (LPBYTE)m_szModDir, &dwSZSIZE); - dwSZSIZE = sizeof(m_szSmpDir); - RegQueryValueEx(key, "Samples_Directory", NULL, &dwREG_SZ, (LPBYTE)m_szSmpDir, &dwSZSIZE); - dwSZSIZE = sizeof(m_szInsDir); - RegQueryValueEx(key, "Instruments_Directory", NULL, &dwREG_SZ, (LPBYTE)m_szInsDir, &dwSZSIZE); - dwSZSIZE = sizeof(m_szPluginsDir); - RegQueryValueEx(key, "Plugins_Directory", NULL, &dwREG_SZ, (LPBYTE)m_szPluginsDir, &dwSZSIZE); + + CHAR sPath[_MAX_PATH] = ""; + DWORD dwSZSIZE = sizeof(sPath); + RegQueryValueEx(key, "Songs_Directory", NULL, &dwREG_SZ, (LPBYTE)sPath, &dwSZSIZE); + SetDefaultDirectory(sPath, DIR_MODS); + dwSZSIZE = sizeof(sPath); + RegQueryValueEx(key, "Samples_Directory", NULL, &dwREG_SZ, (LPBYTE)sPath, &dwSZSIZE); + SetDefaultDirectory(sPath, DIR_SAMPLES); + dwSZSIZE = sizeof(sPath); + RegQueryValueEx(key, "Instruments_Directory", NULL, &dwREG_SZ, (LPBYTE)sPath, &dwSZSIZE); + SetDefaultDirectory(sPath, DIR_INSTRUMENTS); + dwSZSIZE = sizeof(sPath); + RegQueryValueEx(key, "Plugins_Directory", NULL, &dwREG_SZ, (LPBYTE)sPath, &dwSZSIZE); + SetDefaultDirectory(sPath, DIR_PLUGINS); dwSZSIZE = sizeof(m_szKbdFile); RegQueryValueEx(key, "Key_Config_File", NULL, &dwREG_SZ, (LPBYTE)m_szKbdFile, &dwSZSIZE); + RegQueryValueEx(key, "XBassDepth", NULL, &dwREG_DWORD, (LPBYTE)&CSoundFile::m_nXBassDepth, &dwDWORDSize); RegQueryValueEx(key, "XBassRange", NULL, &dwREG_DWORD, (LPBYTE)&CSoundFile::m_nXBassRange, &dwDWORDSize); RegQueryValueEx(key, "ReverbDepth", NULL, &dwREG_DWORD, (LPBYTE)&CSoundFile::m_nReverbDepth, &dwDWORDSize); @@ -658,11 +675,12 @@ } } // Default directory location - strcpy(m_szCurModDir, m_szModDir); - strcpy(m_szCurSmpDir, m_szSmpDir); - strcpy(m_szCurInsDir, m_szInsDir); -// strcpy(m_szCurKbdFile, m_szKbdFile); //rewbs.customKeys - if (m_szModDir[0]) SetCurrentDirectory(m_szModDir); + for(UINT i = 0; i < NUM_DIRS; i++) + { + _tcscpy(m_szWorkingDirectory[i], m_szDefaultDirectory[i]); + } + if (m_szDefaultDirectory[DIR_MODS][0]) SetCurrentDirectory(m_szDefaultDirectory[DIR_MODS]); + // Create Audio Thread m_hAudioWakeUp = CreateEvent(NULL, FALSE, FALSE, NULL); m_hNotifyWakeUp = CreateEvent(NULL, FALSE, FALSE, NULL); @@ -948,10 +966,12 @@ WritePrivateProfileDWord("Pattern Editor", "Record", gbPatternRecord, iniFile); WritePrivateProfileDWord("Pattern Editor", "AutoChordWaitTime", gnAutoChordWaitTime, iniFile); - WritePrivateProfileString("Paths", "Songs_Directory", m_szModDir, iniFile); - WritePrivateProfileString("Paths", "Samples_Directory", m_szSmpDir, iniFile); - WritePrivateProfileString("Paths", "Instruments_Directory", m_szInsDir, iniFile); - WritePrivateProfileString("Paths", "Plugins_Directory", m_szPluginsDir, iniFile); + WritePrivateProfileString("Paths", "Songs_Directory", GetDefaultDirectory(DIR_MODS), iniFile); + WritePrivateProfileString("Paths", "Samples_Directory", GetDefaultDirectory(DIR_SAMPLES), iniFile); + WritePrivateProfileString("Paths", "Instruments_Directory", GetDefaultDirectory(DIR_INSTRUMENTS), iniFile); + WritePrivateProfileString("Paths", "Plugins_Directory", GetDefaultDirectory(DIR_PLUGINS), iniFile); + WritePrivateProfileString("Paths", "Plugin_Presets_Directory", GetDefaultDirectory(DIR_PLUGINPRESETS), iniFile); + WritePrivateProfileString("Paths", "Export_Directory", GetDefaultDirectory(DIR_EXPORT), iniFile); WritePrivateProfileString("Paths", "Key_Config_File", m_szKbdFile, iniFile); WritePrivateProfileLong("Effects", "XBassDepth", CSoundFile::m_nXBassDepth, iniFile); @@ -2179,15 +2199,16 @@ } -BOOL CMainFrame::SetupDirectories(LPCSTR songs, LPCSTR samples, LPCSTR instr) +BOOL CMainFrame::SetupDirectories(LPCTSTR szModDir, LPCTSTR szSampleDir, LPCTSTR szInstrDir, LPCTSTR szVstDir, LPCTSTR szPresetDir) //--------------------------------------------------------------------------- { - strcpy(m_szModDir, songs); - strcpy(m_szSmpDir, samples); - strcpy(m_szInsDir, instr); - if (songs[0]) strcpy(m_szCurModDir, songs); - if (samples[0]) strcpy(m_szCurSmpDir, samples); - if (instr[0]) strcpy(m_szCurInsDir, instr); + // will also set working directory + SetDefaultDirectory(szModDir, DIR_MODS); + SetDefaultDirectory(szSampleDir, DIR_SAMPLES); + SetDefaultDirectory(szInstrDir, DIR_INSTRUMENTS); + SetDefaultDirectory(szVstDir, DIR_PLUGINS); + SetDefaultDirectory(szPresetDir, DIR_PLUGINPRESETS); + // This shouldn't be here (misc options) m_wndToolBar.EnableFlatButtons(m_dwPatternSetup & PATTERN_FLATBUTTONS); UpdateAllViews(HINT_MPTOPTIONS, NULL); @@ -3003,3 +3024,56 @@ CBox.SetItemData(CBox.AddString(s), i); } } + + +// retrieve / set default directory from given string and store it our setup variables +// TODO: Let some magic happen to convert between absolute and relative paths. m_csExecutableDirectoryPath might be helpful + +void CMainFrame::SetDirectory(const LPCTSTR szFilenameFrom, Directory dir, TCHAR (&directories)[NUM_DIRS][_MAX_PATH], bool bStripFilename) +//---------------------------------------------------------------------------- +{ + TCHAR szPath[_MAX_PATH], szDir[_MAX_DIR]; + + if(bStripFilename) + { + _tsplitpath(szFilenameFrom, szPath, szDir, 0, 0); + _tcscat(szPath, szDir); + } + else + { + _tcscpy(szPath, szFilenameFrom); + } + + _tcscpy(directories[dir], szPath); + + // When updating default directory, also update the working directory. + if(szPath[0] && directories == m_szDefaultDirectory) + SetWorkingDirectory(szPath, dir); +} + +void CMainFrame::SetDefaultDirectory(const LPCTSTR szFilenameFrom, Directory dir, bool bStripFilename) +//---------------------------------------------------------------------------- +{ + SetDirectory(szFilenameFrom, dir, m_szDefaultDirectory, bStripFilename); +} + + +void CMainFrame::SetWorkingDirectory(const LPCTSTR szFilenameFrom, Directory dir, bool bStripFilename) +//---------------------------------------------------------------------------- +{ + SetDirectory(szFilenameFrom, dir, m_szWorkingDirectory, bStripFilename); +} + + +LPCTSTR CMainFrame::GetDefaultDirectory(Directory dir) +//---------------------------------------------------------------------------- +{ + return m_szDefaultDirectory[dir]; +} + + +LPCTSTR CMainFrame::GetWorkingDirectory(Directory dir) +//---------------------------------------------------------------------------- +{ + return m_szWorkingDirectory[dir]; +} Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2009-07-06 15:27:09 UTC (rev 281) @@ -340,6 +340,22 @@ ///////////////////////////////////////////////////////////////////////// +// Default directories + +enum Directory +{ + DIR_MODS = 0, + DIR_SAMPLES, + DIR_INSTRUMENTS, + DIR_PLUGINS, + DIR_PLUGINPRESETS, + DIR_EXPORT, + NUM_DIRS +}; + + + +///////////////////////////////////////////////////////////////////////// // Misc. Macros @@ -400,9 +416,8 @@ static COLORREF rgbCustomColors[MAX_MODCOLORS]; static LPMODPLUGDIB bmpPatterns, bmpNotes, bmpVUMeters, bmpVisNode; static HPEN gpenVuMeter[NUM_VUMETER_PENS*2]; - // Arrays - static CHAR m_szModDir[_MAX_PATH], m_szSmpDir[_MAX_PATH], m_szInsDir[_MAX_PATH], m_szKbdFile[_MAX_PATH]; - static CHAR m_szCurModDir[_MAX_PATH], m_szCurSmpDir[_MAX_PATH], m_szCurInsDir[_MAX_PATH], m_szCurKbdDir[_MAX_PATH]; + // key config + static TCHAR m_szKbdFile[_MAX_PATH]; // Low-Level Audio public: @@ -452,8 +467,6 @@ // Notification Buffer MPTNOTIFICATION NotifyBuffer[MAX_UPDATE_HISTORY]; // Misc - CHAR m_szPluginsDir[_MAX_PATH]; - CHAR m_szExportDir[_MAX_PATH]; bool m_bOptionsLocked; //rewbs.customKeys double m_dTotalCPU; CModDoc* m_pJustModifiedDoc; @@ -480,10 +493,6 @@ BOOL dsoundFillBuffers(LPBYTE lpBuf, DWORD dwSize); BOOL DSoundDone(LPBYTE lpBuffer, DWORD dwBytes); BOOL DoNotification(DWORD dwSamplesRead, DWORD dwLatency); - LPCSTR GetPluginsDir() const { return m_szPluginsDir; } - VOID SetPluginsDir(LPCSTR pszDir) { lstrcpyn(m_szPluginsDir, pszDir, sizeof(m_szPluginsDir)); } - LPCSTR GetExportDir() const { return m_szExportDir; } - VOID SetExportDir(LPCSTR pszDir) { lstrcpyn(m_szExportDir, pszDir, sizeof(m_szExportDir)); } // Midi Input Functions public: @@ -517,7 +526,7 @@ static CString GetPrivateProfileCString(const CString section, const CString key, const CString defaultValue, const CString iniFile); -// Misc functions + // Misc functions public: VOID SetUserText(LPCSTR lpszText); VOID SetInfoText(LPCSTR lpszText); @@ -561,7 +570,7 @@ BOOL StopRenderer(CSoundFile*); //rewbs.VSTTimeInfo void SwitchToActiveView(); BOOL SetupSoundCard(DWORD q, DWORD rate, UINT nbits, UINT chns, UINT bufsize, LONG wd); - BOOL SetupDirectories(LPCSTR s, LPCSTR s2, LPCSTR s3); + BOOL SetupDirectories(LPCTSTR szModDir, LPCTSTR szSampleDir, LPCTSTR szInstrDir, LPCTSTR szVstDir, LPCTSTR szPresetDir); BOOL SetupPlayer(DWORD, DWORD, BOOL bForceUpdate=FALSE); BOOL SetupMidi(DWORD d, LONG n); void SetPreAmp(UINT n); @@ -570,6 +579,19 @@ BOOL ResetNotificationBuffer(HWND hwnd=NULL); +public: + // access to default + working directories + static void SetWorkingDirectory(const LPCTSTR szFilenameFrom, Directory dir, bool bStripFilename = false); + static LPCTSTR GetWorkingDirectory(Directory dir); + static void SetDefaultDirectory(const LPCTSTR szFilenameFrom, Directory dir, bool bStripFilename = false); + static LPCTSTR GetDefaultDirectory(Directory dir); +protected: + static void SetDirectory(const LPCTSTR szFilenameFrom, Directory dir, TCHAR (&pDirs)[NUM_DIRS][_MAX_PATH], bool bStripFilename); + // Directory Arrays (default dir + last dir) + static TCHAR m_szDefaultDirectory[NUM_DIRS][_MAX_PATH]; + static TCHAR m_szWorkingDirectory[NUM_DIRS][_MAX_PATH]; + + // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMainFrame) Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -550,15 +550,15 @@ OFN_HIDEREADONLY| OFN_ENABLESIZING | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN, lpszFilter, theApp.m_pMainWnd); - if (CMainFrame::m_szCurModDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurModDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_MODS); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + if (dlg.DoModal() != IDOK) return FALSE; strcpy(s, dlg.GetPathName()); + CMainFrame::SetWorkingDirectory(s, DIR_MODS, true); _splitpath(s, drive, path, fname, fext); - strcpy(CMainFrame::m_szCurModDir, drive); - strcat(CMainFrame::m_szCurModDir, path); } else { _splitpath(lpszPathName, drive, path, fname, NULL); @@ -1374,15 +1374,15 @@ CFileDialog dlg(FALSE, "wav", s, OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN, "Wave Files (*.wav)|*.wav||", pMainFrm); - dlg.m_ofn.lpstrInitialDir = pMainFrm->GetExportDir(); + dlg.m_ofn.lpstrInitialDir = CMainFrame::GetWorkingDirectory(DIR_EXPORT); CWaveConvert wsdlg(pMainFrm); if (wsdlg.DoModal() != IDOK) return; if (dlg.DoModal() != IDOK) return; //rewbs: made filename dialog appear after wav settings dialog - s[0] = 0; - _splitpath(dlg.GetPathName(), s, path, NULL, NULL); - strcat(s, path); - pMainFrm->SetExportDir(s); + + // will set default dir here because there's no setup option for export dir yet (feel free to add one...) + pMainFrm->SetDefaultDirectory(dlg.GetPathName(), DIR_EXPORT, true); + strcpy(s, dlg.GetPathName()); // Saving as wave file @@ -1505,16 +1505,17 @@ OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN, "MPEG Layer III Files (*.mp3)|*.mp3|Layer3 Wave Files (*.wav)|*.wav||", pMainFrm); dlg.m_ofn.nFilterIndex = 0; - dlg.m_ofn.lpstrInitialDir = pMainFrm->GetExportDir(); + + dlg.m_ofn.lpstrInitialDir = CMainFrame::GetWorkingDirectory(DIR_EXPORT); + if (dlg.DoModal() == IDOK) { MPEGLAYER3WAVEFORMAT wfx; HACMDRIVERID hadid; - s[0] = 0; - _splitpath(dlg.GetPathName(), s, path, NULL, NULL); - strcat(s, path); - pMainFrm->SetExportDir(s); + // will set default dir here because there's no setup option for export dir yet (feel free to add one...) + pMainFrm->SetDefaultDirectory(dlg.GetPathName(), DIR_EXPORT, true); + strcpy(s, dlg.GetPathName()); _splitpath(s, NULL, NULL, NULL, fext); if (strlen(fext) <= 1) Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -556,14 +556,17 @@ // COptionsGeneral BEGIN_MESSAGE_MAP(COptionsGeneral, CPropertyPage) - ON_EN_CHANGE(IDC_EDIT1, OnSettingsChanged) - ON_EN_CHANGE(IDC_EDIT2, OnSettingsChanged) - ON_EN_CHANGE(IDC_EDIT3, OnSettingsChanged) - ON_LBN_SELCHANGE(IDC_LIST1, OnOptionSelChanged) - ON_COMMAND(IDC_BUTTON1, OnBrowseSongs) - ON_COMMAND(IDC_BUTTON2, OnBrowseSamples) - ON_COMMAND(IDC_BUTTON3, OnBrowseInstruments) - ON_CLBN_CHKCHANGE(IDC_LIST1, OnSettingsChanged) + ON_EN_CHANGE(IDC_OPTIONS_DIR_MODS, OnSettingsChanged) + ON_EN_CHANGE(IDC_OPTIONS_DIR_SAMPS, OnSettingsChanged) + ON_EN_CHANGE(IDC_OPTIONS_DIR_INSTS, OnSettingsChanged) + ON_EN_CHANGE(IDC_OPTIONS_DIR_VSTPRESETS, OnSettingsChanged) + ON_LBN_SELCHANGE(IDC_LIST1, OnOptionSelChanged) + ON_COMMAND(IDC_BUTTON_CHANGE_MODDIR, OnBrowseSongs) + ON_COMMAND(IDC_BUTTON_CHANGE_SAMPDIR, OnBrowseSamples) + ON_COMMAND(IDC_BUTTON_CHANGE_INSTRDIR, OnBrowseInstruments) + ON_COMMAND(IDC_BUTTON_CHANGE_VSTDIR, OnBrowsePlugins) + ON_COMMAND(IDC_BUTTON_CHANGE_VSTPRESETSDIR, OnBrowsePresets) + ON_CLBN_CHKCHANGE(IDC_LIST1, OnSettingsChanged) END_MESSAGE_MAP() typedef struct OPTGENDESC @@ -711,9 +714,13 @@ } m_CheckList.SetCurSel(0); OnOptionSelChanged(); - SetDlgItemText(IDC_EDIT1, CMainFrame::m_szModDir); - SetDlgItemText(IDC_EDIT2, CMainFrame::m_szSmpDir); - SetDlgItemText(IDC_EDIT3, CMainFrame::m_szInsDir); + + SetDlgItemText(IDC_OPTIONS_DIR_MODS, CMainFrame::GetDefaultDirectory(DIR_MODS)); + SetDlgItemText(IDC_OPTIONS_DIR_SAMPS, CMainFrame::GetDefaultDirectory(DIR_SAMPLES)); + SetDlgItemText(IDC_OPTIONS_DIR_INSTS, CMainFrame::GetDefaultDirectory(DIR_INSTRUMENTS)); + SetDlgItemText(IDC_OPTIONS_DIR_VSTS, CMainFrame::GetDefaultDirectory(DIR_PLUGINS)); + SetDlgItemText(IDC_OPTIONS_DIR_VSTPRESETS, CMainFrame::GetDefaultDirectory(DIR_PLUGINPRESETS)); + return TRUE; } @@ -721,12 +728,16 @@ void COptionsGeneral::OnOK() //-------------------------- { - CHAR szModDir[_MAX_DIR], szSmpDir[_MAX_PATH], szInsDir[_MAX_PATH]; - szModDir[0] = szInsDir[0] = szSmpDir[0] = 0; - GetDlgItemText(IDC_EDIT1, szModDir, _MAX_PATH); - GetDlgItemText(IDC_EDIT2, szSmpDir, _MAX_PATH); - GetDlgItemText(IDC_EDIT3, szInsDir, _MAX_PATH); - for (UINT i=0; i<OPTGEN_MAXOPTIONS; i++) + // Default paths + TCHAR szModDir[_MAX_PATH], szSmpDir[_MAX_PATH], szInsDir[_MAX_PATH], szVstDir[_MAX_PATH], szPresetDir[_MAX_PATH]; + szModDir[0] = szInsDir[0] = szSmpDir[0] = szVstDir[0] = szPresetDir[0] = 0; + GetDlgItemText(IDC_OPTIONS_DIR_MODS, szModDir, _MAX_PATH); + GetDlgItemText(IDC_OPTIONS_DIR_SAMPS, szSmpDir, _MAX_PATH); + GetDlgItemText(IDC_OPTIONS_DIR_INSTS, szInsDir, _MAX_PATH); + GetDlgItemText(IDC_OPTIONS_DIR_VSTS, szVstDir, _MAX_PATH); + GetDlgItemText(IDC_OPTIONS_DIR_VSTPRESETS, szPresetDir, _MAX_PATH); + + for (UINT i=0; i < OPTGEN_MAXOPTIONS; i++) { DWORD mask = 0; BOOL bCheck = m_CheckList.GetCheck(i); @@ -774,7 +785,7 @@ CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); if (pMainFrm) { - pMainFrm->SetupDirectories(szModDir, szSmpDir, szInsDir); + pMainFrm->SetupDirectories(szModDir, szSmpDir, szInsDir, szVstDir, szPresetDir); pMainFrm->UpdateTree(NULL, HINT_MPTOPTIONS); } CPropertyPage::OnOK(); Modified: trunk/OpenMPT/mptrack/Moptions.h =================================================================== --- trunk/OpenMPT/mptrack/Moptions.h 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Moptions.h 2009-07-06 15:27:09 UTC (rev 281) @@ -35,9 +35,11 @@ virtual void DoDataExchange(CDataExchange* pDX); afx_msg void OnOptionSelChanged(); afx_msg void OnSettingsChanged() { SetModified(TRUE); } - afx_msg void OnBrowseSongs() { BrowseForFolder(IDC_EDIT1); } - afx_msg void OnBrowseSamples() { BrowseForFolder(IDC_EDIT2); } - afx_msg void OnBrowseInstruments() { BrowseForFolder(IDC_EDIT3); } + afx_msg void OnBrowseSongs() { BrowseForFolder(IDC_OPTIONS_DIR_MODS); } + afx_msg void OnBrowseSamples() { BrowseForFolder(IDC_OPTIONS_DIR_SAMPS); } + afx_msg void OnBrowseInstruments() { BrowseForFolder(IDC_OPTIONS_DIR_INSTS); } + afx_msg void OnBrowsePlugins() { BrowseForFolder(IDC_OPTIONS_DIR_VSTS); } + afx_msg void OnBrowsePresets() { BrowseForFolder(IDC_OPTIONS_DIR_VSTPRESETS); } //rewbs.customkeys: COptionsKeyboard moved to separate file DECLARE_MESSAGE_MAP(); Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -1277,10 +1277,11 @@ "All Files (*.*)|*.*||", NULL); dlg.m_ofn.nFilterIndex = CMainFrame::m_nFilterIndex; - if (CMainFrame::m_szCurModDir[0]) - { - dlg.m_ofn.lpstrInitialDir = CMainFrame::m_szCurModDir; - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_MODS); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + const size_t bufferSize = 2048; //Note: This is possibly the maximum buffer size in MFC 7(this note was written November 2006). vector<char> filenameBuffer(bufferSize, 0); dlg.GetOFN().lpstrFile = &filenameBuffer[0]; @@ -1290,11 +1291,8 @@ POSITION pos = dlg.GetStartPosition(); while(pos != NULL) { - CHAR szDrive[_MAX_PATH], szDir[_MAX_PATH]; CString pathName = dlg.GetNextPathName(pos); - _splitpath(pathName, szDrive, szDir, NULL, NULL); - strcpy(CMainFrame::m_szCurModDir, szDrive); - strcat(CMainFrame::m_szCurModDir, szDir); + CMainFrame::SetWorkingDirectory(pathName, DIR_MODS, true); CMainFrame::m_nFilterIndex = dlg.m_ofn.nFilterIndex; OpenDocumentFile(pathName); } Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -150,7 +150,7 @@ m_dwStatus |= TREESTATUS_SINGLEEXPAND; } ModifyStyle(dwRemove, dwAdd); - strcpy(m_szInstrLibPath, CMainFrame::m_szSmpDir); + strcpy(m_szInstrLibPath, CMainFrame::GetDefaultDirectory(DIR_SAMPLES)); SetImageList(CMainFrame::GetMainFrame()->GetImageList(), TVSIL_NORMAL); if (m_pDataTree) { @@ -1705,7 +1705,8 @@ if (!GetCurrentDirectory(sizeof(s), s)) s[0] = 0; if (!strcmp(lpszDir+1, ":\\")) { - strcpy(sdrive, lpszDir); + sdrive[0] = lpszDir[0]; + sdrive[1] = lpszDir[1]; sdrive[2] = 0; lpszDir = sdrive; } Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2009-07-06 15:27:09 UTC (rev 281) @@ -1376,15 +1376,11 @@ OFN_FILEMUSTEXIST|OFN_ENABLESIZING |OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_FORCESHOWHIDDEN|OFN_ALLOWMULTISELECT, "VST Plugins (*.dll)|*.dll||", this); - CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); - if (pMainFrm) - { - LPCSTR pszDir = pMainFrm->GetPluginsDir(); - if (pszDir[0]) - { - dlg.m_ofn.lpstrInitialDir = pszDir; - } - } + + const LPCTSTR pszWdir = CMainFrame::GetWorkingDirectory(DIR_PLUGINS); + if(pszWdir[0]) + dlg.m_ofn.lpstrInitialDir = pszWdir; + pszFileNames = new CHAR[MAX_FILEOPEN_BUFSIZE]; if (!pszFileNames) return; pszFileNames[0] = 0; @@ -1393,7 +1389,6 @@ dlg.m_ofn.nMaxFile = MAX_FILEOPEN_BUFSIZE; if (dlg.DoModal() == IDOK) { - CHAR s[_MAX_PATH], sdir[_MAX_PATH]; CVstPluginManager *pManager = theApp.GetPluginManager(); pszFileNames[MAX_FILEOPEN_BUFSIZE-1] = 0; POSITION pos = dlg.GetStartPosition(); @@ -1403,16 +1398,14 @@ PVSTPLUGINLIB plugLib = NULL; while (pos != NULL) { - CString str = dlg.GetNextPathName(pos); + CString sFilename = dlg.GetNextPathName(pos); if (!n) { - _splitpath(str, s, sdir, NULL, NULL); - strcat(s, sdir); - if (pMainFrm) pMainFrm->SetPluginsDir(s); + CMainFrame::SetWorkingDirectory(sFilename, DIR_PLUGINS, true); } n++; if (pManager) { - plugLib = pManager->AddPlugin(str, FALSE); + plugLib = pManager->AddPlugin(sFilename, FALSE); if (plugLib) { bOk = TRUE; } Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-07-06 15:27:09 UTC (rev 281) @@ -762,7 +762,7 @@ CTEXT "Length: 000000 (16-bit)",IDC_TEXT5,175,6,90,13, SS_CENTERIMAGE,WS_EX_STATICEDGE CONTROL "Toolbar2",IDC_TOOLBAR2,"ToolbarWindow32",WS_GROUP | - 0x4d,268,4,195,17 + 0x4d,268,4,186,17 GROUPBOX "",IDC_STATIC,3,22,94,78 LTEXT "Default Volume",IDC_STATIC,8,32,49,8 LTEXT "Global Volume",IDC_STATIC,8,45,46,8 @@ -1416,21 +1416,35 @@ CAPTION "General" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - GROUPBOX "Directories",IDC_STATIC,5,5,261,67 - LTEXT "Songs:",IDC_STATIC,15,20,36,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT1,59,20,174,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BUTTON1,240,20,12,11,NOT WS_TABSTOP - LTEXT "Samples:",IDC_STATIC,15,37,41,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT2,59,37,174,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BUTTON2,240,36,12,11,NOT WS_TABSTOP - LTEXT "Instruments:",IDC_STATIC,15,53,40,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT3,59,53,174,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BUTTON3,240,54,12,11,NOT WS_TABSTOP - GROUPBOX "Options",IDC_STATIC,4,75,261,200 - LTEXT "Description",IDC_TEXT1,144,86,111,175 - LISTBOX IDC_LIST1,9,86,129,181,LBS_OWNERDRAWFIXED | + GROUPBOX "Default Directories",IDC_STATIC,6,6,261,102 + RTEXT "Songs:",IDC_STATIC_MODDIR,12,18,48,12,SS_CENTERIMAGE + EDITTEXT IDC_OPTIONS_DIR_MODS,66,18,174,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_CHANGE_MODDIR,246,18,12,11,NOT + WS_TABSTOP + RTEXT "Samples:",IDC_STATIC_SAMPDIR,12,36,48,12,SS_CENTERIMAGE + EDITTEXT IDC_OPTIONS_DIR_SAMPS,66,36,174,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_CHANGE_SAMPDIR,246,36,12,11,NOT + WS_TABSTOP + RTEXT "Instruments:",IDC_STATIC_INSTRDIR,12,54,48,12, + SS_CENTERIMAGE + EDITTEXT IDC_OPTIONS_DIR_INSTS,66,54,174,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_CHANGE_INSTRDIR,246,54,12,11,NOT + WS_TABSTOP + GROUPBOX "Options",IDC_STATIC,4,114,261,161 + LTEXT "Description",IDC_TEXT1,144,126,111,138 + LISTBOX IDC_LIST1,9,126,129,141,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + RTEXT "VST Plugins:",IDC_STATIC_VSTDIR,12,72,48,12, + SS_CENTERIMAGE + EDITTEXT IDC_OPTIONS_DIR_VSTS,66,72,174,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_CHANGE_VSTDIR,246,72,12,11,NOT + WS_TABSTOP + RTEXT "VST Presets:",IDC_STATIC_VSTPRESETDIR,12,90,48,12, + SS_CENTERIMAGE + EDITTEXT IDC_OPTIONS_DIR_VSTPRESETS,66,90,174,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BUTTON_CHANGE_VSTPRESETSDIR,246,90,12,11,NOT + WS_TABSTOP END IDD_OPTIONS_SOUNDCARD DIALOGEX 0, 0, 272, 276 @@ -1438,7 +1452,6 @@ CAPTION "Sound Card" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - GROUPBOX "",IDC_STATIC,5,5,232,170 LTEXT "Sound Device:",IDC_STATIC,11,14,79,8 CONTROL "",IDC_COMBO1,"ComboBoxEx32",CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP,11,25,219,96 @@ -1472,6 +1485,7 @@ WS_TABSTOP,133,92,64,10 LTEXT "Note: The Pre-Amp and Soft Panning settings are ignored by songs with mix levels set to 1.17RC3 or later in Song Properties.", IDC_STATIC,17,152,204,18 + GROUPBOX "",IDC_STATIC,5,5,232,170 END IDD_MIDIMACRO DIALOGEX 0, 0, 349, 345 @@ -1930,24 +1944,24 @@ LTEXT "around current",IDC_STATIC,156,84,49,8 END -IDD_ADDSILENCE DIALOGEX 0, 0, 175, 63 +IDD_ADDSILENCE DIALOGEX 0, 0, 175, 71 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 + DEFPUSHBUTTON "OK",IDOK,120,12,50,14 + PUSHBUTTON "Cancel",IDCANCEL,120,30,50,14 + GROUPBOX "",IDC_STATIC,6,6,108,60 + EDITTEXT IDC_EDIT1,12,18,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 + UDS_NOTHOUSANDS,44,18,11,14 + LTEXT "samples",IDC_STATIC,59,21,35,8 CONTROL "At beginning of sample",IDC_RADIO1,"Button", - BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,32,89,10 + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,12,36,97,10 CONTROL "At end of sample",IDC_RADIO2,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,11,46,70,10 + BS_AUTORADIOBUTTON | WS_TABSTOP,12,48,97,10 END IDD_PATTERNRANDOMIZER_EFFECT DIALOGEX 0, 0, 235, 172 @@ -2239,7 +2253,7 @@ LEFTMARGIN, 7 RIGHTMARGIN, 168 TOPMARGIN, 7 - BOTTOMMARGIN, 56 + BOTTOMMARGIN, 64 END END Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-07-05 21:01:58 UTC (rev 280) +++ trunk/OpenMPT/mptrack/resource.h 2009-07-06 15:27:09 UTC (rev 281) @@ -830,6 +830,24 @@ #define IDC_DONTSHOWAGAIN 2341 #define IDC_MESSAGETEXT 2342 #define IDC_SAMPLE_DCOFFSET 2343 +#define IDC_OPTIONS_DIR_MODS 2344 +#define IDC_OPTIONS_DIR_SAMPS 2345 +#define IDC_OPTIONS_DIR_INSTS 2346 +#define IDC_OPTIONS_DIR_VSTS 2347 +#define IDC_STATIC_MODDIR 2348 +#define IDC_STATIC_SAMPDIR 2349 +#define IDC_STATIC_INSTRDIR 2350 +#define IDC_STATIC_VSTDIR 2351 +#define IDC_BUTTON_CHANGE_MODDIR 2352 +#define IDC_BUTTON_CHANGE_SAMPDIR 2353 +#define IDC_BUTTON_CHANGE_INSTRDIR 2354 +#define IDC_BUTTON_CHANGE_VSTDIR 2355 +#define IDC_STATIC_AUTOSAVE_OPTIONS 2356 +#define IDC_STATIC_AUTOSAVE_LOCATION 2357 +#define IDC_OPTIONS_DIR_VSTPRESETS 2357 +#define IDC_BUTTON_CHANGE_VSTDIR2 2358 +#define IDC_BUTTON_CHANGE_VSTPRESETSDIR 2358 +#define IDC_STATIC_VSTPRESETDIR 2359 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1067,7 +1085,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 518 #define _APS_NEXT_COMMAND_VALUE 59226 -#define _APS_NEXT_CONTROL_VALUE 2344 +#define _APS_NEXT_CONTROL_VALUE 2360 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-07-05 21:02:00
|
Revision: 280 http://modplug.svn.sourceforge.net/modplug/?rev=280&view=rev Author: relabsoluness Date: 2009-07-05 21:01:58 +0000 (Sun, 05 Jul 2009) Log Message: ----------- (patch from Jojo, merged somewhat modified) [New] Sample tab: DC offset removal. (merge edits: refactoring: moved implementation to modsmp_ctrl and added some helper functions). Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/Ctrl_smp.h trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/patterns.bmp trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/modsmp_ctrl.cpp trunk/OpenMPT/soundlib/modsmp_ctrl.h Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2009-07-05 21:01:58 UTC (rev 280) @@ -2328,6 +2328,11 @@ commands[kcNotePCS].isDummy = false; commands[kcNotePCS].Message = "Parameter control(smooth)(MPTm only)"; + commands[kcSampleRemoveDCOffset].UID = 1790; + commands[kcSampleRemoveDCOffset].Message = "Remove DC Offset"; + commands[kcSampleRemoveDCOffset].isHidden = false; + commands[kcSampleRemoveDCOffset].isDummy = false; + #ifdef _DEBUG for (int i=0; i<kcNumCommands; i++) { if (commands[i].UID != 0) { // ignore unset UIDs Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/CommandSet.h 2009-07-05 21:01:58 UTC (rev 280) @@ -572,7 +572,8 @@ kcSampleZoomDown, kcSampleInvert, kcSampleSignUnsign, - kcEndSampleEditing=kcSampleSignUnsign, + kcSampleRemoveDCOffset, + kcEndSampleEditing=kcSampleRemoveDCOffset, //kcSampStartNotes to kcInsNoteMapEndNoteStops must be contiguous. kcSampStartNotes, Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-07-05 21:01:58 UTC (rev 280) @@ -14,6 +14,7 @@ #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" #include "smbPitchShift.cpp" #pragma warning(default:4244) //"conversion from 'type1' to 'type2', possible loss of data" +#include "modsmp_ctrl.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -67,6 +68,7 @@ ON_COMMAND(IDC_SAMPLE_SILENCE, OnSilence) ON_COMMAND(IDC_SAMPLE_INVERT, OnInvert) ON_COMMAND(IDC_SAMPLE_SIGN_UNSIGN, OnSignUnSign) + ON_COMMAND(IDC_SAMPLE_DCOFFSET, OnRemoveDCOffset) ON_COMMAND(IDC_CHECK1, OnSetPanningChanged) ON_COMMAND(ID_PREVINSTRUMENT, OnPrevInstrument) ON_COMMAND(ID_NEXTINSTRUMENT, OnNextInstrument) @@ -207,6 +209,7 @@ m_ToolBar2.AddButton(IDC_SAMPLE_PLAY, 14); m_ToolBar2.AddButton(IDC_SAMPLE_NORMALIZE, 8); m_ToolBar2.AddButton(IDC_SAMPLE_AMPLIFY, 9); + m_ToolBar2.AddButton(IDC_SAMPLE_DCOFFSET, 37); m_ToolBar2.AddButton(IDC_SAMPLE_UPSAMPLE, 10); m_ToolBar2.AddButton(IDC_SAMPLE_DOWNSAMPLE, 29); m_ToolBar2.AddButton(IDC_SAMPLE_REVERSE, 11); @@ -469,6 +472,10 @@ OnSignUnSign(); break; + case IDC_SAMPLE_DCOFFSET: + OnRemoveDCOffset(); + break; + case IDC_SAMPLE_NORMALIZE: OnNormalize(); break; @@ -1046,8 +1053,8 @@ //Shift -> Normalize all samples if(CMainFrame::GetInputHandler()->ShiftPressed()) { - int ans = MessageBox(GetStrI18N(TEXT("This will normalize all samples independently. Continue?")), GetStrI18N(TEXT("Normalize")), MB_YESNO | MB_ICONQUESTION); - if(ans == IDNO) return; + if(MessageBox(GetStrI18N(TEXT("This will normalize all samples independently. Continue?")), GetStrI18N(TEXT("Normalize")), MB_YESNO | MB_ICONQUESTION) == IDNO) + return; iMinSample = 1; iMaxSample = m_pSndFile->m_nSamples; } else { @@ -1203,6 +1210,89 @@ } +void CCtrlSamples::OnRemoveDCOffset() +//----------------------------------- +{ + if(!m_pModDoc || !m_pSndFile) + return; + + SAMPLEVIEWSTATE viewstate; + UINT iMinSample = m_nSample, iMaxSample = m_nSample; + + memset(&viewstate, 0, sizeof(viewstate)); + SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&viewstate); + + //Shift -> Process all samples + if(CMainFrame::GetInputHandler()->ShiftPressed()) + { + if(MessageBox(GetStrI18N(TEXT("This will process all samples independently. Continue?")), GetStrI18N(TEXT("DC Offset Removal")), MB_YESNO | MB_ICONQUESTION) == IDNO) + return; + iMinSample = 1; + iMaxSample = m_pSndFile->m_nSamples; + } + + BeginWaitCursor(); + + // for report / SetModified + UINT iModified = 0; + float fReportOffset = 0; + + for(UINT iSmp = iMinSample; iSmp <= iMaxSample; iSmp++) + { + UINT iStart, iEnd; + + if( m_pSndFile->Ins[iSmp].pSample == nullptr ) + continue; + + if (iMinSample != iMaxSample) + { + iStart = 0; + iEnd = m_pSndFile->Ins[iSmp].nLength; + } + else + { + iStart = viewstate.dwBeginSel; + iEnd = viewstate.dwEndSel; + } + const float fOffset = ctrlSmp::RemoveDCOffset(m_pSndFile->Ins[iSmp], iStart, iEnd, m_pSndFile->GetType(), m_pSndFile); + + if(fOffset == 0.0f) // No offset removed. + continue; + + fReportOffset += fOffset; + iModified++; + m_pModDoc->UpdateAllViews(NULL, (iSmp << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO, NULL); + } + + EndWaitCursor(); + SwitchToView(); + + // fill the statusbar with some nice information + + CString dcInfo; + if(iModified) + { + m_pModDoc->SetModified(); + if(iModified == 1) + { + dcInfo.Format(GetStrI18N(TEXT("Removed DC offset (%.1f%%)")), fReportOffset * 100); + } + else + { + dcInfo.Format(GetStrI18N(TEXT("Removed DC offset from %d samples (avg %0.1f%%)")), iModified, fReportOffset / iModified * 100); + } + } + else + { + dcInfo.SetString(GetStrI18N(TEXT("No DC offset found"))); + } + + CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); + pMainFrm->SetXInfoText(dcInfo); + +} + + void CCtrlSamples::OnAmplify() //---------------------------- { Modified: trunk/OpenMPT/mptrack/Ctrl_smp.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.h 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/Ctrl_smp.h 2009-07-05 21:01:58 UTC (rev 280) @@ -72,6 +72,7 @@ afx_msg void OnSamplePlay(); afx_msg void OnNormalize(); afx_msg void OnAmplify(); + afx_msg void OnRemoveDCOffset(); afx_msg void OnUpsample(); afx_msg void OnDownsample(); afx_msg void OnReverse(); Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2009-07-05 21:01:58 UTC (rev 280) @@ -2543,12 +2543,13 @@ case kcSampleSave: PostCtrlMessage(IDC_SAMPLE_SAVEAS); return wParam; case kcSampleNew: PostCtrlMessage(IDC_SAMPLE_NEW); return wParam; - case kcSampleReverse: PostCtrlMessage(IDC_SAMPLE_REVERSE); return wParam; - case kcSampleSilence: PostCtrlMessage(IDC_SAMPLE_SILENCE); return wParam; - case kcSampleNormalize: PostCtrlMessage(IDC_SAMPLE_NORMALIZE); return wParam; - case kcSampleAmplify: PostCtrlMessage(IDC_SAMPLE_AMPLIFY); return wParam; - case kcSampleInvert: PostCtrlMessage(IDC_SAMPLE_INVERT); return wParam; - case kcSampleSignUnsign: PostCtrlMessage(IDC_SAMPLE_SIGN_UNSIGN); return wParam; + case kcSampleReverse: PostCtrlMessage(IDC_SAMPLE_REVERSE); return wParam; + case kcSampleSilence: PostCtrlMessage(IDC_SAMPLE_SILENCE); return wParam; + case kcSampleNormalize: PostCtrlMessage(IDC_SAMPLE_NORMALIZE); return wParam; + case kcSampleAmplify: PostCtrlMessage(IDC_SAMPLE_AMPLIFY); return wParam; + case kcSampleInvert: PostCtrlMessage(IDC_SAMPLE_INVERT); return wParam; + case kcSampleSignUnsign: PostCtrlMessage(IDC_SAMPLE_SIGN_UNSIGN); return wParam; + case kcSampleRemoveDCOffset: PostCtrlMessage(IDC_SAMPLE_DCOFFSET); return wParam; case kcNoteOff: PlayNote(NOTE_KEYOFF); return wParam; case kcNoteCut: PlayNote(NOTE_NOTECUT); return wParam; Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-07-05 21:01:58 UTC (rev 280) @@ -762,7 +762,7 @@ CTEXT "Length: 000000 (16-bit)",IDC_TEXT5,175,6,90,13, SS_CENTERIMAGE,WS_EX_STATICEDGE CONTROL "Toolbar2",IDC_TOOLBAR2,"ToolbarWindow32",WS_GROUP | - 0x4d,268,4,164,17 + 0x4d,268,4,195,17 GROUPBOX "",IDC_STATIC,3,22,94,78 LTEXT "Default Volume",IDC_STATIC,8,32,49,8 LTEXT "Global Volume",IDC_STATIC,8,45,46,8 @@ -2487,6 +2487,11 @@ STRINGTABLE BEGIN + IDC_SAMPLE_DCOFFSET "Remove DC Offset\nRemove DC Offset and normalize (hold shift to process all samples)" +END + +STRINGTABLE +BEGIN ID_ENVELOPE_SETLOOP "Enable or disable the envelope loop" ID_ENVELOPE_SUSTAIN "Enable or disable the envelope sustain" ID_ENVELOPE_INSERTPOINT "Insert a new point in the envelope at the current location" @@ -2499,6 +2504,11 @@ ID_PATTERN_PLAYROW "Play current row\nPlay Row" ID_IMPORT_MIDILIB "Defines the default MIDI library used when importing MIDI files" ID_CLEANUP_REARRANGE "Rearrange all patterns so that they are sorted in the order list\nRearrange Patterns" +END + +STRINGTABLE +BEGIN + ID_EDIT_GOTO_MENU "Go to row / channel / pattern / order" ID_CLEANUP_COMPO "Reset attributes to defaults (useful for creating sample packs)\nCompo Cleanup" END @@ -2585,11 +2595,6 @@ IDS_OPERATION_FAIL "Operation failed." END -STRINGTABLE -BEGIN - ID_EDIT_GOTO_MENU "Go to row / channel / pattern / order" -END - #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/res/patterns.bmp =================================================================== (Binary files differ) Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/mptrack/resource.h 2009-07-05 21:01:58 UTC (rev 280) @@ -829,6 +829,7 @@ #define IDC_MIDIPLAYPATTERNONMIDIIN 2340 #define IDC_DONTSHOWAGAIN 2341 #define IDC_MESSAGETEXT 2342 +#define IDC_SAMPLE_DCOFFSET 2343 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1066,7 +1067,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 518 #define _APS_NEXT_COMMAND_VALUE 59226 -#define _APS_NEXT_CONTROL_VALUE 2343 +#define _APS_NEXT_CONTROL_VALUE 2344 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.cpp =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-07-05 21:01:58 UTC (rev 280) @@ -170,4 +170,125 @@ } +namespace +{ + struct OffsetData + { + double dMax, dMin, dOffset; + }; + + // Returns maximum sample amplitude for given sample type (int8/int16). + template <class T> + double GetMaxAmplitude() {return 1.0 + (std::numeric_limits<T>::max)();} + + // Calculates DC offset and returns struct with DC offset, max and min values. + // DC offset value is average of [-1.0, 1.0[-normalized offset values. + template<class T> + OffsetData CalculateOffset(const T* pStart, const SmpLength nLength) + //------------------------------------------------------------------ + { + OffsetData offsetVals = {0,0,0}; + + if(nLength < 1) + return offsetVals; + + const double dMaxAmplitude = GetMaxAmplitude<T>(); + + double dMax = -1, dMin = 1, dSum = 0; + + const T* p = pStart; + for (SmpLength i = 0; i < nLength; i++, p++) + { + const double dVal = double(*p) / dMaxAmplitude; + dSum += dVal; + if(dVal > dMax) dMax = dVal; + if(dVal < dMin) dMin = dVal; + } + + offsetVals.dMax = dMax; + offsetVals.dMin = dMin; + offsetVals.dOffset = (-dSum / (double)(nLength)); + return offsetVals; + } + + template <class T> + void RemoveOffsetAndNormalize(T* pStart, const SmpLength nLength, const double dOffset, const double dAmplify) + //------------------------------------------------------------------------------------------------------------ + { + T* p = pStart; + for (UINT i = 0; i < nLength; i++, p++) + { + double dVal = (*p) * dAmplify + dOffset; + Limit(dVal, (std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)()); + *p = static_cast<T>(dVal); + } + } +}; + +// Remove DC offset +float RemoveDCOffset(MODINSTRUMENT& smp, + SmpLength iStart, + SmpLength iEnd, + const MODTYPE modtype, + CSoundFile* const pSndFile) +//---------------------------------------------- +{ + if(smp.pSample == nullptr || smp.nLength < 1) + return 0; + + MODINSTRUMENT* const pins = &smp; + + if (iEnd > pins->nLength) iEnd = pins->nLength; + if (iStart > iEnd) iStart = iEnd; + if (iStart == iEnd) + { + iStart = 0; + iEnd = pins->nLength; + } + + iStart *= pins->GetNumChannels(); + iEnd *= pins->GetNumChannels(); + + const double dMaxAmplitude = (pins->GetElementarySampleSize() == 2) ? GetMaxAmplitude<int16>() : GetMaxAmplitude<int8>(); + + // step 1: Calculate offset. + OffsetData oData = {0,0,0}; + if(pins->GetElementarySampleSize() == 2) + oData = CalculateOffset(reinterpret_cast<int16*>(pins->pSample) + iStart, iEnd - iStart); + else if(pins->GetElementarySampleSize() == 1) + oData = CalculateOffset(reinterpret_cast<int8*>(pins->pSample) + iStart, iEnd - iStart); + + double dMin = oData.dMin, dMax = oData.dMax, dOffset = oData.dOffset; + + const float fReportOffset = (float)dOffset; + + if((int)(dOffset * dMaxAmplitude) == 0) + return 0; + + // those will be changed... + dMax += dOffset; + dMin += dOffset; + + // ... and that might cause distortion, so we will normalize this. + const double dAmplify = 1 / max(dMax, -dMin); + + // step 2: centralize + normalize sample + dOffset *= dMaxAmplitude * dAmplify; + if(pins->GetElementarySampleSize() == 2) + RemoveOffsetAndNormalize( reinterpret_cast<int16*>(pins->pSample) + iStart, iEnd - iStart, dOffset, dAmplify); + else if(pins->GetElementarySampleSize() == 1) + RemoveOffsetAndNormalize( reinterpret_cast<int8*>(pins->pSample) + iStart, iEnd - iStart, dOffset, dAmplify); + + // step 3: adjust either global vol or default vol of this sample + if(modtype == MOD_TYPE_IT || modtype == MOD_TYPE_MPT) + pins->nGlobalVol = min((WORD)(pins->nGlobalVol / dAmplify), 64); + else if(modtype != MOD_TYPE_NONE) + pins->nVolume = min((WORD)(pins->nVolume / dAmplify), 256); + + AdjustEndOfSample(smp, pSndFile); + + return fReportOffset; +} + + } // namespace ctrlSmp Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.h =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.h 2009-07-01 20:02:20 UTC (rev 279) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.h 2009-07-05 21:01:58 UTC (rev 280) @@ -35,6 +35,16 @@ // Resets samples. void ResetSamples(CSoundFile& rSndFile, ResetFlag resetflag); -} +// Remove DC offset and normalize. +// Return: If DC offset was removed, returns original offset value, zero otherwise. +float RemoveDCOffset(MODINSTRUMENT& smp, + SmpLength iStart, // Start position (for partial DC offset removal). + SmpLength iEnd, // End position (for partial DC offset removal). + const MODTYPE modtype, // Used to determine whether to adjust global or default volume + // to keep volume level the same given the normalization. + // Volume adjustment is not done if this param is MOD_TYPE_NONE. + CSoundFile* const pSndFile); // Passed to AdjustEndOfSample. +} // Namespace ctrlSmp + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-07-01 20:02:40
|
Revision: 279 http://modplug.svn.sourceforge.net/modplug/?rev=279&view=rev Author: relabsoluness Date: 2009-07-01 20:02:20 +0000 (Wed, 01 Jul 2009) Log Message: ----------- (patches from Jojo, merged somewhat modified) [Fix] GDM import: GDM files now show in the load dialogs, MOD transpose/finetune related fix, Endian fixes. [Imp] Sample tab: Better loop point handling when deleting sample selections. [Fix] Sample tab: Transpose is now disabled when using MOD format. [Mod] General: Changes to default general options configuration. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/soundlib/Load_gdm.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-06-29 20:56:43 UTC (rev 278) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-07-01 20:02:20 UTC (rev 279) @@ -599,6 +599,9 @@ m_CheckPanning.EnableWindow(b && !(m_pSndFile->GetType() & MOD_TYPE_XM)); m_EditPanning.EnableWindow(b); m_SpinPanning.EnableWindow(b); + + b = (m_pSndFile->m_nType & MOD_TYPE_MOD) ? FALSE : TRUE; + m_CbnBaseNote.EnableWindow(b); } // Updating Values if (dwHintMask & (HINT_MODTYPE|HINT_SAMPLEINFO)) Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-06-29 20:56:43 UTC (rev 278) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-07-01 20:02:20 UTC (rev 279) @@ -200,7 +200,8 @@ DWORD CMainFrame::m_dwPatternSetup = PATTERN_PLAYNEWNOTE | PATTERN_EFFECTHILIGHT | PATTERN_SMALLFONT | PATTERN_CENTERROW | PATTERN_AUTOSPACEBAR | PATTERN_DRAGNDROPEDIT | PATTERN_FLATBUTTONS - | PATTERN_2NDHIGHLIGHT | PATTERN_STDHIGHLIGHT | PATTERN_HILITETIMESIGS; + | PATTERN_2NDHIGHLIGHT | PATTERN_STDHIGHLIGHT | PATTERN_HILITETIMESIGS + | PATTERN_SHOWPREVIOUS | PATTERN_CONTSCROLL | PATTERN_SYNCMUTE | PATTERN_AUTODELAY | PATTERN_NOTEFADE; DWORD CMainFrame::m_nRowSpacing = 16; DWORD CMainFrame::m_nRowSpacing2 = 4; Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-29 20:56:43 UTC (rev 278) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-07-01 20:02:20 UTC (rev 279) @@ -1253,11 +1253,12 @@ // -> CODE#0023 // -> DESC="IT project files (.itp)" // "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.bak;*.umx;*.amf;*.psm;*.mt2|" +// "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.bak;*.umx;*.amf;*.psm;*.mt2;*.gdm|" #ifndef NO_MO3_SUPPORT - "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.itp;*.mptm;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.umx;*.amf;*.psm;*.mt2;*.mo3|" + "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.itp;*.mptm;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.umx;*.amf;*.psm;*.mt2;*.gdm;*.mo3|" "Compressed Modules (*.mdz;*.s3z;*.xmz;*.itz;*.mo3)|*.mdz;*.s3z;*.xmz;*.itz;*.mdr;*.zip;*.rar;*.lha;*.mo3|" #else - "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.itp;*.mptm;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.umx;*.amf;*.psm;*.mt2|" + "All Modules|*.mod;*.nst;*.wow;*.s3m;*.stm;*.669;*.mtm;*.xm;*.it;*.itp;*.mptm;*.ult;*.mdz;*.s3z;*.xmz;*.itz;mod.*;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.mdr;*.med;*.ams;*.dbm;*.dsm;*.mid;*.rmi;*.smf;*.umx;*.amf;*.psm;*.mt2;*.gdm|" "Compressed Modules (*.mdz;*.s3z;*.xmz;*.itz)|*.mdz;*.s3z;*.xmz;*.itz;*.mdr;*.zip;*.rar;*.lha|" #endif // -! NEW_FEATURE#0023 @@ -1270,7 +1271,7 @@ "Impulse Tracker Projects (*.itp)|*.itp;*.itpz|" // -! NEW_FEATURE#0023 "OpenMPT Modules (*.mptm)|*.mptm;*.mptmz|" - "Other Modules (mtm,okt,mdl,669,far,...)|*.mtm;*.669;*.ult;*.wow;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.med;*.ams;*.dbm;*.dsm;*.umx;*.amf;*.psm;*.mt2|" + "Other Modules (mtm,okt,mdl,669,far,...)|*.mtm;*.669;*.ult;*.wow;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.med;*.ams;*.dbm;*.dsm;*.umx;*.amf;*.psm;*.mt2;*.gdm|" "Wave Files (*.wav)|*.wav|" "Midi Files (*.mid,*.rmi)|*.mid;*.rmi;*.smf|" "All Files (*.*)|*.*||", Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2009-06-29 20:56:43 UTC (rev 278) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2009-07-01 20:02:20 UTC (rev 279) @@ -1704,6 +1704,31 @@ p[i] = (i+cutlen < iend) ? p[i+cutlen] : (char)0; } len = pins->nLength; + + // adjust loop points (could need some optimization) + if(m_dwBeginSel < pins->nLoopStart && m_dwEndSel < pins->nLoopStart) + { + // cut part is before loop start + pins->nLoopStart -= m_dwEndSel - m_dwBeginSel; + pins->nLoopEnd -= m_dwEndSel - m_dwBeginSel; + } + else if(m_dwBeginSel < pins->nLoopStart && m_dwEndSel < pins->nLoopEnd) + { + // cut part is partly before loop start + pins->nLoopStart = m_dwBeginSel; + pins->nLoopEnd -= m_dwEndSel - m_dwBeginSel; + } + else if(m_dwBeginSel > pins->nLoopStart && m_dwEndSel < pins->nLoopEnd) + { + // cut part is in the loop + pins->nLoopEnd -= m_dwEndSel - m_dwBeginSel; + } + else if(m_dwBeginSel > pins->nLoopStart && m_dwBeginSel < pins->nLoopEnd && m_dwEndSel > pins->nLoopEnd) + { + // cut part is partly before loop end + pins->nLoopEnd = m_dwBeginSel; + } + if (pins->nLoopEnd > len) pins->nLoopEnd = len; if (pins->nLoopStart + 4 >= pins->nLoopEnd) { Modified: trunk/OpenMPT/soundlib/Load_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp 2009-06-29 20:56:43 UTC (rev 278) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2009-07-01 20:02:20 UTC (rev 279) @@ -29,8 +29,8 @@ UINT16 TrackID; // Composing Tracker ID code (00 = 2GDM) BYTE TrackMajorVer; // Tracker's major version BYTE TrackMinorVer; // Tracker's minor version - BYTE PanMap[32]; // 0-Left to 15-Right, 255-N/U - BYTE MastVol; // Range: 0...64 + BYTE PanMap[32]; // 0-Left to 15-Right, 255-N/U + BYTE MastVol; // Range: 0...64 BYTE Tempo; // Initial music tempo (6) BYTE BPM; // Initial music BPM (125) UINT16 FormOrigin; // Original format ID: @@ -38,32 +38,32 @@ // (versions of 2GDM prior to v1.15 won't set this correctly) UINT32 OrdOffset; - BYTE NOO; // Number of orders in module - 1 + BYTE NOO; // Number of orders in module - 1 UINT32 PatOffset; - BYTE NOP; // Number of patterns in module - 1 + BYTE NOP; // Number of patterns in module - 1 UINT32 SamHeadOffset; UINT32 SamOffset; - BYTE NOS; // Number of samples in module - 1 - UINT32 MTOffset; // Offset of song message + BYTE NOS; // Number of samples in module - 1 + UINT32 MTOffset; // Offset of song message UINT32 MTLength; - UINT32 SSOffset; // Offset of scrolly script (huh?) + UINT32 SSOffset; // Offset of scrolly script (huh?) UINT16 SSLength; - UINT32 TGOffset; // Offset of text graphic (huh?) + UINT32 TGOffset; // Offset of text graphic (huh?) UINT16 TGLength; } GDMHEADER, *PGDMHEADER; typedef struct _GDMSAMPLEHEADER { - CHAR SamName[32]; - CHAR FileName[12]; + CHAR SamName[32]; // sample's name + CHAR FileName[12]; // sample's filename BYTE EmsHandle; // useless - UINT32 Length; - UINT32 LoopBegin; - UINT32 LoopEnd; - BYTE Flags; - UINT16 C4Hertz; - BYTE Volume; - BYTE Pan; + UINT32 Length; // length in bytes + UINT32 LoopBegin; // loop start in samples + UINT32 LoopEnd; // loop end in samples + BYTE Flags; // misc. flags + UINT16 C4Hertz; // frequency + BYTE Volume; // default volume + BYTE Pan; // default pan } GDMSAMPLEHEADER, *PGDMSAMPLEHEADER; BOOL CSoundFile::ReadGDM(const LPCBYTE lpStream, const DWORD dwMemLength) @@ -90,7 +90,7 @@ return FALSE; } - // todo: Is TrackID, TrackMajorVer, TrackMinorVer relevant? The only TrackID should be 0 - 2GDM.exe + // interesting question: Is TrackID, TrackMajorVer, TrackMinorVer relevant? The only TrackID should be 0 - 2GDM.exe, so the answer would be no. // read channel pan map... 0...15 = channel panning, 16 = surround channel, 255 = channel does not exist m_nChannels = 32; @@ -121,7 +121,7 @@ // 1-MOD, 2-MTM, 3-S3M, 4-669, 5-FAR, 6-ULT, 7-STM, 8-MED - switch(pHeader->FormOrigin) + switch(LittleEndianW(pHeader->FormOrigin)) { case 1: m_nType = MOD_TYPE_MOD; @@ -152,29 +152,36 @@ return FALSE; break; } + UINT32 iSampleOffset = LittleEndian(pHeader->SamOffset), + iPatternsOffset = LittleEndian(pHeader->PatOffset); + const UINT32 iOrdOffset = LittleEndian(pHeader->OrdOffset), iSamHeadOffset = LittleEndian(pHeader->SamHeadOffset), + iMTOffset = LittleEndian(pHeader->MTOffset), iMTLength = LittleEndian(pHeader->MTLength), + iSSOffset = LittleEndian(pHeader->SSOffset), iSSLength = LittleEndianW(pHeader->SSLength), + iTGOffset = LittleEndian(pHeader->TGOffset), iTGLength = LittleEndianW(pHeader->TGLength); + + // check if offsets are valid. we won't read the scrolly text or text graphics, but invalid pointers would probably indicate a broken file... - if( dwMemLength < pHeader->OrdOffset || dwMemLength - pHeader->OrdOffset < pHeader->NOO - || dwMemLength < pHeader->PatOffset - || dwMemLength < pHeader->SamHeadOffset || dwMemLength - pHeader->SamHeadOffset < (pHeader->NOS + 1) * sizeof(GDMSAMPLEHEADER) - || dwMemLength < pHeader->SamOffset - || dwMemLength < pHeader->MTOffset || dwMemLength - pHeader->MTOffset < pHeader->MTLength - || dwMemLength < pHeader->SSOffset || dwMemLength - pHeader->SSOffset < pHeader->SSLength - || dwMemLength < pHeader->TGOffset || dwMemLength - pHeader->TGOffset < pHeader->TGLength) + if( dwMemLength < iOrdOffset || dwMemLength - iOrdOffset < pHeader->NOO + || dwMemLength < iPatternsOffset + || dwMemLength < iSamHeadOffset || dwMemLength - iSamHeadOffset < (pHeader->NOS + 1) * sizeof(GDMSAMPLEHEADER) + || dwMemLength < iSampleOffset + || dwMemLength < iMTOffset || dwMemLength - iMTOffset < iMTLength + || dwMemLength < iSSOffset || dwMemLength - iSSOffset < iSSLength + || dwMemLength < iTGOffset || dwMemLength - iTGOffset < iTGLength) return FALSE; // read orders - Order.ReadAsByte(lpStream + pHeader->OrdOffset, pHeader->NOO + 1, dwMemLength - pHeader->OrdOffset); + Order.ReadAsByte(lpStream + iOrdOffset, pHeader->NOO + 1, dwMemLength - iOrdOffset); // read samples m_nSamples = pHeader->NOS + 1; - DWORD iSampleOffset = pHeader->SamOffset; int iLZWsamples = 0; for(UINT iSmp = 1; iSmp <= m_nSamples; iSmp++) { - const PGDMSAMPLEHEADER pSample = (PGDMSAMPLEHEADER)(lpStream + pHeader->SamHeadOffset + (iSmp - 1) * sizeof(GDMSAMPLEHEADER)); + const PGDMSAMPLEHEADER pSample = (PGDMSAMPLEHEADER)(lpStream + iSamHeadOffset + (iSmp - 1) * sizeof(GDMSAMPLEHEADER)); // sample header @@ -182,13 +189,31 @@ SetNullTerminator(m_szNames[iSmp]); memcpy(Ins[iSmp].name, pSample->FileName, 12); - Ins[iSmp].nC4Speed = pSample->C4Hertz; + Ins[iSmp].nC4Speed = LittleEndianW(pSample->C4Hertz); Ins[iSmp].nGlobalVol = 256; // not supported in this format - Ins[iSmp].nLength = min(pSample->Length, MAX_SAMPLE_LENGTH); // in bytes - Ins[iSmp].nLoopStart = min(pSample->LoopBegin, Ins[iSmp].nLength); // in samples - Ins[iSmp].nLoopEnd = min(pSample->LoopEnd - 1, Ins[iSmp].nLength); // dito + Ins[iSmp].nLength = min(LittleEndian(pSample->Length), MAX_SAMPLE_LENGTH); // in bytes + Ins[iSmp].nLoopStart = min(LittleEndian(pSample->LoopBegin), Ins[iSmp].nLength); // in samples + Ins[iSmp].nLoopEnd = min(LittleEndian(pSample->LoopEnd) - 1, Ins[iSmp].nLength); // dito FrequencyToTranspose(&Ins[iSmp]); // set transpose + finetune for mod files + // fix transpose + finetune for some rare cases where transpose is not C-5 (e.g. sample 4 in wander2.mod) + if(m_nType == MOD_TYPE_MOD) + { + while(Ins[iSmp].RelativeTone != 0) + { + if(Ins[iSmp].RelativeTone > 0) + { + Ins[iSmp].RelativeTone -= 1; + Ins[iSmp].nFineTune += 128; + } + else + { + Ins[iSmp].RelativeTone += 1; + Ins[iSmp].nFineTune -= 128; + } + } + } + if(pSample->Flags & 0x01) Ins[iSmp].uFlags |= CHN_LOOP; // loop sample if(pSample->Flags & 0x04) @@ -243,23 +268,21 @@ // read sample data ReadSample(&Ins[iSmp], iSampleFormat, reinterpret_cast<LPCSTR>(lpStream + iSampleOffset), dwMemLength - iSampleOffset); - iSampleOffset += min(pSample->Length, dwMemLength - iSampleOffset); + iSampleOffset += min(LittleEndian(pSample->Length), dwMemLength - iSampleOffset); } // read patterns Patterns.ResizeArray(max(MAX_PATTERNS, pHeader->NOP + 1)); - // position in file - DWORD iPatternsOffset = pHeader->PatOffset; - BOOL bS3MCommandSet = (GetBestSaveFormat() & (MOD_TYPE_S3M | MOD_TYPE_IT | MOD_TYPE_MPT)); + // we'll start at position iPatternsOffset and decode all patterns for (PATTERNINDEX iPat = 0; iPat < pHeader->NOP + 1; iPat++) { if(iPatternsOffset + 2 > dwMemLength) break; - UINT16 iPatternLength = *(UINT16 *)(lpStream + iPatternsOffset); // pattern length including the two "length" bytes + UINT16 iPatternLength = LittleEndianW(*(UINT16 *)(lpStream + iPatternsOffset)); // pattern length including the two "length" bytes if(iPatternLength > dwMemLength || iPatternsOffset > dwMemLength - iPatternLength) break; if(Patterns.Insert(iPat, 64)) @@ -510,13 +533,13 @@ } // read song comments - if(pHeader->MTLength) + if(iMTLength) { - m_lpszSongComments = new char[pHeader->MTLength + 1]; + m_lpszSongComments = new char[iMTLength + 1]; if (m_lpszSongComments) { - memset(m_lpszSongComments, 0, pHeader->MTLength + 1); - memcpy(m_lpszSongComments, lpStream + pHeader->MTOffset, pHeader->MTLength); + memset(m_lpszSongComments, 0, iMTLength + 1); + memcpy(m_lpszSongComments, lpStream + iMTOffset, iMTLength); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-29 20:57:37
|
Revision: 278 http://modplug.svn.sourceforge.net/modplug/?rev=278&view=rev Author: relabsoluness Date: 2009-06-29 20:56:43 +0000 (Mon, 29 Jun 2009) Log Message: ----------- [Ref] Minor changes (use of note constants, aligned MODCHANNEL, moved command definitions to modcommand.h, simplified CSoundFile::GetNoteName, updated CVstPlugin when building with NO_VST). Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/soundlib/Mmx_mix.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/modcommand.h Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -950,7 +950,7 @@ if ((nPlugin) && (nPlugin <= MAX_MIXPLUGINS)) { IMixPlugin *pPlugin = m_SndFile.m_MixPlugins[nPlugin-1].pMixPlugin; - if (pPlugin) pPlugin->MidiCommand(penv->nMidiChannel, penv->nMidiProgram, penv->wMidiBank, note+0xFF, 0, MAX_BASECHANNELS); + if (pPlugin) pPlugin->MidiCommand(penv->nMidiChannel, penv->nMidiProgram, penv->wMidiBank, note+NOTE_KEYOFF, 0, MAX_BASECHANNELS); } } @@ -1017,7 +1017,7 @@ CVstPlugin *pPlug = (CVstPlugin*)m_SndFile.m_MixPlugins[nPlug-1].pMixPlugin; INSTRUMENTHEADER* penv = m_SndFile.Chn[nChn].pHeader; if (pPlug && penv) { - pPlug->MidiCommand(penv->nMidiChannel, penv->nMidiProgram, penv->wMidiBank, 0xFF, 0, nChn); + pPlug->MidiCommand(penv->nMidiChannel, penv->nMidiProgram, penv->wMidiBank, NOTE_KEYOFF, 0, nChn); } } } else { Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -707,7 +707,7 @@ m_pDocManager = new CModDocManager(); #ifdef _DEBUG - // ASSERT((sizeof(MODCHANNEL)&7) == 0); + ASSERT((sizeof(MODCHANNEL)&7) == 0); // Disabled by rewbs for smoothVST. Might cause minor perf issues due to increased cache misses? #endif Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -3879,7 +3879,7 @@ { ins = m_nSplitInstrument; if (m_bOctaveLink) note += 12*(m_nOctaveModifier-9); - if (note > NOTE_MAX && note<254) note = NOTE_MAX; + if (note > NOTE_MAX && note < NOTE_NOTECUT) note = NOTE_MAX; if (note<0) note=1; } if (!ins) ins = GetCurrentInstrument(); @@ -4536,7 +4536,7 @@ if(GetCurrentInstrument()) p->instr = GetCurrentInstrument(); if (m_bOctaveLink) note += 12*(m_nOctaveModifier-9); - if (note > NOTE_MAX && note<254) note = NOTE_MAX; + if (note > NOTE_MAX && note < NOTE_NOTECUT) note = NOTE_MAX; if (note<0) note=1; p->note = note; Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -2647,12 +2647,12 @@ // Specific Note Off - if (note > 0xFF) //rewbs.vstiLive + if (note > NOTE_KEYOFF) //rewbs.vstiLive { dwMidiCode = 0x80|nCh; //note off, on chan nCh note--; - UINT i = note - 0xFF; + UINT i = note - NOTE_KEYOFF; if (pCh->uNoteOnMap[i][trackChannel]) { pCh->uNoteOnMap[i][trackChannel]--; @@ -2663,7 +2663,7 @@ // "Hard core" All Sounds Off on this midi and tracker channel // This one doesn't check the note mask - just one note off per note. // Also less likely to cause a VST event buffer overflow. - else if (note == 0xFE) // ^^ + else if (note == NOTE_NOTECUT) // ^^ { //MidiSend(0xB0|nCh|(0x79<<8)); // reset all controllers MidiSend(0xB0|nCh|(0x7b<<8)); // all notes off Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/mptrack/Vstplug.h 2009-06-29 20:56:43 UTC (rev 278) @@ -204,10 +204,10 @@ VOID GetPluginType(LPSTR) {} long GetNumPrograms() {return 0;} long GetProgramNameIndexed(long, long, char*) {return 0;} - VOID SetParameter(UINT, FLOAT) {} + VOID SetParameter(PlugParamIndex nIndex, PlugParamValue fValue) {} VOID GetParamLabel(UINT, LPSTR) {} VOID GetParamDisplay(UINT, LPSTR) {} - FLOAT GetParameter(UINT) {return 0;} + PlugParamValue GetParameter(PlugParamIndex nIndex) {return 0;} bool LoadProgram(CString) {return false;} bool SaveProgram(CString) {return false;} VOID SetCurrentProgram(UINT) {} Modified: trunk/OpenMPT/soundlib/Mmx_mix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Mmx_mix.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/soundlib/Mmx_mix.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -161,7 +161,7 @@ { CHAR s[64]; wsprintf(s, "MODCHANNEL not aligned: sizeof(MODCHANNEL) = %d", sizeof(MODCHANNEL)); - //::MessageBox(NULL, s, NULL, MB_OK|MB_ICONEXCLAMATION); //disabled by rewbs + ::MessageBox(NULL, s, NULL, MB_OK|MB_ICONEXCLAMATION); //disabled by rewbs } DWORD dwFastSinc = (DWORD)(LPVOID)gFastSinc; if (dwFastSinc & 7) Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -939,7 +939,7 @@ //switch off duplicated note played on this plugin IMixPlugin *pPlugin = m_MixPlugins[pHeader->nMixPlug-1].pMixPlugin; if (pPlugin && p->nNote) - pPlugin->MidiCommand(p->pHeader->nMidiChannel, p->pHeader->nMidiProgram, p->pHeader->wMidiBank, p->nNote+0xFF, 0, i); + pPlugin->MidiCommand(p->pHeader->nMidiChannel, p->pHeader->nMidiProgram, p->pHeader->wMidiBank, p->nNote+NOTE_KEYOFF, 0, i); break; } } @@ -1027,7 +1027,7 @@ case NNA_NOTEFADE: //switch off note played on this plugin, on this tracker channel and midi channel //pPlugin->MidiCommand(pChn->pHeader->nMidiChannel, pChn->pHeader->nMidiProgram, pChn->nNote+0xFF, 0, n); - pPlugin->MidiCommand(pChn->pHeader->nMidiChannel, pChn->pHeader->nMidiProgram, pChn->pHeader->wMidiBank, /*pChn->nNote+*/0xFF, 0, nChn); + pPlugin->MidiCommand(pChn->pHeader->nMidiChannel, pChn->pHeader->nMidiProgram, pChn->pHeader->wMidiBank, /*pChn->nNote+*/NOTE_KEYOFF, 0, nChn); break; } } @@ -3030,7 +3030,7 @@ if ((nPlug) && (nPlug <= MAX_MIXPLUGINS)) { IMixPlugin *pPlug = (IMixPlugin*)m_MixPlugins[nPlug-1].pMixPlugin; if (pPlug) { - pPlug->MidiCommand(pHeader->nMidiChannel, pHeader->nMidiProgram, pHeader->wMidiBank, /*pChn->nNote+*/0xFF, 0, nChn); + pPlug->MidiCommand(pHeader->nMidiChannel, pHeader->nMidiProgram, pHeader->wMidiBank, /*pChn->nNote+*/NOTE_KEYOFF, 0, nChn); } } } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-29 20:56:43 UTC (rev 278) @@ -2876,14 +2876,14 @@ string CSoundFile::GetNoteName(const CTuning::NOTEINDEXTYPE& note, const int inst) const //---------------------------------------------------------------------------------- { - if(inst >= MAX_INSTRUMENTS || inst < -1) return "BUG"; + if(inst >= MAX_INSTRUMENTS || inst < -1 || note < 1 || note > NOTE_MAX) return "BUG"; if(inst == -1) - return string(szNoteNames[abs(note-1)%12]) + Stringify((note-1)/12); + return szDefaultNoteNames[note-1]; if(m_nType == MOD_TYPE_MPT && Headers[inst] && Headers[inst]->pTuning) return Headers[inst]->pTuning->GetNoteName(note-NOTE_MIDDLEC); else - return string(szNoteNames[abs(note-1)%12]) + Stringify((note-1)/12); + return szDefaultNoteNames[note-1]; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-29 20:56:43 UTC (rev 278) @@ -162,44 +162,6 @@ #define ENV_PITCHCARRY 0x2000 #define ENV_MUTE 0x4000 -#define CMD_NONE 0 -#define CMD_ARPEGGIO 1 -#define CMD_PORTAMENTOUP 2 -#define CMD_PORTAMENTODOWN 3 -#define CMD_TONEPORTAMENTO 4 -#define CMD_VIBRATO 5 -#define CMD_TONEPORTAVOL 6 -#define CMD_VIBRATOVOL 7 -#define CMD_TREMOLO 8 -#define CMD_PANNING8 9 -#define CMD_OFFSET 10 -#define CMD_VOLUMESLIDE 11 -#define CMD_POSITIONJUMP 12 -#define CMD_VOLUME 13 -#define CMD_PATTERNBREAK 14 -#define CMD_RETRIG 15 -#define CMD_SPEED 16 -#define CMD_TEMPO 17 -#define CMD_TREMOR 18 -#define CMD_MODCMDEX 19 -#define CMD_S3MCMDEX 20 -#define CMD_CHANNELVOLUME 21 -#define CMD_CHANNELVOLSLIDE 22 -#define CMD_GLOBALVOLUME 23 -#define CMD_GLOBALVOLSLIDE 24 -#define CMD_KEYOFF 25 -#define CMD_FINEVIBRATO 26 -#define CMD_PANBRELLO 27 -#define CMD_XFINEPORTAUPDOWN 28 -#define CMD_PANNINGSLIDE 29 -#define CMD_SETENVPOSITION 30 -#define CMD_MIDI 31 -#define CMD_SMOOTHMIDI 32 //rewbs.smoothVST -#define CMD_VELOCITY 33 //rewbs.velocity -// -> CODE#0010 -// -> DESC="add extended parameter mechanism to pattern effects" -#define CMD_XPARAM 34 -// -! NEW_FEATURE#0010 // Filter Modes #define FLTMODE_UNCHANGED 0xFF @@ -207,22 +169,6 @@ #define FLTMODE_HIGHPASS 1 #define FLTMODE_BANDPASS 2 -// Volume Column commands -#define VOLCMD_VOLUME 1 -#define VOLCMD_PANNING 2 -#define VOLCMD_VOLSLIDEUP 3 -#define VOLCMD_VOLSLIDEDOWN 4 -#define VOLCMD_FINEVOLUP 5 -#define VOLCMD_FINEVOLDOWN 6 -#define VOLCMD_VIBRATOSPEED 7 -#define VOLCMD_VIBRATO 8 -#define VOLCMD_PANSLIDELEFT 9 -#define VOLCMD_PANSLIDERIGHT 10 -#define VOLCMD_TONEPORTAMENTO 11 -#define VOLCMD_PORTAUP 12 -#define VOLCMD_PORTADOWN 13 -#define VOLCMD_VELOCITY 14 //rewbs.velocity -#define VOLCMD_OFFSET 15 //rewbs.volOff #define RSF_16BIT 0x04 #define RSF_STEREO 0x08 @@ -544,7 +490,7 @@ // Channel Struct -typedef struct _MODCHANNEL +typedef struct __declspec(align(32)) _MODCHANNEL { // First 32-bytes: Most used mixing information: don't change it LPSTR pCurrentSample; @@ -584,9 +530,9 @@ LONG nVolSwing, nPanSwing; LONG nCutSwing, nResSwing; LONG nRestorePanOnNewNote; //If > 0, nPan should be set to nRestorePanOnNewNote - 1 on new note. Used to recover from panswing. - LONG nRestoreResonanceOnNewNote; //Like above - LONG nRestoreCutoffOnNewNote; //Like above // 8-bit members + BYTE nRestoreResonanceOnNewNote; //Like above + BYTE nRestoreCutoffOnNewNote; //Like above BYTE nNote, nNNA; BYTE nNewNote, nNewIns, nCommand, nArpeggio; BYTE nOldVolumeSlide, nOldFineVolUpDown; @@ -607,11 +553,11 @@ BYTE nLeftVU, nRightVU; BYTE nActiveMacro, nFilterMode; + uint16 m_RowPlugParam; //NOTE_PCs memory. float m_nPlugParamValueStep; //rewbs.smoothVST float m_nPlugInitialParamValue; //rewbs.smoothVST - long m_RowPlugParam; //NOTE_PCs memory. PLUGINDEX m_RowPlug; //NOTE_PCs memory. - + void ClearRowCmd() {nRowNote = 0; nRowInstr = 0; nRowVolCmd = 0; nRowVolume = 0; nRowCommand = 0; nRowParam = 0;} typedef UINT VOLUME; Modified: trunk/OpenMPT/soundlib/modcommand.h =================================================================== --- trunk/OpenMPT/soundlib/modcommand.h 2009-06-25 21:53:49 UTC (rev 277) +++ trunk/OpenMPT/soundlib/modcommand.h 2009-06-29 20:56:43 UTC (rev 278) @@ -69,4 +69,60 @@ #define NOTE_MIN_SPECIAL NOTE_PCS +// Volume Column commands +#define VOLCMD_VOLUME 1 +#define VOLCMD_PANNING 2 +#define VOLCMD_VOLSLIDEUP 3 +#define VOLCMD_VOLSLIDEDOWN 4 +#define VOLCMD_FINEVOLUP 5 +#define VOLCMD_FINEVOLDOWN 6 +#define VOLCMD_VIBRATOSPEED 7 +#define VOLCMD_VIBRATO 8 +#define VOLCMD_PANSLIDELEFT 9 +#define VOLCMD_PANSLIDERIGHT 10 +#define VOLCMD_TONEPORTAMENTO 11 +#define VOLCMD_PORTAUP 12 +#define VOLCMD_PORTADOWN 13 +#define VOLCMD_VELOCITY 14 //rewbs.velocity +#define VOLCMD_OFFSET 15 //rewbs.volOff + + +// Effect column commands +#define CMD_NONE 0 +#define CMD_ARPEGGIO 1 +#define CMD_PORTAMENTOUP 2 +#define CMD_PORTAMENTODOWN 3 +#define CMD_TONEPORTAMENTO 4 +#define CMD_VIBRATO 5 +#define CMD_TONEPORTAVOL 6 +#define CMD_VIBRATOVOL 7 +#define CMD_TREMOLO 8 +#define CMD_PANNING8 9 +#define CMD_OFFSET 10 +#define CMD_VOLUMESLIDE 11 +#define CMD_POSITIONJUMP 12 +#define CMD_VOLUME 13 +#define CMD_PATTERNBREAK 14 +#define CMD_RETRIG 15 +#define CMD_SPEED 16 +#define CMD_TEMPO 17 +#define CMD_TREMOR 18 +#define CMD_MODCMDEX 19 +#define CMD_S3MCMDEX 20 +#define CMD_CHANNELVOLUME 21 +#define CMD_CHANNELVOLSLIDE 22 +#define CMD_GLOBALVOLUME 23 +#define CMD_GLOBALVOLSLIDE 24 +#define CMD_KEYOFF 25 +#define CMD_FINEVIBRATO 26 +#define CMD_PANBRELLO 27 +#define CMD_XFINEPORTAUPDOWN 28 +#define CMD_PANNINGSLIDE 29 +#define CMD_SETENVPOSITION 30 +#define CMD_MIDI 31 +#define CMD_SMOOTHMIDI 32 //rewbs.smoothVST +#define CMD_VELOCITY 33 //rewbs.velocity +#define CMD_XPARAM 34 // -> CODE#0010 -> DESC="add extended parameter mechanism to pattern effects" -! NEW_FEATURE#0010 + + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-25 21:53:59
|
Revision: 277 http://modplug.svn.sourceforge.net/modplug/?rev=277&view=rev Author: relabsoluness Date: 2009-06-25 21:53:49 +0000 (Thu, 25 Jun 2009) Log Message: ----------- (merged from devBranch_1_17_03 with some additional modifications) [New] Pattern tab: New experimental parameter controls for controlling plug params(only in mptm). Is more or less fully functional except that the commands won't be saved to file. Includes modifications/additions to: keyshortcuts, various GUI components, pattern draw methods, clipboard handling, pattern editing functions, ProcessEffects(). [Mod] Pattern tab: Added some checks to prevent entering notes which are not supported by the module type. Refactoring -Find/Replace dialog: Added enums for special items. -Disabled keyconfig log messages. -Modification to IMixPlugin for easier parameter control. -Created new note name arrays and functions for populating comboboxes with note names. -Removed constructor from modcommand and instrumentheader. -ProcessMidiOut() now takes modcommand data from modchannel. -Various smaller changes (removed compiler warning etc.) Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/mod2midi.cpp trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/res/view_pat.bmp trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/mptrack/test/test.h trunk/OpenMPT/mptrack/typedefs.h trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/OrderToPatternTable.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp trunk/OpenMPT/soundlib/mod_specifications.h trunk/OpenMPT/soundlib/modcommand.h Added Paths: ----------- trunk/OpenMPT/soundlib/mod_specifications.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -5,6 +5,15 @@ #include <stdio.h> #include <stdlib.h> +#define ENABLE_LOGGING 0 + +#if(ENABLE_LOGGING) + // +#else + #define Log +#endif + + bool CCommandSet::s_bShowErrorOnUnknownKeybinding = true; CCommandSet::CCommandSet(void) @@ -2309,6 +2318,16 @@ commands[kcSwitchEchoPaste].isHidden = false; commands[kcSwitchEchoPaste].isDummy = false; + commands[kcNotePC].UID = 1788; + commands[kcNotePC].isHidden = false; + commands[kcNotePC].isDummy = false; + commands[kcNotePC].Message = "Parameter control(MPTm only)"; + + commands[kcNotePCS].UID = 1789; + commands[kcNotePCS].isHidden = false; + commands[kcNotePCS].isDummy = false; + commands[kcNotePCS].Message = "Parameter control(smooth)(MPTm only)"; + #ifdef _DEBUG for (int i=0; i<kcNumCommands; i++) { if (commands[i].UID != 0) { // ignore unset UIDs @@ -2438,7 +2457,7 @@ { //World's biggest, most confusing method. :) //Needs refactoring. Maybe make lots of Rule subclasses, each with their own Enforce() method? - bool removing = !adding; //for attempt to salvage readability.. + //bool removing = !adding; //for attempt to salvage readability.. KeyCombination curKc; // for looping through key combinations KeyCombination newKc; // for adding new key combinations CString report=""; @@ -2544,7 +2563,7 @@ { KeyCombination newKcDeSel; bool ruleApplies=true; - CommandID cmdOff; + CommandID cmdOff = kcNull; switch (inCmd) { @@ -2942,7 +2961,7 @@ if (IsDummyCommand((CommandID)cmd)) continue; - for (UINT k=0; k<commands[cmd].kcList.GetSize(); k++) + for (INT_PTR k=0; k<commands[cmd].kcList.GetSize(); k++) { contexts.RemoveAll(); eventTypes.RemoveAll(); @@ -2969,7 +2988,7 @@ contexts.Add(curKc.ctx); } - long label = 0; + //long label = 0; for (int cx=0; cx<contexts.GetSize(); cx++) { for (int ke=0; ke<eventTypes.GetSize(); ke++) { km[contexts[cx]][curKc.mod][curKc.code][eventTypes[ke]] = (CommandID)cmd; @@ -2992,7 +3011,7 @@ BYTE ctxCode = (BYTE)ctx; BYTE modCode = (BYTE)mod; BYTE codeCode = (BYTE)code; - BYTE keCode = (BYTE)ke; + //BYTE keCode = (BYTE)ke; DWORD label = ctxCode | (modCode<<8) | (codeCode<<16) | (ke<<24); @@ -3187,7 +3206,7 @@ { for (int i=0; i<kcNumCommands; i++) { - if (commands[i].UID == uid) + if (commands[i].UID == static_cast<UINT>(uid)) return i; } @@ -3270,7 +3289,7 @@ CString CCommandSet::GetKeyTextFromCommand(CommandID c, UINT key) { - if (key < commands[c].kcList.GetSize()) + if ( static_cast<INT_PTR>(key) < commands[c].kcList.GetSize()) return GetKeyText(commands[c].kcList[0].mod, commands[c].kcList[0].code); else return ""; @@ -3396,6 +3415,7 @@ void CCommandSet::GetParentContexts(InputTargetContext child, CArray<InputTargetContext, InputTargetContext> parentList) { + UNREFERENCED_PARAMETER(child); //parentList.RemoveAll(); //for (InputTargetContext parent; parent<kCtxMaxInputContexts; parent++) { @@ -3407,6 +3427,7 @@ void CCommandSet::GetChildContexts(InputTargetContext parent, CArray<InputTargetContext, InputTargetContext> childList) { + UNREFERENCED_PARAMETER(parent); //childList.RemoveAll(); //for (InputTargetContext child; child<kCtxMaxInputContexts; child++) { Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/CommandSet.h 2009-06-25 21:53:49 UTC (rev 277) @@ -433,7 +433,9 @@ kcNoteOff, kcNoteCutOld, kcNoteOffOld, - kcEndNoteMisc=kcNoteOffOld, + kcNotePC, + kcNotePCS, + kcEndNoteMisc=kcNotePCS, //Set instruments Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -822,11 +822,7 @@ // Pitch/Pan Separation m_SpinPPS.SetRange(-32, +32); // Pitch/Pan Center - for (UINT n=0; n<=NOTE_MAX; n++) - { - wsprintf(s, "%s%d", szNoteNames[n % 12], n/12); - m_ComboPPC.SetItemData(m_ComboPPC.AddString(s), n); - } + AppendNotesToControl(m_ComboPPC, 0, NOTE_MAX-1); // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -200,11 +200,8 @@ //CHAR s[8]; CHAR s[10]; - for(int i = 0 ; i < NOTE_MAX ; i++){ - wsprintf(s, "%s%d", szNoteNames[i % 12], i/12); - int n = m_CbnSplitNote.AddString(s); - m_CbnSplitNote.SetItemData(n, i); - } + AppendNotesToControl(m_CbnSplitNote, 0, NOTE_MAX - 1); + m_nSplitInstrument = 0; m_nSplitNote = 60; m_CbnSplitNote.SetCurSel(m_nSplitNote); Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -329,7 +329,15 @@ { m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 14*COLUMN_HEIGHT); } else + if(note >= NOTE_PC) { + m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 15*COLUMN_HEIGHT); + } else + if(note >= NOTE_PCS) + { + m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 16*COLUMN_HEIGHT); + } else + { if(pTuning) { // Drawing custom note names string noteStr = pTuning->GetNoteName(note-NOTE_MIDDLEC); @@ -387,24 +395,40 @@ } -void CViewPattern::DrawVolumeCommand(int x, int y, UINT volcmd, UINT vol) -//----------------------------------------------------------------------- +void CViewPattern::DrawVolumeCommand(int x, int y, const MODCOMMAND mc) +//--------------------------------------------------------------------- { PCPATTERNFONT pfnt = GetCurrentPatternFont(); - if (volcmd) - { - volcmd &= 0x0F; - vol &= 0x7F; - m_Dib.TextBlt(x, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, - pfnt->nVolX, pfnt->nVolY+volcmd*COLUMN_HEIGHT); + + if(mc.note == NOTE_PCS || mc.note == NOTE_PC) + { //If note is parameter control note, drawing volume command differently. + const int val = min(MODCOMMAND::maxColumnValue, mc.GetValueVolCol()); + + m_Dib.TextBlt(x, y, 1, COLUMN_HEIGHT, pfnt->nClrX, pfnt->nClrY); + m_Dib.TextBlt(x + 1, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(val / 100)*COLUMN_HEIGHT); m_Dib.TextBlt(x+pfnt->nVolCmdWidth, y, pfnt->nVolHiWidth, COLUMN_HEIGHT, - pfnt->nNumX, pfnt->nNumY+(vol / 10)*COLUMN_HEIGHT); + pfnt->nNumX, pfnt->nNumY+((val / 10)%10)*COLUMN_HEIGHT); m_Dib.TextBlt(x+pfnt->nVolCmdWidth+pfnt->nVolHiWidth, y, pfnt->nEltWidths[2]-(pfnt->nVolCmdWidth+pfnt->nVolHiWidth), COLUMN_HEIGHT, - pfnt->nNumX, pfnt->nNumY+(vol % 10)*COLUMN_HEIGHT); - } else + pfnt->nNumX, pfnt->nNumY+(val % 10)*COLUMN_HEIGHT); + } + else { - int srcx = pfnt->nEltWidths[0] + pfnt->nEltWidths[1]; - m_Dib.TextBlt(x, y, pfnt->nEltWidths[2], COLUMN_HEIGHT, pfnt->nClrX+srcx, pfnt->nClrY); + if (mc.volcmd) + { + const int volcmd = (mc.volcmd & 0x0F); + const int vol = (mc.vol & 0x7F); + m_Dib.TextBlt(x, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, + pfnt->nVolX, pfnt->nVolY+volcmd*COLUMN_HEIGHT); + m_Dib.TextBlt(x+pfnt->nVolCmdWidth, y, pfnt->nVolHiWidth, COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(vol / 10)*COLUMN_HEIGHT); + m_Dib.TextBlt(x+pfnt->nVolCmdWidth+pfnt->nVolHiWidth, y, pfnt->nEltWidths[2]-(pfnt->nVolCmdWidth+pfnt->nVolHiWidth), COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(vol % 10)*COLUMN_HEIGHT); + } else + { + int srcx = pfnt->nEltWidths[0] + pfnt->nEltWidths[1]; + m_Dib.TextBlt(x, y, pfnt->nEltWidths[2], COLUMN_HEIGHT, pfnt->nClrX+srcx, pfnt->nClrY); + } } } @@ -780,8 +804,19 @@ MODCOMMAND *mold = m - ncols; if (m->note == mold->note) dwSpeedUpMask |= 0x01; if ((m->instr == mold->instr) || (m_nDetailLevel < 1)) dwSpeedUpMask |= 0x02; - if (((m->volcmd == mold->volcmd) && ((!m->volcmd) || (m->vol == mold->vol))) || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; - if ((m->command == mold->command) || (m_nDetailLevel < 3)) dwSpeedUpMask |= (m->command) ? 0x08 : 0x18; + if ( m->note == NOTE_PCS || m->note == NOTE_PC || mold->note == NOTE_PCS || mold->note == NOTE_PC ) + { // Handle speedup mask for PC notes. + if(m->note == mold->note) + { + if(m->GetValueVolCol() == mold->GetValueVolCol() || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; + if(m->GetValueEffectCol() == mold->GetValueEffectCol() || (m_nDetailLevel < 3)) dwSpeedUpMask |= 0x18; + } + } + else + { + if (((m->volcmd == mold->volcmd) && ((!m->volcmd) || (m->vol == mold->vol))) || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; + if ((m->command == mold->command) || (m_nDetailLevel < 3)) dwSpeedUpMask |= (m->command) ? 0x08 : 0x18; + } if (dwSpeedUpMask == 0x1F) goto DoBlit; } bColSel[col] |= 0x40; @@ -857,7 +892,7 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } else - if ((m->volcmd) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) + if (m->note != NOTE_PCS && m->note != NOTE_PC && (m->volcmd) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) { switch(m->volcmd) { @@ -886,15 +921,18 @@ } // Drawing Volume m_Dib.SetTextColor(tx_col, bk_col); - DrawVolumeCommand(xbmp+x, 0, m->volcmd, m->vol); + DrawVolumeCommand(xbmp+x, 0, *m); } x += pfnt->nEltWidths[2]; } // Command & param if (m_nDetailLevel > 2) { + const bool isPCnote = (m->note == NOTE_PC || m->note == NOTE_PCS); + uint16 val = m->GetValueEffectCol(); + if(val > MODCOMMAND::maxColumnValue) val = MODCOMMAND::maxColumnValue; fx_col = row_col; - if ((m->command) && (m->command < MAX_EFFECTS) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) + if (!isPCnote && (m->command) && (m->command < MAX_EFFECTS) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) { switch(gEffectColors[m->command]) { @@ -921,17 +959,26 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } + // Drawing Command m_Dib.SetTextColor(tx_col, bk_col); - if (m->command) + if(isPCnote) { - UINT command = m->command & 0x3F; - int n = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands[command] : gszS3mCommands[command]; - if (n <= ' ') n = '?'; - DrawLetter(xbmp+x, 0, (char)n, pfnt->nEltWidths[3], pfnt->nCmdOfs); - } else + m_Dib.TextBlt(xbmp + x, 0, 2, COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + m_Dib.TextBlt(xbmp + x + 2, 0, pfnt->nEltWidths[3], m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(val / 100)*COLUMN_HEIGHT); + } + else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + if (m->command) + { + UINT command = m->command & 0x3F; + int n = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands[command] : gszS3mCommands[command]; + if (n <= ' ') n = '?'; + DrawLetter(xbmp+x, 0, (char)n, pfnt->nEltWidths[3], pfnt->nCmdOfs); + } else + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + } } } x += pfnt->nEltWidths[3]; @@ -945,15 +992,24 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } + // Drawing param m_Dib.SetTextColor(tx_col, bk_col); - if (m->command) + if(isPCnote) { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(m->param >> 4)*COLUMN_HEIGHT); - m_Dib.TextBlt(xbmp+x+pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(m->param & 0x0F)*COLUMN_HEIGHT); - } else + m_Dib.TextBlt(xbmp + x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+((val / 10) % 10)*COLUMN_HEIGHT); + m_Dib.TextBlt(xbmp + x + pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(val % 10)*COLUMN_HEIGHT); + } + else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX+x, pfnt->nClrY); + if (m->command) + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(m->param >> 4)*COLUMN_HEIGHT); + m_Dib.TextBlt(xbmp+x+pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(m->param & 0x0F)*COLUMN_HEIGHT); + } else + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX+x, pfnt->nClrY); + } } } } @@ -1396,59 +1452,65 @@ pMainFrm->SetUserText(s); if (::GetFocus() == m_hWnd) { - nChn = (m_dwCursor & 0xFFFF) >> 3; + nChn = GetChanFromCursor(m_dwCursor); s[0] = 0; if ((!(m_dwStatus & (PATSTATUS_KEYDRAGSEL/*|PATSTATUS_MOUSEDRAGSEL*/))) //rewbs.xinfo: update indicator even when dragging && (m_dwBeginSel == m_dwEndSel) && (pSndFile->Patterns[m_nPattern]) && (m_nRow < pSndFile->PatternSize[m_nPattern]) && (nChn < pSndFile->m_nChannels)) { MODCOMMAND *m = &pSndFile->Patterns[m_nPattern][m_nRow*pSndFile->m_nChannels+nChn]; - switch (m_dwCursor & 7) + + // Ignore update if using PC or PCs notes because instrument, volcol and effect values + // have different meaning. + if(m->note != NOTE_PC && m->note != NOTE_PCS) { - case 1: - if (m->instr) + switch (GetColTypeFromCursor(m_dwCursor)) { - CHAR sztmp[128] = ""; - if (pSndFile->m_nInstruments) + case 1: + if (m->instr) { - if ((m->instr <= pSndFile->m_nInstruments) && (pSndFile->Headers[m->instr])) + CHAR sztmp[128] = ""; + if (pSndFile->m_nInstruments) { - INSTRUMENTHEADER *penv = pSndFile->Headers[m->instr]; - memcpy(sztmp, penv->name, 32); - sztmp[32] = 0; - if ((m->note) && (m->note <= NOTE_MAX)) + if ((m->instr <= pSndFile->m_nInstruments) && (pSndFile->Headers[m->instr])) { - UINT nsmp = penv->Keyboard[m->note-1]; - if ((nsmp) && (nsmp <= pSndFile->m_nSamples)) + INSTRUMENTHEADER *penv = pSndFile->Headers[m->instr]; + memcpy(sztmp, penv->name, 32); + sztmp[32] = 0; + if ((m->note) && (m->note <= NOTE_MAX)) { - CHAR sztmp2[64] = ""; - memcpy(sztmp2, pSndFile->m_szNames[nsmp], 32); - sztmp2[32] = 0; - if (sztmp2[0]) + UINT nsmp = penv->Keyboard[m->note-1]; + if ((nsmp) && (nsmp <= pSndFile->m_nSamples)) { - wsprintf(sztmp+strlen(sztmp), " (%d: %s)", nsmp, sztmp2); + CHAR sztmp2[64] = ""; + memcpy(sztmp2, pSndFile->m_szNames[nsmp], 32); + sztmp2[32] = 0; + if (sztmp2[0]) + { + wsprintf(sztmp+strlen(sztmp), " (%d: %s)", nsmp, sztmp2); + } } } } - } - } else - { - if (m->instr <= pSndFile->m_nSamples) + } else { - memcpy(sztmp, pSndFile->m_szNames[m->instr], 32); - sztmp[32] = 0; + if (m->instr <= pSndFile->m_nSamples) + { + memcpy(sztmp, pSndFile->m_szNames[m->instr], 32); + sztmp[32] = 0; + } } + if (sztmp[0]) wsprintf(s, "%d: %s", m->instr, sztmp); } - if (sztmp[0]) wsprintf(s, "%d: %s", m->instr, sztmp); + break; + case 2: + if (!pModDoc->GetVolCmdInfo(pModDoc->GetIndexFromVolCmd(m->volcmd), s)) s[0] = 0; + break; + case 3: + case 4: + if (!pModDoc->GetEffectName(s, m->command, m->param, FALSE, nChn)) s[0] = 0; + break; } - break; - case 2: - if (!pModDoc->GetVolCmdInfo(pModDoc->GetIndexFromVolCmd(m->volcmd), s)) s[0] = 0; - break; - case 3: - case 4: - if (!pModDoc->GetEffectName(s, m->command, m->param, FALSE, nChn)) s[0] = 0; - break; } } pMainFrm->SetInfoText(s); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -1598,7 +1598,7 @@ pattern = "Fast Tracker Files (*.xm)|*.xm||"; break;*/ case MOD_TYPE_MOD: - ext = MOD_STD_SPECS.fileExtension; + ext = ModSpecs::mod.fileExtension; pattern = FileFilterMOD; if( AfxMessageBox(GetStrI18N(TEXT( "Compared to regular MOD save, compatibility export makes " @@ -1610,7 +1610,7 @@ return; break; case MOD_TYPE_IT: - ext = IT_STD_SPECS.fileExtension; + ext = ModSpecs::it.fileExtension; pattern = FileFilterIT; ::MessageBox(NULL,"Warning: the exported file will not contain any of MPT's file-format hacks.", "Compatibility export warning.",MB_ICONINFORMATION | MB_OK); break; Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -20,7 +20,19 @@ #define str_mptm_conversion_warning GetStrI18N(_TEXT("Conversion from mptm to any other moduletype may makes certain features unavailable and is not guaranteed to work properly. Do the conversion anyway?")) +const size_t Pow10Table[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; +// Return D'th digit(character) of given value. +// GetDigit<0>(123) == '3' +// GetDigit<1>(123) == '2' +// GetDigit<2>(123) == '1' +template<BYTE D> +inline TCHAR GetDigit(const size_t val) +{ + return (D > 9) ? '0' : 48 + ((val / Pow10Table[D]) % 10); +} + + ////////////////////////////////////////////////////////////////////// // Module type conversion @@ -1578,6 +1590,8 @@ case 0: p[1] = p[2] = p[3] = '.'; break; case NOTE_KEYOFF: p[1] = p[2] = p[3] = '='; break; case NOTE_NOTECUT: p[1] = p[2] = p[3] = '^'; break; + case NOTE_PC: p[1] = 'P'; p[2] = 'C'; p[3] = ' '; break; + case NOTE_PCS: p[1] = 'P'; p[2] = 'C'; p[3] = 'S'; break; default: p[1] = szNoteNames[(note-1) % 12][0]; p[2] = szNoteNames[(note-1) % 12][1]; @@ -1605,12 +1619,22 @@ ncursor++; if ((ncursor >= colmin) && (ncursor <= colmax)) { - if ((m->volcmd) && (m->volcmd <= MAX_VOLCMDS)) + if(m->note == NOTE_PC || m->note == NOTE_PCS) { - p[6] = gszVolCommands[m->volcmd]; - p[7] = '0' + (m->vol / 10); - p[8] = '0' + (m->vol % 10); - } else p[6] = p[7] = p[8] = '.'; + const uint16 val = m->GetValueVolCol(); + p[6] = GetDigit<2>(val); + p[7] = GetDigit<1>(val); + p[8] = GetDigit<0>(val); + } + else + { + if ((m->volcmd) && (m->volcmd <= MAX_VOLCMDS)) + { + p[6] = gszVolCommands[m->volcmd]; + p[7] = '0' + (m->vol / 10); + p[8] = '0' + (m->vol % 10); + } else p[6] = p[7] = p[8] = '.'; + } } else { p[6] = p[7] = p[8] = ' '; @@ -1620,18 +1644,28 @@ if (((ncursor >= colmin) && (ncursor <= colmax)) || ((ncursor+1 >= colmin) && (ncursor+1 <= colmax))) { - if (m->command) + if(m->note == NOTE_PC || m->note == NOTE_PCS) { - if (m_SndFile.m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT)) - p[9] = gszS3mCommands[m->command]; - else - p[9] = gszModCommands[m->command]; - } else p[9] = '.'; - if (m->param) + const uint16 val = m->GetValueEffectCol(); + p[9] = GetDigit<2>(val); + p[10] = GetDigit<1>(val); + p[11] = GetDigit<0>(val); + } + else { - p[10] = szHexChar[m->param >> 4]; - p[11] = szHexChar[m->param & 0x0F]; - } else p[10] = p[11] = '.'; + if (m->command) + { + if (m_SndFile.m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT)) + p[9] = gszS3mCommands[m->command]; + else + p[9] = gszModCommands[m->command]; + } else p[9] = '.'; + if (m->param) + { + p[10] = szHexChar[m->param >> 4]; + p[11] = szHexChar[m->param & 0x0F]; + } else p[10] = p[11] = '.'; + } } else { p[9] = p[10] = p[11] = ' '; @@ -1723,6 +1757,13 @@ m[col].note = 0; if (s[0] == '=') m[col].note = NOTE_KEYOFF; else if (s[0] == '^') m[col].note = NOTE_NOTECUT; else + if (s[0] == 'P') + { + if(s[2] == 'S') + m[col].note = NOTE_PCS; + else + m[col].note = NOTE_PC; + } else if (s[0] != '.') { for (UINT i=0; i<12; i++) @@ -1750,68 +1791,92 @@ { if (s[5] != '.') { - m[col].volcmd = 0; - for (UINT i=1; i<MAX_VOLCMDS; i++) + if(m[col].note == NOTE_PCS || m[col].note == NOTE_PC) { - if (s[5] == gszVolCommands[i]) + char val[4]; + memcpy(val, s+5, 3); + val[3] = 0; + m[col].SetValueVolCol(ConvertStrTo<uint16>(val)); + } + else + { + m[col].volcmd = 0; + for (UINT i=1; i<MAX_VOLCMDS; i++) { - m[col].volcmd = i; - break; + if (s[5] == gszVolCommands[i]) + { + m[col].volcmd = i; + break; + } } + m[col].vol = (s[6]-'0')*10 + (s[7]-'0'); } - m[col].vol = (s[6]-'0')*10 + (s[7]-'0'); } else m[col].volcmd = m[col].vol = 0; } - if (s[8] > ' ' && (!mix || ((!ITStyleMix && origModCmd.command==0) || - (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) + + if(m[col].note == NOTE_PCS || m[col].note == NOTE_PC) { - m[col].command = 0; - if (s[8] != '.') + if(s[8] != '.') { - LPCSTR psc = (bS3M) ? gszS3mCommands : gszModCommands; - for (UINT i=1; i<MAX_EFFECTS; i++) - { - if ((s[8] == psc[i]) && (psc[i] != '?')) m[col].command = i; - } + char val[4]; + memcpy(val, s+8, 3); + val[3] = 0; + m[col].SetValueEffectCol(ConvertStrTo<uint16>(val)); } } - // Effect value - if (s[9] > ' ' && (!mix || ((!ITStyleMix && origModCmd.param==0) || - (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) + else { - m[col].param = 0; - if (s[9] != '.') + if (s[8] > ' ' && (!mix || ((!ITStyleMix && origModCmd.command==0) || + (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) { - for (UINT i=0; i<16; i++) + m[col].command = 0; + if (s[8] != '.') { - if (s[9] == szHexChar[i]) m[col].param |= (i<<4); - if (s[10] == szHexChar[i]) m[col].param |= i; + LPCSTR psc = (bS3M) ? gszS3mCommands : gszModCommands; + for (UINT i=1; i<MAX_EFFECTS; i++) + { + if ((s[8] == psc[i]) && (psc[i] != '?')) m[col].command = i; + } } } - } - // Checking command - if (m_SndFile.m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - { - switch (m[col].command) + // Effect value + if (s[9] > ' ' && (!mix || ((!ITStyleMix && origModCmd.param==0) || + (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) { - case CMD_SPEED: - case CMD_TEMPO: - if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; - else + m[col].param = 0; + if (s[9] != '.') { - if ((m[col].command == CMD_SPEED) && (m[col].param > spdmax)) m[col].param = CMD_TEMPO; else - if ((m[col].command == CMD_TEMPO) && (m[col].param <= spdmax)) m[col].param = CMD_SPEED; + for (UINT i=0; i<16; i++) + { + if (s[9] == szHexChar[i]) m[col].param |= (i<<4); + if (s[10] == szHexChar[i]) m[col].param |= i; + } } - break; } - } else - { - switch (m[col].command) + // Checking command + if (m_SndFile.m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) { - case CMD_SPEED: - case CMD_TEMPO: - if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; - break; + switch (m[col].command) + { + case CMD_SPEED: + case CMD_TEMPO: + if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; + else + { + if ((m[col].command == CMD_SPEED) && (m[col].param > spdmax)) m[col].param = CMD_TEMPO; else + if ((m[col].command == CMD_TEMPO) && (m[col].param <= spdmax)) m[col].param = CMD_SPEED; + } + break; + } + } else + { + switch (m[col].command) + { + case CMD_SPEED: + case CMD_TEMPO: + if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; + break; + } } } } Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -192,19 +192,26 @@ ///////////////////////////////////////////////////////////////////////////// // Common Tables -LPCSTR szNoteNames[12] = +const LPCSTR szNoteNames[12] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }; -LPCSTR szHexChar = "0123456789ABCDEF"; -LPCSTR gszModCommands = " 0123456789ABCDRFFTE???GHK?YXPLZ\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : -LPCSTR gszS3mCommands = " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : -LPCSTR gszVolCommands = " vpcdabuhlrgfe:o"; //rewbs.velocity: added last : ; rewbs.volOff added last o +const LPCTSTR szDefaultNoteNames[NOTE_MAX] = { + TEXT("C-0"), TEXT("C#0"), TEXT("D-0"), TEXT("D#0"), TEXT("E-0"), TEXT("F-0"), TEXT("F#0"), TEXT("G-0"), TEXT("G#0"), TEXT("A-0"), TEXT("A#0"), TEXT("B-0"), + TEXT("C-1"), TEXT("C#1"), TEXT("D-1"), TEXT("D#1"), TEXT("E-1"), TEXT("F-1"), TEXT("F#1"), TEXT("G-1"), TEXT("G#1"), TEXT("A-1"), TEXT("A#1"), TEXT("B-1"), + TEXT("C-2"), TEXT("C#2"), TEXT("D-2"), TEXT("D#2"), TEXT("E-2"), TEXT("F-2"), TEXT("F#2"), TEXT("G-2"), TEXT("G#2"), TEXT("A-2"), TEXT("A#2"), TEXT("B-2"), + TEXT("C-3"), TEXT("C#3"), TEXT("D-3"), TEXT("D#3"), TEXT("E-3"), TEXT("F-3"), TEXT("F#3"), TEXT("G-3"), TEXT("G#3"), TEXT("A-3"), TEXT("A#3"), TEXT("B-3"), + TEXT("C-4"), TEXT("C#4"), TEXT("D-4"), TEXT("D#4"), TEXT("E-4"), TEXT("F-4"), TEXT("F#4"), TEXT("G-4"), TEXT("G#4"), TEXT("A-4"), TEXT("A#4"), TEXT("B-4"), + TEXT("C-5"), TEXT("C#5"), TEXT("D-5"), TEXT("D#5"), TEXT("E-5"), TEXT("F-5"), TEXT("F#5"), TEXT("G-5"), TEXT("G#5"), TEXT("A-5"), TEXT("A#5"), TEXT("B-5"), + TEXT("C-6"), TEXT("C#6"), TEXT("D-6"), TEXT("D#6"), TEXT("E-6"), TEXT("F-6"), TEXT("F#6"), TEXT("G-6"), TEXT("G#6"), TEXT("A-6"), TEXT("A#6"), TEXT("B-6"), + TEXT("C-7"), TEXT("C#7"), TEXT("D-7"), TEXT("D#7"), TEXT("E-7"), TEXT("F-7"), TEXT("F#7"), TEXT("G-7"), TEXT("G#7"), TEXT("A-7"), TEXT("A#7"), TEXT("B-7"), + TEXT("C-8"), TEXT("C#8"), TEXT("D-8"), TEXT("D#8"), TEXT("E-8"), TEXT("F-8"), TEXT("F#8"), TEXT("G-8"), TEXT("G#8"), TEXT("A-8"), TEXT("A#8"), TEXT("B-8"), + TEXT("C-9"), TEXT("C#9"), TEXT("D-9"), TEXT("D#9"), TEXT("E-9"), TEXT("F-9"), TEXT("F#9"), TEXT("G-9"), TEXT("G#9"), TEXT("A-9"), TEXT("A#9"), TEXT("B-9"), +}; - -BYTE gEffectColors[MAX_EFFECTS] = +const BYTE gEffectColors[MAX_EFFECTS] = { 0, 0, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_VOLUME, MODCOLOR_VOLUME, @@ -1119,15 +1126,12 @@ void CTrackApp::LoadChords(PMPTCHORD pChords) //------------------------------------------- -{ - CHAR snam[32]; - +{ if (!m_szConfigFileName[0]) return; for (UINT i=0; i<3*12; i++) { LONG chord; - wsprintf(snam, "%s%d", szNoteNames[i%12], i/12); - if ((chord = GetPrivateProfileInt("Chords", snam, -1, m_szConfigFileName)) >= 0) + if ((chord = GetPrivateProfileInt("Chords", szDefaultNoteNames[i], -1, m_szConfigFileName)) >= 0) { if ((chord & 0xFFFFFFC0) || (!pChords[i].notes[0])) { @@ -1144,14 +1148,13 @@ void CTrackApp::SaveChords(PMPTCHORD pChords) //------------------------------------------- { - CHAR s[64], snam[32]; + CHAR s[64]; if (!m_szConfigFileName[0]) return; for (UINT i=0; i<3*12; i++) { - wsprintf(snam, "%s%d", szNoteNames[i%12], i/12); wsprintf(s, "%d", (pChords[i].key) | (pChords[i].notes[0] << 6) | (pChords[i].notes[1] << 12) | (pChords[i].notes[2] << 18)); - if (!WritePrivateProfileString("Chords", snam, s, m_szConfigFileName)) break; + if (!WritePrivateProfileString("Chords", szDefaultNoteNames[i], s, m_szConfigFileName)) break; } } Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Mptrack.h 2009-06-25 21:53:49 UTC (rev 277) @@ -379,27 +379,48 @@ void Log(LPCSTR format,...); UINT MsgBox(UINT nStringID, CWnd *p=NULL, LPCSTR lpszTitle=NULL, UINT n=MB_OK); void ErrorBox(UINT nStringID, CWnd*p=NULL); + +// Helper function declarations. void AddPluginNamesToCombobox(CComboBox& CBox, SNDMIXPLUGIN* plugarray, const bool librarynames = false); void AddPluginParameternamesToCombobox(CComboBox& CBox, SNDMIXPLUGIN& plugarray); void AddPluginParameternamesToCombobox(CComboBox& CBox, CVstPlugin& plug); +// Append note names in range [noteStart, noteEnd] to given combobox. Index starts from 0. +void AppendNotesToControl(CComboBox& combobox, const MODCOMMAND::NOTE noteStart, const MODCOMMAND::NOTE noteEnd); + +// Append note names to combobox. If pSndFile != nullprt, appends only notes that are +// available in the module type. If nInstr is given, instrument specific note names are used instead of +// default note names. +void AppendNotesToControlEx(CComboBox& combobox, const CSoundFile* const pSndFile = nullptr, const INSTRUMENTINDEX nInstr = MAX_INSTRUMENTS); + +// Returns note name(such as "C-5") of given note. Regular notes are in range [1,MAX_NOTE]. +LPCTSTR GetNoteStr(const MODCOMMAND::NOTE); + /////////////////////////////////////////////////// // Tables #define MAX_EFFECTS 35 //rewbs.smoothVST & rewbs.velocity: increased from 32. Wonder what this will break... //+1 for eric's multiplier #define MAX_VOLCMDS 16 //rewbs.voloff & rewbs.velocity: increased from 14 -extern BYTE gEffectColors[MAX_EFFECTS]; -extern LPCSTR szNoteNames[12]; -extern LPCSTR szHexChar; -extern LPCSTR gszModCommands; -extern LPCSTR gszS3mCommands; -extern LPCSTR gszVolCommands; +extern const BYTE gEffectColors[MAX_EFFECTS]; +extern const LPCSTR szNoteNames[12]; +extern const LPCTSTR szDefaultNoteNames[NOTE_MAX]; +const LPCTSTR szSpecialNoteNames[NOTE_MAX_SPECIAL-NOTE_MIN_SPECIAL + 1] = {TEXT("PCs"), TEXT("PC"), TEXT("^^"), TEXT("==")}; +const LPCTSTR szSpecialNoteShortDesc[NOTE_MAX_SPECIAL-NOTE_MIN_SPECIAL + 1] = {TEXT("Param control(smooth)"), TEXT("Param control"), TEXT("Note Cut"), TEXT("Note Off")}; +// Make sure that special note arrays include string for every note. +STATIC_ASSERT(NOTE_MAX_SPECIAL - NOTE_MIN_SPECIAL + 1 == ARRAYELEMCOUNT(szSpecialNoteNames)); +STATIC_ASSERT(ARRAYELEMCOUNT(szSpecialNoteShortDesc) == ARRAYELEMCOUNT(szSpecialNoteNames)); + +const LPCSTR szHexChar = "0123456789ABCDEF"; +const LPCSTR gszModCommands = " 0123456789ABCDRFFTE???GHK?YXPLZ\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : +const LPCSTR gszS3mCommands = " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : +const LPCSTR gszVolCommands = " vpcdabuhlrgfe:o"; //rewbs.velocity: added last : ; rewbs.volOff added last o + // Defined in load_mid.cpp -extern LPCSTR szMidiProgramNames[128]; -extern LPCSTR szMidiPercussionNames[61]; // notes 25..85 -extern LPCSTR szMidiGroupNames[17]; // 16 groups + Percussions +extern const LPCSTR szMidiProgramNames[128]; +extern const LPCSTR szMidiPercussionNames[61]; // notes 25..85 +extern const LPCSTR szMidiGroupNames[17]; // 16 groups + Percussions ///////////////////////////////////////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -23,9 +23,9 @@ #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" -MODCOMMAND CViewPattern::m_cmdOld; -MODCOMMAND CViewPattern::m_cmdFind; -MODCOMMAND CViewPattern::m_cmdReplace; +MODCOMMAND CViewPattern::m_cmdOld = {0,0,0,0,0,0}; +MODCOMMAND CViewPattern::m_cmdFind = {0,0,0,0,0,0}; +MODCOMMAND CViewPattern::m_cmdReplace = {0,0,0,0,0,0}; DWORD CViewPattern::m_dwFindFlags = 0; DWORD CViewPattern::m_dwReplaceFlags = 0; UINT CViewPattern::m_nFindMinChn = 0; @@ -837,7 +837,7 @@ { UINT chn = i >> 3; MODCOMMAND *blank= &p[row * pSndFile->m_nChannels + chn]; - *blank = MODCOMMAND(); + *blank = MODCOMMAND::Empty(); } } m_dwBeginSel = startSel; @@ -874,6 +874,7 @@ PrepareUndo(m_dwBeginSel, m_dwEndSel); DWORD tmp = m_dwEndSel; + bool invalidateAllCols = false; for (UINT row=(m_dwBeginSel >> 16); row<=(m_dwEndSel >> 16); row++) { // for all selected rows for (UINT i=(m_dwBeginSel & 0xFFFF); i<=(m_dwEndSel & 0xFFFF); i++) if ((i & 7) < 5) { // for all selected cols @@ -884,8 +885,17 @@ switch(i & 7) { case 0: // Clear note if (rm.note) { - m->note = 0; - if (ITStyle) m->instr = 0; + if(m->note == NOTE_PCS || m->note == NOTE_PC) + { // Clear whole row if clearing PC note + m->Clear(); + invalidateAllCols = true; + } + else + { + m->note = 0; + if (ITStyle) m->instr = 0; + } + } break; case 1: // Clear instrument @@ -913,7 +923,17 @@ } //end selected columns } //end selected rows - if ((tmp & 7) == 3) tmp++; + // If selection ends on effect command column, extent invalidation area to + // effect param column as well. + if ((tmp & 7) == EFFECT_COLUMN) + tmp++; + + // If invalidation on all columns is wanted, extent invalidation area. + if(invalidateAllCols) + tmp += LAST_COLUMN - (tmp % 8); + + ASSERT(tmp % 8 <= LAST_COLUMN); + InvalidateArea(m_dwBeginSel, tmp); pModDoc->SetModified(); pModDoc->UpdateAllViews(this, HINT_PATTERNDATA | (m_nPattern << HINT_SHIFT_PAT), NULL); @@ -1791,7 +1811,7 @@ UINT ch = n % pSndFile->m_nChannels; if ((ch < m_nFindMinChn) || (ch > m_nFindMaxChn)) bFound = FALSE; } - if (((m_dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_cmdFind.note) && ((m_cmdFind.note != 0xFD) || (!m->note) || (m->note & 0x80)))) + if (((m_dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_cmdFind.note) && ((m_cmdFind.note != CFindReplaceTab::findAny) || (!m->note) || (m->note & 0x80)))) || ((m_dwFindFlags & PATSEARCH_INSTR) && (m->instr != m_cmdFind.instr)) || ((m_dwFindFlags & PATSEARCH_VOLCMD) && (m->volcmd != m_cmdFind.volcmd)) || ((m_dwFindFlags & PATSEARCH_VOLUME) && (m->vol != m_cmdFind.vol)) @@ -1799,10 +1819,21 @@ || ((m_dwFindFlags & PATSEARCH_PARAM) && (m->param != m_cmdFind.param))) { bFound = FALSE; - } else - if (((m_dwFindFlags & (PATSEARCH_COMMAND|PATSEARCH_PARAM)) == PATSEARCH_COMMAND) && (bEffectEx)) + } + else { - if ((m->param & 0xF0) != (m_cmdFind.param & 0xF0)) bFound = FALSE; + if (((m_dwFindFlags & (PATSEARCH_COMMAND|PATSEARCH_PARAM)) == PATSEARCH_COMMAND) && (bEffectEx)) + { + if ((m->param & 0xF0) != (m_cmdFind.param & 0xF0)) bFound = FALSE; + } + + // Ignore modcommands with PC/PCS notes when searching from volume or effect column. + if( (m->note == NOTE_PC || m->note == NOTE_PCS) + && + m_dwFindFlags & (PATSEARCH_VOLCMD|PATSEARCH_VOLUME|PATSEARCH_COMMAND|PATSEARCH_PARAM)) + { + bFound = FALSE; + } } // Found! if (bFound) @@ -1845,22 +1876,22 @@ if ((m_dwReplaceFlags & PATSEARCH_NOTE)) { // -1 octave - if (m_cmdReplace.note == 0xFA) + if (m_cmdReplace.note == CFindReplaceTab::replaceMinusOctave) { if (m->note > 12) m->note -= 12; } else // +1 octave - if (m_cmdReplace.note == 0xFB) + if (m_cmdReplace.note == CFindReplaceTab::replacePlusOctave) { - if (m->note <= 108) m->note += 12; + if (m->note <= NOTE_MAX - 12) m->note += 12; } else // Note-- - if (m_cmdReplace.note == 0xFC) + if (m_cmdReplace.note == CFindReplaceTab::replaceMinusOne) { if (m->note > 1) m->note--; } else // Note++ - if (m_cmdReplace.note == 0xFD) + if (m_cmdReplace.note == CFindReplaceTab::replacePlusOne) { if (m->note < NOTE_MAX) m->note++; } else m->note = m_cmdReplace.note; @@ -1868,12 +1899,12 @@ if ((m_dwReplaceFlags & PATSEARCH_INSTR)) { // Instr-- - if (m_cmdReplace.instr == 0xFC) + if (m_cmdReplace.instr == CFindReplaceTab::replaceMinusOne) { if (m->instr > 1) m->instr--; } else // Instr++ - if (m_cmdReplace.instr == 0xFD) + if (m_cmdReplace.instr == CFindReplaceTab::replacePlusOne) { if (m->instr < MAX_INSTRUMENTS-1) m->instr++; } else m->instr = m_cmdReplace.instr; @@ -1913,11 +1944,7 @@ { if (m_dwFindFlags & PATSEARCH_NOTE) { - UINT note = m_cmdFind.note; - if (note == 0) strcpy(szFind, "..."); else - if (note == 0xFE) strcpy(szFind, "^^ "); else - if (note == 0xFF) strcpy(szFind, "== "); else - wsprintf(szFind, "%s%d", szNoteNames[(note-1) % 12], (note-1)/12); + wsprintf(szFind, "%s", GetNoteStr(m_cmdFind.note)); } else strcpy(szFind, "???"); strcat(szFind, " "); if (m_dwFindFlags & PATSEARCH_INSTR) @@ -2041,7 +2068,6 @@ UINT nCursor = m_dwCursor & 0x07; CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern] + m_nRow*pSndFile->m_nChannels + nChn; - MODCOMMAND oldcmd = *p; switch(nCursor) { @@ -2173,7 +2199,6 @@ //for all channels where type is selected for (int chnIdx=0; chnIdx<nValidChans; chnIdx++) { - MODCOMMAND *pcmd = pSndFile->Patterns[m_nPattern]; UINT nchn = validChans[chnIdx]; UINT row0 = GetSelectionStartRow(); UINT row1 = GetSelectionEndRow(); @@ -2186,27 +2211,50 @@ PrepareUndo(m_dwBeginSel, m_dwEndSel); } - int vsrc, vdest, vcmd, verr, distance; + bool doPCinterpolation = false; + + int vsrc, vdest, vcmd = 0, verr = 0, distance; distance = row1 - row0; + const MODCOMMAND srcCmd = *pSndFile->Patterns[m_nPattern].GetpModCommand(row0, nchn); + const MODCOMMAND destCmd = *pSndFile->Patterns[m_nPattern].GetpModCommand(row1, nchn); + + MODCOMMAND::NOTE PCnote = 0; + uint16 PCinst = 0, PCparam = 0; + switch(type) { case NOTE_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].note; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].note; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].instr; - verr = (distance * 59) / 120; + vsrc = srcCmd.note; + vdest = destCmd.note; + vcmd = srcCmd.instr; + verr = (distance * 59) / NOTE_MAX; break; case VOL_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].vol; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].vol; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].volcmd; + vsrc = srcCmd.vol; + vdest = destCmd.vol; + vcmd = srcCmd.volcmd; verr = (distance * 63) / 128; break; case PARAM_COLUMN: case EFFECT_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].param; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].param; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].command; + if(srcCmd.note == NOTE_PC || srcCmd.note == NOTE_PCS || destCmd.note == NOTE_PCS || destCmd.note == NOTE_PC) + { + doPCinterpolation = true; + PCnote = (srcCmd.note == NOTE_PC || srcCmd.note == NOTE_PCS) ? srcCmd.note : destCmd.note; + vsrc = srcCmd.GetValueEffectCol(); + vdest = destCmd.GetValueEffectCol(); + PCparam = srcCmd.GetValueVolCol(); + if(PCparam == 0) PCparam = destCmd.GetValueVolCol(); + PCinst = srcCmd.instr; + if(PCinst == 0) + PCinst = destCmd.instr; + } + else + { + vsrc = srcCmd.param; + vdest = destCmd.param; + vcmd = srcCmd.command; + } verr = (distance * 63) / 128; break; default: @@ -2215,8 +2263,9 @@ } if (vdest < vsrc) verr = -verr; - pcmd += row0 * pSndFile->m_nChannels + nchn; + MODCOMMAND* pcmd = pSndFile->Patterns[m_nPattern].GetpModCommand(row0, nchn); + for (UINT i=0; i<=distance; i++, pcmd += pSndFile->m_nChannels) { switch(type) { @@ -2235,11 +2284,24 @@ } break; case EFFECT_COLUMN: - if ((!pcmd->command) || (pcmd->command == vcmd)) { - int val = vsrc + ((vdest - vsrc) * (int)i + verr) / distance; - pcmd->param = (BYTE)val; - pcmd->command = vcmd; + if(doPCinterpolation) + { // With PC/PCs notes, copy PCs note and plug index to all rows where + // effect interpolation is done. + const uint16 val = static_cast<uint16>(vsrc + ((vdest - vsrc) * (int)i + verr) / distance); + pcmd->note = PCnote; + pcmd->instr = PCinst; + pcmd->SetValueVolCol(PCparam); + pcmd->SetValueEffectCol(val); } + else + { + if ((!pcmd->command) || (pcmd->command == vcmd)) + { + int val = vsrc + ((vdest - vsrc) * (int)i + verr) / distance; + pcmd->param = (BYTE)val; + pcmd->command = vcmd; + } + } break; default: ASSERT(false); @@ -3487,6 +3549,8 @@ case kcNoteCutOld: TempEnterNote(NOTE_NOTECUT, true); return wParam; case kcNoteOff: TempEnterNote(NOTE_KEYOFF, false); return wParam; case kcNoteOffOld: TempEnterNote(NOTE_KEYOFF, true); return wParam; + case kcNotePC: TempEnterNote(NOTE_PC); return wParam; + case kcNotePCS: TempEnterNote(NOTE_PCS); return wParam; case kcEditUndo: OnEditUndo(); return wParam; case kcEditFind: OnEditFind(); return wParam; @@ -3576,6 +3640,19 @@ return NULL; } +#define ENTER_PCNOTE_VALUE(v, method) \ + { \ + if((v >= 0) && (v <= 9)) \ + { \ + uint16 val = p->Get##method##(); \ + /* Move existing digits to left, drop out leftmost digit and */ \ + /* push new digit to the least meaning digit. */ \ + val = (val % 100) * 10 + v; \ + if(val > MODCOMMAND::maxColumnValue) val = MODCOMMAND::maxColumnValue; \ + p->Set##method##(val); \ + } \ + } + void CViewPattern::TempEnterVol(int v) //------------------------------------ { @@ -3586,55 +3663,57 @@ { CSoundFile *pSndFile = pModDoc->GetSoundFile(); - MODCOMMAND *p = pSndFile->Patterns[m_nPattern], *prowbase; - - MODCOMMAND oldcmd; // This is the command we are about to overwrite + PrepareUndo(m_dwBeginSel, m_dwEndSel); - // -- Work out where to put the new data - UINT nChn = (m_dwCursor & 0xFFFF) >> 3; - prowbase = p + m_nRow * pSndFile->m_nChannels; - p = prowbase + nChn; - oldcmd = *p; + MODCOMMAND* p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); + MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite - UINT volcmd = p->volcmd; - UINT vol = p->vol; - if ((v >= 0) && (v <= 9)) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - vol = ((vol * 10) + v) % 100; - if (!volcmd) volcmd = VOLCMD_VOLUME; + ENTER_PCNOTE_VALUE(v, ValueVolCol); } else - switch(v+kcSetVolumeStart) + { + UINT volcmd = p->volcmd; + UINT vol = p->vol; + if ((v >= 0) && (v <= 9)) { - case kcSetVolumeVol: volcmd = VOLCMD_VOLUME; break; - case kcSetVolumePan: volcmd = VOLCMD_PANNING; break; - case kcSetVolumeVolSlideUp: volcmd = VOLCMD_VOLSLIDEUP; break; - case kcSetVolumeVolSlideDown: volcmd = VOLCMD_VOLSLIDEDOWN; break; - case kcSetVolumeFineVolUp: volcmd = VOLCMD_FINEVOLUP; break; - case kcSetVolumeFineVolDown: volcmd = VOLCMD_FINEVOLDOWN; break; - case kcSetVolumeVibratoSpd: volcmd = VOLCMD_VIBRATOSPEED; break; - case kcSetVolumeVibrato: volcmd = VOLCMD_VIBRATO; break; - case kcSetVolumeXMPanLeft: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDELEFT; break; - case kcSetVolumeXMPanRight: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDERIGHT; break; - case kcSetVolumePortamento: volcmd = VOLCMD_TONEPORTAMENTO; break; - case kcSetVolumeITPortaUp: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTAUP; break; - case kcSetVolumeITPortaDown: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTADOWN; break; - case kcSetVolumeITVelocity: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_VELOCITY; break; //rewbs.velocity - case kcSetVolumeITOffset: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_OFFSET; break; //rewbs.volOff + vol = ((vol * 10) + v) % 100; + if (!volcmd) volcmd = VOLCMD_VOLUME; } - if ((pSndFile->m_nType & MOD_TYPE_MOD) && (volcmd > VOLCMD_PANNING)) volcmd = vol = 0; + else + switch(v+kcSetVolumeStart) + { + case kcSetVolumeVol: volcmd = VOLCMD_VOLUME; break; + case kcSetVolumePan: volcmd = VOLCMD_PANNING; break; + case kcSetVolumeVolSlideUp: volcmd = VOLCMD_VOLSLIDEUP; break; + case kcSetVolumeVolSlideDown: volcmd = VOLCMD_VOLSLIDEDOWN; break; + case kcSetVolumeFineVolUp: volcmd = VOLCMD_FINEVOLUP; break; + case kcSetVolumeFineVolDown: volcmd = VOLCMD_FINEVOLDOWN; break; + case kcSetVolumeVibratoSpd: volcmd = VOLCMD_VIBRATOSPEED; break; + case kcSetVolumeVibrato: volcmd = VOLCMD_VIBRATO; break; + case kcSetVolumeXMPanLeft: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDELEFT; break; + case kcSetVolumeXMPanRight: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDERIGHT; break; + case kcSetVolumePortamento: volcmd = VOLCMD_TONEPORTAMENTO; break; + case kcSetVolumeITPortaUp: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTAUP; break; + case kcSetVolumeITPortaDown: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTADOWN; break; + case kcSetVolumeITVelocity: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_VELOCITY; break; //rewbs.velocity + case kcSetVolumeITOffset: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_OFFSET; break; //rewbs.volOff + } + if ((pSndFile->m_nType & MOD_TYPE_MOD) && (volcmd > VOLCMD_PANNING)) volcmd = vol = 0; - UINT max = 64; - if (volcmd > VOLCMD_PANNING) - { - max = (pSndFile->m_nType == MOD_TYPE_XM) ? 0x0F : 9; + UINT max = 64; + if (volcmd > VOLCMD_PANNING) + { + max = (pSndFile->m_nType == MOD_TYPE_XM) ? 0x0F : 9; + } + + if (vol > max) vol %= 10; + p->volcmd = volcmd; + p->vol = vol; } - if (vol > max) vol %= 10; - p->volcmd = volcmd; - p->vol = vol; - if (IsEditingEnabled_bmsg()) { DWORD sel = (m_nRow << 16) | m_dwCursor; @@ -3672,47 +3751,52 @@ CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CModDoc *pModDoc = GetDocument(); - if ((pModDoc) && (pMainFrm) && (IsEditingEnabled_bmsg())) + if(!IsEditingEnabled_bmsg()) return; + + if ((pModDoc) && (pMainFrm)) { CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite - //if(p->command != 0 && !overwrite) return true; - PrepareUndo(m_dwBeginSel, m_dwEndSel); - //LPCSTR lpcmd = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands : gszS3mCommands; - if (c) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - if ((c == m_cmdOld.command) && (!p->param) && (!p->command)) p->param = m_cmdOld.param; - else m_cmdOld.param = 0; - m_cmdOld.command = c; + ENTER_PCNOTE_VALUE(c, ValueEffectCol); } - p->command = c; - - // Check for MOD/XM Speed/Tempo command - if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + else { - UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; - p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; - } - //if (IsEditingEnabled_bmsg()) - //{ - DWORD sel = (m_nRow << 16) | m_dwCursor; - SetCurSel(sel, sel); - sel &= ~7; - if(oldcmd != *p) + //LPCSTR lpcmd = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands : gszS3mCommands; + if (c) { - pModDoc->SetModified(); - InvalidateArea(sel, sel+5); - UpdateIndicator(); + if ((c == m_cmdOld.command) && (!p->param) && (!p->command)) p->param = m_cmdOld.param; + else m_cmdOld.param = 0; + m_cmdOld.command = c; } - //} - } // end if mainframe & moddoc exist & editing enabled + p->command = c; + + // Check for MOD/XM Speed/Tempo command + if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) + && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + { + UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; + p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; + } + } + + DWORD sel = (m_nRow << 16) | m_dwCursor; + SetCurSel(sel, sel); + sel &= ~7; + if(oldcmd != *p) + { + pModDoc->SetModified(); + InvalidateArea(sel, sel+5); + UpdateIndicator(); + } + } // end if mainframe & moddoc exist } @@ -3725,41 +3809,43 @@ if ((pModDoc) && (pMainFrm) && (IsEditingEnabled_bmsg())) { CSoundFile *pSndFile = pModDoc->GetSoundFile(); - MODCOMMAND oldcmd; // This is the command we are about to overwrite MODCOMMAND *p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); - oldcmd = *p; + MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite PrepareUndo(m_dwBeginSel, m_dwEndSel); - //if(enterAsAbsoluteValue) p->param = v; - //else p->param = (p->param << 4) | v; - - p->param = (p->param << 4) | v; - if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; - -/* - if (v >= 0 && v <= 9) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - p->param = (p->param << 4) | v; - if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + ENTER_PCNOTE_VALUE(v, ValueEffectCol); } - else if (v >= 10 && v <= 15) + else { - p->param = (p->param << 4) | (v + 0x0A); + + p->param = (p->param << 4) | v; if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + + /* + if (v >= 0 && v <= 9) + { + p->param = (p->param << 4) | v; + if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + } + else if (v >= 10 && v <= 15) + { + p->param = (p->param << 4) | (v + 0x0A); + if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + } + */ + // Check for MOD/XM Speed/Tempo command + if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) + && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + { + UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; + p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; + } } -*/ - // Check for MOD/XM Speed/Tempo command - if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) - { - UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; - p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; - } - //if (IsEditingEnabled()) - //{ DWORD sel = (m_nRow << 16) | m_dwCursor; SetCurSel(sel, sel); sel &= ~7; @@ -3769,7 +3855,6 @@ InvalidateArea(sel, sel+5); UpdateIndicator(); } - //} } } @@ -3971,6 +4056,7 @@ if ((pModDoc) && (pMainFrm)) { + ROWINDEX nRow = m_nRow; CSoundFile *pSndFile = pModDoc->GetSoundFile(); const ROWINDEX nRowPlayback = pSndFile->m_nRow; const UINT nTick = pSndFile->m_nTickCount; @@ -3978,15 +4064,32 @@ const bool bRecordEnabled = IsEditingEnabled(); const UINT nChn = GetChanFromCursor(m_dwCursor); + + if(note > pSndFile->GetModSpecifications().noteMax && note < NOTE_MIN_SPECIAL) + note = pSndFile->GetModSpecifications().noteMax; + else if( note < pSndFile->GetModSpecifications().noteMin) + note = pSndFile->GetModSpecifications().noteMin; + + // Check whether the module format supports the note. + if( pSndFile->GetModSpecifications().HasNote(note) == false ) + return; + BYTE recordGroup = pModDoc->IsChannelRecord(nChn); UINT nPlayIns = 0; - - if (note > NOTE_MAX && note < 254) note = NOTE_MAX; - const bool bIsLiveRecord = IsLiveRecord(*pMainFrm, *pModDoc, *pSndFile); const bool usePlaybackPosition = (bIsLiveRecord && (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY)); + //Param control 'note' + if((note == NOTE_PC || note == NOTE_PCS) && bRecordEnabled) + { + pModDoc->PrepareUndo(m_nPattern, nChn, nRow, 1, 1); + pSndFile->Patterns[m_nPattern].GetpModCommand(nRow, nChn)->note = note; + const DWORD sel = (nRow << 16) | m_dwCursor; + pModDoc->SetModified(); + InvalidateArea(sel, sel+5); + UpdateIndicator(); + return; + } - ROWINDEX nRow = m_nRow; // -- Chord autodetection: step back if we just entered a note if ((bRecordEnabled) && (recordGroup) && !bIsLiveRecord) { @@ -4315,16 +4418,12 @@ switch(field) { - case 0: p->note = 0; if (ITStyle) p->instr = 0; break; //Note + case 0: if(p->note == NOTE_PC || p->note == NOTE_PCS) p->Clear(); else {p->note = 0; if (ITStyle) p->instr = 0;} break; //Note case 1: p->instr = 0; break; //instr case 2: p->vol = 0; p->volcmd = 0; break; //Vol case 3: p->command = 0; break; //Effect case 4: p->param = 0; break; //Param - default: p->note = 0; //If not specified, delete them all! :) - p->instr = 0; - p->vol = 0; p->volcmd = 0; - p->command = 0; - p->param = 0; + default: p->Clear(); //If not specified, delete them all! :) } if(IsEditingEnabled_bmsg()) @@ -4852,28 +4951,32 @@ bool CViewPattern::IsInterpolationPossible(UINT startRow, UINT endRow, UINT chan, UINT colType, CSoundFile* pSndFile) { //--------------------------------------------------------------------------------------- - bool result = false; - MODCOMMAND *pcmd = pSndFile->Patterns[m_nPattern]; - UINT startRowCmd, endRowCmd; - if (startRow == endRow) { return false; } + bool result = false; + const MODCOMMAND startRowMC = *pSndFile->Patterns[m_nPattern].GetpModCommand(startRow, chan); + const MODCOMMAND endRowMC = *pSndFile->Patterns[m_nPattern].GetpModCommand(endRow, chan); + UINT startRowCmd, endRowCmd; + + if(colType == EFFECT_COLUMN && (startRowMC.note == NOTE_PC || startRowMC.note == NOTE_PCS || endRowMC.note == NOTE_PC || endRowMC.note == NOTE_PCS)) + return true; + switch (colType) { case NOTE_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].note; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].note; + startRowCmd = startRowMC.note; + endRowCmd = endRowMC.note; result = (startRowCmd>0 && endRowCmd>0); break; case EFFECT_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].command; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].command; + startRowCmd = startRowMC.command; + endRowCmd = endRowMC.command; result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); break; case VOL_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].volcmd; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].volcmd; + startRowCmd = startRowMC.volcmd; + endRowCmd = endRowMC.volcmd; result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); break; default: Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_pat.h 2009-06-25 21:53:49 UTC (rev 277) @@ -36,6 +36,7 @@ VOL_COLUMN, EFFECT_COLUMN, PARAM_COLUMN, + LAST_COLUMN = PARAM_COLUMN }; @@ -164,7 +165,7 @@ void DrawLetter(int x, int y, char letter, int sizex=10, int ofsx=0); void DrawNote(int x, int y, UINT note, CTuning* pTuning = NULL); void DrawInstrument(int x, int y, UINT instr); - void DrawVolumeCommand(int x, int y, UINT volcmd, UINT vol); + void DrawVolumeCommand(int x, int y, const MODCOMMAND mc); void DrawChannelVUMeter(HDC hdc, int x, int y, UINT nChn); void UpdateAllVUMeters(MPTNOTIFICATION *pnotify); void DrawDragSel(HDC hdc); Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -400,8 +400,7 @@ for (UINT iPerc=24; iPerc<=84; iPerc++) { DWORD dwI... [truncated message content] |
From: <rel...@us...> - 2009-06-24 19:40:35
|
Revision: 276 http://modplug.svn.sourceforge.net/modplug/?rev=276&view=rev Author: relabsoluness Date: 2009-06-24 19:39:33 +0000 (Wed, 24 Jun 2009) Log Message: ----------- [Ref] Moved pattern, playbackeventer and sequence files from mptrack to soundlib. (merged from devBranch_1_17_03) Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/soundlib/Sndfile.h Added Paths: ----------- trunk/OpenMPT/soundlib/OrderToPatternTable.cpp trunk/OpenMPT/soundlib/OrderToPatternTable.h trunk/OpenMPT/soundlib/PlaybackEventer.cpp trunk/OpenMPT/soundlib/PlaybackEventer.h trunk/OpenMPT/soundlib/pattern.cpp trunk/OpenMPT/soundlib/pattern.h trunk/OpenMPT/soundlib/patternContainer.cpp trunk/OpenMPT/soundlib/patternContainer.h Removed Paths: ------------- trunk/OpenMPT/mptrack/OrderToPatternTable.cpp trunk/OpenMPT/mptrack/OrderToPatternTable.h trunk/OpenMPT/mptrack/PlaybackEventer.cpp trunk/OpenMPT/mptrack/PlaybackEventer.h trunk/OpenMPT/mptrack/pattern.cpp trunk/OpenMPT/mptrack/pattern.h trunk/OpenMPT/mptrack/patternContainer.cpp trunk/OpenMPT/mptrack/patternContainer.h Deleted: trunk/OpenMPT/mptrack/OrderToPatternTable.cpp =================================================================== --- trunk/OpenMPT/mptrack/OrderToPatternTable.cpp 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/OrderToPatternTable.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -1,228 +0,0 @@ -#include "stdafx.h" -#include "sndfile.h" -#include "ordertopatterntable.h" - -#define str_SequenceTruncationNote (GetStrI18N((_TEXT("Module has sequence of length %u; it will be truncated to maximum supported length, %u.")))) - -DWORD COrderToPatternTable::Unserialize(const BYTE* const src, const DWORD memLength) -//------------------------------------------------------------------------- -{ - if(memLength < 2 + 4) return 0; - uint16 version = 0; - uint32 s = 0; - DWORD memPos = 0; - memcpy(&version, src, sizeof(version)); - memPos += sizeof(version); - if(version != 0) return memPos; - memcpy(&s, src+memPos, sizeof(s)); - memPos += sizeof(s); - if(s > 65000) return true; - if(memLength < memPos+s*4) return memPos; - - const uint32 nOriginalSize = s; - if(s > MPTM_SPECS.ordersMax) - s = MPTM_SPECS.ordersMax; - - resize(s); - for(size_t i = 0; i<s; i++, memPos +=4 ) - { - uint32 temp; - memcpy(&temp, src+memPos, 4); - (*this)[i] = static_cast<PATTERNINDEX>(temp); - } - memPos += 4*(nOriginalSize - s); - return memPos; -} - - -size_t COrderToPatternTable::WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize) -//----------------------------------------------------------------------------- -{ - if(numOfBytes > destSize) return true; - if(size() < numOfBytes) resize(numOfBytes, 0xFF); - UINT i = 0; - for(i = 0; i<numOfBytes; i++) - { - dest[i] = static_cast<BYTE>((*this)[i]); - } - return i; //Returns the number of bytes written. -} - - -size_t COrderToPatternTable::WriteAsByte(FILE* f, const UINT count) -//--------------------------------------------------------------- -{ - if(size() < count) resize(count, GetInvalidPatIndex()); - - size_t i = 0; - - for(i = 0; i<count; i++) - { - const PATTERNINDEX pat = (*this)[i]; - BYTE temp = static_cast<BYTE>((*this)[i]); - - if(pat > 0xFD) - { - if(pat == GetInvalidPatIndex()) temp = 0xFF; - else temp = 0xFE; - } - fwrite(&temp, 1, 1, f); - } - return i; //Returns the number of bytes written. -} - -bool COrderToPatternTable::ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength) -//------------------------------------------------------------------------- -{ - if(howMany < 0 || howMany > memLength) return true; - if(m_rSndFile.GetType() != MOD_TYPE_MPT && howMany > MAX_ORDERS) return true; - - if(size() < static_cast<size_t>(howMany)) - resize(howMany, GetInvalidPatIndex()); - - for(int i = 0; i<howMany; i++, pFrom++) - (*this)[i] = *pFrom; - return false; -} - - -bool COrderToPatternTable::NeedsExtraDatafield() const -//---------------------------------------------- -{ - if(m_rSndFile.GetType() == MOD_TYPE_MPT && m_rSndFile.Patterns.Size() > 0xFD) - return true; - else - return false; -} - - -void COrderToPatternTable::OnModTypeChanged(const MODTYPE oldtype) -//---------------------------------------------------------------- -{ - const CModSpecifications specs = m_rSndFile.GetModSpecifications(); - - //Resize orderlist if needed. Because old orderlist had MAX_ORDERS(256) elements, not making it - //smaller than that even if the modtype doesn't support that many orders. - if(specs.ordersMax < GetCount()) - { - resize(max(MAX_ORDERS, specs.ordersMax)); - for(ORDERINDEX i = GetCount(); i>specs.ordersMax; --i) (*this)[i-1] = GetInvalidPatIndex(); - } - - //Replace items used to denote end of song/skip order. - replace(begin(), end(), GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); - replace(begin(), end(), GetIgnoreIndex(oldtype), GetIgnoreIndex()); -} - - -ORDERINDEX COrderToPatternTable::GetLengthTailTrimmed() const -//----------------------------------------------------------- -{ - ORDERINDEX nEnd = GetCount(); - if(nEnd == 0) return 0; - nEnd--; - const PATTERNINDEX iInvalid = GetInvalidPatIndex(); - while(nEnd > 0 && (*this)[nEnd] == iInvalid) - nEnd--; - return ((*this)[nEnd] == iInvalid) ? 0 : nEnd+1; -} - - -ORDERINDEX COrderToPatternTable::GetLengthFirstEmpty() const -//---------------------------------------------------------- -{ - const ORDERINDEX nLength = GetCount(); - ORDERINDEX nMax = 0; - while ((nMax < nLength) && ((*this)[nMax] != (*this).GetInvalidPatIndex())) nMax++; - return nMax; -} - - -ORDERINDEX COrderToPatternTable::GetNextOrderIgnoringSkips(const ORDERINDEX start) const -//------------------------------------------------------------------------------------- -{ - const ORDERINDEX count = GetCount(); - if(count == 0) return 0; - ORDERINDEX next = min(count-1, start+1); - while(next+1 < count && (*this)[next] == GetIgnoreIndex()) next++; - return next; -} - -ORDERINDEX COrderToPatternTable::GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const -//------------------------------------------------------------------------------------- -{ - const ORDERINDEX count = GetCount(); - if(start == 0 || count == 0) return 0; - ORDERINDEX prev = min(start-1, count-1); - while(prev > 0 && (*this)[prev] == GetIgnoreIndex()) prev--; - return prev; -} - - -void COrderToPatternTable::Init() -//------------------------------- -{ - resize(MAX_ORDERS, GetInvalidPatIndex()); - for(ORDERINDEX i = 0; i < GetCount(); i++) - { - (*this)[i] = GetInvalidPatIndex(); - } -} - - - -PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65535 : 0xFF;} -PATTERNINDEX COrderToPatternTable::GetIgnoreIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65534 : 0xFE;} - -PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex() const {return GetInvalidPatIndex(m_rSndFile.GetType());} -PATTERNINDEX COrderToPatternTable::GetIgnoreIndex() const {return GetIgnoreIndex(m_rSndFile.GetType());} - - - - -//-------------------------------------------------- -//-------------------------------------------------- -//-------------------------------------------------- - -using namespace srlztn; - -void COrderSerialization::ProWrite(OUTSTREAM& ostrm) const -//-------------------------------------------------------- -{ - uint16 size = static_cast<uint16>(m_rOrders.size()); - ostrm.write(reinterpret_cast<const char*>(&size), 2); - const COrderToPatternTable::const_iterator endIter = m_rOrders.end(); - for(COrderToPatternTable::const_iterator citer = m_rOrders.begin(); citer != endIter; citer++) - { - const uint16 temp = static_cast<uint16>(*citer); - ostrm.write(reinterpret_cast<const char*>(&temp), 2); - } -} - - -void COrderSerialization::ProRead(INSTREAM& istrm, const uint64 /*datasize*/) -//--------------------------------------------------------------------------- -{ - uint16 size; - istrm.read(reinterpret_cast<char*>(&size), 2); - if(size > MPTM_SPECS.ordersMax) - { - // Hack: Show message here if trying to load longer sequence than what is supported. - CString str; str.Format(str_SequenceTruncationNote, size, MPTM_SPECS.ordersMax); - ::MessageBox(0, str, "", MB_ICONWARNING); - size = MPTM_SPECS.ordersMax; - } - m_rOrders.resize(size); - if(size == 0) {m_rOrders.assign(MAX_ORDERS, m_rOrders.GetInvalidPatIndex()); return;} - - const COrderToPatternTable::const_iterator endIter = m_rOrders.end(); - for(COrderToPatternTable::iterator iter = m_rOrders.begin(); iter != endIter; iter++) - { - uint16 temp; - istrm.read(reinterpret_cast<char*>(&temp), 2); - *iter = temp; - } -} - - - Deleted: trunk/OpenMPT/mptrack/OrderToPatternTable.h =================================================================== --- trunk/OpenMPT/mptrack/OrderToPatternTable.h 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/OrderToPatternTable.h 2009-06-24 19:39:33 UTC (rev 276) @@ -1,77 +0,0 @@ -#ifndef ORDERTOPATTERNTABLE_H -#define ORDERTOPATTERNTABLE_H - -#include "serialization_utils.h" -#include <vector> -using std::vector; - -class CSoundFile; -class COrderToPatternTable; - -#pragma warning(disable:4244) //conversion from 'type1' to 'type2', possible loss of data - -class COrderSerialization : public srlztn::ABCSerializationStreamer -//========================================================= -{ -public: - COrderSerialization(COrderToPatternTable& ordertable) : m_rOrders(ordertable) {} - virtual void ProWrite(srlztn::OUTSTREAM& ostrm) const; - virtual void ProRead(srlztn::INSTREAM& istrm, const uint64 /*datasize*/); -private: - COrderToPatternTable& m_rOrders; -}; - -//============================================== -class COrderToPatternTable : public vector<PATTERNINDEX> -//============================================== -{ -public: - COrderToPatternTable(const CSoundFile& sndFile) : m_rSndFile(sndFile) {} - - // Initialize default sized sequence. - void Init(); - - bool ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength); - - size_t WriteAsByte(FILE* f, const UINT count); - - size_t WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize); - - ORDERINDEX GetCount() const {return size();} - - //Deprecated function used for MPTm's created in 1.17.02.46 - 1.17.02.48. - DWORD Unserialize(const BYTE* const src, const DWORD memLength); - - //Returns true if the IT orderlist datafield is not sufficient to store orderlist information. - bool NeedsExtraDatafield() const; - - void OnModTypeChanged(const MODTYPE oldtype); - - // Returns length of sequence without counting trailing '---' items. - ORDERINDEX GetLengthTailTrimmed() const; - - // Returns length of sequence stopping counting on first '---' (or at the end of sequence). - ORDERINDEX GetLengthFirstEmpty() const; - - PATTERNINDEX GetInvalidPatIndex() const; //To correspond 0xFF - static PATTERNINDEX GetInvalidPatIndex(const MODTYPE type); - - PATTERNINDEX GetIgnoreIndex() const; //To correspond 0xFE - static PATTERNINDEX GetIgnoreIndex(const MODTYPE type); - - //Returns the previous/next order ignoring skip indeces(+++). - //If no previous/next order exists, return first/last order, and zero - //when orderlist is empty. - ORDERINDEX GetNextOrderIgnoringSkips(const ORDERINDEX start) const; - ORDERINDEX GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const; - - COrderSerialization* NewReadWriteObject() {return new COrderSerialization(*this);} - -private: - const CSoundFile& m_rSndFile; -}; - -#pragma warning(default:4244) - -#endif - Deleted: trunk/OpenMPT/mptrack/PlaybackEventer.cpp =================================================================== --- trunk/OpenMPT/mptrack/PlaybackEventer.cpp 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/PlaybackEventer.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -1,31 +0,0 @@ -#include "stdafx.h" -#include "PlaybackEventer.h" -#include "sndfile.h" - -CPlaybackEventer::~CPlaybackEventer() -//--------------------------------- -{ -} - -void CPlaybackEventer::PatternTranstionChnSolo(const CHANNELINDEX chnIndex) -//------------------------------------------------------------------------- -{ - if(chnIndex >= m_rSndFile.m_nChannels) - return; - - for(CHANNELINDEX i = 0; i<m_rSndFile.m_nChannels; i++) - { - m_rSndFile.m_bChannelMuteTogglePending[i] = (m_rSndFile.ChnSettings[i].dwFlags & CHN_MUTE) ? false : true; - } - m_rSndFile.m_bChannelMuteTogglePending[chnIndex] = (m_rSndFile.ChnSettings[chnIndex].dwFlags & CHN_MUTE) ? true : false; -} - - -void CPlaybackEventer::PatternTransitionChnUnmuteAll() -//---------------------------------------------------- -{ - for(CHANNELINDEX i = 0; i<m_rSndFile.m_nChannels; i++) - { - m_rSndFile.m_bChannelMuteTogglePending[i] = (m_rSndFile.ChnSettings[i].dwFlags & CHN_MUTE) ? true : false; - } -} \ No newline at end of file Deleted: trunk/OpenMPT/mptrack/PlaybackEventer.h =================================================================== --- trunk/OpenMPT/mptrack/PlaybackEventer.h 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/PlaybackEventer.h 2009-06-24 19:39:33 UTC (rev 276) @@ -1,25 +0,0 @@ -#ifndef PLAYBACKEVENTER_H -#define PLAYBACKEVENTER_H - -#include "pattern.h" - -class CSoundFile; - -//==================== -class CPlaybackEventer -//==================== -{ -public: - CPlaybackEventer(CSoundFile& sndf) : m_rSndFile(sndf) {} - ~CPlaybackEventer(); - - //SetPatternEvent(const PATTERNINDEX pattern, const ROWINDEX row, const CHANNELINDEX column); - - void PatternTranstionChnSolo(const CHANNELINDEX chnIndex); - void PatternTransitionChnUnmuteAll(); - -private: - CSoundFile& m_rSndFile; -}; - -#endif Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-24 19:39:33 UTC (rev 276) @@ -391,13 +391,13 @@ RelativePath=".\OpenGLEditor.cpp"> </File> <File - RelativePath=".\OrderToPatternTable.cpp"> + RelativePath="..\soundlib\OrderToPatternTable.cpp"> </File> <File - RelativePath=".\pattern.cpp"> + RelativePath="..\soundlib\pattern.cpp"> </File> <File - RelativePath=".\patternContainer.cpp"> + RelativePath="..\soundlib\patternContainer.cpp"> </File> <File RelativePath=".\PatternGotoDialog.cpp"> @@ -406,7 +406,7 @@ RelativePath=".\PerformanceCounter.cpp"> </File> <File - RelativePath=".\PlaybackEventer.cpp"> + RelativePath="..\soundlib\PlaybackEventer.cpp"> </File> <File RelativePath=".\PSRatioCalc.cpp"> @@ -804,13 +804,13 @@ RelativePath=".\order.h"> </File> <File - RelativePath=".\OrderToPatternTable.h"> + RelativePath="..\soundlib\OrderToPatternTable.h"> </File> <File - RelativePath=".\pattern.h"> + RelativePath="..\soundlib\pattern.h"> </File> <File - RelativePath=".\patternContainer.h"> + RelativePath="..\soundlib\patternContainer.h"> </File> <File RelativePath=".\PatternGotoDialog.h"> @@ -819,7 +819,7 @@ RelativePath=".\PerformanceCounter.h"> </File> <File - RelativePath=".\PlaybackEventer.h"> + RelativePath="..\soundlib\PlaybackEventer.h"> </File> <File RelativePath=".\PSRatioCalc.h"> Deleted: trunk/OpenMPT/mptrack/pattern.cpp =================================================================== --- trunk/OpenMPT/mptrack/pattern.cpp 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/pattern.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -1,232 +0,0 @@ -#include "stdafx.h" -#include "pattern.h" -#include "patternContainer.h" -#include "mainfrm.h" -#include "moddoc.h" - - -CHANNELINDEX CPattern::GetNumChannels() const -//------------------------------------------- -{ - return m_rPatternContainer.GetSoundFile().GetNumChannels(); -} - -bool CPattern::Resize(const ROWINDEX newRowCount, const bool showDataLossWarning) -//------------------------------------------- -{ - if(m_ModCommands == NULL) - { - //For Mimicing old behavior of setting patternsize before even having the - //actual pattern allocated. - m_Rows = newRowCount; - return false; - } - - - CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); - const CModSpecifications& specs = sndFile.GetModSpecifications(); - if(sndFile.m_pModDoc == NULL) return true; - CModDoc& rModDoc = *sndFile.m_pModDoc; - if(newRowCount > specs.patternRowsMax || newRowCount < specs.patternRowsMin) - return true; - - if (newRowCount == m_Rows) return false; - rModDoc.BeginWaitCursor(); - BEGIN_CRITICAL(); - if (newRowCount > m_Rows) - { - MODCOMMAND *p = CSoundFile::AllocatePattern(newRowCount, sndFile.m_nChannels); - if (p) - { - memcpy(p, m_ModCommands, sndFile.m_nChannels*m_Rows*sizeof(MODCOMMAND)); - CSoundFile::FreePattern(m_ModCommands); - m_ModCommands = p; - m_Rows = newRowCount; - } - } else - { - BOOL bOk = TRUE; - MODCOMMAND *p = m_ModCommands; - UINT ndif = (m_Rows - newRowCount) * sndFile.m_nChannels; - UINT npos = newRowCount * sndFile.m_nChannels; - if(showDataLossWarning) - { - for (UINT i=0; i<ndif; i++) - { - if (*((DWORD *)(p+i+npos))) - { - bOk = FALSE; - break; - } - } - if (!bOk && showDataLossWarning) - { - END_CRITICAL(); - rModDoc.EndWaitCursor(); - if (CMainFrame::GetMainFrame()->MessageBox("Data at the end of the pattern will be lost.\nDo you want to continue", - "Shrink Pattern", MB_YESNO|MB_ICONQUESTION) == IDYES) bOk = TRUE; - rModDoc.BeginWaitCursor(); - BEGIN_CRITICAL(); - } - } - if (bOk) - { - MODCOMMAND *pnew = CSoundFile::AllocatePattern(newRowCount, sndFile.m_nChannels); - if (pnew) - { - memcpy(pnew, m_ModCommands, sndFile.m_nChannels*newRowCount*sizeof(MODCOMMAND)); - CSoundFile::FreePattern(m_ModCommands); - m_ModCommands = pnew; - m_Rows = newRowCount; - } - } - } - END_CRITICAL(); - rModDoc.EndWaitCursor(); - rModDoc.SetModified(); - return (newRowCount == m_Rows) ? false : true; -} - - -bool CPattern::ClearData() -//------------------------ -{ - BEGIN_CRITICAL(); - m_Rows = 0; - CSoundFile::FreePattern(m_ModCommands); - m_ModCommands = NULL; - END_CRITICAL(); - return false; -} - -bool CPattern::Expand() -//--------------------- -{ - MODCOMMAND *newPattern, *oldPattern; - UINT nRows, nChns; - - CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); - if(sndFile.m_pModDoc == NULL) return true; - - CModDoc& rModDoc = *sndFile.m_pModDoc; - - if ((!m_ModCommands) || (m_Rows > sndFile.GetModSpecifications().patternRowsMax / 2)) return true; - - rModDoc.BeginWaitCursor(); - nRows = m_Rows; - nChns = sndFile.m_nChannels; - newPattern = CSoundFile::AllocatePattern(nRows*2, nChns); - if (!newPattern) return true; - - const UINT nPattern = m_rPatternContainer.GetIndex(this); - rModDoc.PrepareUndo(nPattern, 0,0, nChns, nRows); - oldPattern = m_ModCommands; - for (UINT y=0; y<nRows; y++) - { - memcpy(newPattern+y*2*nChns, oldPattern+y*nChns, nChns*sizeof(MODCOMMAND)); - } - m_ModCommands = newPattern; - m_Rows = nRows * 2; - CSoundFile::FreePattern(oldPattern); oldPattern= NULL; - rModDoc.SetModified(); - rModDoc.UpdateAllViews(NULL, HINT_PATTERNDATA | (nPattern << HINT_SHIFT_PAT), NULL); - rModDoc.EndWaitCursor(); - return false; -} - -bool CPattern::Shrink() -//--------------------- -{ - UINT nRows, nChns; - - if (!m_ModCommands || m_Rows < 32) return true; - - CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); - if(sndFile.m_pModDoc == NULL) return true; - - CModDoc& rModDoc = *sndFile.m_pModDoc; - - rModDoc.BeginWaitCursor(); - nRows = m_Rows; - nChns = sndFile.m_nChannels; - const UINT nPattern = m_rPatternContainer.GetIndex(this); - rModDoc.PrepareUndo(nPattern, 0,0, nChns, nRows); - nRows /= 2; - for (UINT y=0; y<nRows; y++) - { - MODCOMMAND *psrc = sndFile.Patterns[nPattern] + (y * 2 * nChns); - MODCOMMAND *pdest = sndFile.Patterns[nPattern] + (y * nChns); - for (UINT x=0; x<nChns; x++) - { - pdest[x] = psrc[x]; - if ((!pdest[x].note) && (!pdest[x].instr)) - { - pdest[x].note = psrc[x+nChns].note; - pdest[x].instr = psrc[x+nChns].instr; - if (psrc[x+nChns].volcmd) - { - pdest[x].volcmd = psrc[x+nChns].volcmd; - pdest[x].vol = psrc[x+nChns].vol; - } - if (!pdest[x].command) - { - pdest[x].command = psrc[x+nChns].command; - pdest[x].param = psrc[x+nChns].param; - } - } - } - } - m_Rows = nRows; - rModDoc.SetModified(); - rModDoc.UpdateAllViews(NULL, HINT_PATTERNDATA | (nPattern << HINT_SHIFT_PAT), NULL); - rModDoc.EndWaitCursor(); - return false; -} - - - -bool CPattern::WriteITPdata(FILE* f) const -//---------------------------------------- -{ - for(ROWINDEX r = 0; r<GetNumRows(); r++) - { - for(CHANNELINDEX c = 0; c<GetNumChannels(); c++) - { - MODCOMMAND mc = GetModCommand(r,c); - fwrite(&mc, sizeof(MODCOMMAND), 1, f); - } - } - return false; -} - -bool CPattern::ReadITPdata(const BYTE* const lpStream, DWORD& streamPos, const DWORD datasize, const DWORD dwMemLength) -//----------------------------------------------------------------------------------------------- -{ - if(streamPos > dwMemLength || datasize >= dwMemLength - streamPos || datasize < sizeof(MODCOMMAND_ORIGINAL)) - return true; - - const DWORD startPos = streamPos; - ROWINDEX counter = 0; - while(streamPos - startPos + sizeof(MODCOMMAND_ORIGINAL) <= datasize) - { - MODCOMMAND_ORIGINAL temp; - memcpy(&temp, lpStream+streamPos, sizeof(MODCOMMAND_ORIGINAL)); - MODCOMMAND& mc = GetModCommand(counter); - mc.command = temp.command; - mc.instr = temp.instr; - mc.note = temp.note; - mc.param = temp.param; - mc.vol = temp.vol; - mc.volcmd = temp.volcmd; - streamPos += sizeof(MODCOMMAND_ORIGINAL); - counter++; - } - if(streamPos != startPos + datasize) - { - ASSERT(false); - return true; - } - else - return false; -} - Deleted: trunk/OpenMPT/mptrack/pattern.h =================================================================== --- trunk/OpenMPT/mptrack/pattern.h 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/pattern.h 2009-06-24 19:39:33 UTC (rev 276) @@ -1,91 +0,0 @@ -#ifndef PATTERN_H -#define PATTERN_H - -#include <vector> -#include "modcommand.h" - -using std::vector; - -class CPatternContainer; - -typedef MODCOMMAND* PatternRow; - - -//============ -class CPattern -//============ -{ - friend class CPatternContainer; - -public: -//BEGIN: OPERATORS - //To mimic MODCOMMAND* - operator MODCOMMAND*() {return m_ModCommands;} - operator const MODCOMMAND*() const {return m_ModCommands;} - CPattern& operator=(MODCOMMAND* const p) {m_ModCommands = p; return *this;} - CPattern& operator=(const CPattern& pat) - { - m_ModCommands = pat.m_ModCommands; - m_Rows = pat.m_Rows; - return *this; - } -//END: OPERATORS - -//BEGIN: INTERFACE METHODS -public: - MODCOMMAND* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) {return &m_ModCommands[r*GetNumChannels()+c];} - const MODCOMMAND* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) const {return &m_ModCommands[r*GetNumChannels()+c];} - - ROWINDEX GetNumRows() const {return m_Rows;} - - // Return true if modcommand can be accessed from given row, false otherwise. - bool IsValidRow(const ROWINDEX iRow) const {return (iRow < GetNumRows());} - - // Return PatternRow object which has operator[] defined so that MODCOMMAND - // at (iRow, iChn) can be accessed with GetRow(iRow)[iChn]. - PatternRow GetRow(const ROWINDEX iRow) {return GetpModCommand(iRow, 0);} - - CHANNELINDEX GetNumChannels() const; - - bool Resize(const ROWINDEX newRowCount, const bool showDataLossWarning = true); - - bool ClearData(); - - bool SetData(MODCOMMAND* p, const ROWINDEX rows) {m_ModCommands = p; m_Rows = rows; return false;} - - bool Expand(); - - bool Shrink(); - - bool WriteITPdata(FILE* f) const; - bool ReadITPdata(const BYTE* const lpStream, DWORD& streamPos, const DWORD datasize, const DWORD dwMemLength); - //Parameters: - //1. Pointer to the beginning of the stream - //2. Tells where to start(lpStream+streamPos) and number of bytes read is added to it. - //3. How many bytes to read - //4. Length of the stream. - //Returns true on error. - -//END: INTERFACE METHODS - - CPattern(CPatternContainer& patCont) : m_ModCommands(0), m_Rows(64), m_rPatternContainer(patCont) {} - -private: - MODCOMMAND& GetModCommand(ROWINDEX i) {return m_ModCommands[i];} - //Returns modcommand from (floor[i/channelCount], i%channelCount) - - MODCOMMAND& GetModCommand(ROWINDEX r, CHANNELINDEX c) {return m_ModCommands[r*GetNumChannels()+c];} - const MODCOMMAND& GetModCommand(ROWINDEX r, CHANNELINDEX c) const {return m_ModCommands[r*GetNumChannels()+c];} - - -//BEGIN: DATA -private: - MODCOMMAND* m_ModCommands; - ROWINDEX m_Rows; - CPatternContainer& m_rPatternContainer; -//END: DATA -}; - - - -#endif Deleted: trunk/OpenMPT/mptrack/patternContainer.cpp =================================================================== --- trunk/OpenMPT/mptrack/patternContainer.cpp 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/patternContainer.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -1,100 +0,0 @@ -#include "stdafx.h" -#include "patternContainer.h" -#include "sndfile.h" -#include "mainfrm.h" - -int CPatternContainer::Insert(const ROWINDEX rows) -//--------------------------------------------- -{ - PATTERNINDEX i = 0; - for(i = 0; i<m_Patterns.size(); i++) - if(!m_Patterns[i]) break; - if(Insert(i, rows)) - return -1; - else return i; - -} - - -bool CPatternContainer::Insert(const PATTERNINDEX index, const ROWINDEX rows) -//--------------------------------------------------------------- -{ - const CModSpecifications& specs = m_rSndFile.GetModSpecifications(); - if(index >= specs.patternsMax || index > m_Patterns.size() || rows > specs.patternRowsMax) - return true; - if(index < m_Patterns.size() && m_Patterns[index]) - return true; - - if(index == m_Patterns.size()) - { - if(index < specs.patternsMax) - m_Patterns.push_back(MODPATTERN(*this)); - else - { - ErrorBox(IDS_ERR_TOOMANYPAT, CMainFrame::GetMainFrame()); - return true; - } - } - - m_Patterns[index] = CSoundFile::AllocatePattern(rows, m_rSndFile.m_nChannels); - m_Patterns[index].m_Rows = rows; - - if(!m_Patterns[index]) return true; - - return false; -} - -bool CPatternContainer::Remove(const PATTERNINDEX ipat) -//---------------------------------------------- -{ - if(ipat >= m_Patterns.size()) - return true; - - return m_Patterns[ipat].ClearData(); -} - -PATTERNINDEX CPatternContainer::GetIndex(const MODPATTERN* const pPat) const -//------------------------------------------------------------------ -{ - const PATTERNINDEX endI = static_cast<PATTERNINDEX>(m_Patterns.size()); - for(PATTERNINDEX i = 0; i<endI; i++) - if(&m_Patterns[i] == pPat) return i; - - return endI; -} - - -void CPatternContainer::ResizeArray(const PATTERNINDEX newSize) -//------------------------------------------------------------- -{ - if(Size() <= newSize) - m_Patterns.resize(newSize, MODPATTERN(*this)); - else - { - for(PATTERNINDEX i = Size(); i > newSize; i--) Remove(i-1); - m_Patterns.resize(newSize, MODPATTERN(*this)); - } -} - - -void CPatternContainer::OnModTypeChanged(const MODTYPE /*oldtype*/) -//---------------------------------------------------------- -{ - const CModSpecifications specs = m_rSndFile.GetModSpecifications(); - if(specs.patternsMax < Size()) ResizeArray(max(MAX_PATTERNS, specs.patternsMax)); - else if(Size() < MAX_PATTERNS) ResizeArray(MAX_PATTERNS); -} - - -void CPatternContainer::Init() -//---------------------------- -{ - for(PATTERNINDEX i = 0; i < Size(); i++) - { - Remove(i); - } - - ResizeArray(MAX_PATTERNS); -} - - Deleted: trunk/OpenMPT/mptrack/patternContainer.h =================================================================== --- trunk/OpenMPT/mptrack/patternContainer.h 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/mptrack/patternContainer.h 2009-06-24 19:39:33 UTC (rev 276) @@ -1,77 +0,0 @@ -#ifdef __SNDFILE_H - -#ifndef PATTERNCONTAINER_H -#define PATTERNCONTAINER_H - -#include "pattern.h" -#include <limits> - -class CSoundFile; -typedef CPattern MODPATTERN; - -//===================== -class CPatternContainer -//===================== -{ -//BEGIN: TYPEDEFS -public: - typedef vector<MODPATTERN> PATTERNVECTOR; -//END: TYPEDEFS - - -//BEGIN: OPERATORS -public: - //To mimic old pattern == MODCOMMAND* behavior. - MODPATTERN& operator[](const int pat) {return m_Patterns[pat];} - const MODPATTERN& operator[](const int pat) const {return m_Patterns[pat];} -//END: OPERATORS - -//BEGIN: INTERFACE METHODS -public: - CPatternContainer(CSoundFile& sndFile) : m_rSndFile(sndFile) {m_Patterns.assign(MAX_PATTERNS, MODPATTERN(*this));} - - // Clears existing patterns and resizes array to default size. - void Init(); - - //Note: No memory handling here. - void ClearPatterns() {m_Patterns.assign(m_Patterns.size(), MODPATTERN(*this));} - - //Insert (default)pattern to given position. If pattern already exists at that position, - //ignoring request. - bool Insert(const PATTERNINDEX index, const ROWINDEX rows); - - //Insert pattern to position with the lowest index, and return that index, -1 - //on failure. - int Insert(const ROWINDEX rows); - - //Remove pattern from given position. Currently it actually makes the pattern - //'invisible' - the pattern data is cleared but the actual pattern object won't get removed. - bool Remove(const PATTERNINDEX index); - - PATTERNINDEX Size() const {return static_cast<PATTERNINDEX>(m_Patterns.size());} - - CSoundFile& GetSoundFile() {return m_rSndFile;} - - //Returns the index of given pattern, Size() if not found. - PATTERNINDEX GetIndex(const MODPATTERN* const pPat) const; - - // Return true if pattern can be accessed with operator[](iPat), false otherwise. - bool IsValidIndex(const PATTERNINDEX iPat) const {return (iPat < Size());} - - void ResizeArray(const PATTERNINDEX newSize); - - void OnModTypeChanged(const MODTYPE oldtype); - -//END: INTERFACE METHODS - - -//BEGIN: DATA MEMBERS -private: - PATTERNVECTOR m_Patterns; - CSoundFile& m_rSndFile; -//END: DATA MEMBERS - -}; - -#endif -#endif Copied: trunk/OpenMPT/soundlib/OrderToPatternTable.cpp (from rev 271, trunk/OpenMPT/mptrack/OrderToPatternTable.cpp) =================================================================== --- trunk/OpenMPT/soundlib/OrderToPatternTable.cpp (rev 0) +++ trunk/OpenMPT/soundlib/OrderToPatternTable.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,228 @@ +#include "stdafx.h" +#include "sndfile.h" +#include "ordertopatterntable.h" + +#define str_SequenceTruncationNote (GetStrI18N((_TEXT("Module has sequence of length %u; it will be truncated to maximum supported length, %u.")))) + +DWORD COrderToPatternTable::Unserialize(const BYTE* const src, const DWORD memLength) +//------------------------------------------------------------------------- +{ + if(memLength < 2 + 4) return 0; + uint16 version = 0; + uint32 s = 0; + DWORD memPos = 0; + memcpy(&version, src, sizeof(version)); + memPos += sizeof(version); + if(version != 0) return memPos; + memcpy(&s, src+memPos, sizeof(s)); + memPos += sizeof(s); + if(s > 65000) return true; + if(memLength < memPos+s*4) return memPos; + + const uint32 nOriginalSize = s; + if(s > MPTM_SPECS.ordersMax) + s = MPTM_SPECS.ordersMax; + + resize(s); + for(size_t i = 0; i<s; i++, memPos +=4 ) + { + uint32 temp; + memcpy(&temp, src+memPos, 4); + (*this)[i] = static_cast<PATTERNINDEX>(temp); + } + memPos += 4*(nOriginalSize - s); + return memPos; +} + + +size_t COrderToPatternTable::WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize) +//----------------------------------------------------------------------------- +{ + if(numOfBytes > destSize) return true; + if(size() < numOfBytes) resize(numOfBytes, 0xFF); + UINT i = 0; + for(i = 0; i<numOfBytes; i++) + { + dest[i] = static_cast<BYTE>((*this)[i]); + } + return i; //Returns the number of bytes written. +} + + +size_t COrderToPatternTable::WriteAsByte(FILE* f, const UINT count) +//--------------------------------------------------------------- +{ + if(size() < count) resize(count, GetInvalidPatIndex()); + + size_t i = 0; + + for(i = 0; i<count; i++) + { + const PATTERNINDEX pat = (*this)[i]; + BYTE temp = static_cast<BYTE>((*this)[i]); + + if(pat > 0xFD) + { + if(pat == GetInvalidPatIndex()) temp = 0xFF; + else temp = 0xFE; + } + fwrite(&temp, 1, 1, f); + } + return i; //Returns the number of bytes written. +} + +bool COrderToPatternTable::ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength) +//------------------------------------------------------------------------- +{ + if(howMany < 0 || howMany > memLength) return true; + if(m_rSndFile.GetType() != MOD_TYPE_MPT && howMany > MAX_ORDERS) return true; + + if(size() < static_cast<size_t>(howMany)) + resize(howMany, GetInvalidPatIndex()); + + for(int i = 0; i<howMany; i++, pFrom++) + (*this)[i] = *pFrom; + return false; +} + + +bool COrderToPatternTable::NeedsExtraDatafield() const +//---------------------------------------------- +{ + if(m_rSndFile.GetType() == MOD_TYPE_MPT && m_rSndFile.Patterns.Size() > 0xFD) + return true; + else + return false; +} + + +void COrderToPatternTable::OnModTypeChanged(const MODTYPE oldtype) +//---------------------------------------------------------------- +{ + const CModSpecifications specs = m_rSndFile.GetModSpecifications(); + + //Resize orderlist if needed. Because old orderlist had MAX_ORDERS(256) elements, not making it + //smaller than that even if the modtype doesn't support that many orders. + if(specs.ordersMax < GetCount()) + { + resize(max(MAX_ORDERS, specs.ordersMax)); + for(ORDERINDEX i = GetCount(); i>specs.ordersMax; --i) (*this)[i-1] = GetInvalidPatIndex(); + } + + //Replace items used to denote end of song/skip order. + replace(begin(), end(), GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); + replace(begin(), end(), GetIgnoreIndex(oldtype), GetIgnoreIndex()); +} + + +ORDERINDEX COrderToPatternTable::GetLengthTailTrimmed() const +//----------------------------------------------------------- +{ + ORDERINDEX nEnd = GetCount(); + if(nEnd == 0) return 0; + nEnd--; + const PATTERNINDEX iInvalid = GetInvalidPatIndex(); + while(nEnd > 0 && (*this)[nEnd] == iInvalid) + nEnd--; + return ((*this)[nEnd] == iInvalid) ? 0 : nEnd+1; +} + + +ORDERINDEX COrderToPatternTable::GetLengthFirstEmpty() const +//---------------------------------------------------------- +{ + const ORDERINDEX nLength = GetCount(); + ORDERINDEX nMax = 0; + while ((nMax < nLength) && ((*this)[nMax] != (*this).GetInvalidPatIndex())) nMax++; + return nMax; +} + + +ORDERINDEX COrderToPatternTable::GetNextOrderIgnoringSkips(const ORDERINDEX start) const +//------------------------------------------------------------------------------------- +{ + const ORDERINDEX count = GetCount(); + if(count == 0) return 0; + ORDERINDEX next = min(count-1, start+1); + while(next+1 < count && (*this)[next] == GetIgnoreIndex()) next++; + return next; +} + +ORDERINDEX COrderToPatternTable::GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const +//------------------------------------------------------------------------------------- +{ + const ORDERINDEX count = GetCount(); + if(start == 0 || count == 0) return 0; + ORDERINDEX prev = min(start-1, count-1); + while(prev > 0 && (*this)[prev] == GetIgnoreIndex()) prev--; + return prev; +} + + +void COrderToPatternTable::Init() +//------------------------------- +{ + resize(MAX_ORDERS, GetInvalidPatIndex()); + for(ORDERINDEX i = 0; i < GetCount(); i++) + { + (*this)[i] = GetInvalidPatIndex(); + } +} + + + +PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65535 : 0xFF;} +PATTERNINDEX COrderToPatternTable::GetIgnoreIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65534 : 0xFE;} + +PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex() const {return GetInvalidPatIndex(m_rSndFile.GetType());} +PATTERNINDEX COrderToPatternTable::GetIgnoreIndex() const {return GetIgnoreIndex(m_rSndFile.GetType());} + + + + +//-------------------------------------------------- +//-------------------------------------------------- +//-------------------------------------------------- + +using namespace srlztn; + +void COrderSerialization::ProWrite(OUTSTREAM& ostrm) const +//-------------------------------------------------------- +{ + uint16 size = static_cast<uint16>(m_rOrders.size()); + ostrm.write(reinterpret_cast<const char*>(&size), 2); + const COrderToPatternTable::const_iterator endIter = m_rOrders.end(); + for(COrderToPatternTable::const_iterator citer = m_rOrders.begin(); citer != endIter; citer++) + { + const uint16 temp = static_cast<uint16>(*citer); + ostrm.write(reinterpret_cast<const char*>(&temp), 2); + } +} + + +void COrderSerialization::ProRead(INSTREAM& istrm, const uint64 /*datasize*/) +//--------------------------------------------------------------------------- +{ + uint16 size; + istrm.read(reinterpret_cast<char*>(&size), 2); + if(size > MPTM_SPECS.ordersMax) + { + // Hack: Show message here if trying to load longer sequence than what is supported. + CString str; str.Format(str_SequenceTruncationNote, size, MPTM_SPECS.ordersMax); + ::MessageBox(0, str, "", MB_ICONWARNING); + size = MPTM_SPECS.ordersMax; + } + m_rOrders.resize(size); + if(size == 0) {m_rOrders.assign(MAX_ORDERS, m_rOrders.GetInvalidPatIndex()); return;} + + const COrderToPatternTable::const_iterator endIter = m_rOrders.end(); + for(COrderToPatternTable::iterator iter = m_rOrders.begin(); iter != endIter; iter++) + { + uint16 temp; + istrm.read(reinterpret_cast<char*>(&temp), 2); + *iter = temp; + } +} + + + Copied: trunk/OpenMPT/soundlib/OrderToPatternTable.h (from rev 271, trunk/OpenMPT/mptrack/OrderToPatternTable.h) =================================================================== --- trunk/OpenMPT/soundlib/OrderToPatternTable.h (rev 0) +++ trunk/OpenMPT/soundlib/OrderToPatternTable.h 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,77 @@ +#ifndef ORDERTOPATTERNTABLE_H +#define ORDERTOPATTERNTABLE_H + +#include "../mptrack/serialization_utils.h" +#include <vector> +using std::vector; + +class CSoundFile; +class COrderToPatternTable; + +#pragma warning(disable:4244) //conversion from 'type1' to 'type2', possible loss of data + +class COrderSerialization : public srlztn::ABCSerializationStreamer +//========================================================= +{ +public: + COrderSerialization(COrderToPatternTable& ordertable) : m_rOrders(ordertable) {} + virtual void ProWrite(srlztn::OUTSTREAM& ostrm) const; + virtual void ProRead(srlztn::INSTREAM& istrm, const uint64 /*datasize*/); +private: + COrderToPatternTable& m_rOrders; +}; + +//============================================== +class COrderToPatternTable : public vector<PATTERNINDEX> +//============================================== +{ +public: + COrderToPatternTable(const CSoundFile& sndFile) : m_rSndFile(sndFile) {} + + // Initialize default sized sequence. + void Init(); + + bool ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength); + + size_t WriteAsByte(FILE* f, const UINT count); + + size_t WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize); + + ORDERINDEX GetCount() const {return size();} + + //Deprecated function used for MPTm's created in 1.17.02.46 - 1.17.02.48. + DWORD Unserialize(const BYTE* const src, const DWORD memLength); + + //Returns true if the IT orderlist datafield is not sufficient to store orderlist information. + bool NeedsExtraDatafield() const; + + void OnModTypeChanged(const MODTYPE oldtype); + + // Returns length of sequence without counting trailing '---' items. + ORDERINDEX GetLengthTailTrimmed() const; + + // Returns length of sequence stopping counting on first '---' (or at the end of sequence). + ORDERINDEX GetLengthFirstEmpty() const; + + PATTERNINDEX GetInvalidPatIndex() const; //To correspond 0xFF + static PATTERNINDEX GetInvalidPatIndex(const MODTYPE type); + + PATTERNINDEX GetIgnoreIndex() const; //To correspond 0xFE + static PATTERNINDEX GetIgnoreIndex(const MODTYPE type); + + //Returns the previous/next order ignoring skip indeces(+++). + //If no previous/next order exists, return first/last order, and zero + //when orderlist is empty. + ORDERINDEX GetNextOrderIgnoringSkips(const ORDERINDEX start) const; + ORDERINDEX GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const; + + COrderSerialization* NewReadWriteObject() {return new COrderSerialization(*this);} + +private: + const CSoundFile& m_rSndFile; +}; + +#pragma warning(default:4244) + +#endif + Copied: trunk/OpenMPT/soundlib/PlaybackEventer.cpp (from rev 217, trunk/OpenMPT/mptrack/PlaybackEventer.cpp) =================================================================== --- trunk/OpenMPT/soundlib/PlaybackEventer.cpp (rev 0) +++ trunk/OpenMPT/soundlib/PlaybackEventer.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,31 @@ +#include "stdafx.h" +#include "PlaybackEventer.h" +#include "sndfile.h" + +CPlaybackEventer::~CPlaybackEventer() +//--------------------------------- +{ +} + +void CPlaybackEventer::PatternTranstionChnSolo(const CHANNELINDEX chnIndex) +//------------------------------------------------------------------------- +{ + if(chnIndex >= m_rSndFile.m_nChannels) + return; + + for(CHANNELINDEX i = 0; i<m_rSndFile.m_nChannels; i++) + { + m_rSndFile.m_bChannelMuteTogglePending[i] = (m_rSndFile.ChnSettings[i].dwFlags & CHN_MUTE) ? false : true; + } + m_rSndFile.m_bChannelMuteTogglePending[chnIndex] = (m_rSndFile.ChnSettings[chnIndex].dwFlags & CHN_MUTE) ? true : false; +} + + +void CPlaybackEventer::PatternTransitionChnUnmuteAll() +//---------------------------------------------------- +{ + for(CHANNELINDEX i = 0; i<m_rSndFile.m_nChannels; i++) + { + m_rSndFile.m_bChannelMuteTogglePending[i] = (m_rSndFile.ChnSettings[i].dwFlags & CHN_MUTE) ? true : false; + } +} \ No newline at end of file Copied: trunk/OpenMPT/soundlib/PlaybackEventer.h (from rev 217, trunk/OpenMPT/mptrack/PlaybackEventer.h) =================================================================== --- trunk/OpenMPT/soundlib/PlaybackEventer.h (rev 0) +++ trunk/OpenMPT/soundlib/PlaybackEventer.h 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,25 @@ +#ifndef PLAYBACKEVENTER_H +#define PLAYBACKEVENTER_H + +#include "pattern.h" + +class CSoundFile; + +//==================== +class CPlaybackEventer +//==================== +{ +public: + CPlaybackEventer(CSoundFile& sndf) : m_rSndFile(sndf) {} + ~CPlaybackEventer(); + + //SetPatternEvent(const PATTERNINDEX pattern, const ROWINDEX row, const CHANNELINDEX column); + + void PatternTranstionChnSolo(const CHANNELINDEX chnIndex); + void PatternTransitionChnUnmuteAll(); + +private: + CSoundFile& m_rSndFile; +}; + +#endif Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-24 15:54:18 UTC (rev 275) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-24 19:39:33 UTC (rev 276) @@ -805,11 +805,11 @@ typedef VOID (__cdecl * LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels -#include "../mptrack/pattern.h" -#include "../mptrack/patternContainer.h" -#include "../mptrack/ordertopatterntable.h" +#include "pattern.h" +#include "patternContainer.h" +#include "ordertopatterntable.h" -#include "../mptrack/playbackEventer.h" +#include "playbackEventer.h" Copied: trunk/OpenMPT/soundlib/pattern.cpp (from rev 217, trunk/OpenMPT/mptrack/pattern.cpp) =================================================================== --- trunk/OpenMPT/soundlib/pattern.cpp (rev 0) +++ trunk/OpenMPT/soundlib/pattern.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,232 @@ +#include "stdafx.h" +#include "pattern.h" +#include "patternContainer.h" +#include "../mptrack/mainfrm.h" +#include "../mptrack/moddoc.h" + + +CHANNELINDEX CPattern::GetNumChannels() const +//------------------------------------------- +{ + return m_rPatternContainer.GetSoundFile().GetNumChannels(); +} + +bool CPattern::Resize(const ROWINDEX newRowCount, const bool showDataLossWarning) +//------------------------------------------- +{ + if(m_ModCommands == NULL) + { + //For Mimicing old behavior of setting patternsize before even having the + //actual pattern allocated. + m_Rows = newRowCount; + return false; + } + + + CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); + const CModSpecifications& specs = sndFile.GetModSpecifications(); + if(sndFile.m_pModDoc == NULL) return true; + CModDoc& rModDoc = *sndFile.m_pModDoc; + if(newRowCount > specs.patternRowsMax || newRowCount < specs.patternRowsMin) + return true; + + if (newRowCount == m_Rows) return false; + rModDoc.BeginWaitCursor(); + BEGIN_CRITICAL(); + if (newRowCount > m_Rows) + { + MODCOMMAND *p = CSoundFile::AllocatePattern(newRowCount, sndFile.m_nChannels); + if (p) + { + memcpy(p, m_ModCommands, sndFile.m_nChannels*m_Rows*sizeof(MODCOMMAND)); + CSoundFile::FreePattern(m_ModCommands); + m_ModCommands = p; + m_Rows = newRowCount; + } + } else + { + BOOL bOk = TRUE; + MODCOMMAND *p = m_ModCommands; + UINT ndif = (m_Rows - newRowCount) * sndFile.m_nChannels; + UINT npos = newRowCount * sndFile.m_nChannels; + if(showDataLossWarning) + { + for (UINT i=0; i<ndif; i++) + { + if (*((DWORD *)(p+i+npos))) + { + bOk = FALSE; + break; + } + } + if (!bOk && showDataLossWarning) + { + END_CRITICAL(); + rModDoc.EndWaitCursor(); + if (CMainFrame::GetMainFrame()->MessageBox("Data at the end of the pattern will be lost.\nDo you want to continue", + "Shrink Pattern", MB_YESNO|MB_ICONQUESTION) == IDYES) bOk = TRUE; + rModDoc.BeginWaitCursor(); + BEGIN_CRITICAL(); + } + } + if (bOk) + { + MODCOMMAND *pnew = CSoundFile::AllocatePattern(newRowCount, sndFile.m_nChannels); + if (pnew) + { + memcpy(pnew, m_ModCommands, sndFile.m_nChannels*newRowCount*sizeof(MODCOMMAND)); + CSoundFile::FreePattern(m_ModCommands); + m_ModCommands = pnew; + m_Rows = newRowCount; + } + } + } + END_CRITICAL(); + rModDoc.EndWaitCursor(); + rModDoc.SetModified(); + return (newRowCount == m_Rows) ? false : true; +} + + +bool CPattern::ClearData() +//------------------------ +{ + BEGIN_CRITICAL(); + m_Rows = 0; + CSoundFile::FreePattern(m_ModCommands); + m_ModCommands = NULL; + END_CRITICAL(); + return false; +} + +bool CPattern::Expand() +//--------------------- +{ + MODCOMMAND *newPattern, *oldPattern; + UINT nRows, nChns; + + CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); + if(sndFile.m_pModDoc == NULL) return true; + + CModDoc& rModDoc = *sndFile.m_pModDoc; + + if ((!m_ModCommands) || (m_Rows > sndFile.GetModSpecifications().patternRowsMax / 2)) return true; + + rModDoc.BeginWaitCursor(); + nRows = m_Rows; + nChns = sndFile.m_nChannels; + newPattern = CSoundFile::AllocatePattern(nRows*2, nChns); + if (!newPattern) return true; + + const UINT nPattern = m_rPatternContainer.GetIndex(this); + rModDoc.PrepareUndo(nPattern, 0,0, nChns, nRows); + oldPattern = m_ModCommands; + for (UINT y=0; y<nRows; y++) + { + memcpy(newPattern+y*2*nChns, oldPattern+y*nChns, nChns*sizeof(MODCOMMAND)); + } + m_ModCommands = newPattern; + m_Rows = nRows * 2; + CSoundFile::FreePattern(oldPattern); oldPattern= NULL; + rModDoc.SetModified(); + rModDoc.UpdateAllViews(NULL, HINT_PATTERNDATA | (nPattern << HINT_SHIFT_PAT), NULL); + rModDoc.EndWaitCursor(); + return false; +} + +bool CPattern::Shrink() +//--------------------- +{ + UINT nRows, nChns; + + if (!m_ModCommands || m_Rows < 32) return true; + + CSoundFile& sndFile = m_rPatternContainer.GetSoundFile(); + if(sndFile.m_pModDoc == NULL) return true; + + CModDoc& rModDoc = *sndFile.m_pModDoc; + + rModDoc.BeginWaitCursor(); + nRows = m_Rows; + nChns = sndFile.m_nChannels; + const UINT nPattern = m_rPatternContainer.GetIndex(this); + rModDoc.PrepareUndo(nPattern, 0,0, nChns, nRows); + nRows /= 2; + for (UINT y=0; y<nRows; y++) + { + MODCOMMAND *psrc = sndFile.Patterns[nPattern] + (y * 2 * nChns); + MODCOMMAND *pdest = sndFile.Patterns[nPattern] + (y * nChns); + for (UINT x=0; x<nChns; x++) + { + pdest[x] = psrc[x]; + if ((!pdest[x].note) && (!pdest[x].instr)) + { + pdest[x].note = psrc[x+nChns].note; + pdest[x].instr = psrc[x+nChns].instr; + if (psrc[x+nChns].volcmd) + { + pdest[x].volcmd = psrc[x+nChns].volcmd; + pdest[x].vol = psrc[x+nChns].vol; + } + if (!pdest[x].command) + { + pdest[x].command = psrc[x+nChns].command; + pdest[x].param = psrc[x+nChns].param; + } + } + } + } + m_Rows = nRows; + rModDoc.SetModified(); + rModDoc.UpdateAllViews(NULL, HINT_PATTERNDATA | (nPattern << HINT_SHIFT_PAT), NULL); + rModDoc.EndWaitCursor(); + return false; +} + + + +bool CPattern::WriteITPdata(FILE* f) const +//---------------------------------------- +{ + for(ROWINDEX r = 0; r<GetNumRows(); r++) + { + for(CHANNELINDEX c = 0; c<GetNumChannels(); c++) + { + MODCOMMAND mc = GetModCommand(r,c); + fwrite(&mc, sizeof(MODCOMMAND), 1, f); + } + } + return false; +} + +bool CPattern::ReadITPdata(const BYTE* const lpStream, DWORD& streamPos, const DWORD datasize, const DWORD dwMemLength) +//----------------------------------------------------------------------------------------------- +{ + if(streamPos > dwMemLength || datasize >= dwMemLength - streamPos || datasize < sizeof(MODCOMMAND_ORIGINAL)) + return true; + + const DWORD startPos = streamPos; + ROWINDEX counter = 0; + while(streamPos - startPos + sizeof(MODCOMMAND_ORIGINAL) <= datasize) + { + MODCOMMAND_ORIGINAL temp; + memcpy(&temp, lpStream+streamPos, sizeof(MODCOMMAND_ORIGINAL)); + MODCOMMAND& mc = GetModCommand(counter); + mc.command = temp.command; + mc.instr = temp.instr; + mc.note = temp.note; + mc.param = temp.param; + mc.vol = temp.vol; + mc.volcmd = temp.volcmd; + streamPos += sizeof(MODCOMMAND_ORIGINAL); + counter++; + } + if(streamPos != startPos + datasize) + { + ASSERT(false); + return true; + } + else + return false; +} + Copied: trunk/OpenMPT/soundlib/pattern.h (from rev 244, trunk/OpenMPT/mptrack/pattern.h) =================================================================== --- trunk/OpenMPT/soundlib/pattern.h (rev 0) +++ trunk/OpenMPT/soundlib/pattern.h 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,91 @@ +#ifndef PATTERN_H +#define PATTERN_H + +#include <vector> +#include "modcommand.h" + +using std::vector; + +class CPatternContainer; + +typedef MODCOMMAND* PatternRow; + + +//============ +class CPattern +//============ +{ + friend class CPatternContainer; + +public: +//BEGIN: OPERATORS + //To mimic MODCOMMAND* + operator MODCOMMAND*() {return m_ModCommands;} + operator const MODCOMMAND*() const {return m_ModCommands;} + CPattern& operator=(MODCOMMAND* const p) {m_ModCommands = p; return *this;} + CPattern& operator=(const CPattern& pat) + { + m_ModCommands = pat.m_ModCommands; + m_Rows = pat.m_Rows; + return *this; + } +//END: OPERATORS + +//BEGIN: INTERFACE METHODS +public: + MODCOMMAND* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) {return &m_ModCommands[r*GetNumChannels()+c];} + const MODCOMMAND* GetpModCommand(const ROWINDEX r, const CHANNELINDEX c) const {return &m_ModCommands[r*GetNumChannels()+c];} + + ROWINDEX GetNumRows() const {return m_Rows;} + + // Return true if modcommand can be accessed from given row, false otherwise. + bool IsValidRow(const ROWINDEX iRow) const {return (iRow < GetNumRows());} + + // Return PatternRow object which has operator[] defined so that MODCOMMAND + // at (iRow, iChn) can be accessed with GetRow(iRow)[iChn]. + PatternRow GetRow(const ROWINDEX iRow) {return GetpModCommand(iRow, 0);} + + CHANNELINDEX GetNumChannels() const; + + bool Resize(const ROWINDEX newRowCount, const bool showDataLossWarning = true); + + bool ClearData(); + + bool SetData(MODCOMMAND* p, const ROWINDEX rows) {m_ModCommands = p; m_Rows = rows; return false;} + + bool Expand(); + + bool Shrink(); + + bool WriteITPdata(FILE* f) const; + bool ReadITPdata(const BYTE* const lpStream, DWORD& streamPos, const DWORD datasize, const DWORD dwMemLength); + //Parameters: + //1. Pointer to the beginning of the stream + //2. Tells where to start(lpStream+streamPos) and number of bytes read is added to it. + //3. How many bytes to read + //4. Length of the stream. + //Returns true on error. + +//END: INTERFACE METHODS + + CPattern(CPatternContainer& patCont) : m_ModCommands(0), m_Rows(64), m_rPatternContainer(patCont) {} + +private: + MODCOMMAND& GetModCommand(ROWINDEX i) {return m_ModCommands[i];} + //Returns modcommand from (floor[i/channelCount], i%channelCount) + + MODCOMMAND& GetModCommand(ROWINDEX r, CHANNELINDEX c) {return m_ModCommands[r*GetNumChannels()+c];} + const MODCOMMAND& GetModCommand(ROWINDEX r, CHANNELINDEX c) const {return m_ModCommands[r*GetNumChannels()+c];} + + +//BEGIN: DATA +private: + MODCOMMAND* m_ModCommands; + ROWINDEX m_Rows; + CPatternContainer& m_rPatternContainer; +//END: DATA +}; + + + +#endif Copied: trunk/OpenMPT/soundlib/patternContainer.cpp (from rev 271, trunk/OpenMPT/mptrack/patternContainer.cpp) =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.cpp (rev 0) +++ trunk/OpenMPT/soundlib/patternContainer.cpp 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,100 @@ +#include "stdafx.h" +#include "patternContainer.h" +#include "sndfile.h" +#include "../mptrack/mainfrm.h" + +int CPatternContainer::Insert(const ROWINDEX rows) +//--------------------------------------------- +{ + PATTERNINDEX i = 0; + for(i = 0; i<m_Patterns.size(); i++) + if(!m_Patterns[i]) break; + if(Insert(i, rows)) + return -1; + else return i; + +} + + +bool CPatternContainer::Insert(const PATTERNINDEX index, const ROWINDEX rows) +//--------------------------------------------------------------- +{ + const CModSpecifications& specs = m_rSndFile.GetModSpecifications(); + if(index >= specs.patternsMax || index > m_Patterns.size() || rows > specs.patternRowsMax) + return true; + if(index < m_Patterns.size() && m_Patterns[index]) + return true; + + if(index == m_Patterns.size()) + { + if(index < specs.patternsMax) + m_Patterns.push_back(MODPATTERN(*this)); + else + { + ErrorBox(IDS_ERR_TOOMANYPAT, CMainFrame::GetMainFrame()); + return true; + } + } + + m_Patterns[index] = CSoundFile::AllocatePattern(rows, m_rSndFile.m_nChannels); + m_Patterns[index].m_Rows = rows; + + if(!m_Patterns[index]) return true; + + return false; +} + +bool CPatternContainer::Remove(const PATTERNINDEX ipat) +//---------------------------------------------- +{ + if(ipat >= m_Patterns.size()) + return true; + + return m_Patterns[ipat].ClearData(); +} + +PATTERNINDEX CPatternContainer::GetIndex(const MODPATTERN* const pPat) const +//------------------------------------------------------------------ +{ + const PATTERNINDEX endI = static_cast<PATTERNINDEX>(m_Patterns.size()); + for(PATTERNINDEX i = 0; i<endI; i++) + if(&m_Patterns[i] == pPat) return i; + + return endI; +} + + +void CPatternContainer::ResizeArray(const PATTERNINDEX newSize) +//------------------------------------------------------------- +{ + if(Size() <= newSize) + m_Patterns.resize(newSize, MODPATTERN(*this)); + else + { + for(PATTERNINDEX i = Size(); i > newSize; i--) Remove(i-1); + m_Patterns.resize(newSize, MODPATTERN(*this)); + } +} + + +void CPatternContainer::OnModTypeChanged(const MODTYPE /*oldtype*/) +//---------------------------------------------------------- +{ + const CModSpecifications specs = m_rSndFile.GetModSpecifications(); + if(specs.patternsMax < Size()) ResizeArray(max(MAX_PATTERNS, specs.patternsMax)); + else if(Size() < MAX_PATTERNS) ResizeArray(MAX_PATTERNS); +} + + +void CPatternContainer::Init() +//---------------------------- +{ + for(PATTERNINDEX i = 0; i < Size(); i++) + { + Remove(i); + } + + ResizeArray(MAX_PATTERNS); +} + + Copied: trunk/OpenMPT/soundlib/patternContainer.h (from rev 271, trunk/OpenMPT/mptrack/patternContainer.h) =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.h (rev 0) +++ trunk/OpenMPT/soundlib/patternContainer.h 2009-06-24 19:39:33 UTC (rev 276) @@ -0,0 +1,77 @@ +#ifdef __SNDFILE_H + +#ifndef PATTERNCONTAINER_H +#define PATTERNCONTAINER_H + +#include "pattern.h" +#include <limits> + +class CSoundFile; +typedef CPattern MODPATTERN; + +//===================== +class CPatternContainer +//===================== +{ +//BEGIN: TYPEDEFS +public: + typedef vector<MODPATTERN> PATTERNVECTOR; +//END: TYPEDEFS + + +//BEGIN: OPERATORS +public: + //To mimic old pattern == MODCOMMAND* behavior. + MODPATTERN& operator[](const int pat) {return m_Patterns[pat];} + const MODPATTERN& operator[](const int pat) const {return m_Patterns[pat];} +//END: OPERATORS + +//BEGIN: INTERFACE METHODS +public: + CPatternContainer(CSoundFile& sndFile) : m_rSndFile(sndFile) {m_Patterns.assign(MAX_PATTERNS, MODPATTERN(*this));} + + // Clears existing patterns and resizes array to default size. + void Init(); + + //Note: No memory handling here. + void ClearPatterns() {m_Patterns.assign(m_Patterns.size(), MODPATTERN(*this));} + + //Insert (default)pattern to given position. If pattern already exists at that position, + //ignoring request. + bool Insert(const PATTERNINDEX index, const ROWINDEX rows); + + //Insert pattern to position with the lowest index, and return that index, -1 + //on failure. + int Insert(const ROWINDEX rows); + + //Remove pattern from given position. Currently it actually makes the pattern + //'invisible' - the pattern data is cleared but the actual pattern object won't get removed. + bool Remove(const PATTERNINDEX index); + + PATTERNINDEX Size() const {return static_cast<PATTERNINDEX>(m_Patterns.size());} + + CSoundFile& GetSoundFile() {return m_rSndFile;} + + //Returns the index of given pattern, Size() if not found. + PATTERNINDEX GetIndex(const MODPATTERN* const pPat) const; + + // Return true if pattern can be accessed with operator[](iPat), false otherwise. + bool IsValidIndex(const PATTERNINDEX iPat) const {return (iPat < Size());} + + void ResizeArray(const PATTERNINDEX newSize); + + void OnModTypeChanged(const MODTYPE oldtype); + +//END: INTERFACE METHODS + + +//BEGIN: DATA MEMBERS +private: + PATTERNVECTOR m_Patterns; + CSoundFile& m_rSndFile; +//END: DATA MEMBERS + +}; + +#endif +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-24 15:54:23
|
Revision: 275 http://modplug.svn.sourceforge.net/modplug/?rev=275&view=rev Author: relabsoluness Date: 2009-06-24 15:54:18 +0000 (Wed, 24 Jun 2009) Log Message: ----------- (Patch from Jojo) . Playback: 4-Bit panning didn't disable surround sound (merge edit: now uses compatibility flag for IT/MPTM/XM). Modified Paths: -------------- trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-23 19:53:05 UTC (rev 274) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-24 15:54:18 UTC (rev 275) @@ -2277,7 +2277,16 @@ // E7x: Set Tremolo WaveForm case 0x70: pChn->nTremoloType = param & 0x07; break; // E8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; + //case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; + case 0x80: if (!m_nTickCount) + { + if( TypeIsIT_MPT_XM() == false || GetModFlag(MSF_COMPATIBLE_PLAY) ) + { + if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND; + } + pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; + } + break; // E9x: Retrig case 0x90: RetrigNote(nChn, param); break; // EAx: Fine Volume Up @@ -2352,7 +2361,16 @@ } break; // S8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; + //case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; + case 0x80: if (!m_nTickCount) + { + if( TypeIsIT_MPT_XM() == false || GetModFlag(MSF_COMPATIBLE_PLAY) ) + { + if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND; + } + pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; + } + break; // S9x: Set Surround case 0x90: ExtendedChannelEffect(pChn, param & 0x0F); break; // SAx: Set 64k Offset This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-23 19:53:13
|
Revision: 274 http://modplug.svn.sourceforge.net/modplug/?rev=274&view=rev Author: relabsoluness Date: 2009-06-23 19:53:05 +0000 (Tue, 23 Jun 2009) Log Message: ----------- 1.17.02.54 Modified Paths: -------------- branches/1.17.02.53x/mptrack/bin/mptrack.exe branches/1.17.02.53x/packageTemplate/History.txt Modified: branches/1.17.02.53x/mptrack/bin/mptrack.exe =================================================================== (Binary files differ) Modified: branches/1.17.02.53x/packageTemplate/History.txt =================================================================== --- branches/1.17.02.53x/packageTemplate/History.txt 2009-06-23 19:38:41 UTC (rev 273) +++ branches/1.17.02.53x/packageTemplate/History.txt 2009-06-23 19:53:05 UTC (rev 274) @@ -8,7 +8,14 @@ ?: other (tx XYZ): thanks to XYZ for telling us about the bug +v1.17.02.54 (June 2009, revision 274) +------------------------------------- + . <re> Pattern tab: It's now possible to use the old note fade behaviour when playing notes (see setup->general). (rev. 267) + . <re> Pattern tab: Fixed wrong interpretations of "Old style pattern context menu"-option. (rev. 267) + . <re> Misc: Some internal fixes. (rev. 267) + + v1.17.02.53 (May 2009, revision 259) ------------------------------------ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-23 19:38:50
|
Revision: 273 http://modplug.svn.sourceforge.net/modplug/?rev=273&view=rev Author: relabsoluness Date: 2009-06-23 19:38:41 +0000 (Tue, 23 Jun 2009) Log Message: ----------- (Patches from Jojo, merged somewhat modified) + General: Can now import GDM files. / Pattern tab: Improved echo paste undo. . Misc: Document will now be set modified when changing rows per beat from main bar. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mainbar.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Added Paths: ----------- trunk/OpenMPT/soundlib/Load_gdm.cpp Modified: trunk/OpenMPT/mptrack/Mainbar.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mainbar.cpp 2009-06-17 18:44:27 UTC (rev 272) +++ trunk/OpenMPT/mptrack/Mainbar.cpp 2009-06-23 19:38:41 UTC (rev 273) @@ -487,6 +487,7 @@ if ((nCurrentSpeed < 0) || (nCurrentTempo < 0)) return; if ((pMainFrm = CMainFrame::GetMainFrame()) != NULL) { + CModDoc *pModDoc = pMainFrm->GetModPlaying(); CSoundFile *pSndFile = pMainFrm->GetSoundFilePlaying(); if (pSndFile) { @@ -524,12 +525,14 @@ if (nCurrentRowsPerBeat > 1) { pSndFile->m_nRowsPerBeat = nCurrentRowsPerBeat - 1; + pModDoc->SetModified(true); } } else { if (nCurrentRowsPerBeat < 64) { pSndFile->m_nRowsPerBeat = nCurrentRowsPerBeat + 1; + pModDoc->SetModified(true); } } m_SpinRowsPerBeat.SetPos(0); Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-17 18:44:27 UTC (rev 272) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-23 19:38:41 UTC (rev 273) @@ -1833,6 +1833,7 @@ nPattern = m_SndFile.Order[oNextOrder]; if(m_SndFile.Patterns.IsValidIndex(nPattern) == false) goto PasteDone; m = m_SndFile.Patterns[nPattern]; + PrepareUndo(nPattern, 0,0, m_SndFile.m_nChannels, m_SndFile.PatternSize[nPattern]); oCurrentOrder = oNextOrder; } } Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-17 18:44:27 UTC (rev 272) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-23 19:38:41 UTC (rev 273) @@ -277,6 +277,9 @@ RelativePath="..\soundlib\Load_far.cpp"> </File> <File + RelativePath="..\soundlib\Load_gdm.cpp"> + </File> + <File RelativePath="..\soundlib\Load_it.cpp"> </File> <File Added: trunk/OpenMPT/soundlib/Load_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp (rev 0) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2009-06-23 19:38:41 UTC (rev 273) @@ -0,0 +1,532 @@ +/* + * This source code is public domain. + * + * Purpose: Load GDM (BWSB Soundsystem) modules + * Authors: Johannes Schultz + * + * This code is partly based on zilym's original code / specs (which are utterly wrong :P). + * Thanks to the MenTaLguY for gdm.txt and ajs for gdm2s3m and some hints. + * + * Hint 1: Most (all?) of the unsupported features were not supported in 2GDM / BWSB either. + * Hint 2: Files will be played like their original formats would be played in MPT, so no + * BWSB quirks including crashes and freezes are supported. :-P +*/ + +#include "stdafx.h" +#include "sndfile.h" + +#pragma pack(1) + +typedef struct _GDMHEADER +{ + DWORD ID; // ID: 'GDM\xFE' + CHAR SongTitle[32]; // Music's title + CHAR SongMusician[32]; // Name of music's composer + CHAR DOSEOF[3]; // 13, 10, 26 + DWORD ID2; // ID: 'GMFS' + BYTE FormMajorVer; // Format major version + BYTE FormMinorVer; // Format minor version + UINT16 TrackID; // Composing Tracker ID code (00 = 2GDM) + BYTE TrackMajorVer; // Tracker's major version + BYTE TrackMinorVer; // Tracker's minor version + BYTE PanMap[32]; // 0-Left to 15-Right, 255-N/U + BYTE MastVol; // Range: 0...64 + BYTE Tempo; // Initial music tempo (6) + BYTE BPM; // Initial music BPM (125) + UINT16 FormOrigin; // Original format ID: + // 1-MOD, 2-MTM, 3-S3M, 4-669, 5-FAR, 6-ULT, 7-STM, 8-MED + // (versions of 2GDM prior to v1.15 won't set this correctly) + + UINT32 OrdOffset; + BYTE NOO; // Number of orders in module - 1 + UINT32 PatOffset; + BYTE NOP; // Number of patterns in module - 1 + UINT32 SamHeadOffset; + UINT32 SamOffset; + BYTE NOS; // Number of samples in module - 1 + UINT32 MTOffset; // Offset of song message + UINT32 MTLength; + UINT32 SSOffset; // Offset of scrolly script (huh?) + UINT16 SSLength; + UINT32 TGOffset; // Offset of text graphic (huh?) + UINT16 TGLength; +} GDMHEADER, *PGDMHEADER; + +typedef struct _GDMSAMPLEHEADER +{ + CHAR SamName[32]; + CHAR FileName[12]; + BYTE EmsHandle; // useless + UINT32 Length; + UINT32 LoopBegin; + UINT32 LoopEnd; + BYTE Flags; + UINT16 C4Hertz; + BYTE Volume; + BYTE Pan; +} GDMSAMPLEHEADER, *PGDMSAMPLEHEADER; + +BOOL CSoundFile::ReadGDM(const LPCBYTE lpStream, const DWORD dwMemLength) +//----------------------------------------------------------- +{ + if ((!lpStream) || (dwMemLength < sizeof(GDMHEADER))) return FALSE; + + const PGDMHEADER pHeader = (PGDMHEADER)lpStream; + + // is it a valid GDM file? + if( (LittleEndian(pHeader->ID) != 0xFE4D4447) || //GDM\xFE + (pHeader->DOSEOF[0] != 13 || pHeader->DOSEOF[1] != 10 || pHeader->DOSEOF[2] != 26) || //CR+LF+EOF + (LittleEndian(pHeader->ID2) != 0x53464D47)) return FALSE; //GMFS + + // song name + memset(m_szNames, 0, sizeof(m_szNames)); + memcpy(m_szNames[0], pHeader->SongTitle, 32); + SetNullTerminator(m_szNames[0]); + + // there are no other format versions... + if(pHeader->FormMajorVer != 1 || pHeader->FormMinorVer != 0) + { + ::MessageBox(0, TEXT("GDM file seems to be valid, but this format version is currently not supported."), TEXT("OpenMPT GDM import"), MB_ICONERROR); + return FALSE; + } + + // todo: Is TrackID, TrackMajorVer, TrackMinorVer relevant? The only TrackID should be 0 - 2GDM.exe + + // read channel pan map... 0...15 = channel panning, 16 = surround channel, 255 = channel does not exist + m_nChannels = 32; + for(int i = 0; i < 32; i++) + { + if(pHeader->PanMap[i] < 16) + { + ChnSettings[i].nPan = min((pHeader->PanMap[i] << 4) + 8, 256); + } + else if(pHeader->PanMap[i] == 16) + { + ChnSettings[i].nPan = 128; + ChnSettings[i].dwFlags |= CHN_SURROUND; + } + else if(pHeader->PanMap[i] == 0xff) + { + m_nChannels = i; + break; + } + } + + m_nDefaultGlobalVolume = min(pHeader->MastVol << 2, 256); + m_nDefaultSpeed = pHeader->Tempo; + m_nDefaultTempo = pHeader->BPM; + m_nRestartPos = 0; // not supported in this format, so use the default value + m_nSamplePreAmp = 48; // dito + m_nVSTiVolume = 48; // dito + + // 1-MOD, 2-MTM, 3-S3M, 4-669, 5-FAR, 6-ULT, 7-STM, 8-MED + + switch(pHeader->FormOrigin) + { + case 1: + m_nType = MOD_TYPE_MOD; + break; + case 2: + m_nType = MOD_TYPE_MTM; + break; + case 3: + m_nType = MOD_TYPE_S3M; + break; + case 4: + m_nType = MOD_TYPE_669; + break; + case 5: + m_nType = MOD_TYPE_FAR; + break; + case 6: + m_nType = MOD_TYPE_ULT; + break; + case 7: + m_nType = MOD_TYPE_STM; + break; + case 8: + m_nType = MOD_TYPE_MED; + break; + default: + ::MessageBox(0, TEXT("GDM file seems to be valid, but the original format is currently not supported.\nThis should not happen."), TEXT("OpenMPT GDM import"), MB_ICONERROR); + return FALSE; + break; + } + + // check if offsets are valid. we won't read the scrolly text or text graphics, but invalid pointers would probably indicate a broken file... + if( dwMemLength < pHeader->OrdOffset || dwMemLength - pHeader->OrdOffset < pHeader->NOO + || dwMemLength < pHeader->PatOffset + || dwMemLength < pHeader->SamHeadOffset || dwMemLength - pHeader->SamHeadOffset < (pHeader->NOS + 1) * sizeof(GDMSAMPLEHEADER) + || dwMemLength < pHeader->SamOffset + || dwMemLength < pHeader->MTOffset || dwMemLength - pHeader->MTOffset < pHeader->MTLength + || dwMemLength < pHeader->SSOffset || dwMemLength - pHeader->SSOffset < pHeader->SSLength + || dwMemLength < pHeader->TGOffset || dwMemLength - pHeader->TGOffset < pHeader->TGLength) + return FALSE; + + // read orders + Order.ReadAsByte(lpStream + pHeader->OrdOffset, pHeader->NOO + 1, dwMemLength - pHeader->OrdOffset); + + // read samples + m_nSamples = pHeader->NOS + 1; + + DWORD iSampleOffset = pHeader->SamOffset; + int iLZWsamples = 0; + + for(UINT iSmp = 1; iSmp <= m_nSamples; iSmp++) + { + const PGDMSAMPLEHEADER pSample = (PGDMSAMPLEHEADER)(lpStream + pHeader->SamHeadOffset + (iSmp - 1) * sizeof(GDMSAMPLEHEADER)); + + // sample header + + memcpy(m_szNames[iSmp], pSample->SamName, 32); + SetNullTerminator(m_szNames[iSmp]); + memcpy(Ins[iSmp].name, pSample->FileName, 12); + + Ins[iSmp].nC4Speed = pSample->C4Hertz; + Ins[iSmp].nGlobalVol = 256; // not supported in this format + Ins[iSmp].nLength = min(pSample->Length, MAX_SAMPLE_LENGTH); // in bytes + Ins[iSmp].nLoopStart = min(pSample->LoopBegin, Ins[iSmp].nLength); // in samples + Ins[iSmp].nLoopEnd = min(pSample->LoopEnd - 1, Ins[iSmp].nLength); // dito + FrequencyToTranspose(&Ins[iSmp]); // set transpose + finetune for mod files + + if(pSample->Flags & 0x01) Ins[iSmp].uFlags |= CHN_LOOP; // loop sample + + if(pSample->Flags & 0x04) + { + Ins[iSmp].nVolume = min(pSample->Volume << 2, 256); // 0...64, 255 = no default volume + } + else + { + Ins[iSmp].nVolume = 256; // default volume + } + + if(pSample->Flags & 0x08) // default panning is used + { + Ins[iSmp].uFlags |= CHN_PANNING; + Ins[iSmp].nPan = (pSample->Pan > 15) ? 128 : min((pSample->Pan << 4) + 8, 256); // 0...15, 16 = surround (not supported), 255 = no default panning + } + else + { + Ins[iSmp].nPan = 128; + } + + /* note: apparently (and according to zilym), 2GDM doesn't handle 16 bit or stereo samples properly. + so those flags are pretty much meaningless and we will ignore them... in fact, samples won't load as expected if we don't! */ + + UINT iSampleFormat; + if(pSample->Flags & 0x02) // 16 bit + { + if(pSample->Flags & 0x20) // stereo + { + iSampleFormat = RS_PCM16U; // should be RS_STPCM16U but that breaks the sample reader + } + else + { + iSampleFormat = RS_PCM16U; + } + } + else // 8 bit + { + if(pSample->Flags & 0x20) // stereo + { + iSampleFormat = RS_PCM8U; // should be RS_STPCM8U - dito + } + else + { + iSampleFormat = RS_PCM8U; + } + } + + // according to zilym, LZW support has never been finished, so this is also practically useless. + if(pSample->Flags & 0x10) + iLZWsamples++; + + // read sample data + ReadSample(&Ins[iSmp], iSampleFormat, reinterpret_cast<LPCSTR>(lpStream + iSampleOffset), dwMemLength - iSampleOffset); + iSampleOffset += min(pSample->Length, dwMemLength - iSampleOffset); + + } + + // read patterns + Patterns.ResizeArray(max(MAX_PATTERNS, pHeader->NOP + 1)); + + // position in file + DWORD iPatternsOffset = pHeader->PatOffset; + + BOOL bS3MCommandSet = (GetBestSaveFormat() & (MOD_TYPE_S3M | MOD_TYPE_IT | MOD_TYPE_MPT)); + + for (PATTERNINDEX iPat = 0; iPat < pHeader->NOP + 1; iPat++) + { + + if(iPatternsOffset + 2 > dwMemLength) break; + UINT16 iPatternLength = *(UINT16 *)(lpStream + iPatternsOffset); // pattern length including the two "length" bytes + if(iPatternLength > dwMemLength || iPatternsOffset > dwMemLength - iPatternLength) break; + + if(Patterns.Insert(iPat, 64)) + { + CString s; + s.Format(TEXT("Allocating patterns failed starting from pattern %u"), iPat); + MessageBox(NULL, s, TEXT("OpenMPT GDM import"), MB_ICONERROR); + break; + } + + // position in THIS pattern + DWORD iPatternPos = iPatternsOffset + 2; + + MODCOMMAND *p = Patterns[iPat]; + + for(UINT iRow = 0; iRow < 64; iRow++) + { + do // zero byte = next row + { + if(iPatternPos + 1 > dwMemLength) break; + + BYTE bChannel = lpStream[iPatternPos++]; + + if(bChannel == 0) break; // next row, please! + + UINT channel = bChannel & 0x1f; + if(channel >= m_nChannels) break; // better safe than sorry! + + MODCOMMAND *m = &p[iRow * m_nChannels + channel]; + + if(bChannel & 0x20) + { + // note and sample follows + if(iPatternPos + 2 > dwMemLength) break; + BYTE bNote = lpStream[iPatternPos++]; + BYTE bSample = lpStream[iPatternPos++]; + + bNote = (bNote & 0x7F) - 1; // this format doesn't have note cuts + if(bNote < 0xF0) bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13; + if(bNote == 0xFF) bNote = 0; + m->note = bNote; + m->instr = bSample; + + } + + if(bChannel & 0x40) + { + // effect(s) follow + + m->command = CMD_NONE; + m->volcmd = CMD_NONE; + + do + { + if(iPatternPos + 2 > dwMemLength) break; + BYTE bEffect = lpStream[iPatternPos++]; + BYTE bEffectData = lpStream[iPatternPos++]; + + BYTE command = bEffect & 0x1F, param = bEffectData; + BYTE volcommand = CMD_NONE, volparam = param; + + switch(command) + { + case 0x01: command = CMD_PORTAMENTOUP; if(param >= 0xE0) param = 0xDF; break; + case 0x02: command = CMD_PORTAMENTODOWN; if(param >= 0xE0) param = 0xDF; break; + case 0x03: command = CMD_TONEPORTAMENTO; break; + case 0x04: command = CMD_VIBRATO; break; + case 0x05: command = CMD_TONEPORTAVOL; if (param & 0xF0) param &= 0xF0; break; + case 0x06: command = CMD_VIBRATOVOL; if (param & 0xF0) param &= 0xF0; break; + case 0x07: command = CMD_TREMOLO; break; + case 0x08: command = CMD_TREMOR; break; + case 0x09: command = CMD_OFFSET; break; + case 0x0A: command = CMD_VOLUMESLIDE; break; + case 0x0B: command = CMD_POSITIONJUMP; break; + case 0x0C: + if(bS3MCommandSet) + { + command = CMD_NONE; + volcommand = VOLCMD_VOLUME; + volparam = min(param, 64); + } + else + { + command = CMD_VOLUME; + param = min(param, 64); + } + break; + case 0x0D: command = CMD_PATTERNBREAK; break; + case 0x0E: + if(bS3MCommandSet) + { + command = CMD_S3MCMDEX; + // need to do some remapping + switch(param >> 4) + { + case 0x0: + // set filter + command = CMD_MODCMDEX; + break; + case 0x1: + // fine porta up + command = CMD_PORTAMENTOUP; + param = 0xF0 | (param & 0x0F); + break; + case 0x2: + // fine porta down + command = CMD_PORTAMENTODOWN; + param = 0xF0 | (param & 0x0F); + break; + case 0x3: + // glissando control + param = 0x10 | (param & 0x0F); + break; + case 0x4: + // vibrato waveform + param = 0x30 | (param & 0x0F); + break; + case 0x5: + // set finetune + param = 0x20 | (param & 0x0F); + break; + case 0x6: + // pattern loop + param = 0xB0 | (param & 0x0F); + break; + case 0x7: + // tremolo waveform + param = 0x40 | (param & 0x0F); + break; + case 0x8: + // extra fine porta up + command = CMD_PORTAMENTOUP; + param = 0xE0 | (param & 0x0F); + break; + case 0x9: + // extra fine porta down + command = CMD_PORTAMENTODOWN; + param = 0xE0 | (param & 0x0F); + break; + case 0xA: + // fine volume up + command = CMD_VOLUMESLIDE; + param = ((param & 0x0F) << 4) | 0x0F; + break; + case 0xB: + // fine volume down + command = CMD_VOLUMESLIDE; + param = 0xF0 | (param & 0x0F); + break; + case 0xC: + // note cut + break; + case 0xD: + // note delay + break; + case 0xE: + // pattern delay + break; + case 0xF: + command = CMD_MODCMDEX; + // invert loop / funk repeat + break; + } + } + else + { + command = CMD_MODCMDEX; + } + break; + case 0x0F: command = CMD_SPEED; break; + case 0x10: command = CMD_ARPEGGIO; break; + case 0x11: command = CMD_NONE /* set internal flag */; break; + case 0x12: + if((!bS3MCommandSet) && ((param & 0xF0) == 0)) + { + // retrig in "mod style" + command = CMD_MODCMDEX; + param = 0x90 | (param & 0x0F); + } + else + { + // either "s3m style" is required or this format is like s3m anyway + command = CMD_RETRIG; + } + break; + case 0x13: command = CMD_GLOBALVOLUME; break; + case 0x14: command = CMD_FINEVIBRATO; break; + case 0x1E: + switch(param >> 4) + { + case 0x0: + switch(param & 0x0F) + { + case 0x0: command = CMD_S3MCMDEX; param = 0x90; break; + case 0x1: command = CMD_PANNING8; param = 0xA4; break; + case 0x2: command = CMD_NONE /* set normal loop - not implemented in 2GDM */; break; + case 0x3: command = CMD_NONE /* set bidi loop - dito */; break; + case 0x4: command = CMD_S3MCMDEX; param = 0x9E; break; + case 0x5: command = CMD_S3MCMDEX; param = 0x9F; break; + case 0x6: command = CMD_NONE /* monaural sample - dito */; break; + case 0x7: command = CMD_NONE /* stereo sample - dito */; break; + case 0x8: command = CMD_NONE /* stop sample on end - dito */; break; + case 0x9: command = CMD_NONE /* loop sample on end - dito */; break; + default: command = CMD_NONE; break; + } + break; + case 0x8: + command = (bS3MCommandSet) ? CMD_S3MCMDEX : CMD_MODCMDEX; + break; + case 0xD: + // adjust frequency (increment in hz) - not implemented in 2GDM + command = CMD_NONE; + break; + default: command = CMD_NONE; break; + } + break; + case 0x1F: command = CMD_TEMPO; break; + default: command = CMD_NONE; break; + } + + if(command != CMD_NONE) + { + // move pannings to volume column - should never happen + if(m->command == CMD_S3MCMDEX && ((m->param >> 4) == 0x8) && volcommand == CMD_NONE) + { + volcommand = VOLCMD_PANNING; + volparam = ((param & 0x0F) << 2) + 2; + } + + m->command = command; + m->param = param; + } + if(volcommand != CMD_NONE) + { + m->volcmd = volcommand; + m->vol = volparam; + } + + if(!(bEffect & 0x20)) break; // no other effect follows + } while(1); + + } + + } while(1); + } + + iPatternsOffset += iPatternLength; + } + + // read song comments + if(pHeader->MTLength) + { + m_lpszSongComments = new char[pHeader->MTLength + 1]; + if (m_lpszSongComments) + { + memset(m_lpszSongComments, 0, pHeader->MTLength + 1); + memcpy(m_lpszSongComments, lpStream + pHeader->MTOffset, pHeader->MTLength); + } + } + + if(iLZWsamples) + { + TCHAR s[128]; + wsprintf(s, TEXT("%d samples are LZW compressed. LZW compression is currently not supported.\nPlease send this file to the OpenMPT team."), iLZWsamples); + ::MessageBox(0, s, TEXT("OpenMPT GDM import"), MB_ICONWARNING); + } + + return TRUE; + +} Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-17 18:44:27 UTC (rev 272) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-23 19:38:41 UTC (rev 273) @@ -593,6 +593,7 @@ #endif #endif // MODPLUG_BASIC_SUPPORT && (!ReadMO3(lpStream, dwMemLength)) + && (!ReadGDM(lpStream, dwMemLength)) && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; #ifdef ZIPPED_MOD_SUPPORT if ((!m_lpszSongComments) && (archive.GetComments(FALSE))) Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-17 18:44:27 UTC (rev 272) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-23 19:38:41 UTC (rev 273) @@ -1068,6 +1068,7 @@ BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadMO3(LPCBYTE lpStream, const DWORD dwMemLength); + BOOL ReadGDM(const LPCBYTE lpStream, const DWORD dwMemLength); BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); // Save Functions #ifndef MODPLUG_NO_FILESAVE This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-17 18:45:13
|
Revision: 272 http://modplug.svn.sourceforge.net/modplug/?rev=272&view=rev Author: relabsoluness Date: 2009-06-17 18:44:27 +0000 (Wed, 17 Jun 2009) Log Message: ----------- ? Misc: Fixed a merge bug from last commit. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.rc Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-06-17 17:50:41 UTC (rev 271) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-06-17 18:44:27 UTC (rev 272) @@ -146,7 +146,7 @@ MENUITEM "Cleanup S&ong", ID_CLEANUP_SONG MENUITEM "Remove &All Instruments", ID_INSTRUMENTS_REMOVEALL MENUITEM "Cleanup &Plugins", ID_CLEANUP_PLUGS - MENUITEM "Co&mpo Cleanup", ID_CLEANUP_COMPO + MENUITEM "Co&mpo Cleanup", ID_CLEANUP_COMPO END MENUITEM SEPARATOR MENUITEM "&Find\tCtrl+F", ID_EDIT_FIND @@ -2051,7 +2051,6 @@ BOTTOMMARGIN, 104 END - ID_CLEANUP_COMPO "Reset attributes to defaults (useful for creating sample packs)\Compo Cleanup" IDD_CONTROL_INSTRUMENTS, DIALOG BEGIN RIGHTMARGIN, 522 @@ -2500,6 +2499,7 @@ ID_PATTERN_PLAYROW "Play current row\nPlay Row" ID_IMPORT_MIDILIB "Defines the default MIDI library used when importing MIDI files" ID_CLEANUP_REARRANGE "Rearrange all patterns so that they are sorted in the order list\nRearrange Patterns" + ID_CLEANUP_COMPO "Reset attributes to defaults (useful for creating sample packs)\nCompo Cleanup" END STRINGTABLE This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-17 17:51:19
|
Revision: 271 http://modplug.svn.sourceforge.net/modplug/?rev=271&view=rev Author: relabsoluness Date: 2009-06-17 17:50:41 +0000 (Wed, 17 Jun 2009) Log Message: ----------- (Patches from Jojo, merged somewhat modified with related refactoring) . General tab: Document will now be set modified when moving or inserting plugins. + Pattern tab: Added description to high offset command in note properties dialog. + Pattern tab: Paste will now optionally continue on next pattern (echo paste). + Sample tab: Can now play sample from given position with Ctrl + left mouse button. + Misc: Compo cleanup / Misc: Updated project file. Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/OrderToPatternTable.cpp trunk/OpenMPT/mptrack/OrderToPatternTable.h trunk/OpenMPT/mptrack/View_gen.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/View_smp.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/patternContainer.cpp trunk/OpenMPT/mptrack/patternContainer.h trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/modsmp_ctrl.cpp trunk/OpenMPT/soundlib/modsmp_ctrl.h Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -2304,6 +2304,11 @@ commands[kcChannelReset].isDummy = false; commands[kcChannelReset].Message = "Reset channel"; + commands[kcSwitchEchoPaste].UID = 1787; + commands[kcSwitchEchoPaste].Message = "Switch echo paste"; + commands[kcSwitchEchoPaste].isHidden = false; + commands[kcSwitchEchoPaste].isDummy = false; + #ifdef _DEBUG for (int i=0; i<kcNumCommands; i++) { if (commands[i].UID != 0) { // ignore unset UIDs Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/CommandSet.h 2009-06-17 17:50:41 UTC (rev 271) @@ -84,6 +84,7 @@ kcEditPaste, kcEditMixPaste, kcEditMixPasteITStyle, + kcSwitchEchoPaste, kcEditSelectAll, kcEditFind, kcEditFindNext, Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -247,6 +247,7 @@ END_CRITICAL(); } m_pParent->SetCurrentPattern(n); + m_pModDoc->SetElapsedTime(static_cast<ORDERINDEX>(m_nScrollPos), 0); } } UpdateInfoText(); Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -166,7 +166,7 @@ int CMainFrame::gnPlugWindowHeight = 332; DWORD CMainFrame::gnPlugWindowLast = 0; -uint32 CMainFrame::gnMsgBoxVisiblityFlags = ~0; +uint32 CMainFrame::gnMsgBoxVisiblityFlags = uint32_max; CRITICAL_SECTION CMainFrame::m_csAudio; HANDLE CMainFrame::m_hPlayThread = NULL; @@ -393,7 +393,7 @@ gnPlugWindowWidth = GetPrivateProfileInt("Display", "PlugSelectWindowWidth", 370, iniFile); gnPlugWindowHeight = GetPrivateProfileInt("Display", "PlugSelectWindowHeight", 332, iniFile); gnPlugWindowLast = GetPrivateProfileDWord("Display", "PlugSelectWindowLast", 0, iniFile); - gnMsgBoxVisiblityFlags = GetPrivateProfileDWord("Display", "MsgBoxVisibilityFlags", ~0, iniFile); + gnMsgBoxVisiblityFlags = GetPrivateProfileDWord("Display", "MsgBoxVisibilityFlags", uint32_max, iniFile); CHAR s[16]; for (int ncol=0; ncol<MAX_MODCOLORS; ncol++) { Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2009-06-17 17:50:41 UTC (rev 271) @@ -207,6 +207,8 @@ #define PATTERN_SYNCMUTE 0x1000000 #define PATTERN_AUTODELAY 0x2000000 #define PATTERN_NOTEFADE 0x4000000 +#define PATTERN_ECHOPASTE 0x8000000 +#define PATTERN_POSITIONAWARETIMER 0x10000000 // Keyboard Setup @@ -552,6 +554,7 @@ inline BOOL IsRendering() const { return (m_dwStatus & MODSTATUS_RENDERING); } //rewbs.VSTTimeInfo DWORD GetElapsedTime() const { return m_dwElapsedTime; } void ResetElapsedTime() { m_dwElapsedTime = 0; } + void SetElapsedTime(DWORD dwElapsedTime) { m_dwElapsedTime = dwElapsedTime; } inline CModDoc *GetModPlaying() const { return (IsPlaying()||IsRendering()) ? m_pModPlaying : NULL; } inline CSoundFile *GetSoundFilePlaying() const { return (IsPlaying()||IsRendering()) ? m_pSndFile : NULL; } //rewbs.VSTTimeInfo BOOL InitRenderer(CSoundFile*); //rewbs.VSTTimeInfo Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -57,6 +57,7 @@ ON_COMMAND(ID_CLEANUP_PATTERNS, OnCleanupPatterns) ON_COMMAND(ID_CLEANUP_SONG, OnCleanupSong) ON_COMMAND(ID_CLEANUP_REARRANGE, OnRearrangePatterns) + ON_COMMAND(ID_CLEANUP_COMPO, OnCompoCleanup) ON_COMMAND(ID_INSTRUMENTS_REMOVEALL,OnRemoveAllInstruments) // -> CODE#0020 // -> DESC="rearrange sample list" @@ -764,7 +765,7 @@ return IDCANCEL; } -UINT CModDoc::PlayNote(UINT note, UINT nins, UINT nsmp, BOOL bpause, LONG nVol, LONG loopstart, LONG loopend, int nCurrentChn) //rewbs.vstiLive: added current chan param +UINT CModDoc::PlayNote(UINT note, UINT nins, UINT nsmp, BOOL bpause, LONG nVol, LONG loopstart, LONG loopend, int nCurrentChn, const uint32 nStartPos) //rewbs.vstiLive: added current chan param //----------------------------------------------------------------------------------------------------------- { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); @@ -860,6 +861,16 @@ pChn->dwFlags &= ~CHN_EXTRALOUD; } + // Handle custom start position + if(nStartPos != uint32_max && pChn->pInstrument) + { + pChn->nPos = nStartPos; + // If start position is after loop end, set loop end to sample end so that the sample starts + // playing. + if(pChn->nLoopEnd < nStartPos) + pChn->nLength = pChn->nLoopEnd = pChn->pInstrument->nLength; + } + /* if (bpause) { if ((loopstart + 16 < loopend) && (loopstart >= 0) && (loopend <= (LONG)pChn->nLength)) { @@ -1882,7 +1893,15 @@ ShowLog("Pattern Rearrange", CMainFrame::GetMainFrame()); } +void CModDoc::OnCompoCleanup() +//------------------------------ +{ + CompoCleanup(); + UpdateAllViews(NULL, HINT_MODTYPE); +} + + void CModDoc::OnUpdateInstrumentOnly(CCmdUI *p) //--------------------------------------------- { @@ -1951,25 +1970,7 @@ void CModDoc::OnRemoveAllInstruments() //------------------------------------ { - if (!m_SndFile.m_nInstruments) return; - if (CMainFrame::GetMainFrame()->MessageBox("This will remove all the instruments in the song,\n" - "Do you want to continue?", "Warning", MB_YESNO | MB_ICONQUESTION) != IDYES) return; - if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples ?\n", - NULL, MB_YESNO | MB_ICONQUESTION) == IDYES) - { - ConvertInstrumentsToSamples(); - } - char removeSamples = -1; - if (::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES) { - removeSamples = 1; - } - - for (UINT i=1; i<=m_SndFile.m_nInstruments; i++) { - m_SndFile.DestroyInstrument(i,removeSamples); - } - m_SndFile.m_nInstruments = 0; - SetModified(); - UpdateAllViews(NULL, HINT_MODTYPE); + RemoveAllInstruments(); } @@ -2651,6 +2652,11 @@ } break; case 0x60: if (gFXInfo[ndx].dwEffect == CMD_MODCMDEX) break; + + case 0xA0: + wsprintf(s, "+ %u samples", 0x10000 * (param & 0x0F)); + break; + case 0xB0: if (gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) { @@ -2949,8 +2955,11 @@ //end rewbs.vstCompliance END_CRITICAL(); - pMainFrm->ResetElapsedTime(); - if (pModPlaying != this) { + // set playback timer in the status bar + SetElapsedTime(static_cast<ORDERINDEX>(nOrd), nRow, true); + + if (pModPlaying != this) + { pMainFrm->PlayMod(this, followSonghWnd, m_dwNotifyType|MPTNOTIFY_POSITION|MPTNOTIFY_VUMETERS); //rewbs.fix2977 } } @@ -2997,7 +3006,9 @@ //end rewbs.VSTCompliance END_CRITICAL(); - pMainFrm->ResetElapsedTime(); + // set playback timer in the status bar + SetElapsedTime(static_cast<ORDERINDEX>(nOrd), nRow, true); + if (pModPlaying != this) { pMainFrm->PlayMod(this, followSonghWnd, m_dwNotifyType|MPTNOTIFY_POSITION|MPTNOTIFY_VUMETERS); //rewbs.fix2977 } @@ -3049,7 +3060,8 @@ //rewbs.VSTCompliance END_CRITICAL(); - pMainFrm->ResetElapsedTime(); + // set playback timer in the status bar + SetElapsedTime(static_cast<ORDERINDEX>(nOrd), nRow, true); if (pModPlaying != this) { pMainFrm->PlayMod(this, followSonghWnd, m_dwNotifyType|MPTNOTIFY_POSITION|MPTNOTIFY_VUMETERS); //rewbs.fix2977 @@ -3262,3 +3274,22 @@ } } + +// Sets playback timer to playback time at given position. If 'bReset' is true, +// timer is reset if playback position timer is not enabled. +void CModDoc::SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow, bool bReset) +//----------------------------------------------------------------------- +{ + CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); + if(pMainFrm == NULL) + return; + + if(CMainFrame::m_dwPatternSetup & PATTERN_POSITIONAWARETIMER) + { + double dPatternPlaytime = max(0, m_SndFile.GetPlaybackTimeAt(nOrd, nRow)); + pMainFrm->SetElapsedTime((DWORD) (dPatternPlaytime * 1000)); + } + else if(bReset) + pMainFrm->ResetElapsedTime(); +} + Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Moddoc.h 2009-06-17 17:50:41 UTC (rev 271) @@ -186,8 +186,11 @@ BOOL ConvertInstrumentsToSamples();; BOOL RemoveUnusedSamples(); BOOL RemoveUnusedInstruments(); + void RemoveAllInstruments(bool bConfirm = true); BOOL RemoveUnusedPlugs(); + UINT RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]); BOOL RemoveUnusedPatterns(BOOL bRemove=TRUE); + BOOL CompoCleanup(); LONG InsertPattern(LONG nOrd=-1, UINT nRows=64); LONG InsertSample(BOOL bLimit=FALSE); LONG InsertInstrument(LONG lSample=0, LONG lDuplicate=0); @@ -196,7 +199,7 @@ BOOL RemovePattern(UINT n); BOOL RemoveSample(UINT n); BOOL RemoveInstrument(UINT n); - UINT PlayNote(UINT note, UINT nins, UINT nsmp, BOOL bpause, LONG nVol=-1, LONG loopstart=0, LONG loopend=0, int nCurrentChn=-1); //rewbs.vstiLive: added current chan param + UINT PlayNote(UINT note, UINT nins, UINT nsmp, BOOL bpause, LONG nVol=-1, LONG loopstart=0, LONG loopend=0, int nCurrentChn=-1, const uint32 nStartPos = uint32_max); //rewbs.vstiLive: added current chan param BOOL NoteOff(UINT note, BOOL bFade=FALSE, UINT nins=-1, UINT nCurrentChn=-1); //rewbs.vstiLive: add params // -> CODE#0020 @@ -255,6 +258,7 @@ void TogglePluginEditor(UINT m_nCurrentPlugin); //rewbs.patPlugNames void RecordParamChange(int slot, long param); void LearnMacro(int macro, long param); + void SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow, bool bReset = false); BOOL RemoveChannels(BOOL bChnMask[MAX_CHANNELS]); @@ -325,6 +329,7 @@ afx_msg void OnCleanupPatterns(); afx_msg void OnCleanupSong(); afx_msg void OnRearrangePatterns(); + afx_msg void OnCompoCleanup(); afx_msg void OnRemoveAllInstruments(); afx_msg void OnEstimateSongLength(); afx_msg void OnApproximateBPM(); Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -809,13 +809,54 @@ return FALSE; } + +UINT CModDoc::RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]) +//--------------------------------------------------------------- +{ + //Remove all plugins whose keepMask[plugindex] is false. + UINT nRemoved=0; + for (PLUGINDEX nPlug=0; nPlug<MAX_MIXPLUGINS; nPlug++) + { + SNDMIXPLUGIN* pPlug = &m_SndFile.m_MixPlugins[nPlug]; + if (keepMask[nPlug] || !pPlug) + { + Log("Keeping mixplug addess (%d): %X\n", nPlug, &(pPlug->pMixPlugin)); + continue; + } + + if (pPlug->pPluginData) + { + delete pPlug->pPluginData; + pPlug->pPluginData = NULL; + } + if (pPlug->pMixPlugin) + { + pPlug->pMixPlugin->Release(); + pPlug->pMixPlugin=NULL; + } + if (pPlug->pMixState) + { + delete pPlug->pMixState; + } + + memset(&(pPlug->Info), 0, sizeof(SNDMIXPLUGININFO)); + Log("Zeroing range (%d) %X - %X\n", nPlug, &(pPlug->Info), &(pPlug->Info)+sizeof(SNDMIXPLUGININFO)); + pPlug->nPluginDataSize=0; + pPlug->fDryRatio=0; + pPlug->defaultProgram=0; + nRemoved++; + } + + return nRemoved; +} + + BOOL CModDoc::RemoveUnusedPlugs() //------------------------------- { - BYTE usedmap[MAX_MIXPLUGINS]; - memset(usedmap, false, MAX_MIXPLUGINS); + bool usedmap[MAX_MIXPLUGINS]; + memset(usedmap, false, sizeof(usedmap)); - for (PLUGINDEX nPlug=0; nPlug < MAX_MIXPLUGINS; nPlug++) { //Is the plugin assigned to a channel? @@ -849,43 +890,49 @@ } - //Remove unused plugins - int nRemoved=0; - for (int nPlug=0; nPlug<MAX_MIXPLUGINS; nPlug++) { - SNDMIXPLUGIN* pPlug = &m_SndFile.m_MixPlugins[nPlug]; - if (usedmap[nPlug] || !pPlug) { - Log("Keeping mixplug addess (%d): %X\n", nPlug, &(pPlug->pMixPlugin)); - continue; - } + UINT nRemoved = RemovePlugs(usedmap); - if (pPlug->pPluginData) { - delete pPlug->pPluginData; - pPlug->pPluginData = NULL; + if (nRemoved) { + SetModified(); + } + + return nRemoved; +} + + +void CModDoc::RemoveAllInstruments(bool bConfirm) +//----------------------------------------------- +{ + if (!m_SndFile.m_nInstruments) + return; + + char removeSamples = -1; + if(bConfirm) + { + if (CMainFrame::GetMainFrame()->MessageBox("This will remove all the instruments in the song,\n" + "Do you want to continue?", "Warning", MB_YESNO | MB_ICONQUESTION) != IDYES) return; + if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples ?\n", + NULL, MB_YESNO | MB_ICONQUESTION) == IDYES) + { + ConvertInstrumentsToSamples(); } - if (pPlug->pMixPlugin) { - pPlug->pMixPlugin->Release(); - pPlug->pMixPlugin=NULL; + + if (::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES) { + removeSamples = 1; } - if (pPlug->pMixState) { - delete pPlug->pMixState; - } - - memset(&(pPlug->Info), 0, sizeof(SNDMIXPLUGININFO)); - Log("Zeroing range (%d) %X - %X\n", nPlug, &(pPlug->Info), &(pPlug->Info)+sizeof(SNDMIXPLUGININFO)); - pPlug->nPluginDataSize=0; - pPlug->fDryRatio=0; - pPlug->defaultProgram=0; - nRemoved++; - } - if (nRemoved) { - SetModified(); + for (UINT i=1; i<=m_SndFile.m_nInstruments; i++) + { + m_SndFile.DestroyInstrument(i,removeSamples); } - return nRemoved; + m_SndFile.m_nInstruments = 0; + SetModified(); + UpdateAllViews(NULL, HINT_MODTYPE); } + BOOL CModDoc::RemoveUnusedInstruments() //------------------------------------- { @@ -931,7 +978,7 @@ } EndWaitCursor(); if ((bReorg) && (m_SndFile.m_nInstruments > 1) - && (::MessageBox(NULL, "Do you want to reorganize the remaining instruments ?", NULL, MB_YESNO | MB_ICONQUESTION) == IDYES)) + && (::MessageBox(NULL, "Do you want to reorganize the remaining instruments?", "Instrument Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES)) { BeginWaitCursor(); BEGIN_CRITICAL(); @@ -993,6 +1040,96 @@ } +BOOL CModDoc::CompoCleanup() +//-------------------------- +{ + //jojo.compocleanup + if(::MessageBox(NULL, TEXT("WARNING: Compo cleanup will convert module to IT format, remove all patterns and reset song, sample and instrument attributes to default values. Continue?"), TEXT("Compo Cleanup"), MB_YESNO | MB_ICONWARNING) == IDNO) + return FALSE; + + // Stop play. + CMainFrame::GetMainFrame()->StopMod(this); + + BeginWaitCursor(); + BEGIN_CRITICAL(); + + // convert to IT... + ChangeModType(MOD_TYPE_IT); + + // clear order list + m_SndFile.Order.Init(); + m_SndFile.Order[0] = 0; + + // remove all patterns + m_SndFile.Patterns.Init(); + m_SndFile.Patterns.Insert(0, 64); + m_SndFile.SetCurrentOrder(0); + + // Global vars + m_SndFile.m_nDefaultTempo = 125; + m_SndFile.m_nDefaultSpeed = 6; + m_SndFile.m_nDefaultGlobalVolume = 256; + m_SndFile.m_nSamplePreAmp = 48; + m_SndFile.m_nVSTiVolume = 48; + m_SndFile.m_nRestartPos = 0; + + // Set 4 default channels. + m_SndFile.ReArrangeChannels(vector<CHANNELINDEX>(4, MAX_BASECHANNELS)); + + //remove plugs + bool keepMask[MAX_MIXPLUGINS]; memset(keepMask, 0, sizeof(keepMask)); + RemovePlugs(keepMask); + + // instruments + if(m_SndFile.m_nInstruments && ::MessageBox(NULL, "Remove instruments?", "Compo Cleanup", MB_YESNO | MB_ICONQUESTION) == IDYES) + { + // remove instruments + RemoveAllInstruments(false); + } + else + { + // reset instruments + for(UINT i = 1; i <= m_SndFile.m_nInstruments; i++) + { + m_SndFile.Headers[i]->nFadeOut = 256; + m_SndFile.Headers[i]->nGlobalVol = 64; + m_SndFile.Headers[i]->nPan = 128; + m_SndFile.Headers[i]->dwFlags &= ~ENV_SETPANNING; + m_SndFile.Headers[i]->nMixPlug = 0; + + m_SndFile.Headers[i]->nVolSwing = 0; + m_SndFile.Headers[i]->nPanSwing = 0; + m_SndFile.Headers[i]->nCutSwing = 0; + m_SndFile.Headers[i]->nResSwing = 0; + + //might be a good idea to leave those enabled... + /* + m_SndFile.Headers[i]->dwFlags &= ~ENV_VOLUME; + m_SndFile.Headers[i]->dwFlags &= ~ENV_PANNING; + m_SndFile.Headers[i]->dwFlags &= ~ENV_PITCH; + m_SndFile.Headers[i]->dwFlags &= ~ENV_FILTER; + */ + } + } + + // reset samples + ctrlSmp::ResetSamples(m_SndFile, ctrlSmp::SmpResetCompo); + + // Set modflags. + m_SndFile.SetModFlag(MSF_MIDICC_BUGEMULATION, false); + m_SndFile.SetModFlag(MSF_OLDVOLSWING, false); + m_SndFile.SetModFlag(MSF_COMPATIBLE_PLAY, true); + + END_CRITICAL(); + EndWaitCursor(); + + UpdateAllViews(NULL, HINT_MODGENERAL, this); + + SetModified(); + return TRUE; +} + + BOOL CModDoc::AdjustEndOfSample(UINT nSample) //------------------------------------------- { @@ -1538,6 +1675,7 @@ MODCOMMAND *m = m_SndFile.Patterns[nPattern]; UINT nrow = dwBeginSel >> 16; UINT ncol = (dwBeginSel & 0xFFFF) >> 3; + ORDERINDEX oCurrentOrder = m_SndFile.GetCurrentOrder(); //jojo.echopaste UINT col; BOOL bS3M = FALSE, bOk = FALSE; UINT len = 0; @@ -1683,6 +1821,22 @@ // Next row m += m_SndFile.m_nChannels; nrow++; + + //jojo.echopaste + if(CMainFrame::m_dwPatternSetup & PATTERN_ECHOPASTE) + { + while(nrow >= m_SndFile.PatternSize[nPattern]) + { + nrow = 0; + ORDERINDEX oNextOrder = m_SndFile.Order.GetNextOrderIgnoringSkips(oCurrentOrder); + if((oNextOrder <= 0) || (oNextOrder >= m_SndFile.Order.size())) goto PasteDone; + nPattern = m_SndFile.Order[oNextOrder]; + if(m_SndFile.Patterns.IsValidIndex(nPattern) == false) goto PasteDone; + m = m_SndFile.Patterns[nPattern]; + oCurrentOrder = oNextOrder; + } + } + } PasteDone: GlobalUnlock(hCpy); Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -602,6 +602,8 @@ OPTGEN_SYNCMUTE, OPTGEN_AUTODELAY, OPTGEN_PATNOTEFADE, + OPTGEN_ECHOPASTE, + OPTGEN_POSITIONAWARETIMER, OPTGEN_MAXOPTIONS }; @@ -637,7 +639,9 @@ {"Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, {"Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"}, {"Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."}, - {"Note fade on key up", "Enable to fade/stop notes on key up in pattern tab." } + {"Note fade on key up", "Enable to fade/stop notes on key up in pattern tab." }, + {"Echo paste mode", "Wrap pasted pattern data into next pattern. This is useful for creating echo channels."}, + {"Position aware timer", "If enabled, timer will show the playback position time if possible instead of running timer."}, }; @@ -700,6 +704,8 @@ case OPTGEN_AUTODELAY: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY); break; case OPTGEN_PATNOTEFADE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE); break; + case OPTGEN_ECHOPASTE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_ECHOPASTE); break; + case OPTGEN_POSITIONAWARETIMER: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_POSITIONAWARETIMER); break; } m_CheckList.SetCheck(i, (bCheck) ? TRUE : FALSE); } @@ -758,6 +764,8 @@ case OPTGEN_SYNCMUTE: mask = PATTERN_SYNCMUTE; break; case OPTGEN_AUTODELAY: mask = PATTERN_AUTODELAY; break; case OPTGEN_PATNOTEFADE: mask = PATTERN_NOTEFADE; break; + case OPTGEN_ECHOPASTE: mask = PATTERN_ECHOPASTE; break; + case OPTGEN_POSITIONAWARETIMER: mask = PATTERN_POSITIONAWARETIMER; break; } if (bCheck) CMainFrame::m_dwPatternSetup |= mask; else CMainFrame::m_dwPatternSetup &= ~mask; Modified: trunk/OpenMPT/mptrack/OrderToPatternTable.cpp =================================================================== --- trunk/OpenMPT/mptrack/OrderToPatternTable.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/OrderToPatternTable.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -159,6 +159,18 @@ } +void COrderToPatternTable::Init() +//------------------------------- +{ + resize(MAX_ORDERS, GetInvalidPatIndex()); + for(ORDERINDEX i = 0; i < GetCount(); i++) + { + (*this)[i] = GetInvalidPatIndex(); + } +} + + + PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65535 : 0xFF;} PATTERNINDEX COrderToPatternTable::GetIgnoreIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65534 : 0xFE;} Modified: trunk/OpenMPT/mptrack/OrderToPatternTable.h =================================================================== --- trunk/OpenMPT/mptrack/OrderToPatternTable.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/OrderToPatternTable.h 2009-06-17 17:50:41 UTC (rev 271) @@ -28,6 +28,9 @@ public: COrderToPatternTable(const CSoundFile& sndFile) : m_rSndFile(sndFile) {} + // Initialize default sized sequence. + void Init(); + bool ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength); size_t WriteAsByte(FILE* f, const UINT count); Modified: trunk/OpenMPT/mptrack/View_gen.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -1359,12 +1359,14 @@ // Update instruments for (INSTRUMENTINDEX nIns=1; nIns<=pSndFile->m_nInstruments; nIns++) { if (pSndFile->Headers[nIns] && (pSndFile->Headers[nIns]->nMixPlug == src+1)) { - pSndFile->Headers[nIns]->nMixPlug = dest+1; + pSndFile->Headers[nIns]->nMixPlug = static_cast<BYTE>(dest+1); } } END_CRITICAL(); + pModDoc->SetModified(); + return true; } @@ -1411,6 +1413,8 @@ m_CbnPlugin.SetCurSel(m_nCurrentPlugin); OnPluginChanged(); + + pModDoc->SetModified(); } } Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -3509,6 +3509,7 @@ case kcChangeLoopStatus: SendCtrlMessage(CTRLMSG_PAT_LOOP, -1); return wParam; case kcNewPattern: SendCtrlMessage(CTRLMSG_PAT_NEWPATTERN); return wParam; case kcSwitchToOrderList: OnSwitchToOrderList(); + case kcSwitchEchoPaste: CMainFrame::m_dwPatternSetup ^= PATTERN_ECHOPASTE; return wParam; } //Ranges: Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -1363,6 +1363,12 @@ InvalidateSample(); pModDoc->SetModified(); } + else + { + // ctrl + click = play from cursor pos + if(CMainFrame::GetInputHandler()->CtrlPressed()) + PlayNote(NOTE_MIDDLEC, ScreenToSample(point.x)); + } } } @@ -2031,8 +2037,8 @@ { } -void CViewSample::PlayNote(UINT note) -//----------------------------------------------------- +void CViewSample::PlayNote(UINT note, const uint32 nStartPos) +//------------------------------------------------------------ { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CModDoc *pModDoc = GetDocument(); @@ -2049,11 +2055,17 @@ pModDoc->NoteOff(note, TRUE); else pModDoc->NoteOff(0, TRUE); + DWORD loopstart = m_dwBeginSel, loopend = m_dwEndSel; if (loopend - loopstart < (UINT)(4 << m_nZoom)) loopend = loopstart = 0; // selection is too small -> no loop - pModDoc->PlayNote(note, 0, m_nSample, FALSE, -1, loopstart, loopend); + if(nStartPos != uint32_max) + pModDoc->PlayNote(note, 0, m_nSample, FALSE, -1, loopstart, loopend, -1, nStartPos); + else + pModDoc->PlayNote(note, 0, m_nSample, FALSE, -1, loopstart, loopend); + + m_dwStatus |= SMPSTATUS_KEYDOWN; s[0] = 0; if ((note) && (note <= NOTE_MAX)) wsprintf(s, "%s%d", szNoteNames[(note-1)%12], (note-1)/12); Modified: trunk/OpenMPT/mptrack/View_smp.h =================================================================== --- trunk/OpenMPT/mptrack/View_smp.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/View_smp.h 2009-06-17 17:50:41 UTC (rev 271) @@ -32,7 +32,7 @@ BOOL SetZoom(UINT nZoom); LONG SampleToScreen(LONG n) const; DWORD ScreenToSample(LONG x) const; - void PlayNote(UINT note); //rewbs.customKeys + void PlayNote(UINT note, const uint32 nStartPos = uint32_max); //rewbs.customKeys void InvalidateSample(); void SetCurSel(DWORD nBegin, DWORD nEnd); void ScrollToPosition(int x); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-06-17 17:50:41 UTC (rev 271) @@ -146,6 +146,7 @@ MENUITEM "Cleanup S&ong", ID_CLEANUP_SONG MENUITEM "Remove &All Instruments", ID_INSTRUMENTS_REMOVEALL MENUITEM "Cleanup &Plugins", ID_CLEANUP_PLUGS + MENUITEM "Co&mpo Cleanup", ID_CLEANUP_COMPO END MENUITEM SEPARATOR MENUITEM "&Find\tCtrl+F", ID_EDIT_FIND @@ -2050,6 +2051,7 @@ BOTTOMMARGIN, 104 END + ID_CLEANUP_COMPO "Reset attributes to defaults (useful for creating sample packs)\Compo Cleanup" IDD_CONTROL_INSTRUMENTS, DIALOG BEGIN RIGHTMARGIN, 522 Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2009-06-17 17:50:41 UTC (rev 271) @@ -358,6 +358,9 @@ RelativePath=".\modedit.cpp"> </File> <File + RelativePath="..\soundlib\modsmp_ctrl.cpp"> + </File> + <File RelativePath=".\Moptions.cpp"> </File> <File @@ -771,6 +774,9 @@ RelativePath=".\moddoc.h"> </File> <File + RelativePath="..\soundlib\modsmp_ctrl.h"> + </File> + <File RelativePath=".\Moptions.h"> </File> <File Modified: trunk/OpenMPT/mptrack/patternContainer.cpp =================================================================== --- trunk/OpenMPT/mptrack/patternContainer.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/patternContainer.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -85,3 +85,16 @@ else if(Size() < MAX_PATTERNS) ResizeArray(MAX_PATTERNS); } + +void CPatternContainer::Init() +//---------------------------- +{ + for(PATTERNINDEX i = 0; i < Size(); i++) + { + Remove(i); + } + + ResizeArray(MAX_PATTERNS); +} + + Modified: trunk/OpenMPT/mptrack/patternContainer.h =================================================================== --- trunk/OpenMPT/mptrack/patternContainer.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/patternContainer.h 2009-06-17 17:50:41 UTC (rev 271) @@ -30,6 +30,9 @@ public: CPatternContainer(CSoundFile& sndFile) : m_rSndFile(sndFile) {m_Patterns.assign(MAX_PATTERNS, MODPATTERN(*this));} + // Clears existing patterns and resizes array to default size. + void Init(); + //Note: No memory handling here. void ClearPatterns() {m_Patterns.assign(m_Patterns.size(), MODPATTERN(*this));} Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/mptrack/resource.h 2009-06-17 17:50:41 UTC (rev 271) @@ -1056,7 +1056,7 @@ #define ID_NETLINK_MODARCHIVE 59214 #define ID_PATTERN_DUPLICATECHANNEL 59216 #define ID_EDIT_GOTO_MENU 59220 - +#define ID_CLEANUP_COMPO 59221 #define ID_SAMPLE_DRAW 59224 #define ID_SAMPLE_ADDSILENCE 59225 // Next default values for new objects Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-17 17:50:41 UTC (rev 271) @@ -846,7 +846,7 @@ public: //Misc void ChangeModTypeTo(const MODTYPE& newType); - //Return value in seconds. + //Returns value in seconds. If given position won't be played at all, returns -1. double GetPlaybackTimeAt(ORDERINDEX, ROWINDEX); uint16 GetModFlags() const {return m_ModFlags;} Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.cpp =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2009-06-17 17:50:41 UTC (rev 271) @@ -149,4 +149,25 @@ } +void ResetSamples(CSoundFile& rSndFile, ResetFlag resetflag) +//---------------------------------------------------------- +{ + const UINT nSamples = rSndFile.GetNumSamples(); + for(UINT i = 1; i <= nSamples; i++) + { + if(resetflag == SmpResetCompo) + { + rSndFile.Ins[i].nPan = 128; + rSndFile.Ins[i].nGlobalVol = 64; + rSndFile.Ins[i].nVolume = 256; + rSndFile.Ins[i].nVibDepth = 0; + rSndFile.Ins[i].nVibRate = 0; + rSndFile.Ins[i].nVibSweep = 0; + rSndFile.Ins[i].nVibType = 0; + rSndFile.Ins[i].uFlags &= ~CHN_PANNING; + } + } +} + + } // namespace ctrlSmp Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.h =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.h 2009-06-15 20:04:15 UTC (rev 270) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.h 2009-06-17 17:50:41 UTC (rev 271) @@ -12,6 +12,11 @@ typedef uintptr_t SmpLength; +enum ResetFlag +{ + SmpResetCompo = 1 +}; + // 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. @@ -27,6 +32,9 @@ // allocation may be more than what this function returns. inline SmpLength GetSampleCapacity(MODINSTRUMENT& smp) {return smp.GetSampleSizeInBytes();} +// Resets samples. +void ResetSamples(CSoundFile& rSndFile, ResetFlag resetflag); + } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-15 20:34:09
|
Revision: 270 http://modplug.svn.sourceforge.net/modplug/?rev=270&view=rev Author: relabsoluness Date: 2009-06-15 20:04:15 +0000 (Mon, 15 Jun 2009) Log Message: ----------- (Patch from Jojo, merged slightly modified) + XM: Compatibility play-mode with a couple of related fixes. + XM: Detects compatibility mode automatically when loading XM-file. Modified Paths: -------------- trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -280,7 +280,9 @@ p->SetWindowText("1. Enable more IT compatible playback.\n" "2. Use old random variation behavior for instruments.\n" "3. Enable plugin volume command bug emulation."); - else if(XM) p->SetWindowText("1. Unused\n2. Unused\n3. Plugin volume command bug emulation"); + else if(XM) p->SetWindowText("1. Enable more XM compatible playback.\n" + "2. Unused\n" + "3. Plugin volume command bug"); } p = GetDlgItem(IDC_FLAGEDITTITLE); if(p) p->ShowWindow(XMorITorMPT); Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -1490,7 +1490,7 @@ { SetModFlag(MSF_MIDICC_BUGEMULATION, false); SetModFlag(MSF_OLDVOLSWING, false); - SetModFlag(MSF_IT_COMPATIBLE_PLAY, true); + SetModFlag(MSF_COMPATIBLE_PLAY, true); } } return TRUE; Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -95,6 +95,8 @@ BYTE samples_used[(MAX_SAMPLES+7)/8]; UINT unused_samples; + bool bMadeWithModPlug = false; + m_nChannels = 0; if ((!lpStream) || (dwMemLength < 0x200)) return FALSE; if (_strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE; @@ -554,6 +556,7 @@ } dwMemPos += len; } + bMadeWithModPlug = true; } // Read midi config: "MIDI" if ((dwMemPos + 8 < dwMemLength) && (LittleEndian(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D)) @@ -566,6 +569,7 @@ m_dwSongFlags |= SONG_EMBEDMIDICFG; dwMemPos += len; //rewbs.fix36946 } + bMadeWithModPlug = true; } // Read pattern names: "PNAM" if ((dwMemPos + 8 < dwMemLength) && (LittleEndian(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) @@ -582,6 +586,7 @@ } dwMemPos += len; } + bMadeWithModPlug = true; } // Read channel names: "CNAM" if ((dwMemPos + 8 < dwMemLength) && (LittleEndian(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) @@ -598,13 +603,18 @@ } dwMemPos += len; } + bMadeWithModPlug = true; } // Read mix plugins information if (dwMemPos + 8 < dwMemLength) { dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos); + bMadeWithModPlug = true; } + if(bMadeWithModPlug == false) + SetModFlag(MSF_COMPATIBLE_PLAY, true); + // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -417,7 +417,7 @@ MODINSTRUMENT *psmp = &Ins[instr]; UINT note = pChn->nNewNote; - if(note == 0 && TypeIsIT_MPT() && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) return; + if(note == 0 && TypeIsIT_MPT() && GetModFlag(MSF_COMPATIBLE_PLAY)) return; if ((penv) && (note) && (note <= 128)) { @@ -498,7 +498,7 @@ if ((!bPorta) || (!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT))) || (m_dwSongFlags & SONG_ITCOMPATMODE) || (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)) //IT compatibility tentative fix: Reset envelopes when instrument changes. - || (TypeIsIT_MPT() && GetModFlag(MSF_IT_COMPATIBLE_PLAY) && bInstrumentChanged)) + || (TypeIsIT_MPT() && GetModFlag(MSF_COMPATIBLE_PLAY) && bInstrumentChanged)) { pChn->dwFlags |= CHN_FASTVOLRAMP; if ((m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE)))) @@ -535,7 +535,7 @@ //IT compatibility tentative fix: Don't anymore change bidi loop direction when //no sample nor instrument is changed. - if(TypeIsIT_MPT() && GetModFlag(MSF_IT_COMPATIBLE_PLAY) && psmp == pChn->pInstrument && !bInstrumentChanged) + if(TypeIsIT_MPT() && GetModFlag(MSF_COMPATIBLE_PLAY) && psmp == pChn->pInstrument && !bInstrumentChanged) pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags & 0xFF); else pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags & 0xFF); @@ -622,7 +622,7 @@ } //IT compatibility tentative fix: Clear channel note memory. - if(TypeIsIT_MPT() && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(TypeIsIT_MPT() && GetModFlag(MSF_COMPATIBLE_PLAY)) { pChn->nNote = 0; pChn->nNewNote = 0; @@ -1085,7 +1085,7 @@ nStartTick = param & 0x0F; //IT compatibility 08. Handling of out-of-range delay command. - if(nStartTick >= m_nMusicSpeed && GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(nStartTick >= m_nMusicSpeed && GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT) && GetModFlag(MSF_COMPATIBLE_PLAY)) { if(instr) { @@ -1137,7 +1137,7 @@ if ((!note) && (instr)) //Case: instrument with no note data. { //IT compatibility: Instrument with no note. - if(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_COMPATIBLE_PLAY)) { if(m_nInstruments) { @@ -1316,14 +1316,14 @@ break; case VOLCMD_PORTAUP: - if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_COMPATIBLE_PLAY)) PortamentoUp(pChn, vol << 2, true); else PortamentoUp(pChn, vol << 2, false); break; case VOLCMD_PORTADOWN: - if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_COMPATIBLE_PLAY)) PortamentoDown(pChn, vol << 2, true); else PortamentoDown(pChn, vol << 2, false); @@ -1533,7 +1533,25 @@ // Key Off case CMD_KEYOFF: - if (!m_nTickCount) KeyOff(nChn); + if(GetModFlag(MSF_COMPATIBLE_PLAY) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) + { + // This is how it's supposed to sound... + if (m_nTickCount == param) + { + // XM: Key-Off + Sample == Note Cut + if ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME))) + { + pChn->dwFlags |= CHN_FASTVOLRAMP; + pChn->nVolume = 0; + } + KeyOff(nChn); + } + } + else + { + // This is how it's NOT supposed to sound... + if (!m_nTickCount) KeyOff(nChn); + } break; // Extra-fine porta up/down @@ -1576,16 +1594,21 @@ if (!m_nTickCount) { pChn->nVolEnvPosition = param; - pChn->nPanEnvPosition = param; - pChn->nPitchEnvPosition = param; - if (pChn->pHeader) + + if(!GetModFlag(MSF_COMPATIBLE_PLAY) || !(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) { - INSTRUMENTHEADER *penv = pChn->pHeader; - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) + pChn->nPanEnvPosition = param; + pChn->nPitchEnvPosition = param; + if (pChn->pHeader) { - pChn->dwFlags &= ~CHN_PANENV; + INSTRUMENTHEADER *penv = pChn->pHeader; + if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) + { + pChn->dwFlags &= ~CHN_PANENV; + } } } + } break; @@ -1944,7 +1967,7 @@ pChn->dwFlags |= CHN_PORTAMENTO; //IT compatibility 03 - if(!(m_dwSongFlags & SONG_ITCOMPATMODE) && (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(!(m_dwSongFlags & SONG_ITCOMPATMODE) && (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_COMPATIBLE_PLAY)) { if(param == 0) param = pChn->nOldPortaUpDown; pChn->nOldPortaUpDown = param; @@ -3061,7 +3084,7 @@ pChn->nPatternLoopCount--; if(!pChn->nPatternLoopCount) { - if(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_COMPATIBLE_PLAY)) pChn->nPatternLoop = m_nRow+1; return -1; @@ -3070,7 +3093,7 @@ { MODCHANNEL *p = Chn; - if(!(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_IT_COMPATIBLE_PLAY))) + if(!(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && GetModFlag(MSF_COMPATIBLE_PLAY))) { for (UINT i=0; i<m_nChannels; i++, p++) if (p != pChn) { Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -2917,22 +2917,15 @@ uint16 CSoundFile::GetModFlagMask(const MODTYPE oldtype, const MODTYPE newtype) const //----------------------------------------------------------------------------------- { - if(oldtype == MOD_TYPE_IT) - { - if(newtype == MOD_TYPE_MPT) return 65535; - if(newtype == MOD_TYPE_XM) return (1 << MSF_MIDICC_BUGEMULATION); - return 0; - } + const MODTYPE combined = oldtype | newtype; - if(oldtype == MOD_TYPE_MPT) - { - if(newtype == MOD_TYPE_IT) return 65535; - if(newtype == MOD_TYPE_XM) return (1 << MSF_MIDICC_BUGEMULATION); - return 0; - } + // XM <-> IT/MPT conversion. + if(combined == (MOD_TYPE_IT|MOD_TYPE_XM) || combined == (MOD_TYPE_MPT|MOD_TYPE_XM)) + return (1 << MSF_COMPATIBLE_PLAY) + (1 << MSF_MIDICC_BUGEMULATION); - if(oldtype == MOD_TYPE_XM && (newtype == MOD_TYPE_IT || newtype == MOD_TYPE_MPT)) - return (1 << MSF_MIDICC_BUGEMULATION); + // IT <-> MPT conversion. + if(combined == (MOD_TYPE_IT|MOD_TYPE_MPT)) + return uint16_max; return 0; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-15 20:04:15 UTC (rev 270) @@ -828,7 +828,7 @@ //Note: These are bit indeces. MSF <-> Mod(Specific)Flag. //If changing these, ChangeModTypeTo() might need modification. -const BYTE MSF_IT_COMPATIBLE_PLAY = 0; //IT/MPT +const BYTE MSF_COMPATIBLE_PLAY = 0; //IT/MPT/XM const BYTE MSF_OLDVOLSWING = 1; //IT/MPT const BYTE MSF_MIDICC_BUGEMULATION = 2; //IT/MPT/XM Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-06-14 21:48:05 UTC (rev 269) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-06-15 20:04:15 UTC (rev 270) @@ -1164,7 +1164,7 @@ else { //IT playback compatibility 01 & 02 - if(GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT) && GetModFlag(MSF_IT_COMPATIBLE_PLAY)) + if(GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT) && GetModFlag(MSF_COMPATIBLE_PLAY)) { if(pChn->nArpeggio >> 4 != 0 || (pChn->nArpeggio & 0x0F) != 0) { @@ -1276,7 +1276,7 @@ switch (pChn->nVibratoType & 0x03) { case 1: - if(GetModFlag(MSF_IT_COMPATIBLE_PLAY) == true) + if(GetModFlag(MSF_COMPATIBLE_PLAY) == true) vdelta = -ModRampDownTable[(vibpos+16) % 64]; else vdelta = ModRampDownTable[vibpos]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <rel...@us...> - 2009-06-12 17:32:32
|
Revision: 268 http://modplug.svn.sourceforge.net/modplug/?rev=268&view=rev Author: relabsoluness Date: 2009-06-12 17:32:08 +0000 (Fri, 12 Jun 2009) Log Message: ----------- ? Added validations to song/instrument extension reading and refactored related code. (merged from rev. 267) Modified Paths: -------------- trunk/OpenMPT/mptrack/misc_util.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/misc_util.h =================================================================== --- trunk/OpenMPT/mptrack/misc_util.h 2009-06-12 16:25:54 UTC (rev 267) +++ trunk/OpenMPT/mptrack/misc_util.h 2009-06-12 17:32:08 UTC (rev 268) @@ -42,10 +42,34 @@ // Size of the array must be known at compile time. template <size_t size> inline void SetNullTerminator(char (&buffer)[size]) +//------------------------------------------------- { STATIC_ASSERT(size > 0); buffer[size-1] = 0; } +// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'. +// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'. +// If 'lowerLimit' > 'upperLimit', 'val' won't be modified. +template<class T, class C> +inline void Limit(T& val, const C lowerLimit, const C upperLimit) +//--------------------------------------------------------------- +{ + if(lowerLimit > upperLimit) return; + if(val < lowerLimit) val = lowerLimit; + else if(val > upperLimit) val = upperLimit; +} + + +// Like Limit, but with upperlimit only. +template<class T, class C> +inline void LimitMax(T& val, const C upperLimit) +//---------------------------------------------- +{ + if(val > upperLimit) + val = upperLimit; +} + + #endif Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-12 16:25:54 UTC (rev 267) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-12 17:32:08 UTC (rev 268) @@ -847,8 +847,7 @@ // Extra info data __int32 fcode = 0; - __int16 fsize = 0; - BYTE * ptr = (BYTE *)(lpStream + streamPos); + LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); if (streamPos <= dwMemLength - 4) { fcode = (*((__int32 *)ptr)); @@ -863,7 +862,7 @@ i = 1; // parse file - while( ptr + 4 <= (BYTE *)(lpStream + dwMemLength) && i <= m_nInstruments ){ + while( uintptr_t(ptr - lpStream) <= dwMemLength - 4 && i <= m_nInstruments ){ fcode = (*((__int32 *)ptr)); // read field code @@ -876,16 +875,7 @@ default: ptr += sizeof(__int32); // jump field code - if(ptr + 2 > (BYTE *)(lpStream + dwMemLength)) return FALSE; - fsize = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[i], fcode, fsize); - if(fadr && fcode != 'K[..') // copy field data in instrument's header - { - if(ptr + fsize > (BYTE *)(lpStream + dwMemLength)) return FALSE; - memcpy(fadr,ptr,fsize); // (except for keyboard mapping) - } - ptr += fsize; // jump field + ReadExtendedInstrumentProperty(Headers[i], fcode, ptr, lpStream + dwMemLength); break; } } @@ -893,7 +883,7 @@ //HACK: if we fail on i <= m_nInstruments above, arrive here without having set fcode as appropriate, // hence the code duplication. - if (ptr + 4 <= (BYTE *)(lpStream + dwMemLength)) { + if ( (uintptr_t)(ptr - lpStream) <= dwMemLength - 4 ) { fcode = (*((__int32 *)ptr)); } @@ -1320,55 +1310,18 @@ ITSAMPLESTRUCT *pis = (ITSAMPLESTRUCT *)(lpStream+smppos[pifh->smpnum-1]); dwMemPos = pis->samplepointer + lastSampleSize; - // Get file pointer to match the first byte of extra settings informations __int16 size = 0; - __int32 code = 0; - __int16 size = 0; - BYTE * ptr = NULL; - if(dwMemPos < dwMemLength) { - ptr = (BYTE *)(lpStream + dwMemPos); - code = (*((__int32 *)ptr));; + // Load instrument and song extensions. + if(mptStartPos >= dwMemPos) + { + LPCBYTE ptr = LoadExtendedInstrumentProperties(lpStream + dwMemPos, lpStream + mptStartPos, &interpretModplugmade); + LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos, &interpretModplugmade); } - - // Instrument extensions - if( code == 'MPTX' ){ - interpretModplugmade = true; - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < mptStartPos ){ //Loop 'till beginning of end of file/mpt specific looking for inst. extensions - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } // -! NEW_FEATURE#0027 - // Song extensions - if( code == 'MPTS' ) - { - interpretModplugmade = true; - LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos); - } + // Reading Patterns Patterns.ResizeArray(max(MAX_PATTERNS, npatterns)); - - // Reading Patterns for (UINT npat=0; npat<npatterns; npat++) { if ((!patpos[npat]) || ((DWORD)patpos[npat] >= dwMemLength - 4)) @@ -3691,47 +3644,124 @@ return; } +LPCBYTE CSoundFile::LoadExtendedInstrumentProperties(const LPCBYTE pStart, + const LPCBYTE pEnd, + bool* pInterpretMptMade) +//--------------------------------------------------------------------------- +{ + if( pStart == NULL || pEnd <= pStart || uintptr_t(pEnd - pStart) < 4) + return NULL; -void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const LPCBYTE lpStream, const size_t searchlimit) -//-------------------------------------------------- + int32 code = 0; + int16 size = 0; + LPCBYTE ptr = pStart; + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTX') + return NULL; + + // Found MPTX, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + ptr += sizeof(int32); // jump extension header code + while( ptr < pEnd && uintptr_t(pEnd-ptr) >= 4) //Loop 'till beginning of end of file/mpt specific looking for inst. extensions + { + memcpy(&code, ptr, sizeof(code)); // read field code + if (code == 'MPTS') //Reached song extensions, break out of this loop + return ptr; + + ptr += sizeof(code); // jump field code + + if((uintptr_t)(pEnd - ptr) < 2) + return NULL; + + memcpy(&size, ptr, sizeof(size)); // read field size + ptr += sizeof(size); // jump field size + + if(IsValidSizeField(ptr, pEnd, size) == false) + return NULL; + + for(UINT nins=1; nins<=m_nInstruments; nins++) + { + if(Headers[nins]) + ReadInstrumentExtensionField(Headers[nins], ptr, code, size); + } + } + + return NULL; +} + + +void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, + LPCBYTE ptr, + const LPCBYTE lpStream, + const size_t searchlimit, + bool* pInterpretMptMade) +//------------------------------------------------------------------- { + if(searchlimit < 6 || ptr == NULL || ptr < lpStream || uintptr_t(ptr - lpStream) > searchlimit - 4) + return; + + const LPCBYTE pEnd = lpStream + searchlimit; + int32 code = 0; int16 size = 0; - ptr += sizeof(int32); // jump extension header code - while( (DWORD)((ptr + 6) - lpStream) <= searchlimit ) //Loop until given limit. + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTS') + return; + + // Found MPTS, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + + // Case macros. + #define CASE(id, data) \ + case id: fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data)); break; + #define CASE_NOTXM(id, data) \ + case id: if(modtype != MOD_TYPE_XM) {fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data));} break; + + ptr += sizeof(code); // jump extension header code + while( uintptr_t(ptr - lpStream) <= searchlimit-6 ) //Loop until given limit. { - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - if(size < 0) break; - ptr += sizeof(__int16); // jump field size + code = (*((int32 *)ptr)); // read field code + ptr += sizeof(int32); // jump field code + size = (*((int16 *)ptr)); // read field size + ptr += sizeof(int16); // jump field size + if(IsValidSizeField(ptr, pEnd, size) == false) + break; + + size_t nMaxReadCount = 0; BYTE * fadr = NULL; - switch (code) { // interpret field code - case 'DT..': fadr = reinterpret_cast<BYTE*>(&m_nDefaultTempo); break; - case 'RPB.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerBeat); break; - case 'RPM.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerMeasure); break; - case 'C...': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nChannels); break; - case 'TM..': fadr = reinterpret_cast<BYTE*>(&m_nTempoMode); break; - case 'PMM.': fadr = reinterpret_cast<BYTE*>(&m_nMixLevels); break; - case 'CWV.': fadr = reinterpret_cast<BYTE*>(&m_dwCreatedWithVersion); break; - case 'LSWV': fadr = reinterpret_cast<BYTE*>(&m_dwLastSavedWithVersion); break; - case 'SPA.': fadr = reinterpret_cast<BYTE*>(&m_nSamplePreAmp); break; - case 'VSTV': fadr = reinterpret_cast<BYTE*>(&m_nVSTiVolume); break; - case 'DGV.': fadr = reinterpret_cast<BYTE*>(&m_nDefaultGlobalVolume); break; - case 'RP..': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nRestartPos); break; - case 'MSF.': fadr = reinterpret_cast<BYTE*>(&m_ModFlags); break; - case 'MIMA': - if(DWORD(ptr - lpStream + DWORD(size)) > searchlimit) - MessageBox(NULL, "Error: Bad MIMA datasizefield", NULL, MB_ICONERROR); - else - GetMIDIMapper().Unserialize(ptr, size); - break; + + switch (code) // interpret field code + { + CASE('DT..', m_nDefaultTempo); + CASE('RPB.', m_nRowsPerBeat); + CASE('RPM.', m_nRowsPerMeasure); + CASE_NOTXM('C...', m_nChannels); + CASE('TM..', m_nTempoMode); + CASE('PMM.', m_nMixLevels); + CASE('CWV.', m_dwCreatedWithVersion); + CASE('LSWV', m_dwLastSavedWithVersion); + CASE('SPA.', m_nSamplePreAmp); + CASE('VSTV', m_nVSTiVolume); + CASE('DGV.', m_nDefaultGlobalVolume); + CASE_NOTXM('RP..', m_nRestartPos); + CASE('MSF.', m_ModFlags); + case 'MIMA': GetMIDIMapper().Unserialize(ptr, size); break; case 'ChnS': - if( ((ptr - lpStream) + DWORD(size) <= searchlimit) && (size <= 63*2) && (size % 2 == 0) ) + if( (size <= 63*2) && (size % 2 == 0) ) { const BYTE* pData = ptr; - for(__int16 i = 0; i<size/2; i++, pData += 2) if(pData[0] != 0xFF) + STATIC_ASSERT(ARRAYELEMCOUNT(ChnSettings) >= 64); + const __int16 nLoopLimit = min(size/2, ARRAYELEMCOUNT(ChnSettings) - 64); + for(__int16 i = 0; i<nLoopLimit; i++, pData += 2) if(pData[0] != 0xFF) { ChnSettings[i+64].nVolume = pData[1]; ChnSettings[i+64].nPan = 128; @@ -3745,11 +3775,30 @@ break; } - if (fadr != NULL && (ptr - lpStream) + DWORD(size) <= searchlimit) { // if field code recognized - memcpy(fadr,ptr,size); // read field data - } + if (fadr != NULL) // if field code recognized + memcpy(fadr,ptr,nMaxReadCount); // read field data + ptr += size; // jump field data } + + // Validate read values. + Limit(m_nDefaultTempo, GetModSpecifications().tempoMin, GetModSpecifications().tempoMax); + //m_nRowsPerBeat + //m_nRowsPerMeasure + LimitMax(m_nChannels, GetModSpecifications().channelsMax); + //m_nTempoMode + //m_nMixLevels + //m_dwCreatedWithVersion + //m_dwLastSavedWithVersion + //m_nSamplePreAmp + //m_nVSTiVolume + //m_nDefaultGlobalVolume); + //m_nRestartPos + //m_ModFlags + + + #undef CASE + #undef CASE_NOTXM } Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-06-12 16:25:54 UTC (rev 267) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-06-12 17:32:08 UTC (rev 268) @@ -611,54 +611,16 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwMemLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - BYTE * ptr = (BYTE *)(lpStream + dwMemPos); + bool bInterpretMptMade = false; + LPCBYTE ptr = lpStream + dwMemPos; + if(m_nInstruments) + ptr = LoadExtendedInstrumentProperties(ptr, lpStream+dwMemLength, &bInterpretMptMade); - // Seek for supported extended settings header - __int16 size = 0; - __int32 code = (*((__int32 *)ptr)); + LoadExtendedSongProperties(GetType(), ptr, lpStream, dwMemLength, &bInterpretMptMade); - // Instrument extensions - if( code == 'MPTX' && m_nInstruments ){ - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < dwMemLength ){ //Loop 'till end of file looking for inst. extensions + if(bInterpretMptMade && m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) + SetModFlag(MSF_MIDICC_BUGEMULATION, true); - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } -// -! NEW_FEATURE#0027 - - // Song extensions - if( code == 'MPTS' ) - { - LoadExtendedSongProperties(MOD_TYPE_XM, ptr, lpStream, dwMemLength); - if(m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) - SetModFlag(MSF_MIDICC_BUGEMULATION, true); - } - - - - - return TRUE; } Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2009-06-12 16:25:54 UTC (rev 267) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2009-06-12 17:32:08 UTC (rev 268) @@ -1297,28 +1297,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Compute current file pointer position - BYTE * ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -1827,28 +1807,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -2043,6 +2003,73 @@ } + +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size) +//------------------------------------------------------------------------------ +{ + if(size < 0 || (uintptr_t)(pEnd - pData) < (uintptr_t)size) + return false; + else + return true; +} + + +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size) +//------------------------------------------------------------------------------------------------------------ +{ + // get field's address in instrument's header + BYTE* fadr = GetInstrumentHeaderFieldPointer(penv, code, size); + + if(fadr && code != 'K[..') // copy field data in instrument's header + memcpy(fadr,ptr,size); // (except for keyboard mapping) + ptr += size; // jump field +} + + +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd) +//--------------------------------------------------------------------------------------------------------------- +{ + if(pEnd < pData || uintptr_t(pEnd - pData) < 2) + return; + + int16 size; + memcpy(&size, pData, sizeof(size)); // read field size + pData += sizeof(size); // jump field size + + if(IsValidSizeField(pData, pEnd, size) == false) + return; + + ReadInstrumentExtensionField(penv, pData, code, size); +} + + +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength) +//-------------------------------------------------------------------------------------------------------------- +{ + if(penv == 0 || pDataStart == 0 || nMemLength < 4) + return; + + LPCBYTE pData = pDataStart; + const LPCBYTE pEnd = pDataStart + nMemLength; + + int32 code; + memcpy(&code, pData, sizeof(code)); + + // Seek for supported extended settings header + if( code == 'MPTX' ) + { + pData += sizeof(code); // jump extension header code + + while( (uintptr_t)(pData - pDataStart) <= nMemLength - 4) + { + memcpy(&code, pData, sizeof(code)); // read field code + pData += sizeof(code); // jump field code + ReadExtendedInstrumentProperty(penv, code, pData, pEnd); + } + } +} + + /////////////////////////////////////////////////////////////////////////////////////////////////// // 8SVX Samples Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-06-12 16:25:54 UTC (rev 267) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-06-12 17:32:08 UTC (rev 268) @@ -1086,8 +1086,13 @@ void WriteInstrumentPropertyForAllInstruments(__int32 code, __int16 size, FILE* f, INSTRUMENTHEADER* instruments[], UINT nInstruments); void SaveExtendedInstrumentProperties(INSTRUMENTHEADER *instruments[], UINT nInstruments, FILE* f); void SaveExtendedSongProperties(FILE* f); - void LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* startpos, const size_t seachlimit); + void LoadExtendedSongProperties(const MODTYPE modtype, LPCBYTE ptr, const LPCBYTE startpos, const size_t seachlimit, bool* pInterpretMptMade = NULL); + // Reads extended instrument properties(XM/IT/MPTM). + // If no errors occur and song extension tag is found, returns pointer to the beginning + // of the tag, else returns NULL. + LPCBYTE LoadExtendedInstrumentProperties(const LPCBYTE pStart, const LPCBYTE pEnd, bool* pInterpretMptMade = NULL); + #endif // MODPLUG_NO_FILESAVE // MOD Convert function UINT GetBestSaveFormat() const; @@ -1515,4 +1520,18 @@ #endif +// Used in instrument/song extension reading to make sure the size field is valid. +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size); + +// Read instrument property with 'code' and 'size' from 'ptr' to instrument 'penv'. +// Note: (ptr, size) pair must be valid (e.g. can read 'size' bytes from 'ptr') +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size); + +// Read instrument property with 'code' from 'pData' to instrument 'penv'. +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd); + +// Read extended instrument properties from 'pDataStart' to instrument 'penv'. +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength); + + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-12 16:25:58
|
Revision: 267 http://modplug.svn.sourceforge.net/modplug/?rev=267&view=rev Author: relabsoluness Date: 2009-06-12 16:25:54 +0000 (Fri, 12 Jun 2009) Log Message: ----------- . XM/IT/MPTM: Fixed a bug in reading an extension. This broke the extension search after reading that entry, although the affected entry has been the last extension in the write order. (merged from rev. 263) . Pattern tab: It's now possible to use the old note fade behaviour when playing notes in pattern tab(see setup->general). (merged from rev. 264) . Pattern tab: Fixed wrong interpretations of "Old style pattern context menu"-option. (merged partly from rev. 262) ? Added validations to song/instrument extension reading and refactored related code. Modified Paths: -------------- branches/1.17.02.53x/mptrack/MainFrm.cpp branches/1.17.02.53x/mptrack/Mainfrm.h branches/1.17.02.53x/mptrack/Moptions.cpp branches/1.17.02.53x/mptrack/View_pat.cpp branches/1.17.02.53x/mptrack/misc_util.h branches/1.17.02.53x/mptrack/version.h branches/1.17.02.53x/soundlib/Load_it.cpp branches/1.17.02.53x/soundlib/Load_xm.cpp branches/1.17.02.53x/soundlib/Sampleio.cpp branches/1.17.02.53x/soundlib/Sndfile.h Modified: branches/1.17.02.53x/mptrack/MainFrm.cpp =================================================================== --- branches/1.17.02.53x/mptrack/MainFrm.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/MainFrm.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -425,6 +425,9 @@ gnMidiPatternLen = GetPrivateProfileLong("MIDI Settings", "MidiImportPatLen", gnMidiPatternLen, iniFile); m_dwPatternSetup = GetPrivateProfileDWord("Pattern Editor", "PatternSetup", m_dwPatternSetup, iniFile); + if(gcsPreviousVersion != "" && MptVersion::ToNum(gcsPreviousVersion) < MAKE_VERSION_NUMERIC(1,17,02,50)) + m_dwPatternSetup |= PATTERN_NOTEFADE; + m_nRowSpacing = GetPrivateProfileDWord("Pattern Editor", "RowSpacing", 16, iniFile); m_nRowSpacing2 = GetPrivateProfileDWord("Pattern Editor", "RowSpacing2", 4, iniFile); gbLoopSong = GetPrivateProfileDWord("Pattern Editor", "LoopSong", true, iniFile); @@ -541,6 +544,7 @@ RegQueryValueEx(key, "MidiSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwMidiSetup, &dwDWORDSize); RegQueryValueEx(key, "MidiDevice", NULL, &dwREG_DWORD, (LPBYTE)&m_nMidiDevice, &dwDWORDSize); RegQueryValueEx(key, "PatternSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwPatternSetup, &dwDWORDSize); + m_dwPatternSetup |= PATTERN_NOTEFADE; // Set flag to maintain old behaviour(was changed in 1.17.02.50). RegQueryValueEx(key, "RowSpacing", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing, &dwDWORDSize); RegQueryValueEx(key, "RowSpacing2", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing2, &dwDWORDSize); RegQueryValueEx(key, "LoopSong", NULL, &dwREG_DWORD, (LPBYTE)&gbLoopSong, &dwDWORDSize); Modified: branches/1.17.02.53x/mptrack/Mainfrm.h =================================================================== --- branches/1.17.02.53x/mptrack/Mainfrm.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/Mainfrm.h 2009-06-12 16:25:54 UTC (rev 267) @@ -206,6 +206,7 @@ #define PATTERN_OLDCTXMENUSTYLE 0x800000 #define PATTERN_SYNCMUTE 0x1000000 #define PATTERN_AUTODELAY 0x2000000 +#define PATTERN_NOTEFADE 0x4000000 // Keyboard Setup Modified: branches/1.17.02.53x/mptrack/Moptions.cpp =================================================================== --- branches/1.17.02.53x/mptrack/Moptions.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/Moptions.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -601,6 +601,7 @@ OPTGEN_PATTERNCTXMENUSTYLE, OPTGEN_SYNCMUTE, OPTGEN_AUTODELAY, + OPTGEN_PATNOTEFADE, OPTGEN_MAXOPTIONS }; @@ -636,6 +637,7 @@ {"Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, {"Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"}, {"Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."}, + {"Note fade on key up", "Enable to fade/stop notes on key up in pattern tab." } }; @@ -697,6 +699,7 @@ case OPTGEN_SYNCMUTE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_SYNCMUTE); break; case OPTGEN_AUTODELAY: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY); break; + case OPTGEN_PATNOTEFADE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE); break; } m_CheckList.SetCheck(i, (bCheck) ? TRUE : FALSE); } @@ -754,6 +757,7 @@ case OPTGEN_PATTERNCTXMENUSTYLE: mask = PATTERN_OLDCTXMENUSTYLE; break; case OPTGEN_SYNCMUTE: mask = PATTERN_SYNCMUTE; break; case OPTGEN_AUTODELAY: mask = PATTERN_AUTODELAY; break; + case OPTGEN_PATNOTEFADE: mask = PATTERN_NOTEFADE; break; } if (bCheck) CMainFrame::m_dwPatternSetup |= mask; else CMainFrame::m_dwPatternSetup &= ~mask; Modified: branches/1.17.02.53x/mptrack/View_pat.cpp =================================================================== --- branches/1.17.02.53x/mptrack/View_pat.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/View_pat.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -3787,8 +3787,12 @@ pModDoc->NoteOff(0, TRUE, ins, m_dwCursor & 0xFFFF); } else - pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); - //pModDoc->NoteOff(note, TRUE, ins, (m_dwCursor & 0xFFFF) >> 3); + { + if(CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE) + pModDoc->NoteOff(note, TRUE, ins, GetChanFromCursor(m_dwCursor)); + else + pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); + } } //Enter note off in pattern? @@ -4518,11 +4522,8 @@ bool CViewPattern::BuildMiscCtxMenu(HMENU hMenu, CInputHandler* ih) //----------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup & PATTERN_OLDCTXMENUSTYLE) return false; - AppendMenu(hMenu, MF_STRING, ID_SHOWTIMEATROW, "Show row play time\t" + ih->GetKeyTextFromCommand(kcTimeAtRow)); return true; - } bool CViewPattern::BuildSelectionCtxMenu(HMENU hMenu, CInputHandler* ih) @@ -4701,9 +4702,6 @@ bool CViewPattern::BuildChannelControlCtxMenu(HMENU hMenu) //-------------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup&PATTERN_OLDCTXMENUSTYLE) return false; - //Not doing the menuentries if opted to use old style menu style. - AppendMenu(hMenu, MF_SEPARATOR, 0, ""); AppendMenu(hMenu, MF_STRING, ID_PATTERN_DUPLICATECHANNEL, "Duplicate this channel"); Modified: branches/1.17.02.53x/mptrack/misc_util.h =================================================================== --- branches/1.17.02.53x/mptrack/misc_util.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/misc_util.h 2009-06-12 16:25:54 UTC (rev 267) @@ -42,10 +42,34 @@ // Size of the array must be known at compile time. template <size_t size> inline void SetNullTerminator(char (&buffer)[size]) +//------------------------------------------------- { STATIC_ASSERT(size > 0); buffer[size-1] = 0; } +// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'. +// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'. +// If 'lowerLimit' > 'upperLimit', 'val' won't be modified. +template<class T, class C> +inline void Limit(T& val, const C lowerLimit, const C upperLimit) +//--------------------------------------------------------------- +{ + if(lowerLimit > upperLimit) return; + if(val < lowerLimit) val = lowerLimit; + else if(val > upperLimit) val = upperLimit; +} + + +// Like Limit, but with upperlimit only. +template<class T, class C> +inline void LimitMax(T& val, const C upperLimit) +//---------------------------------------------- +{ + if(val > upperLimit) + val = upperLimit; +} + + #endif Modified: branches/1.17.02.53x/mptrack/version.h =================================================================== --- branches/1.17.02.53x/mptrack/version.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/version.h 2009-06-12 16:25:54 UTC (rev 267) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 17 #define VER_MINOR 02 -#define VER_MINORMINOR 53 +#define VER_MINORMINOR 54 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of Modified: branches/1.17.02.53x/soundlib/Load_it.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Load_it.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Load_it.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -847,8 +847,7 @@ // Extra info data __int32 fcode = 0; - __int16 fsize = 0; - BYTE * ptr = (BYTE *)(lpStream + streamPos); + LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); if (streamPos <= dwMemLength - 4) { fcode = (*((__int32 *)ptr)); @@ -863,7 +862,7 @@ i = 1; // parse file - while( ptr + 4 <= (BYTE *)(lpStream + dwMemLength) && i <= m_nInstruments ){ + while( uintptr_t(ptr - lpStream) <= dwMemLength - 4 && i <= m_nInstruments ){ fcode = (*((__int32 *)ptr)); // read field code @@ -876,16 +875,7 @@ default: ptr += sizeof(__int32); // jump field code - if(ptr + 2 > (BYTE *)(lpStream + dwMemLength)) return FALSE; - fsize = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[i], fcode, fsize); - if(fadr && fcode != 'K[..') // copy field data in instrument's header - { - if(ptr + fsize > (BYTE *)(lpStream + dwMemLength)) return FALSE; - memcpy(fadr,ptr,fsize); // (except for keyboard mapping) - } - ptr += fsize; // jump field + ReadExtendedInstrumentProperty(Headers[i], fcode, ptr, lpStream + dwMemLength); break; } } @@ -893,7 +883,7 @@ //HACK: if we fail on i <= m_nInstruments above, arrive here without having set fcode as appropriate, // hence the code duplication. - if (ptr + 4 <= (BYTE *)(lpStream + dwMemLength)) { + if ( (uintptr_t)(ptr - lpStream) <= dwMemLength - 4 ) { fcode = (*((__int32 *)ptr)); } @@ -917,8 +907,8 @@ } // -! NEW_FEATURE#0023 -BOOL CSoundFile::ReadIT(const BYTE *lpStream, const DWORD dwMemLength) -//-------------------------------------------------------------- +BOOL CSoundFile::ReadIT(const LPCBYTE lpStream, const DWORD dwMemLength) +//---------------------------------------------------------------------- { ITFILEHEADER *pifh = (ITFILEHEADER *)lpStream; @@ -1320,55 +1310,18 @@ ITSAMPLESTRUCT *pis = (ITSAMPLESTRUCT *)(lpStream+smppos[pifh->smpnum-1]); dwMemPos = pis->samplepointer + lastSampleSize; - // Get file pointer to match the first byte of extra settings informations __int16 size = 0; - __int32 code = 0; - __int16 size = 0; - BYTE * ptr = NULL; - if(dwMemPos < dwMemLength) { - ptr = (BYTE *)(lpStream + dwMemPos); - code = (*((__int32 *)ptr));; + // Load instrument and song extensions. + if(mptStartPos >= dwMemPos) + { + LPCBYTE ptr = LoadExtendedInstrumentProperties(lpStream + dwMemPos, lpStream + mptStartPos, &interpretModplugmade); + LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos, &interpretModplugmade); } - - // Instrument extensions - if( code == 'MPTX' ){ - interpretModplugmade = true; - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < mptStartPos ){ //Loop 'till beginning of end of file/mpt specific looking for inst. extensions - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } // -! NEW_FEATURE#0027 - // Song extensions - if( code == 'MPTS' ) - { - interpretModplugmade = true; - LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos); - } + // Reading Patterns Patterns.ResizeArray(max(MAX_PATTERNS, npatterns)); - - // Reading Patterns for (UINT npat=0; npat<npatterns; npat++) { if ((!patpos[npat]) || ((DWORD)patpos[npat] >= dwMemLength - 4)) @@ -3674,53 +3627,143 @@ return; } +LPCBYTE CSoundFile::LoadExtendedInstrumentProperties(const LPCBYTE pStart, + const LPCBYTE pEnd, + bool* pInterpretMptMade) +//--------------------------------------------------------------------------- +{ + if( pStart == NULL || pEnd <= pStart || uintptr_t(pEnd - pStart) < 4) + return NULL; -void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* lpStream, const size_t searchlimit) -//-------------------------------------------------- + int32 code = 0; + int16 size = 0; + LPCBYTE ptr = pStart; + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTX') + return NULL; + + // Found MPTX, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + ptr += sizeof(int32); // jump extension header code + while( ptr < pEnd && uintptr_t(pEnd-ptr) >= 4) //Loop 'till beginning of end of file/mpt specific looking for inst. extensions + { + memcpy(&code, ptr, sizeof(code)); // read field code + if (code == 'MPTS') //Reached song extensions, break out of this loop + return ptr; + + ptr += sizeof(code); // jump field code + + if((uintptr_t)(pEnd - ptr) < 2) + return NULL; + + memcpy(&size, ptr, sizeof(size)); // read field size + ptr += sizeof(size); // jump field size + + if(IsValidSizeField(ptr, pEnd, size) == false) + return NULL; + + for(UINT nins=1; nins<=m_nInstruments; nins++) + { + if(Headers[nins]) + ReadInstrumentExtensionField(Headers[nins], ptr, code, size); + } + } + + return NULL; +} + + +void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, + LPCBYTE ptr, + const LPCBYTE lpStream, + const size_t searchlimit, + bool* pInterpretMptMade) +//------------------------------------------------------------------- { + if(searchlimit < 6 || ptr == NULL || ptr < lpStream || uintptr_t(ptr - lpStream) > searchlimit - 4) + return; + + const LPCBYTE pEnd = lpStream + searchlimit; + int32 code = 0; int16 size = 0; - ptr += sizeof(int32); // jump extension header code - while( (DWORD)(ptr + 6 - lpStream) <= searchlimit ) //Loop until given limit. + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTS') + return; + + // Found MPTS, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + + // Case macros. + #define CASE(id, data) \ + case id: fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data)); break; + #define CASE_NOTXM(id, data) \ + case id: if(modtype != MOD_TYPE_XM) {fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data));} break; + + ptr += sizeof(code); // jump extension header code + while( uintptr_t(ptr - lpStream) <= searchlimit-6 ) //Loop until given limit. { - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - if(size < 0) break; - ptr += sizeof(__int16); // jump field size + code = (*((int32 *)ptr)); // read field code + ptr += sizeof(int32); // jump field code + size = (*((int16 *)ptr)); // read field size + ptr += sizeof(int16); // jump field size + if(IsValidSizeField(ptr, pEnd, size) == false) + break; + + size_t nMaxReadCount = 0; BYTE * fadr = NULL; - switch (code) { // interpret field code - case 'DT..': fadr = reinterpret_cast<BYTE*>(&m_nDefaultTempo); break; - case 'RPB.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerBeat); break; - case 'RPM.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerMeasure); break; - case 'C...': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nChannels); break; - case 'TM..': fadr = reinterpret_cast<BYTE*>(&m_nTempoMode); break; - case 'PMM.': fadr = reinterpret_cast<BYTE*>(&m_nMixLevels); break; - case 'CWV.': fadr = reinterpret_cast<BYTE*>(&m_dwCreatedWithVersion); break; - case 'LSWV': fadr = reinterpret_cast<BYTE*>(&m_dwLastSavedWithVersion); break; - case 'SPA.': fadr = reinterpret_cast<BYTE*>(&m_nSamplePreAmp); break; - case 'VSTV': fadr = reinterpret_cast<BYTE*>(&m_nVSTiVolume); break; - case 'DGV.': fadr = reinterpret_cast<BYTE*>(&m_nDefaultGlobalVolume); break; - case 'RP..': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nRestartPos); break; - case 'MSF.': fadr = reinterpret_cast<BYTE*>(&m_ModFlags); break; - case 'MIMA': - if(DWORD(ptr - lpStream + DWORD(size)) > searchlimit) - MessageBox(NULL, "Error: Bad MIMA datasizefield", NULL, MB_ICONERROR); - else - { - GetMIDIMapper().Unserialize(ptr, size); - ptr += size; - } - break; + switch (code) // interpret field code + { + CASE('DT..', m_nDefaultTempo); + CASE('RPB.', m_nRowsPerBeat); + CASE('RPM.', m_nRowsPerMeasure); + CASE_NOTXM('C...', m_nChannels); + CASE('TM..', m_nTempoMode); + CASE('PMM.', m_nMixLevels); + CASE('CWV.', m_dwCreatedWithVersion); + CASE('LSWV', m_dwLastSavedWithVersion); + CASE('SPA.', m_nSamplePreAmp); + CASE('VSTV', m_nVSTiVolume); + CASE('DGV.', m_nDefaultGlobalVolume); + CASE_NOTXM('RP..', m_nRestartPos); + CASE('MSF.', m_ModFlags); + case 'MIMA': GetMIDIMapper().Unserialize(ptr, size); break; } - if (fadr != NULL && ptr - lpStream + DWORD(size) <= searchlimit) { // if field code recognized - memcpy(fadr,ptr,size); // read field data - } + if (fadr != NULL) // if field code recognized + memcpy(fadr,ptr,nMaxReadCount); // read field data + ptr += size; // jump field data } + + // Validate read values. + Limit(m_nDefaultTempo, GetModSpecifications().tempoMin, GetModSpecifications().tempoMax); + //m_nRowsPerBeat + //m_nRowsPerMeasure + LimitMax(m_nChannels, GetModSpecifications().channelsMax); + //m_nTempoMode + //m_nMixLevels + //m_dwCreatedWithVersion + //m_dwLastSavedWithVersion + //m_nSamplePreAmp + //m_nVSTiVolume + //m_nDefaultGlobalVolume); + //m_nRestartPos + //m_ModFlags + + + #undef CASE + #undef CASE_NOTXM } Modified: branches/1.17.02.53x/soundlib/Load_xm.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Load_xm.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Load_xm.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -611,54 +611,16 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwMemLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - BYTE * ptr = (BYTE *)(lpStream + dwMemPos); + bool bInterpretMptMade = false; + LPCBYTE ptr = lpStream + dwMemPos; + if(m_nInstruments) + ptr = LoadExtendedInstrumentProperties(ptr, lpStream+dwMemLength, &bInterpretMptMade); - // Seek for supported extended settings header - __int16 size = 0; - __int32 code = (*((__int32 *)ptr)); + LoadExtendedSongProperties(GetType(), ptr, lpStream, dwMemLength, &bInterpretMptMade); - // Instrument extensions - if( code == 'MPTX' && m_nInstruments ){ - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < dwMemLength ){ //Loop 'till end of file looking for inst. extensions + if(bInterpretMptMade && m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) + SetModFlag(MSF_MIDICC_BUGEMULATION, true); - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } -// -! NEW_FEATURE#0027 - - // Song extensions - if( code == 'MPTS' ) - { - LoadExtendedSongProperties(MOD_TYPE_XM, ptr, lpStream, dwMemLength); - if(m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) - SetModFlag(MSF_MIDICC_BUGEMULATION, true); - } - - - - - return TRUE; } Modified: branches/1.17.02.53x/soundlib/Sampleio.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Sampleio.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Sampleio.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -1297,28 +1297,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Compute current file pointer position - BYTE * ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -1827,28 +1807,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -2043,6 +2003,73 @@ } + +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size) +//------------------------------------------------------------------------------ +{ + if(size < 0 || (uintptr_t)(pEnd - pData) < (uintptr_t)size) + return false; + else + return true; +} + + +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size) +//------------------------------------------------------------------------------------------------------------ +{ + // get field's address in instrument's header + BYTE* fadr = GetInstrumentHeaderFieldPointer(penv, code, size); + + if(fadr && code != 'K[..') // copy field data in instrument's header + memcpy(fadr,ptr,size); // (except for keyboard mapping) + ptr += size; // jump field +} + + +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd) +//--------------------------------------------------------------------------------------------------------------- +{ + if(pEnd < pData || uintptr_t(pEnd - pData) < 2) + return; + + int16 size; + memcpy(&size, pData, sizeof(size)); // read field size + pData += sizeof(size); // jump field size + + if(IsValidSizeField(pData, pEnd, size) == false) + return; + + ReadInstrumentExtensionField(penv, pData, code, size); +} + + +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength) +//-------------------------------------------------------------------------------------------------------------- +{ + if(penv == 0 || pDataStart == 0 || nMemLength < 4) + return; + + LPCBYTE pData = pDataStart; + const LPCBYTE pEnd = pDataStart + nMemLength; + + int32 code; + memcpy(&code, pData, sizeof(code)); + + // Seek for supported extended settings header + if( code == 'MPTX' ) + { + pData += sizeof(code); // jump extension header code + + while( (uintptr_t)(pData - pDataStart) <= nMemLength - 4) + { + memcpy(&code, pData, sizeof(code)); // read field code + pData += sizeof(code); // jump field code + ReadExtendedInstrumentProperty(penv, code, pData, pEnd); + } + } +} + + /////////////////////////////////////////////////////////////////////////////////////////////////// // 8SVX Samples Modified: branches/1.17.02.53x/soundlib/Sndfile.h =================================================================== --- branches/1.17.02.53x/soundlib/Sndfile.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Sndfile.h 2009-06-12 16:25:54 UTC (rev 267) @@ -1086,8 +1086,13 @@ void WriteInstrumentPropertyForAllInstruments(__int32 code, __int16 size, FILE* f, INSTRUMENTHEADER* instruments[], UINT nInstruments); void SaveExtendedInstrumentProperties(INSTRUMENTHEADER *instruments[], UINT nInstruments, FILE* f); void SaveExtendedSongProperties(FILE* f); - void LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* startpos, const size_t seachlimit); + void LoadExtendedSongProperties(const MODTYPE modtype, LPCBYTE ptr, const LPCBYTE startpos, const size_t seachlimit, bool* pInterpretMptMade = NULL); + // Reads extended instrument properties(XM/IT/MPTM). + // If no errors occur and song extension tag is found, returns pointer to the beginning + // of the tag, else returns NULL. + LPCBYTE LoadExtendedInstrumentProperties(const LPCBYTE pStart, const LPCBYTE pEnd, bool* pInterpretMptMade = NULL); + #endif // MODPLUG_NO_FILESAVE // MOD Convert function UINT GetBestSaveFormat() const; @@ -1515,4 +1520,18 @@ #endif +// Used in instrument/song extension reading to make sure the size field is valid. +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size); + +// Read instrument property with 'code' and 'size' from 'ptr' to instrument 'penv'. +// Note: (ptr, size) pair must be valid (e.g. can read 'size' bytes from 'ptr') +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size); + +// Read instrument property with 'code' from 'pData' to instrument 'penv'. +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd); + +// Read extended instrument properties from 'pDataStart' to instrument 'penv'. +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength); + + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-09 19:59:10
|
Revision: 266 http://modplug.svn.sourceforge.net/modplug/?rev=266&view=rev Author: relabsoluness Date: 2009-06-09 19:59:04 +0000 (Tue, 09 Jun 2009) Log Message: ----------- Branch for 1.17.02.xx versions starting from 1.17.02.53. Added Paths: ----------- branches/1.17.02.53x/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-08 21:23:56
|
Revision: 265 http://modplug.svn.sourceforge.net/modplug/?rev=265&view=rev Author: relabsoluness Date: 2009-06-08 21:22:25 +0000 (Mon, 08 Jun 2009) Log Message: ----------- . General tab: Fixes channel controls that got badly broken in rev. 263. Modified Paths: -------------- trunk/OpenMPT/mptrack/View_gen.cpp Modified: trunk/OpenMPT/mptrack/View_gen.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-08 19:25:03 UTC (rev 264) +++ trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-08 21:22:25 UTC (rev 265) @@ -662,7 +662,7 @@ short int pos; LockControls(); - const UINT nLoopLimit = pModDoc->GetSoundFile()->GetNumChannels() - nChn; + const UINT nLoopLimit = min(4, pModDoc->GetSoundFile()->GetNumChannels() - nChn); for (UINT iCh=0; iCh<nLoopLimit; iCh++) { // Volume sliders This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-08 19:27:34
|
Revision: 264 http://modplug.svn.sourceforge.net/modplug/?rev=264&view=rev Author: relabsoluness Date: 2009-06-08 19:25:03 +0000 (Mon, 08 Jun 2009) Log Message: ----------- . Pattern tab: It's now possible to use the old note fade behaviour when playing notes in pattern tab(see setup->general). Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/View_pat.cpp Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-06-06 19:11:18 UTC (rev 263) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-06-08 19:25:03 UTC (rev 264) @@ -425,6 +425,9 @@ gnMidiPatternLen = GetPrivateProfileLong("MIDI Settings", "MidiImportPatLen", gnMidiPatternLen, iniFile); m_dwPatternSetup = GetPrivateProfileDWord("Pattern Editor", "PatternSetup", m_dwPatternSetup, iniFile); + if(gcsPreviousVersion != "" && MptVersion::ToNum(gcsPreviousVersion) < MAKE_VERSION_NUMERIC(1,17,02,50)) + m_dwPatternSetup |= PATTERN_NOTEFADE; + m_nRowSpacing = GetPrivateProfileDWord("Pattern Editor", "RowSpacing", 16, iniFile); m_nRowSpacing2 = GetPrivateProfileDWord("Pattern Editor", "RowSpacing2", 4, iniFile); gbLoopSong = GetPrivateProfileDWord("Pattern Editor", "LoopSong", true, iniFile); @@ -541,6 +544,7 @@ RegQueryValueEx(key, "MidiSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwMidiSetup, &dwDWORDSize); RegQueryValueEx(key, "MidiDevice", NULL, &dwREG_DWORD, (LPBYTE)&m_nMidiDevice, &dwDWORDSize); RegQueryValueEx(key, "PatternSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwPatternSetup, &dwDWORDSize); + m_dwPatternSetup |= PATTERN_NOTEFADE; // Set flag to maintain old behaviour(was changed in 1.17.02.50). RegQueryValueEx(key, "RowSpacing", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing, &dwDWORDSize); RegQueryValueEx(key, "RowSpacing2", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing2, &dwDWORDSize); RegQueryValueEx(key, "LoopSong", NULL, &dwREG_DWORD, (LPBYTE)&gbLoopSong, &dwDWORDSize); Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2009-06-06 19:11:18 UTC (rev 263) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2009-06-08 19:25:03 UTC (rev 264) @@ -206,6 +206,7 @@ #define PATTERN_OLDCTXMENUSTYLE 0x800000 #define PATTERN_SYNCMUTE 0x1000000 #define PATTERN_AUTODELAY 0x2000000 +#define PATTERN_NOTEFADE 0x4000000 // Keyboard Setup Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2009-06-06 19:11:18 UTC (rev 263) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2009-06-08 19:25:03 UTC (rev 264) @@ -601,6 +601,7 @@ OPTGEN_PATTERNCTXMENUSTYLE, OPTGEN_SYNCMUTE, OPTGEN_AUTODELAY, + OPTGEN_PATNOTEFADE, OPTGEN_MAXOPTIONS }; @@ -636,6 +637,7 @@ {"Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, {"Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"}, {"Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."}, + {"Note fade on key up", "Enable to fade/stop notes on key up in pattern tab." } }; @@ -697,6 +699,7 @@ case OPTGEN_SYNCMUTE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_SYNCMUTE); break; case OPTGEN_AUTODELAY: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY); break; + case OPTGEN_PATNOTEFADE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE); break; } m_CheckList.SetCheck(i, (bCheck) ? TRUE : FALSE); } @@ -754,6 +757,7 @@ case OPTGEN_PATTERNCTXMENUSTYLE: mask = PATTERN_OLDCTXMENUSTYLE; break; case OPTGEN_SYNCMUTE: mask = PATTERN_SYNCMUTE; break; case OPTGEN_AUTODELAY: mask = PATTERN_AUTODELAY; break; + case OPTGEN_PATNOTEFADE: mask = PATTERN_NOTEFADE; break; } if (bCheck) CMainFrame::m_dwPatternSetup |= mask; else CMainFrame::m_dwPatternSetup &= ~mask; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-06 19:11:18 UTC (rev 263) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-08 19:25:03 UTC (rev 264) @@ -3804,8 +3804,12 @@ pModDoc->NoteOff(0, TRUE, ins, m_dwCursor & 0xFFFF); } else - pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); - //pModDoc->NoteOff(note, TRUE, ins, (m_dwCursor & 0xFFFF) >> 3); + { + if(CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE) + pModDoc->NoteOff(note, TRUE, ins, GetChanFromCursor(m_dwCursor)); + else + pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); + } } //Enter note off in pattern? This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-06 19:11:22
|
Revision: 263 http://modplug.svn.sourceforge.net/modplug/?rev=263&view=rev Author: relabsoluness Date: 2009-06-06 19:11:18 +0000 (Sat, 06 Jun 2009) Log Message: ----------- + IT/MTPM: Channel settings(vol&pan) for channels after 64 will now be saved in the file. . XM/IT/MPTM: Fixed a bug in reading an extension. This broke the extension search after reading that entry, although the affected entry has been the last extension in the write order. ? Minor tweaks. Modified Paths: -------------- trunk/OpenMPT/mptrack/View_gen.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/View_gen.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-06 18:49:52 UTC (rev 262) +++ trunk/OpenMPT/mptrack/View_gen.cpp 2009-06-06 19:11:18 UTC (rev 263) @@ -656,13 +656,14 @@ pModDoc = GetDocument(); nChn = m_nActiveTab * 4; - if ((pModDoc) && (!IsLocked()) && (nChn < 64)) + if ((pModDoc) && (!IsLocked()) && (nChn < MAX_BASECHANNELS)) { BOOL bUpdate = FALSE; short int pos; LockControls(); - for (UINT iCh=0; iCh<4; iCh++) + const UINT nLoopLimit = pModDoc->GetSoundFile()->GetNumChannels() - nChn; + for (UINT iCh=0; iCh<nLoopLimit; iCh++) { // Volume sliders pos = (short int)m_sbVolume[iCh].GetPos(); Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-06 18:49:52 UTC (rev 262) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-06-06 19:11:18 UTC (rev 263) @@ -917,8 +917,8 @@ } // -! NEW_FEATURE#0023 -BOOL CSoundFile::ReadIT(const BYTE *lpStream, const DWORD dwMemLength) -//-------------------------------------------------------------- +BOOL CSoundFile::ReadIT(const LPCBYTE lpStream, const DWORD dwMemLength) +//---------------------------------------------------------------------- { ITFILEHEADER *pifh = (ITFILEHEADER *)lpStream; @@ -3595,6 +3595,23 @@ fwrite(&size, 1, sizeof(__int16), f); fwrite(&m_nChannels, 1, size, f); + if(TypeIsIT_MPT() && m_nChannels > 64) //IT header has room only for 64 channels. Save the + { //settings that do not fit to the header here as an extension. + code = 'ChnS'; + fwrite(&code, 1, sizeof(__int32), f); + size = (m_nChannels - 64)*2; + fwrite(&size, 1, sizeof(__int16), f); + for(UINT ich = 64; ich < m_nChannels; ich++) + { + BYTE panvol[2]; + panvol[0] = ChnSettings[ich].nPan >> 2; + if (ChnSettings[ich].dwFlags & CHN_SURROUND) panvol[0] = 100; + if (ChnSettings[ich].dwFlags & CHN_MUTE) panvol[0] |= 0x80; + panvol[1] = ChnSettings[ich].nVolume; + fwrite(&panvol, sizeof(panvol), 1, f); + } + } + code = 'TM..'; //write m_nTempoMode fwrite(&code, 1, sizeof(__int32), f); size = sizeof(m_nTempoMode); @@ -3675,13 +3692,13 @@ } -void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* lpStream, const size_t searchlimit) +void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const LPCBYTE lpStream, const size_t searchlimit) //-------------------------------------------------- { int32 code = 0; int16 size = 0; ptr += sizeof(int32); // jump extension header code - while( (DWORD)(ptr + 6 - lpStream) <= searchlimit ) //Loop until given limit. + while( (DWORD)((ptr + 6) - lpStream) <= searchlimit ) //Loop until given limit. { code = (*((__int32 *)ptr)); // read field code ptr += sizeof(__int32); // jump field code @@ -3708,15 +3725,27 @@ if(DWORD(ptr - lpStream + DWORD(size)) > searchlimit) MessageBox(NULL, "Error: Bad MIMA datasizefield", NULL, MB_ICONERROR); else + GetMIDIMapper().Unserialize(ptr, size); + break; + case 'ChnS': + if( ((ptr - lpStream) + DWORD(size) <= searchlimit) && (size <= 63*2) && (size % 2 == 0) ) { - GetMIDIMapper().Unserialize(ptr, size); - ptr += size; + const BYTE* pData = ptr; + for(__int16 i = 0; i<size/2; i++, pData += 2) if(pData[0] != 0xFF) + { + ChnSettings[i+64].nVolume = pData[1]; + ChnSettings[i+64].nPan = 128; + if (pData[0] & 0x80) ChnSettings[i+64].dwFlags |= CHN_MUTE; + const UINT n = pData[0] & 0x7F; + if (n <= 64) ChnSettings[i+64].nPan = n << 2; + if (n == 100) ChnSettings[i+64].dwFlags |= CHN_SURROUND; + } } break; } - if (fadr != NULL && ptr - lpStream + DWORD(size) <= searchlimit) { // if field code recognized + if (fadr != NULL && (ptr - lpStream) + DWORD(size) <= searchlimit) { // if field code recognized memcpy(fadr,ptr,size); // read field data } ptr += size; // jump field data Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-06 18:49:52 UTC (rev 262) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-06-06 19:11:18 UTC (rev 263) @@ -136,6 +136,7 @@ [EXT] means external (not related) to INSTRUMENTHEADER content C... [EXT] nChannels +ChnS [EXT] IT/MPTM: Channel settings for channels 65-127 if needed (doesn't fit to IT header). CS.. nCutSwing CWV. [EXT] dwCreatedWithVersion DCT. nDCT; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-06 18:49:54
|
Revision: 262 http://modplug.svn.sourceforge.net/modplug/?rev=262&view=rev Author: relabsoluness Date: 2009-06-06 18:49:52 +0000 (Sat, 06 Jun 2009) Log Message: ----------- Pattern tab: + Channel reset(stops note, sets initial chn settings). Available from channel header context menu and new key binding. . Fixed wrong interpretations of "Old style pattern context menu"-option. / Channel control context menu will now be visible only in channel header context. Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/KeyConfigDlg.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/resource.h Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-06 18:49:52 UTC (rev 262) @@ -2299,6 +2299,11 @@ commands[kcSampleSignUnsign].isHidden = false; commands[kcSampleSignUnsign].isDummy = false; + commands[kcChannelReset].UID = 1786; + commands[kcChannelReset].isHidden = false; + commands[kcChannelReset].isDummy = false; + commands[kcChannelReset].Message = "Reset channel"; + #ifdef _DEBUG for (int i=0; i<kcNumCommands; i++) { if (commands[i].UID != 0) { // ignore unset UIDs Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/CommandSet.h 2009-06-06 18:49:52 UTC (rev 262) @@ -230,6 +230,7 @@ kcToggleChanMuteOnPatTransition, kcUnmuteAllChnOnPatTransition, kcSoloChnOnPatTransition, + kcChannelReset, kcCopyAndLoseSelection, kcTransposeUp, kcTransposeDown, Modified: trunk/OpenMPT/mptrack/KeyConfigDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2009-06-06 18:49:52 UTC (rev 262) @@ -229,9 +229,9 @@ for (int c=kcClearRow; c<=kcInsertAllRows; c++) newCat->commands.Add(c); newCat->separators.Add(kcInsertAllRows); //-------------------------------------- - for (int c=kcChannelMute; c<=kcSoloChnOnPatTransition; c++) + for (int c=kcChannelMute; c<=kcChannelReset; c++) newCat->commands.Add(c); - newCat->separators.Add(kcSoloChnOnPatTransition); //-------------------------------------- + newCat->separators.Add(kcChannelReset); //-------------------------------------- for (int c=kcTransposeUp; c<=kcTransposeOctDown; c++) newCat->commands.Add(c); newCat->separators.Add(kcTransposeOctDown); //-------------------------------------- Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-06 18:49:52 UTC (rev 262) @@ -66,6 +66,7 @@ ON_COMMAND(ID_EDIT_SPLITRECSELECT, OnSplitRecordSelect) // -! NEW_FEATURE#0012 ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_COMMAND(ID_PATTERN_CHNRESET, OnChannelReset) ON_COMMAND(ID_PATTERN_MUTE, OnMuteFromClick) //rewbs.customKeys ON_COMMAND(ID_PATTERN_SOLO, OnSoloFromClick) //rewbs.customKeys ON_COMMAND(ID_PATTERN_TRANSITIONMUTE, OnTogglePendingMuteFromClick) @@ -1218,8 +1219,8 @@ //------ Standard Menu ---------- : else if ((pt.x >= m_szHeader.cx) && (pt.y > m_szHeader.cy)) { - if (BuildSoloMuteCtxMenu(hMenu, ih, nChn, pSndFile)) - AppendMenu(hMenu, MF_SEPARATOR, 0, ""); + /*if (BuildSoloMuteCtxMenu(hMenu, ih, nChn, pSndFile)) + AppendMenu(hMenu, MF_SEPARATOR, 0, "");*/ if (BuildSelectionCtxMenu(hMenu, ih)) AppendMenu(hMenu, MF_SEPARATOR, 0, ""); if (BuildEditCtxMenu(hMenu, ih, pModDoc)) @@ -1376,8 +1377,23 @@ } } +void CViewPattern::OnChannelReset() +//--------------------------------- +{ + const CHANNELINDEX nChn = GetChanFromCursor(m_nMenuParam); + CModDoc *pModDoc = GetDocument(); + CSoundFile* pSndFile; + if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) return; + const bool bIsMuted = pModDoc->IsChannelMuted(nChn); + if(!bIsMuted) pModDoc->MuteChannel(nChn, true); + pSndFile->ResetChannelState(nChn, CHNRESET_TOTAL); + if(!bIsMuted) pModDoc->MuteChannel(nChn, false); +} + + void CViewPattern::OnMuteFromClick() +//---------------------------------- { OnMuteChannel(false); } @@ -3328,6 +3344,7 @@ case kcChannelUnmuteAll: OnUnmuteAll(); return wParam; case kcToggleChanMuteOnPatTransition: TogglePendingMute(GetChanFromCursor(m_dwCursor)); return wParam; case kcUnmuteAllChnOnPatTransition: OnPendingUnmuteAllChnFromClick(); return wParam; + case kcChannelReset: OnChannelReset(); return wParam; case kcTimeAtRow: OnShowTimeAtRow(); return wParam; case kcSoloChnOnPatTransition: PendingSoloChn(GetCurrentChannel()); return wParam; case kcTransposeUp: OnTransposeUp(); return wParam; @@ -4486,6 +4503,8 @@ AppendMenu(hMenu, MF_STRING, ID_PATTERN_TRANSITION_UNMUTEALL, "On transition: Unmute all\t" + ih->GetKeyTextFromCommand(kcUnmuteAllChnOnPatTransition)); AppendMenu(hMenu, MF_STRING, ID_PATTERN_TRANSITIONSOLO, "On transition: Solo\t" + ih->GetKeyTextFromCommand(kcSoloChnOnPatTransition)); + + AppendMenu(hMenu, MF_STRING, ID_PATTERN_CHNRESET, "Reset Channel\t" + ih->GetKeyTextFromCommand(kcChannelReset)); return true; } @@ -4518,11 +4537,8 @@ bool CViewPattern::BuildMiscCtxMenu(HMENU hMenu, CInputHandler* ih) //----------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup & PATTERN_OLDCTXMENUSTYLE) return false; - AppendMenu(hMenu, MF_STRING, ID_SHOWTIMEATROW, "Show row play time\t" + ih->GetKeyTextFromCommand(kcTimeAtRow)); return true; - } bool CViewPattern::BuildSelectionCtxMenu(HMENU hMenu, CInputHandler* ih) @@ -4701,9 +4717,6 @@ bool CViewPattern::BuildChannelControlCtxMenu(HMENU hMenu) //-------------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup&PATTERN_OLDCTXMENUSTYLE) return false; - //Not doing the menuentries if opted to use old style menu style. - AppendMenu(hMenu, MF_SEPARATOR, 0, ""); AppendMenu(hMenu, MF_STRING, ID_PATTERN_DUPLICATECHANNEL, "Duplicate this channel"); @@ -4729,11 +4742,8 @@ CArray<UINT, UINT> validChans; DWORD greyed = (ListChansWhereColSelected(INST_COLUMN, validChans)>0)?FALSE:MF_GRAYED; - if (CMainFrame::m_dwPatternSetup&PATTERN_OLDCTXMENUSTYLE && (!greyed)) { - // Case: User has opted to use old style menu style. - AppendMenu(hMenu, MF_STRING, ID_PATTERN_SETINSTRUMENT, "Change Instrument\t" + ih->GetKeyTextFromCommand(kcPatternSetInstrument)); - } - else { + if (!greyed || !(CMainFrame::m_dwPatternSetup&PATTERN_OLDCTXMENUSTYLE)) + { // Create the new menu and add it to the existing menu. HMENU instrumentChangeMenu = ::CreatePopupMenu(); AppendMenu(hMenu, MF_POPUP|greyed, (UINT)instrumentChangeMenu, "Change Instrument\t" + ih->GetKeyTextFromCommand(kcPatternSetInstrument)); @@ -4741,32 +4751,39 @@ if(pSndFile == NULL) return false; + if(!greyed) + { + if (pSndFile->m_nInstruments) + { + for (UINT i=1; i<=pSndFile->m_nInstruments; i++) + { + if (pSndFile->Headers[i] == NULL) + continue; - if (pSndFile->m_nInstruments) { - for (UINT i=1; i<=pSndFile->m_nInstruments; i++) { - if (pSndFile->Headers[i] == NULL) { - continue; - } CString instString = pSndFile->GetPatternViewInstrumentName(i, true); if(instString.GetLength() > 0) AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT+i, pSndFile->GetPatternViewInstrumentName(i)); //Adding the entry to the list only if it has some name, since if the name is empty, //it likely is some non-used instrument. } - } else { + } + else + { CHAR s[256]; UINT nmax = pSndFile->m_nSamples; while ((nmax > 1) && (pSndFile->Ins[nmax].pSample == NULL) && (!pSndFile->m_szNames[nmax][0])) nmax--; - for (UINT i=1; i<=nmax; i++) if ((pSndFile->m_szNames[i][0]) || (pSndFile->Ins[i].pSample)) { + for (UINT i=1; i<=nmax; i++) if ((pSndFile->m_szNames[i][0]) || (pSndFile->Ins[i].pSample)) + { wsprintf(s, "%02d: %s", i, pSndFile->m_szNames[i]); AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT+i, s); } } - //Add options to remove instrument from selection. - AppendMenu(instrumentChangeMenu, MF_SEPARATOR, 0, 0); - AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT, "Remove instrument"); - AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT+GetCurrentInstrument(), "Set to current instrument"); + //Add options to remove instrument from selection. + AppendMenu(instrumentChangeMenu, MF_SEPARATOR, 0, 0); + AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT, "Remove instrument"); + AppendMenu(instrumentChangeMenu, MF_STRING, ID_CHANGE_INSTRUMENT+GetCurrentInstrument(), "Set to current instrument"); + } return true; } return false; Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/View_pat.h 2009-06-06 18:49:52 UTC (rev 262) @@ -228,6 +228,7 @@ afx_msg void OnEditGoto(); afx_msg void OnEditFindNext(); afx_msg void OnEditUndo(); + afx_msg void OnChannelReset(); afx_msg void OnMuteFromClick(); //rewbs.customKeys afx_msg void OnSoloFromClick(); //rewbs.customKeys afx_msg void OnTogglePendingMuteFromClick(); //rewbs.customKeys Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-06-06 18:40:29 UTC (rev 261) +++ trunk/OpenMPT/mptrack/resource.h 2009-06-06 18:49:52 UTC (rev 262) @@ -961,6 +961,7 @@ #define ID_PATTERN_PLAYNOLOOP 32901 #define ID_PATTERN_OPEN_RANDOMIZER 32905 #define ID_PATTERN_INTERPOLATE_NOTE 32906 +#define ID_PATTERN_CHNRESET 32907 #define ID_PRESET_LOAD 32915 #define ID_PRESET_SAVE 32916 #define ID_PRESET_RANDOM 32917 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-06-06 18:40:37
|
Revision: 261 http://modplug.svn.sourceforge.net/modplug/?rev=261&view=rev Author: relabsoluness Date: 2009-06-06 18:40:29 +0000 (Sat, 06 Jun 2009) Log Message: ----------- / VST: Changed host IDs and a couple of related return values. If compatibility problems occur, old IDs can be set with ini-settings. ? Misc: Modifications to remove some compiler warnings(in mptrack.cpp). ? Misc: Changed version to 1.17.03.01. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/version.h Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-05-30 21:38:42 UTC (rev 260) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-06 18:40:29 UTC (rev 261) @@ -220,6 +220,7 @@ static void ShowChangesDialog() //----------------------------- { + /* const char* const firstOpenMessage = "OpenMPT development build " MPT_VERSION_STR ".\n\n" "Some notable changes since version 1.17.02.48:\n\n" " [New] Name filter in plugin selection dialog.\n" @@ -236,6 +237,7 @@ " For more detailed list of changes, see history.txt."; CMainFrame::GetMainFrame()->MessageBox(firstOpenMessage, "OpenMPT v." MPT_VERSION_STR, MB_ICONINFORMATION); + */ } @@ -1551,7 +1553,7 @@ if (t > 256) m_bFirst = FALSE; - dir = (t/256) % 2; //change dir every 256 t + dir = ((t/256) % 2 != 0); //change dir every 256 t t = t%256; if (!dir) t = (256-t); @@ -2209,9 +2211,9 @@ UINT m = (m_Dib.bmiColors[i].rgbRed >> 2) + (m_Dib.bmiColors[i].rgbGreen >> 1) + (m_Dib.bmiColors[i].rgbBlue >> 2); - m_Dib.bmiColors[i|0x80].rgbRed = (m + r)>>1; - m_Dib.bmiColors[i|0x80].rgbGreen = (m + g)>>1; - m_Dib.bmiColors[i|0x80].rgbBlue = (m + b)>>1; + m_Dib.bmiColors[i|0x80].rgbRed = static_cast<BYTE>((m + r)>>1); + m_Dib.bmiColors[i|0x80].rgbGreen = static_cast<BYTE>((m + g)>>1); + m_Dib.bmiColors[i|0x80].rgbBlue = static_cast<BYTE>((m + b)>>1); } } @@ -2921,6 +2923,17 @@ m_pPluginManager = new CVstPluginManager; if (!m_pPluginManager) return FALSE; nPlugins = GetPrivateProfileInt("VST Plugins", "NumPlugins", 0, m_szConfigFileName); + + #ifndef NO_VST + char buffer[64]; + GetPrivateProfileString("VST Plugins", "HostProductString", CVstPluginManager::s_szHostProductString, buffer, ARRAYELEMCOUNT(buffer), m_szConfigFileName); + strcpy(CVstPluginManager::s_szHostProductString, buffer); + GetPrivateProfileString("VST Plugins", "HostVendorString", CVstPluginManager::s_szHostVendorString, buffer, ARRAYELEMCOUNT(buffer), m_szConfigFileName); + strcpy(CVstPluginManager::s_szHostVendorString, buffer); + CVstPluginManager::s_nHostVendorVersion = GetPrivateProfileInt("VST Plugins", "HostVendorVersion", CVstPluginManager::s_nHostVendorVersion, m_szConfigFileName); + #endif + + CString nonFoundPlugs; for (LONG iPlug=0; iPlug<nPlugins; iPlug++) { @@ -2962,6 +2975,14 @@ } wsprintf(s, "%d", iPlug); WritePrivateProfileString("VST Plugins", "NumPlugins", s, m_szConfigFileName); + + #ifndef NO_VST + WritePrivateProfileString("VST Plugins", "HostProductString", CVstPluginManager::s_szHostProductString, m_szConfigFileName); + WritePrivateProfileString("VST Plugins", "HostVendorString", CVstPluginManager::s_szHostVendorString, m_szConfigFileName); + CMainFrame::WritePrivateProfileLong("VST Plugins", "HostVendorVersion", CVstPluginManager::s_nHostVendorVersion, m_szConfigFileName); + #endif + + if (m_pPluginManager) { delete m_pPluginManager; Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2009-05-30 21:38:42 UTC (rev 260) +++ trunk/OpenMPT/mptrack/Mptrack.h 2009-06-06 18:40:29 UTC (rev 261) @@ -344,7 +344,7 @@ MODPLUGFASTDIB m_Dib; UINT m_nTextColor, m_nBkColor; LPMODPLUGDIB m_pTextDib; - BOOL m_nBlendOffset; + BYTE m_nBlendOffset; BYTE m_n4BitPalette[16]; public: @@ -359,7 +359,7 @@ void SetColor(UINT nIndex, COLORREF cr); void SetAllColors(UINT nBaseIndex, UINT nColors, COLORREF *pcr); void TextBlt(int x, int y, int cx, int cy, int srcx, int srcy, LPMODPLUGDIB lpdib=NULL); - void SetBlendMode(UINT nBlendOfs) { m_nBlendOffset = nBlendOfs; } + void SetBlendMode(BYTE nBlendOfs) { m_nBlendOffset = nBlendOfs; } void SetBlendColor(COLORREF cr); }; Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2009-05-30 21:38:42 UTC (rev 260) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2009-06-06 18:40:29 UTC (rev 261) @@ -13,9 +13,14 @@ #include "VstEditor.h" //rewbs.defaultPlugGUI #include "defaultvsteditor.h" //rewbs.defaultPlugGUI #include "midi.h" +#include "version.h" #ifndef NO_VST +char CVstPluginManager::s_szHostProductString[64] = "OpenMPT"; +char CVstPluginManager::s_szHostVendorString[64] = "OpenMPT project"; +long CVstPluginManager::s_nHostVendorVersion = MptVersion::num; + //#define VST_LOG //#define ENABLE_BUZZ #define DMO_LOG @@ -861,16 +866,19 @@ case audioMasterGetOutputSpeakerArrangement: Log("VST plugin to host: Get Output Speaker Arrangement\n"); break; - case audioMasterGetVendorString: // Prentending to be Steinberg for compat. - strcpy((char*)ptr,"Steinberg"); -// strcpy((char*)ptr,"OpenMPT"); - return 0; - case audioMasterGetVendorVersion: // Prentending to be Cubase VST 7. :) - return 7000; - case audioMasterGetProductString: // Prentending to be Cubase VST for compat. - strcpy((char*)ptr,"Cubase VST"); -// strcpy((char*)ptr,"OpenMPT"); - return 0; + case audioMasterGetVendorString: + strcpy((char*)ptr, s_szHostVendorString); + //strcpy((char*)ptr,"Steinberg"); + //return 0; + return true; + case audioMasterGetVendorVersion: + return s_nHostVendorVersion; + //return 7000; + case audioMasterGetProductString: + strcpy((char*)ptr, s_szHostProductString); + //strcpy((char*)ptr,"Cubase VST"); + //return 0; + return true; case audioMasterVendorSpecific: return 0; // void* in <ptr>, format not defined yet Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2009-05-30 21:38:42 UTC (rev 260) +++ trunk/OpenMPT/mptrack/Vstplug.h 2009-06-06 18:40:29 UTC (rev 261) @@ -249,6 +249,12 @@ static long VSTCALLBACK MasterCallBack(AEffect *effect, long opcode, long index, long value, void *ptr, float opt); static BOOL __cdecl CreateMixPluginProc(PSNDMIXPLUGIN, CSoundFile*); VstTimeInfo timeInfo; //rewbs.VSTcompliance + +public: + static char s_szHostProductString[64]; + static char s_szHostVendorString[64]; + static long s_nHostVendorVersion; + #else // NO_VST public: PVSTPLUGINLIB AddPlugin(LPCSTR, BOOL =TRUE, const bool = false, CString* const = 0) {return 0;} Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2009-05-30 21:38:42 UTC (rev 260) +++ trunk/OpenMPT/mptrack/version.h 2009-06-06 18:40:29 UTC (rev 261) @@ -14,8 +14,8 @@ //Version definitions. The only thing that needs to be changed when changing version number. #define VER_MAJORMAJOR 1 #define VER_MAJOR 17 -#define VER_MINOR 02 -#define VER_MINORMINOR 53 +#define VER_MINOR 03 +#define VER_MINORMINOR 01 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-05-30 21:38:44
|
Revision: 260 http://modplug.svn.sourceforge.net/modplug/?rev=260&view=rev Author: relabsoluness Date: 2009-05-30 21:38:42 +0000 (Sat, 30 May 2009) Log Message: ----------- Tag for 1.17.02.53 Added Paths: ----------- tags/1.17.02.53/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |