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 ¶m, bool toIT, bool compatibilityExport = false) const;
959 void ModSaveCommand(uint8 &command, uint8 ¶m, 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