From: <man...@us...> - 2014-09-24 07:28:27
|
Revision: 4305 http://sourceforge.net/p/modplug/code/4305 Author: manxorist Date: 2014-09-24 07:28:15 +0000 (Wed, 24 Sep 2014) Log Message: ----------- [Ref] sounddev: Rewrite class ChannelMapping to always guarantee the class invariant. Invalid objects can no longer be contructed and get replaced with the empty mapping instead. [Ref] sounddev: Class ChannelMapping now internally knows the number of host channels. [Fix] sounddev: There were cases where incorrect channel mappings were saved to the ini file. Detect those and revert to default identity mapping in that case. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -491,7 +491,7 @@ //-------------------------------------------- { int usedChannels = m_CbnChannels.GetItemData(m_CbnChannels.GetCurSel()); - if(!m_Settings.ChannelMapping.IsValid(usedChannels)) + if(m_Settings.ChannelMapping.GetNumHostChannels() != static_cast<uint32>(usedChannels)) { // If the channel mapping is not valid for the selected number of channels, reset it to default identity mapping. m_Settings.ChannelMapping = SoundDevice::ChannelMapping(); @@ -514,7 +514,7 @@ { const int pos = (int)::SendMessageW(combo->m_hWnd, CB_ADDSTRING, 0, (LPARAM)m_CurrentDeviceDynamicCaps.channelNames[dch].c_str()); combo->SetItemData(pos, (DWORD_PTR)dch); - if(dch == m_Settings.ChannelMapping.ToDevice(mch)) + if(static_cast<int32>(dch) == m_Settings.ChannelMapping.ToDevice(mch)) { combo->SetCurSel(pos); } @@ -738,7 +738,7 @@ if(m_CurrentDeviceCaps.CanChannelMapping) { int numChannels = std::min<int>(m_Settings.Channels, NUM_CHANNELCOMBOBOXES); - std::vector<uint32> channels(numChannels); + std::vector<int32> channels(numChannels); for(int mch = 0; mch < numChannels; mch++) // Host channels { CComboBox *combo = &m_CbnChannelMapping[mch]; Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -450,6 +450,11 @@ m_SoundDeviceSettingsDefaults.BoostThreadPriority = m_SoundDeviceBoostThreadPriority; m_SoundDeviceSettingsDefaults.UseHardwareTiming = m_SoundDeviceUseHardwareTiming; m_SoundDeviceSettingsDefaults.ChannelMapping = m_SoundDeviceChannelMapping; + if(m_SoundDeviceSettingsDefaults.ChannelMapping.GetNumHostChannels() != m_SoundDeviceSettingsDefaults.Channels) + { + // reset invalid channel mapping to default + m_SoundDeviceSettingsDefaults.ChannelMapping = SoundDevice::ChannelMapping(m_SoundDeviceSettingsDefaults.Channels); + } m_SoundDeviceSettingsUseOldDefaults = true; } if(storedVersion < MAKE_VERSION_NUMERIC(1,21,01,26)) @@ -599,6 +604,11 @@ , DitherType(conf, L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"DitherType", defaults.DitherType) , ChannelMapping(conf, L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"ChannelMapping", defaults.ChannelMapping) { + if(ChannelMapping.Get().GetNumHostChannels() != Channels) + { + // reset invalid chanel mapping to default + ChannelMapping = SoundDevice::ChannelMapping(Channels); + } // store informational data (not read back, just to allow the user to mock with the raw ini file) conf.Write(L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"ID", deviceInfo.id); conf.Write(L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"InternalID", deviceInfo.internalID); Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -58,23 +58,31 @@ } -ChannelMapping::ChannelMapping(const std::vector<uint32> &mapping) -//---------------------------------------------------------------- - : ChannelToDeviceChannel(mapping) +ChannelMapping::ChannelMapping(uint32 numHostChannels) +//---------------------------------------------------- { - return; + ChannelToDeviceChannel.resize(numHostChannels); + for(uint32 channel = 0; channel < numHostChannels; ++channel) + { + ChannelToDeviceChannel[channel] = channel; + } } -ChannelMapping ChannelMapping::BaseChannel(uint32 channels, uint32 baseChannel) -//----------------------------------------------------------------------------- +ChannelMapping::ChannelMapping(const std::vector<int32> &mapping) +//--------------------------------------------------------------- { - SoundDevice::ChannelMapping result; - result.ChannelToDeviceChannel.clear(); - if(baseChannel == 0) + if(IsValid(mapping)) { - return result; + ChannelToDeviceChannel = mapping; } +} + + +ChannelMapping ChannelMapping::BaseChannel(uint32 channels, int32 baseChannel) +//---------------------------------------------------------------------------- +{ + SoundDevice::ChannelMapping result; result.ChannelToDeviceChannel.resize(channels); for(uint32 channel = 0; channel < channels; ++channel) { @@ -84,24 +92,29 @@ } -bool ChannelMapping::IsValid(uint32 channels) const -//------------------------------------------------- +bool ChannelMapping::IsValid(const std::vector<int32> &mapping) +//------------------------------------------------------------- { - if(ChannelToDeviceChannel.empty()) + if(mapping.empty()) { return true; } - if(ChannelToDeviceChannel.size() != channels) + std::map<int32, uint32> inverseMapping; + for(uint32 hostChannel = 0; hostChannel < mapping.size(); ++hostChannel) { - return false; + int32 deviceChannel = mapping[hostChannel]; + if(deviceChannel < 0) + { + return false; + } + if(deviceChannel > MaxDeviceChannel) + { + return false; + } + inverseMapping[deviceChannel] = hostChannel; } - std::map<uint32, uint32> inverseMapping; - for(uint32 channel = 0; channel < channels; ++channel) + if(inverseMapping.size() != mapping.size()) { - inverseMapping[ChannelToDeviceChannel[channel]] = channel; - } - if(inverseMapping.size() != channels) - { return false; } return true; @@ -111,14 +124,14 @@ std::string ChannelMapping::ToString() const //------------------------------------------ { - return mpt::String::Combine<uint32>(ChannelToDeviceChannel); + return mpt::String::Combine<int32>(ChannelToDeviceChannel); } ChannelMapping ChannelMapping::FromString(const std::string &str) //--------------------------------------------------------------- { - return SoundDevice::ChannelMapping(mpt::String::Split<uint32>(str)); + return SoundDevice::ChannelMapping(mpt::String::Split<int32>(str)); } @@ -235,9 +248,20 @@ if(m_Settings.UpdateInterval == 0.0) m_Settings.UpdateInterval = m_Caps.DefaultSettings.UpdateInterval; m_Settings.Latency = Clamp(m_Settings.Latency, m_Caps.LatencyMin, m_Caps.LatencyMax); m_Settings.UpdateInterval = Clamp(m_Settings.UpdateInterval, m_Caps.UpdateIntervalMin, m_Caps.UpdateIntervalMax); - if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) + if(m_Caps.CanChannelMapping) { - return false; + if(m_Settings.ChannelMapping.GetNumHostChannels() == 0) + { + // default mapping + m_Settings.ChannelMapping = SoundDevice::ChannelMapping(m_Settings.Channels); + } + if(m_Settings.ChannelMapping.GetNumHostChannels() != m_Settings.Channels) + { + return false; + } + } else + { + m_Settings.ChannelMapping = SoundDevice::ChannelMapping(m_Settings.Channels); } m_Flags = SoundDevice::Flags(); m_BufferAttributes.Latency = m_Settings.Latency; Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-24 07:28:15 UTC (rev 4305) @@ -159,41 +159,52 @@ private: - std::vector<uint32> ChannelToDeviceChannel; + std::vector<int32> ChannelToDeviceChannel; public: - // Construct default identity mapping + static const int32 MaxDeviceChannel = 32000; + +public: + + // Construct default empty mapping ChannelMapping(); + // Construct default identity mapping + ChannelMapping(uint32 numHostChannels); + // Construct mapping from given vector. - ChannelMapping(const std::vector<uint32> &mapping); + // Silently fall back to identity mapping if mapping is invalid. + ChannelMapping(const std::vector<int32> &mapping); // Construct mapping for #channels with a baseChannel offset. - static ChannelMapping BaseChannel(uint32 channels, uint32 baseChannel); + static ChannelMapping BaseChannel(uint32 channels, int32 baseChannel); +private: + + // check that the channel mapping is actually a 1:1 mapping + static bool IsValid(const std::vector<int32> &mapping); + public: bool operator == (const SoundDevice::ChannelMapping &cmp) const { return (ChannelToDeviceChannel == cmp.ChannelToDeviceChannel); } - - // check that the channel mapping is actually a 1:1 mapping - bool IsValid(uint32 channels) const; - + + uint32 GetNumHostChannels() const + { + return ChannelToDeviceChannel.size(); + } + // Get the number of required device channels for this mapping. Derived from the maximum mapped-to channel number. - uint32 GetRequiredDeviceChannels(uint32 numHostChannels) const + int32 GetRequiredDeviceChannels() const { - if(!IsValid(numHostChannels)) + if(ChannelToDeviceChannel.empty()) { return 0; } - if(ChannelToDeviceChannel.empty()) - { - return numHostChannels; - } - uint32 maxChannel = 0; + int32 maxChannel = 0; for(uint32 channel = 0; channel < ChannelToDeviceChannel.size(); ++channel) { if(ChannelToDeviceChannel[channel] > maxChannel) @@ -205,12 +216,8 @@ } // Convert OpenMPT channel number to the mapped device channel number. - uint32 ToDevice(uint32 channel) const + int32 ToDevice(uint32 channel) const { - if(ChannelToDeviceChannel.empty()) - { - return channel; - } if(channel >= ChannelToDeviceChannel.size()) { return channel; Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -272,12 +272,8 @@ { throw ASIOException("Not enough output channels."); } - if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) + if(m_Settings.ChannelMapping.GetRequiredDeviceChannels() > outputChannels) { - throw ASIOException("Channel mapping has wrong channel count."); - } - if(m_Settings.ChannelMapping.GetRequiredDeviceChannels(m_Settings.Channels) > (std::size_t)outputChannels) - { throw ASIOException("Channel mapping requires more channels than available."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |