View Issue Details

IDProjectCategoryView StatusLast Update
0001280OpenMPTlibopenmptpublic2019-12-24 09:30
Reportermanx Assigned Tomanx  
PriorityhighSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Product VersionOpenMPT 1.29.00.* (current testing) 
Target VersionOpenMPT 1.29 / libopenmpt 0.5 (goals)Fixed in VersionOpenMPT 1.29 / libopenmpt 0.5 (goals) 
Summary0001280: ban function-static data
Description

We must ban function-local static data.

static data inside of a function must use a lock to be initialized thread-safely by the compiler. This is required in C++11 and implemented even for C++03 by gcc and clang. The compiler is optionally allowed to use constant-initialization instead, but is by no means and in no circumstances required to do so (not even when the data is declared const and not even if the initializing expression is a constant expression). Current MSVC doesn't use constant-initialization in debug builds and thus introduces a lock, and older MSVC just silently introduces a race condition because it does not implement thread-safe initialization.

static const data inside a function is a bug, in both, C++ pre 11, and post 11.

This affects all active branches:

  • libopenmpt 0.2 (C++03): not thread-safe with GCC 4.2 or any MSVC except VS2015 targeting Windows 7
  • libopenmpt 0.3 (C++11): not thread-safe with any MSVC in Windows XP builds (compiler requires Vista for thread-safe init)
  • libopenmpt 0.4 (C++11): not thread-safe with any MSVC in Windows XP builds (compiler requires Vista for thread-safe init)
  • libopenmpt 0.5 (C++17): sub-optimal code generation due to possibility of compiler-induced locking

There are 3 alternatives:

  • constexpr (with or without static, but without static is much cleaner and easier to read, because static induces thinking about initialization when reading the code) for c++17 or later (possibly also for c++11, however constexpr restrictions probably make this solution infeasible)
  • const data, the compiler is likely to initialize it at compile time anyway, losing nothing compared to the current solution which also does not guarantee anything. this solution requires extra caution when returning a pointer to the data, which would be dangling unless the pointed-to data is a string literal.
  • namespace scope static data, however this is not guaranteed to not generate run-time global initialization without using constexpr either.

Note: function-local static data is no bug in C, because C requires initializers to be constant expressions.

TagsNo tags attached.
Has the bug occurred in previous versions?
Tested code revision (in case you know it)

Activities

Saga Musix

Saga Musix

2019-11-10 17:47

administrator   ~0004149

For static LUTs in module loaders, typically for pattern command conversion, I prefer them to be close to their usage site, so constexpr initialization seems to be the best candidate there. Otherwise putting them at the top of the file with constexpr would be fine too. Apart from a few static const variables here and there (which could also be trivially turned into constexpr), I guess those would be the biggest offenders in soundlib/?

manx

manx

2019-12-21 09:51

administrator   ~0004164

Patch addresses probably most cases (searched for "static const") and replaces them by "static constexpr", unless another solution seemed clearly more suitable at any particular location. The patch also replaces various other "static const" data by "static constexpr", in particular global scope (where it prevents accidental runtime initialization) and class scope (where it prevents linking problems by making the static variables inplicitely inline via constexpr).

avoid-static-const-v2.patch (61,217 bytes)   
Index: common/Logging.h
===================================================================
--- common/Logging.h	(revision 12372)
+++ common/Logging.h	(working copy)
@@ -113,7 +113,7 @@
 // All logging code gets compiled and immediately dead-code eliminated.
 #define MPT_LOG_IS_DISABLED
 #endif
-static const int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
+static constexpr int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
 #else
 extern int GlobalLogLevel;
 #endif
Index: common/misc_util.cpp
===================================================================
--- common/misc_util.cpp	(revision 12372)
+++ common/misc_util.cpp	(working copy)
@@ -20,7 +20,7 @@
 {
 
 
-static const mpt::uchar EncodeNibble[16] = {
+static constexpr mpt::uchar EncodeNibble[16] = {
 	UC_('0'), UC_('1'), UC_('2'), UC_('3'),
 	UC_('4'), UC_('5'), UC_('6'), UC_('7'),
 	UC_('8'), UC_('9'), UC_('A'), UC_('B'),
Index: common/mptCPU.h
===================================================================
--- common/mptCPU.h	(revision 12372)
+++ common/mptCPU.h	(working copy)
@@ -31,10 +31,10 @@
 #define PROCSUPPORT_AVX          0x10000 // Processor supports AVX instructions
 #define PROCSUPPORT_AVX2         0x20000 // Processor supports AVX2 instructions
 
-static const uint32 PROCSUPPORT_i586     = 0u                                                      ;
-static const uint32 PROCSUPPORT_x86_SSE  = 0u | PROCSUPPORT_SSE                                    ;
-static const uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2                 ;
-static const uint32 PROCSUPPORT_AMD64    = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
+static constexpr uint32 PROCSUPPORT_i586     = 0u                                                      ;
+static constexpr uint32 PROCSUPPORT_x86_SSE  = 0u | PROCSUPPORT_SSE                                    ;
+static constexpr uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2                 ;
+static constexpr uint32 PROCSUPPORT_AMD64    = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
 
 #endif
 
Index: common/mptRandom.h
===================================================================
--- common/mptRandom.h	(revision 12372)
+++ common/mptRandom.h	(working copy)
@@ -44,7 +44,7 @@
 
 
 #ifdef MPT_BUILD_FUZZER
-static const uint32 FUZZER_RNG_SEED = 3141592653u; // pi
+static constexpr uint32 FUZZER_RNG_SEED = 3141592653u; // pi
 #endif // MPT_BUILD_FUZZER
 
 
Index: common/mptTime.cpp
===================================================================
--- common/mptTime.cpp	(revision 12372)
+++ common/mptTime.cpp	(working copy)
@@ -47,7 +47,7 @@
 
 mpt::ustring ToUString(uint64 time100ns)
 {
-	static const std::size_t bufsize = 256;
+	constexpr std::size_t bufsize = 256;
 
 	mpt::ustring result;
 
Index: common/Profiler.cpp
===================================================================
--- common/Profiler.cpp	(revision 12372)
+++ common/Profiler.cpp	(working copy)
@@ -52,7 +52,7 @@
 	class Statistics * stats;
 };
 
-static const std::size_t MAX_PROFILES = 1024;
+static constexpr std::size_t MAX_PROFILES = 1024;
 
 static ProfileBlock Profiles[ MAX_PROFILES ];
 
Index: mptrack/AboutDialog.h
===================================================================
--- mptrack/AboutDialog.h	(revision 12372)
+++ mptrack/AboutDialog.h	(working copy)
@@ -20,7 +20,7 @@
 
 public:
 
-	static const DWORD UPDATE_INTERVAL = 15; // milliseconds
+	static constexpr DWORD UPDATE_INTERVAL = 15; // milliseconds
 
 protected:
 
@@ -60,7 +60,7 @@
 	CTabCtrl m_Tab;
 	CEdit m_TabEdit;
 	UINT_PTR m_TimerID = 0;
-	static const UINT_PTR TIMERID_ABOUT_DEFAULT = 3;
+	static constexpr UINT_PTR TIMERID_ABOUT_DEFAULT = 3;
 
 public:
 	static CAboutDlg *instance;
Index: mptrack/ColorConfigDlg.cpp
===================================================================
--- mptrack/ColorConfigDlg.cpp	(revision 12372)
+++ mptrack/ColorConfigDlg.cpp	(working copy)
@@ -19,7 +19,7 @@
 
 OPENMPT_NAMESPACE_BEGIN
 
-static const struct ColorDescriptions
+static constexpr struct ColorDescriptions
 {
 	const TCHAR *name;
 	int previewImage;
Index: mptrack/Ctrl_pat.cpp
===================================================================
--- mptrack/Ctrl_pat.cpp	(revision 12372)
+++ mptrack/Ctrl_pat.cpp	(working copy)
@@ -269,7 +269,7 @@
 		CString s;
 		if(updateAll || updateSmpNames || updateInsNames)
 		{
-			static const TCHAR szSplitFormat[] = _T("%02u %s %02u: %s/%s");
+			constexpr TCHAR szSplitFormat[] = _T("%02u %s %02u: %s/%s");
 			UINT nPos = 0;
 			m_CbnInstrument.SetRedraw(FALSE);
 			m_CbnInstrument.ResetContent();
Index: mptrack/Ctrl_smp.cpp
===================================================================
--- mptrack/Ctrl_smp.cpp	(revision 12372)
+++ mptrack/Ctrl_smp.cpp	(working copy)
@@ -2237,7 +2237,7 @@
 		memcpy(pNewSample, sample.sampleb(), selection.nStart * sample.GetBytesPerSample());
 		memcpy(static_cast<std::byte *>(pNewSample) + stretchEnd * sample.GetBytesPerSample(), sample.sampleb() + selection.nEnd * sample.GetBytesPerSample(), (sample.nLength - selection.nEnd) * sample.GetBytesPerSample());
 
-		static const SmpLength MaxInputChunkSize = 1024;
+		constexpr SmpLength MaxInputChunkSize = 1024;
 
 		std::vector<float> buffer(MaxInputChunkSize * numChannels);
 		std::vector<SC::Convert<float, int16>> convf32(numChannels);
Index: mptrack/dlg_misc.cpp
===================================================================
--- mptrack/dlg_misc.cpp	(revision 12372)
+++ mptrack/dlg_misc.cpp	(working copy)
@@ -826,8 +826,8 @@
 ////////////////////////////////////////////////////////////////////////////////////////////
 // Keyboard Control
 
-static const uint8 whitetab[7] = {0,2,4,5,7,9,11};
-static const uint8 blacktab[7] = {0xff,1,3,0xff,6,8,10};
+static constexpr uint8 whitetab[7] = {0,2,4,5,7,9,11};
+static constexpr uint8 blacktab[7] = {0xff,1,3,0xff,6,8,10};
 
 BEGIN_MESSAGE_MAP(CKeyboardControl, CWnd)
 	ON_WM_DESTROY()
Index: mptrack/EffectInfo.cpp
===================================================================
--- mptrack/EffectInfo.cpp	(revision 12372)
+++ mptrack/EffectInfo.cpp	(working copy)
@@ -47,7 +47,7 @@
 #define MOD_TYPE_ALL		(~ModType(0))
 
 
-static const MPTEFFECTINFO gFXInfo[] =
+static constexpr MPTEFFECTINFO gFXInfo[] =
 {
 	{CMD_ARPEGGIO,		0,0,		0,	MOD_TYPE_ALL,	_T("Arpeggio")},
 	{CMD_PORTAMENTOUP,	0,0,		0,	MOD_TYPE_ALL,	_T("Portamento Up")},
@@ -872,7 +872,7 @@
 	FlagSet<MODTYPE> GetSupportedFormats() const { return FlagSet<MODTYPE>(supportedFormats); }
 };
 
-static const MPTVOLCMDINFO gVolCmdInfo[] =
+static constexpr MPTVOLCMDINFO gVolCmdInfo[] =
 {
 	{VOLCMD_VOLUME,			MOD_TYPE_NOMOD,		_T("Set Volume")},
 	{VOLCMD_PANNING,		MOD_TYPE_NOMOD,		_T("Set Panning")},
Index: mptrack/GeneralConfigDlg.cpp
===================================================================
--- mptrack/GeneralConfigDlg.cpp	(revision 12372)
+++ mptrack/GeneralConfigDlg.cpp	(working copy)
@@ -33,7 +33,7 @@
 END_MESSAGE_MAP()
 
 
-static const struct GeneralOptionsDescriptions
+static constexpr struct GeneralOptionsDescriptions
 {
 	uint32 flag;
 	const char *name, *description;
Index: mptrack/IPCWindow.cpp
===================================================================
--- mptrack/IPCWindow.cpp	(revision 12372)
+++ mptrack/IPCWindow.cpp	(working copy)
@@ -20,7 +20,7 @@
 namespace IPCWindow
 {
 
-	static const TCHAR ClassName[] = _T("OpenMPT_IPC_Wnd");
+	static constexpr TCHAR ClassName[] = _T("OpenMPT_IPC_Wnd");
 	static HWND ipcWindow = nullptr;
 
 	static LRESULT CALLBACK IPCWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Index: mptrack/Mainfrm.h
===================================================================
--- mptrack/Mainfrm.h	(revision 12372)
+++ mptrack/Mainfrm.h	(working copy)
@@ -207,7 +207,7 @@
 class VUMeter
 {
 public:
-	static const std::size_t maxChannels = 4;
+	static constexpr std::size_t maxChannels = 4;
 	static const float dynamicRange; // corresponds to the current implementation of the UI widget diplaying the result
 	struct Channel
 	{
@@ -548,8 +548,8 @@
 	afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
 
 	// Defines maximum number of items in example modules menu.
-	static const size_t nMaxItemsInExampleModulesMenu = 50;
-	static const size_t nMaxItemsInTemplateModulesMenu = 50;
+	static constexpr size_t nMaxItemsInExampleModulesMenu = 50;
+	static constexpr size_t nMaxItemsInTemplateModulesMenu = 50;
 
 	/// Array of paths of example modules that are available from help menu.
 	std::vector<mpt::PathString> m_ExampleModulePaths;
Index: mptrack/Modedit.cpp
===================================================================
--- mptrack/Modedit.cpp	(revision 12372)
+++ mptrack/Modedit.cpp	(working copy)
@@ -999,8 +999,8 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 // Copy/Paste envelope
 
-static const CHAR *pszEnvHdr = "ModPlug Tracker Envelope\r\n";
-static const CHAR *pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\r\n";
+static constexpr const CHAR *pszEnvHdr = "ModPlug Tracker Envelope\r\n";
+static constexpr const CHAR *pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\r\n";
 
 static bool EnvelopeToString(CStringA &s, const InstrumentEnvelope &env)
 {
Index: mptrack/Mpdlgs.cpp
===================================================================
--- mptrack/Mpdlgs.cpp	(revision 12372)
+++ mptrack/Mpdlgs.cpp	(working copy)
@@ -206,7 +206,7 @@
 	}
 	// latency
 	{
-		static const double latencies [] = {
+		static constexpr double latencies [] = {
 			0.001,
 			0.002,
 			0.003,
@@ -250,7 +250,7 @@
 	}
 	// update interval
 	{
-		static const double updateIntervals [] = {
+		static constexpr double updateIntervals [] = {
 			0.001,
 			0.002,
 			0.005,
Index: mptrack/Mptrack.h
===================================================================
--- mptrack/Mptrack.h	(revision 12372)
+++ mptrack/Mptrack.h	(working copy)
@@ -340,7 +340,7 @@
 class CFastBitmap
 {
 protected:
-	static const uint8 BLEND_OFFSET = 0x80;
+	static constexpr uint8 BLEND_OFFSET = 0x80;
 
 	struct MODPLUGFASTDIB
 	{
Index: mptrack/Notification.h
===================================================================
--- mptrack/Notification.h	(revision 12372)
+++ mptrack/Notification.h	(working copy)
@@ -33,8 +33,8 @@
 
 	typedef uint16 Item;
 
-	static const SmpLength PosInvalid = SmpLength(-1);	// pos[i] is not valid (if it contains sample or envelope position)
-	static const uint32 ClipVU = 0x80000000;			// Master VU clip indicator bit (sound output has previously clipped)
+	static constexpr SmpLength PosInvalid = SmpLength(-1);	// pos[i] is not valid (if it contains sample or envelope position)
+	static constexpr uint32 ClipVU = 0x80000000;			// Master VU clip indicator bit (sound output has previously clipped)
 
 	int64 timestampSamples;
 	FlagSet<Notification::Type> type;
Index: mptrack/OPLInstrDlg.cpp
===================================================================
--- mptrack/OPLInstrDlg.cpp	(revision 12372)
+++ mptrack/OPLInstrDlg.cpp	(working copy)
@@ -132,7 +132,7 @@
 // Swap OPL Key Scale Level bits for a "human-readable" value.
 static uint8 KeyScaleLevel(uint8 kslVolume)
 {
-	static const uint8 KSLFix[4] = { 0x00, 0x80, 0x40, 0xC0 };
+	static constexpr uint8 KSLFix[4] = { 0x00, 0x80, 0x40, 0xC0 };
 	return KSLFix[kslVolume >> 6];
 }
 
@@ -163,7 +163,7 @@
 		if(numWaveforms != m_waveform[op].GetCount())
 		{
 			m_waveform[op].ResetContent();
-			static const TCHAR *waveformNames[] =
+			static constexpr const TCHAR *waveformNames[] =
 			{
 				_T("Sine"), _T("Half Sine"), _T("Absolute Sine"), _T("Pulse Sine"),
 				_T("Sine (Even Periods)"), _T("Absolute Sine (Even Periods)"), _T("Square"), _T("Derived Square")
Index: mptrack/plugins/LFOPluginEditor.h
===================================================================
--- mptrack/plugins/LFOPluginEditor.h	(revision 12372)
+++ mptrack/plugins/LFOPluginEditor.h	(working copy)
@@ -28,7 +28,7 @@
 	CSpinButtonCtrl m_midiChnSpin;
 	LFOPlugin &m_lfoPlugin;
 	bool m_locked : 1;
-	static const int SLIDER_GRANULARITY = 1000;
+	static constexpr int SLIDER_GRANULARITY = 1000;
 
 public:
 
Index: mptrack/SampleEditorDialogs.h
===================================================================
--- mptrack/SampleEditorDialogs.h	(revision 12372)
+++ mptrack/SampleEditorDialogs.h	(working copy)
@@ -62,7 +62,7 @@
 	bool m_bRememberFormat;
 
 public:
-	static const SampleIO GetSampleFormat() { return m_nFormat; }
+	static SampleIO GetSampleFormat() { return m_nFormat; }
 	static void SetSampleFormat(SampleIO nFormat) { m_nFormat = nFormat; }
 	bool GetRemeberFormat() const { return m_bRememberFormat; };
 	void SetRememberFormat(bool bRemember) { m_bRememberFormat = bRemember; };
Index: mptrack/SampleGenerator.h
===================================================================
--- mptrack/SampleGenerator.h	(revision 12372)
+++ mptrack/SampleGenerator.h	(working copy)
@@ -50,7 +50,7 @@
 	static size_t samples_written;
 
 	typedef int16 sampling_type; // has to match SMPGEN_MIXBYTES!
-	static const sampling_type sample_maxvalue = (1 << ((SMPGEN_MIXBYTES << 3) - 1)) - 1;
+	static constexpr sampling_type sample_maxvalue = (1 << ((SMPGEN_MIXBYTES << 3) - 1)) - 1;
 
 	// muParser object for parsing the expression
 	mu::Parser muParser;
Index: mptrack/SelectPluginDialog.cpp
===================================================================
--- mptrack/SelectPluginDialog.cpp	(revision 12372)
+++ mptrack/SelectPluginDialog.cpp	(working copy)
@@ -296,7 +296,7 @@
 	m_treePlugins.SetRedraw(FALSE);
 	m_treePlugins.DeleteAllItems();
 
-	static const struct
+	static constexpr struct
 	{
 		VSTPluginLib::PluginCategory category;
 		const TCHAR *description;
Index: mptrack/StreamEncoderMP3.cpp
===================================================================
--- mptrack/StreamEncoderMP3.cpp	(revision 12372)
+++ mptrack/StreamEncoderMP3.cpp	(working copy)
@@ -709,7 +709,7 @@
 #ifdef MPT_WITH_LAME
 	if(m_Type == MP3EncoderLame)
 	{
-		static const int q_table[11] = { 240, 220, 190, 170, 160, 130, 120, 100, 80, 70, 50 }; // http://wiki.hydrogenaud.io/index.php?title=LAME
+		static constexpr int q_table[11] = { 240, 220, 190, 170, 160, 130, 120, 100, 80, 70, 50 }; // http://wiki.hydrogenaud.io/index.php?title=LAME
 		int q = mpt::saturate_round<int>((1.0f - quality) * 10.0f);
 		if(q < 0) q = 0;
 		if(q >= 10)
Index: mptrack/StreamEncoderVorbis.cpp
===================================================================
--- mptrack/StreamEncoderVorbis.cpp	(revision 12372)
+++ mptrack/StreamEncoderVorbis.cpp	(working copy)
@@ -249,7 +249,7 @@
 
 mpt::ustring VorbisEncoder::DescribeQuality(float quality) const
 {
-	static const int q_table[11] = { 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500 }; // http://wiki.hydrogenaud.io/index.php?title=Recommended_Ogg_Vorbis
+	static constexpr int q_table[11] = { 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500 }; // http://wiki.hydrogenaud.io/index.php?title=Recommended_Ogg_Vorbis
 	int q = Clamp(mpt::saturate_round<int>(quality * 10.0f), 0, 10);
 	return mpt::format(U_("Q%1 (~%2 kbit)"))(mpt::ufmt::fix(quality * 10.0f, 1), q_table[q]);
 }
Index: mptrack/TrackerSettings.h
===================================================================
--- mptrack/TrackerSettings.h	(revision 12372)
+++ mptrack/TrackerSettings.h	(working copy)
@@ -156,7 +156,7 @@
 	uint32 Freqs[MAX_EQ_BANDS];
 };
 
-static const EQPreset FlatEQPreset = { "Flat", {16,16,16,16,16,16}, { 125, 300, 600, 1250, 4000, 8000 } };
+constexpr EQPreset FlatEQPreset = { "Flat", {16,16,16,16,16,16}, { 125, 300, 600, 1250, 4000, 8000 } };
 
 template<> inline SettingValue ToSettingValue(const EQPreset &val)
 {
Index: mptrack/TuningDialog.h
===================================================================
--- mptrack/TuningDialog.h	(revision 12372)
+++ mptrack/TuningDialog.h	(working copy)
@@ -320,7 +320,7 @@
 	};
 
 	static CString GetSclImportFailureMsg(EnSclImport);
-	static const size_t s_nSclImportMaxNoteCount = 256;
+	static constexpr size_t s_nSclImportMaxNoteCount = 256;
 
 	//To indicate whether to apply changes made to
 	//those edit boxes(they are modified by certain activities
Index: mptrack/UpdateHints.h
===================================================================
--- mptrack/UpdateHints.h	(revision 12372)
+++ mptrack/UpdateHints.h	(working copy)
@@ -133,7 +133,7 @@
 
 struct GeneralHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_GENERAL;
+	static constexpr HintCategory classCategory = HINTCAT_GENERAL;
 	GeneralHint(int channelTab = 0) : UpdateHint(classCategory, channelTab) { }
 	MPT_FORCEINLINE GeneralHint &General() { type |= HINT_MODGENERAL; return *this; }
 	MPT_FORCEINLINE GeneralHint &Channels() { type |= HINT_MODCHANNELS; return *this; }
@@ -144,7 +144,7 @@
 
 struct PatternHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PATTERNS;
+	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	PatternHint(PATTERNINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE PatternHint &Data() { type |= HINT_PATTERNDATA; return *this; }
 	MPT_FORCEINLINE PatternHint &Names() { type |= HINT_PATNAMES; return *this; }
@@ -154,7 +154,7 @@
 
 struct RowHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PATTERNS;
+	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	RowHint(ROWINDEX item = 0) : UpdateHint(classCategory, item) { type = HINT_PATTERNROW; }
 
 	MPT_FORCEINLINE ROWINDEX GetRow() const { return GetData<ROWINDEX>(); }
@@ -162,7 +162,7 @@
 
 struct SampleHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_SAMPLES;
+	static constexpr HintCategory classCategory = HINTCAT_SAMPLES;
 	SampleHint(SAMPLEINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE SampleHint &Info() { type |= HINT_SAMPLEINFO; return *this; }
 	MPT_FORCEINLINE SampleHint &Data() { type |= HINT_SAMPLEDATA; return *this; }
@@ -173,7 +173,7 @@
 
 struct InstrumentHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_INSTRUMENTS;
+	static constexpr HintCategory classCategory = HINTCAT_INSTRUMENTS;
 	InstrumentHint(INSTRUMENTINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE InstrumentHint &Info() { type |= HINT_INSTRUMENT; return *this; }
 	MPT_FORCEINLINE InstrumentHint &Envelope() { type |= HINT_ENVELOPE; return *this; }
@@ -184,7 +184,7 @@
 
 struct SequenceHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_SEQUENCE;
+	static constexpr HintCategory classCategory = HINTCAT_SEQUENCE;
 	SequenceHint(SEQUENCEINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE SequenceHint &Data() { type |= HINT_MODSEQUENCE; return *this; }
 	MPT_FORCEINLINE SequenceHint &Names() { type |= HINT_SEQNAMES; return *this; }
@@ -195,7 +195,7 @@
 
 struct PluginHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PLUGINS;
+	static constexpr HintCategory classCategory = HINTCAT_PLUGINS;
 	PluginHint(PLUGINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE PluginHint &Info() { type |= HINT_MIXPLUGINS; return *this; }
 	MPT_FORCEINLINE PluginHint &Names() { type |= HINT_PLUGINNAMES; return *this; }
@@ -206,7 +206,7 @@
 
 struct CommentHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_COMMENTS;
+	static constexpr HintCategory classCategory = HINTCAT_COMMENTS;
 	CommentHint() : UpdateHint(classCategory) { type = HINT_MODCOMMENTS; }
 };
 
Index: mptrack/View_ins.cpp
===================================================================
--- mptrack/View_ins.cpp	(revision 12372)
+++ mptrack/View_ins.cpp	(working copy)
@@ -46,7 +46,7 @@
 #define ENV_LEFTBAR_CYBTN		Util::ScalePixels(22, m_hWnd)
 
 
-static const UINT cLeftBarButtons[ENV_LEFTBAR_BUTTONS] =
+static constexpr UINT cLeftBarButtons[ENV_LEFTBAR_BUTTONS] =
 {
 	ID_ENVSEL_VOLUME,
 	ID_ENVSEL_PANNING,
Index: mptrack/View_pat.cpp
===================================================================
--- mptrack/View_pat.cpp	(revision 12372)
+++ mptrack/View_pat.cpp	(working copy)
@@ -2774,7 +2774,7 @@
 	BeginWaitCursor();
 	pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, sndFile.GetNumChannels(), sndFile.Patterns[m_nPattern].GetNumRows(), moveSelection ? "Move Selection" : "Copy Selection");
 
-	static const ModCommand empty = ModCommand::Empty();
+	const ModCommand empty = ModCommand::Empty();
 	auto p = pattern.begin();
 	for(ROWINDEX row = 0; row < sndFile.Patterns[m_nPattern].GetNumRows(); row++)
 	{
@@ -6915,8 +6915,8 @@
 	const ModCommand &m = GetCursorCommand();
 	const size_t columnIndex = m_Cursor.GetColumnType();
 	const TCHAR *column = _T("");
-	static const TCHAR *regularColumns[] = {_T("Note"), _T("Instrument"), _T("Volume"), _T("Effect"), _T("Parameter")};
-	static const TCHAR *pcColumns[] = {_T("Note"), _T("Plugin"), _T("Plugin Parameter"), _T("Parameter Value"), _T("Parameter Value")};
+	static constexpr const TCHAR *regularColumns[] = {_T("Note"), _T("Instrument"), _T("Volume"), _T("Effect"), _T("Parameter")};
+	static constexpr const TCHAR *pcColumns[] = {_T("Note"), _T("Plugin"), _T("Plugin Parameter"), _T("Parameter Value"), _T("Parameter Value")};
 	static_assert(PatternCursor::lastColumn + 1 == std::size(regularColumns));
 	static_assert(PatternCursor::lastColumn + 1 == std::size(pcColumns));
 
Index: mptrack/View_smp.cpp
===================================================================
--- mptrack/View_smp.cpp	(revision 12372)
+++ mptrack/View_smp.cpp	(working copy)
@@ -53,7 +53,7 @@
 // of trimming is nTrimLengthMin + 1.
 #define MIN_TRIM_LENGTH			4
 
-static const UINT cLeftBarButtons[SMP_LEFTBAR_BUTTONS] =
+static constexpr UINT cLeftBarButtons[SMP_LEFTBAR_BUTTONS] =
 {
 	ID_SAMPLE_ZOOMUP,
 	ID_SAMPLE_ZOOMDOWN,
Index: mptrack/View_tre.cpp
===================================================================
--- mptrack/View_tre.cpp	(revision 12372)
+++ mptrack/View_tre.cpp	(working copy)
@@ -1972,12 +1972,12 @@
 		if((hFind = FindFirstFile(path.AsNative().c_str(), &wfd)) != INVALID_HANDLE_VALUE)
 		{
 			static constexpr int FILTER_REJECT_FILE = -1;
-			static const auto modExts = CSoundFile::GetSupportedExtensions(false);
-			static const auto instrExts = {"xi", "iti", "sfz", "sf2", "sbk", "dls", "mss", "pat"};
-			static const auto sampleExts = {"wav", "flac", "ogg", "opus", "mp1", "mp2", "mp3", "smp", "raw", "s3i", "its", "aif", "aiff", "au", "snd", "svx", "voc", "8sv", "8svx", "16sv", "16svx", "w64", "caf", "sb0", "sb2", "sbi"};
-			static const auto allExtsBlacklist = {"txt", "diz", "nfo", "doc", "ini", "pdf", "zip", "rar", "lha", "exe", "dll", "lnk", "url"};
+			auto modExts = CSoundFile::GetSupportedExtensions(false);
+			static constexpr auto instrExts = {"xi", "iti", "sfz", "sf2", "sbk", "dls", "mss", "pat"};
+			static constexpr auto sampleExts = {"wav", "flac", "ogg", "opus", "mp1", "mp2", "mp3", "smp", "raw", "s3i", "its", "aif", "aiff", "au", "snd", "svx", "voc", "8sv", "8svx", "16sv", "16svx", "w64", "caf", "sb0", "sb2", "sbi"};
+			static constexpr auto allExtsBlacklist = {"txt", "diz", "nfo", "doc", "ini", "pdf", "zip", "rar", "lha", "exe", "dll", "lnk", "url"};
 
-			const auto FilterFile = [this, showInstrs, showDirs](const mpt::PathString &fileName) -> int
+			const auto FilterFile = [this, modExts, showInstrs, showDirs](const mpt::PathString &fileName) -> int
 			{
 				// Get lower-case file extension without dot.
 				mpt::PathString extPS = fileName.GetFileExt();
Index: mptrack/Vstplug.cpp
===================================================================
--- mptrack/Vstplug.cpp	(revision 12372)
+++ mptrack/Vstplug.cpp	(working copy)
@@ -1463,7 +1463,7 @@
 
 void CVstPlugin::HardAllNotesOff()
 {
-	static const uint32 SCRATCH_BUFFER_SIZE = 64;
+	constexpr uint32 SCRATCH_BUFFER_SIZE = 64;
 	float out[2][SCRATCH_BUFFER_SIZE]; // scratch buffers
 
 	// The JUCE framework doesn't like processing while being suspended.
Index: pluginBridge/BridgeCommon.h
===================================================================
--- pluginBridge/BridgeCommon.h	(revision 12372)
+++ pluginBridge/BridgeCommon.h	(working copy)
@@ -570,7 +570,7 @@
 
 	static void CreateCommunicationWindow(WNDPROC windowProc)
 	{
-		static const TCHAR windowClassName[] = _T("OpenMPTPluginBridgeCommunication");
+		static constexpr TCHAR windowClassName[] = _T("OpenMPTPluginBridgeCommunication");
 		static bool registered = false;
 		if(!registered)
 		{
Index: soundbase/SampleFormatConverters.h
===================================================================
--- soundbase/SampleFormatConverters.h	(revision 12372)
+++ soundbase/SampleFormatConverters.h	(working copy)
@@ -69,7 +69,7 @@
 
 
 // Every sample decoding functor has to typedef its input_t and output_t
-// and has to provide a static const input_inc member
+// and has to provide a static constexpr input_inc member
 // which describes by how many input_t elements inBuf has to be incremented between invocations.
 // input_inc is normally 1 except when decoding e.g. bigger sample values
 // from multiple std::byte values.
@@ -1015,7 +1015,7 @@
 {
 	typedef int32 input_t;
 	typedef uint8 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1032,7 +1032,7 @@
 {
 	typedef int32 input_t;
 	typedef int8 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1049,7 +1049,7 @@
 {
 	typedef int32 input_t;
 	typedef int16 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1066,7 +1066,7 @@
 {
 	typedef int32 input_t;
 	typedef int24 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1135,7 +1135,7 @@
 {
 	typedef uint8 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1149,7 +1149,7 @@
 {
 	typedef int8 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1163,7 +1163,7 @@
 {
 	typedef int16 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1177,7 +1177,7 @@
 {
 	typedef int24 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
Index: sounddev/SoundDevice.h
===================================================================
--- sounddev/SoundDevice.h	(revision 12372)
+++ sounddev/SoundDevice.h	(working copy)
@@ -98,13 +98,13 @@
 };
 
 
-static const mpt::uchar TypeWAVEOUT          [] = UL_("WaveOut");
-static const mpt::uchar TypeDSOUND           [] = UL_("DirectSound");
-static const mpt::uchar TypeASIO             [] = UL_("ASIO");
-static const mpt::uchar TypePORTAUDIO_WASAPI [] = UL_("WASAPI");
-static const mpt::uchar TypePORTAUDIO_WDMKS  [] = UL_("WDM-KS");
-static const mpt::uchar TypePORTAUDIO_WMME   [] = UL_("MME");
-static const mpt::uchar TypePORTAUDIO_DS     [] = UL_("DS");
+static constexpr mpt::uchar TypeWAVEOUT          [] = UL_("WaveOut");
+static constexpr mpt::uchar TypeDSOUND           [] = UL_("DirectSound");
+static constexpr mpt::uchar TypeASIO             [] = UL_("ASIO");
+static constexpr mpt::uchar TypePORTAUDIO_WASAPI [] = UL_("WASAPI");
+static constexpr mpt::uchar TypePORTAUDIO_WDMKS  [] = UL_("WDM-KS");
+static constexpr mpt::uchar TypePORTAUDIO_WMME   [] = UL_("MME");
+static constexpr mpt::uchar TypePORTAUDIO_DS     [] = UL_("DS");
 
 typedef mpt::ustring Type;
 
@@ -242,7 +242,7 @@
 
 public:
 
-	static const int32 MaxDeviceChannel = 32000;
+	static constexpr int32 MaxDeviceChannel = 32000;
 
 public:
 
@@ -628,17 +628,17 @@
 namespace Legacy
 {
 typedef uint16 ID;
-static const SoundDevice::Legacy::ID MaskType = 0xff00;
-static const SoundDevice::Legacy::ID MaskIndex = 0x00ff;
-static const int ShiftType = 8;
-static const int ShiftIndex = 0;
-static const SoundDevice::Legacy::ID TypeWAVEOUT          = 0;
-static const SoundDevice::Legacy::ID TypeDSOUND           = 1;
-static const SoundDevice::Legacy::ID TypeASIO             = 2;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS  = 4;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WMME   = 5;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_DS     = 6;
+static constexpr SoundDevice::Legacy::ID MaskType = 0xff00;
+static constexpr SoundDevice::Legacy::ID MaskIndex = 0x00ff;
+static constexpr int ShiftType = 8;
+static constexpr int ShiftIndex = 0;
+static constexpr SoundDevice::Legacy::ID TypeWAVEOUT          = 0;
+static constexpr SoundDevice::Legacy::ID TypeDSOUND           = 1;
+static constexpr SoundDevice::Legacy::ID TypeASIO             = 2;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS  = 4;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WMME   = 5;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_DS     = 6;
 #if MPT_OS_WINDOWS
 mpt::ustring GetDirectSoundDefaultDeviceIdentifierPre_1_25_00_04();
 mpt::ustring GetDirectSoundDefaultDeviceIdentifier_1_25_00_04();
Index: sounddev/SoundDeviceWaveout.cpp
===================================================================
--- sounddev/SoundDeviceWaveout.cpp	(revision 12372)
+++ sounddev/SoundDeviceWaveout.cpp	(working copy)
@@ -31,10 +31,10 @@
 MPT_REGISTERED_COMPONENT(ComponentWaveOut, "WaveOut")
 
 
-static const std::size_t WAVEOUT_MINBUFFERS = 3;
-static const std::size_t WAVEOUT_MAXBUFFERS = 4096;
-static const std::size_t WAVEOUT_MINBUFFERFRAMECOUNT = 8;
-static const std::size_t WAVEOUT_MAXBUFFERSIZE = 16384; // fits in int16
+static constexpr std::size_t WAVEOUT_MINBUFFERS = 3;
+static constexpr std::size_t WAVEOUT_MAXBUFFERS = 4096;
+static constexpr std::size_t WAVEOUT_MINBUFFERFRAMECOUNT = 8;
+static constexpr std::size_t WAVEOUT_MAXBUFFERSIZE = 16384; // fits in int16
 
 
 static inline LONG* interlocked_access(DWORD* p)
@@ -436,12 +436,12 @@
 	// We could thereby try to avoid any potential wraparound inside the driver on older
 	// Windows versions, which would be, once converted into other units, really
 	// difficult to detect or handle.
-	static const UINT timeType = TIME_SAMPLES; // should work for sane systems
-	//static const std::size_t valid_bits = 32; // should work for sane systems
-	//static const UINT timeType = TIME_BYTES; // safest
-	static const std::size_t valid_bits = 27; // safe for WinXP TIME_SAMPLES
-	static const uint32 valid_mask = static_cast<uint32>((uint64(1) << valid_bits) - 1u);
-	static const uint32 valid_watermark = static_cast<uint32>(uint64(1) << (valid_bits - 1u)); // half the valid range in order to be able to catch backwards fluctuations
+	static constexpr UINT timeType = TIME_SAMPLES; // should work for sane systems
+	//static constexpr std::size_t valid_bits = 32; // should work for sane systems
+	//static constexpr UINT timeType = TIME_BYTES; // safest
+	static constexpr std::size_t valid_bits = 27; // safe for WinXP TIME_SAMPLES
+	static constexpr uint32 valid_mask = static_cast<uint32>((uint64(1) << valid_bits) - 1u);
+	static constexpr uint32 valid_watermark = static_cast<uint32>(uint64(1) << (valid_bits - 1u)); // half the valid range in order to be able to catch backwards fluctuations
 
 	MMTIME mmtime;
 	MemsetZero(mmtime);
Index: sounddev/SoundDeviceWaveout.h
===================================================================
--- sounddev/SoundDeviceWaveout.h	(revision 12372)
+++ sounddev/SoundDeviceWaveout.h	(working copy)
@@ -60,11 +60,11 @@
 	mutable MMTIME m_PositionLast;
 	mutable std::size_t m_PositionWrappedCount;
 
-	static const uint32 DriverBugDoneNotificationAndHeaderInQueue = (1u<<0u); //  1
-	static const uint32 DriverBugDoneNotificationAndHeaderNotDone = (1u<<1u); //  2
-	static const uint32 DriverBugBufferFillAndHeaderInQueue = (1u<<2u);       //  4
-	static const uint32 DriverBugBufferFillAndHeaderNotDone = (1u<<3u);       //  8
-	static const uint32 DriverBugDoneNotificationOutOfOrder = (1u<<4u);       // 10
+	static constexpr uint32 DriverBugDoneNotificationAndHeaderInQueue = (1u<<0u); //  1
+	static constexpr uint32 DriverBugDoneNotificationAndHeaderNotDone = (1u<<1u); //  2
+	static constexpr uint32 DriverBugBufferFillAndHeaderInQueue = (1u<<2u);       //  4
+	static constexpr uint32 DriverBugBufferFillAndHeaderNotDone = (1u<<3u);       //  8
+	static constexpr uint32 DriverBugDoneNotificationOutOfOrder = (1u<<4u);       // 10
 	std::atomic<uint32> m_DriverBugs;
 
 public:
Index: sounddsp/EQ.cpp
===================================================================
--- sounddsp/EQ.cpp	(revision 12372)
+++ sounddsp/EQ.cpp	(working copy)
@@ -27,7 +27,7 @@
 
 
 
-static const UINT gEqLinearToDB[33] =
+static constexpr UINT gEqLinearToDB[33] =
 {
 	16, 19, 22, 25, 28, 31, 34, 37,
 	40, 43, 46, 49, 52, 55, 58, 61,
@@ -35,7 +35,7 @@
 	160, 172, 184, 196, 208, 220, 232, 244, 256
 };
 
-static const EQBANDSTRUCT gEQDefaults[MAX_EQ_BANDS*2] =
+static constexpr EQBANDSTRUCT gEQDefaults[MAX_EQ_BANDS*2] =
 {
 	// Default: Flat EQ
 	{0,0,0,0,0, 0,0,0,0, 1,   120, false},
@@ -119,7 +119,7 @@
 
 static void SSE_StereoEQ(EQBANDSTRUCT *pbl, EQBANDSTRUCT *pbr, float32 *pbuffer, UINT nCount)
 {
-	static const float gk1 = 1.0f;
+	static constexpr float gk1 = 1.0f;
 	_asm {
 	mov eax, pbl
 	mov edx, pbr
Index: soundlib/ContainerMMCMP.cpp
===================================================================
--- soundlib/ContainerMMCMP.cpp	(revision 12372)
+++ soundlib/ContainerMMCMP.cpp	(working copy)
@@ -74,23 +74,23 @@
 #define MMCMP_ABS16		0x0200
 #define MMCMP_ENDIAN	0x0400
 
-static const uint8 MMCMP8BitCommands[8] =
+static constexpr uint8 MMCMP8BitCommands[8] =
 {
 	0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8
 };
 
-static const uint8 MMCMP8BitFetch[8] =
+static constexpr uint8 MMCMP8BitFetch[8] =
 {
 	3, 3, 3, 3, 2, 1, 0, 0
 };
 
-static const uint16 MMCMP16BitCommands[16] =
+static constexpr uint16 MMCMP16BitCommands[16] =
 {
 	0x01,  0x03,  0x07,  0x0F,  0x1E,   0x3C,   0x78,   0xF0,
 	0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
 };
 
-static const uint8 MMCMP16BitFetch[16] =
+static constexpr uint8 MMCMP16BitFetch[16] =
 {
 	4, 4, 4, 4, 3, 2, 1, 0,
 	0, 0, 0, 0, 0, 0, 0, 0
Index: soundlib/ContainerXPK.cpp
===================================================================
--- soundlib/ContainerXPK.cpp	(revision 12372)
+++ soundlib/ContainerXPK.cpp	(working copy)
@@ -104,7 +104,7 @@
 
 static uint8 XPK_ReadTable(int32 index)
 {
-	static const uint8 xpk_table[] = {
+	static constexpr uint8 xpk_table[] = {
 		2,3,4,5,6,7,8,0,3,2,4,5,6,7,8,0,4,3,5,2,6,7,8,0,5,4,6,2,3,7,8,0,6,5,7,2,3,4,8,0,7,6,8,2,3,4,5,0,8,7,6,2,3,4,5,0
 	};
 	if(index < 0) throw XPK_error();
Index: soundlib/Load_amf.cpp
===================================================================
--- soundlib/Load_amf.cpp	(revision 12372)
+++ soundlib/Load_amf.cpp	(working copy)
@@ -263,7 +263,7 @@
 		} else
 		{
 			// Effect
-			static const ModCommand::COMMAND effTrans[] =
+			static constexpr ModCommand::COMMAND effTrans[] =
 			{
 				CMD_NONE,			CMD_SPEED,			CMD_VOLUMESLIDE,		CMD_VOLUME,
 				CMD_PORTAMENTOUP,	CMD_NONE,			CMD_TONEPORTAMENTO,		CMD_TREMOR,
Index: soundlib/Load_ams.cpp
===================================================================
--- soundlib/Load_ams.cpp	(revision 12372)
+++ soundlib/Load_ams.cpp	(working copy)
@@ -42,7 +42,7 @@
 	};
 
 	// Effect translation table for extended (non-Protracker) effects
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_S3MCMDEX,		// Forward / Backward
 		CMD_PORTAMENTOUP,	// Extra fine slide up
Index: soundlib/Load_c67.cpp
===================================================================
--- soundlib/Load_c67.cpp	(revision 12372)
+++ soundlib/Load_c67.cpp	(working copy)
@@ -104,7 +104,7 @@
 	// CDFM uses a linear volume scale for FM instruments.
 	// ScreamTracker, on the other hand, directly uses the OPL chip's logarithmic volume scale.
 	// Neither FM nor PCM instruments can be fully muted in CDFM.
-	static const uint8 fmVolume[16] =
+	static constexpr uint8 fmVolume[16] =
 	{
 		0x08, 0x10, 0x18, 0x20, 0x28, 0x2C, 0x30, 0x34,
 		0x36, 0x38, 0x3A, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
Index: soundlib/Load_dbm.cpp
===================================================================
--- soundlib/Load_dbm.cpp	(revision 12372)
+++ soundlib/Load_dbm.cpp	(working copy)
@@ -127,7 +127,7 @@
 
 
 // Note: Unlike in MOD, 1Fx, 2Fx, 5Fx / 5xF, 6Fx / 6xF and AFx / AxF are fine slides.
-static const ModCommand::COMMAND dbmEffects[] =
+static constexpr ModCommand::COMMAND dbmEffects[] =
 {
 	CMD_ARPEGGIO, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 	CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_far.cpp
===================================================================
--- soundlib/Load_far.cpp	(revision 12372)
+++ soundlib/Load_far.cpp	(working copy)
@@ -201,7 +201,7 @@
 	file.Seek(fileHeader.headerLength);
 	
 	// Pattern effect LUT
-	static const EffectCommand farEffects[] =
+	static constexpr EffectCommand farEffects[] =
 	{
 		CMD_NONE,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_gdm.cpp
===================================================================
--- soundlib/Load_gdm.cpp	(revision 12372)
+++ soundlib/Load_gdm.cpp	(working copy)
@@ -90,15 +90,15 @@
 MPT_BINARY_STRUCT(GDMSampleHeader, 62)
 
 
-static const MODTYPE gdmFormatOrigin[] =
+static constexpr MODTYPE gdmFormatOrigin[] =
 {
 	MOD_TYPE_NONE, MOD_TYPE_MOD, MOD_TYPE_MTM, MOD_TYPE_S3M, MOD_TYPE_669, MOD_TYPE_FAR, MOD_TYPE_ULT, MOD_TYPE_STM, MOD_TYPE_MED, MOD_TYPE_PSM
 };
-static const mpt::uchar gdmFormatOriginType[][4] =
+static constexpr mpt::uchar gdmFormatOriginType[][4] =
 {
 	UL_(""), UL_("mod"), UL_("mtm"), UL_("s3m"), UL_("669"), UL_("far"), UL_("ult"), UL_("stm"), UL_("med"), UL_("psm")
 };
-static const mpt::uchar * const gdmFormatOriginFormat[] =
+static constexpr const mpt::uchar * gdmFormatOriginFormat[] =
 {
 	UL_(""),
 	UL_("Generic MOD"),
@@ -243,7 +243,7 @@
 		{
 			// Use the same inaccurate table as 2GDM for translating back to finetune, as our own routines
 			// give slightly different results for the provided sample rates that may result in transpose != 0.
-			static const uint16 rate2finetune[] = { 8363, 8424, 8485, 8547, 8608, 8671, 8734, 8797, 7894, 7951, 8009, 8067, 8125, 8184, 8244, 8303 };
+			static constexpr uint16 rate2finetune[] = { 8363, 8424, 8485, 8547, 8608, 8671, 8734, 8797, 7894, 7951, 8009, 8067, 8125, 8184, 8244, 8303 };
 			for(uint8 i = 0; i < 16; i++)
 			{
 				if(sample.nC5Speed == rate2finetune[i])
@@ -386,7 +386,7 @@
 						m.param = param;
 
 						// Effect translation LUT
-						static const EffectCommand gdmEffTrans[] =
+						static constexpr EffectCommand gdmEffTrans[] =
 						{
 							CMD_NONE, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 							CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_imf.cpp
===================================================================
--- soundlib/Load_imf.cpp	(revision 12372)
+++ soundlib/Load_imf.cpp	(working copy)
@@ -202,7 +202,7 @@
 MPT_BINARY_STRUCT(IMFSample, 64)
 
 
-static const EffectCommand imfEffects[] =
+static constexpr EffectCommand imfEffects[] =
 {
 	CMD_NONE,
 	CMD_SPEED,			// 0x01 1xx Set Tempo
Index: soundlib/load_j2b.cpp
===================================================================
--- soundlib/load_j2b.cpp	(revision 12372)
+++ soundlib/load_j2b.cpp	(working copy)
@@ -31,7 +31,7 @@
 
 
 // First off, a nice vibrato translation LUT.
-static const VibratoType j2bAutoVibratoTrans[] = 
+static constexpr VibratoType j2bAutoVibratoTrans[] = 
 {
 	VIB_SINE, VIB_SQUARE, VIB_RAMP_UP, VIB_RAMP_DOWN, VIB_RANDOM,
 };
@@ -471,7 +471,7 @@
 static bool ConvertAMPattern(FileReader chunk, PATTERNINDEX pat, bool isAM, CSoundFile &sndFile)
 {
 	// Effect translation LUT
-	static const EffectCommand amEffTrans[] =
+	static constexpr EffectCommand amEffTrans[] =
 	{
 		CMD_ARPEGGIO, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 		CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_mdl.cpp
===================================================================
--- soundlib/Load_mdl.cpp	(revision 12372)
+++ soundlib/Load_mdl.cpp	(working copy)
@@ -154,9 +154,9 @@
 };
 
 
-static const VibratoType MDLVibratoType[] = { VIB_SINE, VIB_RAMP_DOWN, VIB_SQUARE, VIB_SINE };
+static constexpr VibratoType MDLVibratoType[] = { VIB_SINE, VIB_RAMP_DOWN, VIB_SQUARE, VIB_SINE };
 
-static const ModCommand::COMMAND MDLEffTrans[] =
+static constexpr ModCommand::COMMAND MDLEffTrans[] =
 {
 	/* 0 */ CMD_NONE,
 	/* 1st column only */
Index: soundlib/Load_med.cpp
===================================================================
--- soundlib/Load_med.cpp	(revision 12372)
+++ soundlib/Load_med.cpp	(working copy)
@@ -285,7 +285,7 @@
 MPT_BINARY_STRUCT(MMD0EXP, 80)
 
 
-static const uint8 bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
+static constexpr uint8 bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
 
 static void MedConvert(ModCommand &p, const MMD0SONGHEADER *pmsh)
 {
Index: soundlib/Load_mo3.cpp
===================================================================
--- soundlib/Load_mo3.cpp	(revision 12372)
+++ soundlib/Load_mo3.cpp	(working copy)
@@ -1006,7 +1006,7 @@
 	L= 06 00 22 x
 	*/
 
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_NONE,				CMD_NONE,				CMD_NONE,				CMD_ARPEGGIO,
 		CMD_PORTAMENTOUP,		CMD_PORTAMENTODOWN,		CMD_TONEPORTAMENTO,		CMD_VIBRATO,
Index: soundlib/Load_plm.cpp
===================================================================
--- soundlib/Load_plm.cpp	(revision 12372)
+++ soundlib/Load_plm.cpp	(working copy)
@@ -229,7 +229,7 @@
 	const ROWINDEX rowsPerPat = 64;
 	uint32 maxPos = 0;
 
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_NONE,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_ptm.cpp
===================================================================
--- soundlib/Load_ptm.cpp	(revision 12372)
+++ soundlib/Load_ptm.cpp	(working copy)
@@ -252,7 +252,7 @@
 				m.command = command;
 				m.param = param;
 
-				static const EffectCommand effTrans[] = { CMD_GLOBALVOLUME, CMD_RETRIG, CMD_FINEVIBRATO, CMD_NOTESLIDEUP, CMD_NOTESLIDEDOWN, CMD_NOTESLIDEUPRETRIG, CMD_NOTESLIDEDOWNRETRIG, CMD_REVERSEOFFSET };
+				static constexpr EffectCommand effTrans[] = { CMD_GLOBALVOLUME, CMD_RETRIG, CMD_FINEVIBRATO, CMD_NOTESLIDEUP, CMD_NOTESLIDEDOWN, CMD_NOTESLIDEUPRETRIG, CMD_NOTESLIDEDOWNRETRIG, CMD_REVERSEOFFSET };
 				if(m.command < 0x10)
 				{
 					// Beware: Effect letters are as in MOD, but portamento and volume slides behave like in S3M (i.e. fine slides share the same effect letters)
Index: soundlib/Load_s3m.cpp
===================================================================
--- soundlib/Load_s3m.cpp	(revision 12372)
+++ soundlib/Load_s3m.cpp	(working copy)
@@ -602,7 +602,7 @@
 
 bool CSoundFile::SaveS3M(std::ostream &f) const
 {
-	static const uint8 filler[16] =
+	static constexpr uint8 filler[16] =
 	{
 		0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
 		0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
Index: soundlib/Load_stm.cpp
===================================================================
--- soundlib/Load_stm.cpp	(revision 12372)
+++ soundlib/Load_stm.cpp	(working copy)
@@ -258,7 +258,7 @@
 				m->vol = vol;
 			}
 
-			static const EffectCommand stmEffects[] =
+			static constexpr EffectCommand stmEffects[] =
 			{
 				CMD_NONE,        CMD_SPEED,          CMD_POSITIONJUMP, CMD_PATTERNBREAK,   // .ABC
 				CMD_VOLUMESLIDE, CMD_PORTAMENTODOWN, CMD_PORTAMENTOUP, CMD_TONEPORTAMENTO, // DEFG
Index: soundlib/Load_ult.cpp
===================================================================
--- soundlib/Load_ult.cpp	(revision 12372)
+++ soundlib/Load_ult.cpp	(working copy)
@@ -97,7 +97,7 @@
 static void TranslateULTCommands(uint8 &effect, uint8 &param, uint8 version)
 {
 
-	static const uint8 ultEffTrans[] =
+	static constexpr uint8 ultEffTrans[] =
 	{
 		CMD_ARPEGGIO,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_xm.cpp
===================================================================
--- soundlib/Load_xm.cpp	(revision 12372)
+++ soundlib/Load_xm.cpp	(working copy)
@@ -334,7 +334,7 @@
 			} else if (vol >= 0x60)
 			{
 				// Volume commands 6-F translation.
-				static const ModCommand::VOLCMD volEffTrans[] =
+				static constexpr ModCommand::VOLCMD volEffTrans[] =
 				{
 					VOLCMD_VOLSLIDEDOWN, VOLCMD_VOLSLIDEUP, VOLCMD_FINEVOLDOWN, VOLCMD_FINEVOLUP,
 					VOLCMD_VIBRATOSPEED, VOLCMD_VIBRATODEPTH, VOLCMD_PANNING, VOLCMD_PANSLIDELEFT,
Index: soundlib/modcommand.cpp
===================================================================
--- soundlib/modcommand.cpp	(revision 12372)
+++ soundlib/modcommand.cpp	(working copy)
@@ -900,7 +900,7 @@
 size_t ModCommand::GetEffectWeight(COMMAND cmd)
 {
 	// Effect weights, sorted from lowest to highest weight.
-	static const COMMAND weights[] =
+	static constexpr COMMAND weights[] =
 	{
 		CMD_NONE,
 		CMD_DUMMY,
Index: soundlib/MPEGFrame.cpp
===================================================================
--- soundlib/MPEGFrame.cpp	(revision 12372)
+++ soundlib/MPEGFrame.cpp	(working copy)
@@ -15,13 +15,13 @@
 OPENMPT_NAMESPACE_BEGIN
 
 // Samples per frame - for each MPEG version and all three layers
-static const uint16 samplesPerFrame[2][3] =
+static constexpr uint16 samplesPerFrame[2][3] =
 {
 	{ 384, 1152, 1152 },	// MPEG 1
 	{ 384, 1152,  576 }		// MPEG 2 / 2.5
 };
 // Bit rates for each MPEG version and all three layers
-static const uint16 bitRates[2][3][15] =
+static constexpr uint16 bitRates[2][3][15] =
 {
 	// MPEG 1
 	{
@@ -37,7 +37,7 @@
 	}
 };
 // Sampling rates for each MPEG version and all three layers
-static const uint16 samplingRates[4][3] =
+static constexpr uint16 samplingRates[4][3] =
 { 
 	{ 11025, 12000,  8000 },	// MPEG 2.5
 	{     0,     0,     0 },	// Invalid
@@ -45,13 +45,13 @@
 	{ 44100, 48000, 32000 }		// MPEG 1
 };
 // Samples per Frame / 8
-static const uint8 mpegCoefficients[2][3] =
+static constexpr uint8 mpegCoefficients[2][3] =
 {
 	{ 12, 144, 144 },	// MPEG 1
 	{ 12, 144,  72 }	// MPEG 2 / 2.5
 };
 // Side info size = Offset in frame where Xing/Info magic starts
-static const uint8 sideInfoSize[2][2] =
+static constexpr uint8 sideInfoSize[2][2] =
 {
 	{ 17, 32 },	// MPEG 1
 	{  9, 17 }	// MPEG 2 / 2.5
Index: soundlib/opal.h
===================================================================
--- soundlib/opal.h	(revision 12372)
+++ soundlib/opal.h	(working copy)
@@ -375,7 +375,7 @@
 //==================================================================================================
 void Opal::Port(uint16_t reg_num, uint8_t val) {
 
-    static const int8_t op_lookup[] = {
+    static constexpr int8_t op_lookup[] = {
     //  00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F
         0,  1,  2,  3,  4,  5,  -1, -1, 6,  7,  8,  9,  10, 11, -1, -1,
     //  10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F
@@ -1185,7 +1185,7 @@
 //==================================================================================================
 void Opal::Operator::SetKeyScale(uint16_t scale) {
 
-    static const uint8_t kslShift[4] = { 15, 1, 2, 0 };
+    static constexpr uint8_t kslShift[4] = { 15, 1, 2, 0 };
     KeyScaleShift = kslShift[scale];
     ComputeKeyScaleLevel();
 }
@@ -1314,7 +1314,7 @@
 //==================================================================================================
 void Opal::Operator::ComputeKeyScaleLevel() {
 
-    static const uint8_t levtab[] = {
+    static constexpr uint8_t levtab[] = {
         0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
         0,      0,      0,      0,      0,      0,      0,      0,      0,      8,      12,     16,     20,     24,     28,     32,
         0,      0,      0,      0,      0,      12,     20,     28,     32,     40,     44,     48,     52,     56,     60,     64,
Index: soundlib/OPL.cpp
===================================================================
--- soundlib/OPL.cpp	(revision 12372)
+++ soundlib/OPL.cpp	(working copy)
@@ -67,7 +67,7 @@
 // Translate a channel's first operator address into a register
 uint16 OPL::OperatorToRegister(uint8 oplCh)
 {
-	static const uint8 OPLChannelToOperator[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
+	static constexpr uint8 OPLChannelToOperator[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
 	if(oplCh < 9)
 		return OPLChannelToOperator[oplCh];
 	else
Index: soundlib/plugins/dmo/Distortion.cpp
===================================================================
--- soundlib/plugins/dmo/Distortion.cpp	(revision 12372)
+++ soundlib/plugins/dmo/Distortion.cpp	(working copy)
@@ -222,7 +222,7 @@
 		shift = 5;
 	m_shift = shift;
 
-	static const float LogNorm[32] =
+	static constexpr float LogNorm[32] =
 	{
 		1.00f, 1.00f, 1.50f, 1.00f, 1.75f, 1.40f, 1.17f, 1.00f,
 		1.88f, 1.76f, 1.50f, 1.36f, 1.25f, 1.15f, 1.07f, 1.00f,
Index: soundlib/plugins/dmo/DMOPlugin.cpp
===================================================================
--- soundlib/plugins/dmo/DMOPlugin.cpp	(revision 12372)
+++ soundlib/plugins/dmo/DMOPlugin.cpp	(working copy)
@@ -126,8 +126,8 @@
 }
 
 
-static const float _f2si = 32768.0f;
-static const float _si2f = 1.0f / 32768.0f;
+static constexpr float _f2si = 32768.0f;
+static constexpr float _si2f = 1.0f / 32768.0f;
 
 
 static void InterleaveStereo(const float * MPT_RESTRICT inputL, const float * MPT_RESTRICT inputR, float * MPT_RESTRICT output, uint32 numFrames)
Index: soundlib/plugins/dmo/I3DL2Reverb.cpp
===================================================================
--- soundlib/plugins/dmo/I3DL2Reverb.cpp	(revision 12372)
+++ soundlib/plugins/dmo/I3DL2Reverb.cpp	(working copy)
@@ -450,7 +450,7 @@
 
 CString I3DL2Reverb::GetParamDisplay(PlugParamIndex param)
 {
-	static const TCHAR *modes[] = { _T("LQ"), _T("LQ+"), _T("HQ"), _T("HQ+") };
+	static constexpr const TCHAR * const modes[] = { _T("LQ"), _T("LQ+"), _T("HQ"), _T("HQ+") };
 	float value = m_param[param];
 	switch(param)
 	{
@@ -520,7 +520,7 @@
 void I3DL2Reverb::SetDelayTaps()
 {
 	// Early reflections
-	static const float delays[] =
+	static constexpr float delays[] =
 	{
 		1.0000f, 1.0000f, 0.0000f, 0.1078f, 0.1768f, 0.2727f,
 		0.3953f, 0.5386f, 0.6899f, 0.8306f, 0.9400f, 0.9800f,
Index: soundlib/plugins/LFOPlugin.cpp
===================================================================
--- soundlib/plugins/LFOPlugin.cpp	(revision 12372)
+++ soundlib/plugins/LFOPlugin.cpp	(working copy)
@@ -415,7 +415,7 @@
 		return m_bypassed ? _T("Yes") : _T("No");
 	} else if(param == kWaveform)
 	{
-		static const TCHAR *waveforms[] = { _T("Sine"), _T("Triangle"), _T("Saw"), _T("Square"), _T("Noise"), _T("Smoothed Noise") };
+		static constexpr const TCHAR * const waveforms[] = { _T("Sine"), _T("Triangle"), _T("Saw"), _T("Square"), _T("Noise"), _T("Smoothed Noise") };
 		if(m_waveForm < MPT_ARRAY_COUNT(waveforms))
 			return waveforms[m_waveForm];
 	} else if(param == kLoopMode)
Index: soundlib/plugins/OpCodes.h
===================================================================
--- soundlib/plugins/OpCodes.h	(revision 12372)
+++ soundlib/plugins/OpCodes.h	(working copy)
@@ -15,7 +15,7 @@
 OPENMPT_NAMESPACE_BEGIN
 
 #ifndef NO_VST
-static const char *VstOpCodes[] =
+static constexpr const char *VstOpCodes[] =
 {
 	"effOpen",
 	"effClose",
Index: soundlib/plugins/PluginManager.cpp
===================================================================
--- soundlib/plugins/PluginManager.cpp	(revision 12372)
+++ soundlib/plugins/PluginManager.cpp	(working copy)
@@ -66,7 +66,7 @@
 #endif
 
 #ifdef MODPLUG_TRACKER
-static const mpt::uchar *const cacheSection = UL_("PluginCache");
+static constexpr const mpt::uchar *cacheSection = UL_("PluginCache");
 #endif // MODPLUG_TRACKER
 
 
Index: soundlib/SampleFormatFLAC.cpp
===================================================================
--- soundlib/SampleFormatFLAC.cpp	(revision 12372)
+++ soundlib/SampleFormatFLAC.cpp	(working copy)
@@ -258,7 +258,7 @@
 		file.Rewind();
 		bool oggOK = false;
 		bool needMoreData = true;
-		static const long bufsize = 65536;
+		constexpr long bufsize = 65536;
 		std::size_t readSize = 0;
 		char *buf = nullptr;
 		ogg_sync_state oy;
Index: soundlib/SampleFormats.cpp
===================================================================
--- soundlib/SampleFormats.cpp	(revision 12372)
+++ soundlib/SampleFormats.cpp	(working copy)
@@ -339,8 +339,8 @@
 
 static bool IMAADPCMUnpack16(int16 *target, SmpLength sampleLen, FileReader file, uint16 blockAlign, uint32 numChannels)
 {
-	static const int32 IMAIndexTab[8] =  { -1, -1, -1, -1, 2, 4, 6, 8 };
-	static const int32 IMAUnpackTable[90] =
+	static constexpr int32 IMAIndexTab[8] =  { -1, -1, -1, -1, 2, 4, 6, 8 };
+	static constexpr int32 IMAUnpackTable[90] =
 	{
 		7,     8,     9,     10,    11,    12,    13,    14,
 		16,    17,    19,    21,    23,    25,    28,    31,
@@ -1621,7 +1621,7 @@
 		} else
 		{
 			// Scientific pitch
-			static const int8 keys[] = { 9, 11, 0, 2, 4, 5, 7 };
+			static constexpr int8 keys[] = { 9, 11, 0, 2, 4, 5, 7 };
 			static_assert(CountOf(keys) == 'g' - 'a' + 1);
 			auto keyC = value[0];
 			if(keyC >= 'A' && keyC <= 'G')
Index: soundlib/SampleIO.cpp
===================================================================
--- soundlib/SampleIO.cpp	(revision 12372)
+++ soundlib/SampleIO.cpp	(working copy)
@@ -232,7 +232,7 @@
 	} else if((GetEncoding() == uLaw || GetEncoding() == aLaw) && GetBitDepth() == 16 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved))
 	{
 		// 8-to-16 bit G.711 u-law / a-law
-		static const int16 uLawTable[256] =
+		static constexpr int16 uLawTable[256] =
 		{
 			-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
 			-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
@@ -268,7 +268,7 @@
 			    56,    48,    40,    32,    24,    16,     8,     0,
 		};
 
-		static const int16 aLawTable[256] =
+		static constexpr int16 aLawTable[256] =
 		{
 			 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
 			 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
Index: soundlib/Snd_fx.cpp
===================================================================
--- soundlib/Snd_fx.cpp	(revision 12372)
+++ soundlib/Snd_fx.cpp	(working copy)
@@ -73,7 +73,7 @@
 #endif
 	std::vector<ChnSettings> chnSettings;
 	double elapsedTime;
-	static const uint32 IGNORE_CHANNEL = uint32_max;
+	static constexpr uint32 IGNORE_CHANNEL = uint32_max;
 
 	GetLengthMemory(const CSoundFile &sf)
 		: sndFile(sf)
@@ -5705,8 +5705,8 @@
 // Convert a ST2 tempo byte to classic tempo and speed combination
 TEMPO CSoundFile::ConvertST2Tempo(uint8 tempo)
 {
-	static const uint8 ST2TempoFactor[] = { 140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1 };
-	static const uint32 st2MixingRate = 23863; // Highest possible setting in ST2
+	static constexpr uint8 ST2TempoFactor[] = { 140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1 };
+	static constexpr uint32 st2MixingRate = 23863; // Highest possible setting in ST2
 
 	// This underflows at tempo 06...0F, and the resulting tick lengths depend on the mixing rate.
 	int32 samplesPerTick = st2MixingRate / (49 - ((ST2TempoFactor[tempo >> 4u] * (tempo & 0x0F)) >> 4u));
Index: soundlib/Sndfile.cpp
===================================================================
--- soundlib/Sndfile.cpp	(revision 12372)
+++ soundlib/Sndfile.cpp	(working copy)
@@ -294,9 +294,6 @@
 }
 
 
-const std::size_t CSoundFile::ProbeRecommendedSize = PROBE_RECOMMENDED_SIZE;
-
-
 #define MPT_DO_PROBE( storedResult , call ) \
 	MPT_DO { \
 		ProbeResult lastResult = call ; \
Index: soundlib/Sndfile.h
===================================================================
--- soundlib/Sndfile.h	(revision 12372)
+++ soundlib/Sndfile.h	(working copy)
@@ -620,7 +620,7 @@
 
 	#define PROBE_RECOMMENDED_SIZE 2048u
 
-	static const std::size_t ProbeRecommendedSize;
+	static constexpr std::size_t ProbeRecommendedSize = PROBE_RECOMMENDED_SIZE;
 
 	enum ProbeFlags
 	{
Index: soundlib/Sndmix.cpp
===================================================================
--- soundlib/Sndmix.cpp	(revision 12372)
+++ soundlib/Sndmix.cpp	(working copy)
@@ -28,7 +28,7 @@
 // Log tables for pre-amp
 // Pre-amp (or more precisely: Pre-attenuation) depends on the number of channels,
 // Which this table takes care of.
-static const uint8 PreAmpTable[16] =
+static constexpr uint8 PreAmpTable[16] =
 {
 	0x60, 0x60, 0x60, 0x70,	// 0-7
 	0x80, 0x88, 0x90, 0x98,	// 8-15
@@ -37,7 +37,7 @@
 };
 
 #ifndef NO_AGC
-static const uint8 PreAmpAGCTable[16] =
+static constexpr uint8 PreAmpAGCTable[16] =
 {
 	0x60, 0x60, 0x60, 0x64,
 	0x68, 0x70, 0x78, 0x80,
@@ -786,7 +786,7 @@
 	} else if(GetType() & (MOD_TYPE_DIGI | MOD_TYPE_DBM))
 	{
 		// Other waveforms are not supported.
-		static const int8 DBMSinus[] =
+		static constexpr int8 DBMSinus[] =
 		{
 			33, 52, 69, 84, 96, 107, 116, 122,  125, 127,  125, 122, 116, 107, 96, 84,
 			69, 52, 33, 13, -8, -31, -54, -79, -104,-128, -104, -79, -54, -31, -8, 13,
Index: soundlib/tuning.h
===================================================================
--- soundlib/tuning.h	(revision 12372)
+++ soundlib/tuning.h	(working copy)
@@ -28,7 +28,7 @@
 
 public:
 
-	static const char s_FileExtension[5];
+	static constexpr char s_FileExtension[5] = ".tun";
 
 	enum TuningType
 	{
Index: soundlib/tuningbase.cpp
===================================================================
--- soundlib/tuningbase.cpp	(revision 12372)
+++ soundlib/tuningbase.cpp	(working copy)
@@ -35,10 +35,6 @@
 
 
 
-const char CTuningRTI::s_FileExtension[5] = ".tun";
-
-
-
 void CTuningRTI::SetNoteName(const NOTEINDEXTYPE& n, const std::string& str)
 {
 	if(!str.empty())
Index: soundlib/tuningCollection.cpp
===================================================================
--- soundlib/tuningCollection.cpp	(revision 12372)
+++ soundlib/tuningCollection.cpp	(working copy)
@@ -34,9 +34,6 @@
 */
 
 
-const char CTuningCollection::s_FileExtension[4] = ".tc";
-
-
 namespace CTuningS11n
 {
 	void ReadStr(std::istream& iStrm, std::string& str, const size_t);
Index: soundlib/tuningcollection.h
===================================================================
--- soundlib/tuningcollection.h	(revision 12372)
+++ soundlib/tuningcollection.h	(working copy)
@@ -28,7 +28,7 @@
 
 public:
 
-	static const char s_FileExtension[4];
+	static constexpr char s_FileExtension[4] = ".tc";
 
 	// OpenMPT <= 1.26 had to following limits:
 	//  *  255 built-in tunings (only 2 were ever actually provided)
avoid-static-const-v2.patch (61,217 bytes)   
manx

manx

2019-12-21 09:56

administrator   ~0004165

Given the size of the patch, and various flakyness with older compilers regarding constexpr, I am not sure whether backporting this patch to earlier branches would be desirable.

Saga Musix

Saga Musix

2019-12-22 15:45

administrator   ~0004166

Looks good in general, although I would suggest to keep modExts static const in View_tre.cpp. This function is only ever accessed through the GUI thread, so a lock that can be immediately acquired will still perform better than having to reconstruct the vector with every file browser update. Apart from that I'd apply the patch as-is.

I also agree that we shouldn't apply it to older branches, at least for now - nobody every reported any issues on this topic so I don't see any immediate need to address it in those versions.

Gerirish

Gerirish

2019-12-23 17:32

reporter   ~0004167

The target versions OpenMPT 1.28.09.00 & libopenmpt 0.4.11 aren't correct anymore. These versions were recently released without this change.

manx

manx

2019-12-23 17:59

administrator   ~0004168

This function is only ever accessed through the GUI thread, so a lock that can be immediately acquired will still perform better than having to reconstruct the vector with every file browser update. Apart from that I'd apply the patch as-is.

I moved modExts to CModTree::m_modExtensions. The code already does the same for Media Foundation extensions. Avoids both, the unwanted lock, and reconstruction of the vector.

avoid-static-const-v3.patch (62,819 bytes)   
Index: common/Logging.h
===================================================================
--- common/Logging.h	(revision 12400)
+++ common/Logging.h	(working copy)
@@ -113,7 +113,7 @@
 // All logging code gets compiled and immediately dead-code eliminated.
 #define MPT_LOG_IS_DISABLED
 #endif
-static const int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
+static constexpr int GlobalLogLevel = MPT_LOG_GLOBAL_LEVEL ;
 #else
 extern int GlobalLogLevel;
 #endif
Index: common/misc_util.cpp
===================================================================
--- common/misc_util.cpp	(revision 12400)
+++ common/misc_util.cpp	(working copy)
@@ -20,7 +20,7 @@
 {
 
 
-static const mpt::uchar EncodeNibble[16] = {
+static constexpr mpt::uchar EncodeNibble[16] = {
 	UC_('0'), UC_('1'), UC_('2'), UC_('3'),
 	UC_('4'), UC_('5'), UC_('6'), UC_('7'),
 	UC_('8'), UC_('9'), UC_('A'), UC_('B'),
Index: common/mptCPU.h
===================================================================
--- common/mptCPU.h	(revision 12400)
+++ common/mptCPU.h	(working copy)
@@ -31,10 +31,10 @@
 #define PROCSUPPORT_AVX          0x10000 // Processor supports AVX instructions
 #define PROCSUPPORT_AVX2         0x20000 // Processor supports AVX2 instructions
 
-static const uint32 PROCSUPPORT_i586     = 0u                                                      ;
-static const uint32 PROCSUPPORT_x86_SSE  = 0u | PROCSUPPORT_SSE                                    ;
-static const uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2                 ;
-static const uint32 PROCSUPPORT_AMD64    = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
+static constexpr uint32 PROCSUPPORT_i586     = 0u                                                      ;
+static constexpr uint32 PROCSUPPORT_x86_SSE  = 0u | PROCSUPPORT_SSE                                    ;
+static constexpr uint32 PROCSUPPORT_x86_SSE2 = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2                 ;
+static constexpr uint32 PROCSUPPORT_AMD64    = 0u | PROCSUPPORT_SSE | PROCSUPPORT_SSE2 | PROCSUPPORT_LM;
 
 #endif
 
Index: common/mptRandom.h
===================================================================
--- common/mptRandom.h	(revision 12400)
+++ common/mptRandom.h	(working copy)
@@ -44,7 +44,7 @@
 
 
 #ifdef MPT_BUILD_FUZZER
-static const uint32 FUZZER_RNG_SEED = 3141592653u; // pi
+static constexpr uint32 FUZZER_RNG_SEED = 3141592653u; // pi
 #endif // MPT_BUILD_FUZZER
 
 
Index: common/mptTime.cpp
===================================================================
--- common/mptTime.cpp	(revision 12400)
+++ common/mptTime.cpp	(working copy)
@@ -47,7 +47,7 @@
 
 mpt::ustring ToUString(uint64 time100ns)
 {
-	static const std::size_t bufsize = 256;
+	constexpr std::size_t bufsize = 256;
 
 	mpt::ustring result;
 
Index: common/Profiler.cpp
===================================================================
--- common/Profiler.cpp	(revision 12400)
+++ common/Profiler.cpp	(working copy)
@@ -52,7 +52,7 @@
 	class Statistics * stats;
 };
 
-static const std::size_t MAX_PROFILES = 1024;
+static constexpr std::size_t MAX_PROFILES = 1024;
 
 static ProfileBlock Profiles[ MAX_PROFILES ];
 
Index: mptrack/AboutDialog.h
===================================================================
--- mptrack/AboutDialog.h	(revision 12400)
+++ mptrack/AboutDialog.h	(working copy)
@@ -20,7 +20,7 @@
 
 public:
 
-	static const DWORD UPDATE_INTERVAL = 15; // milliseconds
+	static constexpr DWORD UPDATE_INTERVAL = 15; // milliseconds
 
 protected:
 
@@ -60,7 +60,7 @@
 	CTabCtrl m_Tab;
 	CEdit m_TabEdit;
 	UINT_PTR m_TimerID = 0;
-	static const UINT_PTR TIMERID_ABOUT_DEFAULT = 3;
+	static constexpr UINT_PTR TIMERID_ABOUT_DEFAULT = 3;
 
 public:
 	static CAboutDlg *instance;
Index: mptrack/ColorConfigDlg.cpp
===================================================================
--- mptrack/ColorConfigDlg.cpp	(revision 12400)
+++ mptrack/ColorConfigDlg.cpp	(working copy)
@@ -19,7 +19,7 @@
 
 OPENMPT_NAMESPACE_BEGIN
 
-static const struct ColorDescriptions
+static constexpr struct ColorDescriptions
 {
 	const TCHAR *name;
 	int previewImage;
Index: mptrack/Ctrl_pat.cpp
===================================================================
--- mptrack/Ctrl_pat.cpp	(revision 12400)
+++ mptrack/Ctrl_pat.cpp	(working copy)
@@ -269,7 +269,7 @@
 		CString s;
 		if(updateAll || updateSmpNames || updateInsNames)
 		{
-			static const TCHAR szSplitFormat[] = _T("%02u %s %02u: %s/%s");
+			constexpr TCHAR szSplitFormat[] = _T("%02u %s %02u: %s/%s");
 			UINT nPos = 0;
 			m_CbnInstrument.SetRedraw(FALSE);
 			m_CbnInstrument.ResetContent();
Index: mptrack/Ctrl_smp.cpp
===================================================================
--- mptrack/Ctrl_smp.cpp	(revision 12400)
+++ mptrack/Ctrl_smp.cpp	(working copy)
@@ -2246,7 +2246,7 @@
 		memcpy(pNewSample, sample.sampleb(), selection.nStart * sample.GetBytesPerSample());
 		memcpy(static_cast<std::byte *>(pNewSample) + stretchEnd * sample.GetBytesPerSample(), sample.sampleb() + selection.nEnd * sample.GetBytesPerSample(), (sample.nLength - selection.nEnd) * sample.GetBytesPerSample());
 
-		static const SmpLength MaxInputChunkSize = 1024;
+		constexpr SmpLength MaxInputChunkSize = 1024;
 
 		std::vector<float> buffer(MaxInputChunkSize * numChannels);
 		std::vector<SC::Convert<float, int16>> convf32(numChannels);
Index: mptrack/dlg_misc.cpp
===================================================================
--- mptrack/dlg_misc.cpp	(revision 12400)
+++ mptrack/dlg_misc.cpp	(working copy)
@@ -826,8 +826,8 @@
 ////////////////////////////////////////////////////////////////////////////////////////////
 // Keyboard Control
 
-static const uint8 whitetab[7] = {0,2,4,5,7,9,11};
-static const uint8 blacktab[7] = {0xff,1,3,0xff,6,8,10};
+static constexpr uint8 whitetab[7] = {0,2,4,5,7,9,11};
+static constexpr uint8 blacktab[7] = {0xff,1,3,0xff,6,8,10};
 
 BEGIN_MESSAGE_MAP(CKeyboardControl, CWnd)
 	ON_WM_DESTROY()
Index: mptrack/EffectInfo.cpp
===================================================================
--- mptrack/EffectInfo.cpp	(revision 12400)
+++ mptrack/EffectInfo.cpp	(working copy)
@@ -47,7 +47,7 @@
 #define MOD_TYPE_ALL		(~ModType(0))
 
 
-static const MPTEFFECTINFO gFXInfo[] =
+static constexpr MPTEFFECTINFO gFXInfo[] =
 {
 	{CMD_ARPEGGIO,		0,0,		0,	MOD_TYPE_ALL,	_T("Arpeggio")},
 	{CMD_PORTAMENTOUP,	0,0,		0,	MOD_TYPE_ALL,	_T("Portamento Up")},
@@ -872,7 +872,7 @@
 	FlagSet<MODTYPE> GetSupportedFormats() const { return FlagSet<MODTYPE>(supportedFormats); }
 };
 
-static const MPTVOLCMDINFO gVolCmdInfo[] =
+static constexpr MPTVOLCMDINFO gVolCmdInfo[] =
 {
 	{VOLCMD_VOLUME,			MOD_TYPE_NOMOD,		_T("Set Volume")},
 	{VOLCMD_PANNING,		MOD_TYPE_NOMOD,		_T("Set Panning")},
Index: mptrack/GeneralConfigDlg.cpp
===================================================================
--- mptrack/GeneralConfigDlg.cpp	(revision 12400)
+++ mptrack/GeneralConfigDlg.cpp	(working copy)
@@ -33,7 +33,7 @@
 END_MESSAGE_MAP()
 
 
-static const struct GeneralOptionsDescriptions
+static constexpr struct GeneralOptionsDescriptions
 {
 	uint32 flag;
 	const char *name, *description;
Index: mptrack/IPCWindow.cpp
===================================================================
--- mptrack/IPCWindow.cpp	(revision 12400)
+++ mptrack/IPCWindow.cpp	(working copy)
@@ -20,7 +20,7 @@
 namespace IPCWindow
 {
 
-	static const TCHAR ClassName[] = _T("OpenMPT_IPC_Wnd");
+	static constexpr TCHAR ClassName[] = _T("OpenMPT_IPC_Wnd");
 	static HWND ipcWindow = nullptr;
 
 	static LRESULT CALLBACK IPCWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Index: mptrack/Mainfrm.h
===================================================================
--- mptrack/Mainfrm.h	(revision 12400)
+++ mptrack/Mainfrm.h	(working copy)
@@ -207,7 +207,7 @@
 class VUMeter
 {
 public:
-	static const std::size_t maxChannels = 4;
+	static constexpr std::size_t maxChannels = 4;
 	static const float dynamicRange; // corresponds to the current implementation of the UI widget diplaying the result
 	struct Channel
 	{
@@ -548,8 +548,8 @@
 	afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
 
 	// Defines maximum number of items in example modules menu.
-	static const size_t nMaxItemsInExampleModulesMenu = 50;
-	static const size_t nMaxItemsInTemplateModulesMenu = 50;
+	static constexpr size_t nMaxItemsInExampleModulesMenu = 50;
+	static constexpr size_t nMaxItemsInTemplateModulesMenu = 50;
 
 	/// Array of paths of example modules that are available from help menu.
 	std::vector<mpt::PathString> m_ExampleModulePaths;
Index: mptrack/Modedit.cpp
===================================================================
--- mptrack/Modedit.cpp	(revision 12400)
+++ mptrack/Modedit.cpp	(working copy)
@@ -999,8 +999,8 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 // Copy/Paste envelope
 
-static const CHAR *pszEnvHdr = "ModPlug Tracker Envelope\r\n";
-static const CHAR *pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\r\n";
+static constexpr const CHAR *pszEnvHdr = "ModPlug Tracker Envelope\r\n";
+static constexpr const CHAR *pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\r\n";
 
 static bool EnvelopeToString(CStringA &s, const InstrumentEnvelope &env)
 {
Index: mptrack/Mpdlgs.cpp
===================================================================
--- mptrack/Mpdlgs.cpp	(revision 12400)
+++ mptrack/Mpdlgs.cpp	(working copy)
@@ -206,7 +206,7 @@
 	}
 	// latency
 	{
-		static const double latencies [] = {
+		static constexpr double latencies [] = {
 			0.001,
 			0.002,
 			0.003,
@@ -250,7 +250,7 @@
 	}
 	// update interval
 	{
-		static const double updateIntervals [] = {
+		static constexpr double updateIntervals [] = {
 			0.001,
 			0.002,
 			0.005,
Index: mptrack/Mptrack.h
===================================================================
--- mptrack/Mptrack.h	(revision 12400)
+++ mptrack/Mptrack.h	(working copy)
@@ -340,7 +340,7 @@
 class CFastBitmap
 {
 protected:
-	static const uint8 BLEND_OFFSET = 0x80;
+	static constexpr uint8 BLEND_OFFSET = 0x80;
 
 	struct MODPLUGFASTDIB
 	{
Index: mptrack/Notification.h
===================================================================
--- mptrack/Notification.h	(revision 12400)
+++ mptrack/Notification.h	(working copy)
@@ -33,8 +33,8 @@
 
 	typedef uint16 Item;
 
-	static const SmpLength PosInvalid = SmpLength(-1);	// pos[i] is not valid (if it contains sample or envelope position)
-	static const uint32 ClipVU = 0x80000000;			// Master VU clip indicator bit (sound output has previously clipped)
+	static constexpr SmpLength PosInvalid = SmpLength(-1);	// pos[i] is not valid (if it contains sample or envelope position)
+	static constexpr uint32 ClipVU = 0x80000000;			// Master VU clip indicator bit (sound output has previously clipped)
 
 	int64 timestampSamples;
 	FlagSet<Notification::Type> type;
Index: mptrack/OPLInstrDlg.cpp
===================================================================
--- mptrack/OPLInstrDlg.cpp	(revision 12400)
+++ mptrack/OPLInstrDlg.cpp	(working copy)
@@ -132,7 +132,7 @@
 // Swap OPL Key Scale Level bits for a "human-readable" value.
 static uint8 KeyScaleLevel(uint8 kslVolume)
 {
-	static const uint8 KSLFix[4] = { 0x00, 0x80, 0x40, 0xC0 };
+	static constexpr uint8 KSLFix[4] = { 0x00, 0x80, 0x40, 0xC0 };
 	return KSLFix[kslVolume >> 6];
 }
 
@@ -163,7 +163,7 @@
 		if(numWaveforms != m_waveform[op].GetCount())
 		{
 			m_waveform[op].ResetContent();
-			static const TCHAR *waveformNames[] =
+			static constexpr const TCHAR *waveformNames[] =
 			{
 				_T("Sine"), _T("Half Sine"), _T("Absolute Sine"), _T("Pulse Sine"),
 				_T("Sine (Even Periods)"), _T("Absolute Sine (Even Periods)"), _T("Square"), _T("Derived Square")
Index: mptrack/plugins/LFOPluginEditor.h
===================================================================
--- mptrack/plugins/LFOPluginEditor.h	(revision 12400)
+++ mptrack/plugins/LFOPluginEditor.h	(working copy)
@@ -28,7 +28,7 @@
 	CSpinButtonCtrl m_midiChnSpin;
 	LFOPlugin &m_lfoPlugin;
 	bool m_locked : 1;
-	static const int SLIDER_GRANULARITY = 1000;
+	static constexpr int SLIDER_GRANULARITY = 1000;
 
 public:
 
Index: mptrack/SampleEditorDialogs.h
===================================================================
--- mptrack/SampleEditorDialogs.h	(revision 12400)
+++ mptrack/SampleEditorDialogs.h	(working copy)
@@ -62,7 +62,7 @@
 	bool m_bRememberFormat;
 
 public:
-	static const SampleIO GetSampleFormat() { return m_nFormat; }
+	static SampleIO GetSampleFormat() { return m_nFormat; }
 	static void SetSampleFormat(SampleIO nFormat) { m_nFormat = nFormat; }
 	bool GetRemeberFormat() const { return m_bRememberFormat; };
 	void SetRememberFormat(bool bRemember) { m_bRememberFormat = bRemember; };
Index: mptrack/SampleGenerator.h
===================================================================
--- mptrack/SampleGenerator.h	(revision 12400)
+++ mptrack/SampleGenerator.h	(working copy)
@@ -50,7 +50,7 @@
 	static size_t samples_written;
 
 	typedef int16 sampling_type; // has to match SMPGEN_MIXBYTES!
-	static const sampling_type sample_maxvalue = (1 << ((SMPGEN_MIXBYTES << 3) - 1)) - 1;
+	static constexpr sampling_type sample_maxvalue = (1 << ((SMPGEN_MIXBYTES << 3) - 1)) - 1;
 
 	// muParser object for parsing the expression
 	mu::Parser muParser;
Index: mptrack/SelectPluginDialog.cpp
===================================================================
--- mptrack/SelectPluginDialog.cpp	(revision 12400)
+++ mptrack/SelectPluginDialog.cpp	(working copy)
@@ -296,7 +296,7 @@
 	m_treePlugins.SetRedraw(FALSE);
 	m_treePlugins.DeleteAllItems();
 
-	static const struct
+	static constexpr struct
 	{
 		VSTPluginLib::PluginCategory category;
 		const TCHAR *description;
Index: mptrack/StreamEncoderMP3.cpp
===================================================================
--- mptrack/StreamEncoderMP3.cpp	(revision 12400)
+++ mptrack/StreamEncoderMP3.cpp	(working copy)
@@ -709,7 +709,7 @@
 #ifdef MPT_WITH_LAME
 	if(m_Type == MP3EncoderLame)
 	{
-		static const int q_table[11] = { 240, 220, 190, 170, 160, 130, 120, 100, 80, 70, 50 }; // http://wiki.hydrogenaud.io/index.php?title=LAME
+		static constexpr int q_table[11] = { 240, 220, 190, 170, 160, 130, 120, 100, 80, 70, 50 }; // http://wiki.hydrogenaud.io/index.php?title=LAME
 		int q = mpt::saturate_round<int>((1.0f - quality) * 10.0f);
 		if(q < 0) q = 0;
 		if(q >= 10)
Index: mptrack/StreamEncoderVorbis.cpp
===================================================================
--- mptrack/StreamEncoderVorbis.cpp	(revision 12400)
+++ mptrack/StreamEncoderVorbis.cpp	(working copy)
@@ -249,7 +249,7 @@
 
 mpt::ustring VorbisEncoder::DescribeQuality(float quality) const
 {
-	static const int q_table[11] = { 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500 }; // http://wiki.hydrogenaud.io/index.php?title=Recommended_Ogg_Vorbis
+	static constexpr int q_table[11] = { 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 500 }; // http://wiki.hydrogenaud.io/index.php?title=Recommended_Ogg_Vorbis
 	int q = Clamp(mpt::saturate_round<int>(quality * 10.0f), 0, 10);
 	return mpt::format(U_("Q%1 (~%2 kbit)"))(mpt::ufmt::fix(quality * 10.0f, 1), q_table[q]);
 }
Index: mptrack/TrackerSettings.h
===================================================================
--- mptrack/TrackerSettings.h	(revision 12400)
+++ mptrack/TrackerSettings.h	(working copy)
@@ -156,7 +156,7 @@
 	uint32 Freqs[MAX_EQ_BANDS];
 };
 
-static const EQPreset FlatEQPreset = { "Flat", {16,16,16,16,16,16}, { 125, 300, 600, 1250, 4000, 8000 } };
+constexpr EQPreset FlatEQPreset = { "Flat", {16,16,16,16,16,16}, { 125, 300, 600, 1250, 4000, 8000 } };
 
 template<> inline SettingValue ToSettingValue(const EQPreset &val)
 {
Index: mptrack/TuningDialog.h
===================================================================
--- mptrack/TuningDialog.h	(revision 12400)
+++ mptrack/TuningDialog.h	(working copy)
@@ -320,7 +320,7 @@
 	};
 
 	static CString GetSclImportFailureMsg(EnSclImport);
-	static const size_t s_nSclImportMaxNoteCount = 256;
+	static constexpr size_t s_nSclImportMaxNoteCount = 256;
 
 	//To indicate whether to apply changes made to
 	//those edit boxes(they are modified by certain activities
Index: mptrack/UpdateHints.h
===================================================================
--- mptrack/UpdateHints.h	(revision 12400)
+++ mptrack/UpdateHints.h	(working copy)
@@ -133,7 +133,7 @@
 
 struct GeneralHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_GENERAL;
+	static constexpr HintCategory classCategory = HINTCAT_GENERAL;
 	GeneralHint(int channelTab = 0) : UpdateHint(classCategory, channelTab) { }
 	MPT_FORCEINLINE GeneralHint &General() { type |= HINT_MODGENERAL; return *this; }
 	MPT_FORCEINLINE GeneralHint &Channels() { type |= HINT_MODCHANNELS; return *this; }
@@ -144,7 +144,7 @@
 
 struct PatternHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PATTERNS;
+	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	PatternHint(PATTERNINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE PatternHint &Data() { type |= HINT_PATTERNDATA; return *this; }
 	MPT_FORCEINLINE PatternHint &Names() { type |= HINT_PATNAMES; return *this; }
@@ -154,7 +154,7 @@
 
 struct RowHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PATTERNS;
+	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
 	RowHint(ROWINDEX item = 0) : UpdateHint(classCategory, item) { type = HINT_PATTERNROW; }
 
 	MPT_FORCEINLINE ROWINDEX GetRow() const { return GetData<ROWINDEX>(); }
@@ -162,7 +162,7 @@
 
 struct SampleHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_SAMPLES;
+	static constexpr HintCategory classCategory = HINTCAT_SAMPLES;
 	SampleHint(SAMPLEINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE SampleHint &Info() { type |= HINT_SAMPLEINFO; return *this; }
 	MPT_FORCEINLINE SampleHint &Data() { type |= HINT_SAMPLEDATA; return *this; }
@@ -173,7 +173,7 @@
 
 struct InstrumentHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_INSTRUMENTS;
+	static constexpr HintCategory classCategory = HINTCAT_INSTRUMENTS;
 	InstrumentHint(INSTRUMENTINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE InstrumentHint &Info() { type |= HINT_INSTRUMENT; return *this; }
 	MPT_FORCEINLINE InstrumentHint &Envelope() { type |= HINT_ENVELOPE; return *this; }
@@ -184,7 +184,7 @@
 
 struct SequenceHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_SEQUENCE;
+	static constexpr HintCategory classCategory = HINTCAT_SEQUENCE;
 	SequenceHint(SEQUENCEINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE SequenceHint &Data() { type |= HINT_MODSEQUENCE; return *this; }
 	MPT_FORCEINLINE SequenceHint &Names() { type |= HINT_SEQNAMES; return *this; }
@@ -195,7 +195,7 @@
 
 struct PluginHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_PLUGINS;
+	static constexpr HintCategory classCategory = HINTCAT_PLUGINS;
 	PluginHint(PLUGINDEX item = 0) : UpdateHint(classCategory, item) { }
 	MPT_FORCEINLINE PluginHint &Info() { type |= HINT_MIXPLUGINS; return *this; }
 	MPT_FORCEINLINE PluginHint &Names() { type |= HINT_PLUGINNAMES; return *this; }
@@ -206,7 +206,7 @@
 
 struct CommentHint : public UpdateHint
 {
-	static const HintCategory classCategory = HINTCAT_COMMENTS;
+	static constexpr HintCategory classCategory = HINTCAT_COMMENTS;
 	CommentHint() : UpdateHint(classCategory) { type = HINT_MODCOMMENTS; }
 };
 
Index: mptrack/View_ins.cpp
===================================================================
--- mptrack/View_ins.cpp	(revision 12400)
+++ mptrack/View_ins.cpp	(working copy)
@@ -46,7 +46,7 @@
 #define ENV_LEFTBAR_CYBTN		Util::ScalePixels(22, m_hWnd)
 
 
-static const UINT cLeftBarButtons[ENV_LEFTBAR_BUTTONS] =
+static constexpr UINT cLeftBarButtons[ENV_LEFTBAR_BUTTONS] =
 {
 	ID_ENVSEL_VOLUME,
 	ID_ENVSEL_PANNING,
Index: mptrack/View_pat.cpp
===================================================================
--- mptrack/View_pat.cpp	(revision 12400)
+++ mptrack/View_pat.cpp	(working copy)
@@ -2774,7 +2774,7 @@
 	BeginWaitCursor();
 	pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, sndFile.GetNumChannels(), sndFile.Patterns[m_nPattern].GetNumRows(), moveSelection ? "Move Selection" : "Copy Selection");
 
-	static const ModCommand empty = ModCommand::Empty();
+	const ModCommand empty = ModCommand::Empty();
 	auto p = pattern.begin();
 	for(ROWINDEX row = 0; row < sndFile.Patterns[m_nPattern].GetNumRows(); row++)
 	{
@@ -6914,8 +6914,8 @@
 	const ModCommand &m = GetCursorCommand();
 	const size_t columnIndex = m_Cursor.GetColumnType();
 	const TCHAR *column = _T("");
-	static const TCHAR *regularColumns[] = {_T("Note"), _T("Instrument"), _T("Volume"), _T("Effect"), _T("Parameter")};
-	static const TCHAR *pcColumns[] = {_T("Note"), _T("Plugin"), _T("Plugin Parameter"), _T("Parameter Value"), _T("Parameter Value")};
+	static constexpr const TCHAR *regularColumns[] = {_T("Note"), _T("Instrument"), _T("Volume"), _T("Effect"), _T("Parameter")};
+	static constexpr const TCHAR *pcColumns[] = {_T("Note"), _T("Plugin"), _T("Plugin Parameter"), _T("Parameter Value"), _T("Parameter Value")};
 	static_assert(PatternCursor::lastColumn + 1 == std::size(regularColumns));
 	static_assert(PatternCursor::lastColumn + 1 == std::size(pcColumns));
 
Index: mptrack/View_smp.cpp
===================================================================
--- mptrack/View_smp.cpp	(revision 12400)
+++ mptrack/View_smp.cpp	(working copy)
@@ -53,7 +53,7 @@
 // of trimming is nTrimLengthMin + 1.
 #define MIN_TRIM_LENGTH			4
 
-static const UINT cLeftBarButtons[SMP_LEFTBAR_BUTTONS] =
+static constexpr UINT cLeftBarButtons[SMP_LEFTBAR_BUTTONS] =
 {
 	ID_SAMPLE_ZOOMUP,
 	ID_SAMPLE_ZOOMDOWN,
Index: mptrack/View_tre.cpp
===================================================================
--- mptrack/View_tre.cpp	(revision 12400)
+++ mptrack/View_tre.cpp	(working copy)
@@ -171,6 +171,7 @@
 
 void CModTree::Init()
 {
+	m_modExtensions = CSoundFile::GetSupportedExtensions(false);
 	m_MediaFoundationExtensions = FileType(CSoundFile::GetMediaFoundationFileTypes()).GetExtensions();
 
 	DWORD dwRemove = TVS_SINGLEEXPAND;
@@ -1972,10 +1973,9 @@
 		if((hFind = FindFirstFile(path.AsNative().c_str(), &wfd)) != INVALID_HANDLE_VALUE)
 		{
 			static constexpr int FILTER_REJECT_FILE = -1;
-			static const auto modExts = CSoundFile::GetSupportedExtensions(false);
-			static const auto instrExts = {"xi", "iti", "sfz", "sf2", "sbk", "dls", "mss", "pat"};
-			static const auto sampleExts = {"wav", "flac", "ogg", "opus", "mp1", "mp2", "mp3", "smp", "raw", "s3i", "its", "aif", "aiff", "au", "snd", "svx", "voc", "8sv", "8svx", "16sv", "16svx", "w64", "caf", "sb0", "sb2", "sbi"};
-			static const auto allExtsBlacklist = {"txt", "diz", "nfo", "doc", "ini", "pdf", "zip", "rar", "lha", "exe", "dll", "lnk", "url"};
+			static constexpr auto instrExts = {"xi", "iti", "sfz", "sf2", "sbk", "dls", "mss", "pat"};
+			static constexpr auto sampleExts = {"wav", "flac", "ogg", "opus", "mp1", "mp2", "mp3", "smp", "raw", "s3i", "its", "aif", "aiff", "au", "snd", "svx", "voc", "8sv", "8svx", "16sv", "16svx", "w64", "caf", "sb0", "sb2", "sbi"};
+			static constexpr auto allExtsBlacklist = {"txt", "diz", "nfo", "doc", "ini", "pdf", "zip", "rar", "lha", "exe", "dll", "lnk", "url"};
 
 			const auto FilterFile = [this, showInstrs, showDirs](const mpt::PathString &fileName) -> int
 			{
@@ -1997,7 +1997,7 @@
 				{
 					if(showInstrs)
 						return IMAGE_SAMPLES;
-				} else if(std::find(modExts.begin(), modExts.end(), ext) != modExts.end())
+				} else if(std::find(m_modExtensions.begin(), m_modExtensions.end(), ext) != m_modExtensions.end())
 				{
 					if(showDirs)
 						return IMAGE_FOLDERSONG;
@@ -2010,7 +2010,7 @@
 					// Amiga-style prefix (i.e. mod.songname)
 					std::string prefixExt = fileName.ToUTF8();
 					const auto dotPos = prefixExt.find('.');
-					if(dotPos != std::string::npos && std::find(modExts.begin(), modExts.end(), prefixExt.erase(dotPos)) != modExts.end())
+					if(dotPos != std::string::npos && std::find(m_modExtensions.begin(), m_modExtensions.end(), prefixExt.erase(dotPos)) != m_modExtensions.end())
 						return IMAGE_FOLDERSONG;
 				}
 				
Index: mptrack/View_tre.h
===================================================================
--- mptrack/View_tre.h	(revision 12400)
+++ mptrack/View_tre.h	(working copy)
@@ -178,6 +178,7 @@
 	mpt::PathString m_InstrLibHighlightPath;  // Folder to highlight in browser after a refresh
 	mpt::PathString m_SongFileName;           // Name of open module, without path (== m_szInstrLibPath).
 	mpt::PathString m_previousPath;           // The folder from which we came from when navigating one folder up
+	std::vector<const char*> m_modExtensions;                  // cached in order to avoid querying too often when changing browsed folder
 	std::vector<mpt::PathString> m_MediaFoundationExtensions;  // cached in order to avoid querying too often when changing browsed folder
 	bool m_showAllFiles = false;
 
Index: mptrack/Vstplug.cpp
===================================================================
--- mptrack/Vstplug.cpp	(revision 12400)
+++ mptrack/Vstplug.cpp	(working copy)
@@ -1463,7 +1463,7 @@
 
 void CVstPlugin::HardAllNotesOff()
 {
-	static const uint32 SCRATCH_BUFFER_SIZE = 64;
+	constexpr uint32 SCRATCH_BUFFER_SIZE = 64;
 	float out[2][SCRATCH_BUFFER_SIZE]; // scratch buffers
 
 	// The JUCE framework doesn't like processing while being suspended.
Index: pluginBridge/BridgeCommon.h
===================================================================
--- pluginBridge/BridgeCommon.h	(revision 12400)
+++ pluginBridge/BridgeCommon.h	(working copy)
@@ -570,7 +570,7 @@
 
 	static void CreateCommunicationWindow(WNDPROC windowProc)
 	{
-		static const TCHAR windowClassName[] = _T("OpenMPTPluginBridgeCommunication");
+		static constexpr TCHAR windowClassName[] = _T("OpenMPTPluginBridgeCommunication");
 		static bool registered = false;
 		if(!registered)
 		{
Index: soundbase/SampleFormatConverters.h
===================================================================
--- soundbase/SampleFormatConverters.h	(revision 12400)
+++ soundbase/SampleFormatConverters.h	(working copy)
@@ -69,7 +69,7 @@
 
 
 // Every sample decoding functor has to typedef its input_t and output_t
-// and has to provide a static const input_inc member
+// and has to provide a static constexpr input_inc member
 // which describes by how many input_t elements inBuf has to be incremented between invocations.
 // input_inc is normally 1 except when decoding e.g. bigger sample values
 // from multiple std::byte values.
@@ -1015,7 +1015,7 @@
 {
 	typedef int32 input_t;
 	typedef uint8 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1032,7 +1032,7 @@
 {
 	typedef int32 input_t;
 	typedef int8 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1049,7 +1049,7 @@
 {
 	typedef int32 input_t;
 	typedef int16 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1066,7 +1066,7 @@
 {
 	typedef int32 input_t;
 	typedef int24 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
@@ -1135,7 +1135,7 @@
 {
 	typedef uint8 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1149,7 +1149,7 @@
 {
 	typedef int8 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1163,7 +1163,7 @@
 {
 	typedef int16 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
@@ -1177,7 +1177,7 @@
 {
 	typedef int24 input_t;
 	typedef int32 output_t;
-	static const int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
+	static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8;
 	MPT_FORCEINLINE output_t operator() (input_t val)
 	{
 		static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1);
Index: sounddev/SoundDevice.h
===================================================================
--- sounddev/SoundDevice.h	(revision 12400)
+++ sounddev/SoundDevice.h	(working copy)
@@ -98,13 +98,13 @@
 };
 
 
-static const mpt::uchar TypeWAVEOUT          [] = UL_("WaveOut");
-static const mpt::uchar TypeDSOUND           [] = UL_("DirectSound");
-static const mpt::uchar TypeASIO             [] = UL_("ASIO");
-static const mpt::uchar TypePORTAUDIO_WASAPI [] = UL_("WASAPI");
-static const mpt::uchar TypePORTAUDIO_WDMKS  [] = UL_("WDM-KS");
-static const mpt::uchar TypePORTAUDIO_WMME   [] = UL_("MME");
-static const mpt::uchar TypePORTAUDIO_DS     [] = UL_("DS");
+static constexpr mpt::uchar TypeWAVEOUT          [] = UL_("WaveOut");
+static constexpr mpt::uchar TypeDSOUND           [] = UL_("DirectSound");
+static constexpr mpt::uchar TypeASIO             [] = UL_("ASIO");
+static constexpr mpt::uchar TypePORTAUDIO_WASAPI [] = UL_("WASAPI");
+static constexpr mpt::uchar TypePORTAUDIO_WDMKS  [] = UL_("WDM-KS");
+static constexpr mpt::uchar TypePORTAUDIO_WMME   [] = UL_("MME");
+static constexpr mpt::uchar TypePORTAUDIO_DS     [] = UL_("DS");
 
 typedef mpt::ustring Type;
 
@@ -242,7 +242,7 @@
 
 public:
 
-	static const int32 MaxDeviceChannel = 32000;
+	static constexpr int32 MaxDeviceChannel = 32000;
 
 public:
 
@@ -628,17 +628,17 @@
 namespace Legacy
 {
 typedef uint16 ID;
-static const SoundDevice::Legacy::ID MaskType = 0xff00;
-static const SoundDevice::Legacy::ID MaskIndex = 0x00ff;
-static const int ShiftType = 8;
-static const int ShiftIndex = 0;
-static const SoundDevice::Legacy::ID TypeWAVEOUT          = 0;
-static const SoundDevice::Legacy::ID TypeDSOUND           = 1;
-static const SoundDevice::Legacy::ID TypeASIO             = 2;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS  = 4;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_WMME   = 5;
-static const SoundDevice::Legacy::ID TypePORTAUDIO_DS     = 6;
+static constexpr SoundDevice::Legacy::ID MaskType = 0xff00;
+static constexpr SoundDevice::Legacy::ID MaskIndex = 0x00ff;
+static constexpr int ShiftType = 8;
+static constexpr int ShiftIndex = 0;
+static constexpr SoundDevice::Legacy::ID TypeWAVEOUT          = 0;
+static constexpr SoundDevice::Legacy::ID TypeDSOUND           = 1;
+static constexpr SoundDevice::Legacy::ID TypeASIO             = 2;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS  = 4;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_WMME   = 5;
+static constexpr SoundDevice::Legacy::ID TypePORTAUDIO_DS     = 6;
 #if MPT_OS_WINDOWS
 mpt::ustring GetDirectSoundDefaultDeviceIdentifierPre_1_25_00_04();
 mpt::ustring GetDirectSoundDefaultDeviceIdentifier_1_25_00_04();
Index: sounddev/SoundDeviceWaveout.cpp
===================================================================
--- sounddev/SoundDeviceWaveout.cpp	(revision 12400)
+++ sounddev/SoundDeviceWaveout.cpp	(working copy)
@@ -31,10 +31,10 @@
 MPT_REGISTERED_COMPONENT(ComponentWaveOut, "WaveOut")
 
 
-static const std::size_t WAVEOUT_MINBUFFERS = 3;
-static const std::size_t WAVEOUT_MAXBUFFERS = 4096;
-static const std::size_t WAVEOUT_MINBUFFERFRAMECOUNT = 8;
-static const std::size_t WAVEOUT_MAXBUFFERSIZE = 16384; // fits in int16
+static constexpr std::size_t WAVEOUT_MINBUFFERS = 3;
+static constexpr std::size_t WAVEOUT_MAXBUFFERS = 4096;
+static constexpr std::size_t WAVEOUT_MINBUFFERFRAMECOUNT = 8;
+static constexpr std::size_t WAVEOUT_MAXBUFFERSIZE = 16384; // fits in int16
 
 
 static inline LONG* interlocked_access(DWORD* p)
@@ -436,12 +436,12 @@
 	// We could thereby try to avoid any potential wraparound inside the driver on older
 	// Windows versions, which would be, once converted into other units, really
 	// difficult to detect or handle.
-	static const UINT timeType = TIME_SAMPLES; // should work for sane systems
-	//static const std::size_t valid_bits = 32; // should work for sane systems
-	//static const UINT timeType = TIME_BYTES; // safest
-	static const std::size_t valid_bits = 27; // safe for WinXP TIME_SAMPLES
-	static const uint32 valid_mask = static_cast<uint32>((uint64(1) << valid_bits) - 1u);
-	static const uint32 valid_watermark = static_cast<uint32>(uint64(1) << (valid_bits - 1u)); // half the valid range in order to be able to catch backwards fluctuations
+	static constexpr UINT timeType = TIME_SAMPLES; // should work for sane systems
+	//static constexpr std::size_t valid_bits = 32; // should work for sane systems
+	//static constexpr UINT timeType = TIME_BYTES; // safest
+	static constexpr std::size_t valid_bits = 27; // safe for WinXP TIME_SAMPLES
+	static constexpr uint32 valid_mask = static_cast<uint32>((uint64(1) << valid_bits) - 1u);
+	static constexpr uint32 valid_watermark = static_cast<uint32>(uint64(1) << (valid_bits - 1u)); // half the valid range in order to be able to catch backwards fluctuations
 
 	MMTIME mmtime;
 	MemsetZero(mmtime);
Index: sounddev/SoundDeviceWaveout.h
===================================================================
--- sounddev/SoundDeviceWaveout.h	(revision 12400)
+++ sounddev/SoundDeviceWaveout.h	(working copy)
@@ -60,11 +60,11 @@
 	mutable MMTIME m_PositionLast;
 	mutable std::size_t m_PositionWrappedCount;
 
-	static const uint32 DriverBugDoneNotificationAndHeaderInQueue = (1u<<0u); //  1
-	static const uint32 DriverBugDoneNotificationAndHeaderNotDone = (1u<<1u); //  2
-	static const uint32 DriverBugBufferFillAndHeaderInQueue = (1u<<2u);       //  4
-	static const uint32 DriverBugBufferFillAndHeaderNotDone = (1u<<3u);       //  8
-	static const uint32 DriverBugDoneNotificationOutOfOrder = (1u<<4u);       // 10
+	static constexpr uint32 DriverBugDoneNotificationAndHeaderInQueue = (1u<<0u); //  1
+	static constexpr uint32 DriverBugDoneNotificationAndHeaderNotDone = (1u<<1u); //  2
+	static constexpr uint32 DriverBugBufferFillAndHeaderInQueue = (1u<<2u);       //  4
+	static constexpr uint32 DriverBugBufferFillAndHeaderNotDone = (1u<<3u);       //  8
+	static constexpr uint32 DriverBugDoneNotificationOutOfOrder = (1u<<4u);       // 10
 	std::atomic<uint32> m_DriverBugs;
 
 public:
Index: sounddsp/EQ.cpp
===================================================================
--- sounddsp/EQ.cpp	(revision 12400)
+++ sounddsp/EQ.cpp	(working copy)
@@ -27,7 +27,7 @@
 
 
 
-static const UINT gEqLinearToDB[33] =
+static constexpr UINT gEqLinearToDB[33] =
 {
 	16, 19, 22, 25, 28, 31, 34, 37,
 	40, 43, 46, 49, 52, 55, 58, 61,
@@ -35,7 +35,7 @@
 	160, 172, 184, 196, 208, 220, 232, 244, 256
 };
 
-static const EQBANDSTRUCT gEQDefaults[MAX_EQ_BANDS*2] =
+static constexpr EQBANDSTRUCT gEQDefaults[MAX_EQ_BANDS*2] =
 {
 	// Default: Flat EQ
 	{0,0,0,0,0, 0,0,0,0, 1,   120, false},
@@ -119,7 +119,7 @@
 
 static void SSE_StereoEQ(EQBANDSTRUCT *pbl, EQBANDSTRUCT *pbr, float32 *pbuffer, UINT nCount)
 {
-	static const float gk1 = 1.0f;
+	static constexpr float gk1 = 1.0f;
 	_asm {
 	mov eax, pbl
 	mov edx, pbr
Index: soundlib/ContainerMMCMP.cpp
===================================================================
--- soundlib/ContainerMMCMP.cpp	(revision 12400)
+++ soundlib/ContainerMMCMP.cpp	(working copy)
@@ -74,23 +74,23 @@
 #define MMCMP_ABS16		0x0200
 #define MMCMP_ENDIAN	0x0400
 
-static const uint8 MMCMP8BitCommands[8] =
+static constexpr uint8 MMCMP8BitCommands[8] =
 {
 	0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8
 };
 
-static const uint8 MMCMP8BitFetch[8] =
+static constexpr uint8 MMCMP8BitFetch[8] =
 {
 	3, 3, 3, 3, 2, 1, 0, 0
 };
 
-static const uint16 MMCMP16BitCommands[16] =
+static constexpr uint16 MMCMP16BitCommands[16] =
 {
 	0x01,  0x03,  0x07,  0x0F,  0x1E,   0x3C,   0x78,   0xF0,
 	0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
 };
 
-static const uint8 MMCMP16BitFetch[16] =
+static constexpr uint8 MMCMP16BitFetch[16] =
 {
 	4, 4, 4, 4, 3, 2, 1, 0,
 	0, 0, 0, 0, 0, 0, 0, 0
Index: soundlib/ContainerXPK.cpp
===================================================================
--- soundlib/ContainerXPK.cpp	(revision 12400)
+++ soundlib/ContainerXPK.cpp	(working copy)
@@ -104,7 +104,7 @@
 
 static uint8 XPK_ReadTable(int32 index)
 {
-	static const uint8 xpk_table[] = {
+	static constexpr uint8 xpk_table[] = {
 		2,3,4,5,6,7,8,0,3,2,4,5,6,7,8,0,4,3,5,2,6,7,8,0,5,4,6,2,3,7,8,0,6,5,7,2,3,4,8,0,7,6,8,2,3,4,5,0,8,7,6,2,3,4,5,0
 	};
 	if(index < 0) throw XPK_error();
Index: soundlib/Load_amf.cpp
===================================================================
--- soundlib/Load_amf.cpp	(revision 12400)
+++ soundlib/Load_amf.cpp	(working copy)
@@ -263,7 +263,7 @@
 		} else
 		{
 			// Effect
-			static const ModCommand::COMMAND effTrans[] =
+			static constexpr ModCommand::COMMAND effTrans[] =
 			{
 				CMD_NONE,			CMD_SPEED,			CMD_VOLUMESLIDE,		CMD_VOLUME,
 				CMD_PORTAMENTOUP,	CMD_NONE,			CMD_TONEPORTAMENTO,		CMD_TREMOR,
Index: soundlib/Load_ams.cpp
===================================================================
--- soundlib/Load_ams.cpp	(revision 12400)
+++ soundlib/Load_ams.cpp	(working copy)
@@ -42,7 +42,7 @@
 	};
 
 	// Effect translation table for extended (non-Protracker) effects
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_S3MCMDEX,		// Forward / Backward
 		CMD_PORTAMENTOUP,	// Extra fine slide up
Index: soundlib/Load_c67.cpp
===================================================================
--- soundlib/Load_c67.cpp	(revision 12400)
+++ soundlib/Load_c67.cpp	(working copy)
@@ -104,7 +104,7 @@
 	// CDFM uses a linear volume scale for FM instruments.
 	// ScreamTracker, on the other hand, directly uses the OPL chip's logarithmic volume scale.
 	// Neither FM nor PCM instruments can be fully muted in CDFM.
-	static const uint8 fmVolume[16] =
+	static constexpr uint8 fmVolume[16] =
 	{
 		0x08, 0x10, 0x18, 0x20, 0x28, 0x2C, 0x30, 0x34,
 		0x36, 0x38, 0x3A, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
Index: soundlib/Load_dbm.cpp
===================================================================
--- soundlib/Load_dbm.cpp	(revision 12400)
+++ soundlib/Load_dbm.cpp	(working copy)
@@ -127,7 +127,7 @@
 
 
 // Note: Unlike in MOD, 1Fx, 2Fx, 5Fx / 5xF, 6Fx / 6xF and AFx / AxF are fine slides.
-static const ModCommand::COMMAND dbmEffects[] =
+static constexpr ModCommand::COMMAND dbmEffects[] =
 {
 	CMD_ARPEGGIO, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 	CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_far.cpp
===================================================================
--- soundlib/Load_far.cpp	(revision 12400)
+++ soundlib/Load_far.cpp	(working copy)
@@ -201,7 +201,7 @@
 	file.Seek(fileHeader.headerLength);
 	
 	// Pattern effect LUT
-	static const EffectCommand farEffects[] =
+	static constexpr EffectCommand farEffects[] =
 	{
 		CMD_NONE,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_gdm.cpp
===================================================================
--- soundlib/Load_gdm.cpp	(revision 12400)
+++ soundlib/Load_gdm.cpp	(working copy)
@@ -90,15 +90,15 @@
 MPT_BINARY_STRUCT(GDMSampleHeader, 62)
 
 
-static const MODTYPE gdmFormatOrigin[] =
+static constexpr MODTYPE gdmFormatOrigin[] =
 {
 	MOD_TYPE_NONE, MOD_TYPE_MOD, MOD_TYPE_MTM, MOD_TYPE_S3M, MOD_TYPE_669, MOD_TYPE_FAR, MOD_TYPE_ULT, MOD_TYPE_STM, MOD_TYPE_MED, MOD_TYPE_PSM
 };
-static const mpt::uchar gdmFormatOriginType[][4] =
+static constexpr mpt::uchar gdmFormatOriginType[][4] =
 {
 	UL_(""), UL_("mod"), UL_("mtm"), UL_("s3m"), UL_("669"), UL_("far"), UL_("ult"), UL_("stm"), UL_("med"), UL_("psm")
 };
-static const mpt::uchar * const gdmFormatOriginFormat[] =
+static constexpr const mpt::uchar * gdmFormatOriginFormat[] =
 {
 	UL_(""),
 	UL_("Generic MOD"),
@@ -243,7 +243,7 @@
 		{
 			// Use the same inaccurate table as 2GDM for translating back to finetune, as our own routines
 			// give slightly different results for the provided sample rates that may result in transpose != 0.
-			static const uint16 rate2finetune[] = { 8363, 8424, 8485, 8547, 8608, 8671, 8734, 8797, 7894, 7951, 8009, 8067, 8125, 8184, 8244, 8303 };
+			static constexpr uint16 rate2finetune[] = { 8363, 8424, 8485, 8547, 8608, 8671, 8734, 8797, 7894, 7951, 8009, 8067, 8125, 8184, 8244, 8303 };
 			for(uint8 i = 0; i < 16; i++)
 			{
 				if(sample.nC5Speed == rate2finetune[i])
@@ -386,7 +386,7 @@
 						m.param = param;
 
 						// Effect translation LUT
-						static const EffectCommand gdmEffTrans[] =
+						static constexpr EffectCommand gdmEffTrans[] =
 						{
 							CMD_NONE, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 							CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_imf.cpp
===================================================================
--- soundlib/Load_imf.cpp	(revision 12400)
+++ soundlib/Load_imf.cpp	(working copy)
@@ -202,7 +202,7 @@
 MPT_BINARY_STRUCT(IMFSample, 64)
 
 
-static const EffectCommand imfEffects[] =
+static constexpr EffectCommand imfEffects[] =
 {
 	CMD_NONE,
 	CMD_SPEED,			// 0x01 1xx Set Tempo
Index: soundlib/load_j2b.cpp
===================================================================
--- soundlib/load_j2b.cpp	(revision 12400)
+++ soundlib/load_j2b.cpp	(working copy)
@@ -31,7 +31,7 @@
 
 
 // First off, a nice vibrato translation LUT.
-static const VibratoType j2bAutoVibratoTrans[] = 
+static constexpr VibratoType j2bAutoVibratoTrans[] = 
 {
 	VIB_SINE, VIB_SQUARE, VIB_RAMP_UP, VIB_RAMP_DOWN, VIB_RANDOM,
 };
@@ -471,7 +471,7 @@
 static bool ConvertAMPattern(FileReader chunk, PATTERNINDEX pat, bool isAM, CSoundFile &sndFile)
 {
 	// Effect translation LUT
-	static const EffectCommand amEffTrans[] =
+	static constexpr EffectCommand amEffTrans[] =
 	{
 		CMD_ARPEGGIO, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO,
 		CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO,
Index: soundlib/Load_mdl.cpp
===================================================================
--- soundlib/Load_mdl.cpp	(revision 12400)
+++ soundlib/Load_mdl.cpp	(working copy)
@@ -154,9 +154,9 @@
 };
 
 
-static const VibratoType MDLVibratoType[] = { VIB_SINE, VIB_RAMP_DOWN, VIB_SQUARE, VIB_SINE };
+static constexpr VibratoType MDLVibratoType[] = { VIB_SINE, VIB_RAMP_DOWN, VIB_SQUARE, VIB_SINE };
 
-static const ModCommand::COMMAND MDLEffTrans[] =
+static constexpr ModCommand::COMMAND MDLEffTrans[] =
 {
 	/* 0 */ CMD_NONE,
 	/* 1st column only */
Index: soundlib/Load_med.cpp
===================================================================
--- soundlib/Load_med.cpp	(revision 12400)
+++ soundlib/Load_med.cpp	(working copy)
@@ -285,7 +285,7 @@
 MPT_BINARY_STRUCT(MMD0EXP, 80)
 
 
-static const uint8 bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
+static constexpr uint8 bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
 
 static void MedConvert(ModCommand &p, const MMD0SONGHEADER *pmsh)
 {
Index: soundlib/Load_mo3.cpp
===================================================================
--- soundlib/Load_mo3.cpp	(revision 12400)
+++ soundlib/Load_mo3.cpp	(working copy)
@@ -1006,7 +1006,7 @@
 	L= 06 00 22 x
 	*/
 
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_NONE,				CMD_NONE,				CMD_NONE,				CMD_ARPEGGIO,
 		CMD_PORTAMENTOUP,		CMD_PORTAMENTODOWN,		CMD_TONEPORTAMENTO,		CMD_VIBRATO,
Index: soundlib/Load_plm.cpp
===================================================================
--- soundlib/Load_plm.cpp	(revision 12400)
+++ soundlib/Load_plm.cpp	(working copy)
@@ -229,7 +229,7 @@
 	const ROWINDEX rowsPerPat = 64;
 	uint32 maxPos = 0;
 
-	static const ModCommand::COMMAND effTrans[] =
+	static constexpr ModCommand::COMMAND effTrans[] =
 	{
 		CMD_NONE,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_ptm.cpp
===================================================================
--- soundlib/Load_ptm.cpp	(revision 12400)
+++ soundlib/Load_ptm.cpp	(working copy)
@@ -252,7 +252,7 @@
 				m.command = command;
 				m.param = param;
 
-				static const EffectCommand effTrans[] = { CMD_GLOBALVOLUME, CMD_RETRIG, CMD_FINEVIBRATO, CMD_NOTESLIDEUP, CMD_NOTESLIDEDOWN, CMD_NOTESLIDEUPRETRIG, CMD_NOTESLIDEDOWNRETRIG, CMD_REVERSEOFFSET };
+				static constexpr EffectCommand effTrans[] = { CMD_GLOBALVOLUME, CMD_RETRIG, CMD_FINEVIBRATO, CMD_NOTESLIDEUP, CMD_NOTESLIDEDOWN, CMD_NOTESLIDEUPRETRIG, CMD_NOTESLIDEDOWNRETRIG, CMD_REVERSEOFFSET };
 				if(m.command < 0x10)
 				{
 					// Beware: Effect letters are as in MOD, but portamento and volume slides behave like in S3M (i.e. fine slides share the same effect letters)
Index: soundlib/Load_s3m.cpp
===================================================================
--- soundlib/Load_s3m.cpp	(revision 12400)
+++ soundlib/Load_s3m.cpp	(working copy)
@@ -602,7 +602,7 @@
 
 bool CSoundFile::SaveS3M(std::ostream &f) const
 {
-	static const uint8 filler[16] =
+	static constexpr uint8 filler[16] =
 	{
 		0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
 		0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
Index: soundlib/Load_stm.cpp
===================================================================
--- soundlib/Load_stm.cpp	(revision 12400)
+++ soundlib/Load_stm.cpp	(working copy)
@@ -258,7 +258,7 @@
 				m->vol = vol;
 			}
 
-			static const EffectCommand stmEffects[] =
+			static constexpr EffectCommand stmEffects[] =
 			{
 				CMD_NONE,        CMD_SPEED,          CMD_POSITIONJUMP, CMD_PATTERNBREAK,   // .ABC
 				CMD_VOLUMESLIDE, CMD_PORTAMENTODOWN, CMD_PORTAMENTOUP, CMD_TONEPORTAMENTO, // DEFG
Index: soundlib/Load_ult.cpp
===================================================================
--- soundlib/Load_ult.cpp	(revision 12400)
+++ soundlib/Load_ult.cpp	(working copy)
@@ -97,7 +97,7 @@
 static void TranslateULTCommands(uint8 &effect, uint8 &param, uint8 version)
 {
 
-	static const uint8 ultEffTrans[] =
+	static constexpr uint8 ultEffTrans[] =
 	{
 		CMD_ARPEGGIO,
 		CMD_PORTAMENTOUP,
Index: soundlib/Load_xm.cpp
===================================================================
--- soundlib/Load_xm.cpp	(revision 12400)
+++ soundlib/Load_xm.cpp	(working copy)
@@ -334,7 +334,7 @@
 			} else if (vol >= 0x60)
 			{
 				// Volume commands 6-F translation.
-				static const ModCommand::VOLCMD volEffTrans[] =
+				static constexpr ModCommand::VOLCMD volEffTrans[] =
 				{
 					VOLCMD_VOLSLIDEDOWN, VOLCMD_VOLSLIDEUP, VOLCMD_FINEVOLDOWN, VOLCMD_FINEVOLUP,
 					VOLCMD_VIBRATOSPEED, VOLCMD_VIBRATODEPTH, VOLCMD_PANNING, VOLCMD_PANSLIDELEFT,
Index: soundlib/modcommand.cpp
===================================================================
--- soundlib/modcommand.cpp	(revision 12400)
+++ soundlib/modcommand.cpp	(working copy)
@@ -900,7 +900,7 @@
 size_t ModCommand::GetEffectWeight(COMMAND cmd)
 {
 	// Effect weights, sorted from lowest to highest weight.
-	static const COMMAND weights[] =
+	static constexpr COMMAND weights[] =
 	{
 		CMD_NONE,
 		CMD_DUMMY,
Index: soundlib/MPEGFrame.cpp
===================================================================
--- soundlib/MPEGFrame.cpp	(revision 12400)
+++ soundlib/MPEGFrame.cpp	(working copy)
@@ -15,13 +15,13 @@
 OPENMPT_NAMESPACE_BEGIN
 
 // Samples per frame - for each MPEG version and all three layers
-static const uint16 samplesPerFrame[2][3] =
+static constexpr uint16 samplesPerFrame[2][3] =
 {
 	{ 384, 1152, 1152 },	// MPEG 1
 	{ 384, 1152,  576 }		// MPEG 2 / 2.5
 };
 // Bit rates for each MPEG version and all three layers
-static const uint16 bitRates[2][3][15] =
+static constexpr uint16 bitRates[2][3][15] =
 {
 	// MPEG 1
 	{
@@ -37,7 +37,7 @@
 	}
 };
 // Sampling rates for each MPEG version and all three layers
-static const uint16 samplingRates[4][3] =
+static constexpr uint16 samplingRates[4][3] =
 { 
 	{ 11025, 12000,  8000 },	// MPEG 2.5
 	{     0,     0,     0 },	// Invalid
@@ -45,13 +45,13 @@
 	{ 44100, 48000, 32000 }		// MPEG 1
 };
 // Samples per Frame / 8
-static const uint8 mpegCoefficients[2][3] =
+static constexpr uint8 mpegCoefficients[2][3] =
 {
 	{ 12, 144, 144 },	// MPEG 1
 	{ 12, 144,  72 }	// MPEG 2 / 2.5
 };
 // Side info size = Offset in frame where Xing/Info magic starts
-static const uint8 sideInfoSize[2][2] =
+static constexpr uint8 sideInfoSize[2][2] =
 {
 	{ 17, 32 },	// MPEG 1
 	{  9, 17 }	// MPEG 2 / 2.5
Index: soundlib/opal.h
===================================================================
--- soundlib/opal.h	(revision 12400)
+++ soundlib/opal.h	(working copy)
@@ -375,7 +375,7 @@
 //==================================================================================================
 void Opal::Port(uint16_t reg_num, uint8_t val) {
 
-    static const int8_t op_lookup[] = {
+    static constexpr int8_t op_lookup[] = {
     //  00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F
         0,  1,  2,  3,  4,  5,  -1, -1, 6,  7,  8,  9,  10, 11, -1, -1,
     //  10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F
@@ -1185,7 +1185,7 @@
 //==================================================================================================
 void Opal::Operator::SetKeyScale(uint16_t scale) {
 
-    static const uint8_t kslShift[4] = { 15, 1, 2, 0 };
+    static constexpr uint8_t kslShift[4] = { 15, 1, 2, 0 };
     KeyScaleShift = kslShift[scale];
     ComputeKeyScaleLevel();
 }
@@ -1314,7 +1314,7 @@
 //==================================================================================================
 void Opal::Operator::ComputeKeyScaleLevel() {
 
-    static const uint8_t levtab[] = {
+    static constexpr uint8_t levtab[] = {
         0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
         0,      0,      0,      0,      0,      0,      0,      0,      0,      8,      12,     16,     20,     24,     28,     32,
         0,      0,      0,      0,      0,      12,     20,     28,     32,     40,     44,     48,     52,     56,     60,     64,
Index: soundlib/OPL.cpp
===================================================================
--- soundlib/OPL.cpp	(revision 12400)
+++ soundlib/OPL.cpp	(working copy)
@@ -67,7 +67,7 @@
 // Translate a channel's first operator address into a register
 uint16 OPL::OperatorToRegister(uint8 oplCh)
 {
-	static const uint8 OPLChannelToOperator[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
+	static constexpr uint8 OPLChannelToOperator[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
 	if(oplCh < 9)
 		return OPLChannelToOperator[oplCh];
 	else
Index: soundlib/plugins/dmo/Distortion.cpp
===================================================================
--- soundlib/plugins/dmo/Distortion.cpp	(revision 12400)
+++ soundlib/plugins/dmo/Distortion.cpp	(working copy)
@@ -222,7 +222,7 @@
 		shift = 5;
 	m_shift = shift;
 
-	static const float LogNorm[32] =
+	static constexpr float LogNorm[32] =
 	{
 		1.00f, 1.00f, 1.50f, 1.00f, 1.75f, 1.40f, 1.17f, 1.00f,
 		1.88f, 1.76f, 1.50f, 1.36f, 1.25f, 1.15f, 1.07f, 1.00f,
Index: soundlib/plugins/dmo/DMOPlugin.cpp
===================================================================
--- soundlib/plugins/dmo/DMOPlugin.cpp	(revision 12400)
+++ soundlib/plugins/dmo/DMOPlugin.cpp	(working copy)
@@ -126,8 +126,8 @@
 }
 
 
-static const float _f2si = 32768.0f;
-static const float _si2f = 1.0f / 32768.0f;
+static constexpr float _f2si = 32768.0f;
+static constexpr float _si2f = 1.0f / 32768.0f;
 
 
 static void InterleaveStereo(const float * MPT_RESTRICT inputL, const float * MPT_RESTRICT inputR, float * MPT_RESTRICT output, uint32 numFrames)
Index: soundlib/plugins/dmo/I3DL2Reverb.cpp
===================================================================
--- soundlib/plugins/dmo/I3DL2Reverb.cpp	(revision 12400)
+++ soundlib/plugins/dmo/I3DL2Reverb.cpp	(working copy)
@@ -450,7 +450,7 @@
 
 CString I3DL2Reverb::GetParamDisplay(PlugParamIndex param)
 {
-	static const TCHAR *modes[] = { _T("LQ"), _T("LQ+"), _T("HQ"), _T("HQ+") };
+	static constexpr const TCHAR * const modes[] = { _T("LQ"), _T("LQ+"), _T("HQ"), _T("HQ+") };
 	float value = m_param[param];
 	switch(param)
 	{
@@ -520,7 +520,7 @@
 void I3DL2Reverb::SetDelayTaps()
 {
 	// Early reflections
-	static const float delays[] =
+	static constexpr float delays[] =
 	{
 		1.0000f, 1.0000f, 0.0000f, 0.1078f, 0.1768f, 0.2727f,
 		0.3953f, 0.5386f, 0.6899f, 0.8306f, 0.9400f, 0.9800f,
Index: soundlib/plugins/LFOPlugin.cpp
===================================================================
--- soundlib/plugins/LFOPlugin.cpp	(revision 12400)
+++ soundlib/plugins/LFOPlugin.cpp	(working copy)
@@ -415,7 +415,7 @@
 		return m_bypassed ? _T("Yes") : _T("No");
 	} else if(param == kWaveform)
 	{
-		static const TCHAR *waveforms[] = { _T("Sine"), _T("Triangle"), _T("Saw"), _T("Square"), _T("Noise"), _T("Smoothed Noise") };
+		static constexpr const TCHAR * const waveforms[] = { _T("Sine"), _T("Triangle"), _T("Saw"), _T("Square"), _T("Noise"), _T("Smoothed Noise") };
 		if(m_waveForm < MPT_ARRAY_COUNT(waveforms))
 			return waveforms[m_waveForm];
 	} else if(param == kLoopMode)
Index: soundlib/plugins/OpCodes.h
===================================================================
--- soundlib/plugins/OpCodes.h	(revision 12400)
+++ soundlib/plugins/OpCodes.h	(working copy)
@@ -15,7 +15,7 @@
 OPENMPT_NAMESPACE_BEGIN
 
 #ifndef NO_VST
-static const char *VstOpCodes[] =
+static constexpr const char *VstOpCodes[] =
 {
 	"effOpen",
 	"effClose",
Index: soundlib/plugins/PluginManager.cpp
===================================================================
--- soundlib/plugins/PluginManager.cpp	(revision 12400)
+++ soundlib/plugins/PluginManager.cpp	(working copy)
@@ -66,7 +66,7 @@
 #endif
 
 #ifdef MODPLUG_TRACKER
-static const mpt::uchar *const cacheSection = UL_("PluginCache");
+static constexpr const mpt::uchar *cacheSection = UL_("PluginCache");
 #endif // MODPLUG_TRACKER
 
 
Index: soundlib/SampleFormatFLAC.cpp
===================================================================
--- soundlib/SampleFormatFLAC.cpp	(revision 12400)
+++ soundlib/SampleFormatFLAC.cpp	(working copy)
@@ -258,7 +258,7 @@
 		file.Rewind();
 		bool oggOK = false;
 		bool needMoreData = true;
-		static const long bufsize = 65536;
+		constexpr long bufsize = 65536;
 		std::size_t readSize = 0;
 		char *buf = nullptr;
 		ogg_sync_state oy;
Index: soundlib/SampleFormats.cpp
===================================================================
--- soundlib/SampleFormats.cpp	(revision 12400)
+++ soundlib/SampleFormats.cpp	(working copy)
@@ -339,8 +339,8 @@
 
 static bool IMAADPCMUnpack16(int16 *target, SmpLength sampleLen, FileReader file, uint16 blockAlign, uint32 numChannels)
 {
-	static const int32 IMAIndexTab[8] =  { -1, -1, -1, -1, 2, 4, 6, 8 };
-	static const int32 IMAUnpackTable[90] =
+	static constexpr int32 IMAIndexTab[8] =  { -1, -1, -1, -1, 2, 4, 6, 8 };
+	static constexpr int32 IMAUnpackTable[90] =
 	{
 		7,     8,     9,     10,    11,    12,    13,    14,
 		16,    17,    19,    21,    23,    25,    28,    31,
@@ -1621,7 +1621,7 @@
 		} else
 		{
 			// Scientific pitch
-			static const int8 keys[] = { 9, 11, 0, 2, 4, 5, 7 };
+			static constexpr int8 keys[] = { 9, 11, 0, 2, 4, 5, 7 };
 			static_assert(CountOf(keys) == 'g' - 'a' + 1);
 			auto keyC = value[0];
 			if(keyC >= 'A' && keyC <= 'G')
Index: soundlib/SampleIO.cpp
===================================================================
--- soundlib/SampleIO.cpp	(revision 12400)
+++ soundlib/SampleIO.cpp	(working copy)
@@ -232,7 +232,7 @@
 	} else if((GetEncoding() == uLaw || GetEncoding() == aLaw) && GetBitDepth() == 16 && (GetChannelFormat() == mono || GetChannelFormat() == stereoInterleaved))
 	{
 		// 8-to-16 bit G.711 u-law / a-law
-		static const int16 uLawTable[256] =
+		static constexpr int16 uLawTable[256] =
 		{
 			-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
 			-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
@@ -268,7 +268,7 @@
 			    56,    48,    40,    32,    24,    16,     8,     0,
 		};
 
-		static const int16 aLawTable[256] =
+		static constexpr int16 aLawTable[256] =
 		{
 			 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
 			 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
Index: soundlib/Snd_fx.cpp
===================================================================
--- soundlib/Snd_fx.cpp	(revision 12400)
+++ soundlib/Snd_fx.cpp	(working copy)
@@ -73,7 +73,7 @@
 #endif
 	std::vector<ChnSettings> chnSettings;
 	double elapsedTime;
-	static const uint32 IGNORE_CHANNEL = uint32_max;
+	static constexpr uint32 IGNORE_CHANNEL = uint32_max;
 
 	GetLengthMemory(const CSoundFile &sf)
 		: sndFile(sf)
@@ -5705,8 +5705,8 @@
 // Convert a ST2 tempo byte to classic tempo and speed combination
 TEMPO CSoundFile::ConvertST2Tempo(uint8 tempo)
 {
-	static const uint8 ST2TempoFactor[] = { 140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1 };
-	static const uint32 st2MixingRate = 23863; // Highest possible setting in ST2
+	static constexpr uint8 ST2TempoFactor[] = { 140, 50, 25, 15, 10, 7, 6, 4, 3, 3, 2, 2, 2, 2, 1, 1 };
+	static constexpr uint32 st2MixingRate = 23863; // Highest possible setting in ST2
 
 	// This underflows at tempo 06...0F, and the resulting tick lengths depend on the mixing rate.
 	int32 samplesPerTick = st2MixingRate / (49 - ((ST2TempoFactor[tempo >> 4u] * (tempo & 0x0F)) >> 4u));
Index: soundlib/Sndfile.cpp
===================================================================
--- soundlib/Sndfile.cpp	(revision 12400)
+++ soundlib/Sndfile.cpp	(working copy)
@@ -294,9 +294,6 @@
 }
 
 
-const std::size_t CSoundFile::ProbeRecommendedSize = PROBE_RECOMMENDED_SIZE;
-
-
 #define MPT_DO_PROBE( storedResult , call ) \
 	MPT_DO { \
 		ProbeResult lastResult = call ; \
Index: soundlib/Sndfile.h
===================================================================
--- soundlib/Sndfile.h	(revision 12400)
+++ soundlib/Sndfile.h	(working copy)
@@ -622,7 +622,7 @@
 
 	#define PROBE_RECOMMENDED_SIZE 2048u
 
-	static const std::size_t ProbeRecommendedSize;
+	static constexpr std::size_t ProbeRecommendedSize = PROBE_RECOMMENDED_SIZE;
 
 	enum ProbeFlags
 	{
Index: soundlib/Sndmix.cpp
===================================================================
--- soundlib/Sndmix.cpp	(revision 12400)
+++ soundlib/Sndmix.cpp	(working copy)
@@ -28,7 +28,7 @@
 // Log tables for pre-amp
 // Pre-amp (or more precisely: Pre-attenuation) depends on the number of channels,
 // Which this table takes care of.
-static const uint8 PreAmpTable[16] =
+static constexpr uint8 PreAmpTable[16] =
 {
 	0x60, 0x60, 0x60, 0x70,	// 0-7
 	0x80, 0x88, 0x90, 0x98,	// 8-15
@@ -37,7 +37,7 @@
 };
 
 #ifndef NO_AGC
-static const uint8 PreAmpAGCTable[16] =
+static constexpr uint8 PreAmpAGCTable[16] =
 {
 	0x60, 0x60, 0x60, 0x64,
 	0x68, 0x70, 0x78, 0x80,
@@ -786,7 +786,7 @@
 	} else if(GetType() & (MOD_TYPE_DIGI | MOD_TYPE_DBM))
 	{
 		// Other waveforms are not supported.
-		static const int8 DBMSinus[] =
+		static constexpr int8 DBMSinus[] =
 		{
 			33, 52, 69, 84, 96, 107, 116, 122,  125, 127,  125, 122, 116, 107, 96, 84,
 			69, 52, 33, 13, -8, -31, -54, -79, -104,-128, -104, -79, -54, -31, -8, 13,
Index: soundlib/tuning.h
===================================================================
--- soundlib/tuning.h	(revision 12400)
+++ soundlib/tuning.h	(working copy)
@@ -28,7 +28,7 @@
 
 public:
 
-	static const char s_FileExtension[5];
+	static constexpr char s_FileExtension[5] = ".tun";
 
 	enum TuningType
 	{
Index: soundlib/tuningbase.cpp
===================================================================
--- soundlib/tuningbase.cpp	(revision 12400)
+++ soundlib/tuningbase.cpp	(working copy)
@@ -35,10 +35,6 @@
 
 
 
-const char CTuningRTI::s_FileExtension[5] = ".tun";
-
-
-
 void CTuningRTI::SetNoteName(const NOTEINDEXTYPE& n, const std::string& str)
 {
 	if(!str.empty())
Index: soundlib/tuningCollection.cpp
===================================================================
--- soundlib/tuningCollection.cpp	(revision 12400)
+++ soundlib/tuningCollection.cpp	(working copy)
@@ -34,9 +34,6 @@
 */
 
 
-const char CTuningCollection::s_FileExtension[4] = ".tc";
-
-
 namespace CTuningS11n
 {
 	void ReadStr(std::istream& iStrm, std::string& str, const size_t);
Index: soundlib/tuningcollection.h
===================================================================
--- soundlib/tuningcollection.h	(revision 12400)
+++ soundlib/tuningcollection.h	(working copy)
@@ -28,7 +28,7 @@
 
 public:
 
-	static const char s_FileExtension[4];
+	static constexpr char s_FileExtension[4] = ".tc";
 
 	// OpenMPT <= 1.26 had to following limits:
 	//  *  255 built-in tunings (only 2 were ever actually provided)
avoid-static-const-v3.patch (62,819 bytes)   
Saga Musix

Saga Musix

2019-12-23 18:07

administrator   ~0004169

That's even better of course.

manx

manx

2019-12-24 09:30

administrator   ~0004170

r12407

Issue History

Date Modified Username Field Change
2019-11-06 16:02 manx New Issue
2019-11-06 16:02 manx Status new => assigned
2019-11-06 16:02 manx Assigned To => manx
2019-11-10 17:47 Saga Musix Note Added: 0004149
2019-12-21 09:51 manx Note Added: 0004164
2019-12-21 09:51 manx File Added: avoid-static-const-v2.patch
2019-12-21 09:56 manx Note Added: 0004165
2019-12-22 15:45 Saga Musix Note Added: 0004166
2019-12-23 17:32 Gerirish Note Added: 0004167
2019-12-23 17:45 manx Target Version OpenMPT 1.28.09.00 / libopenmpt 0.4.11 (current stable) => OpenMPT 1.29 / libopenmpt 0.5 (goals)
2019-12-23 17:59 manx Note Added: 0004168
2019-12-23 17:59 manx File Added: avoid-static-const-v3.patch
2019-12-23 18:07 Saga Musix Note Added: 0004169
2019-12-24 09:30 manx Status assigned => resolved
2019-12-24 09:30 manx Resolution open => fixed
2019-12-24 09:30 manx Fixed in Version => OpenMPT 1.29 / libopenmpt 0.5 (goals)
2019-12-24 09:30 manx Note Added: 0004170