Sndfile.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083
  1. /*
  2. * Sndfile.cpp
  3. * -----------
  4. * Purpose: Core class of the playback engine. Every song is represented by a CSoundFile object.
  5. * Notes : (currently none)
  6. * Authors: Olivier Lapicque
  7. * OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #include "stdafx.h"
  11. #ifdef MODPLUG_TRACKER
  12. #include "../mptrack/Mptrack.h" // For CTrackApp::OpenURL
  13. #include "../mptrack/TrackerSettings.h"
  14. #include "../mptrack/Moddoc.h"
  15. #include "../mptrack/Reporting.h"
  16. #include "../mptrack/Mainfrm.h"
  17. #endif // MODPLUG_TRACKER
  18. #ifdef MPT_EXTERNAL_SAMPLES
  19. #include "../common/mptFileIO.h"
  20. #endif // MPT_EXTERNAL_SAMPLES
  21. #include "../common/version.h"
  22. #include "../soundlib/AudioCriticalSection.h"
  23. #include "../common/serialization_utils.h"
  24. #include "Sndfile.h"
  25. #include "Tables.h"
  26. #include "mod_specifications.h"
  27. #include "tuningcollection.h"
  28. #include "plugins/PluginManager.h"
  29. #include "plugins/PlugInterface.h"
  30. #include "../common/mptStringBuffer.h"
  31. #include "../common/FileReader.h"
  32. #include "Container.h"
  33. #include "OPL.h"
  34. #include "mpt/io/io.hpp"
  35. #include "mpt/io/io_stdstream.hpp"
  36. #ifndef NO_ARCHIVE_SUPPORT
  37. #include "../unarchiver/unarchiver.h"
  38. #endif // NO_ARCHIVE_SUPPORT
  39. OPENMPT_NAMESPACE_BEGIN
  40. bool SettingCacheCompleteFileBeforeLoading()
  41. {
  42. #ifdef MODPLUG_TRACKER
  43. return TrackerSettings::Instance().MiscCacheCompleteFileBeforeLoading;
  44. #else
  45. return false;
  46. #endif
  47. }
  48. mpt::ustring FileHistory::AsISO8601() const
  49. {
  50. tm date = loadDate;
  51. if(openTime > 0)
  52. {
  53. // Calculate the date when editing finished.
  54. double openSeconds = static_cast<double>(openTime) / HISTORY_TIMER_PRECISION;
  55. tm tmpLoadDate = loadDate;
  56. int64 loadDateSinceEpoch = mpt::Date::Unix::FromUTC(tmpLoadDate);
  57. int64 saveDateSinceEpoch = loadDateSinceEpoch + mpt::saturate_round<int64>(openSeconds);
  58. date = mpt::Date::Unix(saveDateSinceEpoch).AsUTC();
  59. }
  60. return mpt::Date::ToShortenedISO8601(date);
  61. }
  62. CSoundFile::PlayState::PlayState()
  63. {
  64. std::fill(std::begin(Chn), std::end(Chn), ModChannel{});
  65. m_midiMacroScratchSpace.reserve(kMacroLength); // Note: If macros ever become variable-length, the scratch space needs to be at least one byte longer than the longest macro in the file for end-of-SysEx insertion to stay allocation-free in the mixer!
  66. }
  67. //////////////////////////////////////////////////////////
  68. // CSoundFile
  69. #ifdef MODPLUG_TRACKER
  70. const NoteName *CSoundFile::m_NoteNames = NoteNamesFlat;
  71. #endif
  72. CSoundFile::CSoundFile() :
  73. #ifndef MODPLUG_TRACKER
  74. m_NoteNames(NoteNamesSharp),
  75. #endif
  76. m_pModSpecs(&ModSpecs::itEx),
  77. m_nType(MOD_TYPE_NONE),
  78. Patterns(*this),
  79. #ifdef MODPLUG_TRACKER
  80. m_MIDIMapper(*this),
  81. #endif
  82. Order(*this),
  83. m_PRNG(mpt::make_prng<mpt::fast_prng>(mpt::global_prng())),
  84. m_visitedRows(*this)
  85. {
  86. MemsetZero(MixSoundBuffer);
  87. MemsetZero(MixRearBuffer);
  88. MemsetZero(MixFloatBuffer);
  89. #ifdef MODPLUG_TRACKER
  90. m_bChannelMuteTogglePending.reset();
  91. m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = (TrackerSettings::Instance().m_nRowHighlightBeats) ? TrackerSettings::Instance().m_nRowHighlightBeats : 4;
  92. m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = (TrackerSettings::Instance().m_nRowHighlightMeasures >= m_nDefaultRowsPerBeat) ? TrackerSettings::Instance().m_nRowHighlightMeasures : m_nDefaultRowsPerBeat * 4;
  93. #else
  94. m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = 4;
  95. m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = 16;
  96. #endif // MODPLUG_TRACKER
  97. MemsetZero(Instruments);
  98. Clear(m_szNames);
  99. m_pTuningsTuneSpecific = new CTuningCollection();
  100. }
  101. CSoundFile::~CSoundFile()
  102. {
  103. Destroy();
  104. delete m_pTuningsTuneSpecific;
  105. m_pTuningsTuneSpecific = nullptr;
  106. }
  107. void CSoundFile::AddToLog(LogLevel level, const mpt::ustring &text) const
  108. {
  109. if(m_pCustomLog)
  110. {
  111. m_pCustomLog->AddToLog(level, text);
  112. } else
  113. {
  114. #ifdef MODPLUG_TRACKER
  115. if(GetpModDoc()) GetpModDoc()->AddToLog(level, text);
  116. #else
  117. MPT_LOG_GLOBAL(level, "soundlib", text);
  118. #endif
  119. }
  120. }
  121. // Global variable initializer for loader functions
  122. void CSoundFile::InitializeGlobals(MODTYPE type)
  123. {
  124. // Do not add or change any of these values! And if you do, review each and every loader to check if they require these defaults!
  125. m_nType = type;
  126. MODTYPE bestType = GetBestSaveFormat();
  127. m_playBehaviour = GetDefaultPlaybackBehaviour(bestType);
  128. SetModSpecsPointer(m_pModSpecs, bestType);
  129. // Delete instruments in case some previously called loader already created them.
  130. for(INSTRUMENTINDEX i = 1; i <= m_nInstruments; i++)
  131. {
  132. delete Instruments[i];
  133. Instruments[i] = nullptr;
  134. }
  135. m_ContainerType = MOD_CONTAINERTYPE_NONE;
  136. m_nChannels = 0;
  137. m_nInstruments = 0;
  138. m_nSamples = 0;
  139. m_nSamplePreAmp = 48;
  140. m_nVSTiVolume = 48;
  141. m_OPLVolumeFactor = m_OPLVolumeFactorScale;
  142. m_nDefaultSpeed = 6;
  143. m_nDefaultTempo.Set(125);
  144. m_nDefaultGlobalVolume = MAX_GLOBAL_VOLUME;
  145. m_SongFlags.reset();
  146. m_nMinPeriod = 16;
  147. m_nMaxPeriod = 32767;
  148. m_nResampling = SRCMODE_DEFAULT;
  149. m_dwLastSavedWithVersion = Version(0);
  150. m_dwCreatedWithVersion = Version(0);
  151. SetMixLevels(MixLevels::Compatible);
  152. Patterns.ClearPatterns();
  153. Order.Initialize();
  154. m_songName.clear();
  155. m_songArtist.clear();
  156. m_songMessage.clear();
  157. m_modFormat = ModFormatDetails();
  158. m_FileHistory.clear();
  159. m_tempoSwing.clear();
  160. #ifdef MPT_EXTERNAL_SAMPLES
  161. m_samplePaths.clear();
  162. #endif // MPT_EXTERNAL_SAMPLES
  163. // Note: we do not use the Amiga resampler for DBM as it's a multichannel format and can make use of higher-quality Amiga soundcards instead of Paula.
  164. if(GetType() & (/*MOD_TYPE_DBM | */MOD_TYPE_DIGI | MOD_TYPE_MED | MOD_TYPE_MOD | MOD_TYPE_OKT | MOD_TYPE_SFX | MOD_TYPE_STP))
  165. {
  166. m_SongFlags.set(SONG_ISAMIGA);
  167. }
  168. }
  169. void CSoundFile::InitializeChannels()
  170. {
  171. for(CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++)
  172. {
  173. InitChannel(nChn);
  174. }
  175. }
  176. struct FileFormatLoader
  177. {
  178. decltype(CSoundFile::ProbeFileHeaderXM) *prober;
  179. decltype(&CSoundFile::ReadXM) loader;
  180. };
  181. #ifdef MODPLUG_TRACKER
  182. #define MPT_DECLARE_FORMAT(format) { nullptr, &CSoundFile::Read ## format }
  183. #else
  184. #define MPT_DECLARE_FORMAT(format) { CSoundFile::ProbeFileHeader ## format, &CSoundFile::Read ## format }
  185. #endif
  186. // All module format loaders, in the order they should be executed.
  187. // This order matters, depending on the format, due to some unfortunate
  188. // clashes or lack of magic bytes that can lead to mis-detection of some formats.
  189. // Apart from that, more common formats with sane magic bytes are also found
  190. // at the top of the list to match the most common cases more quickly.
  191. static constexpr FileFormatLoader ModuleFormatLoaders[] =
  192. {
  193. MPT_DECLARE_FORMAT(XM),
  194. MPT_DECLARE_FORMAT(IT),
  195. MPT_DECLARE_FORMAT(S3M),
  196. MPT_DECLARE_FORMAT(STM),
  197. MPT_DECLARE_FORMAT(MED),
  198. MPT_DECLARE_FORMAT(MTM),
  199. MPT_DECLARE_FORMAT(MDL),
  200. MPT_DECLARE_FORMAT(DBM),
  201. MPT_DECLARE_FORMAT(FAR),
  202. MPT_DECLARE_FORMAT(AMS),
  203. MPT_DECLARE_FORMAT(AMS2),
  204. MPT_DECLARE_FORMAT(OKT),
  205. MPT_DECLARE_FORMAT(PTM),
  206. MPT_DECLARE_FORMAT(ULT),
  207. MPT_DECLARE_FORMAT(DMF),
  208. MPT_DECLARE_FORMAT(DSM),
  209. MPT_DECLARE_FORMAT(AMF_Asylum),
  210. MPT_DECLARE_FORMAT(AMF_DSMI),
  211. MPT_DECLARE_FORMAT(PSM),
  212. MPT_DECLARE_FORMAT(PSM16),
  213. MPT_DECLARE_FORMAT(MT2),
  214. MPT_DECLARE_FORMAT(ITP),
  215. #if defined(MODPLUG_TRACKER) || defined(MPT_FUZZ_TRACKER)
  216. // These make little sense for a module player library
  217. MPT_DECLARE_FORMAT(UAX),
  218. MPT_DECLARE_FORMAT(WAV),
  219. MPT_DECLARE_FORMAT(MID),
  220. #endif // MODPLUG_TRACKER || MPT_FUZZ_TRACKER
  221. MPT_DECLARE_FORMAT(GDM),
  222. MPT_DECLARE_FORMAT(IMF),
  223. MPT_DECLARE_FORMAT(DIGI),
  224. MPT_DECLARE_FORMAT(DTM),
  225. MPT_DECLARE_FORMAT(PLM),
  226. MPT_DECLARE_FORMAT(AM),
  227. MPT_DECLARE_FORMAT(J2B),
  228. MPT_DECLARE_FORMAT(PT36),
  229. MPT_DECLARE_FORMAT(SymMOD),
  230. MPT_DECLARE_FORMAT(MUS_KM),
  231. MPT_DECLARE_FORMAT(FMT),
  232. MPT_DECLARE_FORMAT(SFX),
  233. MPT_DECLARE_FORMAT(STP),
  234. MPT_DECLARE_FORMAT(DSym),
  235. MPT_DECLARE_FORMAT(STX),
  236. MPT_DECLARE_FORMAT(MOD),
  237. MPT_DECLARE_FORMAT(ICE),
  238. MPT_DECLARE_FORMAT(669),
  239. MPT_DECLARE_FORMAT(C67),
  240. MPT_DECLARE_FORMAT(MO3),
  241. MPT_DECLARE_FORMAT(M15),
  242. };
  243. #undef MPT_DECLARE_FORMAT
  244. CSoundFile::ProbeResult CSoundFile::ProbeAdditionalSize(MemoryFileReader &file, const uint64 *pfilesize, uint64 minimumAdditionalSize)
  245. {
  246. const uint64 availableFileSize = file.GetLength();
  247. const uint64 fileSize = (pfilesize ? *pfilesize : file.GetLength());
  248. //const uint64 validFileSize = std::min(fileSize, static_cast<uint64>(ProbeRecommendedSize));
  249. const uint64 goalSize = file.GetPosition() + minimumAdditionalSize;
  250. //const uint64 goalMinimumSize = std::min(goalSize, static_cast<uint64>(ProbeRecommendedSize));
  251. if(pfilesize)
  252. {
  253. if(availableFileSize < std::min(fileSize, static_cast<uint64>(ProbeRecommendedSize)))
  254. {
  255. if(availableFileSize < goalSize)
  256. {
  257. return ProbeWantMoreData;
  258. }
  259. } else
  260. {
  261. if(fileSize < goalSize)
  262. {
  263. return ProbeFailure;
  264. }
  265. }
  266. return ProbeSuccess;
  267. }
  268. return ProbeSuccess;
  269. }
  270. #define MPT_DO_PROBE( storedResult , call ) \
  271. do { \
  272. ProbeResult lastResult = call ; \
  273. if(lastResult == ProbeSuccess) { \
  274. return ProbeSuccess; \
  275. } else if(lastResult == ProbeWantMoreData) { \
  276. storedResult = ProbeWantMoreData; \
  277. } \
  278. } while(0) \
  279. /**/
  280. CSoundFile::ProbeResult CSoundFile::Probe(ProbeFlags flags, mpt::span<const std::byte> data, const uint64 *pfilesize)
  281. {
  282. ProbeResult result = ProbeFailure;
  283. if(pfilesize && (*pfilesize < data.size()))
  284. {
  285. throw std::out_of_range("");
  286. }
  287. if(!data.data())
  288. {
  289. throw std::invalid_argument("");
  290. }
  291. MemoryFileReader file(data);
  292. if(flags & ProbeContainers)
  293. {
  294. #if !defined(MPT_WITH_ANCIENT)
  295. MPT_DO_PROBE(result, ProbeFileHeaderMMCMP(file, pfilesize));
  296. MPT_DO_PROBE(result, ProbeFileHeaderPP20(file, pfilesize));
  297. MPT_DO_PROBE(result, ProbeFileHeaderXPK(file, pfilesize));
  298. #endif // !MPT_WITH_ANCIENT
  299. MPT_DO_PROBE(result, ProbeFileHeaderUMX(file, pfilesize));
  300. }
  301. if(flags & ProbeModules)
  302. {
  303. for(const auto &format : ModuleFormatLoaders)
  304. {
  305. if(format.prober != nullptr)
  306. {
  307. MPT_DO_PROBE(result, format.prober(file, pfilesize));
  308. }
  309. }
  310. }
  311. if(pfilesize)
  312. {
  313. if((result == ProbeWantMoreData) && (mpt::saturate_cast<std::size_t>(*pfilesize) <= data.size()))
  314. {
  315. // If the prober wants more data but we already reached EOF,
  316. // probing must fail.
  317. result = ProbeFailure;
  318. }
  319. } else
  320. {
  321. if((result == ProbeWantMoreData) && (data.size() >= ProbeRecommendedSize))
  322. {
  323. // If the prober wants more daat but we already provided the recommended required maximum,
  324. // just return success as this is the best we can do for the suggestesd probing size.
  325. result = ProbeSuccess;
  326. }
  327. }
  328. return result;
  329. }
  330. bool CSoundFile::Create(FileReader file, ModLoadingFlags loadFlags, CModDoc *pModDoc)
  331. {
  332. m_nMixChannels = 0;
  333. #ifdef MODPLUG_TRACKER
  334. m_pModDoc = pModDoc;
  335. #else
  336. MPT_UNUSED(pModDoc);
  337. m_nFreqFactor = m_nTempoFactor = 65536;
  338. #endif // MODPLUG_TRACKER
  339. Clear(m_szNames);
  340. #ifndef NO_PLUGINS
  341. std::fill(std::begin(m_MixPlugins), std::end(m_MixPlugins), SNDMIXPLUGIN());
  342. #endif // NO_PLUGINS
  343. if(CreateInternal(file, loadFlags))
  344. return true;
  345. #ifndef NO_ARCHIVE_SUPPORT
  346. if(!(loadFlags & skipContainer) && file.IsValid())
  347. {
  348. CUnarchiver unarchiver(file);
  349. if(unarchiver.ExtractBestFile(GetSupportedExtensions(true)))
  350. {
  351. if(CreateInternal(unarchiver.GetOutputFile(), loadFlags))
  352. {
  353. // Read archive comment if there is no song comment
  354. if(m_songMessage.empty())
  355. {
  356. m_songMessage.assign(mpt::ToCharset(mpt::Charset::Locale, unarchiver.GetComment()));
  357. }
  358. return true;
  359. }
  360. }
  361. }
  362. #endif
  363. return false;
  364. }
  365. bool CSoundFile::CreateInternal(FileReader file, ModLoadingFlags loadFlags)
  366. {
  367. if(file.IsValid())
  368. {
  369. std::vector<ContainerItem> containerItems;
  370. MODCONTAINERTYPE packedContainerType = MOD_CONTAINERTYPE_NONE;
  371. if(!(loadFlags & skipContainer))
  372. {
  373. ContainerLoadingFlags containerLoadFlags = (loadFlags == onlyVerifyHeader) ? ContainerOnlyVerifyHeader : ContainerUnwrapData;
  374. #if !defined(MPT_WITH_ANCIENT)
  375. if(packedContainerType == MOD_CONTAINERTYPE_NONE && UnpackXPK(containerItems, file, containerLoadFlags)) packedContainerType = MOD_CONTAINERTYPE_XPK;
  376. if(packedContainerType == MOD_CONTAINERTYPE_NONE && UnpackPP20(containerItems, file, containerLoadFlags)) packedContainerType = MOD_CONTAINERTYPE_PP20;
  377. if(packedContainerType == MOD_CONTAINERTYPE_NONE && UnpackMMCMP(containerItems, file, containerLoadFlags)) packedContainerType = MOD_CONTAINERTYPE_MMCMP;
  378. #endif // !MPT_WITH_ANCIENT
  379. if(packedContainerType == MOD_CONTAINERTYPE_NONE && UnpackUMX(containerItems, file, containerLoadFlags)) packedContainerType = MOD_CONTAINERTYPE_UMX;
  380. if(packedContainerType != MOD_CONTAINERTYPE_NONE)
  381. {
  382. if(loadFlags == onlyVerifyHeader)
  383. {
  384. return true;
  385. }
  386. if(!containerItems.empty())
  387. {
  388. // cppcheck false-positive
  389. // cppcheck-suppress containerOutOfBounds
  390. file = containerItems[0].file;
  391. }
  392. }
  393. }
  394. if(loadFlags & skipModules)
  395. {
  396. return false;
  397. }
  398. // Try all module format loaders
  399. bool loaderSuccess = false;
  400. for(const auto &format : ModuleFormatLoaders)
  401. {
  402. loaderSuccess = (this->*(format.loader))(file, loadFlags);
  403. if(loaderSuccess)
  404. break;
  405. }
  406. if(!loaderSuccess)
  407. {
  408. m_nType = MOD_TYPE_NONE;
  409. m_ContainerType = MOD_CONTAINERTYPE_NONE;
  410. }
  411. if(loadFlags == onlyVerifyHeader)
  412. {
  413. return loaderSuccess;
  414. }
  415. if(packedContainerType != MOD_CONTAINERTYPE_NONE && m_ContainerType == MOD_CONTAINERTYPE_NONE)
  416. {
  417. m_ContainerType = packedContainerType;
  418. }
  419. m_visitedRows.Initialize(true);
  420. } else
  421. {
  422. // New song
  423. InitializeGlobals();
  424. m_visitedRows.Initialize(true);
  425. m_dwCreatedWithVersion = Version::Current();
  426. }
  427. // Adjust channels
  428. const auto muteFlag = GetChannelMuteFlag();
  429. for(CHANNELINDEX chn = 0; chn < MAX_BASECHANNELS; chn++)
  430. {
  431. LimitMax(ChnSettings[chn].nVolume, uint16(64));
  432. if(ChnSettings[chn].nPan > 256)
  433. ChnSettings[chn].nPan = 128;
  434. if(ChnSettings[chn].nMixPlugin > MAX_MIXPLUGINS)
  435. ChnSettings[chn].nMixPlugin = 0;
  436. m_PlayState.Chn[chn].Reset(ModChannel::resetTotal, *this, chn, muteFlag);
  437. }
  438. // Checking samples, load external samples
  439. for(SAMPLEINDEX nSmp = 1; nSmp <= m_nSamples; nSmp++)
  440. {
  441. ModSample &sample = Samples[nSmp];
  442. #ifdef MPT_EXTERNAL_SAMPLES
  443. if(SampleHasPath(nSmp))
  444. {
  445. mpt::PathString filename = GetSamplePath(nSmp);
  446. if(file.GetOptionalFileName())
  447. {
  448. filename = filename.RelativePathToAbsolute(file.GetOptionalFileName()->GetPath());
  449. } else if(GetpModDoc() != nullptr)
  450. {
  451. filename = filename.RelativePathToAbsolute(GetpModDoc()->GetPathNameMpt().GetPath());
  452. }
  453. filename = filename.Simplify();
  454. if(!LoadExternalSample(nSmp, filename))
  455. {
  456. #ifndef MODPLUG_TRACKER
  457. // OpenMPT has its own way of reporting this error in CModDoc.
  458. AddToLog(LogError, MPT_UFORMAT("Unable to load sample {}: {}")(i, filename.ToUnicode()));
  459. #endif // MODPLUG_TRACKER
  460. }
  461. } else
  462. {
  463. sample.uFlags.reset(SMP_KEEPONDISK);
  464. }
  465. #endif // MPT_EXTERNAL_SAMPLES
  466. if(sample.HasSampleData())
  467. {
  468. sample.PrecomputeLoops(*this, false);
  469. } else if(!sample.uFlags[SMP_KEEPONDISK])
  470. {
  471. sample.nLength = 0;
  472. sample.nLoopStart = 0;
  473. sample.nLoopEnd = 0;
  474. sample.nSustainStart = 0;
  475. sample.nSustainEnd = 0;
  476. sample.uFlags.reset(CHN_LOOP | CHN_PINGPONGLOOP | CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN);
  477. }
  478. if(sample.nGlobalVol > 64) sample.nGlobalVol = 64;
  479. if(sample.uFlags[CHN_ADLIB] && m_opl == nullptr) InitOPL();
  480. }
  481. // Check invalid instruments
  482. INSTRUMENTINDEX maxInstr = 0;
  483. for(INSTRUMENTINDEX i = 0; i <= m_nInstruments; i++)
  484. {
  485. if(Instruments[i] != nullptr)
  486. {
  487. maxInstr = i;
  488. Instruments[i]->Sanitize(GetType());
  489. }
  490. }
  491. m_nInstruments = maxInstr;
  492. // Set default play state values
  493. if(!m_nDefaultTempo.GetInt())
  494. m_nDefaultTempo.Set(125);
  495. else
  496. LimitMax(m_nDefaultTempo, TEMPO(uint16_max, 0));
  497. if(!m_nDefaultSpeed)
  498. m_nDefaultSpeed = 6;
  499. if(m_nDefaultRowsPerMeasure < m_nDefaultRowsPerBeat)
  500. m_nDefaultRowsPerMeasure = m_nDefaultRowsPerBeat;
  501. LimitMax(m_nDefaultRowsPerBeat, MAX_ROWS_PER_BEAT);
  502. LimitMax(m_nDefaultRowsPerMeasure, MAX_ROWS_PER_BEAT);
  503. LimitMax(m_nDefaultGlobalVolume, MAX_GLOBAL_VOLUME);
  504. if(!m_tempoSwing.empty())
  505. m_tempoSwing.resize(m_nDefaultRowsPerBeat);
  506. m_PlayState.m_nMusicSpeed = m_nDefaultSpeed;
  507. m_PlayState.m_nMusicTempo = m_nDefaultTempo;
  508. m_PlayState.m_nCurrentRowsPerBeat = m_nDefaultRowsPerBeat;
  509. m_PlayState.m_nCurrentRowsPerMeasure = m_nDefaultRowsPerMeasure;
  510. m_PlayState.m_nGlobalVolume = static_cast<int32>(m_nDefaultGlobalVolume);
  511. m_PlayState.ResetGlobalVolumeRamping();
  512. m_PlayState.m_nNextOrder = 0;
  513. m_PlayState.m_nCurrentOrder = 0;
  514. m_PlayState.m_nPattern = 0;
  515. m_PlayState.m_nBufferCount = 0;
  516. m_PlayState.m_dBufferDiff = 0;
  517. m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
  518. m_PlayState.m_nNextRow = 0;
  519. m_PlayState.m_nRow = 0;
  520. m_PlayState.m_nPatternDelay = 0;
  521. m_PlayState.m_nFrameDelay = 0;
  522. m_PlayState.m_nextPatStartRow = 0;
  523. m_PlayState.m_nSeqOverride = ORDERINDEX_INVALID;
  524. if(UseFinetuneAndTranspose())
  525. m_playBehaviour.reset(kPeriodsAreHertz);
  526. m_nMaxOrderPosition = 0;
  527. RecalculateSamplesPerTick();
  528. for(auto &order : Order)
  529. {
  530. order.Shrink();
  531. if(order.GetRestartPos() >= order.size())
  532. {
  533. order.SetRestartPos(0);
  534. }
  535. }
  536. if(GetType() == MOD_TYPE_NONE)
  537. {
  538. return false;
  539. }
  540. SetModSpecsPointer(m_pModSpecs, GetBestSaveFormat());
  541. // When reading a file made with an older version of MPT, it might be necessary to upgrade some settings automatically.
  542. if(m_dwLastSavedWithVersion)
  543. {
  544. UpgradeModule();
  545. }
  546. #ifndef NO_PLUGINS
  547. // Load plugins
  548. #ifdef MODPLUG_TRACKER
  549. mpt::ustring notFoundText;
  550. #endif // MODPLUG_TRACKER
  551. std::vector<const SNDMIXPLUGININFO *> notFoundIDs;
  552. if((loadFlags & (loadPluginData | loadPluginInstance)) == (loadPluginData | loadPluginInstance))
  553. {
  554. for(PLUGINDEX plug = 0; plug < MAX_MIXPLUGINS; plug++)
  555. {
  556. auto &plugin = m_MixPlugins[plug];
  557. if(plugin.IsValidPlugin())
  558. {
  559. #ifdef MODPLUG_TRACKER
  560. // Provide some visual feedback
  561. {
  562. mpt::ustring s = MPT_UFORMAT("Loading Plugin FX{}: {} ({})")(
  563. mpt::ufmt::dec0<2>(plug + 1),
  564. mpt::ToUnicode(mpt::Charset::UTF8, plugin.Info.szLibraryName),
  565. mpt::ToUnicode(mpt::Charset::Locale, plugin.Info.szName));
  566. CMainFrame::GetMainFrame()->SetHelpText(mpt::ToCString(s));
  567. }
  568. #endif // MODPLUG_TRACKER
  569. CreateMixPluginProc(plugin, *this);
  570. if(plugin.pMixPlugin)
  571. {
  572. // Plugin was found
  573. plugin.pMixPlugin->RestoreAllParameters(plugin.defaultProgram);
  574. } else
  575. {
  576. // Plugin not found - add to list
  577. bool found = std::find_if(notFoundIDs.cbegin(), notFoundIDs.cend(),
  578. [&plugin](const SNDMIXPLUGININFO *info) { return info->dwPluginId2 == plugin.Info.dwPluginId2 && info->dwPluginId1 == plugin.Info.dwPluginId1; }) != notFoundIDs.cend();
  579. if(!found)
  580. {
  581. notFoundIDs.push_back(&plugin.Info);
  582. #ifdef MODPLUG_TRACKER
  583. notFoundText.append(plugin.GetLibraryName());
  584. notFoundText.append(UL_("\n"));
  585. #else
  586. AddToLog(LogWarning, U_("Plugin not found: ") + plugin.GetLibraryName());
  587. #endif // MODPLUG_TRACKER
  588. }
  589. }
  590. }
  591. }
  592. }
  593. // Set up mix levels (also recalculates plugin mix levels - must be done after plugins were loaded)
  594. SetMixLevels(m_nMixLevels);
  595. #ifdef MODPLUG_TRACKER
  596. // Display a nice message so the user sees which plugins are missing
  597. // TODO: Use IDD_MODLOADING_WARNINGS dialog (NON-MODAL!) to display all warnings that are encountered when loading a module.
  598. if(!notFoundIDs.empty())
  599. {
  600. if(notFoundIDs.size() == 1)
  601. {
  602. notFoundText = UL_("The following plugin has not been found:\n\n") + notFoundText + UL_("\nDo you want to search for it online?");
  603. } else
  604. {
  605. notFoundText = UL_("The following plugins have not been found:\n\n") + notFoundText + UL_("\nDo you want to search for them online?");
  606. }
  607. if(Reporting::Confirm(notFoundText, U_("OpenMPT - Plugins missing"), false, true) == cnfYes)
  608. {
  609. mpt::ustring url = U_("https://resources.openmpt.org/plugins/search.php?p=");
  610. for(const auto &id : notFoundIDs)
  611. {
  612. url += mpt::ufmt::HEX0<8>(id->dwPluginId2.get());
  613. url += mpt::ToUnicode(mpt::Charset::UTF8, id->szLibraryName);
  614. url += UL_("%0a");
  615. }
  616. CTrackApp::OpenURL(mpt::PathString::FromUnicode(url));
  617. }
  618. }
  619. #endif // MODPLUG_TRACKER
  620. #endif // NO_PLUGINS
  621. return true;
  622. }
  623. bool CSoundFile::Destroy()
  624. {
  625. for(auto &chn : m_PlayState.Chn)
  626. {
  627. chn.pModInstrument = nullptr;
  628. chn.pModSample = nullptr;
  629. chn.pCurrentSample = nullptr;
  630. chn.nLength = 0;
  631. }
  632. Patterns.DestroyPatterns();
  633. m_songName.clear();
  634. m_songArtist.clear();
  635. m_songMessage.clear();
  636. m_FileHistory.clear();
  637. #ifdef MPT_EXTERNAL_SAMPLES
  638. m_samplePaths.clear();
  639. #endif // MPT_EXTERNAL_SAMPLES
  640. for(auto &smp : Samples)
  641. {
  642. smp.FreeSample();
  643. }
  644. for(auto &ins : Instruments)
  645. {
  646. delete ins;
  647. ins = nullptr;
  648. }
  649. #ifndef NO_PLUGINS
  650. for(auto &plug : m_MixPlugins)
  651. {
  652. plug.Destroy();
  653. }
  654. #endif // NO_PLUGINS
  655. m_nType = MOD_TYPE_NONE;
  656. m_ContainerType = MOD_CONTAINERTYPE_NONE;
  657. m_nChannels = m_nSamples = m_nInstruments = 0;
  658. return true;
  659. }
  660. //////////////////////////////////////////////////////////////////////////
  661. // Misc functions
  662. void CSoundFile::SetDspEffects(uint32 DSPMask)
  663. {
  664. m_MixerSettings.DSPMask = DSPMask;
  665. InitPlayer(false);
  666. }
  667. void CSoundFile::SetPreAmp(uint32 nVol)
  668. {
  669. if (nVol < 1) nVol = 1;
  670. if (nVol > 0x200) nVol = 0x200; // x4 maximum
  671. #ifndef NO_AGC
  672. if ((nVol < m_MixerSettings.m_nPreAmp) && (nVol) && (m_MixerSettings.DSPMask & SNDDSP_AGC))
  673. {
  674. m_AGC.Adjust(m_MixerSettings.m_nPreAmp, nVol);
  675. }
  676. #endif
  677. m_MixerSettings.m_nPreAmp = nVol;
  678. }
  679. double CSoundFile::GetCurrentBPM() const
  680. {
  681. double bpm;
  682. if (m_nTempoMode == TempoMode::Modern)
  683. {
  684. // With modern mode, we trust that true bpm is close enough to what user chose.
  685. // This avoids oscillation due to tick-to-tick corrections.
  686. bpm = m_PlayState.m_nMusicTempo.ToDouble();
  687. } else
  688. {
  689. //with other modes, we calculate it:
  690. double ticksPerBeat = m_PlayState.m_nMusicSpeed * m_PlayState.m_nCurrentRowsPerBeat; //ticks/beat = ticks/row * rows/beat
  691. double samplesPerBeat = m_PlayState.m_nSamplesPerTick * ticksPerBeat; //samps/beat = samps/tick * ticks/beat
  692. bpm = m_MixerSettings.gdwMixingFreq / samplesPerBeat * 60; //beats/sec = samps/sec / samps/beat
  693. } //beats/min = beats/sec * 60
  694. return bpm;
  695. }
  696. void CSoundFile::ResetPlayPos()
  697. {
  698. const auto muteFlag = GetChannelMuteFlag();
  699. for(CHANNELINDEX i = 0; i < MAX_CHANNELS; i++)
  700. m_PlayState.Chn[i].Reset(ModChannel::resetSetPosFull, *this, i, muteFlag);
  701. m_visitedRows.Initialize(true);
  702. m_SongFlags.reset(SONG_FADINGSONG | SONG_ENDREACHED);
  703. m_PlayState.m_nGlobalVolume = m_nDefaultGlobalVolume;
  704. m_PlayState.m_nMusicSpeed = m_nDefaultSpeed;
  705. m_PlayState.m_nMusicTempo = m_nDefaultTempo;
  706. // Do not ramp global volume when starting playback
  707. m_PlayState.ResetGlobalVolumeRamping();
  708. m_PlayState.m_nNextOrder = 0;
  709. m_PlayState.m_nNextRow = 0;
  710. m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
  711. m_PlayState.m_nBufferCount = 0;
  712. m_PlayState.m_nPatternDelay = 0;
  713. m_PlayState.m_nFrameDelay = 0;
  714. m_PlayState.m_nextPatStartRow = 0;
  715. m_PlayState.m_lTotalSampleCount = 0;
  716. }
  717. void CSoundFile::SetCurrentOrder(ORDERINDEX nOrder)
  718. {
  719. while(nOrder < Order().size() && !Order().IsValidPat(nOrder))
  720. nOrder++;
  721. if(nOrder >= Order().size())
  722. return;
  723. for(auto &chn : m_PlayState.Chn)
  724. {
  725. chn.nPeriod = 0;
  726. chn.nNote = NOTE_NONE;
  727. chn.nPortamentoDest = 0;
  728. chn.nCommand = 0;
  729. chn.nPatternLoopCount = 0;
  730. chn.nPatternLoop = 0;
  731. chn.nVibratoPos = chn.nTremoloPos = chn.nPanbrelloPos = 0;
  732. //IT compatibility 15. Retrigger
  733. if(m_playBehaviour[kITRetrigger])
  734. {
  735. chn.nRetrigCount = 0;
  736. chn.nRetrigParam = 1;
  737. }
  738. chn.nTremorCount = 0;
  739. }
  740. #ifndef NO_PLUGINS
  741. // Stop hanging notes from VST instruments as well
  742. StopAllVsti();
  743. #endif // NO_PLUGINS
  744. if (!nOrder)
  745. {
  746. ResetPlayPos();
  747. } else
  748. {
  749. m_PlayState.m_nNextOrder = nOrder;
  750. m_PlayState.m_nRow = m_PlayState.m_nNextRow = 0;
  751. m_PlayState.m_nPattern = 0;
  752. m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
  753. m_PlayState.m_nBufferCount = 0;
  754. m_PlayState.m_nPatternDelay = 0;
  755. m_PlayState.m_nFrameDelay = 0;
  756. m_PlayState.m_nextPatStartRow = 0;
  757. }
  758. m_SongFlags.reset(SONG_FADINGSONG | SONG_ENDREACHED);
  759. }
  760. void CSoundFile::SuspendPlugins()
  761. {
  762. #ifndef NO_PLUGINS
  763. for(auto &plug : m_MixPlugins)
  764. {
  765. IMixPlugin *pPlugin = plug.pMixPlugin;
  766. if(pPlugin != nullptr && pPlugin->IsResumed())
  767. {
  768. pPlugin->NotifySongPlaying(false);
  769. pPlugin->HardAllNotesOff();
  770. pPlugin->Suspend();
  771. }
  772. }
  773. #endif // NO_PLUGINS
  774. }
  775. void CSoundFile::ResumePlugins()
  776. {
  777. #ifndef NO_PLUGINS
  778. for(auto &plugin : m_MixPlugins)
  779. {
  780. IMixPlugin *pPlugin = plugin.pMixPlugin;
  781. if(pPlugin != nullptr && !pPlugin->IsResumed())
  782. {
  783. pPlugin->NotifySongPlaying(true);
  784. pPlugin->Resume();
  785. }
  786. }
  787. #endif // NO_PLUGINS
  788. }
  789. void CSoundFile::StopAllVsti()
  790. {
  791. #ifndef NO_PLUGINS
  792. for(auto &plugin : m_MixPlugins)
  793. {
  794. IMixPlugin *pPlugin = plugin.pMixPlugin;
  795. if(pPlugin != nullptr && pPlugin->IsResumed())
  796. {
  797. pPlugin->HardAllNotesOff();
  798. }
  799. }
  800. #endif // NO_PLUGINS
  801. }
  802. void CSoundFile::SetMixLevels(MixLevels levels)
  803. {
  804. m_nMixLevels = levels;
  805. m_PlayConfig.SetMixLevels(m_nMixLevels);
  806. RecalculateGainForAllPlugs();
  807. }
  808. void CSoundFile::RecalculateGainForAllPlugs()
  809. {
  810. #ifndef NO_PLUGINS
  811. for(auto &plugin : m_MixPlugins)
  812. {
  813. if(plugin.pMixPlugin != nullptr)
  814. plugin.pMixPlugin->RecalculateGain();
  815. }
  816. #endif // NO_PLUGINS
  817. }
  818. void CSoundFile::ResetChannels()
  819. {
  820. m_SongFlags.reset(SONG_FADINGSONG | SONG_ENDREACHED);
  821. m_PlayState.m_nBufferCount = 0;
  822. for(auto &chn : m_PlayState.Chn)
  823. {
  824. chn.nROfs = chn.nLOfs = 0;
  825. chn.nLength = 0;
  826. if(chn.dwFlags[CHN_ADLIB] && m_opl)
  827. {
  828. CHANNELINDEX c = static_cast<CHANNELINDEX>(std::distance(std::begin(m_PlayState.Chn), &chn));
  829. m_opl->NoteCut(c);
  830. }
  831. }
  832. }
  833. #ifdef MODPLUG_TRACKER
  834. void CSoundFile::PatternTranstionChnSolo(const CHANNELINDEX chnIndex)
  835. {
  836. if(chnIndex >= m_nChannels)
  837. return;
  838. for(CHANNELINDEX i = 0; i < m_nChannels; i++)
  839. {
  840. m_bChannelMuteTogglePending[i] = !ChnSettings[i].dwFlags[CHN_MUTE];
  841. }
  842. m_bChannelMuteTogglePending[chnIndex] = ChnSettings[chnIndex].dwFlags[CHN_MUTE];
  843. }
  844. void CSoundFile::PatternTransitionChnUnmuteAll()
  845. {
  846. for(CHANNELINDEX i = 0; i < m_nChannels; i++)
  847. {
  848. m_bChannelMuteTogglePending[i] = ChnSettings[i].dwFlags[CHN_MUTE];
  849. }
  850. }
  851. #endif // MODPLUG_TRACKER
  852. void CSoundFile::LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow)
  853. {
  854. if(!Patterns.IsValidPat(nPat))
  855. {
  856. m_SongFlags.reset(SONG_PATTERNLOOP);
  857. } else
  858. {
  859. if(nRow >= Patterns[nPat].GetNumRows()) nRow = 0;
  860. m_PlayState.m_nPattern = nPat;
  861. m_PlayState.m_nRow = m_PlayState.m_nNextRow = nRow;
  862. m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
  863. m_PlayState.m_nPatternDelay = 0;
  864. m_PlayState.m_nFrameDelay = 0;
  865. m_PlayState.m_nextPatStartRow = 0;
  866. m_SongFlags.set(SONG_PATTERNLOOP);
  867. }
  868. m_PlayState.m_nBufferCount = 0;
  869. }
  870. void CSoundFile::DontLoopPattern(PATTERNINDEX nPat, ROWINDEX nRow)
  871. {
  872. if(!Patterns.IsValidPat(nPat)) nPat = 0;
  873. if(nRow >= Patterns[nPat].GetNumRows()) nRow = 0;
  874. m_PlayState.m_nPattern = nPat;
  875. m_PlayState.m_nRow = m_PlayState.m_nNextRow = nRow;
  876. m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
  877. m_PlayState.m_nPatternDelay = 0;
  878. m_PlayState.m_nFrameDelay = 0;
  879. m_PlayState.m_nBufferCount = 0;
  880. m_PlayState.m_nextPatStartRow = 0;
  881. m_SongFlags.reset(SONG_PATTERNLOOP);
  882. }
  883. void CSoundFile::SetDefaultPlaybackBehaviour(MODTYPE type)
  884. {
  885. m_playBehaviour = GetDefaultPlaybackBehaviour(type);
  886. }
  887. PlayBehaviourSet CSoundFile::GetSupportedPlaybackBehaviour(MODTYPE type)
  888. {
  889. PlayBehaviourSet playBehaviour;
  890. switch(type)
  891. {
  892. case MOD_TYPE_MPT:
  893. case MOD_TYPE_IT:
  894. playBehaviour.set(MSF_COMPATIBLE_PLAY);
  895. playBehaviour.set(kPeriodsAreHertz);
  896. playBehaviour.set(kTempoClamp);
  897. playBehaviour.set(kPerChannelGlobalVolSlide);
  898. playBehaviour.set(kPanOverride);
  899. playBehaviour.set(kITInstrWithoutNote);
  900. playBehaviour.set(kITVolColFinePortamento);
  901. playBehaviour.set(kITArpeggio);
  902. playBehaviour.set(kITOutOfRangeDelay);
  903. playBehaviour.set(kITPortaMemoryShare);
  904. playBehaviour.set(kITPatternLoopTargetReset);
  905. playBehaviour.set(kITFT2PatternLoop);
  906. playBehaviour.set(kITPingPongNoReset);
  907. playBehaviour.set(kITEnvelopeReset);
  908. playBehaviour.set(kITClearOldNoteAfterCut);
  909. playBehaviour.set(kITVibratoTremoloPanbrello);
  910. playBehaviour.set(kITTremor);
  911. playBehaviour.set(kITRetrigger);
  912. playBehaviour.set(kITMultiSampleBehaviour);
  913. playBehaviour.set(kITPortaTargetReached);
  914. playBehaviour.set(kITPatternLoopBreak);
  915. playBehaviour.set(kITOffset);
  916. playBehaviour.set(kITSwingBehaviour);
  917. playBehaviour.set(kITNNAReset);
  918. playBehaviour.set(kITSCxStopsSample);
  919. playBehaviour.set(kITEnvelopePositionHandling);
  920. playBehaviour.set(kITPortamentoInstrument);
  921. playBehaviour.set(kITPingPongMode);
  922. playBehaviour.set(kITRealNoteMapping);
  923. playBehaviour.set(kITHighOffsetNoRetrig);
  924. playBehaviour.set(kITFilterBehaviour);
  925. playBehaviour.set(kITNoSurroundPan);
  926. playBehaviour.set(kITShortSampleRetrig);
  927. playBehaviour.set(kITPortaNoNote);
  928. playBehaviour.set(kITFT2DontResetNoteOffOnPorta);
  929. playBehaviour.set(kITVolColMemory);
  930. playBehaviour.set(kITPortamentoSwapResetsPos);
  931. playBehaviour.set(kITEmptyNoteMapSlot);
  932. playBehaviour.set(kITFirstTickHandling);
  933. playBehaviour.set(kITSampleAndHoldPanbrello);
  934. playBehaviour.set(kITClearPortaTarget);
  935. playBehaviour.set(kITPanbrelloHold);
  936. playBehaviour.set(kITPanningReset);
  937. playBehaviour.set(kITPatternLoopWithJumps);
  938. playBehaviour.set(kITInstrWithNoteOff);
  939. playBehaviour.set(kITMultiSampleInstrumentNumber);
  940. playBehaviour.set(kRowDelayWithNoteDelay);
  941. playBehaviour.set(kITInstrWithNoteOffOldEffects);
  942. playBehaviour.set(kITDoNotOverrideChannelPan);
  943. playBehaviour.set(kITDCTBehaviour);
  944. playBehaviour.set(kITPitchPanSeparation);
  945. if(type == MOD_TYPE_MPT)
  946. {
  947. playBehaviour.set(kOPLFlexibleNoteOff);
  948. playBehaviour.set(kOPLwithNNA);
  949. playBehaviour.set(kOPLNoteOffOnNoteChange);
  950. }
  951. break;
  952. case MOD_TYPE_XM:
  953. playBehaviour.set(MSF_COMPATIBLE_PLAY);
  954. playBehaviour.set(kFT2VolumeRamping);
  955. playBehaviour.set(kTempoClamp);
  956. playBehaviour.set(kPerChannelGlobalVolSlide);
  957. playBehaviour.set(kPanOverride);
  958. playBehaviour.set(kITFT2PatternLoop);
  959. playBehaviour.set(kITFT2DontResetNoteOffOnPorta);
  960. playBehaviour.set(kFT2Arpeggio);
  961. playBehaviour.set(kFT2Retrigger);
  962. playBehaviour.set(kFT2VolColVibrato);
  963. playBehaviour.set(kFT2PortaNoNote);
  964. playBehaviour.set(kFT2KeyOff);
  965. playBehaviour.set(kFT2PanSlide);
  966. playBehaviour.set(kFT2ST3OffsetOutOfRange);
  967. playBehaviour.set(kFT2RestrictXCommand);
  968. playBehaviour.set(kFT2RetrigWithNoteDelay);
  969. playBehaviour.set(kFT2SetPanEnvPos);
  970. playBehaviour.set(kFT2PortaIgnoreInstr);
  971. playBehaviour.set(kFT2VolColMemory);
  972. playBehaviour.set(kFT2LoopE60Restart);
  973. playBehaviour.set(kFT2ProcessSilentChannels);
  974. playBehaviour.set(kFT2ReloadSampleSettings);
  975. playBehaviour.set(kFT2PortaDelay);
  976. playBehaviour.set(kFT2Transpose);
  977. playBehaviour.set(kFT2PatternLoopWithJumps);
  978. playBehaviour.set(kFT2PortaTargetNoReset);
  979. playBehaviour.set(kFT2EnvelopeEscape);
  980. playBehaviour.set(kFT2Tremor);
  981. playBehaviour.set(kFT2OutOfRangeDelay);
  982. playBehaviour.set(kFT2Periods);
  983. playBehaviour.set(kFT2PanWithDelayedNoteOff);
  984. playBehaviour.set(kFT2VolColDelay);
  985. playBehaviour.set(kFT2FinetunePrecision);
  986. playBehaviour.set(kFT2NoteOffFlags);
  987. playBehaviour.set(kRowDelayWithNoteDelay);
  988. playBehaviour.set(kFT2MODTremoloRampWaveform);
  989. playBehaviour.set(kFT2PortaUpDownMemory);
  990. playBehaviour.set(kFT2PanSustainRelease);
  991. playBehaviour.set(kFT2NoteDelayWithoutInstr);
  992. playBehaviour.set(kFT2PortaResetDirection);
  993. break;
  994. case MOD_TYPE_S3M:
  995. playBehaviour.set(MSF_COMPATIBLE_PLAY);
  996. playBehaviour.set(kTempoClamp);
  997. playBehaviour.set(kPanOverride);
  998. playBehaviour.set(kITPanbrelloHold);
  999. playBehaviour.set(kFT2ST3OffsetOutOfRange);
  1000. playBehaviour.set(kST3NoMutedChannels);
  1001. playBehaviour.set(kST3PortaSampleChange);
  1002. playBehaviour.set(kST3EffectMemory);
  1003. playBehaviour.set(kST3VibratoMemory);
  1004. playBehaviour.set(KST3PortaAfterArpeggio);
  1005. playBehaviour.set(kRowDelayWithNoteDelay);
  1006. playBehaviour.set(kST3OffsetWithoutInstrument);
  1007. playBehaviour.set(kST3RetrigAfterNoteCut);
  1008. playBehaviour.set(kST3SampleSwap);
  1009. playBehaviour.set(kOPLNoteOffOnNoteChange);
  1010. playBehaviour.set(kApplyUpperPeriodLimit);
  1011. break;
  1012. case MOD_TYPE_MOD:
  1013. playBehaviour.set(kMODVBlankTiming);
  1014. playBehaviour.set(kMODOneShotLoops);
  1015. playBehaviour.set(kMODIgnorePanning);
  1016. playBehaviour.set(kMODSampleSwap);
  1017. playBehaviour.set(kMODOutOfRangeNoteDelay);
  1018. playBehaviour.set(kMODTempoOnSecondTick);
  1019. playBehaviour.set(kRowDelayWithNoteDelay);
  1020. playBehaviour.set(kFT2MODTremoloRampWaveform);
  1021. break;
  1022. default:
  1023. playBehaviour.set(MSF_COMPATIBLE_PLAY);
  1024. playBehaviour.set(kPeriodsAreHertz);
  1025. playBehaviour.set(kTempoClamp);
  1026. playBehaviour.set(kPanOverride);
  1027. break;
  1028. }
  1029. return playBehaviour;
  1030. }
  1031. PlayBehaviourSet CSoundFile::GetDefaultPlaybackBehaviour(MODTYPE type)
  1032. {
  1033. PlayBehaviourSet playBehaviour;
  1034. switch(type)
  1035. {
  1036. case MOD_TYPE_MPT:
  1037. playBehaviour.set(kPeriodsAreHertz);
  1038. playBehaviour.set(kPerChannelGlobalVolSlide);
  1039. playBehaviour.set(kPanOverride);
  1040. playBehaviour.set(kITArpeggio);
  1041. playBehaviour.set(kITPortaMemoryShare);
  1042. playBehaviour.set(kITPatternLoopTargetReset);
  1043. playBehaviour.set(kITFT2PatternLoop);
  1044. playBehaviour.set(kITPingPongNoReset);
  1045. playBehaviour.set(kITClearOldNoteAfterCut);
  1046. playBehaviour.set(kITVibratoTremoloPanbrello);
  1047. playBehaviour.set(kITMultiSampleBehaviour);
  1048. playBehaviour.set(kITPortaTargetReached);
  1049. playBehaviour.set(kITPatternLoopBreak);
  1050. playBehaviour.set(kITSwingBehaviour);
  1051. playBehaviour.set(kITSCxStopsSample);
  1052. playBehaviour.set(kITEnvelopePositionHandling);
  1053. playBehaviour.set(kITPingPongMode);
  1054. playBehaviour.set(kITRealNoteMapping);
  1055. playBehaviour.set(kITPortaNoNote);
  1056. playBehaviour.set(kITVolColMemory);
  1057. playBehaviour.set(kITFirstTickHandling);
  1058. playBehaviour.set(kITClearPortaTarget);
  1059. playBehaviour.set(kITSampleAndHoldPanbrello);
  1060. playBehaviour.set(kITPanbrelloHold);
  1061. playBehaviour.set(kITPanningReset);
  1062. playBehaviour.set(kITInstrWithNoteOff);
  1063. playBehaviour.set(kOPLFlexibleNoteOff);
  1064. playBehaviour.set(kITDoNotOverrideChannelPan);
  1065. playBehaviour.set(kITDCTBehaviour);
  1066. playBehaviour.set(kOPLwithNNA);
  1067. playBehaviour.set(kITPitchPanSeparation);
  1068. break;
  1069. case MOD_TYPE_S3M:
  1070. playBehaviour = GetSupportedPlaybackBehaviour(type);
  1071. // Default behaviour was chosen to follow GUS, so kST3PortaSampleChange is enabled and kST3SampleSwap is disabled.
  1072. // For SoundBlaster behaviour, those two flags would need to be swapped.
  1073. playBehaviour.reset(kST3SampleSwap);
  1074. break;
  1075. case MOD_TYPE_XM:
  1076. playBehaviour = GetSupportedPlaybackBehaviour(type);
  1077. // Only set this explicitely for FT2-made XMs.
  1078. playBehaviour.reset(kFT2VolumeRamping);
  1079. break;
  1080. case MOD_TYPE_MOD:
  1081. playBehaviour.set(kRowDelayWithNoteDelay);
  1082. break;
  1083. default:
  1084. playBehaviour = GetSupportedPlaybackBehaviour(type);
  1085. break;
  1086. }
  1087. return playBehaviour;
  1088. }
  1089. MODTYPE CSoundFile::GetBestSaveFormat() const
  1090. {
  1091. switch(GetType())
  1092. {
  1093. case MOD_TYPE_MOD:
  1094. case MOD_TYPE_S3M:
  1095. case MOD_TYPE_XM:
  1096. case MOD_TYPE_IT:
  1097. case MOD_TYPE_MPT:
  1098. return GetType();
  1099. case MOD_TYPE_AMF0:
  1100. case MOD_TYPE_DIGI:
  1101. case MOD_TYPE_SFX:
  1102. case MOD_TYPE_STP:
  1103. return MOD_TYPE_MOD;
  1104. case MOD_TYPE_MED:
  1105. if(!m_nInstruments)
  1106. {
  1107. for(const auto &pat : Patterns)
  1108. {
  1109. if(pat.IsValid() && pat.GetNumRows() != 64)
  1110. return MOD_TYPE_XM;
  1111. }
  1112. return MOD_TYPE_MOD;
  1113. }
  1114. return MOD_TYPE_XM;
  1115. case MOD_TYPE_PSM:
  1116. if(GetNumChannels() > 16)
  1117. return MOD_TYPE_IT;
  1118. for(CHANNELINDEX i = 0; i < GetNumChannels(); i++)
  1119. {
  1120. if(ChnSettings[i].dwFlags[CHN_SURROUND] || ChnSettings[i].nVolume != 64)
  1121. {
  1122. return MOD_TYPE_IT;
  1123. break;
  1124. }
  1125. }
  1126. return MOD_TYPE_S3M;
  1127. case MOD_TYPE_669:
  1128. case MOD_TYPE_FAR:
  1129. case MOD_TYPE_STM:
  1130. case MOD_TYPE_DSM:
  1131. case MOD_TYPE_AMF:
  1132. case MOD_TYPE_MTM:
  1133. return MOD_TYPE_S3M;
  1134. case MOD_TYPE_AMS:
  1135. case MOD_TYPE_DMF:
  1136. case MOD_TYPE_DBM:
  1137. case MOD_TYPE_IMF:
  1138. case MOD_TYPE_J2B:
  1139. case MOD_TYPE_ULT:
  1140. case MOD_TYPE_OKT:
  1141. case MOD_TYPE_MT2:
  1142. case MOD_TYPE_MDL:
  1143. case MOD_TYPE_PTM:
  1144. case MOD_TYPE_DTM:
  1145. default:
  1146. return MOD_TYPE_IT;
  1147. case MOD_TYPE_MID:
  1148. return MOD_TYPE_MPT;
  1149. }
  1150. }
  1151. const char *CSoundFile::GetSampleName(SAMPLEINDEX nSample) const
  1152. {
  1153. MPT_ASSERT(nSample <= GetNumSamples());
  1154. if (nSample < MAX_SAMPLES)
  1155. {
  1156. return m_szNames[nSample].buf;
  1157. } else
  1158. {
  1159. return "";
  1160. }
  1161. }
  1162. const char *CSoundFile::GetInstrumentName(INSTRUMENTINDEX nInstr) const
  1163. {
  1164. if((nInstr >= MAX_INSTRUMENTS) || (!Instruments[nInstr]))
  1165. return "";
  1166. MPT_ASSERT(nInstr <= GetNumInstruments());
  1167. return Instruments[nInstr]->name.buf;
  1168. }
  1169. bool CSoundFile::InitChannel(CHANNELINDEX nChn)
  1170. {
  1171. if(nChn >= MAX_BASECHANNELS)
  1172. return true;
  1173. ChnSettings[nChn].Reset();
  1174. m_PlayState.Chn[nChn].Reset(ModChannel::resetTotal, *this, nChn, GetChannelMuteFlag());
  1175. #ifdef MODPLUG_TRACKER
  1176. if(GetpModDoc() != nullptr)
  1177. {
  1178. GetpModDoc()->SetChannelRecordGroup(nChn, RecordGroup::NoGroup);
  1179. }
  1180. #endif // MODPLUG_TRACKER
  1181. #ifdef MODPLUG_TRACKER
  1182. m_bChannelMuteTogglePending[nChn] = false;
  1183. #endif // MODPLUG_TRACKER
  1184. return false;
  1185. }
  1186. void CSoundFile::InitAmigaResampler()
  1187. {
  1188. if(m_SongFlags[SONG_ISAMIGA] && m_Resampler.m_Settings.emulateAmiga != Resampling::AmigaFilter::Off)
  1189. {
  1190. const Paula::State defaultState(GetSampleRate());
  1191. for(auto &chn : m_PlayState.Chn)
  1192. {
  1193. chn.paulaState = defaultState;
  1194. }
  1195. }
  1196. }
  1197. void CSoundFile::InitOPL()
  1198. {
  1199. if(!m_opl)
  1200. m_opl = std::make_unique<OPL>(m_MixerSettings.gdwMixingFreq);
  1201. }
  1202. // Detect samples that are referenced by an instrument, but actually not used in a song.
  1203. // Only works in instrument mode. Unused samples are marked as false in the vector.
  1204. SAMPLEINDEX CSoundFile::DetectUnusedSamples(std::vector<bool> &sampleUsed) const
  1205. {
  1206. sampleUsed.assign(GetNumSamples() + 1, false);
  1207. if(GetNumInstruments() == 0)
  1208. {
  1209. return 0;
  1210. }
  1211. SAMPLEINDEX unused = 0;
  1212. std::vector<ModCommand::INSTR> lastIns;
  1213. for(const auto &pat : Patterns) if(pat.IsValid())
  1214. {
  1215. lastIns.assign(GetNumChannels(), 0);
  1216. auto p = pat.cbegin();
  1217. for(ROWINDEX row = 0; row < pat.GetNumRows(); row++)
  1218. {
  1219. for(CHANNELINDEX c = 0; c < GetNumChannels(); c++, p++)
  1220. {
  1221. if(p->IsNote())
  1222. {
  1223. ModCommand::INSTR instr = p->instr;
  1224. if(!p->instr)
  1225. instr = lastIns[c];
  1226. INSTRUMENTINDEX minInstr = 1, maxInstr = GetNumInstruments();
  1227. if(instr > 0)
  1228. {
  1229. if(instr <= GetNumInstruments())
  1230. {
  1231. minInstr = maxInstr = instr;
  1232. }
  1233. lastIns[c] = instr;
  1234. } else
  1235. {
  1236. // No idea which instrument this note belongs to, so mark it used in any instruments.
  1237. }
  1238. for(INSTRUMENTINDEX i = minInstr; i <= maxInstr; i++)
  1239. {
  1240. if(const auto *pIns = Instruments[i]; pIns != nullptr)
  1241. {
  1242. SAMPLEINDEX n = pIns->Keyboard[p->note - NOTE_MIN];
  1243. if(n <= GetNumSamples())
  1244. sampleUsed[n] = true;
  1245. }
  1246. }
  1247. }
  1248. }
  1249. }
  1250. }
  1251. for (SAMPLEINDEX ichk = GetNumSamples(); ichk >= 1; ichk--)
  1252. {
  1253. if ((!sampleUsed[ichk]) && (Samples[ichk].HasSampleData())) unused++;
  1254. }
  1255. return unused;
  1256. }
  1257. // Destroy samples where keepSamples index is false. First sample is keepSamples[1]!
  1258. SAMPLEINDEX CSoundFile::RemoveSelectedSamples(const std::vector<bool> &keepSamples)
  1259. {
  1260. if(keepSamples.empty())
  1261. {
  1262. return 0;
  1263. }
  1264. SAMPLEINDEX nRemoved = 0;
  1265. for(SAMPLEINDEX nSmp = std::min(GetNumSamples(), static_cast<SAMPLEINDEX>(keepSamples.size() - 1)); nSmp >= 1; nSmp--)
  1266. {
  1267. if(!keepSamples[nSmp])
  1268. {
  1269. CriticalSection cs;
  1270. #ifdef MODPLUG_TRACKER
  1271. if(GetpModDoc())
  1272. {
  1273. GetpModDoc()->GetSampleUndo().PrepareUndo(nSmp, sundo_replace, "Remove Sample");
  1274. }
  1275. #endif // MODPLUG_TRACKER
  1276. if(DestroySample(nSmp))
  1277. {
  1278. m_szNames[nSmp] = "";
  1279. nRemoved++;
  1280. }
  1281. if((nSmp == GetNumSamples()) && (nSmp > 1)) m_nSamples--;
  1282. }
  1283. }
  1284. return nRemoved;
  1285. }
  1286. bool CSoundFile::DestroySample(SAMPLEINDEX nSample)
  1287. {
  1288. if(!nSample || nSample >= MAX_SAMPLES)
  1289. {
  1290. return false;
  1291. }
  1292. if(!Samples[nSample].HasSampleData())
  1293. {
  1294. return true;
  1295. }
  1296. ModSample &sample = Samples[nSample];
  1297. for(auto &chn : m_PlayState.Chn)
  1298. {
  1299. if(chn.pModSample == &sample)
  1300. {
  1301. chn.position.Set(0);
  1302. chn.nLength = 0;
  1303. chn.pCurrentSample = nullptr;
  1304. }
  1305. }
  1306. sample.FreeSample();
  1307. sample.nLength = 0;
  1308. sample.uFlags.reset(CHN_16BIT | CHN_STEREO);
  1309. sample.SetAdlib(false);
  1310. #ifdef MODPLUG_TRACKER
  1311. ResetSamplePath(nSample);
  1312. #endif
  1313. return true;
  1314. }
  1315. bool CSoundFile::DestroySampleThreadsafe(SAMPLEINDEX nSample)
  1316. {
  1317. CriticalSection cs;
  1318. return DestroySample(nSample);
  1319. }
  1320. std::unique_ptr<CTuning> CSoundFile::CreateTuning12TET(const mpt::ustring &name)
  1321. {
  1322. std::unique_ptr<CTuning> pT = CTuning::CreateGeometric(name, 12, 2, 15);
  1323. for(ModCommand::NOTE note = 0; note < 12; ++note)
  1324. {
  1325. pT->SetNoteName(note, mpt::ustring(NoteNamesSharp[note]));
  1326. }
  1327. return pT;
  1328. }
  1329. mpt::ustring CSoundFile::GetNoteName(const ModCommand::NOTE note, const INSTRUMENTINDEX inst) const
  1330. {
  1331. // For MPTM instruments with custom tuning, find the appropriate note name. Else, use default note names.
  1332. if(ModCommand::IsNote(note) && GetType() == MOD_TYPE_MPT && inst >= 1 && inst <= GetNumInstruments() && Instruments[inst] && Instruments[inst]->pTuning)
  1333. {
  1334. return Instruments[inst]->pTuning->GetNoteName(note - NOTE_MIDDLEC);
  1335. } else
  1336. {
  1337. return GetNoteName(note);
  1338. }
  1339. }
  1340. mpt::ustring CSoundFile::GetNoteName(const ModCommand::NOTE note) const
  1341. {
  1342. return GetNoteName(note, m_NoteNames);
  1343. }
  1344. mpt::ustring CSoundFile::GetNoteName(const ModCommand::NOTE note, const NoteName *noteNames)
  1345. {
  1346. if(ModCommand::IsSpecialNote(note))
  1347. {
  1348. // cppcheck false-positive
  1349. // cppcheck-suppress constStatement
  1350. const mpt::uchar specialNoteNames[][4] = { UL_("PCs"), UL_("PC "), UL_("~~~"), UL_("^^^"), UL_("===") };
  1351. static_assert(mpt::array_size<decltype(specialNoteNames)>::size == NOTE_MAX_SPECIAL - NOTE_MIN_SPECIAL + 1);
  1352. return specialNoteNames[note - NOTE_MIN_SPECIAL];
  1353. } else if(ModCommand::IsNote(note))
  1354. {
  1355. return mpt::ustring()
  1356. .append(noteNames[(note - NOTE_MIN) % 12])
  1357. .append(1, UC_('0') + (note - NOTE_MIN) / 12)
  1358. ; // e.g. "C#" + "5"
  1359. } else if(note == NOTE_NONE)
  1360. {
  1361. return UL_("...");
  1362. }
  1363. return UL_("???");
  1364. }
  1365. #ifdef MODPLUG_TRACKER
  1366. void CSoundFile::SetDefaultNoteNames()
  1367. {
  1368. m_NoteNames = TrackerSettings::Instance().accidentalFlats ? NoteNamesFlat : NoteNamesSharp;
  1369. }
  1370. const NoteName *CSoundFile::GetDefaultNoteNames()
  1371. {
  1372. return m_NoteNames;
  1373. }
  1374. #endif // MODPLUG_TRACKER
  1375. void CSoundFile::SetModSpecsPointer(const CModSpecifications*& pModSpecs, const MODTYPE type)
  1376. {
  1377. switch(type)
  1378. {
  1379. case MOD_TYPE_MPT:
  1380. pModSpecs = &ModSpecs::mptm;
  1381. break;
  1382. case MOD_TYPE_IT:
  1383. pModSpecs = &ModSpecs::itEx;
  1384. break;
  1385. case MOD_TYPE_XM:
  1386. pModSpecs = &ModSpecs::xmEx;
  1387. break;
  1388. case MOD_TYPE_S3M:
  1389. pModSpecs = &ModSpecs::s3mEx;
  1390. break;
  1391. case MOD_TYPE_MOD:
  1392. default:
  1393. pModSpecs = &ModSpecs::mod;
  1394. break;
  1395. }
  1396. }
  1397. void CSoundFile::SetType(MODTYPE type)
  1398. {
  1399. m_nType = type;
  1400. m_playBehaviour = GetDefaultPlaybackBehaviour(GetBestSaveFormat());
  1401. SetModSpecsPointer(m_pModSpecs, GetBestSaveFormat());
  1402. }
  1403. #ifdef MODPLUG_TRACKER
  1404. void CSoundFile::ChangeModTypeTo(const MODTYPE newType, bool adjust)
  1405. {
  1406. const MODTYPE oldType = GetType();
  1407. m_nType = newType;
  1408. SetModSpecsPointer(m_pModSpecs, m_nType);
  1409. if(oldType == newType || !adjust)
  1410. return;
  1411. SetupMODPanning(); // Setup LRRL panning scheme if needed
  1412. // Only keep supported play behaviour flags
  1413. PlayBehaviourSet oldAllowedFlags = GetSupportedPlaybackBehaviour(oldType);
  1414. PlayBehaviourSet newAllowedFlags = GetSupportedPlaybackBehaviour(newType);
  1415. PlayBehaviourSet newDefaultFlags = GetDefaultPlaybackBehaviour(newType);
  1416. for(size_t i = 0; i < m_playBehaviour.size(); i++)
  1417. {
  1418. // If a flag is supported in both formats, keep its status
  1419. if(m_playBehaviour[i]) m_playBehaviour.set(i, newAllowedFlags[i]);
  1420. // Set allowed flags to their defaults if they were not supported in the old format
  1421. if(!oldAllowedFlags[i]) m_playBehaviour.set(i, newDefaultFlags[i]);
  1422. }
  1423. // Special case for OPL behaviour when converting from S3M to MPTM to retain S3M-like note-off behaviour
  1424. if(oldType == MOD_TYPE_S3M && newType == MOD_TYPE_MPT && m_opl)
  1425. m_playBehaviour.reset(kOPLFlexibleNoteOff);
  1426. Order.OnModTypeChanged(oldType);
  1427. Patterns.OnModTypeChanged(oldType);
  1428. m_modFormat.type = mpt::ToUnicode(mpt::Charset::UTF8, GetModSpecifications().fileExtension);
  1429. }
  1430. #endif // MODPLUG_TRACKER
  1431. ModMessageHeuristicOrder CSoundFile::GetMessageHeuristic() const
  1432. {
  1433. ModMessageHeuristicOrder result = ModMessageHeuristicOrder::Default;
  1434. switch(GetType())
  1435. {
  1436. case MOD_TYPE_MPT:
  1437. result = ModMessageHeuristicOrder::Samples;
  1438. break;
  1439. case MOD_TYPE_IT:
  1440. result = ModMessageHeuristicOrder::Samples;
  1441. break;
  1442. case MOD_TYPE_XM:
  1443. result = ModMessageHeuristicOrder::InstrumentsSamples;
  1444. break;
  1445. case MOD_TYPE_MDL:
  1446. result = ModMessageHeuristicOrder::InstrumentsSamples;
  1447. break;
  1448. case MOD_TYPE_IMF:
  1449. result = ModMessageHeuristicOrder::InstrumentsSamples;
  1450. break;
  1451. default:
  1452. result = ModMessageHeuristicOrder::Default;
  1453. break;
  1454. }
  1455. return result;
  1456. }
  1457. bool CSoundFile::SetTitle(const std::string &newTitle)
  1458. {
  1459. if(m_songName != newTitle)
  1460. {
  1461. m_songName = newTitle;
  1462. return true;
  1463. }
  1464. return false;
  1465. }
  1466. double CSoundFile::GetPlaybackTimeAt(ORDERINDEX ord, ROWINDEX row, bool updateVars, bool updateSamplePos)
  1467. {
  1468. const GetLengthType t = GetLength(updateVars ? (updateSamplePos ? eAdjustSamplePositions : eAdjust) : eNoAdjust, GetLengthTarget(ord, row)).back();
  1469. if(t.targetReached) return t.duration;
  1470. else return -1; //Given position not found from play sequence.
  1471. }
  1472. std::vector<SubSong> CSoundFile::GetAllSubSongs()
  1473. {
  1474. std::vector<SubSong> subSongs;
  1475. for(SEQUENCEINDEX seq = 0; seq < Order.GetNumSequences(); seq++)
  1476. {
  1477. const auto subSongsSeq = GetLength(eNoAdjust, GetLengthTarget(true).StartPos(seq, 0, 0));
  1478. subSongs.reserve(subSongs.size() + subSongsSeq.size());
  1479. for(const auto &song : subSongsSeq)
  1480. {
  1481. subSongs.push_back({song.duration, song.startRow, song.endRow, song.lastRow, song.startOrder, song.endOrder, song.lastOrder, seq});
  1482. }
  1483. }
  1484. return subSongs;
  1485. }
  1486. // Calculate the length of a tick, depending on the tempo mode.
  1487. // This differs from GetTickDuration() by not accumulating errors
  1488. // because this is not called once per tick but in unrelated
  1489. // circumstances. So this should not update error accumulation.
  1490. void CSoundFile::RecalculateSamplesPerTick()
  1491. {
  1492. switch(m_nTempoMode)
  1493. {
  1494. case TempoMode::Classic:
  1495. default:
  1496. m_PlayState.m_nSamplesPerTick = Util::muldiv(m_MixerSettings.gdwMixingFreq, 5 * TEMPO::fractFact, std::max(TEMPO::store_t(1), m_PlayState.m_nMusicTempo.GetRaw() << 1));
  1497. break;
  1498. case TempoMode::Modern:
  1499. m_PlayState.m_nSamplesPerTick = static_cast<uint32>((Util::mul32to64_unsigned(m_MixerSettings.gdwMixingFreq, 60 * TEMPO::fractFact) / std::max(uint64(1), Util::mul32to64_unsigned(m_PlayState.m_nMusicSpeed, m_PlayState.m_nCurrentRowsPerBeat) * m_PlayState.m_nMusicTempo.GetRaw())));
  1500. break;
  1501. case TempoMode::Alternative:
  1502. m_PlayState.m_nSamplesPerTick = Util::muldiv(m_MixerSettings.gdwMixingFreq, TEMPO::fractFact, std::max(TEMPO::store_t(1), m_PlayState.m_nMusicTempo.GetRaw()));
  1503. break;
  1504. }
  1505. #ifndef MODPLUG_TRACKER
  1506. m_PlayState.m_nSamplesPerTick = Util::muldivr(m_PlayState.m_nSamplesPerTick, m_nTempoFactor, 65536);
  1507. #endif // !MODPLUG_TRACKER
  1508. if(!m_PlayState.m_nSamplesPerTick)
  1509. m_PlayState.m_nSamplesPerTick = 1;
  1510. }
  1511. // Get length of a tick in sample, with tick-to-tick tempo correction in modern tempo mode.
  1512. // This has to be called exactly once per tick because otherwise the error accumulation
  1513. // goes wrong.
  1514. uint32 CSoundFile::GetTickDuration(PlayState &playState) const
  1515. {
  1516. uint32 retval = 0;
  1517. switch(m_nTempoMode)
  1518. {
  1519. case TempoMode::Classic:
  1520. default:
  1521. retval = Util::muldiv(m_MixerSettings.gdwMixingFreq, 5 * TEMPO::fractFact, std::max(TEMPO::store_t(1), playState.m_nMusicTempo.GetRaw() << 1));
  1522. break;
  1523. case TempoMode::Alternative:
  1524. retval = Util::muldiv(m_MixerSettings.gdwMixingFreq, TEMPO::fractFact, std::max(TEMPO::store_t(1), playState.m_nMusicTempo.GetRaw()));
  1525. break;
  1526. case TempoMode::Modern:
  1527. {
  1528. double accurateBufferCount = static_cast<double>(m_MixerSettings.gdwMixingFreq) * (60.0 / (playState.m_nMusicTempo.ToDouble() * Util::mul32to64_unsigned(playState.m_nMusicSpeed, playState.m_nCurrentRowsPerBeat)));
  1529. const TempoSwing &swing = (Patterns.IsValidPat(playState.m_nPattern) && Patterns[playState.m_nPattern].HasTempoSwing())
  1530. ? Patterns[playState.m_nPattern].GetTempoSwing()
  1531. : m_tempoSwing;
  1532. if(!swing.empty())
  1533. {
  1534. // Apply current row's tempo swing factor
  1535. TempoSwing::value_type swingFactor = swing[playState.m_nRow % swing.size()];
  1536. accurateBufferCount = accurateBufferCount * swingFactor / double(TempoSwing::Unity);
  1537. }
  1538. uint32 bufferCount = static_cast<int>(accurateBufferCount);
  1539. playState.m_dBufferDiff += accurateBufferCount - bufferCount;
  1540. //tick-to-tick tempo correction:
  1541. if(playState.m_dBufferDiff >= 1)
  1542. {
  1543. bufferCount++;
  1544. playState.m_dBufferDiff--;
  1545. } else if(m_PlayState.m_dBufferDiff <= -1)
  1546. {
  1547. bufferCount--;
  1548. playState.m_dBufferDiff++;
  1549. }
  1550. MPT_ASSERT(std::abs(playState.m_dBufferDiff) < 1.0);
  1551. retval = bufferCount;
  1552. }
  1553. break;
  1554. }
  1555. #ifndef MODPLUG_TRACKER
  1556. // when the user modifies the tempo, we do not really care about accurate tempo error accumulation
  1557. retval = Util::muldivr_unsigned(retval, m_nTempoFactor, 65536);
  1558. #endif // !MODPLUG_TRACKER
  1559. if(!retval)
  1560. retval = 1;
  1561. return retval;
  1562. }
  1563. // Get the duration of a row in milliseconds, based on the current rows per beat and given speed and tempo settings.
  1564. double CSoundFile::GetRowDuration(TEMPO tempo, uint32 speed) const
  1565. {
  1566. switch(m_nTempoMode)
  1567. {
  1568. case TempoMode::Classic:
  1569. default:
  1570. return static_cast<double>(2500 * speed) / tempo.ToDouble();
  1571. case TempoMode::Modern:
  1572. {
  1573. // If there are any row delay effects, the row length factor compensates for those.
  1574. return 60000.0 / tempo.ToDouble() / static_cast<double>(m_PlayState.m_nCurrentRowsPerBeat);
  1575. }
  1576. case TempoMode::Alternative:
  1577. return static_cast<double>(1000 * speed) / tempo.ToDouble();
  1578. }
  1579. }
  1580. const CModSpecifications& CSoundFile::GetModSpecifications(const MODTYPE type)
  1581. {
  1582. const CModSpecifications* p = nullptr;
  1583. SetModSpecsPointer(p, type);
  1584. return *p;
  1585. }
  1586. ChannelFlags CSoundFile::GetChannelMuteFlag()
  1587. {
  1588. #ifdef MODPLUG_TRACKER
  1589. return (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_SYNCMUTE) ? CHN_SYNCMUTE : CHN_MUTE;
  1590. #else
  1591. return CHN_SYNCMUTE;
  1592. #endif
  1593. }
  1594. // Resolve note/instrument combination to real sample index. Return value is guaranteed to be in [0, GetNumSamples()].
  1595. SAMPLEINDEX CSoundFile::GetSampleIndex(ModCommand::NOTE note, uint32 instr) const noexcept
  1596. {
  1597. SAMPLEINDEX smp = 0;
  1598. if(GetNumInstruments())
  1599. {
  1600. if(ModCommand::IsNote(note) && instr <= GetNumInstruments() && Instruments[instr] != nullptr)
  1601. smp = Instruments[instr]->Keyboard[note - NOTE_MIN];
  1602. } else
  1603. {
  1604. smp = static_cast<SAMPLEINDEX>(instr);
  1605. }
  1606. if(smp <= GetNumSamples())
  1607. return smp;
  1608. else
  1609. return 0;
  1610. }
  1611. // Find an unused sample slot. If it is going to be assigned to an instrument, targetInstrument should be specified.
  1612. // SAMPLEINDEX_INVLAID is returned if no free sample slot could be found.
  1613. SAMPLEINDEX CSoundFile::GetNextFreeSample(INSTRUMENTINDEX targetInstrument, SAMPLEINDEX start) const
  1614. {
  1615. // Find empty slot in two passes - in the first pass, we only search for samples with empty sample names,
  1616. // in the second pass we check all samples with non-empty sample names.
  1617. for(int passes = 0; passes < 2; passes++)
  1618. {
  1619. for(SAMPLEINDEX i = start; i <= GetModSpecifications().samplesMax; i++)
  1620. {
  1621. // Early exit for FM instruments
  1622. if(Samples[i].uFlags[CHN_ADLIB] && (targetInstrument == INSTRUMENTINDEX_INVALID || !IsSampleReferencedByInstrument(i, targetInstrument)))
  1623. continue;
  1624. // When loading into an instrument, ignore non-empty sample names. Else, only use this slot if the sample name is empty or we're in second pass.
  1625. if((i > GetNumSamples() && passes == 1)
  1626. || (!Samples[i].HasSampleData() && (!m_szNames[i][0] || passes == 1 || targetInstrument != INSTRUMENTINDEX_INVALID))
  1627. || (targetInstrument != INSTRUMENTINDEX_INVALID && IsSampleReferencedByInstrument(i, targetInstrument))) // Not empty, but already used by this instrument. XXX this should only be done when replacing an instrument with a single sample! Otherwise it will use an inconsistent sample map!
  1628. {
  1629. // Empty slot, so it's a good candidate already.
  1630. // In instrument mode, check whether any instrument references this sample slot. If that is the case, we won't use it as it could lead to unwanted conflicts.
  1631. // If we are loading the sample *into* an instrument, we should also not consider that instrument's sample map, since it might be inconsistent at this time.
  1632. bool isReferenced = false;
  1633. for(INSTRUMENTINDEX ins = 1; ins <= GetNumInstruments(); ins++)
  1634. {
  1635. if(ins == targetInstrument)
  1636. {
  1637. continue;
  1638. }
  1639. if(IsSampleReferencedByInstrument(i, ins))
  1640. {
  1641. isReferenced = true;
  1642. break;
  1643. }
  1644. }
  1645. if(!isReferenced)
  1646. {
  1647. return i;
  1648. }
  1649. }
  1650. }
  1651. }
  1652. return SAMPLEINDEX_INVALID;
  1653. }
  1654. // Find an unused instrument slot.
  1655. // INSTRUMENTINDEX_INVALID is returned if no free instrument slot could be found.
  1656. INSTRUMENTINDEX CSoundFile::GetNextFreeInstrument(INSTRUMENTINDEX start) const
  1657. {
  1658. for(INSTRUMENTINDEX i = start; i <= GetModSpecifications().instrumentsMax; i++)
  1659. {
  1660. if(Instruments[i] == nullptr)
  1661. {
  1662. return i;
  1663. }
  1664. }
  1665. return INSTRUMENTINDEX_INVALID;
  1666. }
  1667. // Check whether a given sample is used by a given instrument.
  1668. bool CSoundFile::IsSampleReferencedByInstrument(SAMPLEINDEX sample, INSTRUMENTINDEX instr) const
  1669. {
  1670. if(instr < 1 || instr > GetNumInstruments())
  1671. return false;
  1672. const ModInstrument *targetIns = Instruments[instr];
  1673. if(targetIns == nullptr)
  1674. return false;
  1675. return mpt::contains(mpt::as_span(targetIns->Keyboard).first(NOTE_MAX), sample);
  1676. }
  1677. ModInstrument *CSoundFile::AllocateInstrument(INSTRUMENTINDEX instr, SAMPLEINDEX assignedSample)
  1678. {
  1679. if(instr == 0 || instr >= MAX_INSTRUMENTS)
  1680. {
  1681. return nullptr;
  1682. }
  1683. ModInstrument *ins = Instruments[instr];
  1684. if(ins != nullptr)
  1685. {
  1686. // Re-initialize instrument
  1687. *ins = ModInstrument(assignedSample);
  1688. } else
  1689. {
  1690. // Create new instrument
  1691. Instruments[instr] = ins = new (std::nothrow) ModInstrument(assignedSample);
  1692. }
  1693. if(ins != nullptr)
  1694. {
  1695. m_nInstruments = std::max(m_nInstruments, instr);
  1696. }
  1697. return ins;
  1698. }
  1699. void CSoundFile::PrecomputeSampleLoops(bool updateChannels)
  1700. {
  1701. for(SAMPLEINDEX i = 1; i <= GetNumSamples(); i++)
  1702. {
  1703. Samples[i].PrecomputeLoops(*this, updateChannels);
  1704. }
  1705. }
  1706. #ifdef MPT_EXTERNAL_SAMPLES
  1707. // Load external waveform, but keep sample properties like frequency, panning, etc...
  1708. // Returns true if the file could be loaded.
  1709. bool CSoundFile::LoadExternalSample(SAMPLEINDEX smp, const mpt::PathString &filename)
  1710. {
  1711. bool ok = false;
  1712. InputFile f(filename, SettingCacheCompleteFileBeforeLoading());
  1713. if(f.IsValid())
  1714. {
  1715. const ModSample origSample = Samples[smp];
  1716. mpt::charbuf<MAX_SAMPLENAME> origName;
  1717. origName = m_szNames[smp];
  1718. FileReader file = GetFileReader(f);
  1719. ok = ReadSampleFromFile(smp, file, false);
  1720. if(ok)
  1721. {
  1722. // Copy over old attributes, but keep new sample data
  1723. ModSample &sample = GetSample(smp);
  1724. SmpLength newLength = sample.nLength;
  1725. void *newData = sample.samplev();
  1726. SampleFlags newFlags = sample.uFlags;
  1727. sample = origSample;
  1728. sample.nLength = newLength;
  1729. sample.pData.pSample = newData;
  1730. sample.uFlags.set(CHN_16BIT, newFlags[CHN_16BIT]);
  1731. sample.uFlags.set(CHN_STEREO, newFlags[CHN_STEREO]);
  1732. sample.uFlags.reset(SMP_MODIFIED);
  1733. sample.SanitizeLoops();
  1734. }
  1735. m_szNames[smp] = origName;
  1736. }
  1737. SetSamplePath(smp, filename);
  1738. return ok;
  1739. }
  1740. #endif // MPT_EXTERNAL_SAMPLES
  1741. // Set up channel panning and volume suitable for MOD + similar files. If the current mod type is not MOD, bForceSetup has to be set to true.
  1742. void CSoundFile::SetupMODPanning(bool bForceSetup)
  1743. {
  1744. // Setup LRRL panning, max channel volume
  1745. if(!(GetType() & MOD_TYPE_MOD) && bForceSetup == false) return;
  1746. for(CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++)
  1747. {
  1748. ChnSettings[nChn].nVolume = 64;
  1749. ChnSettings[nChn].dwFlags.reset(CHN_SURROUND);
  1750. if(m_MixerSettings.MixerFlags & SNDMIX_MAXDEFAULTPAN)
  1751. ChnSettings[nChn].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 256 : 0;
  1752. else
  1753. ChnSettings[nChn].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 0xC0 : 0x40;
  1754. }
  1755. }
  1756. void CSoundFile::PropagateXMAutoVibrato(INSTRUMENTINDEX ins, VibratoType type, uint8 sweep, uint8 depth, uint8 rate)
  1757. {
  1758. if(ins > m_nInstruments || Instruments[ins] == nullptr)
  1759. return;
  1760. const std::set<SAMPLEINDEX> referencedSamples = Instruments[ins]->GetSamples();
  1761. // Propagate changes to all samples that belong to this instrument.
  1762. for(auto sample : referencedSamples)
  1763. {
  1764. if(sample <= m_nSamples)
  1765. {
  1766. Samples[sample].nVibDepth = depth;
  1767. Samples[sample].nVibType = type;
  1768. Samples[sample].nVibRate = rate;
  1769. Samples[sample].nVibSweep = sweep;
  1770. }
  1771. }
  1772. }
  1773. // Normalize the tempo swing coefficients so that they add up to exactly the specified tempo again
  1774. void TempoSwing::Normalize()
  1775. {
  1776. if(empty()) return;
  1777. uint64 sum = 0;
  1778. for(auto &i : *this)
  1779. {
  1780. Limit(i, Unity / 4u, Unity * 4u);
  1781. sum += i;
  1782. }
  1783. sum /= size();
  1784. MPT_ASSERT(sum > 0); // clang-analyzer false-positive
  1785. int64 remain = Unity * size();
  1786. for(auto &i : *this)
  1787. {
  1788. i = Util::muldivr_unsigned(i, Unity, static_cast<int32>(sum));
  1789. remain -= i;
  1790. }
  1791. //MPT_ASSERT(static_cast<uint32>(std::abs(static_cast<int32>(remain))) <= size());
  1792. at(0) += static_cast<int32>(remain);
  1793. }
  1794. void TempoSwing::Serialize(std::ostream &oStrm, const TempoSwing &swing)
  1795. {
  1796. mpt::IO::WriteIntLE<uint16>(oStrm, static_cast<uint16>(swing.size()));
  1797. for(std::size_t i = 0; i < swing.size(); i++)
  1798. {
  1799. mpt::IO::WriteIntLE<uint32>(oStrm, swing[i]);
  1800. }
  1801. }
  1802. void TempoSwing::Deserialize(std::istream &iStrm, TempoSwing &swing, const size_t)
  1803. {
  1804. uint16 numEntries;
  1805. mpt::IO::ReadIntLE<uint16>(iStrm, numEntries);
  1806. swing.resize(numEntries);
  1807. for(uint16 i = 0; i < numEntries; i++)
  1808. {
  1809. mpt::IO::ReadIntLE<uint32>(iStrm, swing[i]);
  1810. }
  1811. swing.Normalize();
  1812. }
  1813. OPENMPT_NAMESPACE_END