From: <man...@us...> - 2014-02-01 13:50:53
|
Revision: 3601 http://sourceforge.net/p/modplug/code/3601 Author: manxorist Date: 2014-02-01 13:50:38 +0000 (Sat, 01 Feb 2014) Log Message: ----------- Merged branches/floatmixer-loopfix-new: New floatmixer + loop fix branch, based on the current HEAD revisions with further fixes and improvements. [New] Removed ugly macro-based mixer by template-based mixer with both support for integer and floating point mixing. (FP mixer doesn't compile yet) [Fix] Interpolation around loop points is now handled correctly (at least at the loop end). [Ref] One more table documentation, and an unused removed extern Modified Paths: -------------- trunk/OpenMPT/common/typedefs.h trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Undo.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/sounddsp/EQ.cpp trunk/OpenMPT/sounddsp/EQ.h trunk/OpenMPT/sounddsp/Reverb.cpp trunk/OpenMPT/sounddsp/Reverb.h trunk/OpenMPT/soundlib/AudioReadTarget.h trunk/OpenMPT/soundlib/Dither.cpp trunk/OpenMPT/soundlib/Dlsbank.cpp trunk/OpenMPT/soundlib/Fastmix.cpp trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Load_wav.cpp trunk/OpenMPT/soundlib/MixerLoops.cpp trunk/OpenMPT/soundlib/MixerLoops.h trunk/OpenMPT/soundlib/ModChannel.h trunk/OpenMPT/soundlib/ModSample.cpp trunk/OpenMPT/soundlib/ModSample.h trunk/OpenMPT/soundlib/Resampler.h trunk/OpenMPT/soundlib/SampleFormatConverters.h trunk/OpenMPT/soundlib/SampleFormats.cpp trunk/OpenMPT/soundlib/SampleIO.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Snd_flt.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp trunk/OpenMPT/soundlib/SoundFilePlayConfig.cpp trunk/OpenMPT/soundlib/Tables.cpp trunk/OpenMPT/soundlib/WindowedFIR.cpp trunk/OpenMPT/soundlib/WindowedFIR.h trunk/OpenMPT/soundlib/modsmp_ctrl.cpp trunk/OpenMPT/soundlib/modsmp_ctrl.h trunk/OpenMPT/soundlib/plugins/PlugInterface.h Added Paths: ----------- trunk/OpenMPT/soundlib/FloatMixer.h trunk/OpenMPT/soundlib/IntMixer.h trunk/OpenMPT/soundlib/Mixer.h trunk/OpenMPT/soundlib/MixerInterface.h Property Changed: ---------------- trunk/OpenMPT/ Index: trunk/OpenMPT =================================================================== --- trunk/OpenMPT 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT 2014-02-01 13:50:38 UTC (rev 3601) Property changes on: trunk/OpenMPT ___________________________________________________________________ Modified: svn:mergeinfo ## -1,3 +1,4 ## +/branches/floatmixer-loopfix-new:3572-3600 /branches/manx/build-speedup:1586-1589 /branches/manx/gcc-fixes:2018-2022,2024-2048,2052-2071,2075-2077,2080,2087-2089 /branches/manx/header-dependencies-cleanups:1394-1397,1401-1402,1405-1406 \ No newline at end of property Modified: trunk/OpenMPT/common/typedefs.h =================================================================== --- trunk/OpenMPT/common/typedefs.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/common/typedefs.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -94,6 +94,15 @@ +// Use MPT_RESTRICT to indicate that a pointer is guaranteed to not be aliased. +#if MPT_COMPILER_MSVC || MPT_COMPILER_GCC || MPT_COMPILER_CLANG +#define MPT_RESTRICT __restrict +#else +#define MPT_RESTRICT +#endif + + + // Some functions might be deprecated although they are still in use. // Tag them with "MPT_DEPRECATED". #if MPT_COMPILER_MSVC Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-02-01 13:50:38 UTC (rev 3601) @@ -202,12 +202,16 @@ <ClInclude Include="..\soundlib\Dlsbank.h" /> <ClInclude Include="..\soundlib\Endianness.h" /> <ClInclude Include="..\soundlib\FileReader.h" /> + <ClInclude Include="..\soundlib\FloatMixer.h" /> + <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> <ClInclude Include="..\soundlib\ITTools.h" /> <ClInclude Include="..\soundlib\Loaders.h" /> <ClInclude Include="..\soundlib\Message.h" /> <ClInclude Include="..\soundlib\MIDIEvents.h" /> <ClInclude Include="..\soundlib\MIDIMacros.h" /> + <ClInclude Include="..\soundlib\Mixer.h" /> + <ClInclude Include="..\soundlib\MixerInterface.h" /> <ClInclude Include="..\soundlib\MixerLoops.h" /> <ClInclude Include="..\soundlib\MixerSettings.h" /> <ClInclude Include="..\soundlib\ModChannel.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-02-01 13:50:38 UTC (rev 3601) @@ -245,6 +245,18 @@ <ClInclude Include="libopenmpt_ext.hpp"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\soundlib\FloatMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\IntMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\Mixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\MixerInterface.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-02-01 13:50:38 UTC (rev 3601) @@ -210,12 +210,16 @@ <ClInclude Include="..\soundlib\Dlsbank.h" /> <ClInclude Include="..\soundlib\Endianness.h" /> <ClInclude Include="..\soundlib\FileReader.h" /> + <ClInclude Include="..\soundlib\FloatMixer.h" /> + <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> <ClInclude Include="..\soundlib\ITTools.h" /> <ClInclude Include="..\soundlib\Loaders.h" /> <ClInclude Include="..\soundlib\Message.h" /> <ClInclude Include="..\soundlib\MIDIEvents.h" /> <ClInclude Include="..\soundlib\MIDIMacros.h" /> + <ClInclude Include="..\soundlib\Mixer.h" /> + <ClInclude Include="..\soundlib\MixerInterface.h" /> <ClInclude Include="..\soundlib\MixerLoops.h" /> <ClInclude Include="..\soundlib\MixerSettings.h" /> <ClInclude Include="..\soundlib\ModChannel.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-02-01 13:50:38 UTC (rev 3601) @@ -251,6 +251,18 @@ <ClInclude Include="libopenmpt_ext.hpp"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\soundlib\FloatMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\IntMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\Mixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\MixerInterface.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-02-01 13:50:38 UTC (rev 3601) @@ -206,12 +206,16 @@ <ClInclude Include="..\soundlib\Dlsbank.h" /> <ClInclude Include="..\soundlib\Endianness.h" /> <ClInclude Include="..\soundlib\FileReader.h" /> + <ClInclude Include="..\soundlib\FloatMixer.h" /> + <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> <ClInclude Include="..\soundlib\ITTools.h" /> <ClInclude Include="..\soundlib\Loaders.h" /> <ClInclude Include="..\soundlib\Message.h" /> <ClInclude Include="..\soundlib\MIDIEvents.h" /> <ClInclude Include="..\soundlib\MIDIMacros.h" /> + <ClInclude Include="..\soundlib\Mixer.h" /> + <ClInclude Include="..\soundlib\MixerInterface.h" /> <ClInclude Include="..\soundlib\MixerLoops.h" /> <ClInclude Include="..\soundlib\MixerSettings.h" /> <ClInclude Include="..\soundlib\ModChannel.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-02-01 13:50:38 UTC (rev 3601) @@ -245,6 +245,18 @@ <ClInclude Include="libopenmpt_ext.hpp"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\soundlib\FloatMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\IntMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\Mixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\MixerInterface.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -805,6 +805,7 @@ sample.filename[0] = '\0'; m_sndFile.m_szNames[m_nSample][0] = '\0'; if(!sample.nC5Speed) sample.nC5Speed = 22050; + sample.PrecomputeLoops(m_sndFile, false); } else { m_modDoc.GetSampleUndo().Undo(m_nSample); @@ -1204,7 +1205,7 @@ if (bOk) { - m_modDoc.AdjustEndOfSample(iSmp); + sample.PrecomputeLoops(m_sndFile, false); m_modDoc.UpdateAllViews(NULL, (iSmp << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); } } @@ -1261,7 +1262,7 @@ p[i] = (signed char)l; } } - m_modDoc.AdjustEndOfSample(m_nSample); + sample.PrecomputeLoops(m_sndFile, false); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); m_modDoc.SetModified(); EndWaitCursor(); @@ -1413,7 +1414,7 @@ pOriginal = sample.pSample; dwNewLen = sample.nLength + (dwEnd - dwStart); pNewSample = NULL; - if (dwNewLen + 4 <= MAX_SAMPLE_LENGTH) pNewSample = CSoundFile::AllocateSample((dwNewLen + 4)*newsmplsize); + if (dwNewLen <= MAX_SAMPLE_LENGTH) pNewSample = ModSample::AllocateSample(dwNewLen, newsmplsize); if (pNewSample) { m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); @@ -1467,7 +1468,7 @@ } } } - if (sample.uFlags & CHN_16BIT) + if (sample.uFlags[CHN_16BIT]) { if (dwStart > 0) memcpy(pNewSample, pOriginal, dwStart*smplsize); if (dwEnd < sample.nLength) memcpy(((LPSTR)pNewSample)+(dwStart+(dwEnd-dwStart)*2)*smplsize, ((LPSTR)pOriginal)+(dwEnd*smplsize), (sample.nLength-dwEnd)*smplsize); @@ -1500,6 +1501,9 @@ sample.uFlags.set(CHN_16BIT); ctrlSmp::ReplaceSample(sample, (LPSTR)pNewSample, dwNewLen, m_sndFile); + // Update loop wrap-around buffer + sample.PrecomputeLoops(m_sndFile); + if(!selection.selectionActive) { if(!(m_sndFile.GetType() & MOD_TYPE_MOD)) @@ -1507,10 +1511,7 @@ if(sample.nC5Speed < 1000000) sample.nC5Speed *= 2; if(sample.RelativeTone < 84) sample.RelativeTone += 12; } - } - - m_modDoc.AdjustEndOfSample(m_nSample); - if (selection.selectionActive == true) + } else { SetSelectionPoints(dwStart, dwEnd + (dwEnd - dwStart)); } @@ -1549,7 +1550,7 @@ dwNewLen = sample.nLength - dwRemove; dwEnd = dwStart+dwRemove*2; pNewSample = NULL; - if ((dwNewLen > 32) && (dwRemove)) pNewSample = CSoundFile::AllocateSample((dwNewLen + 4) * smplsize); + if ((dwNewLen >= 4) && (dwRemove)) pNewSample = ModSample::AllocateSample(dwNewLen, smplsize); if (pNewSample) { @@ -1616,6 +1617,9 @@ if (sample.nSustainEnd > dwNewLen) sample.nSustainEnd = dwNewLen; ctrlSmp::ReplaceSample(sample, (LPSTR)pNewSample, dwNewLen, m_sndFile); + // Update loop wrap-around buffer + sample.PrecomputeLoops(m_sndFile); + if(!selection.selectionActive) { if(!(m_sndFile.GetType() & MOD_TYPE_MOD)) @@ -1623,10 +1627,7 @@ if(sample.nC5Speed > 2000) sample.nC5Speed /= 2; if(sample.RelativeTone > -84) sample.RelativeTone -= 12; } - } - - m_modDoc.AdjustEndOfSample(m_nSample); - if (selection.selectionActive == true) + } else { SetSelectionPoints(dwStart, dwStart + dwRemove); } @@ -1724,10 +1725,19 @@ //Update loop points only if no error occured. if(errorcode == 0) { - sample.nLoopStart = (UINT)MIN(sample.nLoopStart * (m_dTimeStretchRatio / 100.0), sample.nLength); - sample.nLoopEnd = (UINT)MIN(sample.nLoopEnd * (m_dTimeStretchRatio/100.0), sample.nLength); - sample.nSustainStart = (UINT)MIN(sample.nSustainStart * (m_dTimeStretchRatio/100.0), sample.nLength); - sample.nSustainEnd = (UINT)MIN(sample.nSustainEnd * (m_dTimeStretchRatio/100.0), sample.nLength); + // Update loop wrap-around buffer + sample.SetLoop( + static_cast<SmpLength>(sample.nLoopStart * (m_dTimeStretchRatio / 100.0)), + static_cast<SmpLength>(sample.nLoopEnd * (m_dTimeStretchRatio / 100.0)), + sample.uFlags[CHN_LOOP], + sample.uFlags[CHN_PINGPONGLOOP], + m_sndFile); + sample.SetSustainLoop( + static_cast<SmpLength>(sample.nSustainStart * (m_dTimeStretchRatio / 100.0)), + static_cast<SmpLength>(sample.nSustainEnd * (m_dTimeStretchRatio / 100.0)), + sample.uFlags[CHN_SUSTAINLOOP], + sample.uFlags[CHN_PINGPONGSUSTAIN], + m_sndFile); } } @@ -1851,7 +1861,7 @@ void *pNewSample = nullptr; if(nNewSampleLength <= MAX_SAMPLE_LENGTH) { - pNewSample = CSoundFile::AllocateSample(nNewSampleLength * nChn * smpsize); + pNewSample = ModSample::AllocateSample(nNewSampleLength, nChn * smpsize); } if(pNewSample == nullptr) { @@ -2270,7 +2280,7 @@ p[i] = (signed char)n; } } - m_modDoc.AdjustEndOfSample(m_nSample); + sample.PrecomputeLoops(m_sndFile, false); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); m_modDoc.SetModified(); } @@ -2559,23 +2569,25 @@ ModSample &sample = m_sndFile.GetSample(m_nSample); bool wasDisabled = !sample.uFlags[CHN_LOOP]; - // 0: Off, 1: On, 2: PingPong + // Loop type index: 0: Off, 1: On, 2: PingPong sample.uFlags.set(CHN_LOOP, n > 0); sample.uFlags.set(CHN_PINGPONGLOOP, n == 2); // set loop points if theren't any - if(wasDisabled && ((sample.uFlags & CHN_LOOP) != 0) && (sample.nLoopStart == sample.nLoopEnd) && (sample.nLoopStart == 0)) + if(wasDisabled && sample.uFlags[CHN_LOOP] && sample.nLoopStart == sample.nLoopEnd) { SampleSelectionPoints selection = GetSelectionPoints(); if(selection.selectionActive) { - sample.nLoopStart = selection.nStart; - sample.nLoopEnd = selection.nEnd; + sample.SetLoop(selection.nStart, selection.nEnd, true, n == 2, m_sndFile); } else { - sample.nLoopEnd = sample.nLength; + sample.SetLoop(0, sample.nLength, true, n == 2, m_sndFile); } m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO, NULL); + } else + { + sample.PrecomputeLoops(m_sndFile); } ctrlSmp::UpdateLoopPoints(sample, m_sndFile); m_modDoc.SetModified(); @@ -2590,8 +2602,7 @@ SmpLength n = GetDlgItemInt(IDC_EDIT1); if ((n >= 0) && (n < sample.nLength) && ((n < sample.nLoopEnd) || !sample.uFlags[CHN_LOOP])) { - sample.nLoopStart = n; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.SetLoop(n, sample.nLoopEnd, sample.uFlags[CHN_LOOP], sample.uFlags[CHN_PINGPONGLOOP], m_sndFile); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, this); m_modDoc.SetModified(); } @@ -2606,8 +2617,7 @@ SmpLength n = GetDlgItemInt(IDC_EDIT2); if ((n >= 0) && (n <= sample.nLength) && ((n > sample.nLoopStart) || !sample.uFlags[CHN_LOOP])) { - sample.nLoopEnd = n; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.SetLoop(sample.nLoopStart, n, sample.uFlags[CHN_LOOP], sample.uFlags[CHN_PINGPONGLOOP], m_sndFile); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, this); m_modDoc.SetModified(); } @@ -2622,24 +2632,26 @@ ModSample &sample = m_sndFile.GetSample(m_nSample); bool wasDisabled = !sample.uFlags[CHN_SUSTAINLOOP]; - // 0: Off, 1: On, 2: PingPong + // Loop type index: 0: Off, 1: On, 2: PingPong sample.uFlags.set(CHN_SUSTAINLOOP, n > 0); sample.uFlags.set(CHN_PINGPONGSUSTAIN, n == 2); // set sustain loop points if theren't any - if(wasDisabled && ((sample.uFlags & CHN_SUSTAINLOOP) != 0) && (sample.nSustainStart == sample.nSustainEnd) && (sample.nSustainStart == 0)) + if(wasDisabled && sample.uFlags[CHN_SUSTAINLOOP] && sample.nSustainStart == sample.nSustainEnd) { SampleSelectionPoints selection = GetSelectionPoints(); if(selection.selectionActive) { - sample.nSustainStart = selection.nStart; - sample.nSustainEnd = selection.nEnd; + sample.SetSustainLoop(selection.nStart, selection.nEnd, true, n == 2, m_sndFile); } else { - sample.nSustainEnd = sample.nLength; + sample.SetSustainLoop(0, sample.nLength, true, n == 2, m_sndFile); } m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO, NULL); + } else + { + sample.PrecomputeLoops(m_sndFile); } ctrlSmp::UpdateLoopPoints(sample, m_sndFile); m_modDoc.SetModified(); @@ -2655,8 +2667,7 @@ if ((n >= 0) && (n <= sample.nLength) && ((n < sample.nSustainEnd) || !sample.uFlags[CHN_SUSTAINLOOP])) { - sample.nSustainStart = n; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.SetSustainLoop(n, sample.nSustainEnd, sample.uFlags[CHN_SUSTAINLOOP], sample.uFlags[CHN_PINGPONGSUSTAIN], m_sndFile); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, this); m_modDoc.SetModified(); } @@ -2672,8 +2683,7 @@ if ((n >= 0) && (n <= sample.nLength) && ((n > sample.nSustainStart) || !sample.uFlags[CHN_SUSTAINLOOP])) { - sample.nSustainEnd = n; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.SetSustainLoop(sample.nSustainStart, n, sample.uFlags[CHN_SUSTAINLOOP], sample.uFlags[CHN_PINGPONGSUSTAIN], m_sndFile); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, this); m_modDoc.SetModified(); } @@ -2786,9 +2796,8 @@ { wsprintf(s, "%u", sample.nLoopStart); m_EditLoopStart.SetWindowText(s); - m_modDoc.AdjustEndOfSample(m_nSample); redraw = true; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.PrecomputeLoops(m_sndFile); } m_SpinLoopStart.SetPos(0); } @@ -2831,9 +2840,8 @@ { wsprintf(s, "%u", sample.nLoopEnd); m_EditLoopEnd.SetWindowText(s); - m_modDoc.AdjustEndOfSample(m_nSample); redraw = true; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.PrecomputeLoops(m_sndFile); } m_SpinLoopEnd.SetPos(0); } @@ -2878,7 +2886,7 @@ wsprintf(s, "%u", sample.nSustainStart); m_EditSustainStart.SetWindowText(s); redraw = true; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.PrecomputeLoops(m_sndFile); } m_SpinSustainStart.SetPos(0); } @@ -2922,7 +2930,7 @@ wsprintf(s, "%u", sample.nSustainEnd); m_EditSustainEnd.SetWindowText(s); redraw = true; - ctrlSmp::UpdateLoopPoints(sample, m_sndFile); + sample.PrecomputeLoops(m_sndFile); } m_SpinSustainEnd.SetPos(0); } Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -484,6 +484,9 @@ CriticalSection cs; m_SndFile.ChangeModTypeTo(nNewType); + // In case we need to update IT bidi loop handling pre-computation or loops got changed... + m_SndFile.PrecomputeSampleLoops(false); + // Song flags if(!(CSoundFile::GetModSpecifications(nNewType).songFlags & SONG_LINEARSLIDES) && m_SndFile.m_SongFlags[SONG_LINEARSLIDES]) { Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Moddoc.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -308,7 +308,6 @@ CHANNELINDEX GetNumChannels() const { return m_SndFile.m_nChannels; } UINT GetPatternSize(PATTERNINDEX nPat) const; - BOOL AdjustEndOfSample(UINT nSample); bool IsChildSample(INSTRUMENTINDEX nIns, SAMPLEINDEX nSmp) const; INSTRUMENTINDEX FindSampleParent(SAMPLEINDEX sample) const; UINT FindInstrumentChild(UINT nIns) const; Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -322,23 +322,24 @@ for(SAMPLEINDEX i = 0; i < newNumSamples; i++) { const SAMPLEINDEX origSlot = newOrder[i]; + ModSample &target = m_SndFile.GetSample(i + 1); if(origSlot > 0 && origSlot <= oldNumSamples) { // Copy an original sample. - m_SndFile.GetSample(i + 1) = sampleHeaders[origSlot]; + target = sampleHeaders[origSlot]; if(--sampleCount[origSlot] > 0 && sampleHeaders[origSlot].pSample != nullptr) { // This sample slot is referenced multiple times, so we have to copy the actual sample. - m_SndFile.GetSample(i + 1).pSample = m_SndFile.AllocateSample(m_SndFile.GetSample(i + 1).GetSampleSizeInBytes()); - memcpy(m_SndFile.GetSample(i + 1).pSample, sampleHeaders[origSlot].pSample, m_SndFile.GetSample(i + 1).GetSampleSizeInBytes()); - ctrlSmp::AdjustEndOfSample(m_SndFile.GetSample(i + 1), m_SndFile); + target.pSample = ModSample::AllocateSample(target.nLength, target.GetSampleSizeInBytes()); + memcpy(target.pSample, sampleHeaders[origSlot].pSample, target.GetSampleSizeInBytes()); + target.PrecomputeLoops(m_SndFile, false); } strcpy(m_SndFile.m_szNames[i + 1], sampleNames[origSlot].c_str()); } else { // Invalid sample reference. - m_SndFile.GetSample(i + 1).Initialize(m_SndFile.GetType()); - m_SndFile.GetSample(i + 1).pSample = nullptr; + target.Initialize(m_SndFile.GetType()); + target.pSample = nullptr; strcpy(m_SndFile.m_szNames[i + 1], ""); } } @@ -583,19 +584,6 @@ } -BOOL CModDoc::AdjustEndOfSample(UINT nSample) -//------------------------------------------- -{ - if (nSample >= MAX_SAMPLES) return FALSE; - ModSample &sample = m_SndFile.GetSample(nSample); - if ((!sample.nLength) || (!sample.pSample)) return FALSE; - - ctrlSmp::AdjustEndOfSample(sample, m_SndFile); - - return TRUE; -} - - PATTERNINDEX CModDoc::InsertPattern(ORDERINDEX nOrd, ROWINDEX nRows) //------------------------------------------------------------------ { Modified: trunk/OpenMPT/mptrack/Undo.cpp =================================================================== --- trunk/OpenMPT/mptrack/Undo.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Undo.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -326,7 +326,7 @@ const size_t bytesPerSample = oldSample.GetBytesPerSample(); const size_t changeLen = changeEnd - changeStart; - undo.samplePtr = sndFile.AllocateSample((changeLen + 4) * bytesPerSample); + undo.samplePtr = ModSample::AllocateSample(changeLen, bytesPerSample); if(undo.samplePtr == nullptr) return false; memcpy(undo.samplePtr, static_cast<const char *>(oldSample.pSample) + changeStart * bytesPerSample, changeLen * bytesPerSample); @@ -408,7 +408,7 @@ case sundo_delete: // insert deleted data - pNewSample = static_cast<char *>(sndFile.AllocateSample(undo.OldSample.GetSampleSizeInBytes() + 4 * bytesPerSample)); + pNewSample = static_cast<char *>(ModSample::AllocateSample(undo.OldSample.nLength, bytesPerSample)); if(pNewSample == nullptr) return false; replace = true; memcpy(pNewSample, pCurrentSample, undo.changeStart * bytesPerSample); @@ -437,7 +437,7 @@ { ctrlSmp::ReplaceSample(sample, pNewSample, undo.OldSample.nLength, sndFile); } - ctrlSmp::AdjustEndOfSample(sample, sndFile); + sample.PrecomputeLoops(sndFile, true); RemoveLastUndoStep(smp); @@ -462,7 +462,7 @@ //------------------------------------------------------------------------ { if(!SampleBufferExists(smp, false) || step >= UndoBuffer[smp - 1].size()) return; - CSoundFile::FreeSample(UndoBuffer[smp - 1][step].samplePtr); + ModSample::FreeSample(UndoBuffer[smp - 1][step].samplePtr); UndoBuffer[smp - 1].erase(UndoBuffer[smp - 1].begin() + step); } Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -1414,7 +1414,7 @@ else if(sndFile.GetSample(m_nSample).GetElementarySampleSize() == 1) SetSampleData<int8, uint8>(sndFile.GetSample(m_nSample).pSample, point, old); - ctrlSmp::AdjustEndOfSample(sndFile.GetSample(m_nSample), sndFile); + sndFile.GetSample(m_nSample).PrecomputeLoops(sndFile, false); InvalidateSample(); pModDoc->SetModified(); @@ -1433,12 +1433,11 @@ //------------------------------------------------- { CModDoc *pModDoc = GetDocument(); - CSoundFile *pSndFile; DWORD len; if(m_dwStatus[SMPSTATUS_MOUSEDRAG] || (!pModDoc)) return; - pSndFile = pModDoc->GetSoundFile(); - ModSample &sample = pSndFile->GetSample(m_nSample); + CSoundFile &sndFile = pModDoc->GetrSoundFile(); + ModSample &sample = sndFile.GetSample(m_nSample); len = sample.nLength; if (!len) @@ -1472,6 +1471,8 @@ else if(sample.GetElementarySampleSize() == 1) SetInitialDrawPoint<int8, uint8>(sample.pSample, point); + sndFile.GetSample(m_nSample).PrecomputeLoops(sndFile, false); + InvalidateSample(); pModDoc->SetModified(); } else @@ -1724,11 +1725,8 @@ { if ((sample.nLoopStart != m_dwBeginSel) || (sample.nLoopEnd != m_dwEndSel)) { - sample.nLoopStart = m_dwBeginSel; - sample.nLoopEnd = m_dwEndSel; - sample.uFlags |= CHN_LOOP; + sample.SetLoop(m_dwBeginSel, m_dwEndSel, true, sample.uFlags[CHN_PINGPONGLOOP], sndFile); pModDoc->SetModified(); - pModDoc->AdjustEndOfSample(m_nSample); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } @@ -1748,11 +1746,8 @@ { if ((sample.nSustainStart != m_dwBeginSel) || (sample.nSustainEnd != m_dwEndSel)) { - sample.nSustainStart = m_dwBeginSel; - sample.nSustainEnd = m_dwEndSel; - sample.uFlags |= CHN_SUSTAINLOOP; + sample.SetSustainLoop(m_dwBeginSel, m_dwEndSel, true, sample.uFlags[CHN_PINGPONGSUSTAIN], sndFile); pModDoc->SetModified(); - pModDoc->AdjustEndOfSample(m_nSample); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } @@ -1863,9 +1858,10 @@ { sample.uFlags.reset(CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN); } + + sample.PrecomputeLoops(sndFile); } SetCurSel(0, 0); - pModDoc->AdjustEndOfSample(m_nSample); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | dwUpdateFlags, NULL); } @@ -1976,7 +1972,7 @@ BeginWaitCursor(); if ((pModDoc) && (OpenClipboard())) { - CHAR s[32], s2[32]; + char s[MAX_SAMPLENAME], s2[MAX_SAMPLEFILENAME]; HGLOBAL hCpy = ::GetClipboardData(CF_WAVE); LPBYTE p; @@ -1984,27 +1980,27 @@ { pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); - CSoundFile *pSndFile = pModDoc->GetSoundFile(); - DWORD dwMemSize = GlobalSize(hCpy); + CSoundFile &sndFile = pModDoc->GetrSoundFile(); + ModSample &sample = sndFile.GetSample(m_nSample); - ModSample &sample = pSndFile->GetSample(m_nSample); + MemCopy(s, sndFile.m_szNames[m_nSample]); + MemCopy(s2, sample.filename); - memcpy(s, pSndFile->m_szNames[m_nSample], 32); - memcpy(s2, sample.filename, 22); - FileReader file(p, dwMemSize); - pSndFile->ReadSampleFromFile(m_nSample, file, TrackerSettings::Instance().m_MayNormalizeSamplesOnLoad); - if (!pSndFile->m_szNames[m_nSample][0]) -{ - memcpy(pSndFile->m_szNames[m_nSample], s, 32); -} + FileReader file(p, GlobalSize(hCpy)); + sndFile.ReadSampleFromFile(m_nSample, file); + + if(!sndFile.m_szNames[m_nSample][0]) + { + MemCopy(sndFile.m_szNames[m_nSample], s); + } if (!sample.filename[0]) { - memcpy(sample.filename, s2, 22); + MemCopy(sample.filename, s2); } GlobalUnlock(hCpy); SetCurSel(0, 0); - pModDoc->AdjustEndOfSample(m_nSample); + sample.PrecomputeLoops(sndFile, true); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA | HINT_SMPNAMES, NULL); } @@ -2046,15 +2042,15 @@ p[i] = (signed char) ((*((short int *)(p+i*2))) / 256); } sample.uFlags.reset(CHN_16BIT); - for (UINT j=0; j<MAX_CHANNELS; j++) if (sndFile.Chn[j].pSample == sample.pSample) + for (CHANNELINDEX j = 0; j < MAX_CHANNELS; j++) if (sndFile.Chn[j].pSample == sample.pSample) { sndFile.Chn[j].dwFlags.reset(CHN_16BIT); } + sample.PrecomputeLoops(sndFile, false); cs.Leave(); pModDoc->SetModified(); - pModDoc->AdjustEndOfSample(m_nSample); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO, NULL); } } @@ -2191,10 +2187,10 @@ } sample.nLength = nEnd; + sample.PrecomputeLoops(sndFile); cs.Leave(); pModDoc->SetModified(); - pModDoc->AdjustEndOfSample(m_nSample); SetCurSel(0, 0); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO, NULL); } @@ -2380,7 +2376,6 @@ } if (bUpdate) { - pModDoc->AdjustEndOfSample(m_nSample); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA | HINT_SAMPLEINFO | HINT_SMPNAMES, NULL); pModDoc->SetModified(); } @@ -2451,10 +2446,8 @@ if ((m_dwMenuParam+4 <= sample.nLoopEnd) && (sample.nLoopStart != m_dwMenuParam)) { pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); - sample.nLoopStart = m_dwMenuParam; - sample.uFlags |= CHN_LOOP; + sample.SetLoop(m_dwMenuParam, sample.nLoopEnd, true, sample.uFlags[CHN_PINGPONGLOOP], sndFile); pModDoc->SetModified(); - ctrlSmp::UpdateLoopPoints(sample, sndFile); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } @@ -2472,10 +2465,8 @@ if ((m_dwMenuParam >= sample.nLoopStart+4) && (sample.nLoopEnd != m_dwMenuParam)) { pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); - sample.nLoopEnd = m_dwMenuParam; - sample.uFlags |= CHN_LOOP; + sample.SetLoop(sample.nLoopStart, m_dwMenuParam, true, sample.uFlags[CHN_PINGPONGLOOP], sndFile); pModDoc->SetModified(); - ctrlSmp::UpdateLoopPoints(sample, sndFile); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } @@ -2493,10 +2484,8 @@ if ((m_dwMenuParam+4 <= sample.nSustainEnd) && (sample.nSustainStart != m_dwMenuParam)) { pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); - sample.nSustainStart = m_dwMenuParam; - sample.uFlags |= CHN_SUSTAINLOOP; + sample.SetSustainLoop(m_dwMenuParam, sample.nSustainEnd, true, sample.uFlags[CHN_PINGPONGSUSTAIN], sndFile); pModDoc->SetModified(); - ctrlSmp::UpdateLoopPoints(sample, sndFile); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } @@ -2514,10 +2503,8 @@ if ((m_dwMenuParam >= sample.nSustainStart+4) && (sample.nSustainEnd != m_dwMenuParam)) { pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); - sample.nSustainEnd = m_dwMenuParam; - sample.uFlags |= CHN_SUSTAINLOOP; + sample.SetSustainLoop(sample.nSustainStart, m_dwMenuParam, true, sample.uFlags[CHN_PINGPONGSUSTAIN], sndFile); pModDoc->SetModified(); - ctrlSmp::UpdateLoopPoints(sample, sndFile); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } } Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -654,7 +654,7 @@ m_MixState.dwFlags = 0; m_MixState.nVolDecayL = 0; m_MixState.nVolDecayR = 0; - m_MixState.pMixBuffer = (int *)((((intptr_t)m_MixBuffer) + 7) & ~7); + m_MixState.pMixBuffer = (mixsample_t *)((((intptr_t)m_MixBuffer) + 7) & ~7); m_MixState.pOutBufferL = mixBuffer.GetInputBuffer(0); m_MixState.pOutBufferR = mixBuffer.GetInputBuffer(1); Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/Vstplug.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -94,6 +94,7 @@ #ifndef NO_VST #include "../soundlib/plugins/PluginEventQueue.h" +#include "../soundlib/Mixer.h" #endif // NO_VST @@ -149,7 +150,7 @@ VSTInstrChannel m_MidiCh[16]; // MIDI channel state PluginMixBuffer<float, MIXBUFFERSIZE> mixBuffer; // Float buffers (input and output) for plugins - int32 m_MixBuffer[MIXBUFFERSIZE * 2 + 2]; // Stereo interleaved + mixsample_t m_MixBuffer[MIXBUFFERSIZE * 2 + 2]; // Stereo interleaved PluginEventQueue<vstNumProcessEvents> vstEvents; // MIDI events that should be sent to the plugin public: Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-02-01 13:50:38 UTC (rev 3601) @@ -1015,6 +1015,22 @@ > </File> <File + RelativePath="..\soundlib\FloatMixer.h" + > + </File> + <File + RelativePath="..\soundlib\IntMixer.h" + > + </File> + <File + RelativePath="..\soundlib\Mixer.h" + > + </File> + <File + RelativePath="..\soundlib\MixerInterface.h" + > + </File> + <File RelativePath="..\soundlib\MixerLoops.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-02-01 13:50:38 UTC (rev 3601) @@ -463,7 +463,13 @@ <ClCompile Include="..\sounddsp\Reverb.cpp" /> <ClCompile Include="..\soundlib\Dither.cpp" /> <ClCompile Include="..\soundlib\Dlsbank.cpp" /> - <ClCompile Include="..\soundlib\Fastmix.cpp" /> + <ClCompile Include="..\soundlib\Fastmix.cpp"> + <DebugInformationFormat Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">ProgramDatabase</DebugInformationFormat> + <InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AnySuitable</InlineFunctionExpansion> + <IntrinsicFunctions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IntrinsicFunctions> + <InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AnySuitable</InlineFunctionExpansion> + <IntrinsicFunctions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IntrinsicFunctions> + </ClCompile> <ClCompile Include="..\soundlib\ITCompression.cpp" /> <ClCompile Include="..\soundlib\ITTools.cpp" /> <ClCompile Include="..\soundlib\Load_digi.cpp" /> @@ -660,11 +666,15 @@ <ClInclude Include="..\soundlib\Dlsbank.h" /> <ClInclude Include="..\soundlib\Endianness.h" /> <ClInclude Include="..\soundlib\FileReader.h" /> + <ClInclude Include="..\soundlib\FloatMixer.h" /> + <ClInclude Include="..\soundlib\IntMixer.h" /> <ClInclude Include="..\soundlib\ITCompression.h" /> <ClInclude Include="..\soundlib\ITTools.h" /> <ClInclude Include="..\soundlib\Message.h" /> <ClInclude Include="..\soundlib\MIDIEvents.h" /> <ClInclude Include="..\soundlib\MIDIMacros.h" /> + <ClInclude Include="..\soundlib\Mixer.h" /> + <ClInclude Include="..\soundlib\MixerInterface.h" /> <ClInclude Include="..\soundlib\MixerLoops.h" /> <ClInclude Include="..\soundlib\MixerSettings.h" /> <ClInclude Include="..\soundlib\ModChannel.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-02-01 13:50:38 UTC (rev 3601) @@ -963,6 +963,18 @@ <ClInclude Include="CTreeCtrl.h"> <Filter>Header Files\mptrack</Filter> </ClInclude> + <ClInclude Include="..\soundlib\FloatMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\IntMixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\Mixer.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> + <ClInclude Include="..\soundlib\MixerInterface.h"> + <Filter>Header Files\soundlib</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/sounddsp/EQ.cpp =================================================================== --- trunk/OpenMPT/sounddsp/EQ.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/sounddsp/EQ.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -28,10 +28,6 @@ 160, 172, 184, 196, 208, 220, 232, 244, 256 }; - -static const float32 f2ic = (float32)(1 << 28); -static const float32 i2fc = (float32)(1.0 / (1 << 28)); - static const EQBANDSTRUCT gEQDefaults[MAX_EQ_BANDS*2] = { // Default: Flat EQ Modified: trunk/OpenMPT/sounddsp/EQ.h =================================================================== --- trunk/OpenMPT/sounddsp/EQ.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/sounddsp/EQ.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -10,8 +10,8 @@ #pragma once +#include "../soundlib/Mixer.h" // For MIXBUFFERSIZE - #define MAX_EQ_BANDS 6 typedef struct ALIGN(4) _EQBANDSTRUCT Modified: trunk/OpenMPT/sounddsp/Reverb.cpp =================================================================== --- trunk/OpenMPT/sounddsp/Reverb.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/sounddsp/Reverb.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -18,7 +18,7 @@ #pragma warning(disable:4725) // Pentium fdiv bug #pragma warning(disable:4731) // ebp modified -extern void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); +extern void StereoFill(int *pBuffer, UINT nSamples, mixsample_t &lpROfs, mixsample_t &lpLOfs); @@ -409,7 +409,7 @@ { if(!gnReverbSend) { // and we did not clear the buffer yet, do it now because we will get new data - StereoFill(MixReverbBuffer, nSamples, &gnRvbROfsVol, &gnRvbLOfsVol); + StereoFill(MixReverbBuffer, nSamples, gnRvbROfsVol, gnRvbLOfsVol); } gnReverbSend = 1; // we will have to process reverb return MixReverbBuffer; @@ -427,7 +427,7 @@ } if(!gnReverbSend) { // no input data in MixReverbBuffer, so the buffer got not cleared in GetReverbSendBuffer(), do it now for decay - StereoFill(MixReverbBuffer, nSamples, &gnRvbROfsVol, &gnRvbLOfsVol); + StereoFill(MixReverbBuffer, nSamples, gnRvbROfsVol, gnRvbLOfsVol); } UINT nIn, nOut; Modified: trunk/OpenMPT/sounddsp/Reverb.h =================================================================== --- trunk/OpenMPT/sounddsp/Reverb.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/sounddsp/Reverb.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -11,6 +11,7 @@ #pragma once #ifndef NO_REVERB +#include "../soundlib/Mixer.h" // For MIXBUFFERSIZE ///////////////////////////////////////////////////////////////////////////// // @@ -129,8 +130,7 @@ private: int MixReverbBuffer[MIXBUFFERSIZE * 2]; public: - LONG gnRvbROfsVol; - LONG gnRvbLOfsVol; + mixsample_t gnRvbROfsVol, gnRvbLOfsVol; private: Modified: trunk/OpenMPT/soundlib/AudioReadTarget.h =================================================================== --- trunk/OpenMPT/soundlib/AudioReadTarget.h 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/soundlib/AudioReadTarget.h 2014-02-01 13:50:38 UTC (rev 3601) @@ -13,6 +13,7 @@ #include "SampleFormatConverters.h" #include "SampleFormat.h" #include "MixerLoops.h" +#include "Mixer.h" template<typename Tsample> Modified: trunk/OpenMPT/soundlib/Dither.cpp =================================================================== --- trunk/OpenMPT/soundlib/Dither.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/soundlib/Dither.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -11,11 +11,10 @@ #include "stdafx.h" #include "Dither.h" +#include "Mixer.h" -#include "Snd_defs.h" - ////////////////////////////////////////////////////////////////////////// // Noise Shaping (Dithering) Modified: trunk/OpenMPT/soundlib/Dlsbank.cpp =================================================================== --- trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/soundlib/Dlsbank.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -1560,6 +1560,7 @@ SampleIO::littleEndian, SampleIO::signedPCM) .ReadSample(sample, chunk); + sample.PrecomputeLoops(sndFile, false); } bWaveForm = (sample.pSample) ? TRUE : FALSE; } else Modified: trunk/OpenMPT/soundlib/Fastmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Fastmix.cpp 2014-02-01 13:41:36 UTC (rev 3600) +++ trunk/OpenMPT/soundlib/Fastmix.cpp 2014-02-01 13:50:38 UTC (rev 3601) @@ -3,1433 +3,259 @@ * ----------- * Purpose: Mixer core for rendering samples, mixing plugins, etc... * Notes : If this is Fastmix.cpp, where is Slowmix.cpp? :) - * This code is ugly like hell and you are probably not going to understand it - * unless you have worked with OpenMPT for a long time - at least I didn't. :) - * I guess that a lot of this could be refactored using inline functions. + * The Visual Studio project settings for this file have been adjusted + * to force function inlining, so that the mixer has a somewhat acceptable + * performance in debug mode. If you need to debug anything here, be sure + * to disable those optimizations if needed. * Authors: Olivier Lapicque * OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ +// FIXME: +// - Playing samples backwards should reverse interpolation LUTs for interpolation modes +// with more than two taps since they're not symmetric. We might need separate LUTs +// because otherwise we will add tons of branches. +// - Loop wraparound works pretty well in general, but not at the start of bidi samples. +// - THe loop lookahead stuff might still fail for samples with backward loops. + #include "stdafx.h" #include "Sndfile.h" - #include "MixerLoops.h" -#include "Resampler.h" -#include "WindowedFIR.h" +#ifdef MPT_INTMIXER +#include "IntMixer.h" +#else +#include "FloatMixer.h" +#endif // MPT_INTMIXER -// 4x256 taps polyphase FIR resampling filter -#define gFastSinc CResampler::FastSincTable +namespace MixFuncTable +{ +#ifdef MPT_INTMIXER + typedef Int8MToIntS I8M; + typedef Int16MToIntS I16M; + typedef Int8SToIntS I8S; + typedef Int16SToIntS I16S; +#else + typedef Int8MToFloatS I8M; + typedef Int16MToFloatS I16M; + typedef Int8SToFloatS I8S; + typedef Int16SToFloatS I16S; +#endif // MPT_INTMIXER +// Table index: +// [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo) +// [b2] ramp +// [b3] filter +// [b6-b4] src type -///////////////////////////////////////////////////// -// Mixing Macros +// Sample type / processing type index +enum FunctionIndex +{ + ndx16Bit = 0x01, + ndxStereo = 0x02, + ndxRamp = 0x04, + ndxFilter = 0x08, +}; -#define SNDMIX_BEGINSAMPLELOOP8\ - register ModChannel * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed char *p = (signed char *)(pChn->pCurrentSample)+pChn->nPos;\ - if (pChn->dwFlags[CHN_STEREO]) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_BEGINSAMPLELOOP16\ - register ModChannel * const pChn = pChannel;\ - nPos = pChn->nPosLo;\ - const signed short *p = (signed short *)(pChn->pCurrentSample)+pChn->nPos;\ - if (pChn->dwFlags[CHN_STEREO]) p += pChn->nPos;\ - int *pvol = pbuffer;\ - do { - -#define SNDMIX_ENDSAMPLELOOP\ - nPos += pChn->nInc;\ - } while (pvol < pbufmax);\ - pChn->nPos += nPos >> 16;\ - pChn->nPosLo = nPos & 0xFFFF; - -#define SNDMIX_ENDSAMPLELOOP8 SNDMIX_ENDSAMPLELOOP -#define SNDMIX_ENDSAMPLELOOP16 SNDMIX_ENDSAMPLELOOP - -////////////////////////////////////////////////////////////////////////////// -// Mono - -// No interpolation -#define SNDMIX_GETMONOVOL8NOIDO\ - int vol = p[nPos >> 16] << 8; - -#define SNDMIX_GETMONOVOL16NOIDO\ - int vol = p[nPos >> 16]; - -// Linear Interpolation -#define SNDMIX_GETMONOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol))); - -#define SNDMIX_GETMONOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol = p[poshi];\ - int destvol = p[poshi+1];\ - int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8); - -// Cubic Spline -#define SNDMIX_GETMONOVOL8HQSRC\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 6) & 0x3FC;\ - int vol = (gFastSinc[poslo]*p[poshi-1] + gFastSinc[poslo+1]*p[poshi]\ - + gFastSinc[poslo+2]*p[poshi+1] + gFastSinc[poslo+3]*p[poshi+2]) >> 6;\ - -#define SNDMIX_GETMONOVOL16HQSRC\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 6) & 0x3FC;\ - int vol = (gFastSinc[poslo]*p[poshi-1] + gFastSinc[poslo+1]*p[poshi]\ - + gFastSinc[poslo+2]*p[poshi+1] + gFastSinc[poslo+3]*p[poshi+2]) >> 14;\ - -// 8-taps polyphase -#define SNDMIX_GETMONOVOL8KAISER\ - int poshi = nPos >> 16;\ - const SINC_TYPE *poslo = sinc + ((nPos >> (16-SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;\ - int vol = ((poslo[0]*p[poshi-3] + poslo[1]*p[poshi-2]\ - + poslo[2]*p[poshi-1] + poslo[3]*p[poshi]\ - + poslo[4]*p[poshi+1] + poslo[5]*p[poshi+2]\ - + poslo[6]*p[poshi+3] + poslo[7]*p[poshi+4]) >> (SINC_QUANTSHIFT-8));\ - -#define SNDMIX_GETMONOVOL16KAISER\ - int poshi = nPos >> 16;\ - const SINC_TYPE *poslo = sinc + ((nPos >> (16-SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;\ - int vol = ((poslo[0]*p[poshi-3] + poslo[1]*p[poshi-2]\ - + poslo[2]*p[poshi-1] + poslo[3]*p[poshi]\ - + poslo[4]*p[poshi+1] + poslo[5]*p[poshi+2]\ - + poslo[6]*p[poshi+3] + poslo[7]*p[poshi+4]) >> SINC_QUANTSHIFT);\ -// rewbs.resamplerConf -#define SNDMIX_GETMONOVOL8FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol = (WFIR_lut[firidx+0]*(int)p[poshi+1-4]); \ - vol += (WFIR_lut[firidx+1]*(int)p[poshi+2-4]); \ - vol += (WFIR_lut[firidx+2]*(int)p[poshi+3-4]); \ - vol += (WFIR_lut[firidx+3]*(int)p[poshi+4-4]); \ - vol += (WFIR_lut[firidx+4]*(int)p[poshi+5-4]); \ - vol += (WFIR_lut[firidx+5]*(int)p[poshi+6-4]); \ - vol += (WFIR_lut[firidx+6]*(int)p[poshi+7-4]); \ - vol += (WFIR_lut[firidx+7]*(int)p[poshi+8-4]); \ - vol >>= WFIR_8SHIFT; - -#define SNDMIX_GETMONOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1 = (WFIR_lut[firidx+0]*(int)p[poshi+1-4]); \ - vol1 += (WFIR_lut[firidx+1]*(int)p[poshi+2-4]); \ - vol1 += (WFIR_lut[firidx+2]*(int)p[poshi+3-4]); \ - vol1 += (WFIR_lut[firidx+3]*(int)p[poshi+4-4]); \ - int vol2 = (WFIR_lut[firidx+4]*(int)p[poshi+5-4]); \ - vol2 += (WFIR_lut[firidx+5]*(int)p[poshi+6-4]); \ - vol2 += (WFIR_lut[firidx+6]*(int)p[poshi+7-4]); \ - vol2 += (WFIR_lut[firidx+7]*(int)p[poshi+8-4]); \ - int vol = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1); - - -// end rewbs.resamplerConf -#define SNDMIX_INITSINCTABLE\ - const SINC_TYPE * const sinc = (((pChannel->nInc > 0x13000) || (pChannel->nInc < -0x13000)) ?\ - (((pChannel->nInc > 0x18000) || (pChannel->nInc < -0x18000)) ? pResampler->gDownsample2x : pResampler->gDownsample13x) : pResampler->gKaiserSinc); - -#define SNDMIX_INITFIRTABLE\ - const signed short * const WFIR_lut = pResampler->m_WindowedFIR.lut; - - -///////////////////////////////////////////////////////////////////////////// -// Stereo - -// No interpolation -#define SNDMIX_GETSTEREOVOL8NOIDO\ - int vol_l = p[(nPos>>16)*2] << 8;\ - int vol_r = p[(nPos>>16)*2+1] << 8; - -#define SNDMIX_GETSTEREOVOL16NOIDO\ - int vol_l = p[(nPos>>16)*2];\ - int vol_r = p[(nPos>>16)*2+1]; - -// Linear Interpolation -#define SNDMIX_GETSTEREOVOL8LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r))); - -#define SNDMIX_GETSTEREOVOL16LINEAR\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 8) & 0xFF;\ - int srcvol_l = p[poshi*2];\ - int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\ - int srcvol_r = p[poshi*2+1];\ - int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\ - -// Cubic Spline -#define SNDMIX_GETSTEREOVOL8HQSRC\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 6) & 0x3FC;\ - int vol_l = (gFastSinc[poslo]*p[poshi*2-2] + gFastSinc[poslo+1]*p[poshi*2]\ - + gFastSinc[poslo+2]*p[poshi*2+2] + gFastSinc[poslo+3]*p[poshi*2+4]) >> 6;\ - int vol_r = (gFastSinc[poslo]*p[poshi*2-1] + gFastSinc[poslo+1]*p[poshi*2+1]\ - + gFastSinc[poslo+2]*p[poshi*2+3] + gFastSinc[poslo+3]*p[poshi*2+5]) >> 6;\ - -#define SNDMIX_GETSTEREOVOL16HQSRC\ - int poshi = nPos >> 16;\ - int poslo = (nPos >> 6) & 0x3FC;\ - int vol_l = (gFastSinc[poslo]*p[poshi*2-2] + gFastSinc[poslo+1]*p[poshi*2]\ - + gFastSinc[poslo+2]*p[poshi*2+2] + gFastSinc[poslo+3]*p[poshi*2+4]) >> 14;\ - int vol_r = (gFastSinc[poslo]*p[poshi*2-1] + gFastSinc[poslo+1]*p[poshi*2+1]\ - + gFastSinc[poslo+2]*p[poshi*2+3] + gFastSinc[poslo+3]*p[poshi*2+5]) >> 14;\ - -// -> CODE#0025 -// -> DESC="enable polyphase resampling on stereo samples" -// 8-taps polyphase -#define SNDMIX_GETSTEREOVOL8KAISER\ - int poshi = nPos >> 16;\ - const SINC_TYPE *poslo = sinc + ((nPos >> (16-SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;\ - int vol_l = ((poslo[0]*p[poshi*2-6] + poslo[1]*p[poshi*2-4]\ - + poslo[2]*p[poshi*2-2] + poslo[3]*p[poshi*2]\ - + poslo[4]*p[poshi*2+2] + poslo[5]*p[poshi*2+4]\ - + poslo[6]*p[poshi*2+6] + poslo[7]*p[poshi*2+8]) >> (SINC_QUANTSHIFT-8));\ - int vol_r = ((poslo[0]*p[poshi*2-5] + poslo[1]*p[poshi*2-3]\ - + poslo[2]*p[poshi*2-1] + poslo[3]*p[poshi*2+1]\ - + poslo[4]*p[poshi*2+3] + poslo[5]*p[poshi*2+5]\ - + poslo[6]*p[poshi*2+7] + poslo[7]*p[poshi*2+9]) >> (SINC_QUANTSHIFT-8));\ - -#define SNDMIX_GETSTEREOVOL16KAISER\ - int poshi = nPos >> 16;\ - const SINC_TYPE *poslo = sinc + ((nPos >> (16-SINC_PHASES_BITS)) & SINC_MASK) * SINC_WIDTH;\ - int vol_l = ((poslo[0]*p[poshi*2-6] + poslo[1]*p[poshi*2-4]\ - + poslo[2]*p[poshi*2-2] + poslo[3]*p[poshi*2]\ - + poslo[4]*p[poshi*2+2] + poslo[5]*p[poshi*2+4]\ - + poslo[6]*p[poshi*2+6] + poslo[7]*p[poshi*2+8]) >> SINC_QUANTSHIFT);\ - int vol_r = ((poslo[0]*p[poshi*2-5] + poslo[1]*p[poshi*2-3]\ - + poslo[2]*p[poshi*2-1] + poslo[3]*p[poshi*2+1]\ - + poslo[4]*p[poshi*2+3] + poslo[5]*p[poshi*2+5]\ - + poslo[6]*p[poshi*2+7] + poslo[7]*p[poshi*2+9]) >> SINC_QUANTSHIFT);\ -// rewbs.resamplerConf -// fir interpolation -#define SNDMIX_GETSTEREOVOL8FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol_l = (WFIR_lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol_l += (WFIR_lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - vol_l >>= WFIR_8SHIFT; \ - int vol_r = (WFIR_lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol_r += (WFIR_lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - vol_r >>= WFIR_8SHIFT; - -#define SNDMIX_GETSTEREOVOL16FIRFILTER \ - int poshi = nPos >> 16;\ - int poslo = (nPos & 0xFFFF);\ - int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \ - int vol1_l = (WFIR_lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \ - vol1_l += (WFIR_lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \ - vol1_l += (WFIR_lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \ - vol1_l += (WFIR_lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \ - int vol2_l = (WFIR_lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \ - vol2_l += (WFIR_lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \ - vol2_l += (WFIR_lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \ - vol2_l += (WFIR_lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \ - int vol_l = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \ - int vol1_r = (WFIR_lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \ - vol1_r += (WFIR_lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \ - vol1_r += (WFIR_lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \ - vol1_r += (WFIR_lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \ - int vol2_r = (WFIR_lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \ - vol2_r += (WFIR_lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \ - vol2_r += (WFIR_lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \ - vol2_r += (WFIR_lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \ - int vol_r = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1); -//end rewbs.resamplerConf -// -! BEHAVIOUR_CHANGE#0025 - - -///////////////////////////////////////////////////////////////////////////// - -#define SNDMIX_STOREMONOVOL\ - pvol[0] += vol * pChn->leftVol;\ - pvol[1] += vol * pChn->rightVol;\ - pvol += 2; - -#define SNDMIX_STORESTEREOVOL\ - pvol[0] += vol_l * pChn->leftVol;\ - pvol[1] += vol_r * pChn->rightVol;\ - pvol += 2; - -#define SNDMIX_STOREFASTMONOVOL\ - int v = vol * pChn->leftVol;\ - pvol[0] += v;\ - pvol[1] += v;\ - pvol += 2; - -#define SNDMIX_RAMPMONOVOL\ - rampLeftVol += pChn->leftRamp;\ - rampRightVol += pChn->rightRamp;\ - pvol[0] += vol * (rampLeftVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol * (rampRightVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - -#define SNDMIX_RAMPFASTMONOVOL\ - rampLeftVol += pChn->leftRamp;\ - int fastvol = vol * (rampLeftVol >> VOLUMERAMPPRECISION);\ - pvol[0] += fastvol;\ - pvol[1] += fastvol;\ - pvol += 2; - -#define SNDMIX_RAMPSTEREOVOL\ - rampLeftVol += pChn->leftRamp;\ - rampRightVol += pChn->rightRamp;\ - pvol[0] += vol_l * (rampLeftVol >> VOLUMERAMPPRECISION);\ - pvol[1] += vol_r * (rampRightVol >> VOLUMERAMPPRECISION);\ - pvol += 2; - - -/////////////////////////////////////////////////// -// Resonant Filters - -// Filter values are clipped to double the input range (assuming input is 16-Bit, which it currently is) -#define ClipFilter(x) Clamp(x, 2.0f * (float)int16_min, 2.0f * (float)int16_max) - -// Resonant filter for Mono samples -static forceinline void ProcessMonoFilter(int &vol, ModChannel *pChn) -//------------------------------------------------------------------- +// SRC index +enum ResamplingIndex { - float fy1 = pChn->nFilter_Y1; - float fy2 = pChn->nFilter_Y2; + ndxNoInterpolation = 0x00, + ndxLinear = 0x10, + ndxFastSinc = 0x20, + ndxKaiser = 0x30, + ndxFIRFilter = 0x40, +}; - float fy = ((float)vol * pChn->nFilter_A0 + ClipFilter(fy1) * pChn->nFilter_B0 + ClipFilter(fy2) * pChn->nFilter_B1); - fy2 = fy1; - fy1 = fy - (float)(vol & pChn->nFilter_HP); - vol = (int)fy; +// Build mix function table for given resampling, filter and ramping settings: One function each for 8-Bit / 16-Bit Mono / Stereo +#define BuildMixFuncTableRamp(resampling, filter, ramp) \ + SampleLoop<I8M, resampling<I8M>, filter<I8M>, MixMono ## ramp<I8M> >, \ + SampleLoop<I16M, resampling<I16M>, filter<I16M>, MixMono ## ramp<I16M> >, \ + SampleLoop<I8S, resampling<I8S>, filter<I8S>, MixStereo ## ramp<I8S> >, \ + SampleLoop<I16S, resampling<I16S>, filter<I16S>, MixStereo ## ramp<I16S> > - pChn->nFilter_Y1 = fy1; - pChn->nFilter_Y2 = fy2; -} +// Build mix function table for given resampling, filter settings: With and without ramping +#define BuildMixFuncTableFilter(resampling, filter) \ + BuildMixFuncTableRamp(resampling, filter, NoRamp), \ + BuildMixFuncTableRamp(resampling, filter, Ramp) +// Build mix function table for given resampling settings: With and without filter +#define BuildMixFuncTable(resampling) \ + BuildMixFuncTableFilter(resampling, NoFilter), \ + BuildMixFuncTableFilter(resampling, ResonantFilter) -// Resonant filter for Stereo samples -static forceinline void ProcessStereoFilter(int &vol_l, int &vol_r, ModChannel *pChn) -//----------------------------------------------------------------------------------- +const MixFuncInterface Functions[5 * 16] = { - // Left channel - float fy1 = pChn->nFilter_Y1; - float fy2 = pChn->nFilter_Y2; + BuildMixFuncTable(NoInterpolation), // No SRC + BuildMixFuncTable(LinearInterpolation), // Linear SRC + BuildMixFuncTable(FastSincInterpolation), // Fast Sinc (Cubic Spline) SRC + BuildMixFuncTable(PolyphaseInterpolation), // Kaiser SRC + BuildMixFuncTable(FIRFilterInterpolation), // FIR SRC +}; - float fy = ((float)vol_l * pChn->nFilter_A0 + ClipFilter(fy1) * pChn->nFilter_B0 + ClipFilter(fy2) * pChn->nFilter_B1); - fy2 = fy1; - fy1 = fy - (float)(vol_l & pChn->nFilter_HP); - vol_l = (int)fy; +#undef BuildMixFuncTableRamp +#undef BuildMixFuncTableFilter +#undef BuildMixFuncTable - pChn->nFilter_Y1 = fy1; - pChn->nFilter_Y2 = ... [truncated message content] |