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
(191) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
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. |
From: <rel...@us...> - 2009-05-30 21:22:03
|
Revision: 259 http://modplug.svn.sourceforge.net/modplug/?rev=259&view=rev Author: relabsoluness Date: 2009-05-30 21:21:35 +0000 (Sat, 30 May 2009) Log Message: ----------- 1.17.02.53 Modified Paths: -------------- trunk/OpenMPT/mptrack/bin/mptrack.exe trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/packageTemplate/SoundTouch/README.html trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb Added Paths: ----------- trunk/OpenMPT/mptrack/bin/OpenMPT_SoundTouch.dll Added: trunk/OpenMPT/mptrack/bin/OpenMPT_SoundTouch.dll =================================================================== (Binary files differ) Property changes on: trunk/OpenMPT/mptrack/bin/OpenMPT_SoundTouch.dll ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/OpenMPT/mptrack/bin/mptrack.exe =================================================================== (Binary files differ) Modified: trunk/OpenMPT/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2009-05-17 14:54:05 UTC (rev 258) +++ trunk/OpenMPT/packageTemplate/History.txt 2009-05-30 21:21:35 UTC (rev 259) @@ -8,15 +8,217 @@ ?: other (tx XYZ): thanks to XYZ for telling us about the bug + +v1.17.02.53 (May 2009, revision 259) +------------------------------------ + +General: + + <jojo> Can now import MO3 files using external library. (rev. 248) + + . <jojo> Song Cleanup: Sample cleanup should no longer remove data after sustain loop end point. (rev. 248) + . <jojo> Misc: When adding channels from song properties, new channels are now initialized properly (bug 1814). (rev. 236) + . <jojo> BPM approximation showed wrong rows per beat in some cases (bug 2532) (rev. 231) + . <jojo> Disabled special handling of '&'-character when drawing texts to various components where the special handling should not take place. (http://lpchip.com/modplug/viewtopic.php?t=1962) (rev. 229) + . <re> File opening: Added a couple of return value checks to reduce the change of crash when opening lots of files (bug 2546) (rev. 239) + + / <jojo> Menu: Goto dialog can now be opened from Edit-menu. (rev. 246) + / <re> Pattern cleanup: Clearing sequence after first '---' item is now optional. (rev. 239) + / <re> When passing MIDI to plug, documents will now be set modified since MIDI data may change parameters. (rev. 243) + +General tab: + / <jojo> General tab: VST volume slider is now disabled for S3M. (rev. 246) + / <jojo> General tab: Initial channel volume controls are now enabled only for IT and MPTM. (rev. 246) + +Pattern tab: + + <jojo> Added descriptions of SBx, S3x, S4x and S5x command parameters to note properties dialog. (rev. 251) + + <jojo> Descriptions to retrigger note command parameters in note properties dialog. (rev. 248) + + <jojo> Ability to start playback with incoming MIDI note (see setup->MIDI) (rev. 246) + + <jojo> Duplicate channel (see channel header context menu). (246) + + <re> MIDI controllers can now be used to input smooth MIDI macro commands to pattern (setup->MIDI). (rev. 240) + + . <re> Undo should now work with chords. (rev. 244) + . <re> When playing with MIDI keyboard, plugins got a constant note velocity, not the actual velocity (bug 2754) (rev. 239) + . <re> Undo fixes (didn't properly handle playback positions/multichannel record, set redundant undo points)(rev 243) + . <re> Param record in plugs GUI wrote commands even when pattern record was off. (rev 243) + . <re> Fixed chord detection when row spacing was enabled. (rev 243) + . <re> Fix to displaying wrong pattern name when using more than 255 patterns (http://lpchip.com/modplug/viewtopic.php?t=2344) (rev. 212) + . <re> Accidental moving when selecting order in margins shouldn't happen anymore. (rev 225) + . <re> Fix to possible crash when using undo after pattern resize (bug introduced in rev. 168) + + / <jojo> When applying "change instrument", won't add instrument number to note off/cut if the note doesn't have instrument already. (rev. 248) + / <re> Default orderlist margin value can now be controlled with "DefaultSequenceMargins" ini-settings under "Pattern Editor" context. (rev 225) + / <jojo & re> Sequence view: Sequence scrolling won't no longer be cut on first '---' item on IT/MPTM/XM. (rev. 237) + / <re> Pattern: The keyboard split 'feature' when entering chords is removed (bug 2790). (rev. 244) + +Sample tab: + + <jojo> Can now normalize sample selections. (rev. 254) + + <jojo> Can now optionally normalize all samples instead of just one (click normalize with shift down) (rev. 249) + + <jojo & re> Status bar now displays offset value at given sample point. (rev. 232) + + <jojo & re> Sample amplify now accepts negative values(inverts sample phase) (request 2219) (rev. 234) + + <jojo & re> Signed/unsigned sample conversion. (rev. 235) + + <re> Added button for phase invert to toolbar. (rev. 235) + + <jojo> Ability to save sample as raw. (rev. 236) + + . <re> Fix to zoom-related crash when loading samples in sample tab. Occurs usually with lengthy samples. (rev. 211) + . <jojo> Playing sample selection didn't work properly in all cases (bug 1700). (rev. 231) + . <jojo> Setting loop points could affect playing of sample even if loop was disabled (bug 1874) (rev. 231) + + / <jojo> Notes from MIDI should now be played like notes from keyboard. (rev. 246) + / <jojo> Play sample button now stops previous note even if mod is playing (bug 1366) (rev. 231) + / <jojo> Sustain loop will now be enabled when setting it to sample selection. (rev. 231) + / <jojo> Sample editing: If possible, use loop points as trim limits if there's no selection chosen. (rev. 230) + / <re> Time stretching is now implemented with SoundTouch library. (rev. 228) + / <re> Disabled pitchshifting/time stretching of 8-bit samples(didn't seem to work). (rev. 228) + +Instrument tab: + . <jojo> Envelope view: Middle line will now be drawn in panning and pitch/filter envelopes even if row guidelines are enabled. (rev. 254) + + / <jojo> Instrument tab: Sample map can now map "No sample". (rev. 236) + / <re> Changed default instrument plug volume command handling from Dry/Wet to none. Also added ini-setting with which one can set the default value used for new instruments. Ini setting is "DefaultPlugVolumeHandling" in [Misc], possible values are 0,1,2. (rev. 238) + +MPTM: + . <re> Pattern cleanup: In some cases sequence wasn't cleaned properly for mptm. (rev. 239) + / <re> Changed pattern/order limit for MPTm from 65000 to 4000. (rev. 212) + Instrument tuning: + + <re> Added letter 'b' to drawable letters. (rev. 217) + . <re> Creating 'group geometric' was broken (perhaps since v. 1.17.02.49) (rev. 252) + . <re> Loading certain old tuning objects didn't work. (rev. 238) + / <re> Notes should now be drawn more clearly when using custom tunings. (rev. 217) + +IT: + . <jojo & re> Macro config should now be loaded correctly also when loading IT files not made with MPT. (rev. 257) + . <jojo & re> Playback fix to vibrato with ramp down waveform in IT compatibility play. (rev. 257) + . <re> When file was saved with compatibility export, the last order was not shown in Impulse Tracker. (rev. 257) + +XM: + . <jojo> Fix to handling a special case of Bxx and Dxx (bug 2769) (rev 241) + +S3M: + . <re> S3M saving: Sequence of length 241-255 should now be cut to length 240 instead of ~16. (rev. 239) + / <re> When loading S3M files which contain Zxx-effects, user is now asked how to process them. (bug 2166) (rev. 233) + / <re> S3M saving: Saved sequence is no longer cut on first '---' item. (rev. 239) + +MOD: + . <jojo & re> Fixes to MOD saving: it should now be possible to create ProTracker compatible MOD files with compatibility export. (rev. 256) + +Package template: + / <jojo> PackageTemplate: Update to DE_jojo-keymap + +Misc: + . <from libmodplug> Fix to faulty portamento handling on loading AMF. + . <various> Lots of smaller bug fixes. + + + +v1.17.02.52 (14 Apr 2008, revision 210) +--------------------------------------- + . <re> Shouldn't need winhttp anymore(at least now that updatecheck is disabled). Dependency caused problems in Win98. + . <re> Fix to faulty plug file existence check(introduced in 1.17.02.51)(http://lpchip.com/modplug/viewtopic.php?t=2255) + . <re> Sound card-options buffer length value validation. + . <re> In .51, muted channels were ignored completely in MIDI export. Now pattern effects are processed in muted channels. + . <re> IT style-playback fix + + +v1.17.02.51 (29 Mar 2008, revision 208) +--------------------------------------- + . <re> Fix to crash when loading VST with long(>32) param name. + . <ma & re> Fix to possible memory corruption problem on handling VST with more than 30 outputs. + - VST with more than 32 outputs might still be handled poorly. + . <re> Fix to possible crash when browsing modules in treeview(http://lpchip.com/modplug/viewtopic.php?t=2222). + . <re> Fix to severe memory leak in the same section as above. + . <re> Fix to mptm not showing in tree view file browser. + . <re> Fix to MIDI drum export (http://lpchip.com/modplug/viewtopic.php?t=2024) + . <re> Fix to possible crash on MIDI export if exporting module with more than 64 channels. + / <re> MIDI export won't anymore export muted channels(http://lpchip.com/modplug/viewtopic.php?t=2017) + . <re> When converting MOD->S3M/IT/MPTM, finetune setting was ignored (http://lpchip.com/modplug/viewtopic.php?t=1706) + . <re> IT compatibility: Fix to not resetting envelopes on new instrument (http://lpchip.com/modplug/viewtopic.php?t=1869) + . <re> IT compatibility: Fix to bidi loop resetting (http://lpchip.com/modplug/viewtopic.php?t=788) + . <re> IT compatibility: Fix to note trigger after note cut(http://lpchip.com/modplug/viewtopic.php?t=2080) + . <re> Mixmode-tooltip in general tab was in some cases shown on unrelated controls (http://lpchip.com/modplug/viewtopic.php?t=2176) + . <re> Pitch/tempo lock was lost on first instrument when opening instrument tab for the first time. (http://lpchip.com/modplug/viewtopic.php?t=1823) + . <re> Verifying buffer length-setting read from INI-file to prevent the impression that it can be set < 10 (http://lpchip.com/modplug/viewtopic.php?t=992) + . <re> Pattern effectdata paste was broken for MOD (probably since .46) (http://lpchip.com/modplug/viewtopic.php?t=1938) + / <re> When loading plug information at startup, checking whether the plug files exist. (http://lpchip.com/modplug/viewtopic.php?t=1367) + . <re> Continuous pattern navigation fixes(http://lpchip.com/modplug/viewtopic.php?t=1960, http://lpchip.com/modplug/viewtopic.php?t=1959) + . <re> Keyboard split related fix (http://lpchip.com/modplug/viewtopic.php?t=1887) + . <re> Releasenode information should now be included when copying instrument envelopes (http://lpchip.com/modplug/viewtopic.php?t=1780) + . <ma> Potential memory corruption bug when loading VSTs + + - <re> Removed buggy rearrange samples (http://lpchip.com/modplug/viewtopic.php?t=2148) + . <re> Fixed MIDI mapping not checking MIDI event, which could cause events like pitch bend to trigger some mapping item. + . <re> Extended song/instrument properties were not always loaded correctly for IT (bug introduced in 1.17.02.50)(http://lpchip.com/modplug/viewtopic.php?p=16335) + . <re> Fix for faulty tabs when switching between modtypes with and without instrumenttab. (http://lpchip.com/modplug/viewtopic.php?t=1614) + . <re> Fix for possible crash on save/load when using more than 64 channels with MPTM. + / <re> Modified flag is not set when sliding tempo/global volume slider for MOD file. + / <re> When setting instrument pan, checking whether instrument samples have set pan enabled and optionally disabling them. + + <re> Unmute all(on transition) shortcutkeys should now work in orderlist context. + / <re> Disabled Set Pan in sample tab for XM. + + <re> Half/double pattern rownumber buttons to pattern properties dialog. + / <re> Show prev/next pattern now shows pattern over +++ orderlist items. + + <re> Channel status in status bar now show channel volume info. + / <re> Disabled setting channel pan for MOD/XM in general view. + + +v1.17.02.50 (26 Jan 2008, revision 198) +--------------------------------------- + / <re> MIDICC bug related compatibility improvement for loading old IT/MPTm files. + + <re> MIDI controller mapping to plug params. + + <re> Ability to take MIDI volume into account when playing notes. + + <re> Ability to pass MIDI to plug. + + <re> Ability to start/continue/stop play with certain MIDI messages (untested) + + <re> Ability to choose how volume commands behave for plugs. + . <re> Fixed sending wrong MIDI message in ::MidiCC. + + + <re> Keyshortcuts for preset navigation jumps in VST editor. + . <re> Default VST editor preset field name validation in the menubar. + + + <re> Added ability to edit various flags in song properties. + . <re> Fix for pattern duplicate for small patterns (http://lpchip.com/modplug/viewtopic.php?t=1747) + . <re> Fixed song properties-menu entry in mainframe(was grayed and didn't show keyshortcut) + . <re> Fixed crash with certain toolbar related ini-settings (http://lpchip.com/modplug/viewtopic.php?t=2033) + . <re> Further fixes to prevent unnotified overwriting of file. + / <re> .bak-files won't now be shown with "All modules" filter when loading modules. + . <re> Show row playtime didn't on certain cases work on first pattern row (http://lpchip.com/modplug/viewtopic.php?t=2044) + . <re> Fix to faulty play with certain instruments without notes in IT compatible playmode (http://lpchip.com/modplug/viewtopic.php?t=2080) + . <re> Pattern number box didn't open pattern properties when using MPTm. (http://lpchip.com/modplug/viewtopic.php?t=2073) + . <re> Fixed wrong MIDI CC names in macro editor. + ./ <re> Setting volume to 0(v00) in pattern didn't necessarily set volume to 0 when using volume random variation for instrument. All other random variation behaviors are changed as well; now the 'swing' is applied directly to channel values instead of using swing addition, and by default the swing effect is reset on new note. (http://lpchip.com/modplug/viewtopic.php?t=2074) + + / <re> MPTm made with this version will be recognized as IT in earlier versions. + / <re> Various validity checks for read data in ITP loading. + + +v1.17.02.49 (17 Nov 2007, revision 194) +--------------------------------------- + + <re> Improved VST preset navigation in VST window. Known problem: doesn't update if preset is changed from VSTs own preset navigation. + + <re> Improvements in IT compatibility playmode. When loading ITs, if file doesn't seem modplug made, then automatically setting IT compatibility playmode. The playmode setting can be toggled in song properties dialog, and the autodetection with an ini setting. + + <re> 'key binding not understood'-messages can be disabled with an ini setting. + . <re> Fixed wrong file version in IT compatibility save. (http://lpchip.com/modplug/viewtopic.php?t=1723) + . <re> Fixed possible unnotified overwriting of file occurring for example when dealing with a new file. (http://lpchip.com/modplug/viewtopic.php?t=1813) + . <re> Fixed broken note preview for certain type of instruments in instrument tab. (http://lpchip.com/modplug/viewtopic.php?t=1996) + . <re> Fixed possible crash on channel mode wav export when a channel has a long name. (http://lpchip.com/modplug/viewtopic.php?t=2005) + . <re> Fixed pattern position indicator jump when clicking VST-box in channel header. (http://lpchip.com/modplug/viewtopic.php?t=2014) + / <re> Custom tuning related + -file format changes + -changed interpretation of finesteps: now zero finesteps means that finesteps are equal to notesteps, previously zero finesteps disabled portamentos etc) + -Pitch slide between notes with portamentos is now specialised also for other tuning types than just geometric(changes behavior). Previously behavior was 'geometric' for all types. + + . <rewbs> Fix pattern search, which could search for the wrong param. Also enable typing of desired param value rather than only selecting from listbox. (http://lpchip.com/modplug/viewtopic.php?t=1799) + . <rewbs> Delay-load winhttp.dll and don't die if it can't be found, e.g. on win98. (http://lpchip.com/modplug/viewtopic.php?t=1778) + . <rewbs> Fix a couple of pixels on D# in the pattern editor small font bitmap. (http://lpchip.com/modplug/viewtopic.php?t=1781) + + <rewbs> Add name filter to plugin selection dialog. Useful when you have hundreds of plugins. + + <Pelya> Allow Window key as a modifier in the keyboard configuration. Disables start menu pop-up when pressing the Win key if and only if it used in the active keyboard configuration. + + <Pelya> Disables NumLock/CapsLock/ScrollLock lamps on keyboard if and only if they are used in the active keyboard configuration. The lamps will blink anyway - can't help it until we start using DirectInput. + v1.17.02.48 - . <Relabs> Fix song cleanup issue (http://lpchip.com/modplug/viewtopic.php?t=1711) - . <Relabs> Pitch/Tempo lock fix (broken in .46 and .47) (http://lpchip.com/modplug/viewtopic.php?t=1646) - / <Relabs> Pattern manager channel reordering behviour changes / fixes. (http://lpchip.com/modplug/viewtopic.php?t=1148) + . <re> Fix song cleanup issue (http://lpchip.com/modplug/viewtopic.php?t=1711) + . <re> Pitch/Tempo lock fix (broken in .46 and .47) (http://lpchip.com/modplug/viewtopic.php?t=1646) + / <re> Pattern manager channel reordering behviour changes / fixes. (http://lpchip.com/modplug/viewtopic.php?t=1148) . <pelya> Fix bad horizontal scrolling in pattern editor when positioning the cursor with the mouse. (http://lpchip.com/modplug/viewtopic.php?t=1650) . <rewbs> Fix odd "play row" behaviour when using 1 tick-per-row (http://lpchip.com/modplug/viewtopic.php?t=1038). . <rewbs> Fix pop due to ramping when song starts with a pattern command that sets a low global volume. (http://lpchip.com/modplug/viewtopic.php?t=523) . <rewbs> Fix occasional colour issues with orderlist (http://lpchip.com/modplug/viewtopic.php?t=867) - . <rewbs> Fix impossible horizontal scrolling in pattern editor when playing with follow song on + . <rewbs> Fix impossible horizontal scrolling in pattern editor when playing with follow song on . <rewbs> Grey out "Trim" option in sample editor context menu if there's no selection. (http://lpchip.com/modplug/viewtopic.php?t=908) v1.17.02.47 @@ -26,54 +228,54 @@ . <rewbs> Fix saturation on old modules (introduced in 1.17.02.46). Loading tracks with no saved mixlevel setting defaults to 'original'. Starting new IT, MPTM, ITP or XM defaults to '117RC3'. Starting new MOD or S3M defaults to 'original'. . <rewbs> Tree view FX list now starts with FX01 instead of FX00. - / <Relabs> Pattern skipping behavior returned to that of .45 + / <re> Pattern skipping behavior returned to that of .45 . <pelya & rewbs> internal: ifdefs for compilation on vs2005 - . <Relabs> internal: VS Edit&Continue fix (gone broken in 'RC3'branch) - / <Relabs> Minor modifications(cleanup of channel state reset code, removed unused orderundo-vector.) + . <re> internal: VS Edit&Continue fix (gone broken in 'RC3'branch) + / <re> Minor modifications(cleanup of channel state reset code, removed unused orderundo-vector.) v1.17.02.46 - + <Relabsoluness> Experimental MPTm format: + + <re> Experimental MPTm format: --> Internally, it is still very close to the IT-based format. --> Order&pattern limit increased to 65000; whole range not tested :) (Note that modeffects such as position jump doesn't cover the whole range unless the #-extension can be used(haven't tested)) - + <Relabsoluness> User definable tuning modes for instruments: + + <re> User definable tuning modes for instruments: --> Only available for MPTm --> Ratio value as well as note name for every key can be assigned invidually; gives rather free hands for experiments. --> Every instrument can have it's own tuning --> Tunings can be saved to file and loaded from file. --> IMPORTANT: When using tunings, behavior of various modcommands such as portamento have been changed, and new behaviors are still to be decided. - + <Relabsoluness> In song properties, option to increase playback compatibility with original Impulse Tracker behavior. Is in no way complete; currently affects only a couple of differences. Many differences are still there. - + <Relabsoluness> Ability to load multiple mods/samples/instruments from corresponding load dialogs. + + <re> In song properties, option to increase playback compatibility with original Impulse Tracker behavior. Is in no way complete; currently affects only a couple of differences. Many differences are still there. + + <re> Ability to load multiple mods/samples/instruments from corresponding load dialogs. --> Known issue: Intermittent failures. - + <Relabsoluness> 32-bit float wav import - . <Relabsoluness> 24/32-bit PCM wav sample import fixed - + <Relabsoluness> Playback control additions: 'Solo on transition' & 'Mute on transition'. Available from pattern view context menu(right click). - + <Relabsoluness> Envelope points can be scaled by a factor through context menu on envelopeview(right click) - + <Relabsoluness> Calculator of playback time (measured from start) at the beginning of any row of any pattern (uses existing modlength calculator). + + <re> 32-bit float wav import + . <re> 24/32-bit PCM wav sample import fixed + + <re> Playback control additions: 'Solo on transition' & 'Mute on transition'. Available from pattern view context menu(right click). + + <re> Envelope points can be scaled by a factor through context menu on envelopeview(right click) + + <re> Calculator of playback time (measured from start) at the beginning of any row of any pattern (uses existing modlength calculator). --> Known limitation: When the row is within pattern loop, doesn't give all possible times. + <rewbs> SCx now sends note-off to VSTis at tick x. + <rewbs> New mixmode (called 1.17RC3): bypass global preamp, force soft panning, provide explicit dB value for sample attenuation. WARNING: this mixmode is subject to change. + <rewbs> Check for updates on startup. To disable, set CheckForUpdates=0 in mptrack.ini. . <rewbs> Plugin list window remembers its position/size even on cancel. . <rewbs> Fix odd window position on very first startup (before mptrack.ini is created). - . <Relabsoluness> When opening instruments, load dialog didn't remember its previous path. - . <Relabsoluness> In general tab, it was possible to give longer modname than the fileformat could save. - . <Relabsoluness> Instruments associates with VSTis no longer also need to be associated to a sample in order to play. - . <Relabsoluness> Trash characters to empty ITP comments should no longer appear. - . <Relabsoluness> Channel state should now be updated correctly when e.g. moving channels through channel manager. - . <Relabsoluness> It should no longer be possible to remove all channels from channel manager. - / <Relabsoluness> Channel states resetting when jumping between orders from orderlist. + . <re> When opening instruments, load dialog didn't remember its previous path. + . <re> In general tab, it was possible to give longer modname than the fileformat could save. + . <re> Instruments associates with VSTis no longer also need to be associated to a sample in order to play. + . <re> Trash characters to empty ITP comments should no longer appear. + . <re> Channel state should now be updated correctly when e.g. moving channels through channel manager. + . <re> It should no longer be possible to remove all channels from channel manager. + / <re> Channel states resetting when jumping between orders from orderlist. --> NOTE: While this fixes a bug (behavior change) introduced in the tuning branch(?), it also changes quite prominent behavior so can annoy people - might need to be modified at some point. - / <Relabsoluness> Added version number to the mainframe title. - / <Relabsoluness> Changed the 'order message' at the bottom bar of the screen "Position x of y" to "Position x of y (x in hex of y in hex)". - / <Relabsoluness> Lots of smaller (internal) changes. + / <re> Added version number to the mainframe title. + / <re> Changed the 'order message' at the bottom bar of the screen "Position x of y" to "Position x of y (x in hex of y in hex)". + / <re> Lots of smaller (internal) changes. v1.17.02.45 - + <Relabsoluness & Alex> "Pitch to tempo lock" instrument setting: define the tempo at which your instrument loops correctly, and it will be pitched automatically to match the song's current tempo. - + <Relabsoluness> Notification when attempting to modify pattern but pattern record is off. - + <Relabsoluness> Orderlist margins: you can define how many slots to keep visible around the active pattern as the orderlist scrolls - . <Relabsoluness> Fixes for various unexpected pattern loop state changes. - . <Relabsoluness> Fixes to IT Style clear. - . <Relabsoluness> Memory management fixes and misc other bug fixes. + + <re & Alex> "Pitch to tempo lock" instrument setting: define the tempo at which your instrument loops correctly, and it will be pitched automatically to match the song's current tempo. + + <re> Notification when attempting to modify pattern but pattern record is off. + + <re> Orderlist margins: you can define how many slots to keep visible around the active pattern as the orderlist scrolls + . <re> Fixes for various unexpected pattern loop state changes. + . <re> Fixes to IT Style clear. + . <re> Memory management fixes and misc other bug fixes. . <rewbs> ITP loading fixed (I broke it in v1.17.02.44) . <rewbs> Time estimation fixed for tracks with pattern break+XParam. . <rewbs> "Last saved with" version number was not always saved correctly - fixed @@ -91,14 +293,6 @@ . <rewbs> Added channel limit check when adding chans from the pattern editor. . <rewbs> Fixed instant crash with SampleTank 2.1. -. v1.17.02.43 - + <rewbs> You can now load up new plugins from anywhere, not just the General tab. Select "Plugin Manager..." from the view menu. This can also be assigned to a global hotkey. - Limitation: currently plugins added to a song in this manner with always be put in the first empty slot. In a future version you'll be able to choose the slot directly from that window. - + <rewbs> "Cleanup Plugins" to remove any plugs that are not associated to a channel and not used by an instrument and not used as an output for any used plugs. - . <rewbs> Fixed channel limits. Should be able to correctly save IT pattern data with up to 127 chans. There's only space for 64 channel headers though (channel names etc..). XMs restricted to 64 chans. - . <rewbs> Added channel limit check when adding chans from the pattern editor. - . <rewbs> Fixed instant crash with SampleTank 2.1. - . v1.17.02.42 + <rewbs> "Compatibility export" in file menu: save as 'plain' IT, without all of OpenMPT's crap. IT only for now (not XM). . <rewbs> Set instrument in pattern editor should work when no note is specified (tx Torvus - http://lpchip.com/modplug/viewtopic.php?t=470) @@ -115,14 +309,14 @@ . v 1.17.02.40 - + <Relabsoluness> Added indicator of currently playing pattern to orderlist. - + <Relabsoluness> 'Loop pattern' and 'follow song' keys should now work when orderlist has focus. + + <re> Added indicator of currently playing pattern to orderlist. + + <re> 'Loop pattern' and 'follow song' keys should now work when orderlist has focus. + <rewbs> Removed registry dependencies. All settings will now be saved to ini file. . <rewbs> Correcly update orderlist position when cycling through patterns - . <Relabsoluness> Fixed orderlist GUI update on ctrl-transition when in patternloop mode - . <Relabsoluness> Moving a channel should now correctly take into account record-channels and pending mutes - . <Relabsoluness> Switching autodelay off in the options now works for note-offs as well. - . <Relabsoluness> Some mod-effects like 'pattern jump' and 'break pattern' no longer conflict with pattern loop toggling. + . <re> Fixed orderlist GUI update on ctrl-transition when in patternloop mode + . <re> Moving a channel should now correctly take into account record-channels and pending mutes + . <re> Switching autodelay off in the options now works for note-offs as well. + . <re> Some mod-effects like 'pattern jump' and 'break pattern' no longer conflict with pattern loop toggling. . <rewbs> Fixed bad capping of random cutoff variation (tx LPChip) . <rewbs> Fixed crash on loading ITP with pattern names (tx Relabsoluness) . <rewbs> Fixed incorrect version number in saved files (tx Relabsoluness) @@ -131,12 +325,12 @@ . v 1.17.02.39 - + <Relabsoluness> Remove and insert channels directly from pattern editor via channel header context menu - + <Relabsoluness> Toggle loop pattern playback mode with a shortcut key and a checkbox above the pattern editor - + <Relabsoluness> The automatic note delays that are inserted when recording notes live are now optional - . <Relabsoluness> Fixed auto note delays so they work with S3Ms too - . <Relabsoluness> Fixes and improvements to displayed instrument name in pattern editor - . <Relabsoluness> Fixes and improvements to instrument swap from context menu + + <re> Remove and insert channels directly from pattern editor via channel header context menu + + <re> Toggle loop pattern playback mode with a shortcut key and a checkbox above the pattern editor + + <re> The automatic note delays that are inserted when recording notes live are now optional + . <re> Fixed auto note delays so they work with S3Ms too + . <re> Fixes and improvements to displayed instrument name in pattern editor + . <re> Fixes and improvements to instrument swap from context menu . <rewbs> Plugins should never cause song to be marked as modified if their GUI is not open (tx LPChip) / <rewbs> Version number in executable properties now correlates with real OpenMPT version number / <rewbs> Restored solo/mute in pattern editor main context menu. @@ -173,17 +367,17 @@ (+ <rewbs> volume commands without notes now send volume MIDI CC to plugs, but as far as I've seen, no plugs seem to respond to it.) . v 1.17.02.35 - + <rewbs & Relabsoluness> Note delay (SDx) is written automatically during "live tracking" if there are no effects already on the existing row. + + <rewbs & re> Note delay (SDx) is written automatically during "live tracking" if there are no effects already on the existing row. + <rewbs> Preliminary parameter value recording should work a bit now with follow song on. Attempts to set correct macro if it exists. Will only overwite \xx. Does not work with certain plugs that don't give idle time back to the host during mouse down (e.g. Albino, Vanguard...), still trying to understand this. Please play with this & give feedback, but don't expect miracles yet. :) . <rewbs> Restored external 0-255 sample panning range with XM. / <rewbs> experimental: muting a channel with a VSTi playing should turn off the active note on that channel. / <rewbs> Midi pitch bend reset on each new note for that instrument's midi channel. . v 1.17.02.34 - + <Relabsoluness> Added dynamic instrument list for Change Instrument item in pattern ctx menu. + + <re> Added dynamic instrument list for Change Instrument item in pattern ctx menu. / <rewbs> Disabled it for users who have opted for the old style context menu in general settings, + other minor change. - + <Relabsoluness> Added "Clear selection" item in pattern ctx menu - / <Relabsoluness> Can now set an instrument value for notes which previously had no attached instruments. + + <re> Added "Clear selection" item in pattern ctx menu + / <re> Can now set an instrument value for notes which previously had no attached instruments. + <rewbs> If you load a track with unrecognized plugins, you'll be prompted to search for the plugs on kvraudio. . <rewbs> Fixed rare crash on playback if playing a song with missing plugins. / <rewbs> Minor code cleanups @@ -703,4 +897,4 @@ Questions/comments/bug reports? ------------------------------- -Visit http://modplug.sourceforge.net/forum. \ No newline at end of file +Visit http://modplug.sourceforge.net/forum. Modified: trunk/OpenMPT/packageTemplate/SoundTouch/README.html =================================================================== --- trunk/OpenMPT/packageTemplate/SoundTouch/README.html 2009-05-17 14:54:05 UTC (rev 258) +++ trunk/OpenMPT/packageTemplate/SoundTouch/README.html 2009-05-30 21:21:35 UTC (rev 259) @@ -14,10 +14,10 @@ SoundTouch readme providing documentation for the time stretching feature.<br> SoundTouch WWW page: http://www.surina.net/soundtouch </h5></font> -<h1>SoundTouch audio processing library v1.3.1 +<h1>SoundTouch audio processing library v1.4.0 </h1> <p class="normal">SoundTouch library Copyright (c) Olli -Parviainen 2002-2006 </p> +Parviainen 2002-2009 </p> <hr> <h2>3. About implementation & Usage tips</h2> <h3>3.3. About algorithms</h3> @@ -40,10 +40,10 @@ sound the default parameter set may result into a sub-optimal result.</p> <p>The time-stretch algorithm default -parameter values are set by these #defines in file "TDStretch.h":</p> +parameter values are set by these #defines in file "TDStretch.h":</p> <blockquote> - <pre>#define DEFAULT_SEQUENCE_MS 82 -#define DEFAULT_SEEKWINDOW_MS 28 + <pre>#define DEFAULT_SEQUENCE_MS AUTOMATIC +#define DEFAULT_SEEKWINDOW_MS AUTOMATIC #define DEFAULT_OVERLAP_MS 12</pre> </blockquote> <p>These parameters affect to the time-stretch @@ -55,13 +55,16 @@ the time-stretch algorithm. Larger values mean fewer sequences are used in processing. In principle a larger value sounds better when slowing down the tempo, but worse when increasing the tempo and vice -versa.<br> +versa. <br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_SEEKWINDOW_MS</strong>: The seeking window default length in milliseconds is for the algorithm that seeks the best possible overlapping location. This determines from how wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together.<br> +location when the sound sequences are to be linked back together. <br> <br> The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may @@ -69,6 +72,9 @@ chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting.<br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_OVERLAP_MS</strong>: Overlap length in milliseconds. When the sound sequences are mixed back @@ -82,7 +88,7 @@ <p>Notice that these parameters can also be set during execution time with functions "<strong>TDStretch::setParameters()</strong>" and "<strong>SoundTouch::setSetting()</strong>".</p> -<p>The table below summarizes how the +<p>The table below summaries how the parameters can be adjusted for different applications:</p> <table border="1"> <tbody> @@ -94,9 +100,7 @@ affects...</strong></td> <td valign="top"><strong>Smaller value affects...</strong></td> - <td valign="top"><strong>Music</strong></td> - <td valign="top"><strong>Speech</strong></td> - <td valign="top"><strong>Effect in CPU burden</strong></td> + <td valign="top"><strong>Effect to CPU burden</strong></td> </tr> <tr> <td valign="top"> @@ -110,9 +114,6 @@ <td valign="top">Smaller value might be better for speeding up tempo. Reducing the value accelerates the "echoing" artifact when slowing down the tempo </td> - <td valign="top">Default value usually good</td> - <td valign="top">A smaller value than default -might be better</td> <td valign="top">Increasing the parameter value reduces computation burden</td> </tr> @@ -126,9 +127,6 @@ good mixing position, but may cause a "drifting" artifact</td> <td valign="top">Smaller reduce possibility to find a good mixing position, but reduce the "drifting" artifact.</td> - <td valign="top">Default value usually good, -unless a "drifting" artifact is disturbing.</td> - <td valign="top">Default value usually good</td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> @@ -141,22 +139,124 @@ <td valign="top"> </td> <td valign="top">If you reduce the "sequence ms" setting, you might wish to try a smaller value.</td> - <td valign="top"> </td> - <td valign="top"> </td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> </tbody> </table> <hr> -<h2 align="left">6. LICENSE </h2> +<h2>5. Change History</h2> +<h3>5.1. SoundTouch library Change History </h3> + +<p><strong>1.4.0:</strong></p> +<ul> +<li>Improved sound quality by automatic calculation of time stretch algorithm + processing parameters according to tempo setting</li> +<li>Moved BPM detection routines from SoundStretch application into SoundTouch + library</li> +<li>Bugfixes: Usage of uninitialied variables, GNU build scripts, compiler errors + due to 'const' keyword mismatch.</li> +<li>Source code cleanup</li> + +</ul> + +<p><strong>v1.3.1: +</strong></p> +<ul> +<li>Changed static class declaration to GCC 4.x compiler compatible syntax.</li> +<li>Enabled MMX/SSE-optimized routines also for GCC compilers. Earlier +the MMX/SSE-optimized routines were written in compiler-specific inline +assembler, now these routines are migrated to use compiler intrinsic +syntax which allows compiling the same MMX/SSE-optimized source code with +both Visual C++ and GCC compilers. </li> +<li>Set floating point as the default sample format and added switch to +the GNU configure script for selecting the other sample format.</li> + +</ul> + +<p><strong>v1.3.0: +</strong></p> +<ul> + <li>Fixed tempo routine output duration inaccuracy due to rounding +error </li> + <li>Implemented separate processing routines for integer and +floating arithmetic to allow improvements to floating point routines +(earlier used algorithms mostly optimized for integer arithmetic also +for floating point samples) </li> + <li>Fixed a bug that distorts sound if sample rate changes during the +sound stream </li> + <li>Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized +routines </li> + <li>Reduced redundant code pieces in MMX/SSE/3DNow! optimized +routines vs. the standard C routines.</li> + <li>MMX routine incompatibility with new gcc compiler versions </li> + <li>Other miscellaneous bug fixes </li> +</ul> +<p><strong>v1.2.1: </strong></p> +<ul> + <li>Added automake/autoconf scripts for GNU +platforms (in courtesy of David Durham)</li> + <li>Fixed SCALE overflow bug in rate transposer +routine.</li> + <li>Fixed 64bit address space bugs.</li> + <li>Created a 'soundtouch' namespace for +SAMPLETYPE definitions.</li> +</ul> +<p><strong>v1.2.0: </strong></p> +<ul> + <li>Added support for 32bit floating point sample +data type with SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations currently not supported in GCC environment)</li> + <li>Replaced 'make-gcc' script for GNU environment +by master Makefile</li> + <li>Added time-stretch routine configurability to +SoundTouch main class</li> + <li>Bugfixes</li> +</ul> +<p><strong>v1.1.1: </strong></p> +<ul> + <li>Moved SoundTouch under lesser GPL license (LGPL). This allows using SoundTouch library in programs that aren't +released under GPL license. </li> + <li>Changed MMX routine organiation so that MMX optimized routines are now implemented in classes that are derived from +the basic classes having the standard non-mmx routines. </li> + <li>MMX routines to support gcc version 3. </li> + <li>Replaced windows makefiles by script using the .dsw files </li> +</ul> +<p><strong>v1.01: </strong></p> +<ul> + <li>"mmx_gcc.cpp": Added "using namespace std" and +removed "return 0" from a function with void return value to fix +compiler errors when compiling the library in Solaris environment. </li> + <li>Moved file "FIFOSampleBuffer.h" to "include" +directory to allow accessing the FIFOSampleBuffer class from external +files. </li> +</ul> +<p><strong>v1.0: </strong></p> +<ul> + <li>Initial release </li> +</ul> +<p> </p> +<hr> +<h2 >6. Acknowledgements </h2> +<p >Kudos for these people who have submitted bugfixed since +SoundTouch v1.3.1: </p> +<ul> + <li>Arthur A</li> + <li>Richard Ash</li> + <li>Stanislav Brabec</li> + <li>Brian Cameron</li> + <li>Justin Frankel</li> + <li>Jason Garland</li> + <li>Takashi Iwai</li> +</ul> +<p >Moral greetings to all other contributors as well!</p> +<hr> +<h2 >7. LICENSE </h2> <p>SoundTouch audio processing library<br> Copyright (c) Olli Parviainen</p> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU -Lesser General Public License as published by the Free Software -Foundation; either version 2.1 of the License, or (at your option) -any later version.</p> +Lesser General Public License vesrion 2.1 as published by the Free Software +Foundation.</p> <p>This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A Modified: trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2009-05-17 14:54:05 UTC (rev 258) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2009-05-30 21:21:35 UTC (rev 259) @@ -8,6 +8,8 @@ 0:1346:2:79:1 //File/Open: Ctrl+O (KeyDown) 0:1348:2:87:1 //File/Close: Ctrl+W (KeyDown) 0:1349:2:83:1 //File/Save: Ctrl+S (KeyDown) +0:1693:0:166:1 //Previous Document: (KeyDown) +0:1694:0:167:1 //Next Document: (KeyDown) 0:1030:0:116:1 //Play song/Pause song: F5 (KeyDown) 0:1031:0:119:1 //Pause song: F8 (KeyDown) 0:1375:0:27:1 //Stop Song: ESC (KeyDown) @@ -194,6 +196,7 @@ 5:1229:0:55:1 //Set volume digit 7: 7 (KeyDown) 5:1229:0:103:1 //Set volume digit 7: 7 (ZEHNERTASTATUR) (KeyDown) 5:1230:0:56:1 //Set volume digit 8: 8 (KeyDown) +5:1230:0:104:1 //Set volume digit 8: 8 (ZEHNERTASTATUR) (KeyDown) 5:1231:0:57:1 //Set volume digit 9: 9 (KeyDown) 5:1231:0:105:1 //Set volume digit 9: 9 (ZEHNERTASTATUR) (KeyDown) 5:1232:0:86:1 //Vol command - volume: V (KeyDown) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-05-17 14:54:15
|
Revision: 258 http://modplug.svn.sourceforge.net/modplug/?rev=258&view=rev Author: relabsoluness Date: 2009-05-17 14:54:05 +0000 (Sun, 17 May 2009) Log Message: ----------- . Pattern tab: Fix to possible crash when using undo after pattern resize (bug introduced in rev. 168). ./ Miscellaneous tweaks (typo fixes etc.). Modified Paths: -------------- trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/dlg_misc.cpp Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-05-09 23:01:26 UTC (rev 257) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-05-17 14:54:05 UTC (rev 258) @@ -2093,10 +2093,11 @@ MODCOMMAND *newPattern = CSoundFile::AllocatePattern(nRows, m_SndFile.m_nChannels); MODCOMMAND *oldPattern = m_SndFile.Patterns[nPattern]; if (!newPattern) return (UINT)-1; + const ROWINDEX nOldRowCount = m_SndFile.Patterns[nPattern].GetNumRows(); m_SndFile.Patterns[nPattern].SetData(newPattern, nRows); if (oldPattern) { - memcpy(newPattern, oldPattern, m_SndFile.m_nChannels*m_SndFile.PatternSize[nPattern]*sizeof(MODCOMMAND)); + memcpy(newPattern, oldPattern, m_SndFile.m_nChannels*nOldRowCount*sizeof(MODCOMMAND)); CSoundFile::FreePattern(oldPattern); } } Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-05-09 23:01:26 UTC (rev 257) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-05-17 14:54:05 UTC (rev 258) @@ -231,9 +231,9 @@ " [Mod] mptm files made with this version will be recognized as IT in 1.17.02.48.\n" " [Mod] Automatic update check on startup is no longer available.\n" " [Fix] Copy/Paste in pattern was partly broken when working with MOD format.\n" - " [Fix] Fixed wrong version in IT files saved with compatibility save.\n" + " [Fix] Fixed wrong version in IT files saved with compatibility export.\n" "\n" - " For more detail, see history.txt."; + " For more detailed list of changes, see history.txt."; CMainFrame::GetMainFrame()->MessageBox(firstOpenMessage, "OpenMPT v." MPT_VERSION_STR, MB_ICONINFORMATION); } @@ -1264,7 +1264,7 @@ // -> DESC="IT project files (.itp)" "Impulse Tracker Projects (*.itp)|*.itp;*.itpz|" // -! NEW_FEATURE#0023 - "Open MPT Modules (*.mptm)|*.mptm;*.mptmz|" + "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|" "Wave Files (*.wav)|*.wav|" "Midi Files (*.mid,*.rmi)|*.mid;*.rmi;*.smf|" @@ -1651,7 +1651,7 @@ m_bmp.LoadBitmap(MAKEINTRESOURCE(IDB_MPTRACK)); wsprintf(s, "Build Date: %s", gszBuildDate); SetDlgItemText(IDC_EDIT2, s); - SetDlgItemText(IDC_EDIT3, CString("Open Modplug Tracker, version ") + MptVersion::str + " (development build)"); + SetDlgItemText(IDC_EDIT3, CString("OpenMPT, version ") + MptVersion::str + " (development build)"); m_heContact.SetWindowText( "Contact / Discussion:\r\n\ Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-05-09 23:01:26 UTC (rev 257) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-05-17 14:54:05 UTC (rev 258) @@ -1967,7 +1967,7 @@ int param = m_pModDoc->MacroToPlugParam(&(m_MidiCfg.szMidiSFXExt[sfx*32])); CVstPlugin *pVstPlugin; char s[256]; - message.Format("These are the parameters that can be conrolled by macro SF%X:\n\n",sfx); + message.Format("These are the parameters that can be controlled by macro SF%X:\n\n",sfx); for (UINT plug=0; plug<MAX_MIXPLUGINS; plug++) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-05-09 23:01:43
|
Revision: 257 http://modplug.svn.sourceforge.net/modplug/?rev=257&view=rev Author: relabsoluness Date: 2009-05-09 23:01:26 +0000 (Sat, 09 May 2009) Log Message: ----------- . IT load: Macro config should now be loaded correctly also when loading IT files not made with MPT. . IT compatibility export: tentative fix to hidden last sequence item when opened in IT. . IT compatibility play: tentative fix to vibrato with ramp down waveform. / Misc: Minor changes to load functions. / Misc: Removed tremor effect description. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/LOAD_AMF.CPP trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/Load_mt2.cpp trunk/OpenMPT/soundlib/Load_okt.cpp trunk/OpenMPT/soundlib/Load_stm.cpp trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -2495,12 +2495,6 @@ wsprintf(s, "%dbpm", param); break; - case CMD_TREMOR: - if(param) - wsprintf(s, "ontime %d, offtime %d", param >> 4, param & 0x0F); - else - strcpy(s, "continue"); - break; case CMD_RETRIG: switch(param >> 4) { Modified: trunk/OpenMPT/soundlib/LOAD_AMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2009-05-09 23:01:26 UTC (rev 257) @@ -174,7 +174,7 @@ DWORD dwMemPos; if ((!lpStream) || (dwMemLength < 2048)) return FALSE; - if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096)) + if ((!strncmp((LPCSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096)) { UINT numorders, numpats, numsamples; @@ -370,7 +370,7 @@ // Store tracks positions BYTE **pTrackData = new BYTE *[realtrackcnt]; memset(pTrackData, 0, sizeof(pTrackData)); - for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength) + for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos <= dwMemLength-3) { UINT nTrkSize = LittleEndianW(*(USHORT *)(lpStream+dwMemPos)); nTrkSize += (UINT)lpStream[dwMemPos+2] << 16; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -980,7 +980,7 @@ if (pifh->flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES; if (pifh->flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS; if (pifh->flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE; - if (pifh->flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG; + if ((pifh->flags & 0x80) || (pifh->special & 0x08)) m_dwSongFlags |= SONG_EMBEDMIDICFG; if (pifh->flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; memcpy(m_szNames[0], pifh->songname, 26); m_szNames[0][26] = 0; @@ -1241,7 +1241,7 @@ // Reading Samples m_nSamples = pifh->smpnum; if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT nsmp=0; nsmp<pifh->smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] + sizeof(ITSAMPLESTRUCT) <= dwMemLength)) + for (UINT nsmp=0; nsmp<pifh->smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] <= dwMemLength - sizeof(ITSAMPLESTRUCT))) { lastSampleSize = 0; //ensure lastsamplesize = 0 if last sample is empty, else we'll skip the MPTX stuff. ITSAMPLESTRUCT *pis = (ITSAMPLESTRUCT *)(lpStream+smppos[nsmp]); @@ -1761,7 +1761,6 @@ memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->name, 12); memcpy(itss.name, m_szNames[nsmp], 26); - SetNullTerminator(itss.name); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; @@ -2058,7 +2057,6 @@ memset(smpcount, 0, sizeof(smpcount)); memcpy(iti.filename, penv->filename, 12); memcpy(iti.name, penv->name, 26); - SetNullTerminator(iti.name); iti.mbank = penv->wMidiBank; iti.mpr = penv->nMidiProgram; iti.mch = penv->nMidiChannel; @@ -2376,7 +2374,6 @@ memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->name, 12); memcpy(itss.name, m_szNames[nsmp], 26); - SetNullTerminator(itss.name); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; if (m_nInstruments) @@ -2545,6 +2542,10 @@ while (header.ordnum>0 && Order[header.ordnum-1]==0xFF) { header.ordnum--; } + + if(header.ordnum + 1 < MAX_ORDERS) + header.ordnum++; + header.patnum = MAX_PATTERNS; while ((header.patnum > 0) && (!Patterns[header.patnum-1])) { header.patnum--; Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -328,7 +328,6 @@ INSTRUMENTHEADER *penv = Headers[nins]; memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, lpStream+dwPos+2, 32); - SetNullTerminator(penv->name); penv->nGlobalVol = 64; penv->nPPC = 5*12; SetDefaultInstrumentValues(penv); @@ -458,7 +457,7 @@ { DWORD dwLen = *((DWORD *)(lpStream+dwPos)); dwPos += 4; - if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4)) + if ( (dwLen <= dwMemLength) && (dwPos <= dwMemLength - dwLen) && (dwLen > 4) ) { flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8; ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen); Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -521,7 +521,7 @@ dwBlockArr = BigEndian(pmmh->blockarr); dwSmplArr = BigEndian(pmmh->smplarr); dwExpData = BigEndian(pmmh->expdata); - if ((dwExpData) && (dwExpData+sizeof(MMD0EXP) < dwMemLength)) + if ((dwExpData) && (dwExpData < dwMemLength - sizeof(MMD0EXP))) pmex = (MMD0EXP *)(lpStream+dwExpData); else pmex = NULL; @@ -659,7 +659,7 @@ } UINT pseq = 0; - if ((playseqtable) && (playseqtable + nplayseq*4 < dwMemLength)) + if ((playseqtable) && (playseqtable < dwMemLength) && (nplayseq*4 < dwMemLength - playseqtable)) { pseq = BigEndian(((LPDWORD)(lpStream+playseqtable))[nplayseq]); } @@ -737,7 +737,7 @@ } // Track Names DWORD trackinfo_ofs = BigEndian(pmex->trackinfo_ofs); - if ((trackinfo_ofs) && (trackinfo_ofs + m_nChannels * 4 < dwMemLength)) + if ((trackinfo_ofs) && (trackinfo_ofs < dwMemLength) && (m_nChannels * 4 < dwMemLength - trackinfo_ofs)) { DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs); for (UINT i=0; i<m_nChannels; i++) @@ -866,7 +866,7 @@ { DWORD nameofs = BigEndian(pbi->blockname); UINT namelen = BigEndian(pbi->blocknamelen); - if ((nameofs < dwMemLength) && (nameofs+namelen < dwMemLength)) + if ((nameofs < dwMemLength) && (namelen < dwMemLength - nameofs)) { SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs)); } Modified: trunk/OpenMPT/soundlib/Load_mid.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mid.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_mid.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -590,7 +590,7 @@ pmth = (MIDITRACKHEADER *)(lpStream+dwMemPos); if (dwMemPos + 8 >= dwMemLength) break; DWORD len = BigEndian(pmth->len); - if ((pmth->id == 0x6B72544D) && (dwMemPos + 8 + len <= dwMemLength)) + if ((pmth->id == 0x6B72544D) && (len <= dwMemLength - (dwMemPos + 8))) { #ifdef MIDI_DETAILED_LOG Log(" track%d at offset %d len=%d ", itrk, dwMemPos+8, len); Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mt2.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -418,7 +418,7 @@ #ifdef MT2DEBUG if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen); #endif - if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength)) + if (((LONG)pmi->dwDataLen > 0) && (dwMemPos <= dwMemLength - 40) && (pmi->dwDataLen <= dwMemLength - (dwMemPos + 40))) { InstrMap[iIns-1] = pmi; if (penv) Modified: trunk/OpenMPT/soundlib/Load_okt.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_okt.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_okt.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -113,7 +113,7 @@ } // PBOD UINT npat = 0; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) + while ((dwMemPos < dwMemLength-10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) { DWORD dwPos = dwMemPos + 10; UINT rows = lpStream[dwMemPos+9]; @@ -189,7 +189,7 @@ } // SBOD UINT nsmp = 1; - while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) + while ((dwMemPos < dwMemLength - 10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) { if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; Modified: trunk/OpenMPT/soundlib/Load_stm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_stm.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Load_stm.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -177,7 +177,7 @@ if (pIns->nLength) { UINT nPos = ((UINT)phdr->sample[nSmp-1].reserved) << 4; - if ((nPos >= sizeof(STMHEADER)) && (nPos+pIns->nLength <= dwMemLength)) dwMemPos = nPos; + if ((nPos >= sizeof(STMHEADER)) && (nPos <= dwMemLength) && (pIns->nLength <= dwMemLength-nPos)) dwMemPos = nPos; if (dwMemPos < dwMemLength) { dwMemPos += ReadSample(pIns, RS_PCM8S, (LPSTR)(lpStream+dwMemPos),dwMemLength-dwMemPos); Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -566,7 +566,6 @@ if (xtrabytes >= 22) { memcpy(pins->name, pszTextEx, 22); - SetNullTerminator(pins->name); xtrabytes -= 22; } } Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-05-02 20:42:19 UTC (rev 256) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-05-09 23:01:26 UTC (rev 257) @@ -1276,7 +1276,10 @@ switch (pChn->nVibratoType & 0x03) { case 1: - vdelta = ModRampDownTable[vibpos]; + if(GetModFlag(MSF_IT_COMPATIBLE_PLAY) == true) + vdelta = -ModRampDownTable[(vibpos+16) % 64]; + else + vdelta = ModRampDownTable[vibpos]; break; case 2: vdelta = ModSquareTable[vibpos]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-05-02 20:42:23
|
Revision: 256 http://modplug.svn.sourceforge.net/modplug/?rev=256&view=rev Author: relabsoluness Date: 2009-05-02 20:42:19 +0000 (Sat, 02 May 2009) Log Message: ----------- . (patch from Jojo, merged somewhat modified) Fixes to MOD saving: it should now be possible to create ProTracker compatible MOD files with compatibility export. + Added a few hidable usage tips. . Fix to parameter validation in ReadSample. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -2242,9 +2242,10 @@ memset(&viewstate, 0, sizeof(viewstate)); SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&viewstate); if ((!m_pModDoc) || (!m_pSndFile) || (!m_pSndFile->Ins[m_nSample].pSample)) return; - if( AfxMessageBox(TEXT(GetStrI18N("Apply signed/unsigned conversion(distortion)?\n\n" - "Note: in many cases this increases volume level significantly.")), MB_YESNO|MB_ICONQUESTION) == IDNO ) - return; + + if(m_pModDoc->IsNotePlaying(0, m_nSample, 0) == TRUE) + MsgBoxHidable(ConfirmSignUnsignWhenPlaying); + BeginWaitCursor(); pins = &m_pSndFile->Ins[m_nSample]; dwStart = viewstate.dwBeginSel; Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -166,6 +166,8 @@ int CMainFrame::gnPlugWindowHeight = 332; DWORD CMainFrame::gnPlugWindowLast = 0; +uint32 CMainFrame::gnMsgBoxVisiblityFlags = ~0; + CRITICAL_SECTION CMainFrame::m_csAudio; HANDLE CMainFrame::m_hPlayThread = NULL; DWORD CMainFrame::m_dwPlayThreadId = 0; @@ -391,6 +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); CHAR s[16]; for (int ncol=0; ncol<MAX_MODCOLORS; ncol++) { @@ -902,6 +905,7 @@ WritePrivateProfileLong("Display", "PlugSelectWindowWidth", gnPlugWindowWidth, iniFile); WritePrivateProfileLong("Display", "PlugSelectWindowHeight", gnPlugWindowHeight, iniFile); WritePrivateProfileLong("Display", "PlugSelectWindowLast", gnPlugWindowLast, iniFile); + WritePrivateProfileDWord("Display", "MsgBoxVisibilityFlags", gnMsgBoxVisiblityFlags, iniFile); CHAR s[16]; for (int ncol=0; ncol<MAX_MODCOLORS; ncol++) { Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2009-05-02 20:42:19 UTC (rev 256) @@ -425,6 +425,8 @@ static int gnPlugWindowHeight; static DWORD gnPlugWindowLast; + static uint32 gnMsgBoxVisiblityFlags; + // Midi Input public: static HMIDIIN shMidiIn; Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -20,6 +20,12 @@ static char THIS_FILE[] = __FILE__; #endif +const TCHAR* const FileFilterMOD = TEXT("ProTracker Modules (*.mod)|*.mod||"); +const TCHAR* const FileFilterXM = TEXT("FastTracker Modules (*.xm)|*.xm||"); +const TCHAR* const FileFilterS3M = TEXT("ScreamTracker Modules (*.s3m)|*.s3m||"); +const TCHAR* const FileFilterIT = TEXT("Impulse Tracker Modules (*.it)|*.it||"); +const TCHAR* const FileFilterITP = TEXT("Impulse Tracker Projects (*.itp)|*.itp||"); +const TCHAR* const FileFilterMPT = TEXT("OpenMPT Modules (*.mptm)|*.mptm||"); ///////////////////////////////////////////////////////////////////////////// // CModDoc @@ -487,18 +493,19 @@ switch(m_SndFile.GetType()) { case MOD_TYPE_MOD: + MsgBoxHidable(ModCompatibilityExportTip); lpszDefExt = "mod"; - lpszFilter = "ProTracker Modules (*.mod)|*.mod||"; + lpszFilter = FileFilterMOD; strcpy(fext, ".mod"); break; case MOD_TYPE_S3M: lpszDefExt = "s3m"; - lpszFilter = "ScreamTracker Modules (*.s3m)|*.s3m||"; + lpszFilter = FileFilterS3M; strcpy(fext, ".s3m"); break; case MOD_TYPE_XM: lpszDefExt = "xm"; - lpszFilter = "FastTracker Modules (*.xm)|*.xm||"; + lpszFilter = FileFilterXM; strcpy(fext, ".xm"); break; case MOD_TYPE_IT: @@ -509,19 +516,21 @@ // strcpy(fext, ".it"); if(m_SndFile.m_dwSongFlags & SONG_ITPROJECT){ lpszDefExt = "itp"; - lpszFilter = "Impulse Tracker Projects (*.itp)|*.itp||"; + lpszFilter = FileFilterITP; strcpy(fext, ".itp"); } - else{ + else + { + MsgBoxHidable(ItCompatibilityExportTip); lpszDefExt = "it"; - lpszFilter = "Impulse Tracker Modules (*.it)|*.it||"; + lpszFilter = FileFilterIT; strcpy(fext, ".it"); } // -! NEW_FEATURE#0023 break; case MOD_TYPE_MPT: lpszDefExt = "mptm"; - lpszFilter = "OpenMPT Modules (*.mptm)|*.mptm||"; + lpszFilter = FileFilterMPT; strcpy(fext, ".mptm"); break; default: @@ -1561,7 +1570,7 @@ //HACK: This is a quick fix. Needs to be better integrated into player and GUI. void CModDoc::OnFileCompatibilitySave() -//------------------------------- +//------------------------------------- { CHAR path[_MAX_PATH]="", drive[_MAX_DRIVE]=""; CHAR s[_MAX_PATH], fname[_MAX_FNAME]=""; @@ -1571,21 +1580,34 @@ UINT type = m_SndFile.GetType(); if ((!pMainFrm) || (!m_SndFile.GetType())) return; - switch (type) { + switch (type) + { /*case MOD_TYPE_XM: ext = "xm"; pattern = "Fast Tracker Files (*.xm)|*.xm||"; break;*/ + case MOD_TYPE_MOD: + ext = MOD_STD_SPECS.fileExtension; + pattern = FileFilterMOD; + if( AfxMessageBox(GetStrI18N(TEXT( + "Compared to regular MOD save, compatibility export makes " + "small adjustments to the save file in order to make the file compatible with " + "ProTracker. Note that this feature is not complete and the " + "file is not guaranteed to be free of MPT-specific features.\n\n " + "Important: beginning of some samples may be adjusted in the process. Proceed?")), MB_ICONINFORMATION|MB_YESNO) != IDYES + ) + return; + break; case MOD_TYPE_IT: - ext = "it"; - pattern = "Impulse Tracker Files (*.it)|*.it||"; + ext = IT_STD_SPECS.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; default: - ::MessageBox(NULL,"Compatibility export is currently only available the IT format.", "Can't do compatibility export.",MB_ICONINFORMATION | MB_OK); + ::MessageBox(NULL,"Compatibility export is currently only available for MOD and IT modules.", "Can't do compatibility export.",MB_ICONINFORMATION | MB_OK); return; } - ::MessageBox(NULL,"Warning: the exported file will not contain any of MPT's file-format hacks.", "Compatibility export warning.",MB_ICONINFORMATION | MB_OK); _splitpath(GetPathName(), drive, path, fname, NULL); strcpy(s, drive); strcat(s, path); @@ -1602,7 +1624,13 @@ if (dlg.DoModal() != IDOK){ return; } - switch (type) { + switch (type) + { + case MOD_TYPE_MOD: + m_SndFile.SaveMod(dlg.GetPathName(), 0, true); + SetModified(); // Compatibility save may adjust samples so set modified... + m_ShowSavedialog = true; // ...and force save dialog to appear when saving. + break; case MOD_TYPE_XM: m_SndFile.SaveCompatXM(dlg.GetPathName()); break; Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -2710,4 +2710,90 @@ CDialog::OnCancel(); } +/////////////////////////////////////////////////////////////////////////////////////// +// Messagebox with 'don't show again'-option. +//=================================== +class CMsgBoxHidable : public CDialog +//=================================== +{ +public: + CMsgBoxHidable(LPCTSTR strMsg, bool checkStatus = true, CWnd* pParent = NULL); + enum { IDD = IDD_MSGBOX_HIDABLE }; + + int m_nCheckStatus; + LPCTSTR m_StrMsg; +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); +}; + + +struct MsgBoxHidableMessage +//========================= +{ + LPCTSTR strMsg; + uint32 nMask; + bool bDefaultDontShowAgainStatus; // true for don't show again, false for show again. +}; + +const MsgBoxHidableMessage HidableMessages[] = +{ + {TEXT("Tip: To create ProTracker compatible MOD-files, try compatibility export from File-menu."), 1, true}, + {TEXT("Tip: To create IT-files without MPT-specific extensions included, try compatibility export from File-menu."), 1 << 1, true}, + {TEXT("Press OK to apply signed/unsigned conversion\n (note: this often significantly increases volume level)"), 1 << 2, false} +}; + +STATIC_ASSERT(ARRAYELEMCOUNT(HidableMessages) == enMsgBoxHidableMessage_count); + +// Messagebox with 'don't show this again'-checkbox. Uses parameter 'enMsg' +// to get the needed information from message array, and updates the variable that +// controls the show/don't show-flags. +void MsgBoxHidable(enMsgBoxHidableMessage enMsg) +//---------------------------------------------- +{ + // Check whether the message should be shown. + if((CMainFrame::gnMsgBoxVisiblityFlags & HidableMessages[enMsg].nMask) == 0) + return; + + const LPCTSTR strMsg = HidableMessages[enMsg].strMsg; + const uint32 mask = HidableMessages[enMsg].nMask; + const bool defaulCheckStatus = HidableMessages[enMsg].bDefaultDontShowAgainStatus; + + // Show dialog. + CMsgBoxHidable dlg(strMsg, defaulCheckStatus); + dlg.DoModal(); + + // Update visibility flags. + if(dlg.m_nCheckStatus == BST_CHECKED) + CMainFrame::gnMsgBoxVisiblityFlags &= ~mask; + else + CMainFrame::gnMsgBoxVisiblityFlags |= mask; +} + + +CMsgBoxHidable::CMsgBoxHidable(LPCTSTR strMsg, bool checkStatus, CWnd* pParent) + : CDialog(CMsgBoxHidable::IDD, pParent), + m_StrMsg(strMsg), + m_nCheckStatus((checkStatus) ? BST_CHECKED : BST_UNCHECKED) +//---------------------------------------------------------------------------- +{} + +BOOL CMsgBoxHidable::OnInitDialog() +//---------------------------------- +{ + CDialog::OnInitDialog(); + SetDlgItemText(IDC_MESSAGETEXT, m_StrMsg); + SetWindowText(AfxGetAppName()); + return TRUE; +} + +void CMsgBoxHidable::DoDataExchange(CDataExchange* pDX) +//------------------------------------------------------ +{ + CDialog::DoDataExchange(pDX); + DDX_Check(pDX, IDC_DONTSHOWAGAIN, m_nCheckStatus); +} + + + Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2009-05-02 20:42:19 UTC (rev 256) @@ -493,4 +493,18 @@ }; +///////////////////////////////////////////////////////////////////////// +// Messagebox with 'don't show again'-option. + +// Enums for message entries. See dlg_misc.cpp for the array of entries. +enum enMsgBoxHidableMessage +{ + ModCompatibilityExportTip = 0, + ItCompatibilityExportTip = 1, + ConfirmSignUnsignWhenPlaying = 2, + enMsgBoxHidableMessage_count = 3 +}; + +void MsgBoxHidable(enMsgBoxHidableMessage enMsg); + #endif Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-05-02 20:42:19 UTC (rev 256) @@ -2626,6 +2626,19 @@ // Dialog // +IDD_MSGBOX_HIDABLE DIALOGEX 0, 0, 186, 71 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,149,50,30,14 + PUSHBUTTON "Cancel",IDCANCEL,111,49,30,14,NOT WS_VISIBLE + CONTROL "Don't show this again.",IDC_DONTSHOWAGAIN,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,54,90,10 + LTEXT "Static",IDC_MESSAGETEXT,7,7,172,40 +END + IDD_MIDIPARAMCONTROL DIALOGEX 0, 0, 392, 202 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU @@ -2837,6 +2850,14 @@ #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN + IDD_MSGBOX_HIDABLE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 64 + END + IDD_MIDIPARAMCONTROL, DIALOG BEGIN RIGHTMARGIN, 388 Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/mptrack/resource.h 2009-05-02 20:42:19 UTC (rev 256) @@ -104,6 +104,7 @@ #define IDD_DIALOG3 513 #define IDS_ERR_TUNING_SERIALISATION 514 #define IDD_MIDIPARAMCONTROL 515 +#define IDD_MSGBOX_HIDABLE 516 #define IDC_BUTTON1 1001 #define IDC_BUTTON2 1002 #define IDC_BUTTON3 1003 @@ -825,6 +826,8 @@ #define IDC_EDIT_STRETCHPARAMS 2338 #define IDC_MIDI_MACRO_CONTROL 2339 #define IDC_MIDIPLAYPATTERNONMIDIIN 2340 +#define IDC_DONTSHOWAGAIN 2341 +#define IDC_MESSAGETEXT 2342 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1057,9 +1060,9 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 516 +#define _APS_NEXT_RESOURCE_VALUE 517 #define _APS_NEXT_COMMAND_VALUE 59221 -#define _APS_NEXT_CONTROL_VALUE 2341 +#define _APS_NEXT_CONTROL_VALUE 2343 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -373,8 +373,8 @@ #ifndef MODPLUG_NO_FILESAVE #pragma warning(disable:4100) -BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- +BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking, const bool bCompatibilityExport) +//------------------------------------------------------------------------------------------- { BYTE insmap[32]; UINT inslen[32]; @@ -418,8 +418,11 @@ bTab[25] = pins->nVolume >> 2; bTab[26] = pins->nLoopStart >> 9; bTab[27] = pins->nLoopStart >> 1; - bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9; - bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1; + UINT replen = pins->nLoopEnd - pins->nLoopStart; + if(bCompatibilityExport && replen < 2) // ensure PT will load it properly + replen = 2; + bTab[28] = replen >> 9; + bTab[29] = replen >> 1; fwrite(bTab, 30, 1, f); } // Writing number of patterns @@ -501,6 +504,11 @@ for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd]) { MODINSTRUMENT *pins = &Ins[insmap[ismpd]]; + if(bCompatibilityExport == true) + { + if(pins->nLength > 0) pins->pSample[0] = 0; + if(pins->nLength > 1) pins->pSample[1] = 0; + } UINT flags = RS_PCM8S; #ifndef NO_PACKING if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-05-02 20:42:19 UTC (rev 256) @@ -1899,12 +1899,13 @@ UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength, const WORD format) //----------------------------------------------------------------------------------------------------------------------- { + if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; + if(pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; UINT len = 0, mem = pIns->nLength+6; - if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); if (nFlags & RSF_16BIT) { Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2009-05-01 14:12:28 UTC (rev 255) +++ trunk/OpenMPT/soundlib/Sndfile.h 2009-05-02 20:42:19 UTC (rev 256) @@ -1074,7 +1074,7 @@ UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0); BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0); BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0); - BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0); + BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0, const bool bCompatibilityExport = false); BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0); BOOL SaveCompatIT(LPCSTR lpszFileName); BOOL SaveCompatXM(LPCSTR lpszFileName); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-05-01 14:12:37
|
Revision: 255 http://modplug.svn.sourceforge.net/modplug/?rev=255&view=rev Author: relabsoluness Date: 2009-05-01 14:12:28 +0000 (Fri, 01 May 2009) Log Message: ----------- . Fix to faulty portamento handling on loading AMF (patch copied from libmodplug). . Various string null termination and other validations to load functions. Modified Paths: -------------- trunk/OpenMPT/mptrack/misc_util.h trunk/OpenMPT/soundlib/Dlsbank.cpp trunk/OpenMPT/soundlib/LOAD_AMF.CPP trunk/OpenMPT/soundlib/Load_far.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mt2.cpp trunk/OpenMPT/soundlib/Load_ult.cpp trunk/OpenMPT/soundlib/Sampleio.cpp Modified: trunk/OpenMPT/mptrack/misc_util.h =================================================================== --- trunk/OpenMPT/mptrack/misc_util.h 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/mptrack/misc_util.h 2009-05-01 14:12:28 UTC (rev 255) @@ -38,5 +38,14 @@ */ } +// Sets last character to null in given char array. +// 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; +} + #endif Modified: trunk/OpenMPT/soundlib/Dlsbank.cpp =================================================================== --- trunk/OpenMPT/soundlib/Dlsbank.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Dlsbank.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -1592,7 +1592,7 @@ if (pSndFile->m_nType & MOD_TYPE_XM) psmp->uFlags |= CHN_PANNING; } } - if (pins->szName[0]) memcpy(pSndFile->m_szNames[nSample], pins->szName, 32); + if (pins->szName[0]) memcpy(pSndFile->m_szNames[nSample], pins->szName, 31); bOk = TRUE; } FreeWaveForm(pWaveForm); @@ -1672,6 +1672,7 @@ } else { memcpy(penv->name, pins->szName, 32); + SetNullTerminator(penv->name); } int nTranspose = 0; for (UINT iNoteMap=0; iNoteMap<NOTE_MAX; iNoteMap++) Modified: trunk/OpenMPT/soundlib/LOAD_AMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2009-05-01 14:12:28 UTC (rev 255) @@ -109,8 +109,10 @@ else param = (param&0x0F)<<4; break; // 0x04: Porta Up/Down - case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = -(signed char)param; } - else { command = CMD_PORTAMENTODOWN; } break; + //case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = -(signed char)param; } + // else { command = CMD_PORTAMENTODOWN; } break; + case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = (-(signed char)param)&0x7F; } + else { command = CMD_PORTAMENTODOWN; } break; // 0x06: Tone Portamento case 0x06: command = CMD_TONEPORTAMENTO; break; // 0x07: Tremor @@ -268,7 +270,7 @@ || (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES) || (pfh->numchannels < 4) || (pfh->numchannels > 32)) return FALSE; - memcpy(m_szNames[0], pfh->title, 32); + memcpy(m_szNames[0], pfh->title, 31); dwMemPos = sizeof(AMFFILEHEADER); m_nType = MOD_TYPE_AMF; m_nChannels = pfh->numchannels; @@ -330,7 +332,7 @@ AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos); dwMemPos += sizeof(AMFSAMPLE); - memcpy(m_szNames[iIns+1], psh->samplename, 32); + memcpy(m_szNames[iIns+1], psh->samplename, 31); memcpy(pins->name, psh->filename, 13); pins->nLength = LittleEndian(psh->length); pins->nC4Speed = LittleEndianW(psh->c2spd); Modified: trunk/OpenMPT/soundlib/Load_far.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_far.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_far.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -67,7 +67,7 @@ FARHEADER1 farHeader; memcpy(&farHeader, lpStream, sizeof(FARHEADER1)); FARHEADER1 *pmh1 = &farHeader; - FARHEADER2 *pmh2; + FARHEADER2 *pmh2 = 0; DWORD dwMemPos = sizeof(FARHEADER1); UINT headerlen; BYTE samplemap[8]; @@ -87,7 +87,7 @@ m_nDefaultTempo = 80; m_nDefaultGlobalVolume = 256; - memcpy(m_szNames[0], pmh1->songname, 32); + memcpy(m_szNames[0], pmh1->songname, 31); // Channel Setting for (UINT nchpan=0; nchpan<16; nchpan++) { @@ -124,7 +124,7 @@ if (dwMemPos >= dwMemLength) return TRUE; // byteswap pattern data. - for(uint16 psfix = 256; psfix--;) + for(uint16 psfix = 0; psfix < 256; psfix++) { pmh2->patsiz[psfix] = LittleEndianW( pmh2->patsiz[psfix] ) ; } @@ -249,7 +249,7 @@ const FARSAMPLE *pfs = reinterpret_cast<const FARSAMPLE*>(lpStream + dwMemPos); dwMemPos += sizeof(FARSAMPLE); m_nSamples = ismp + 1; - memcpy(m_szNames[ismp+1], pfs->samplename, 32); + memcpy(m_szNames[ismp+1], pfs->samplename, 31); const DWORD length = LittleEndian( pfs->length ); pins->nLength = length; pins->nLoopStart = LittleEndian(pfs->reppos) ; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -600,6 +600,7 @@ // ChnSettings[i].szName memcpy(&ChnSettings[i].szName[0],lpStream+streamPos,len); + SetNullTerminator(ChnSettings[i].szName); streamPos += len; } @@ -647,6 +648,7 @@ for(i=0; i<m_nInstruments; i++){ ASSERT_CAN_READ(len); memcpy(&m_szInstrumentPath[i][0],lpStream+streamPos,len); + SetNullTerminator(m_szInstrumentPath[i]); streamPos += len; } @@ -1008,7 +1010,7 @@ if (m_nChannels < GetModSpecifications().channelsMin) m_nChannels = GetModSpecifications().channelsMin; // Reading Song Message - if ((pifh->special & 0x01) && (pifh->msglength) && (pifh->msgoffset + pifh->msglength < dwMemLength)) + if ((pifh->special & 0x01) && (pifh->msglength) && (pifh->msglength <= dwMemLength) && (pifh->msgoffset < dwMemLength - pifh->msglength)) { m_lpszSongComments = new char[pifh->msglength+1]; if (m_lpszSongComments) @@ -1759,6 +1761,7 @@ memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->name, 12); memcpy(itss.name, m_szNames[nsmp], 26); + SetNullTerminator(itss.name); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; @@ -2055,6 +2058,7 @@ memset(smpcount, 0, sizeof(smpcount)); memcpy(iti.filename, penv->filename, 12); memcpy(iti.name, penv->name, 26); + SetNullTerminator(iti.name); iti.mbank = penv->wMidiBank; iti.mpr = penv->nMidiProgram; iti.mch = penv->nMidiChannel; @@ -2372,6 +2376,7 @@ memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->name, 12); memcpy(itss.name, m_szNames[nsmp], 26); + SetNullTerminator(itss.name); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; if (m_nInstruments) @@ -2681,6 +2686,7 @@ memset(smpcount, 0, sizeof(smpcount)); memcpy(iti.filename, penv->filename, 12); memcpy(iti.name, penv->name, 26); + SetNullTerminator(iti.name); iti.mbank = penv->wMidiBank; iti.mpr = penv->nMidiProgram; iti.mch = penv->nMidiChannel; @@ -2988,6 +2994,7 @@ memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->name, 12); memcpy(itss.name, m_szNames[nsmp], 26); + SetNullTerminator(itss.name); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; if (m_nInstruments) Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -215,7 +215,7 @@ block = *((WORD *)(lpStream+dwMemPos)); blocklen = *((DWORD *)(lpStream+dwMemPos+2)); dwMemPos += 6; - if (dwMemPos + blocklen > dwMemLength) + if (blocklen > dwMemLength - dwMemPos) { if (dwMemPos == 11) return FALSE; break; @@ -228,7 +228,7 @@ Log("infoblock: %d bytes\n", blocklen); #endif pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); - memcpy(m_szNames[0], pmib->songname, 32); + memcpy(m_szNames[0], pmib->songname, 31); norders = pmib->norders; if (norders > MAX_ORDERS) norders = MAX_ORDERS; m_nRestartPos = pmib->repeatpos; @@ -328,6 +328,7 @@ INSTRUMENTHEADER *penv = Headers[nins]; memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, lpStream+dwPos+2, 32); + SetNullTerminator(penv->name); penv->nGlobalVol = 64; penv->nPPC = 5*12; SetDefaultInstrumentValues(penv); @@ -411,7 +412,7 @@ if ((nins >= MAX_SAMPLES) || (!nins)) continue; if (m_nSamples < nins) m_nSamples = nins; MODINSTRUMENT *pins = &Ins[nins]; - memcpy(m_szNames[nins], lpStream+dwPos+1, 32); + memcpy(m_szNames[nins], lpStream+dwPos+1, 31); memcpy(pins->name, lpStream+dwPos+33, 8); const BYTE *p = lpStream+dwPos+41; if (pmsh->version > 0) Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -699,9 +699,11 @@ UINT annotxt = BigEndian(pmex->annotxt); UINT annolen = BigEndian(pmex->annolen); annolen = min(annolen, MED_MAX_COMMENT_LENGTH); //Thanks to Luigi Auriemma for pointing out an overflow risk - if ((annotxt) && (annolen) && (annolen <= dwMemLength) && (annotxt <= dwMemLength - annolen) ) { + if ((annotxt) && (annolen) && (annolen <= dwMemLength) && (annotxt <= dwMemLength - annolen) ) + { m_lpszSongComments = new char[annolen+1]; - if (m_lpszSongComments) { + if (m_lpszSongComments) + { memcpy(m_lpszSongComments, lpStream+annotxt, annolen); m_lpszSongComments[annolen] = 0; } @@ -709,7 +711,7 @@ // Song Name UINT songname = BigEndian(pmex->songname); UINT songnamelen = BigEndian(pmex->songnamelen); - if ((songname) && (songnamelen) && (songname+songnamelen <= dwMemLength)) + if ((songname) && (songnamelen) && (songname <= dwMemLength) && (songnamelen <= dwMemLength-songname)) { if (songnamelen > 31) songnamelen = 31; memcpy(m_szNames[0], lpStream+songname, songnamelen); @@ -722,14 +724,14 @@ UINT ientries = BigEndianW(pmex->i_ext_entries); UINT ientrysz = BigEndianW(pmex->i_ext_entrsz); - if ((iinfoptr) && (ientrysz < 256) && (iinfoptr + ientries*ientrysz < dwMemLength)) + if ((iinfoptr) && (ientrysz < 256) && (ientries*ientrysz < dwMemLength) && (iinfoptr < dwMemLength - ientries*ientrysz)) { LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr); UINT maxnamelen = ientrysz; - if (maxnamelen > 32) maxnamelen = 32; + if (maxnamelen > 31) maxnamelen = 31; for (UINT i=0; i<ientries; i++) if (i < m_nSamples) { - lstrcpyn(m_szNames[i+1], psznames + i*ientrysz, maxnamelen); + memcpy(m_szNames[i+1], psznames + i*ientrysz, maxnamelen); } } } @@ -742,7 +744,7 @@ { DWORD trknameofs = 0, trknamelen = 0; DWORD trktagofs = BigEndian(ptrktags[i]); - if (trktagofs) + if (trktagofs && (trktagofs <= dwMemLength - 8) ) { while (trktagofs+8 < dwMemLength) { @@ -757,9 +759,10 @@ trktagofs += 8; } if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME; - if ((trknameofs) && (trknameofs + trknamelen < dwMemLength)) + if ((trknameofs) && (trknameofs < dwMemLength - trknamelen)) { - lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME); + memcpy(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME); + SetNullTerminator(ChnSettings[i].szName); } } } Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mt2.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -406,6 +406,7 @@ { memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, pmi->szName, 32); + SetNullTerminator(penv->name); penv->nGlobalVol = 64; penv->nPan = 128; for (UINT i=0; i<NOTE_MAX; i++) @@ -536,7 +537,7 @@ #endif if (iSmp < MAX_SAMPLES) { - memcpy(m_szNames[iSmp], pms->szName, 32); + memcpy(m_szNames[iSmp], pms->szName, 31); } if (pms->dwDataLen > 0) { Modified: trunk/OpenMPT/soundlib/Load_ult.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Load_ult.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -60,7 +60,7 @@ m_nType = MOD_TYPE_ULT; m_nDefaultSpeed = 6; m_nDefaultTempo = 125; - memcpy(m_szNames[0], pmh->songtitle, 32); + memcpy(m_szNames[0], pmh->songtitle, 31); // read songtext dwMemPos = sizeof(ULTHEADER); if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength)) @@ -89,7 +89,7 @@ { pus = (ULTSAMPLE *)(lpStream+dwMemPos); MODINSTRUMENT *pins = &Ins[ins]; - memcpy(m_szNames[ins], pus->samplename, 32); + memcpy(m_szNames[ins], pus->samplename, 31); memcpy(pins->name, pus->dosname, 12); pins->nLoopStart = pus->loopstart; pins->nLoopEnd = pus->loopend; Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2009-04-04 20:15:12 UTC (rev 254) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2009-05-01 14:12:28 UTC (rev 255) @@ -524,7 +524,7 @@ if ((dwInfoList+d+8+len <= dwFileLength) && (len)) { DWORD dwNameLen = len; - if (dwNameLen > 32) dwNameLen = 32; + if (dwNameLen > 31) dwNameLen = 31; memcpy(m_szNames[nSample], lpMemFile+dwInfoList+d+8, dwNameLen); if (phdr->id_RIFF != 0x46464952) { @@ -560,12 +560,13 @@ LPSTR pszTextEx = (LPSTR)(pxh+1); if (xtrabytes >= 32) { - memcpy(m_szNames[nSample], pszTextEx, 32); + memcpy(m_szNames[nSample], pszTextEx, 31); pszTextEx += 32; xtrabytes -= 32; if (xtrabytes >= 22) { memcpy(pins->name, pszTextEx, 22); + SetNullTerminator(pins->name); xtrabytes -= 22; } } @@ -1875,6 +1876,7 @@ iti->id = 0x49504D49; // "IMPI" memcpy(iti->filename, penv->filename, 12); memcpy(iti->name, penv->name, 26); + SetNullTerminator(iti->name); iti->mpr = penv->nMidiProgram; iti->mch = penv->nMidiChannel; iti->mbank = penv->wMidiBank; //rewbs.MidiBank @@ -2125,7 +2127,7 @@ case IFFID_NAME: { UINT len = dwChunkLen; - if (len > 32) len = 32; + if (len > 31) len = 31; memset(m_szNames[nSample], 0, 32); memcpy(m_szNames[nSample], pChunkData, len); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-04-04 20:15:26
|
Revision: 254 http://modplug.svn.sourceforge.net/modplug/?rev=254&view=rev Author: relabsoluness Date: 2009-04-04 20:15:12 +0000 (Sat, 04 Apr 2009) Log Message: ----------- (Patches from Jojo, merged slightly modified) + Sample tab: Can now normalize sample selections. . Envelope view: Middle line will now be drawn in panning and pitch/filter envelopes even if row guidelines are enabled. / PackageTemplate:: Update to DE_jojo-keymap Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/View_ins.cpp trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-04-04 19:09:48 UTC (rev 253) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-04-04 20:15:12 UTC (rev 254) @@ -1037,7 +1037,9 @@ //Default case: Normalize current sample UINT iMinSample = m_nSample, iMaxSample = m_nSample; - + //If only one sample is selected, parts of it may be amplified + UINT iStart = 0, iEnd = 0; + //Shift -> Normalize all samples if(CMainFrame::GetInputHandler()->ShiftPressed()) { @@ -1045,6 +1047,13 @@ if(ans == IDNO) return; iMinSample = 1; iMaxSample = m_pSndFile->m_nSamples; + } else { + SAMPLEVIEWSTATE viewstate; + memset(&viewstate, 0, sizeof(viewstate)); + SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&viewstate); + + iStart = viewstate.dwBeginSel; + iEnd = viewstate.dwEndSel; } @@ -1058,13 +1067,26 @@ BOOL bOk = FALSE; MODINSTRUMENT *pins = &m_pSndFile->Ins[iSmp]; + if(iMinSample != iMaxSample) { + //if more than one sample is selected, always amplify the whole sample. + iStart = 0; + iEnd = pins->nLength; + } else { + //one sample: correct the boundaries, if needed + if (iEnd > pins->nLength) iEnd = pins->nLength; + if (iStart > iEnd) iStart = iEnd; + if (iStart == iEnd) { + iStart = 0; + iEnd = pins->nLength; + } + } + if (pins->uFlags & CHN_STEREO) { iStart *= 2; iEnd *= 2; } + if (pins->uFlags & CHN_16BIT) { - UINT len = pins->nLength; signed short *p = (signed short *)pins->pSample; - if (pins->uFlags & CHN_STEREO) len *= 2; int max = 1; - for (UINT i=0; i<len; i++) + for (UINT i = iStart; i < iEnd; i++) { if (p[i] > max) max = p[i]; if (-p[i] > max) max = -p[i]; @@ -1072,7 +1094,7 @@ if (max < 32767) { max++; - for (UINT j=0; j<len; j++) + for (UINT j = iStart; j < iEnd; j++) { int l = p[j]; p[j] = (l << 15) / max; @@ -1081,11 +1103,9 @@ } } else { - UINT len = pins->nLength; signed char *p = (signed char *)pins->pSample; - if (pins->uFlags & CHN_STEREO) len *= 2; int max = 1; - for (UINT i=0; i<len; i++) + for (UINT i = iStart; i < iEnd; i++) { if (p[i] > max) max = p[i]; if (-p[i] > max) max = -p[i]; @@ -1093,7 +1113,7 @@ if (max < 127) { max++; - for (UINT j=0; j<len; j++) + for (UINT j = iStart; j < iEnd; j++) { int l = p[j]; p[j] = (l << 7) / max; Modified: trunk/OpenMPT/mptrack/View_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_ins.cpp 2009-04-04 19:09:48 UTC (rev 253) +++ trunk/OpenMPT/mptrack/View_ins.cpp 2009-04-04 20:15:12 UTC (rev 254) @@ -1268,15 +1268,15 @@ //hdc = pDC->m_hDC; oldpen = m_dcMemMain.SelectObject(CMainFrame::penDarkGray); m_dcMemMain.FillRect(&m_rcClient, CBrush::FromHandle(CMainFrame::brushBlack)); + if (m_bGrid) + { + DrawGrid(&m_dcMemMain, pSndFile->m_nMusicSpeed); + } if (m_nEnv != ENV_VOLUME) { m_dcMemMain.MoveTo(0, ymed); m_dcMemMain.LineTo(m_rcClient.right, ymed); } - if (m_bGrid) - { - DrawGrid(&m_dcMemMain, pSndFile->m_nMusicSpeed); - } m_dcMemMain.SelectObject(CMainFrame::penDarkGray); // Drawing Loop Start/End if (EnvGetLoop()) Modified: trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2009-04-04 19:09:48 UTC (rev 253) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2009-04-04 20:15:12 UTC (rev 254) @@ -6,6 +6,7 @@ //----( Global Context (0) )------------ 0:1347:2:78:1 //File/New: Ctrl+N (KeyDown) 0:1346:2:79:1 //File/Open: Ctrl+O (KeyDown) +0:1348:2:87:1 //File/Close: Ctrl+W (KeyDown) 0:1349:2:83:1 //File/Save: Ctrl+S (KeyDown) 0:1030:0:116:1 //Play song/Pause song: F5 (KeyDown) 0:1031:0:119:1 //Pause song: F8 (KeyDown) @@ -19,6 +20,7 @@ 0:1361:2:67:1 //Copy: Ctrl+C (KeyDown) 0:1361:2:45:1 //Copy: Ctrl+EINFG (KeyDown) 0:1362:2:86:1 //Paste: Ctrl+V (KeyDown) +0:1363:3:86:1 //Mix Paste: Shift+Ctrl+V (KeyDown) 0:1686:1:86:1 //Mix Paste (old IT Style): Shift+V (KeyDown) 0:1364:2:53:1 //SelectAll: Ctrl+5 (KeyDown) 0:1365:2:70:1 //Find: Ctrl+F (KeyDown) @@ -62,6 +64,7 @@ 2:1049:6:35:1 //Go to last row of last channel: Ctrl+Alt+ENDE (KeyDown) 2:1050:1:16:1 //Selection key: Shift+UMSCHALT (KeyDown) 2:1011:2:76:1 //Select channel / Select all: Ctrl+L (KeyDown) +2:1663:0:145:1 //Toggle follow song: ROLLEN-FESTSTELL (KeyDown) 2:1003:0:13:1 //Quick copy: EINGABE (KeyDown) 2:1004:0:32:5 //Quick paste: LEER (KeyDown|KeyHold) 2:1001:2:32:1 //Enable recording: Ctrl+LEER (KeyDown) @@ -79,10 +82,12 @@ 2:1014:2:74:1 //Interpolate volume: Ctrl+J (KeyDown) 2:1015:2:75:1 //Interpolate effect: Ctrl+K (KeyDown) 2:1016:4:66:1 //Open effect visualizer: Alt+B (KeyDown) +2:1766:2:71:1 //Go to row/channel/...: Ctrl+G (KeyDown) 2:1013:2:73:1 //Apply current instrument: Ctrl+I (KeyDown) 2:1660:4:69:5 //Grow selection: Alt+E (KeyDown|KeyHold) 2:1661:4:68:5 //Shrink selection: Alt+D (KeyDown|KeyHold) 2:1059:2:46:1 //Clear row and step: Ctrl+ENTF (KeyDown) +2:1060:1:46:1 //Clear field and step: Shift+ENTF (KeyDown) 2:1665:0:46:1 //Clear field and step (IT Style): ENTF (KeyDown) 2:1061:0:8:5 //Delete rows: R\xDCCK (KeyDown|KeyHold) 2:1377:2:8:5 //Delete all rows: Ctrl+R\xDCCK (KeyDown|KeyHold) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-04-04 19:09:52
|
Revision: 253 http://modplug.svn.sourceforge.net/modplug/?rev=253&view=rev Author: relabsoluness Date: 2009-04-04 19:09:48 +0000 (Sat, 04 Apr 2009) Log Message: ----------- / Small tweaks(ctrl_smp, setup dialog). Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-03-30 22:41:07 UTC (rev 252) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-04-04 19:09:48 UTC (rev 253) @@ -1665,7 +1665,7 @@ default: wsprintf(str,"Unknown Error..."); break; } - ::MessageBox(NULL,str,"Error",MB_ICONERROR); + AfxMessageBox(str, MB_ICONERROR); } // Update sample view @@ -1759,12 +1759,26 @@ MODINSTRUMENT *pins = &m_pSndFile->Ins[m_nSample]; if(!pins) return -1; + const uint32 nSampleRate = pins->GetSampleRate(m_pSndFile->GetType()); + + // SoundTouch(v1.4.0) documentation says that sample rates 8000-48000 are supported. + // Check whether sample rate is within that range, and if not, + // ask user whether to proceed. + if(nSampleRate < 8000 || nSampleRate > 48000) + { + CString str; + str.Format(TEXT(GetStrI18N("Current samplerate, %u Hz, is not in the supported samplerate range 8000 Hz - 48000 Hz. Continue?")), nSampleRate); + if(AfxMessageBox(str, MB_ICONQUESTION|MB_YESNO) != IDYES) + return -1; + + } + // Stretching is implemented only for 16-bit samples. Return with // error if trying to use wtih non 16-bit samples. if(pins->GetElementarySampleSize() != 2) return 4; - // SoundTouch seems to crash with short samples. Don't know what + // SoundTouch(1.3.1) seems to crash with short samples. Don't know what // the actual limit or whether it depends on sample rate, // but simply set some semiarbitrary threshold here. if(pins->nLength < 256) @@ -1832,7 +1846,6 @@ // Initialize soundtouch object. { - const uint32 nSampleRate = pins->GetSampleRate(m_pSndFile->GetType()); if(nSampleRate < 300) // Too low samplerate crashes soundtouch. { // Limiting it to value 300(quite arbitrarily chosen). delete pSoundTouch; @@ -2209,6 +2222,9 @@ memset(&viewstate, 0, sizeof(viewstate)); SendViewMessage(VIEWMSG_SAVESTATE, (LPARAM)&viewstate); if ((!m_pModDoc) || (!m_pSndFile) || (!m_pSndFile->Ins[m_nSample].pSample)) return; + if( AfxMessageBox(TEXT(GetStrI18N("Apply signed/unsigned conversion(distortion)?\n\n" + "Note: in many cases this increases volume level significantly.")), MB_YESNO|MB_ICONQUESTION) == IDNO ) + return; BeginWaitCursor(); pins = &m_pSndFile->Ins[m_nSample]; dwStart = viewstate.dwBeginSel; Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2009-03-30 22:41:07 UTC (rev 252) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2009-04-04 19:09:48 UTC (rev 253) @@ -283,7 +283,7 @@ else { m_PreAmpNoteShowed = true; - MessageBox(str_preampChangeNote, _TEXT(""), MB_ICONINFORMATION); + AfxMessageBox(str_preampChangeNote, MB_ICONINFORMATION); SetPreAmpSliderPosition(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-03-30 22:41:23
|
Revision: 252 http://modplug.svn.sourceforge.net/modplug/?rev=252&view=rev Author: relabsoluness Date: 2009-03-30 22:41:07 +0000 (Mon, 30 Mar 2009) Log Message: ----------- Instrument tuning related changes: . Creating 'group geometric' was broken. / Return-key won't now close the dialog. / Added index in front of note names. / groupsize and groupratio edits are now enabled with general types. Modified Paths: -------------- trunk/OpenMPT/mptrack/TuningDialog.cpp trunk/OpenMPT/mptrack/TuningDialog.h trunk/OpenMPT/mptrack/tuningRatioMapWnd.cpp trunk/OpenMPT/soundlib/tuningbase.cpp Modified: trunk/OpenMPT/mptrack/TuningDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/TuningDialog.cpp 2009-03-07 21:24:44 UTC (rev 251) +++ trunk/OpenMPT/mptrack/TuningDialog.cpp 2009-03-30 22:41:07 UTC (rev 252) @@ -273,8 +273,8 @@ } else //case: m_pActiveTuning is of type general. { - m_EditSteps.EnableWindow(false); - m_EditRatioPeriod.EnableWindow(false); + //m_EditSteps.EnableWindow(false); + //m_EditRatioPeriod.EnableWindow(false); } m_EditRatioPeriod.Invalidate(); @@ -1293,6 +1293,17 @@ } +void CTuningDialog::OnOK() +//------------------------ +{ + // Prevent return-key from closing the window. + if(GetKeyState(VK_RETURN) <= -127) + return; + else + CDialog::OnOK(); +} + + //////////////////////////////////////////////////////// //*************** //CTuningTreeCtrl Modified: trunk/OpenMPT/mptrack/TuningDialog.h =================================================================== --- trunk/OpenMPT/mptrack/TuningDialog.h 2009-03-07 21:24:44 UTC (rev 251) +++ trunk/OpenMPT/mptrack/TuningDialog.h 2009-03-30 22:41:07 UTC (rev 252) @@ -321,6 +321,7 @@ void DoErrorExit(); + virtual void OnOK(); //Treectrl context menu functions. public: Modified: trunk/OpenMPT/mptrack/tuningRatioMapWnd.cpp =================================================================== --- trunk/OpenMPT/mptrack/tuningRatioMapWnd.cpp 2009-03-07 21:24:44 UTC (rev 251) +++ trunk/OpenMPT/mptrack/tuningRatioMapWnd.cpp 2009-03-30 22:41:07 UTC (rev 252) @@ -64,9 +64,12 @@ const bool isValidNote = m_pTuning->IsValidNote(noteToDraw); string temp; - if(isValidNote) temp = m_pTuning->GetNoteName(noteToDraw); + if(isValidNote) + { + temp = "(" + Stringify(noteToDraw) + ") " + m_pTuning->GetNoteName(noteToDraw); + } - if(isValidNote && temp.size() < sizeofS) + if(isValidNote && temp.size()+1 < sizeofS) wsprintf(s, "%s", temp.c_str()); else wsprintf(s, "%s", "..."); Modified: trunk/OpenMPT/soundlib/tuningbase.cpp =================================================================== --- trunk/OpenMPT/soundlib/tuningbase.cpp 2009-03-07 21:24:44 UTC (rev 251) +++ trunk/OpenMPT/soundlib/tuningbase.cpp 2009-03-30 22:41:07 UTC (rev 252) @@ -431,7 +431,7 @@ return true; if(m_TuningType == TT_GROUPGEOMETRIC) - return CreateGroupGeometric(s, GetGroupRatio(), GetValidityRange().first); + return CreateGroupGeometric(s, GetGroupRatio(), 0); if(m_TuningType == TT_GEOMETRIC) return CreateGeometric(s, GetGroupRatio()); @@ -448,7 +448,7 @@ return true; if(m_TuningType == TT_GROUPGEOMETRIC) - return CreateGroupGeometric(GetGroupSize(), r, GetValidityRange().first); + return CreateGroupGeometric(GetGroupSize(), r, 0); if(m_TuningType == TT_GEOMETRIC) return CreateGeometric(GetGroupSize(), r); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-03-07 21:25:00
|
Revision: 251 http://modplug.svn.sourceforge.net/modplug/?rev=251&view=rev Author: relabsoluness Date: 2009-03-07 21:24:44 +0000 (Sat, 07 Mar 2009) Log Message: ----------- (Patch from Jojo, merged slightly modified) + Added descriptions of SBx, S3x, S4x and S5x command parameters to note properties dialog. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-02-14 19:45:18 UTC (rev 250) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-03-07 21:24:44 UTC (rev 251) @@ -2420,28 +2420,28 @@ if (param) wsprintf(s, "note+%d note+%d", param >> 4, param & 0x0F); else - wsprintf(s, "continue"); + strcpy(s, "continue"); break; case CMD_PORTAMENTOUP: if (param) wsprintf(s, "+%d", param); else - wsprintf(s, "continue"); + strcpy(s, "continue"); break; case CMD_PORTAMENTODOWN: if (param) wsprintf(s, "-%d", param); else - wsprintf(s, "continue"); + strcpy(s, "continue"); break; case CMD_TONEPORTAMENTO: if (param) wsprintf(s, "speed %d", param); else - wsprintf(s, "continue"); + strcpy(s, "continue"); break; case CMD_VIBRATO: @@ -2614,7 +2614,30 @@ { switch(param & 0xF0) { + case 0x30: + case 0x40: + case 0x50: + if(gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) + { + 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; + } + } + break; case 0x60: if (gFXInfo[ndx].dwEffect == CMD_MODCMDEX) break; + case 0xB0: + if (gFXInfo[ndx].dwEffect == CMD_S3MCMDEX) + { + if((param & 0x0F) == 0x00) + strcpy(s, "loop start"); + else + strcat(s, " times"); + } + break; case 0xC0: case 0xD0: strcat(s, " frames"); break; case 0xE0: strcat(s, " rows"); break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rel...@us...> - 2009-02-14 19:45:25
|
Revision: 250 http://modplug.svn.sourceforge.net/modplug/?rev=250&view=rev Author: relabsoluness Date: 2009-02-14 19:45:18 +0000 (Sat, 14 Feb 2009) Log Message: ----------- / SoundTouch: Updated to SoundTouch 1.4.0 Modified Paths: -------------- trunk/OpenMPT/soundtouch/3dnow_win.cpp trunk/OpenMPT/soundtouch/AAFilter.cpp trunk/OpenMPT/soundtouch/AAFilter.h trunk/OpenMPT/soundtouch/BPMDetect.h trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h trunk/OpenMPT/soundtouch/FIFOSamplePipe.h trunk/OpenMPT/soundtouch/FIRFilter.cpp trunk/OpenMPT/soundtouch/FIRFilter.h trunk/OpenMPT/soundtouch/README.html trunk/OpenMPT/soundtouch/RateTransposer.cpp trunk/OpenMPT/soundtouch/RateTransposer.h trunk/OpenMPT/soundtouch/STTypes.h trunk/OpenMPT/soundtouch/SoundTouch.cpp trunk/OpenMPT/soundtouch/SoundTouch.h trunk/OpenMPT/soundtouch/TDStretch.cpp trunk/OpenMPT/soundtouch/TDStretch.h trunk/OpenMPT/soundtouch/cpu_detect.h trunk/OpenMPT/soundtouch/cpu_detect_x86_win.cpp trunk/OpenMPT/soundtouch/mmx_optimized.cpp trunk/OpenMPT/soundtouch/soundtouch.vcproj trunk/OpenMPT/soundtouch/sse_optimized.cpp Added Paths: ----------- trunk/OpenMPT/soundtouch/BPMDetect.cpp trunk/OpenMPT/soundtouch/PeakFinder.cpp trunk/OpenMPT/soundtouch/PeakFinder.h Removed Paths: ------------- trunk/OpenMPT/soundtouch/soundtouch-1.3.1.zip Modified: trunk/OpenMPT/soundtouch/3dnow_win.cpp =================================================================== --- trunk/OpenMPT/soundtouch/3dnow_win.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/3dnow_win.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -24,7 +24,7 @@ /// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ /// 6.0 processor pack" update to support 3DNow! instruction set. The update is /// available for download at Microsoft Developers Network, see here: -/// http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx +/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx /// /// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and /// perform a search with keywords "processor pack". @@ -35,10 +35,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.10 $ +// Last changed : $Date: 2009-01-25 16:13:39 +0200 (Sun, 25 Jan 2009) $ +// File revision : $Revision: 4 $ // -// $Id: 3dnow_win.cpp,v 1.10 2006/02/05 16:44:06 Olli Exp $ +// $Id: 3dnow_win.cpp 51 2009-01-25 14:13:39Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -82,10 +82,10 @@ ////////////////////////////////////////////////////////////////////////////// #include "TDStretch.h" -#include <limits.h> +//#include <limits.h> // these are declared in 'TDStretch.cpp' -extern int scanOffsets[4][24]; +// extern int scanOffsets[4][24]; // Calculates cross correlation of two buffers @@ -181,12 +181,15 @@ FIRFilter3DNow::FIRFilter3DNow() : FIRFilter() { filterCoeffsUnalign = NULL; + filterCoeffsAlign = NULL; } FIRFilter3DNow::~FIRFilter3DNow() { delete[] filterCoeffsUnalign; + filterCoeffsUnalign = NULL; + filterCoeffsAlign = NULL; } @@ -203,7 +206,7 @@ // Ensure that filter coeffs array is aligned to 16-byte boundary delete[] filterCoeffsUnalign; filterCoeffsUnalign = new float[2 * newLength + 4]; - filterCoeffsAlign = (float *)(((uint)filterCoeffsUnalign + 15) & -16); + filterCoeffsAlign = (float *)(((uint)filterCoeffsUnalign + 15) & (uint)-16); fDivider = (float)resultDivider; @@ -217,10 +220,10 @@ // 3DNow!-optimized version of the filter routine for stereo sound -uint FIRFilter3DNow::evaluateFilterStereo(float *dest, const float *src, const uint numSamples) const +uint FIRFilter3DNow::evaluateFilterStereo(float *dest, const float *src, uint numSamples) const { float *filterCoeffsLocal = filterCoeffsAlign; - uint count = (numSamples - length) & -2; + uint count = (numSamples - length) & (uint)-2; uint lengthLocal = length / 4; assert(length != 0); Modified: trunk/OpenMPT/soundtouch/AAFilter.cpp =================================================================== --- trunk/OpenMPT/soundtouch/AAFilter.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/AAFilter.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -12,10 +12,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.9 $ +// Last changed : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $ +// File revision : $Revision: 4 $ // -// $Id: AAFilter.cpp,v 1.9 2006/02/05 16:44:06 Olli Exp $ +// $Id: AAFilter.cpp 45 2009-01-11 11:34:24Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -58,11 +58,11 @@ * *****************************************************************************/ -AAFilter::AAFilter(const uint length) +AAFilter::AAFilter(uint len) { pFIR = FIRFilter::newInstance(); cutoffFreq = 0.5; - setLength(length); + setLength(len); } @@ -77,7 +77,7 @@ // Sets new anti-alias filter cut-off edge frequency, scaled to // sampling frequency (nyquist frequency = 0.5). // The filter will cut frequencies higher than the given frequency. -void AAFilter::setCutoffFreq(const double newCutoffFreq) +void AAFilter::setCutoffFreq(double newCutoffFreq) { cutoffFreq = newCutoffFreq; calculateCoeffs(); @@ -86,7 +86,7 @@ // Sets number of FIR filter taps -void AAFilter::setLength(const uint newLength) +void AAFilter::setLength(uint newLength) { length = newLength; calculateCoeffs(); @@ -104,7 +104,7 @@ double *work; SAMPLETYPE *coeffs; - assert(length > 0); + assert(length >= 2); assert(length % 4 == 0); assert(cutoffFreq >= 0); assert(cutoffFreq <= 0.5); Modified: trunk/OpenMPT/soundtouch/AAFilter.h =================================================================== --- trunk/OpenMPT/soundtouch/AAFilter.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/AAFilter.h 2009-02-14 19:45:18 UTC (rev 250) @@ -13,10 +13,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.10 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: AAFilter.h,v 1.10 2006/02/05 16:44:06 Olli Exp $ +// $Id: AAFilter.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // Added: trunk/OpenMPT/soundtouch/BPMDetect.cpp =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.cpp (rev 0) +++ trunk/OpenMPT/soundtouch/BPMDetect.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,311 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Beats-per-minute (BPM) detection routine. +/// +/// The beat detection algorithm works as follows: +/// - Use function 'inputSamples' to input a chunks of samples to the class for +/// analysis. It's a good idea to enter a large sound file or stream in smallish +/// chunks of around few kilosamples in order not to extinguish too much RAM memory. +/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden, +/// which is basically ok as low (bass) frequencies mostly determine the beat rate. +/// Simple averaging is used for anti-alias filtering because the resulting signal +/// quality isn't of that high importance. +/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by +/// taking absolute value that's smoothed by sliding average. Signal levels that +/// are below a couple of times the general RMS amplitude level are cut away to +/// leave only notable peaks there. +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// autocorrelation function of the enveloped signal. +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// function, calculates it's precise location and converts this reading to bpm's. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: BPMDetect.cpp 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include <math.h> +#include <assert.h> +#include <string.h> +#include "FIFOSampleBuffer.h" +#include "PeakFinder.h" +#include "BPMDetect.h" + +using namespace soundtouch; + +#define INPUT_BLOCK_SAMPLES 2048 +#define DECIMATED_BLOCK_SAMPLES 256 + +typedef unsigned short ushort; + +/// decay constant for calculating RMS volume sliding average approximation +/// (time constant is about 10 sec) +const float avgdecay = 0.99986f; + +/// Normalization coefficient for calculating RMS sliding average approximation. +const float avgnorm = (1 - avgdecay); + + + +BPMDetect::BPMDetect(int numChannels, int sampleRate) +{ + xcorr = NULL; + + buffer = new FIFOSampleBuffer(); + + decimateSum = 0; + decimateCount = 0; + decimateBy = 0; + + this->sampleRate = sampleRate; + this->channels = numChannels; + + envelopeAccu = 0; + + // Initialize RMS volume accumulator to RMS level of 3000 (out of 32768) that's + // a typical RMS signal level value for song data. This value is then adapted + // to the actual level during processing. +#ifdef INTEGER_SAMPLES + // integer samples + RMSVolumeAccu = (3000 * 3000) / avgnorm; +#else + // float samples, scaled to range [-1..+1[ + RMSVolumeAccu = (0.092f * 0.092f) / avgnorm; +#endif + + init(numChannels, sampleRate); +} + + + +BPMDetect::~BPMDetect() +{ + delete[] xcorr; + delete buffer; +} + + +/// low-pass filter & decimate to about 500 Hz. return number of outputted samples. +/// +/// Decimation is used to remove the unnecessary frequencies and thus to reduce +/// the amount of data needed to be processed as calculating autocorrelation +/// function is a very-very heavy operation. +/// +/// Anti-alias filtering is done simply by averaging the samples. This is really a +/// poor-man's anti-alias filtering, but it's not so critical in this kind of application +/// (it'd also be difficult to design a high-quality filter with steep cut-off at very +/// narrow band) +int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples) +{ + int count, outcount; + LONG_SAMPLETYPE out; + + assert(decimateBy != 0); + outcount = 0; + for (count = 0; count < numsamples; count ++) + { + decimateSum += src[count]; + + decimateCount ++; + if (decimateCount >= decimateBy) + { + // Store every Nth sample only + out = (LONG_SAMPLETYPE)(decimateSum / decimateBy); + decimateSum = 0; + decimateCount = 0; +#ifdef INTEGER_SAMPLES + // check ranges for sure (shouldn't actually be necessary) + if (out > 32767) + { + out = 32767; + } + else if (out < -32768) + { + out = -32768; + } +#endif // INTEGER_SAMPLES + dest[outcount] = (SAMPLETYPE)out; + outcount ++; + } + } + return outcount; +} + + + +// Calculates autocorrelation function of the sample history buffer +void BPMDetect::updateXCorr(int process_samples) +{ + int offs; + SAMPLETYPE *pBuffer; + + assert(buffer->numSamples() >= (uint)(process_samples + windowLen)); + + pBuffer = buffer->ptrBegin(); + for (offs = windowStart; offs < windowLen; offs ++) + { + LONG_SAMPLETYPE sum; + int i; + + sum = 0; + for (i = 0; i < process_samples; i ++) + { + sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary + } +// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients + // if it's desired that the system adapts automatically to + // various bpms, e.g. in processing continouos music stream. + // The 'xcorr_decay' should be a value that's smaller than but + // close to one, and should also depend on 'process_samples' value. + + xcorr[offs] += (float)sum; + } +} + + + +// Calculates envelope of the sample data +void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples) +{ + const float decay = 0.7f; // decay constant for smoothing the envelope + const float norm = (1 - decay); + + int i; + LONG_SAMPLETYPE out; + float val; + + for (i = 0; i < numsamples; i ++) + { + // calc average RMS volume + RMSVolumeAccu *= avgdecay; + val = (float)fabs((float)samples[i]); + RMSVolumeAccu += val * val; + + // cut amplitudes that are below 2 times average RMS volume + // (we're interested in peak values, not the silent moments) + val -= 2 * (float)sqrt(RMSVolumeAccu * avgnorm); + val = (val > 0) ? val : 0; + + // smooth amplitude envelope + envelopeAccu *= decay; + envelopeAccu += val; + out = (LONG_SAMPLETYPE)(envelopeAccu * norm); + +#ifdef INTEGER_SAMPLES + // cut peaks (shouldn't be necessary though) + if (out > 32767) out = 32767; +#endif // INTEGER_SAMPLES + samples[i] = (SAMPLETYPE)out; + } +} + + + +void BPMDetect::inputSamples(SAMPLETYPE *samples, int numSamples) +{ + SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES]; + + // convert from stereo to mono if necessary + if (channels == 2) + { + int i; + + for (i = 0; i < numSamples; i ++) + { + samples[i] = (samples[i * 2] + samples[i * 2 + 1]) / 2; + } + } + + // decimate + numSamples = decimate(decimated, samples, numSamples); + + // envelope new samples and add them to buffer + calcEnvelope(decimated, numSamples); + buffer->putSamples(decimated, numSamples); + + // when the buffer has enought samples for processing... + if ((int)buffer->numSamples() > windowLen) + { + int processLength; + + // how many samples are processed + processLength = buffer->numSamples() - windowLen; + + // ... calculate autocorrelations for oldest samples... + updateXCorr(processLength); + // ... and remove them from the buffer + buffer->receiveSamples(processLength); + } +} + + +void BPMDetect::init(int numChannels, int sampleRate) +{ + this->sampleRate = sampleRate; + + // choose decimation factor so that result is approx. 500 Hz + decimateBy = sampleRate / 500; + assert(decimateBy > 0); + assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES); + + // Calculate window length & starting item according to desired min & max bpms + windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); + windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM); + + assert(windowLen > windowStart); + + // allocate new working objects + xcorr = new float[windowLen]; + memset(xcorr, 0, windowLen * sizeof(float)); + + // we do processing in mono mode + buffer->setChannels(1); + buffer->clear(); +} + + + +float BPMDetect::getBpm() +{ + double peakPos; + PeakFinder peakFinder; + + // find peak position + peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen); + + assert(decimateBy != 0); + if (peakPos < 1e-6) return 0.0; // detection failed. + + // calculate BPM + return (float)(60.0 * (((double)sampleRate / (double)decimateBy) / peakPos)); +} Modified: trunk/OpenMPT/soundtouch/BPMDetect.h =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/BPMDetect.h 2009-02-14 19:45:18 UTC (rev 250) @@ -26,10 +26,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.5 $ +// Last changed : $Date: 2008-12-25 14:20:01 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ // -// $Id: BPMDetect.h,v 1.5 2006/02/05 16:44:06 Olli Exp $ +// $Id: BPMDetect.h 33 2008-12-25 12:20:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -60,8 +60,11 @@ #include "STTypes.h" #include "FIFOSampleBuffer.h" +namespace soundtouch +{ + /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit. -#define MIN_BPM 45 +#define MIN_BPM 29 /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit. #define MAX_BPM 230 @@ -156,4 +159,6 @@ float getBpm(); }; +} + #endif // _BPMDetect_H_ Modified: trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.11 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.cpp,v 1.11 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIFOSampleBuffer.cpp 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -54,14 +54,15 @@ using namespace soundtouch; // Constructor -FIFOSampleBuffer::FIFOSampleBuffer(uint numChannels) +FIFOSampleBuffer::FIFOSampleBuffer(int numChannels) { + assert(numChannels > 0); sizeInBytes = 0; // reasonable initial value - buffer = NULL; //new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE)]; + buffer = NULL; bufferUnaligned = NULL; samplesInBuffer = 0; bufferPos = 0; - channels = numChannels; + channels = (uint)numChannels; } @@ -69,16 +70,19 @@ FIFOSampleBuffer::~FIFOSampleBuffer() { delete[] bufferUnaligned; + bufferUnaligned = NULL; + buffer = NULL; } // Sets number of channels, 1 = mono, 2 = stereo -void FIFOSampleBuffer::setChannels(const uint numChannels) +void FIFOSampleBuffer::setChannels(int numChannels) { uint usedBytes; + assert(numChannels > 0); usedBytes = channels * samplesInBuffer; - channels = numChannels; + channels = (uint)numChannels; samplesInBuffer = usedBytes / channels; } @@ -88,7 +92,7 @@ // location on to the beginning of the buffer. void FIFOSampleBuffer::rewind() { - if (bufferPos) + if (buffer && bufferPos) { memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); bufferPos = 0; @@ -98,10 +102,10 @@ // Adds 'numSamples' pcs of samples from the 'samples' memory position to // the sample buffer. -void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint numSamples) +void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples) { - memcpy(ptrEnd(numSamples), samples, sizeof(SAMPLETYPE) * numSamples * channels); - samplesInBuffer += numSamples; + memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels); + samplesInBuffer += nSamples; } @@ -111,13 +115,13 @@ // This function is used to update the number of samples in the sample buffer // when accessing the buffer directly with 'ptrEnd' function. Please be // careful though! -void FIFOSampleBuffer::putSamples(uint numSamples) +void FIFOSampleBuffer::putSamples(uint nSamples) { uint req; - req = samplesInBuffer + numSamples; + req = samplesInBuffer + nSamples; ensureCapacity(req); - samplesInBuffer += numSamples; + samplesInBuffer += nSamples; } @@ -164,14 +168,14 @@ if (capacityRequirement > getCapacity()) { // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) - sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & -4096; + sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; assert(sizeInBytes % 2 == 0); tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; if (tempUnaligned == NULL) { throw std::runtime_error("Couldn't allocate memory!\n"); } - temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & -16); + temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16); memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); delete[] bufferUnaligned; buffer = temp; Modified: trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h 2009-02-14 19:45:18 UTC (rev 250) @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.9 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.h,v 1.9 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIFOSampleBuffer.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -85,7 +85,7 @@ void rewind(); /// Ensures that the buffer has capacity for at least this many samples. - void ensureCapacity(const uint capacityRequirement); + void ensureCapacity(uint capacityRequirement); /// Returns current capacity. uint getCapacity() const; @@ -93,7 +93,7 @@ public: /// Constructor - FIFOSampleBuffer(uint numChannels = 2 ///< Number of channels, 1=mono, 2=stereo. + FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo. ///< Default is stereo. ); @@ -160,7 +160,7 @@ virtual uint numSamples() const; /// Sets number of channels, 1 = mono, 2 = stereo. - void setChannels(uint numChannels); + void setChannels(int numChannels); /// Returns nonzero if there aren't any samples available for outputting. virtual int isEmpty() const; Modified: trunk/OpenMPT/soundtouch/FIFOSamplePipe.h =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSamplePipe.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSamplePipe.h 2009-02-14 19:45:18 UTC (rev 250) @@ -26,11 +26,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.8 $ // -// $Id: FIFOSamplePipe.h,v 1.8 2006/02/05 16:44:06 Olli Exp $ -// //////////////////////////////////////////////////////////////////////////////// // // License : @@ -81,7 +77,7 @@ /// Adds 'numSamples' pcs of samples from the 'samples' memory position to /// the sample buffer. virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples. - uint numSamples ///< Number of samples to insert. + uint numSamples ///< Number of samples to insert. ) = 0; Modified: trunk/OpenMPT/soundtouch/FIRFilter.cpp =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIRFilter.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -20,11 +20,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.16 $ // -// $Id: FIRFilter.cpp,v 1.16 2006/02/05 16:44:06 Olli Exp $ -// //////////////////////////////////////////////////////////////////////////////// // // License : @@ -67,6 +63,7 @@ FIRFilter::FIRFilter() { resultDivFactor = 0; + resultDivider = 0; length = 0; lengthDiv8 = 0; filterCoeffs = NULL; @@ -90,6 +87,9 @@ #endif assert(length != 0); + assert(src != NULL); + assert(dest != NULL); + assert(filterCoeffs != NULL); end = 2 * (numSamples - length); @@ -186,8 +186,8 @@ assert(length == newLength); resultDivFactor = uResultDivFactor; - //OpenMPT_change--> Fix to ambiguous pow(). - //resultDivider = (SAMPLETYPE)pow(2, resultDivFactor); + //OpenMPT_change--> + //resultDivider = (SAMPLETYPE)::pow(2, resultDivFactor); resultDivider = (1 << resultDivFactor); // == 2^resultDivFactor //<-- @@ -215,7 +215,6 @@ assert(length > 0); assert(lengthDiv8 * 8 == length); if (numSamples < length) return 0; - assert(resultDivFactor >= 0); if (numChannels == 2) { return evaluateFilterStereo(dest, src, numSamples); @@ -231,7 +230,7 @@ void * FIRFilter::operator new(size_t s) { // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! - throw std::runtime_error("Don't use 'new FIRFilter', use 'newInstance' member instead!"); + throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); return NULL; } Modified: trunk/OpenMPT/soundtouch/FIRFilter.h =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIRFilter.h 2009-02-14 19:45:18 UTC (rev 250) @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.17 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIRFilter.h,v 1.17 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIRFilter.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -77,7 +77,7 @@ /// Operator 'new' is overloaded so that it automatically creates a suitable instance /// depending on if we've a MMX-capable CPU available or not. - void * operator new(size_t s); + static void * operator new(size_t s); static FIRFilter *newInstance(); Added: trunk/OpenMPT/soundtouch/PeakFinder.cpp =================================================================== --- trunk/OpenMPT/soundtouch/PeakFinder.cpp (rev 0) +++ trunk/OpenMPT/soundtouch/PeakFinder.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,236 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Peak detection routine. +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.cpp 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include <math.h> +#include <assert.h> + +#include "PeakFinder.h" + +using namespace soundtouch; + +#define max(x, y) (((x) > (y)) ? (x) : (y)) + + +PeakFinder::PeakFinder() +{ +} + + +// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding +// to direction defined by 'direction' until next 'hump' after minimum value will +// begin +int PeakFinder::findGround(const float *data, int peakpos, int direction) const +{ + float refvalue; + int lowpos; + int pos; + int climb_count; + float delta; + + climb_count = 0; + refvalue = data[peakpos]; + lowpos = peakpos; + + pos = peakpos; + + while ((pos > minPos) && (pos < maxPos)) + { + int prevpos; + + prevpos = pos; + pos += direction; + + // calculate derivate + delta = data[pos] - data[prevpos]; + if (delta <= 0) + { + // going downhill, ok + if (climb_count) + { + climb_count --; // decrease climb count + } + + // check if new minimum found + if (data[pos] < refvalue) + { + // new minimum found + lowpos = pos; + refvalue = data[pos]; + } + } + else + { + // going uphill, increase climbing counter + climb_count ++; + if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit + } + } + return lowpos; +} + + +// Find offset where the value crosses the given level, when starting from 'peakpos' and +// proceeds to direction defined in 'direction' +int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const +{ + float peaklevel; + int pos; + + peaklevel = data[peakpos]; + assert(peaklevel >= level); + pos = peakpos; + while ((pos >= minPos) && (pos < maxPos)) + { + if (data[pos + direction] < level) return pos; // crossing found + pos += direction; + } + return -1; // not found +} + + +// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos' +double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const +{ + int i; + float sum; + float wsum; + + sum = 0; + wsum = 0; + for (i = firstPos; i <= lastPos; i ++) + { + sum += (float)i * data[i]; + wsum += data[i]; + } + return sum / wsum; +} + + + +/// get exact center of peak near given position by calculating local mass of center +double PeakFinder::getPeakCenter(const float *data, int peakpos) +{ + float peakLevel; // peak level + int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level + float cutLevel; // cutting value + float groundLevel; // ground level of the peak + int gp1, gp2; // bottom positions of the peak 'hump' + + // find ground positions. + gp1 = findGround(data, peakpos, -1); + gp2 = findGround(data, peakpos, 1); + + groundLevel = max(data[gp1], data[gp2]); + peakLevel = data[peakpos]; + + if (groundLevel < 1e-6) return 0; // ground level too small => detection failed + if ((peakLevel / groundLevel) < 1.3) return 0; // peak less than 30% of the ground level => no good peak detected + + // calculate 70%-level of the peak + cutLevel = 0.70f * peakLevel + 0.30f * groundLevel; + // find mid-level crossings + crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1); + crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1); + + if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak.. + + // calculate mass center of the peak surroundings + return calcMassCenter(data, crosspos1, crosspos2); +} + + + +double PeakFinder::detectPeak(const float *data, int minPos, int maxPos) +{ + + int i; + int peakpos; // position of peak level + double highPeak, peak; + + this->minPos = minPos; + this->maxPos = maxPos; + + // find absolute peak + peakpos = minPos; + peak = data[minPos]; + for (i = minPos + 1; i < maxPos; i ++) + { + if (data[i] > peak) + { + peak = data[i]; + peakpos = i; + } + } + + // Calculate exact location of the highest peak mass center + highPeak = getPeakCenter(data, peakpos); + peak = highPeak; + + // Now check if the highest peak were in fact harmonic of the true base beat peak + // - sometimes the highest peak can be Nth harmonic of the true base peak yet + // just a slightly higher than the true base + for (i = 2; i < 10; i ++) + { + double peaktmp, tmp; + int i1,i2; + + peakpos = (int)(highPeak / (double)i + 0.5f); + if (peakpos < minPos) break; + + // calculate mass-center of possible base peak + peaktmp = getPeakCenter(data, peakpos); + + // now compare to highest detected peak + i1 = (int)(highPeak + 0.5); + i2 = (int)(peaktmp + 0.5); + tmp = 2 * (data[i2] - data[i1]) / (data[i2] + data[i1]); + if (fabs(tmp) < 0.1) + { + // The highest peak is harmonic of almost as high base peak, + // thus use the base peak instead + peak = peaktmp; + } + } + + return peak; +} + + Added: trunk/OpenMPT/soundtouch/PeakFinder.h =================================================================== --- trunk/OpenMPT/soundtouch/PeakFinder.h (rev 0) +++ trunk/OpenMPT/soundtouch/PeakFinder.h 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.h 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _PeakFinder_H_ +#define _PeakFinder_H_ + +namespace soundtouch +{ + +class PeakFinder +{ +protected: + /// Min, max allowed peak positions within the data vector + int minPos, maxPos; + + /// Calculates the mass center between given vector items. + double calcMassCenter(const float *data, ///< Data vector. + int firstPos, ///< Index of first vector item beloging to the peak. + int lastPos ///< Index of last vector item beloging to the peak. + ) const; + + /// Finds the data vector index where the monotoniously decreasing signal crosses the + /// given level. + int findCrossingLevel(const float *data, ///< Data vector. + float level, ///< Goal crossing level. + int peakpos, ///< Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right- + /// or left-hand side of the given peak position. + int findGround(const float *data, /// Data vector. + int peakpos, /// Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// get exact center of peak near given position by calculating local mass of center + double getPeakCenter(const float *data, int peakpos); + +public: + /// Constructor. + PeakFinder(); + + /// Detect exact peak position of the data vector by finding the largest peak 'hump' + /// and calculating the mass-center location of the peak hump. + /// + /// \return The location of the largest base harmonic peak hump. + double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has + /// to be at least 'maxPos' items long. + int minPos, ///< Min allowed peak location within the vector data. + int maxPos ///< Max allowed peak location within the vector data. + ); +}; + +} + +#endif // _PeakFinder_H_ Modified: trunk/OpenMPT/soundtouch/README.html =================================================================== --- trunk/OpenMPT/soundtouch/README.html 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/README.html 2009-02-14 19:45:18 UTC (rev 250) @@ -18,14 +18,13 @@ </head> <body class="normal"> <hr> -<font color=red><h4>NOTE: SoundTouch used with OpenMPT is slightly modified version. - The file soundtouch-1.3.1.zip, and this readme excluding this - note, are the original SoundTouch files. +<font color=red><h4>Note: Some of the SoundTouch files included in OpenMPT repository are modified versions +of the original SoundTouch files. This readme, excluding this note, is the original SoundTouch readme. </h4></font> -<h1>SoundTouch audio processing library v1.3.1 +<h1>SoundTouch audio processing library v1.4.0 </h1> <p class="normal">SoundTouch library Copyright (c) Olli -Parviainen 2002-2006 </p> +Parviainen 2002-2009 </p> <hr> <h2>1. Introduction </h2> <p>SoundTouch is an open-source audio @@ -51,37 +50,27 @@ for more information.</p> <h3>2.1. Building in Microsoft Windows</h3> <p>Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are -supplied with the source code package. Please notice that SoundTouch +supplied with the source code package. </p> +<p> Please notice that SoundTouch library uses processor-specific optimizations for Pentium III and AMD -processors that require a processor pack upgrade for -the Visual Studio 6.0 to be installed in order to support these -optimizations. The processor pack upgrade can be downloaded from +processors. Visual Studio .NET and later versions supports the required +instructions by default, but Visual Studio 6.0 requires a processor pack upgrade +to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from Microsoft site at this URL:</p> -<p><a - href="http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx"> -http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx</a></p> +<p><a href="http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx">http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx</a></p> <p>If the above URL is unavailable or removed, go to <a href="http://msdn.microsoft.com/">http://msdn.microsoft.com</a> -and perform a search with keywords processor pack. </p> -<p>Visual Studio .NET supports required -instructions by default and thus doesn't require installing the -processor pack.</p> -<p>To build the binaries with Visual C++ 6.0 -compiler, either run "make-win.bat" script or open the +and perform a search with keywords "processor pack". </p> +<p>To build the binaries with Visual C++ +compiler, either run "make-win.bat" script, or open the appropriate project files in source code directories with Visual Studio. The final executable will appear under the "SoundTouch\bin" directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and -lib have to be created manually to the SoundTouch +lib may need to be created manually to the SoundTouch package root for the final executables. The make-win.bat script creates these directories automatically. </p> -<p>Also other C++ compilers than Visual C++ can be -used, but project or makefiles then have to be adapted accordingly. -Performance optimizations are written in Visual C++ compatible -syntax, they may or may not be compatible with other compilers. If -using GCC (Gnu C Compiler) compiler package such as DJGPP or Cygwin, -please see next chapter for instructions. </p> <h3>2.2. Building in Gnu platforms</h3> <p>The SoundTouch library can be compiled in practically any platform supporting GNU compiler (GCC) tools. @@ -91,7 +80,7 @@ x86 platforms only, they are automatically disabled and replaced with standard C routines in other processor platforms.</p> <p>To build and install the binaries, run the -following commands in SoundTouch/ directory:</p> +following commands in the SoundTouch/ directory:</p> <table border="0" cellpadding="0" cellspacing="4"> <tbody> <tr valign="top"> @@ -125,14 +114,13 @@ </tr> </tbody> </table> -<p><b>NOTE:</b> At the time of release the SoundTouch package has been +<p><b>NOTE:</b> At the release time the SoundTouch package has been tested to compile in GNU/Linux platform. However, in past it's happened that new gcc versions aren't necessarily compatible with the assembler setttings used in the optimized routines. <b>If you have problems getting the -SoundTouch library compiled, try the workaround of disabling the -optimizations</b> by editing the file "include/STTypes.h" and removing +SoundTouch library compiled, try the workaround of disabling the optimizations</b> by editing the file "include/STTypes.h" and removing the following definition there:</p> <blockquote> <pre>#define ALLOW_OPTIMIZATIONS 1</pre> @@ -146,7 +134,7 @@ <p> In Windows environment, the sample data format is chosen -in file "STTypes.h" by choosing one of the following +in file "STTypes.h" by choosing one of the following defines:</p> <ul> <li><span style="font-weight: bold;">#define INTEGER_SAMPLES</span> @@ -171,7 +159,7 @@ recommended because processing the channels separately would result in losing the phase coherency between the channels, which consequently would ruin the stereo effect.</p> -<p>Sample rates between 8000-48000Hz are +<p>Sample rates between 8000-48000H are supported.</p> <h3>3.2. Processing latency</h3> <p>The processing and latency constraints of @@ -183,8 +171,8 @@ requirement is much shorter, see section 'About algorithms'.</li> <li>Processing CD-quality sound (16bit stereo -sound with 44100Hz sample rate) in real-time or faster is possible -starting from processors equivalent to Intel Pentium 133Mhz or better, +sound with 44100H sample rate) in real-time or faster is possible +starting from processors equivalent to Intel Pentium 133Mh or better, if using the "quick" processing algorithm. If not using the "quick" mode or if floating point sample data are being used, several times more CPU @@ -198,8 +186,7 @@ <p><em>Sample rate transposing</em> affects both the audio stream duration and pitch. It's implemented simply by converting the original audio sample stream to the desired -duration by interpolating from the original audio samples. In -SoundTouch, linear interpolation with anti-alias filtering is +duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is used. Theoretically a higher-order interpolation provide better result than 1st order linear interpolation, but in audio application linear interpolation together with anti-alias @@ -240,10 +227,10 @@ sound the default parameter set may result into a sub-optimal result.</p> <p>The time-stretch algorithm default -parameter values are set by these #defines in file "TDStretch.h":</p> +parameter values are set by these #defines in file "TDStretch.h":</p> <blockquote> - <pre>#define DEFAULT_SEQUENCE_MS 82 -#define DEFAULT_SEEKWINDOW_MS 28 + <pre>#define DEFAULT_SEQUENCE_MS AUTOMATIC +#define DEFAULT_SEEKWINDOW_MS AUTOMATIC #define DEFAULT_OVERLAP_MS 12</pre> </blockquote> <p>These parameters affect to the time-stretch @@ -255,13 +242,16 @@ the time-stretch algorithm. Larger values mean fewer sequences are used in processing. In principle a larger value sounds better when slowing down the tempo, but worse when increasing the tempo and vice -versa.<br> +versa. <br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_SEEKWINDOW_MS</strong>: The seeking window default length in milliseconds is for the algorithm that seeks the best possible overlapping location. This determines from how wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together.<br> +location when the sound sequences are to be linked back together. <br> <br> The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may @@ -269,6 +259,9 @@ chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting.<br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_OVERLAP_MS</strong>: Overlap length in milliseconds. When the sound sequences are mixed back @@ -282,7 +275,7 @@ <p>Notice that these parameters can also be set during execution time with functions "<strong>TDStretch::setParameters()</strong>" and "<strong>SoundTouch::setSetting()</strong>".</p> -<p>The table below summarizes how the +<p>The table below summaries how the parameters can be adjusted for different applications:</p> <table border="1"> <tbody> @@ -294,9 +287,7 @@ affects...</strong></td> <td valign="top"><strong>Smaller value affects...</strong></td> - <td valign="top"><strong>Music</strong></td> - <td valign="top"><strong>Speech</strong></td> - <td valign="top"><strong>Effect in CPU burden</strong></td> + <td valign="top"><strong>Effect to CPU burden</strong></td> </tr> <tr> <td valign="top"> @@ -310,9 +301,6 @@ <td valign="top">Smaller value might be better for speeding up tempo. Reducing the value accelerates the "echoing" artifact when slowing down the tempo </td> - <td valign="top">Default value usually good</td> - <td valign="top">A smaller value than default -might be better</td> <td valign="top">Increasing the parameter value reduces computation burden</td> </tr> @@ -326,9 +314,6 @@ good mixing position, but may cause a "drifting" artifact</td> <td valign="top">Smaller reduce possibility to find a good mixing position, but reduce the "drifting" artifact.</td> - <td valign="top">Default value usually good, -unless a "drifting" artifact is disturbing.</td> - <td valign="top">Default value usually good</td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> @@ -341,8 +326,6 @@ <td valign="top"> </td> <td valign="top">If you reduce the "sequence ms" setting, you might wish to try a smaller value.</td> - <td valign="top"> </td> - <td valign="top"> </td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> @@ -361,13 +344,11 @@ <p><strong>CPU-specific optimizations:</strong></p> <ul> <li>Intel MMX optimized routines are used with -compatible CPUs when 16bit integer sample type is used. MMX -optimizations are available both in Win32 and Gnu/x86 platforms. +compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms. Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon and later. </li> <li>Intel SSE optimized routines are used with -compatible CPUs when floating point sample type is used. SSE -optimizations are currently implemented for Win32 platform only. +compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. Processors compatible with SSE extension are Intel processors starting from Pentium-III, and AMD processors starting from Athlon XP. </li> <li>AMD 3DNow! optimized routines are used with @@ -377,41 +358,67 @@ AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are used with AMD processor starting from Athlon XP. </li> </ul> +<h3>3.6 GNU compilation issues </h3> +<h4><b>3.6.1 Required GNU tools</b> </h4> +<p> Bash shell, GNU C++ compiler, libtool, autoconf and automake tools are required +for compiling +the SoundTouch library. These are usually included with the GNU/Linux distribution, but if +not, install these packages first. For example, in Ubuntu Linux these can be acquired and +installed with the following command:</p> +<pre><b>sudo apt-get install <font SIZE="2">automake autoconf libtool build-essential</font></b></pre> +<h4><b>3.6.2 Problems with configure script or build process</b> </h4> +<p>Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source +codes, if your GNU tool versions are not compatible with the versions used for +preparing the SoundTouch kit. </p> +<p>To resolve the issue, regenerate the configure scripts with your local tool +set by running +the "<b>./bootstrap</b>" script included in the SoundTouch source code +kit. After that, run the <b>configure</b> script and <b>make</b> as usually.</p> +<h4><b>3.6.3 Compiler issues with non-x86 processors</b></h4> +<p>SoundTouch library works also on non-x86 processors.</p> +<p>However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file +"<b>source\SoundTouch\Makefile.am</b>" and remove the "<b>-msse2</b>" +flag on the <b>AM_CXXFLAGS </b>line:</p> +<pre><b>AM_CXXFLAGS=-O3 -fcheck-new -I../../include # Note: -msse2 flag removed!</b></pre> +<p>After that, run "<b>./bootstrap</b>" script, and then run <b>configure</b> +and <b>make</b> again.</p> <hr> <h2><a name="SoundStretch"></a>4. SoundStretch audio processing utility </h2> <p>SoundStretch audio processing utility<br> -Copyright (c) Olli Parviainen 2002-2005</p> +Copyright (c) Olli Parviainen 2002-2009</p> <p>SoundStretch is a simple command-line application that can change tempo, pitch and playback rates of WAV sound files. This program is intended primarily to -demonstrate how the "SoundTouch" library can be used to +demonstrate how the "SoundTouch" library can be used to process sound in your own program, but it can as well be used for processing sound files.</p> <h3>4.1. SoundStretch Usage Instructions</h3> <p>SoundStretch Usage syntax:</p> <blockquote> - <pre>soundstretch infile.wav outfile.wav [switches]</pre> + <pre>soundstretch infilename outfilename [switches]</pre> </blockquote> <p>Where: </p> <table border="0" cellpadding="2" width="100%"> <tbody> <tr> <td valign="top"> - <pre>"infile.wav"</pre> + <pre>"infilename"</pre> </td> - <td valign="top">is the name of the input sound -data file (in .WAV audio file format). </td> + <td valign="top">Name of the input sound +data file (in .WAV audio file format). Give "stdin" as filename to use + standard input pipe. </td> </tr> <tr> <td valign="top"> - <pre>"outfile.wav"</pre> + <pre>"outfilename"</pre> </td> - <td valign="top">is the name of the output sound + <td valign="top">Name of the output sound file where the resulting sound is saved (in .WAV audio file format). This parameter may be omitted if you don't want to save the output -(e.g. when only calculating BPM rate with '-bpm' switch).</td> +(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout" + as filename to use standard output pipe.</td> </tr> <tr> <td valign="top"> @@ -450,11 +457,11 @@ <td valign="top"> <pre>-bpm=n</pre> </td> - <td valign="top">Detect the Beats-Per-Minute -(BPM) rate of the sound and adjust the tempo to meet 'n' BPMs. If this -switch is defined, the "-tempo=n" switch value is ignored. If "=n" is -omitted, i.e. switch "-bpm" is used alone, the program just calculates -and displays the BPM rate but doesn't adjust tempo according to the BPM + <td valign="top">Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n' + BPMs. When this switch is + applied, the "-tempo" switch is ignored. If "=n" is +omitted, i.e. switch "-bpm" is used alone, then the BPM rate is + estimated and displayed, but tempo not adjusted according to the BPM value. </td> </tr> <tr> @@ -483,57 +490,69 @@ </table> <p>Notes:</p> <ul> - <li>The numerical switch values can be entered -using either integer (e.g. "-tempo=123") or decimal (e.g. + <li>To use standard input/output pipes for processing, give "stdin" + and "stdout" as input/output filenames correspondingly. The + standard input/output pipes will still carry the audio data in .wav audio + file format.</li> + <li>The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g. "-tempo=123.45") numbers.</li> <li>The "-naa" and/or "-quick" switches can be used to reduce CPU usage while compromising some sound quality </li> <li>The BPM detection algorithm works by detecting -repeating low-frequency (<250Hz) sound patterns and thus works -mostly with most rock/pop music with bass or drum beat. The BPM -detection doesn't work on pieces such as classical music without -distinct, repeating bass frequency patterns. Also pieces with varying -tempo, varying bass patterns or very complex bass patterns (jazz, hiphop) may produce odd BPM readings. <br> - <br> -In cases when the bass pattern drifts a bit around a nominal beat rate -(e.g. drummer is again drunken :), the BPM algorithm may report -incorrect harmonic one-halft to one-thirdth of the correct BPM value; -in such case the system could for example report BPM value of 50 or 100 -instead of correct BPM value of 150. </li> +repeating bass or drum patterns at low frequencies of <250Hz. A + lower-than-expected BPM figure may be reported for music with uneven or + complex bass patterns. </li> </ul> <h3>4.2. SoundStretch usage examples </h3> <p><strong>Example 1</strong></p> <p>The following command increases tempo of -the sound file "originalfile.wav" by 12.5% and saves -result to file "destinationfile.wav":</p> +the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":</p> <blockquote> <pre>soundstretch originalfile.wav destinationfile.wav -tempo=12.5</pre> </blockquote> <p><strong>Example 2</strong></p> <p>The following command decreases the sound pitch (key) of the sound file "orig.wav" by two -semitones and saves the result to file "dest.wav":</p> +semitones and stores the result to file "dest.wav":</p> <blockquote> <pre>soundstretch orig.wav dest.wav -pitch=-2</pre> </blockquote> <p><strong>Example 3</strong></p> <p>The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and -increasing the sound pitch (key) by 1.5 semitones. Result is -saved to file "dest.wav":</p> +increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is +directed to standard output pipe:</p> <blockquote> - <pre>soundstretch orig.wav dest.wav -tempo=-25.3 -pitch=1.5</pre> + <pre>soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5</pre> </blockquote> <p><strong>Example 4</strong></p> <p>The following command detects the BPM rate of the file "orig.wav" and adjusts the tempo to match -100 beats per minute. Result is saved to file "dest.wav":</p> +100 beats per minute. Result is stored to file "dest.wav":</p> <blockquote> <pre>soundstretch orig.wav dest.wav -bpm=100</pre> </blockquote> +<p><strong>Example 5</strong></p> +<p>The following command reads .wav sound data from standard input pipe and +estimates the BPM rate:</p> +<blockquote> + <pre>soundstretch stdin -bpm</pre> +</blockquote> <hr> <h2>5. Change History</h2> <h3>5.1. SoundTouch library Change History </h3> +<p><strong>1.4.0:</strong></p> +<ul> +<li>Improved sound quality by automatic calculation of time stretch algorithm + processing parameters according to tempo settin... [truncated message content] |
From: <rel...@us...> - 2009-02-14 16:22:12
|
Revision: 249 http://modplug.svn.sourceforge.net/modplug/?rev=249&view=rev Author: relabsoluness Date: 2009-02-14 16:22:07 +0000 (Sat, 14 Feb 2009) Log Message: ----------- (Patch from Jojo, merged somewhat modified) + Can now optionally normalize all samples instead of just one (click normalize with shift down) Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/mptrack.rc Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-01-29 20:46:51 UTC (rev 248) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2009-02-14 16:22:07 UTC (rev 249) @@ -1032,63 +1032,88 @@ void CCtrlSamples::OnNormalize() //------------------------------ { + if(!m_pModDoc || !m_pSndFile) + return; + + //Default case: Normalize current sample + UINT iMinSample = m_nSample, iMaxSample = m_nSample; + + //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; + iMinSample = 1; + iMaxSample = m_pSndFile->m_nSamples; + } + + BeginWaitCursor(); - if ((m_pModDoc) && (m_pSndFile) && (m_pSndFile->Ins[m_nSample].pSample)) + BOOL bModified = FALSE; + + for(UINT iSmp = iMinSample; iSmp <= iMaxSample; iSmp++) { - BOOL bOk = FALSE; - MODINSTRUMENT *pins = &m_pSndFile->Ins[m_nSample]; - - if (pins->uFlags & CHN_16BIT) + if (m_pSndFile->Ins[iSmp].pSample) { - UINT len = pins->nLength; - signed short *p = (signed short *)pins->pSample; - if (pins->uFlags & CHN_STEREO) len *= 2; - int max = 1; - for (UINT i=0; i<len; i++) + BOOL bOk = FALSE; + MODINSTRUMENT *pins = &m_pSndFile->Ins[iSmp]; + + if (pins->uFlags & CHN_16BIT) { - if (p[i] > max) max = p[i]; - if (-p[i] > max) max = -p[i]; - } - if (max < 32767) + UINT len = pins->nLength; + signed short *p = (signed short *)pins->pSample; + if (pins->uFlags & CHN_STEREO) len *= 2; + int max = 1; + for (UINT i=0; i<len; i++) + { + if (p[i] > max) max = p[i]; + if (-p[i] > max) max = -p[i]; + } + if (max < 32767) + { + max++; + for (UINT j=0; j<len; j++) + { + int l = p[j]; + p[j] = (l << 15) / max; + } + bModified = bOk = TRUE; + } + } else { - max++; - for (UINT j=0; j<len; j++) + UINT len = pins->nLength; + signed char *p = (signed char *)pins->pSample; + if (pins->uFlags & CHN_STEREO) len *= 2; + int max = 1; + for (UINT i=0; i<len; i++) { - int l = p[j]; - p[j] = (l << 15) / max; + if (p[i] > max) max = p[i]; + if (-p[i] > max) max = -p[i]; } - bOk = TRUE; + if (max < 127) + { + max++; + for (UINT j=0; j<len; j++) + { + int l = p[j]; + p[j] = (l << 7) / max; + } + bModified = bOk = TRUE; + } } - } else - { - UINT len = pins->nLength; - signed char *p = (signed char *)pins->pSample; - if (pins->uFlags & CHN_STEREO) len *= 2; - int max = 1; - for (UINT i=0; i<len; i++) + + if (bOk) { - if (p[i] > max) max = p[i]; - if (-p[i] > max) max = -p[i]; + m_pModDoc->AdjustEndOfSample(iSmp); + m_pModDoc->UpdateAllViews(NULL, (iSmp << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); } - if (max < 127) - { - max++; - for (UINT j=0; j<len; j++) - { - int l = p[j]; - p[j] = (l << 7) / max; - } - bOk = TRUE; - } } - if (bOk) - { - m_pModDoc->AdjustEndOfSample(m_nSample); - // 05/01/05 : ericus replaced "m_nSample << 24" by "m_nSample << 20" : 4000 samples -> 12bits [see Moddoc.h] - m_pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); - m_pModDoc->SetModified(); - } } + + if(bModified) + { + m_pModDoc->SetModified(); + } EndWaitCursor(); SwitchToView(); } Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-01-29 20:46:51 UTC (rev 248) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-02-14 16:22:07 UTC (rev 249) @@ -2421,7 +2421,7 @@ IDC_SAMPLE_NEW "Create a new sample\nNew Sample" IDC_SAMPLE_OPEN "Load sample from disk\nImport sample" IDC_SAMPLE_SAVEAS "Save the current sample to disk\nSave sample" - IDC_SAMPLE_NORMALIZE "Normalize the current sample (full scale)\nNormalize" + IDC_SAMPLE_NORMALIZE "Normalize the current sample (full scale)\nNormalize (hold shift to normalize all samples)" IDC_SAMPLE_AMPLIFY "Amplify selection\nAmplify" IDC_SAMPLE_UPSAMPLE "Stretch selection\nUpsample" IDC_SAMPLE_REVERSE "Reverse selection\nReverse" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |