1 /*
2  * Sndfile.h
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 
11 
12 #pragma once
13 
14 #include "openmpt/all/BuildSettings.hpp"
15 
16 #include "SoundFilePlayConfig.h"
17 #include "MixerSettings.h"
18 #include "../common/misc_util.h"
19 #include "../common/mptRandom.h"
20 #include "../common/version.h"
21 #include <vector>
22 #include <bitset>
23 #include <set>
24 #include "Snd_defs.h"
25 #include "tuningbase.h"
26 #include "MIDIMacros.h"
27 #ifdef MODPLUG_TRACKER
28 #include "../mptrack/MIDIMapping.h"
29 #endif // MODPLUG_TRACKER
30 
31 #include "Mixer.h"
32 #include "Resampler.h"
33 #ifndef NO_REVERB
34 #include "../sounddsp/Reverb.h"
35 #endif
36 #ifndef NO_AGC
37 #include "../sounddsp/AGC.h"
38 #endif
39 #ifndef NO_DSP
40 #include "../sounddsp/DSP.h"
41 #endif
42 #ifndef NO_EQ
43 #include "../sounddsp/EQ.h"
44 #endif
45 
46 #include "modcommand.h"
47 #include "ModSample.h"
48 #include "ModInstrument.h"
49 #include "ModChannel.h"
50 #include "plugins/PluginStructs.h"
51 #include "RowVisitor.h"
52 #include "Message.h"
53 #include "pattern.h"
54 #include "patternContainer.h"
55 #include "ModSequence.h"
56 
57 #include "mpt/audio/span.hpp"
58 
59 #include "../common/FileReaderFwd.h"
60 
61 
62 OPENMPT_NAMESPACE_BEGIN
63 
64 
65 bool SettingCacheCompleteFileBeforeLoading();
66 
67 
68 // -----------------------------------------------------------------------------
69 // MODULAR ModInstrument FIELD ACCESS : body content in InstrumentExtensions.cpp
70 // -----------------------------------------------------------------------------
71 #ifndef MODPLUG_NO_FILESAVE
72 void WriteInstrumentHeaderStructOrField(ModInstrument * input, std::ostream &file, uint32 only_this_code = -1 /* -1 for all */, uint16 fixedsize = 0);
73 #endif // !MODPLUG_NO_FILESAVE
74 bool ReadInstrumentHeaderField(ModInstrument * input, uint32 fcode, uint16 fsize, FileReader &file);
75 // --------------------------------------------------------------------------------------------
76 // --------------------------------------------------------------------------------------------
77 
78 
79 // Sample decompression routines in format-specific source files
80 void AMSUnpack(const int8 * const source, size_t sourceSize, void * const dest, const size_t destSize, char packCharacter);
81 uintptr_t DMFUnpack(FileReader &file, uint8 *psample, uint32 maxlen);
82 
83 
84 #ifdef LIBOPENMPT_BUILD
85 #ifndef NO_PLUGINS
86 class CVstPluginManager;
87 #endif
88 #endif
89 
90 
91 using PlayBehaviourSet = std::bitset<kMaxPlayBehaviours>;
92 
93 #ifdef MODPLUG_TRACKER
94 
95 // For WAV export (writing pattern positions to file)
96 struct PatternCuePoint
97 {
98 	uint64     offset;    // offset in the file (in samples)
99 	ORDERINDEX order;     // which order is this?
100 	bool       processed; // has this point been processed by the main WAV render function yet?
101 };
102 
103 #endif // MODPLUG_TRACKER
104 
105 
106 // Return values for GetLength()
107 struct GetLengthType
108 {
109 	double     duration = 0.0;                 // Total time in seconds
110 	ROWINDEX   lastRow = ROWINDEX_INVALID;     // Last parsed row (if no target is specified, this is the first row that is parsed twice, i.e. not the *last* played order)
111 	ROWINDEX   endRow = ROWINDEX_INVALID;      // Last row before module loops (UNDEFINED if a target is specified)
112 	ROWINDEX   startRow = 0;                   // First row of parsed subsong
113 	ORDERINDEX lastOrder = ORDERINDEX_INVALID; // Last parsed order (see lastRow remark)
114 	ORDERINDEX endOrder = ORDERINDEX_INVALID;  // Last order before module loops (UNDEFINED if a target is specified)
115 	ORDERINDEX startOrder = 0;                 // First order of parsed subsong
116 	bool       targetReached = false;          // True if the specified order/row combination or duration has been reached while going through the module
117 };
118 
119 
120 struct SubSong
121 {
122 	double duration;
123 	ROWINDEX startRow, endRow, loopStartRow;
124 	ORDERINDEX startOrder, endOrder, loopStartOrder;
125 	SEQUENCEINDEX sequence;
126 };
127 
128 
129 // Target seek mode for GetLength()
130 struct GetLengthTarget
131 {
132 	ROWINDEX startRow;
133 	ORDERINDEX startOrder;
134 	SEQUENCEINDEX sequence;
135 
136 	struct pos_type
137 	{
138 		ROWINDEX row;
139 		ORDERINDEX order;
140 	};
141 
142 	union
143 	{
144 		double time;
145 		pos_type pos;
146 	};
147 
148 	enum Mode
149 	{
150 		NoTarget,       // Don't seek, i.e. return complete length of the first subsong.
151 		GetAllSubsongs, // Same as NoTarget (i.e. get complete length), but returns the length of all sub songs
152 		SeekPosition,   // Seek to given pattern position.
153 		SeekSeconds,    // Seek to given time.
154 	} mode;
155 
156 	// Don't seek, i.e. return complete module length.
157 	GetLengthTarget(bool allSongs = false)
158 	{
159 		mode = allSongs ? GetAllSubsongs : NoTarget;
160 		sequence = SEQUENCEINDEX_INVALID;
161 		startOrder = 0;
162 		startRow = 0;
163 	}
164 
165 	// Seek to given pattern position if position is valid.
GetLengthTargetGetLengthTarget166 	GetLengthTarget(ORDERINDEX order, ROWINDEX row)
167 	{
168 		mode = NoTarget;
169 		sequence = SEQUENCEINDEX_INVALID;
170 		startOrder = 0;
171 		startRow = 0;
172 		if(order != ORDERINDEX_INVALID && row != ROWINDEX_INVALID)
173 		{
174 			mode = SeekPosition;
175 			pos.row = row;
176 			pos.order = order;
177 		}
178 	}
179 
180 	// Seek to given time if t is valid (i.e. not negative).
GetLengthTargetGetLengthTarget181 	GetLengthTarget(double t)
182 	{
183 		mode = NoTarget;
184 		sequence = SEQUENCEINDEX_INVALID;
185 		startOrder = 0;
186 		startRow = 0;
187 		if(t >= 0.0)
188 		{
189 			mode = SeekSeconds;
190 			time = t;
191 		}
192 	}
193 
194 	// Set start position from which seeking should begin.
StartPosGetLengthTarget195 	GetLengthTarget &StartPos(SEQUENCEINDEX seq, ORDERINDEX order, ROWINDEX row)
196 	{
197 		sequence = seq;
198 		startOrder = order;
199 		startRow = row;
200 		return *this;
201 	}
202 };
203 
204 
205 // Reset mode for GetLength()
206 enum enmGetLengthResetMode
207 {
208 	// Never adjust global variables / mod parameters
209 	eNoAdjust = 0x00,
210 	// Mod parameters (such as global volume, speed, tempo, etc...) will always be memorized if the target was reached (i.e. they won't be reset to the previous values).  If target couldn't be reached, they are reset to their default values.
211 	eAdjust = 0x01,
212 	// Same as above, but global variables will only be memorized if the target could be reached. This does *NOT* influence the visited rows vector - it will *ALWAYS* be adjusted in this mode.
213 	eAdjustOnSuccess = 0x02 | eAdjust,
214 	// Same as previous option, but will also try to emulate sample playback so that voices from previous patterns will sound when continuing playback at the target position.
215 	eAdjustSamplePositions = 0x04 | eAdjustOnSuccess,
216 	// Only adjust the visited rows state
217 	eAdjustOnlyVisitedRows = 0x08,
218 };
219 
220 
221 // Delete samples assigned to instrument
222 enum deleteInstrumentSamples
223 {
224 	deleteAssociatedSamples,
225 	doNoDeleteAssociatedSamples,
226 };
227 
228 
229 namespace Tuning {
230 class CTuningCollection;
231 } // namespace Tuning
232 using CTuningCollection = Tuning::CTuningCollection;
233 struct CModSpecifications;
234 class OPL;
235 #ifdef MODPLUG_TRACKER
236 class CModDoc;
237 #endif // MODPLUG_TRACKER
238 
239 
240 /////////////////////////////////////////////////////////////////////////
241 // File edit history
242 
243 #define HISTORY_TIMER_PRECISION	18.2
244 
245 struct FileHistory
246 {
247 	// Date when the file was loaded in the the tracker or created.
248 	tm loadDate = {};
249 	// Time the file was open in the editor, in 1/18.2th seconds (frequency of a standard DOS timer, to keep compatibility with Impulse Tracker easy).
250 	uint32 openTime = 0;
251 	// Return the date as a (possibly truncated if not enough precision is available) ISO 8601 formatted date.
252 	mpt::ustring AsISO8601() const;
253 	// Returns true if the date component is valid. Some formats only store edit time, not edit date.
HasValidDateFileHistory254 	bool HasValidDate() const { return loadDate.tm_mday != 0; }
255 };
256 
257 
258 struct TimingInfo
259 {
260 	double InputLatency = 0.0; // seconds
261 	double OutputLatency = 0.0; // seconds
262 	int64 StreamFrames = 0;
263 	uint64 SystemTimestamp = 0; // nanoseconds
264 	double Speed = 1.0;
265 };
266 
267 
268 enum class ModMessageHeuristicOrder
269 {
270 	Instruments,
271 	Samples,
272 	InstrumentsSamples,
273 	SamplesInstruments,
274 	BothInstrumentsSamples,
275 	BothSamplesInstruments,
276 	Default = InstrumentsSamples,
277 };
278 
279 struct ModFormatDetails
280 {
281 	mpt::ustring formatName;         // "FastTracker 2"
282 	mpt::ustring type;               // "xm"
283 	mpt::ustring madeWithTracker;    // "OpenMPT 1.28.01.00"
284 	mpt::ustring originalFormatName; // "FastTracker 2" in the case of converted formats like MO3 or GDM
285 	mpt::ustring originalType;       // "xm" in the case of converted formats like MO3 or GDM
286 	mpt::Charset charset = mpt::Charset::UTF8;
287 };
288 
289 
290 class IAudioTarget
291 {
292 protected:
293 	virtual ~IAudioTarget() = default;
294 public:
295 	virtual void Process(mpt::audio_span_interleaved<MixSampleInt> buffer) = 0;
296 	virtual void Process(mpt::audio_span_interleaved<MixSampleFloat> buffer) = 0;
297 };
298 
299 
300 class IAudioSource
301 {
302 public:
303 	virtual ~IAudioSource() = default;
304 public:
305 	virtual void Process(mpt::audio_span_planar<MixSampleInt> buffer) = 0;
306 	virtual void Process(mpt::audio_span_planar<MixSampleFloat> buffer) = 0;
307 };
308 
309 
310 class IMonitorInput
311 {
312 public:
313 	virtual ~IMonitorInput() = default;
314 public:
315 	virtual void Process(mpt::audio_span_planar<const MixSampleInt> buffer) = 0;
316 	virtual void Process(mpt::audio_span_planar<const MixSampleFloat> buffer) = 0;
317 };
318 
319 
320 class IMonitorOutput
321 {
322 public:
323 	virtual ~IMonitorOutput() = default;
324 public:
325 	virtual void Process(mpt::audio_span_interleaved<const MixSampleInt> buffer) = 0;
326 	virtual void Process(mpt::audio_span_interleaved<const MixSampleFloat> buffer) = 0;
327 };
328 
329 
330 class AudioSourceNone
331 	: public IAudioSource
332 {
333 public:
Process(mpt::audio_span_planar<MixSampleInt> buffer)334 	void Process(mpt::audio_span_planar<MixSampleInt> buffer) override
335 	{
336 		for(std::size_t channel = 0; channel < buffer.size_channels(); ++channel)
337 		{
338 			for(std::size_t frame = 0; frame < buffer.size_frames(); ++frame)
339 			{
340 				buffer(channel, frame) = 0;
341 			}
342 		}
343 	}
Process(mpt::audio_span_planar<MixSampleFloat> buffer)344 	void Process(mpt::audio_span_planar<MixSampleFloat> buffer) override
345 	{
346 		for(std::size_t channel = 0; channel < buffer.size_channels(); ++channel)
347 		{
348 			for(std::size_t frame = 0; frame < buffer.size_frames(); ++frame)
349 			{
350 				buffer(channel, frame) = MixSampleFloat(0.0);
351 			}
352 		}
353 	}
354 };
355 
356 
357 using NoteName = mpt::uchar[4];
358 
359 
360 class CSoundFile
361 {
362 	friend class GetLengthMemory;
363 
364 public:
365 #ifdef MODPLUG_TRACKER
366 	void ChangeModTypeTo(const MODTYPE newType, bool adjust = true);
367 #endif // MODPLUG_TRACKER
368 
369 	// Returns value in seconds. If given position won't be played at all, returns -1.
370 	// If updateVars is true, the state of various playback variables will be updated according to the playback position.
371 	// If updateSamplePos is also true, the sample positions of samples still playing from previous patterns will be kept in sync.
372 	double GetPlaybackTimeAt(ORDERINDEX ord, ROWINDEX row, bool updateVars, bool updateSamplePos);
373 
374 	std::vector<SubSong> GetAllSubSongs();
375 
376 	//Tuning-->
377 public:
378 	static std::unique_ptr<CTuning> CreateTuning12TET(const mpt::ustring &name);
GetDefaultTuning()379 	static CTuning *GetDefaultTuning() {return nullptr;}
GetTuneSpecificTunings()380 	CTuningCollection& GetTuneSpecificTunings() {return *m_pTuningsTuneSpecific;}
381 
382 	mpt::ustring GetNoteName(const ModCommand::NOTE note, const INSTRUMENTINDEX inst) const;
383 	mpt::ustring GetNoteName(const ModCommand::NOTE note) const;
384 	static mpt::ustring GetNoteName(const ModCommand::NOTE note, const NoteName *noteNames);
385 #ifdef MODPLUG_TRACKER
386 public:
387 	static void SetDefaultNoteNames();
388 	static const NoteName *GetDefaultNoteNames();
GetDefaultNoteName(int note)389 	static mpt::ustring GetDefaultNoteName(int note)  // note = [0..11]
390 	{
391 		return m_NoteNames[note];
392 	}
393 private:
394 	static const NoteName *m_NoteNames;
395 #else
396 private:
397 	const NoteName *m_NoteNames;
398 #endif
399 
400 private:
401 	CTuningCollection* m_pTuningsTuneSpecific = nullptr;
402 
403 #ifdef MODPLUG_TRACKER
404 public:
GetMIDIMapper()405 	CMIDIMapper& GetMIDIMapper() {return m_MIDIMapper;}
GetMIDIMapper()406 	const CMIDIMapper& GetMIDIMapper() const {return m_MIDIMapper;}
407 private:
408 	CMIDIMapper m_MIDIMapper;
409 
410 #endif // MODPLUG_TRACKER
411 
412 private: //Misc private methods.
413 	static void SetModSpecsPointer(const CModSpecifications* &pModSpecs, const MODTYPE type);
414 
415 private: //Misc data
416 	const CModSpecifications *m_pModSpecs;
417 
418 private:
419 	// Interleaved Front Mix Buffer (Also room for interleaved rear mix)
420 	mixsample_t MixSoundBuffer[MIXBUFFERSIZE * 4];
421 	mixsample_t MixRearBuffer[MIXBUFFERSIZE * 2];
422 	// Non-interleaved plugin processing buffer
423 	float MixFloatBuffer[2][MIXBUFFERSIZE];
424 	mixsample_t MixInputBuffer[NUMMIXINPUTBUFFERS][MIXBUFFERSIZE];
425 
426 	// End-of-sample pop reduction tail level
427 	mixsample_t m_dryLOfsVol = 0, m_dryROfsVol = 0;
428 	mixsample_t m_surroundLOfsVol = 0, m_surroundROfsVol = 0;
429 
430 public:
431 	MixerSettings m_MixerSettings;
432 	CResampler m_Resampler;
433 #ifndef NO_REVERB
434 	mixsample_t ReverbSendBuffer[MIXBUFFERSIZE * 2];
435 	mixsample_t m_RvbROfsVol = 0, m_RvbLOfsVol = 0;
436 	CReverb m_Reverb;
437 #endif
438 #ifndef NO_DSP
439 	CSurround m_Surround;
440 	CMegaBass m_MegaBass;
441 #endif
442 #ifndef NO_EQ
443 	CEQ m_EQ;
444 #endif
445 #ifndef NO_AGC
446 	CAGC m_AGC;
447 #endif
448 #ifndef NO_DSP
449 	BitCrush m_BitCrush;
450 #endif
451 
452 	using samplecount_t = uint32; // Number of rendered samples
453 
454 	static constexpr uint32 TICKS_ROW_FINISHED = uint32_max - 1u;
455 
456 public:	// for Editing
457 #ifdef MODPLUG_TRACKER
458 	CModDoc *m_pModDoc = nullptr; // Can be a null pointer for example when previewing samples from the treeview.
459 #endif // MODPLUG_TRACKER
460 	Enum<MODTYPE> m_nType;
461 private:
462 	MODCONTAINERTYPE m_ContainerType = MOD_CONTAINERTYPE_NONE;
463 public:
464 	CHANNELINDEX m_nChannels = 0;
465 	SAMPLEINDEX m_nSamples = 0;
466 	INSTRUMENTINDEX m_nInstruments = 0;
467 	uint32 m_nDefaultSpeed, m_nDefaultGlobalVolume;
468 	TEMPO m_nDefaultTempo;
469 	FlagSet<SongFlags> m_SongFlags;
470 	CHANNELINDEX m_nMixChannels = 0;
471 private:
472 	CHANNELINDEX m_nMixStat;
473 public:
474 	ROWINDEX m_nDefaultRowsPerBeat, m_nDefaultRowsPerMeasure;	// default rows per beat and measure for this module
475 	TempoMode m_nTempoMode = TempoMode::Classic;
476 
477 #ifdef MODPLUG_TRACKER
478 	// Lock playback between two rows. Lock is active if lock start != ROWINDEX_INVALID).
479 	ROWINDEX m_lockRowStart = ROWINDEX_INVALID, m_lockRowEnd = ROWINDEX_INVALID;
480 	// Lock playback between two orders. Lock is active if lock start != ORDERINDEX_INVALID).
481 	ORDERINDEX m_lockOrderStart = ORDERINDEX_INVALID, m_lockOrderEnd = ORDERINDEX_INVALID;
482 #endif // MODPLUG_TRACKER
483 
484 	uint32 m_nSamplePreAmp, m_nVSTiVolume;
485 	uint32 m_OPLVolumeFactor;  // 16.16
486 	static constexpr uint32 m_OPLVolumeFactorScale = 1 << 16;
487 
IsGlobalVolumeUnset()488 	constexpr bool IsGlobalVolumeUnset() const noexcept { return IsFirstTick(); }
489 #ifndef MODPLUG_TRACKER
490 	uint32 m_nFreqFactor = 65536; // Pitch shift factor (65536 = no pitch shifting). Only used in libopenmpt (openmpt::ext::interactive::set_pitch_factor)
491 	uint32 m_nTempoFactor = 65536; // Tempo factor (65536 = no tempo adjustment). Only used in libopenmpt (openmpt::ext::interactive::set_tempo_factor)
492 #endif
493 
494 	// Row swing factors for modern tempo mode
495 	TempoSwing m_tempoSwing;
496 
497 	// Min Period = highest possible frequency, Max Period = lowest possible frequency for current format
498 	// Note: Period is an Amiga metric that is inverse to frequency.
499 	// Periods in MPT are 4 times as fine as Amiga periods because of extra fine frequency slides (introduced in the S3M format).
500 	int32 m_nMinPeriod, m_nMaxPeriod;
501 
502 	ResamplingMode m_nResampling; // Resampling mode (if overriding the globally set resampling)
503 	int32 m_nRepeatCount = 0;     // -1 means repeat infinitely.
504 	ORDERINDEX m_nMaxOrderPosition;
505 	ModChannelSettings ChnSettings[MAX_BASECHANNELS];  // Initial channels settings
506 	CPatternContainer Patterns;
507 	ModSequenceSet Order;  // Pattern sequences (order lists)
508 protected:
509 	ModSample Samples[MAX_SAMPLES];
510 public:
511 	ModInstrument *Instruments[MAX_INSTRUMENTS];  // Instrument Headers
512 	MIDIMacroConfig m_MidiCfg;                    // MIDI Macro config table
513 #ifndef NO_PLUGINS
514 	SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS];  // Mix plugins
515 	uint32 m_loadedPlugins = 0;                 // Not a PLUGINDEX because number of loaded plugins may exceed MAX_MIXPLUGINS during MIDI conversion
516 #endif
517 	mpt::charbuf<MAX_SAMPLENAME> m_szNames[MAX_SAMPLES];  // Sample names
518 
519 	Version m_dwCreatedWithVersion;
520 	Version m_dwLastSavedWithVersion;
521 
522 	PlayBehaviourSet m_playBehaviour;
523 
524 protected:
525 
526 	mpt::fast_prng m_PRNG;
AccessPRNG()527 	inline mpt::fast_prng & AccessPRNG() const { return const_cast<CSoundFile*>(this)->m_PRNG; }
AccessPRNG()528 	inline mpt::fast_prng & AccessPRNG() { return m_PRNG; }
529 
530 protected:
531 	// Mix level stuff
532 	CSoundFilePlayConfig m_PlayConfig;
533 	MixLevels m_nMixLevels;
534 
535 public:
536 	struct PlayState
537 	{
538 		friend class CSoundFile;
539 
540 	public:
541 		samplecount_t m_lTotalSampleCount = 0;  // Total number of rendered samples
542 	protected:
543 		samplecount_t m_nBufferCount = 0;  // Remaining number samples to render for this tick
544 		double m_dBufferDiff = 0.0;        // Modern tempo rounding error compensation
545 
546 	public:
547 		uint32 m_nTickCount = 0;  // Current tick being processed
548 	protected:
549 		uint32 m_nPatternDelay = 0;  // Pattern delay (rows)
550 		uint32 m_nFrameDelay = 0;    // Fine pattern delay (ticks)
551 	public:
552 		uint32 m_nSamplesPerTick = 0;
553 		ROWINDEX m_nCurrentRowsPerBeat = 0;     // Current time signature
554 		ROWINDEX m_nCurrentRowsPerMeasure = 0;  // Current time signature
555 		uint32 m_nMusicSpeed = 0;               // Current speed
556 		TEMPO m_nMusicTempo;                    // Current tempo
557 
558 		// Playback position
559 		ROWINDEX m_nRow = 0;      // Current row being processed
560 		ROWINDEX m_nNextRow = 0;  // Next row to process
561 	protected:
562 		ROWINDEX m_nextPatStartRow = 0;  // For FT2's E60 bug
563 		ROWINDEX m_breakRow = 0;          // Candidate target row for pattern break
564 		ROWINDEX m_patLoopRow = 0;        // Candidate target row for pattern loop
565 		ORDERINDEX m_posJump = 0;         // Candidate target order for position jump
566 
567 	public:
568 		PATTERNINDEX m_nPattern = 0;                     // Current pattern being processed
569 		ORDERINDEX m_nCurrentOrder = 0;                  // Current order being processed
570 		ORDERINDEX m_nNextOrder = 0;                     // Next order to process
571 		ORDERINDEX m_nSeqOverride = ORDERINDEX_INVALID;  // Queued order to be processed next, regardless of what order would normally follow
572 
573 		// Global volume
574 	public:
575 		int32 m_nGlobalVolume = MAX_GLOBAL_VOLUME;  // Current global volume (0...MAX_GLOBAL_VOLUME)
576 	protected:
577 		int32 m_nSamplesToGlobalVolRampDest = 0, m_nGlobalVolumeRampAmount = 0,
578 		      m_nGlobalVolumeDestination = 0;     // Global volume ramping
579 		int32 m_lHighResRampingGlobalVolume = 0;  // Global volume ramping
580 
581 	public:
582 		bool m_bPositionChanged = true; // Report to plugins that we jumped around in the module
583 
584 	public:
585 		CHANNELINDEX ChnMix[MAX_CHANNELS]; // Index of channels in Chn to be actually mixed
586 		ModChannel Chn[MAX_CHANNELS];      // Mixing channels... First m_nChannels channels are master channels (i.e. they are never NNA channels)!
587 
588 	public:
PlayStatePlayState589 		PlayState()
590 		{
591 			std::fill(std::begin(Chn), std::end(Chn), ModChannel());
592 		}
593 
ResetGlobalVolumeRampingPlayState594 		void ResetGlobalVolumeRamping()
595 		{
596 			m_lHighResRampingGlobalVolume = m_nGlobalVolume << VOLUMERAMPPRECISION;
597 			m_nGlobalVolumeDestination = m_nGlobalVolume;
598 			m_nSamplesToGlobalVolRampDest = 0;
599 			m_nGlobalVolumeRampAmount = 0;
600 		}
601 
TicksOnRowPlayState602 		constexpr uint32 TicksOnRow() const noexcept
603 		{
604 			return (m_nMusicSpeed + m_nFrameDelay) * std::max(m_nPatternDelay, uint32(1));
605 		}
606 	};
607 
608 	PlayState m_PlayState;
609 
610 protected:
611 	// For handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav.
612 	RowVisitor m_visitedRows;
613 
614 public:
615 #ifdef MODPLUG_TRACKER
616 	std::bitset<MAX_BASECHANNELS> m_bChannelMuteTogglePending;
617 
618 	std::vector<PatternCuePoint> *m_PatternCuePoints = nullptr;	// For WAV export (writing pattern positions to file)
619 	std::vector<SmpLength> *m_SamplePlayLengths = nullptr;	// For storing the maximum play length of each sample for automatic sample trimming
620 #endif // MODPLUG_TRACKER
621 
622 	std::unique_ptr<OPL> m_opl;
623 
624 public:
625 #ifdef LIBOPENMPT_BUILD
626 #ifndef NO_PLUGINS
627 	std::unique_ptr<CVstPluginManager> m_PluginManager;
628 #endif
629 #endif
630 
631 public:
632 	std::string m_songName;
633 	mpt::ustring m_songArtist;
634 	SongMessage m_songMessage;
635 	ModFormatDetails m_modFormat;
636 
637 protected:
638 	std::vector<FileHistory> m_FileHistory;	// File edit history
639 public:
GetFileHistory()640 	std::vector<FileHistory> &GetFileHistory() { return m_FileHistory; }
GetFileHistory()641 	const std::vector<FileHistory> &GetFileHistory() const { return m_FileHistory; }
642 
643 #ifdef MPT_EXTERNAL_SAMPLES
644 	// MPTM external on-disk sample paths
645 protected:
646 	std::vector<mpt::PathString> m_samplePaths;
647 
648 public:
SetSamplePath(SAMPLEINDEX smp,mpt::PathString filename)649 	void SetSamplePath(SAMPLEINDEX smp, mpt::PathString filename) { if(m_samplePaths.size() < smp) m_samplePaths.resize(smp); m_samplePaths[smp - 1] = std::move(filename); }
ResetSamplePath(SAMPLEINDEX smp)650 	void ResetSamplePath(SAMPLEINDEX smp) { if(m_samplePaths.size() >= smp) m_samplePaths[smp - 1] = mpt::PathString(); Samples[smp].uFlags.reset(SMP_KEEPONDISK | SMP_MODIFIED);}
GetSamplePath(SAMPLEINDEX smp)651 	mpt::PathString GetSamplePath(SAMPLEINDEX smp) const { if(m_samplePaths.size() >= smp) return m_samplePaths[smp - 1]; else return mpt::PathString(); }
SampleHasPath(SAMPLEINDEX smp)652 	bool SampleHasPath(SAMPLEINDEX smp) const { if(m_samplePaths.size() >= smp) return !m_samplePaths[smp - 1].empty(); else return false; }
IsExternalSampleMissing(SAMPLEINDEX smp)653 	bool IsExternalSampleMissing(SAMPLEINDEX smp) const { return Samples[smp].uFlags[SMP_KEEPONDISK] && !Samples[smp].HasSampleData(); }
654 
655 	bool LoadExternalSample(SAMPLEINDEX smp, const mpt::PathString &filename);
656 #endif // MPT_EXTERNAL_SAMPLES
657 
658 	bool m_bIsRendering = false;
659 	TimingInfo m_TimingInfo; // only valid if !m_bIsRendering
660 
661 private:
662 	// logging
663 	ILog *m_pCustomLog = nullptr;
664 
665 public:
666 	CSoundFile();
667 	CSoundFile(const CSoundFile &) = delete;
668 	CSoundFile & operator=(const CSoundFile &) = delete;
669 	~CSoundFile();
670 
671 public:
672 	// logging
SetCustomLog(ILog * pLog)673 	void SetCustomLog(ILog *pLog) { m_pCustomLog = pLog; }
674 	void AddToLog(LogLevel level, const mpt::ustring &text) const;
675 
676 public:
677 
678 	enum ModLoadingFlags
679 	{
680 		onlyVerifyHeader   = 0x00,
681 		loadPatternData    = 0x01, // If unset, advise loaders to not process any pattern data (if possible)
682 		loadSampleData     = 0x02, // If unset, advise loaders to not process any sample data (if possible)
683 		loadPluginData     = 0x04, // If unset, plugin data is not loaded (and as a consequence, plugins are not instanciated).
684 		loadPluginInstance = 0x08, // If unset, plugins are not instanciated.
685 		skipContainer      = 0x10,
686 		skipModules        = 0x20,
687 
688 		// Shortcuts
689 		loadCompleteModule = loadSampleData | loadPatternData | loadPluginData | loadPluginInstance,
690 		loadNoPatternOrPluginData	= loadSampleData,
691 		loadNoPluginInstance = loadSampleData | loadPatternData | loadPluginData,
692 	};
693 
694 	#define PROBE_RECOMMENDED_SIZE 2048u
695 
696 	static constexpr std::size_t ProbeRecommendedSize = PROBE_RECOMMENDED_SIZE;
697 
698 	enum ProbeFlags
699 	{
700 		ProbeModules    = 0x1,
701 		ProbeContainers = 0x2,
702 
703 		ProbeFlagsDefault = ProbeModules | ProbeContainers,
704 		ProbeFlagsNone = 0
705 	};
706 
707 	enum ProbeResult
708 	{
709 		ProbeSuccess      =  1,
710 		ProbeFailure      =  0,
711 		ProbeWantMoreData = -1
712 	};
713 
714 	static ProbeResult ProbeAdditionalSize(MemoryFileReader &file, const uint64 *pfilesize, uint64 minimumAdditionalSize);
715 
716 	static ProbeResult Probe(ProbeFlags flags, mpt::span<const std::byte> data, const uint64 *pfilesize);
717 
718 public:
719 
720 #ifdef MODPLUG_TRACKER
721 	// Get parent CModDoc. Can be nullptr if previewing from tree view, and is always nullptr if we're not actually compiling OpenMPT.
GetpModDoc()722 	CModDoc *GetpModDoc() const noexcept { return m_pModDoc; }
723 
724 	bool Create(FileReader file, ModLoadingFlags loadFlags = loadCompleteModule, CModDoc *pModDoc = nullptr);
725 #else
726 	bool Create(FileReader file, ModLoadingFlags loadFlags);
727 #endif // MODPLUG_TRACKER
728 
729 	bool Destroy();
GetType()730 	Enum<MODTYPE> GetType() const noexcept { return m_nType; }
731 
GetContainerType()732 	MODCONTAINERTYPE GetContainerType() const noexcept { return m_ContainerType; }
733 
734 	// rough heuristic, could be improved
GetCharsetFile()735 	mpt::Charset GetCharsetFile() const // 8bit string encoding of strings in the on-disk file
736 	{
737 		return m_modFormat.charset;
738 	}
GetCharsetInternal()739 	mpt::Charset GetCharsetInternal() const // 8bit string encoding of strings internal in CSoundFile
740 	{
741 		#if defined(MODPLUG_TRACKER)
742 			return mpt::Charset::Locale;
743 		#else // MODPLUG_TRACKER
744 			return GetCharsetFile();
745 		#endif // MODPLUG_TRACKER
746 	}
747 
748 	ModMessageHeuristicOrder GetMessageHeuristic() const;
749 
750 	void SetPreAmp(uint32 vol);
GetPreAmp()751 	uint32 GetPreAmp() const noexcept { return m_MixerSettings.m_nPreAmp; }
752 
753 	void SetMixLevels(MixLevels levels);
GetMixLevels()754 	MixLevels GetMixLevels() const noexcept { return m_nMixLevels; }
GetPlayConfig()755 	const CSoundFilePlayConfig &GetPlayConfig() const noexcept { return m_PlayConfig; }
756 
GetNumInstruments()757 	constexpr INSTRUMENTINDEX GetNumInstruments() const noexcept { return m_nInstruments; }
GetNumSamples()758 	constexpr SAMPLEINDEX GetNumSamples() const noexcept { return m_nSamples; }
GetCurrentPattern()759 	constexpr PATTERNINDEX GetCurrentPattern() const noexcept { return m_PlayState.m_nPattern; }
GetCurrentOrder()760 	constexpr ORDERINDEX GetCurrentOrder() const noexcept { return m_PlayState.m_nCurrentOrder; }
GetNumChannels()761 	constexpr CHANNELINDEX GetNumChannels() const noexcept { return m_nChannels; }
762 
763 	constexpr bool CanAddMoreSamples(SAMPLEINDEX amount = 1) const noexcept { return (amount < MAX_SAMPLES) && m_nSamples < (MAX_SAMPLES - amount); }
764 	constexpr bool CanAddMoreInstruments(INSTRUMENTINDEX amount = 1) const noexcept { return (amount < MAX_INSTRUMENTS) && m_nInstruments < (MAX_INSTRUMENTS - amount); }
765 
766 #ifndef NO_PLUGINS
767 	IMixPlugin* GetInstrumentPlugin(INSTRUMENTINDEX instr) const noexcept;
768 #endif
GetModSpecifications()769 	const CModSpecifications& GetModSpecifications() const {return *m_pModSpecs;}
770 	static const CModSpecifications& GetModSpecifications(const MODTYPE type);
771 
772 	static ChannelFlags GetChannelMuteFlag();
773 
774 #ifdef MODPLUG_TRACKER
775 	void PatternTranstionChnSolo(const CHANNELINDEX chnIndex);
776 	void PatternTransitionChnUnmuteAll();
777 
778 protected:
779 	void HandlePatternTransitionEvents();
780 #endif  // MODPLUG_TRACKER
781 
782 public:
783 	double GetCurrentBPM() const;
784 	void DontLoopPattern(PATTERNINDEX nPat, ROWINDEX nRow = 0);
GetMixStat()785 	CHANNELINDEX GetMixStat() const { return m_nMixStat; }
ResetMixStat()786 	void ResetMixStat() { m_nMixStat = 0; }
787 	void ResetPlayPos();
788 	void SetCurrentOrder(ORDERINDEX nOrder);
GetTitle()789 	std::string GetTitle() const { return m_songName; }
790 	bool SetTitle(const std::string &newTitle); // Return true if title was changed.
791 	const char *GetSampleName(SAMPLEINDEX nSample) const;
792 	const char *GetInstrumentName(INSTRUMENTINDEX nInstr) const;
GetMusicSpeed()793 	uint32 GetMusicSpeed() const { return m_PlayState.m_nMusicSpeed; }
GetMusicTempo()794 	TEMPO GetMusicTempo() const { return m_PlayState.m_nMusicTempo; }
IsFirstTick()795 	constexpr bool IsFirstTick() const noexcept { return (m_PlayState.m_lTotalSampleCount == 0); }
796 
797 	// Get song duration in various cases: total length, length to specific order & row, etc.
798 	std::vector<GetLengthType> GetLength(enmGetLengthResetMode adjustMode, GetLengthTarget target = GetLengthTarget());
799 
800 public:
801 	void RecalculateSamplesPerTick();
802 	double GetRowDuration(TEMPO tempo, uint32 speed) const;
803 	uint32 GetTickDuration(PlayState &playState) const;
804 
805 	// A repeat count value of -1 means infinite loop
SetRepeatCount(int n)806 	void SetRepeatCount(int n) { m_nRepeatCount = n; }
GetRepeatCount()807 	int GetRepeatCount() const { return m_nRepeatCount; }
IsPaused()808 	bool IsPaused() const { return m_SongFlags[SONG_PAUSED | SONG_STEP]; }	// Added SONG_STEP as it seems to be desirable in most cases to check for this as well.
809 	void LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow = 0);
810 
811 	bool InitChannel(CHANNELINDEX nChn);
812 	void InitAmigaResampler();
813 
814 	void InitOPL();
SupportsOPL(MODTYPE type)815 	static constexpr bool SupportsOPL(MODTYPE type) noexcept { return type & (MOD_TYPE_S3M | MOD_TYPE_MPT); }
SupportsOPL()816 	bool SupportsOPL() const noexcept { return SupportsOPL(m_nType); }
817 
818 #if !defined(MPT_WITH_ANCIENT)
819 	static ProbeResult ProbeFileHeaderMMCMP(MemoryFileReader file, const uint64 *pfilesize);
820 	static ProbeResult ProbeFileHeaderPP20(MemoryFileReader file, const uint64 *pfilesize);
821 	static ProbeResult ProbeFileHeaderXPK(MemoryFileReader file, const uint64 *pfilesize);
822 #endif // !MPT_WITH_ANCIENT
823 	static ProbeResult ProbeFileHeaderUMX(MemoryFileReader file, const uint64* pfilesize);
824 
825 	static ProbeResult ProbeFileHeader669(MemoryFileReader file, const uint64 *pfilesize);
826 	static ProbeResult ProbeFileHeaderAM(MemoryFileReader file, const uint64 *pfilesize);
827 	static ProbeResult ProbeFileHeaderAMF_Asylum(MemoryFileReader file, const uint64 *pfilesize);
828 	static ProbeResult ProbeFileHeaderAMF_DSMI(MemoryFileReader file, const uint64 *pfilesize);
829 	static ProbeResult ProbeFileHeaderAMS(MemoryFileReader file, const uint64 *pfilesize);
830 	static ProbeResult ProbeFileHeaderAMS2(MemoryFileReader file, const uint64 *pfilesize);
831 	static ProbeResult ProbeFileHeaderC67(MemoryFileReader file, const uint64 *pfilesize);
832 	static ProbeResult ProbeFileHeaderDBM(MemoryFileReader file, const uint64 *pfilesize);
833 	static ProbeResult ProbeFileHeaderDTM(MemoryFileReader file, const uint64 *pfilesize);
834 	static ProbeResult ProbeFileHeaderDIGI(MemoryFileReader file, const uint64 *pfilesize);
835 	static ProbeResult ProbeFileHeaderDMF(MemoryFileReader file, const uint64 *pfilesize);
836 	static ProbeResult ProbeFileHeaderDSM(MemoryFileReader file, const uint64 *pfilesize);
837 	static ProbeResult ProbeFileHeaderDSym(MemoryFileReader file, const uint64 *pfilesize);
838 	static ProbeResult ProbeFileHeaderFAR(MemoryFileReader file, const uint64 *pfilesize);
839 	static ProbeResult ProbeFileHeaderFMT(MemoryFileReader file, const uint64* pfilesize);
840 	static ProbeResult ProbeFileHeaderGDM(MemoryFileReader file, const uint64 *pfilesize);
841 	static ProbeResult ProbeFileHeaderICE(MemoryFileReader file, const uint64 *pfilesize);
842 	static ProbeResult ProbeFileHeaderIMF(MemoryFileReader file, const uint64 *pfilesize);
843 	static ProbeResult ProbeFileHeaderIT(MemoryFileReader file, const uint64 *pfilesize);
844 	static ProbeResult ProbeFileHeaderITP(MemoryFileReader file, const uint64 *pfilesize);
845 	static ProbeResult ProbeFileHeaderJ2B(MemoryFileReader file, const uint64 *pfilesize);
846 	static ProbeResult ProbeFileHeaderMUS_KM(MemoryFileReader file, const uint64 *pfilesize);
847 	static ProbeResult ProbeFileHeaderM15(MemoryFileReader file, const uint64 *pfilesize);
848 	static ProbeResult ProbeFileHeaderMDL(MemoryFileReader file, const uint64 *pfilesize);
849 	static ProbeResult ProbeFileHeaderMED(MemoryFileReader file, const uint64 *pfilesize);
850 	static ProbeResult ProbeFileHeaderMO3(MemoryFileReader file, const uint64 *pfilesize);
851 	static ProbeResult ProbeFileHeaderMOD(MemoryFileReader file, const uint64 *pfilesize);
852 	static ProbeResult ProbeFileHeaderMT2(MemoryFileReader file, const uint64 *pfilesize);
853 	static ProbeResult ProbeFileHeaderMTM(MemoryFileReader file, const uint64 *pfilesize);
854 	static ProbeResult ProbeFileHeaderOKT(MemoryFileReader file, const uint64 *pfilesize);
855 	static ProbeResult ProbeFileHeaderPLM(MemoryFileReader file, const uint64 *pfilesize);
856 	static ProbeResult ProbeFileHeaderPSM(MemoryFileReader file, const uint64 *pfilesize);
857 	static ProbeResult ProbeFileHeaderPSM16(MemoryFileReader file, const uint64 *pfilesize);
858 	static ProbeResult ProbeFileHeaderPT36(MemoryFileReader file, const uint64 *pfilesize);
859 	static ProbeResult ProbeFileHeaderPTM(MemoryFileReader file, const uint64 *pfilesize);
860 	static ProbeResult ProbeFileHeaderS3M(MemoryFileReader file, const uint64 *pfilesize);
861 	static ProbeResult ProbeFileHeaderSFX(MemoryFileReader file, const uint64 *pfilesize);
862 	static ProbeResult ProbeFileHeaderSTM(MemoryFileReader file, const uint64 *pfilesize);
863 	static ProbeResult ProbeFileHeaderSTP(MemoryFileReader file, const uint64 *pfilesize);
864 	static ProbeResult ProbeFileHeaderSTX(MemoryFileReader file, const uint64 *pfilesize);
865 	static ProbeResult ProbeFileHeaderSymMOD(MemoryFileReader file, const uint64 *pfilesize);
866 	static ProbeResult ProbeFileHeaderULT(MemoryFileReader file, const uint64 *pfilesize);
867 	static ProbeResult ProbeFileHeaderXM(MemoryFileReader file, const uint64 *pfilesize);
868 
869 	static ProbeResult ProbeFileHeaderMID(MemoryFileReader file, const uint64 *pfilesize);
870 	static ProbeResult ProbeFileHeaderUAX(MemoryFileReader file, const uint64 *pfilesize);
871 	static ProbeResult ProbeFileHeaderWAV(MemoryFileReader file, const uint64 *pfilesize);
872 
873 	// Module Loaders
874 	bool Read669(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
875 	bool ReadAM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
876 	bool ReadAMF_Asylum(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
877 	bool ReadAMF_DSMI(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
878 	bool ReadAMS(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
879 	bool ReadAMS2(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
880 	bool ReadC67(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
881 	bool ReadDBM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
882 	bool ReadDTM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
883 	bool ReadDIGI(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
884 	bool ReadDMF(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
885 	bool ReadDSM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
886 	bool ReadDSym(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
887 	bool ReadFAR(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
888 	bool ReadFMT(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
889 	bool ReadGDM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
890 	bool ReadICE(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
891 	bool ReadIMF(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
892 	bool ReadIT(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
893 	bool ReadITP(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
894 	bool ReadJ2B(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
895 	bool ReadMUS_KM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
896 	bool ReadM15(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
897 	bool ReadMDL(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
898 	bool ReadMED(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
899 	bool ReadMO3(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
900 	bool ReadMOD(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
901 	bool ReadMT2(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
902 	bool ReadMTM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
903 	bool ReadOKT(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
904 	bool ReadPLM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
905 	bool ReadPSM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
906 	bool ReadPSM16(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
907 	bool ReadPT36(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
908 	bool ReadPTM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
909 	bool ReadS3M(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
910 	bool ReadSFX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
911 	bool ReadSTM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
912 	bool ReadSTP(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
913 	bool ReadSTX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
914 	bool ReadSymMOD(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
915 	bool ReadULT(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
916 	bool ReadXM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
917 
918 	bool ReadMID(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
919 	bool ReadUAX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
920 	bool ReadWAV(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
921 
922 	static std::vector<const char *> GetSupportedExtensions(bool otherFormats);
923 	static bool IsExtensionSupported(std::string_view ext); // UTF8, casing of ext is ignored
924 	static mpt::ustring ModContainerTypeToString(MODCONTAINERTYPE containertype);
925 	static mpt::ustring ModContainerTypeToTracker(MODCONTAINERTYPE containertype);
926 
927 	// Repair non-standard stuff in modules saved with previous ModPlug versions
928 	void UpgradeModule();
929 
930 	// Save Functions
931 #ifndef MODPLUG_NO_FILESAVE
932 	bool SaveXM(std::ostream &f, bool compatibilityExport = false);
933 	bool SaveS3M(std::ostream &f) const;
934 	bool SaveMod(std::ostream &f) const;
935 	bool SaveIT(std::ostream &f, const mpt::PathString &filename, bool compatibilityExport = false);
936 	uint32 SaveMixPlugins(std::ostream *file=nullptr, bool bUpdate=true);
937 	void WriteInstrumentPropertyForAllInstruments(uint32 code,  uint16 size, std::ostream &f, INSTRUMENTINDEX nInstruments) const;
938 	void SaveExtendedInstrumentProperties(INSTRUMENTINDEX nInstruments, std::ostream &f) const;
939 	void SaveExtendedSongProperties(std::ostream &f) const;
940 #endif // MODPLUG_NO_FILESAVE
941 	void LoadExtendedSongProperties(FileReader &file, bool ignoreChannelCount, bool* pInterpretMptMade = nullptr);
942 	void LoadMPTMProperties(FileReader &file, uint16 cwtv);
943 
944 	static mpt::ustring GetSchismTrackerVersion(uint16 cwtv, uint32 reserved);
945 
946 	// Reads extended instrument properties(XM/IT/MPTM).
947 	// Returns true if extended instrument properties were found.
948 	bool LoadExtendedInstrumentProperties(FileReader &file);
949 
950 	void SetDefaultPlaybackBehaviour(MODTYPE type);
951 	static PlayBehaviourSet GetSupportedPlaybackBehaviour(MODTYPE type);
952 	static PlayBehaviourSet GetDefaultPlaybackBehaviour(MODTYPE type);
953 
954 	// MOD Convert function
955 	MODTYPE GetBestSaveFormat() const;
956 	static void ConvertModCommand(ModCommand &m);
957 	static void S3MConvert(ModCommand &m, bool fromIT);
958 	void S3MSaveConvert(uint8 &command, uint8 &param, bool toIT, bool compatibilityExport = false) const;
959 	void ModSaveCommand(uint8 &command, uint8 &param, const bool toXM, const bool compatibilityExport = false) const;
960 	static void ReadMODPatternEntry(FileReader &file, ModCommand &m);
961 	static void ReadMODPatternEntry(const std::array<uint8, 4> data, ModCommand &m);
962 
963 	void SetupMODPanning(bool bForceSetup = false); // Setup LRRL panning, max channel volume
964 
965 public:
966 	// Real-time sound functions
967 	void SuspendPlugins();
968 	void ResumePlugins();
969 	void StopAllVsti();
970 	void RecalculateGainForAllPlugs();
971 	void ResetChannels();
Read(samplecount_t count,IAudioTarget & target)972 	samplecount_t Read(samplecount_t count, IAudioTarget &target) { AudioSourceNone source; return Read(count, target, source); }
973 	samplecount_t Read(
974 		samplecount_t count,
975 		IAudioTarget &target,
976 		IAudioSource &source,
977 		std::optional<std::reference_wrapper<IMonitorOutput>> outputMonitor = std::nullopt,
978 		std::optional<std::reference_wrapper<IMonitorInput>> inputMonitor = std::nullopt
979 		);
980 	samplecount_t ReadOneTick();
981 private:
982 	void CreateStereoMix(int count);
983 public:
984 	bool FadeSong(uint32 msec);
985 private:
986 	void ProcessDSP(uint32 countChunk);
987 	void ProcessPlugins(uint32 nCount);
988 	void ProcessInputChannels(IAudioSource &source, std::size_t countChunk);
989 public:
GetTotalSampleCount()990 	samplecount_t GetTotalSampleCount() const { return m_PlayState.m_lTotalSampleCount; }
HasPositionChanged()991 	bool HasPositionChanged() { bool b = m_PlayState.m_bPositionChanged; m_PlayState.m_bPositionChanged = false; return b; }
IsRenderingToDisc()992 	bool IsRenderingToDisc() const { return m_bIsRendering; }
993 
994 	void PrecomputeSampleLoops(bool updateChannels = false);
995 
996 public:
997 	// Mixer Config
998 	void SetMixerSettings(const MixerSettings &mixersettings);
999 	void SetResamplerSettings(const CResamplerSettings &resamplersettings);
1000 	void InitPlayer(bool bReset=false);
1001 	void SetDspEffects(uint32 DSPMask);
GetSampleRate()1002 	uint32 GetSampleRate() const { return m_MixerSettings.gdwMixingFreq; }
1003 #ifndef NO_EQ
1004 	void SetEQGains(const uint32 *pGains, const uint32 *pFreqs, bool bReset = false) { m_EQ.SetEQGains(pGains, pFreqs, bReset, m_MixerSettings.gdwMixingFreq); } // 0=-12dB, 32=+12dB
1005 #endif // NO_EQ
1006 public:
1007 	bool ReadNote();
1008 	bool ProcessRow();
1009 	bool ProcessEffects();
1010 	std::pair<bool, bool> NextRow(PlayState &playState, const bool breakRow) const;
1011 	void SetupNextRow(PlayState &playState, const bool patternLoop) const;
1012 	CHANNELINDEX GetNNAChannel(CHANNELINDEX nChn) const;
1013 	CHANNELINDEX CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, bool forceCut);
1014 	void NoteChange(ModChannel &chn, int note, bool bPorta = false, bool bResetEnv = true, bool bManual = false, CHANNELINDEX channelHint = CHANNELINDEX_INVALID) const;
1015 	void InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta = false, bool bUpdVol = true, bool bResetEnv = true) const;
1016 	void ApplyInstrumentPanning(ModChannel &chn, const ModInstrument *instr, const ModSample *smp) const;
1017 	uint32 CalculateXParam(PATTERNINDEX pat, ROWINDEX row, CHANNELINDEX chn, uint32 *extendedRows = nullptr) const;
1018 
1019 	// Channel Effects
1020 	void KeyOff(ModChannel &chn) const;
1021 	// Global Effects
1022 	void SetTempo(TEMPO param, bool setAsNonModcommand = false);
1023 	void SetSpeed(PlayState &playState, uint32 param) const;
1024 	static TEMPO ConvertST2Tempo(uint8 tempo);
1025 
1026 	void ProcessRamping(ModChannel &chn) const;
1027 
1028 protected:
1029 	// Global variable initializer for loader functions
1030 	void SetType(MODTYPE type);
1031 	void InitializeGlobals(MODTYPE type = MOD_TYPE_NONE);
1032 	void InitializeChannels();
1033 
1034 	// Channel effect processing
1035 	int GetVibratoDelta(int type, int position) const;
1036 
1037 	void ProcessVolumeSwing(ModChannel &chn, int &vol) const;
1038 	void ProcessPanningSwing(ModChannel &chn) const;
1039 	void ProcessTremolo(ModChannel &chn, int &vol) const;
1040 	void ProcessTremor(CHANNELINDEX nChn, int &vol);
1041 
1042 	bool IsEnvelopeProcessed(const ModChannel &chn, EnvelopeType env) const;
1043 	void ProcessVolumeEnvelope(ModChannel &chn, int &vol) const;
1044 	void ProcessPanningEnvelope(ModChannel &chn) const;
1045 	int ProcessPitchFilterEnvelope(ModChannel &chn, int32 &period) const;
1046 
1047 	void IncrementEnvelopePosition(ModChannel &chn, EnvelopeType envType) const;
1048 	void IncrementEnvelopePositions(ModChannel &chn) const;
1049 
1050 	void ProcessInstrumentFade(ModChannel &chn, int &vol) const;
1051 
1052 	static void ProcessPitchPanSeparation(int32 &pan, int note, const ModInstrument &instr);
1053 	void ProcessPanbrello(ModChannel &chn) const;
1054 
1055 	void ProcessArpeggio(CHANNELINDEX nChn, int32 &period, Tuning::NOTEINDEXTYPE &arpeggioSteps);
1056 	void ProcessVibrato(CHANNELINDEX nChn, int32 &period, Tuning::RATIOTYPE &vibratoFactor);
1057 	void ProcessSampleAutoVibrato(ModChannel &chn, int32 &period, Tuning::RATIOTYPE &vibratoFactor, int &nPeriodFrac) const;
1058 
1059 	std::pair<SamplePosition, uint32> GetChannelIncrement(const ModChannel &chn, uint32 period, int periodFrac) const;
1060 
1061 protected:
1062 	// Type of panning command
1063 	enum PanningType
1064 	{
1065 		Pan4bit = 4,
1066 		Pan6bit = 6,
1067 		Pan8bit = 8,
1068 	};
1069 	// Channel Effects
1070 	void UpdateS3MEffectMemory(ModChannel &chn, ModCommand::PARAM param) const;
1071 	void PortamentoUp(CHANNELINDEX nChn, ModCommand::PARAM param, const bool doFinePortamentoAsRegular = false);
1072 	void PortamentoDown(CHANNELINDEX nChn, ModCommand::PARAM param, const bool doFinePortamentoAsRegular = false);
1073 	void MidiPortamento(CHANNELINDEX nChn, int param, bool doFineSlides);
1074 	void FinePortamentoUp(ModChannel &chn, ModCommand::PARAM param) const;
1075 	void FinePortamentoDown(ModChannel &chn, ModCommand::PARAM param) const;
1076 	void ExtraFinePortamentoUp(ModChannel &chn, ModCommand::PARAM param) const;
1077 	void ExtraFinePortamentoDown(ModChannel &chn, ModCommand::PARAM param) const;
1078 	void PortamentoMPT(ModChannel &chn, int);
1079 	void PortamentoFineMPT(ModChannel &chn, int);
1080 	void PortamentoExtraFineMPT(ModChannel &chn, int);
1081 	void SetFinetune(CHANNELINDEX channel, PlayState &playState, bool isSmooth) const;
1082 	void NoteSlide(ModChannel &chn, uint32 param, bool slideUp, bool retrig) const;
1083 	std::pair<uint16, bool> GetVolCmdTonePorta(const ModCommand &m, uint32 startTick) const;
1084 	void TonePortamento(ModChannel &chn, uint16 param) const;
1085 	void Vibrato(ModChannel &chn, uint32 param) const;
1086 	void FineVibrato(ModChannel &chn, uint32 param) const;
1087 	void VolumeSlide(ModChannel &chn, ModCommand::PARAM param) const;
1088 	void PanningSlide(ModChannel &chn, ModCommand::PARAM param, bool memory = true) const;
1089 	void ChannelVolSlide(ModChannel &chn, ModCommand::PARAM param) const;
1090 	void FineVolumeUp(ModChannel &chn, ModCommand::PARAM param, bool volCol) const;
1091 	void FineVolumeDown(ModChannel &chn, ModCommand::PARAM param, bool volCol) const;
1092 	void Tremolo(ModChannel &chn, uint32 param) const;
1093 	void Panbrello(ModChannel &chn, uint32 param) const;
1094 	void Panning(ModChannel &chn, uint32 param, PanningType panBits) const;
1095 	void RetrigNote(CHANNELINDEX nChn, int param, int offset = 0);
1096 	void ProcessSampleOffset(ModChannel &chn, CHANNELINDEX nChn, const PlayState &playState) const;
1097 	void SampleOffset(ModChannel &chn, SmpLength param) const;
1098 	void ReverseSampleOffset(ModChannel &chn, ModCommand::PARAM param) const;
1099 	void NoteCut(CHANNELINDEX nChn, uint32 nTick, bool cutSample);
1100 	void PatternLoop(PlayState &state, ModChannel &chn, ModCommand::PARAM param) const;
1101 	bool HandleNextRow(PlayState &state, const ModSequence &order, bool honorPatternLoop) const;
1102 	void ExtendedMODCommands(CHANNELINDEX nChn, ModCommand::PARAM param);
1103 	void ExtendedS3MCommands(CHANNELINDEX nChn, ModCommand::PARAM param);
1104 	void ExtendedChannelEffect(ModChannel &chn, uint32 param);
1105 	void InvertLoop(ModChannel &chn);
1106 	void PositionJump(PlayState &state, CHANNELINDEX chn) const;
1107 	ROWINDEX PatternBreak(PlayState &state, CHANNELINDEX chn, uint8 param) const;
1108 	void GlobalVolSlide(ModCommand::PARAM param, uint8 &nOldGlobalVolSlide);
1109 
1110 	void ProcessMacroOnChannel(CHANNELINDEX nChn);
1111 	void ProcessMIDIMacro(CHANNELINDEX nChn, bool isSmooth, const char *macro, uint8 param = 0, PLUGINDEX plugin = 0);
1112 	float CalculateSmoothParamChange(float currentValue, float param) const;
1113 	uint32 SendMIDIData(CHANNELINDEX nChn, bool isSmooth, const unsigned char *macro, uint32 macroLen, PLUGINDEX plugin);
1114 	void SendMIDINote(CHANNELINDEX chn, uint16 note, uint16 volume);
1115 
1116 	int SetupChannelFilter(ModChannel &chn, bool bReset, int envModifier = 256) const;
1117 
1118 	// Low-Level effect processing
1119 	void DoFreqSlide(ModChannel &chn, int32 &period, int32 amount, bool isTonePorta = false) const;
1120 	void UpdateTimeSignature();
1121 
1122 public:
1123 	// Convert frequency to IT cutoff (0...127)
1124 	uint8 FrequencyToCutOff(double frequency) const;
1125 	// Convert IT cutoff (0...127 + modifier) to frequency
1126 	uint32 CutOffToFrequency(uint32 nCutOff, int envModifier = 256) const; // [0-127] => [1-10KHz]
1127 
1128 	// Returns true if periods are actually plain frequency values in Hz.
PeriodsAreFrequencies()1129 	bool PeriodsAreFrequencies() const noexcept
1130 	{
1131 		return m_playBehaviour[kPeriodsAreHertz] && !UseFinetuneAndTranspose();
1132 	}
1133 
1134 	// Returns true if the current format uses transpose+finetune rather than frequency in Hz to specify middle-C.
UseFinetuneAndTranspose(MODTYPE type)1135 	static constexpr bool UseFinetuneAndTranspose(MODTYPE type) noexcept
1136 	{
1137 		return (type & (MOD_TYPE_AMF0 | MOD_TYPE_DIGI | MOD_TYPE_MED | MOD_TYPE_MOD | MOD_TYPE_MTM | MOD_TYPE_OKT | MOD_TYPE_SFX | MOD_TYPE_STP | MOD_TYPE_XM));
1138 	}
UseFinetuneAndTranspose()1139 	bool UseFinetuneAndTranspose() const noexcept
1140 	{
1141 		return UseFinetuneAndTranspose(GetType());
1142 	}
1143 
1144 	bool DestroySample(SAMPLEINDEX nSample);
1145 	bool DestroySampleThreadsafe(SAMPLEINDEX nSample);
1146 
1147 	// Find an unused sample slot. If it is going to be assigned to an instrument, targetInstrument should be specified.
1148 	// SAMPLEINDEX_INVLAID is returned if no free sample slot could be found.
1149 	SAMPLEINDEX GetNextFreeSample(INSTRUMENTINDEX targetInstrument = INSTRUMENTINDEX_INVALID, SAMPLEINDEX start = 1) const;
1150 	// Find an unused instrument slot.
1151 	// INSTRUMENTINDEX_INVALID is returned if no free instrument slot could be found.
1152 	INSTRUMENTINDEX GetNextFreeInstrument(INSTRUMENTINDEX start = 1) const;
1153 	// Check whether a given sample is used by a given instrument.
1154 	bool IsSampleReferencedByInstrument(SAMPLEINDEX sample, INSTRUMENTINDEX instr) const;
1155 
1156 	ModInstrument *AllocateInstrument(INSTRUMENTINDEX instr, SAMPLEINDEX assignedSample = 0);
1157 	bool DestroyInstrument(INSTRUMENTINDEX nInstr, deleteInstrumentSamples removeSamples);
1158 	bool RemoveInstrumentSamples(INSTRUMENTINDEX nInstr, SAMPLEINDEX keepSample = SAMPLEINDEX_INVALID);
1159 	SAMPLEINDEX DetectUnusedSamples(std::vector<bool> &sampleUsed) const;
1160 	SAMPLEINDEX RemoveSelectedSamples(const std::vector<bool> &keepSamples);
1161 
1162 	// Set the autovibrato settings for all samples associated to the given instrument.
1163 	void PropagateXMAutoVibrato(INSTRUMENTINDEX ins, VibratoType type, uint8 sweep, uint8 depth, uint8 rate);
1164 
1165 	// Samples file I/O
1166 	bool ReadSampleFromFile(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false, bool includeInstrumentFormats = true);
1167 	bool ReadWAVSample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false, FileReader *wsmpChunk = nullptr);
1168 protected:
1169 	bool ReadW64Sample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false);
1170 	bool ReadPATSample(SAMPLEINDEX nSample, FileReader &file);
1171 	bool ReadS3ISample(SAMPLEINDEX nSample, FileReader &file);
1172 	bool ReadSBISample(SAMPLEINDEX sample, FileReader &file);
1173 	bool ReadCAFSample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false);
1174 	bool ReadAIFFSample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false);
1175 	bool ReadAUSample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize = false);
1176 	bool ReadXISample(SAMPLEINDEX nSample, FileReader &file);
1177 	bool ReadITSSample(SAMPLEINDEX nSample, FileReader &file, bool rewind = true);
1178 	bool ReadITISample(SAMPLEINDEX nSample, FileReader &file);
1179 	bool ReadIFFSample(SAMPLEINDEX sample, FileReader &file);
1180 	bool ReadBRRSample(SAMPLEINDEX sample, FileReader &file);
1181 	bool ReadFLACSample(SAMPLEINDEX sample, FileReader &file);
1182 	bool ReadOpusSample(SAMPLEINDEX sample, FileReader &file);
1183 	bool ReadVorbisSample(SAMPLEINDEX sample, FileReader &file);
1184 	bool ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw = false, bool mo3Decode = false);  //  raw: ignore all encoder-/decodr-delays, decode just raw frames  ;  mod3Decode: skip metadata and loop-precompute
1185 	bool ReadMediaFoundationSample(SAMPLEINDEX sample, FileReader &file, bool mo3Decode = false);  //  mod3Decode: skip metadata and loop-precompute
1186 public:
1187 #ifdef MODPLUG_TRACKER
1188 	static std::vector<FileType> GetMediaFoundationFileTypes();
1189 #endif // MODPLUG_TRACKER
1190 #ifndef MODPLUG_NO_FILESAVE
1191 	bool SaveWAVSample(SAMPLEINDEX nSample, std::ostream &f) const;
1192 	bool SaveRAWSample(SAMPLEINDEX nSample, std::ostream &f) const;
1193 	bool SaveFLACSample(SAMPLEINDEX nSample, std::ostream &f) const;
1194 	bool SaveS3ISample(SAMPLEINDEX smp, std::ostream &f) const;
1195 #endif
1196 
1197 	// Instrument file I/O
1198 	bool ReadInstrumentFromFile(INSTRUMENTINDEX nInstr, FileReader &file, bool mayNormalize = false);
1199 	bool ReadSampleAsInstrument(INSTRUMENTINDEX nInstr, FileReader &file, bool mayNormalize = false);
1200 protected:
1201 	bool ReadXIInstrument(INSTRUMENTINDEX nInstr, FileReader &file);
1202 	bool ReadITIInstrument(INSTRUMENTINDEX nInstr, FileReader &file);
1203 	bool ReadPATInstrument(INSTRUMENTINDEX nInstr, FileReader &file);
1204 	bool ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file);
1205 public:
1206 #ifndef MODPLUG_NO_FILESAVE
1207 	bool SaveXIInstrument(INSTRUMENTINDEX nInstr, std::ostream &f) const;
1208 	bool SaveITIInstrument(INSTRUMENTINDEX nInstr, std::ostream &f, const mpt::PathString &filename, bool compress, bool allowExternal) const;
1209 	bool SaveSFZInstrument(INSTRUMENTINDEX nInstr, std::ostream &f, const mpt::PathString &filename, bool useFLACsamples) const;
1210 #endif
1211 
1212 	// I/O from another sound file
1213 	bool ReadInstrumentFromSong(INSTRUMENTINDEX targetInstr, const CSoundFile &srcSong, INSTRUMENTINDEX sourceInstr);
1214 	bool ReadSampleFromSong(SAMPLEINDEX targetSample, const CSoundFile &srcSong, SAMPLEINDEX sourceSample);
1215 
1216 	// Period/Note functions
1217 	uint32 GetNoteFromPeriod(uint32 period, int32 nFineTune = 0, uint32 nC5Speed = 0) const;
1218 	uint32 GetPeriodFromNote(uint32 note, int32 nFineTune, uint32 nC5Speed) const;
1219 	uint32 GetFreqFromPeriod(uint32 period, uint32 c5speed, int32 nPeriodFrac = 0) const;
1220 	// Misc functions
GetSample(SAMPLEINDEX sample)1221 	ModSample &GetSample(SAMPLEINDEX sample) { MPT_ASSERT(sample <= m_nSamples && sample < std::size(Samples)); return Samples[sample]; }
GetSample(SAMPLEINDEX sample)1222 	const ModSample &GetSample(SAMPLEINDEX sample) const { MPT_ASSERT(sample <= m_nSamples && sample < std::size(Samples)); return Samples[sample]; }
1223 
1224 	// Resolve note/instrument combination to real sample index. Return value is guaranteed to be in [0, GetNumSamples()].
1225 	SAMPLEINDEX GetSampleIndex(ModCommand::NOTE note, uint32 instr) const noexcept;
1226 
1227 	uint32 MapMidiInstrument(uint8 program, uint16 bank, uint8 midiChannel, uint8 note, bool isXG, std::bitset<16> drumChns);
1228 	size_t ITInstrToMPT(FileReader &file, ModInstrument &ins, uint16 trkvers);
1229 	bool LoadMixPlugins(FileReader &file);
1230 #ifndef NO_PLUGINS
1231 	static void ReadMixPluginChunk(FileReader &file, SNDMIXPLUGIN &plugin);
1232 	void ProcessMidiOut(CHANNELINDEX nChn);
1233 #endif // NO_PLUGINS
1234 
1235 	void ProcessGlobalVolume(long countChunk);
1236 	void ProcessStereoSeparation(long countChunk);
1237 
1238 private:
1239 	PLUGINDEX GetChannelPlugin(CHANNELINDEX nChn, PluginMutePriority respectMutes) const;
1240 	PLUGINDEX GetActiveInstrumentPlugin(CHANNELINDEX, PluginMutePriority respectMutes) const;
1241 	IMixPlugin *GetChannelInstrumentPlugin(CHANNELINDEX chn) const;
1242 
1243 public:
1244 	PLUGINDEX GetBestPlugin(CHANNELINDEX nChn, PluginPriority priority, PluginMutePriority respectMutes) const;
1245 
1246 };
1247 
1248 
1249 #ifndef NO_PLUGINS
GetInstrumentPlugin(INSTRUMENTINDEX instr)1250 inline IMixPlugin* CSoundFile::GetInstrumentPlugin(INSTRUMENTINDEX instr) const noexcept
1251 {
1252 	if(instr > 0 && instr <= GetNumInstruments() && Instruments[instr] && Instruments[instr]->nMixPlug && Instruments[instr]->nMixPlug <= MAX_MIXPLUGINS)
1253 		return m_MixPlugins[Instruments[instr]->nMixPlug - 1].pMixPlugin;
1254 	else
1255 		return nullptr;
1256 }
1257 #endif // NO_PLUGINS
1258 
1259 
1260 ///////////////////////////////////////////////////////////
1261 // Low-level Mixing functions
1262 
1263 #define FADESONGDELAY		100
1264 
MOD2XMFineTune(int v)1265 MPT_CONSTEXPRINLINE int8 MOD2XMFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) << 4); }
XM2MODFineTune(int v)1266 MPT_CONSTEXPRINLINE int8 XM2MODFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) >> 4); }
1267 
1268 // Read instrument property with 'code' and 'size' from 'file' to instrument 'pIns'.
1269 void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const uint16 size, FileReader &file);
1270 
1271 // Read instrument property with 'code' from 'file' to instrument 'pIns'.
1272 void ReadExtendedInstrumentProperty(ModInstrument* pIns, const uint32 code, FileReader &file);
1273 
1274 // Read extended instrument properties from 'file' to instrument 'pIns'.
1275 void ReadExtendedInstrumentProperties(ModInstrument* pIns, FileReader &file);
1276 
1277 
1278 OPENMPT_NAMESPACE_END
1279