1 /* 2 * Copyright (c) 2009, The MilkyTracker Team. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * - Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * - Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * - Neither the name of the <ORGANIZATION> nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * XModule.h 32 * MilkyPlay 33 * 34 * 35 */ 36 #ifndef __XMODULE_H__ 37 #define __XMODULE_H__ 38 39 #include "XMFile.h" 40 41 #define MP_MAXTEXT 32 42 #define MP_MAXORDERS 256 43 #define MP_MAXINS 255 44 #define MP_MAXINSSAMPS 96 45 46 struct TXMHeader 47 { 48 char sig[17]; 49 char name[MP_MAXTEXT]; 50 char whythis1a; 51 char tracker[MP_MAXTEXT]; 52 mp_uword ver; 53 mp_uint32 hdrsize; 54 mp_uword ordnum; 55 mp_uword restart; 56 mp_uword channum; 57 mp_uword patnum; 58 mp_uword insnum; 59 mp_uword smpnum; // additional: number of samples in tune 60 mp_uword volenvnum; // additional: number of volume envelopes 61 mp_uword panenvnum; // additional: number of panning envelopes 62 mp_uword frqenvnum; // additional: number of frequency envelopes (MDL) 63 mp_uword vibenvnum; // additional: number of vibrato envelopes (AMS) 64 mp_uword pitchenvnum; // additional: number of pitch envelopes (IT) 65 mp_uword freqtab; 66 mp_ubyte uppernotebound; // additional: note limit if not zero 67 mp_sbyte relnote; // additional: semitone adjust value 68 mp_dword flags; // additional: some flags 69 mp_uword tempo; 70 mp_uword speed; 71 mp_uword mainvol; 72 mp_ubyte ord[MP_MAXORDERS]; 73 mp_ubyte pan[256]; 74 }; 75 76 // ** BEWARE :) ** 77 // the order of the different elements concerning the envelope info 78 // is not like in the xm format 79 struct TEnvelope 80 { 81 mp_uword env[256][2]; 82 mp_ubyte num,sustain,susloope,loops,loope,type,speed; 83 }; 84 85 struct TXMInstrument 86 { 87 enum Flags 88 { 89 IF_ITNOTEREMAPPING = 0x01, 90 IF_ITFADEOUT = 0x02, 91 IF_ITENVELOPES = 0x04, 92 IF_ITGOBALINSVOL = 0x08 93 }; 94 95 mp_uint32 size; 96 char name[MP_MAXTEXT]; 97 char type; 98 mp_uword samp; 99 mp_uint32 shsize; 100 mp_sword snum[120]; // -1 is an invalid/empty sample 101 mp_uword flags; // not in .XM => from myself 102 // Also holds NNA (bit 4-5), DCT (bit 6-7), DCA (bit 8-9) 103 mp_ubyte notemap[120]; // Impulse Tracker addition 104 mp_uword volfade; // Impulse Tracker addition 105 106 mp_uword venvnum; // Impulse Tracker envelopes can't be sample-based (different envelopes can map to the same sample) ... 107 mp_uword penvnum; // ... (only when IF_ITENVELOPES flag is set) 108 mp_uword fenvnum; 109 mp_uword vibenvnum; 110 mp_uword pitchenvnum; // IT pitch envelope 111 112 mp_uword res; // when bit 3 (= 8) of flags is set, take this as global instrument vol (Impulse Tracker) 113 114 mp_ubyte ifc; // IT Initial Filter cutoff 115 mp_ubyte ifr; // IT Initial Filter resonance 116 //char extra[20]; 117 }; 118 119 // some words about the samples: 120 // although the sample buffer is freely available for acess, I would not recommend 121 // accessing it directly if you don't exactly know what you are doing because 122 // to avoid sample clicks when looping samples, it uses a tricky double buffering 123 // technique between smoothed out sample loop areas and the original sample data 124 // If you need to modify sample data yourself, use the provided methods 125 // getSampleValue and setSampleValue and call postProcessSamples when you're done 126 // modifying the sample, so the loop information is updated correctly 127 // Also call postProcessSamples when you're changing the loop information 128 struct TXMSample 129 { 130 private: 131 struct TLoopDoubleBuffProps 132 { 133 enum 134 { 135 StateUnused, 136 StateUsed, 137 StateDirty, 138 }; 139 140 mp_uint32 samplesize; 141 mp_ubyte state[4]; 142 mp_uint32 lastloopend; 143 }; 144 145 enum 146 { 147 LoopAreaBackupSize = 4, 148 LoopAreaBackupSizeMaxInBytes = 8, 149 EmptySize = 8, 150 LeadingPadding = sizeof(TLoopDoubleBuffProps) + LoopAreaBackupSizeMaxInBytes + EmptySize, 151 TrailingPadding = 16, 152 PaddingSpace = LeadingPadding+TrailingPadding 153 }; 154 155 void restoreLoopArea(); 156 157 public: 158 mp_uint32 samplen; 159 mp_uint32 loopstart; 160 mp_uint32 looplen; 161 mp_ubyte flags; // Bit 0: Use volume 162 // Bit 1: Use panning 163 // Bit 2: Use sample volume as channel global volume (.PLM modules) 164 // Bit 3: Use the res field as global sample volume 165 // Bit 4: Use IT style auto vibrato (not implemented yet) 166 mp_ubyte vol; 167 mp_sbyte finetune; 168 mp_ubyte type; // In Addition to XM: Bit 5: One shot forward looping sample (MOD backward compatibility) 169 mp_ubyte pan; 170 mp_sbyte relnote; 171 mp_uword venvnum; 172 mp_uword penvnum; 173 mp_uword fenvnum; 174 mp_uword vibenvnum; 175 mp_uword pitchenvnum; 176 mp_ubyte vibtype, vibsweep, vibdepth, vibrate; 177 mp_uword volfade; 178 mp_ubyte res; // when bit 3 (= 8) of flags is set, take this as global sample vol (Impulse Tracker) 179 mp_sword freqadjust; 180 char name[MP_MAXTEXT]; 181 mp_ubyte terminate; 182 mp_sbyte* sample; 183 getPaddedSizeTXMSample184 static mp_uint32 getPaddedSize(mp_uint32 size) 185 { 186 return size+TXMSample::PaddingSpace; 187 } 188 getPadStartAddrTXMSample189 static mp_ubyte* getPadStartAddr(mp_ubyte* mem) 190 { 191 return mem-TXMSample::LeadingPadding; 192 } 193 allocPaddedMemTXMSample194 static mp_ubyte* allocPaddedMem(mp_uint32 size) 195 { 196 mp_ubyte* result = new mp_ubyte[getPaddedSize(size)]; 197 198 if (result == NULL) 199 return NULL; 200 201 // clear out padding space 202 memset(result, 0, TXMSample::LeadingPadding); 203 memset(result+size+TXMSample::LeadingPadding, 0, TXMSample::TrailingPadding); 204 205 TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)result; 206 loopBufferProps->samplesize = size; 207 208 return result + TXMSample::LeadingPadding; 209 } 210 freePaddedMemTXMSample211 static void freePaddedMem(mp_ubyte* mem) 212 { 213 // behave safely on NULL 214 if (mem == NULL) 215 return; 216 217 delete[] getPadStartAddr(mem); 218 } 219 copyPaddedMemTXMSample220 static void copyPaddedMem(void* dst, const void* src, mp_uint32 size) 221 { 222 mp_ubyte* _src = ((mp_ubyte*)src) - TXMSample::LeadingPadding; 223 mp_ubyte* _dst = ((mp_ubyte*)dst) - TXMSample::LeadingPadding; 224 memcpy(_dst, _src, getPaddedSize(size)); 225 } 226 getSampleSizeInBytesTXMSample227 static mp_uint32 getSampleSizeInBytes(mp_ubyte* mem) 228 { 229 TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)getPadStartAddr(mem); 230 return loopBufferProps->samplesize; 231 } 232 getSampleSizeInSamplesTXMSample233 static mp_uint32 getSampleSizeInSamples(mp_ubyte* mem) 234 { 235 TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)getPadStartAddr(mem); 236 return (loopBufferProps->state[1] & 16) ? (loopBufferProps->samplesize >> 1) : loopBufferProps->samplesize; 237 } 238 239 void smoothLooping(); 240 void restoreOriginalState(); 241 void postProcessSamples(); 242 243 // get sample value 244 // values range from [-32768,32767] in case of a 16 bit sample 245 // or from [-128,127] in case of an 8 bit sample 246 mp_sint32 getSampleValue(mp_uint32 index); 247 mp_sint32 getSampleValue(mp_ubyte* sample, mp_uint32 index); 248 void setSampleValue(mp_uint32 index, mp_sint32 value); 249 void setSampleValue(mp_ubyte* sample, mp_uint32 index, mp_sint32 value); 250 251 #ifdef MILKYTRACKER equalsTXMSample252 bool equals(const TXMSample& sample) const 253 { 254 if (this->sample != sample.sample) 255 return false; 256 257 if (samplen != sample.samplen) 258 return false; 259 260 return true; 261 } 262 isMinimizableTXMSample263 bool isMinimizable() const 264 { 265 return (loopstart + looplen < samplen && (type & 3)); 266 } 267 #endif 268 269 friend class XModule; 270 }; 271 272 struct TXMPattern 273 { 274 mp_uint32 len; 275 mp_ubyte ptype; 276 mp_uword rows; 277 mp_ubyte effnum; 278 mp_ubyte channum; 279 mp_uword patdata; 280 mp_ubyte* patternData; 281 282 mp_sint32 compress(mp_ubyte* dest) const; 283 mp_sint32 decompress(mp_ubyte* src, mp_sint32 len); 284 #ifdef MILKYTRACKER 285 bool saveExtendedPattern(const SYSCHAR* fileName) const; 286 bool loadExtendedPattern(const SYSCHAR* fileName); 287 288 bool saveExtendedTrack(const SYSCHAR* fileName, mp_uint32 channel) const; 289 bool loadExtendedTrack(const SYSCHAR* fileName, mp_uint32 channel); 290 291 const TXMPattern& operator=(const TXMPattern& src); 292 #endif 293 }; 294 295 ////////////////////////////////////////////////////////////////////////// 296 // This is the class which handles a MilkyPlay module // 297 ////////////////////////////////////////////////////////////////////////// 298 class XModule 299 { 300 public: 301 enum 302 { 303 IdentificationBufferSize = 2048, 304 }; 305 306 /////////////////////////////////////////////////////// 307 // this is our loader interface (abstract class) // 308 // each loader has to conform to this interface // 309 /////////////////////////////////////////////////////// 310 class LoaderInterface 311 { 312 public: 313 // make GCC shut up ~LoaderInterface()314 virtual ~LoaderInterface() { } 315 // returns c-string which identifies the module, NULL if loader can't identify module 316 // IMPORTANT: buffer MUST contain eIdentifyBufferSize bytes of the beginning of the file 317 virtual const char* identifyModule(const mp_ubyte* buffer) = 0; 318 // try to load module (check with identifyModule first) 319 virtual mp_sint32 load(XMFileBase& f, XModule* module) = 0; 320 }; 321 322 enum ModuleTypes 323 { 324 ModuleType_UNKNOWN, 325 ModuleType_669, 326 ModuleType_AMF, 327 ModuleType_AMS, 328 ModuleType_CBA, 329 ModuleType_DBM, 330 ModuleType_DIGI, 331 ModuleType_DSM, 332 ModuleType_DSm, 333 ModuleType_DTM_1, 334 ModuleType_DTM_2, 335 ModuleType_FAR, 336 ModuleType_GDM, 337 ModuleType_GMC, 338 ModuleType_IMF, 339 ModuleType_IT, 340 ModuleType_MDL, 341 ModuleType_MOD, 342 ModuleType_MTM, 343 ModuleType_MXM, 344 ModuleType_OKT, 345 ModuleType_PLM, 346 ModuleType_PSM, 347 ModuleType_PTM, 348 ModuleType_S3M, 349 ModuleType_STM, 350 ModuleType_SFX, 351 ModuleType_UNI, 352 ModuleType_ULT, 353 ModuleType_XM, 354 ModuleType_NONE = -1, 355 }; 356 357 class SampleLoader 358 { 359 protected: 360 XMFileBase& f; 361 362 public: SampleLoader(XMFileBase & file)363 SampleLoader(XMFileBase& file) : 364 f(file) 365 { 366 } 367 ~SampleLoader()368 virtual ~SampleLoader() 369 { 370 } 371 372 virtual mp_sint32 load_sample_8bits(void* p_dest_buffer, mp_sint32 compressedSize, mp_sint32 p_buffsize) = 0; 373 virtual mp_sint32 load_sample_16bits(void* p_dest_buffer, mp_sint32 compressedSize, mp_sint32 p_buffsize) = 0; 374 }; 375 376 private: 377 struct TLoaderInfo 378 { 379 LoaderInterface* loader; 380 ModuleTypes moduleType; 381 }; 382 383 public: 384 enum 385 { 386 ST_DEFAULT = 0x00, 387 ST_DELTA = 0x01, 388 ST_UNSIGNED = 0x02, 389 ST_16BIT = 0x04, 390 ST_PACKING_MDL = 0x08, 391 ST_DELTA_PTM = 0x10, 392 ST_BIGENDIAN = 0x20, 393 ST_PACKING_IT = 0x40, 394 ST_PACKING_IT215 = 0x80, 395 ST_PACKING_ADPCM = 0x100 396 }; 397 398 static const mp_sint32 periods[12]; 399 static const mp_sint32 sfinetunes[16]; 400 static const mp_sbyte modfinetunes[16]; 401 402 static const mp_ubyte numValidXMEffects; 403 static const mp_ubyte validXMEffects[]; 404 405 ////////////////////////////////////////////////////////////////////////// 406 // different stuff for importing different module types into own format // 407 ////////////////////////////////////////////////////////////////////////// FixedMUL(mp_sint32 a,mp_sint32 b)408 static mp_sint32 FixedMUL(mp_sint32 a,mp_sint32 b) { return ((mp_sint32)(((mp_int64)(a)*(mp_int64)(b))>>16)); } 409 410 /////////////////////////////////////////////////////// 411 // convert relative note + finetune into C4 speed // 412 /////////////////////////////////////////////////////// 413 static mp_sint32 getc4spd(mp_sint32 relnote, mp_sint32 finetune); 414 /////////////////////////////////////////////////////// 415 // convert C4 speed into relative note + finetune // 416 /////////////////////////////////////////////////////// 417 static void convertc4spd(mp_uint32 c4spd, mp_sbyte* finetune, mp_sbyte* relnote); 418 419 static mp_uint32 amigaPeriodToNote(mp_uint32 period); 420 421 /////////////////////////////////////////////////////// 422 // load sample into memory // 423 /////////////////////////////////////////////////////// 424 static bool loadSample(XMFileBase& f, void* buffer, 425 mp_uint32 size, mp_uint32 length, 426 mp_sint32 flags = ST_DEFAULT); 427 428 /////////////////////////////////////////////////////// 429 // load a bunch of samples into memory // 430 /////////////////////////////////////////////////////// 431 mp_sint32 loadModuleSample(XMFileBase& f, mp_sint32 index, 432 mp_sint32 flags8 = ST_DEFAULT, mp_sint32 flags16 = ST_16BIT, 433 mp_uint32 alternateSize = 0); 434 435 mp_sint32 loadModuleSamples(XMFileBase& f, 436 mp_sint32 flags8 = ST_DEFAULT, mp_sint32 flags16 = ST_16BIT); 437 438 static void convertXMVolumeEffects(mp_ubyte volume, mp_ubyte& eff, mp_ubyte& op); 439 440 /////////////////////////////////////////////////////// 441 // Allocate sample memory and store pointer in pool // 442 // *Note* that this memory is always padded with 16 // 443 // bytes at the start *AND* 16 bytes at the end. // 444 /////////////////////////////////////////////////////// 445 mp_ubyte* allocSampleMem(mp_uint32 size); 446 447 /////////////////////////////////////////////////////// 448 // Free sample memory 449 /////////////////////////////////////////////////////// 450 void freeSampleMem(mp_ubyte* mem, bool assertCheck = true); 451 452 #ifdef MILKYTRACKER 453 void insertSamplePtr(mp_ubyte* ptr); 454 void removeSamplePtr(mp_ubyte* ptr); 455 #endif 456 457 /////////////////////////////////////////////////////// 458 // Clean up! (Is called before loading a song) // 459 /////////////////////////////////////////////////////// 460 bool cleanUp(); 461 462 /////////////////////////////////////////////////////// 463 // scan through samples and post process to avoid // 464 // interpolation clicks // 465 /////////////////////////////////////////////////////// 466 void postProcessSamples(bool heavy = false); 467 468 /////////////////////////////////////////////////////// 469 // set default panning // 470 /////////////////////////////////////////////////////// 471 void setDefaultPanning(); 472 473 private: 474 // Identify module 475 ModuleTypes type; 476 477 // Indicates whether a file is loaded or if it's just an empty song 478 bool moduleLoaded; 479 480 // each module comes with it's own sample-memory management (MILKYPLAY_MAXSAMPLES samples max.) 481 mp_ubyte* samplePool[MP_MAXSAMPLES]; 482 mp_uint32 samplePointerIndex; 483 484 // song message retrieving 485 char* messagePtr; 486 487 // subsong position table 488 mp_ubyte subSongPositions[256*2]; 489 mp_sint32 numSubSongs; 490 491 // add nother envelope to a given list and increase size of array if necessary 492 static bool addEnvelope(TEnvelope*& envs,const TEnvelope& env,mp_uint32& numEnvsAlloc,mp_uint32& numEnvs); 493 // fix broken envelopes (1 point envelope for example) 494 static void fixEnvelopes(TEnvelope* envs, mp_uint32 numEnvs); 495 496 // holds available loader instances 497 class LoaderManager 498 { 499 private: 500 TLoaderInfo* loaders; 501 502 mp_uint32 numLoaders; 503 mp_uint32 numAllocatedLoaders; 504 505 mp_sint32 iteratorCounter; 506 507 void registerLoader(LoaderInterface* loader, ModuleTypes type); 508 509 public: 510 LoaderManager(); 511 ~LoaderManager(); 512 513 TLoaderInfo* getFirstLoaderInfo(); 514 TLoaderInfo* getNextLoaderInfo(); 515 }; 516 517 friend class LoaderManager; 518 519 bool validate(); 520 521 public: 522 523 // Module flags 524 enum 525 { 526 MODULE_OLDS3MVOLSLIDES = 1, 527 MODULE_ST3NOTECUT = 2, 528 MODULE_ST3DUALCOMMANDS = 4, 529 MODULE_STMARPEGGIO = 8, 530 MODULE_XMARPEGGIO = 16, 531 MODULE_XMVOLCOLUMNVIBRATO = 32, 532 MODULE_XMNOTECLIPPING = 64, 533 MODULE_XMPORTANOTEBUFFER = 128, 534 MODULE_AMSENVELOPES = 256, 535 MODULE_PTNEWINSTRUMENT = 512, 536 MODULE_ST3NEWINSTRUMENT = 1024, 537 MODULE_OLDPTINSTRUMENTCHANGE = 2048, 538 MODULE_ITNOTEOFF = 4096, 539 MODULE_ITNEWEFFECTS = 8192, 540 MODULE_ITNEWGXX = 16384, 541 MODULE_ITLINKPORTAMEM = 32768, 542 MODULE_ITTEMPOSLIDE = 65536, 543 }; 544 545 enum 546 { 547 NOTE_LAST = 120, 548 NOTE_OFF = 121, 549 NOTE_CUT = 122, 550 NOTE_FADE = 123, 551 552 SubSongMarkEffect = 0x1E, 553 SubSongMarkOperand = 0xFF, 554 }; 555 556 TXMHeader header; // module header 557 TXMInstrument* instr; // all instruments (256 of them) 558 TXMSample* smp; // all samples (256 of them, only 255 can be used) 559 TXMPattern* phead; // all pattern headers (256 of them) 560 561 mp_uint32 messageBytesAlloc; 562 char* message; // song message 563 564 TEnvelope* venvs; 565 mp_uint32 numVEnvsAlloc; 566 mp_uint32 numVEnvs; // should be equal to header.venvnum addVolumeEnvelope(const TEnvelope & env)567 bool addVolumeEnvelope(const TEnvelope& env) { return addEnvelope(venvs, env, numVEnvsAlloc, numVEnvs); } 568 569 TEnvelope* penvs; 570 mp_uint32 numPEnvsAlloc; 571 mp_uint32 numPEnvs; // should be equal to header.penvnum addPanningEnvelope(const TEnvelope & env)572 bool addPanningEnvelope(const TEnvelope& env) { return addEnvelope(penvs, env, numPEnvsAlloc, numPEnvs); } 573 574 TEnvelope* fenvs; 575 mp_uint32 numFEnvsAlloc; 576 mp_uint32 numFEnvs; // should be equal to header.fenvnum addFrequencyEnvelope(const TEnvelope & env)577 bool addFrequencyEnvelope(const TEnvelope& env) { return addEnvelope(fenvs, env, numFEnvsAlloc, numFEnvs); } 578 579 TEnvelope* vibenvs; 580 mp_uint32 numVibEnvsAlloc; 581 mp_uint32 numVibEnvs; // should be equal to header.vibenvnum addVibratoEnvelope(TEnvelope & env)582 bool addVibratoEnvelope(TEnvelope& env) { return addEnvelope(vibenvs, env, numVibEnvsAlloc, numVibEnvs); } 583 584 TEnvelope* pitchenvs; 585 mp_uint32 numPitchEnvsAlloc; 586 mp_uint32 numPitchEnvs; // should be equal to header.vibenvnum addPitchEnvelope(TEnvelope & env)587 bool addPitchEnvelope(TEnvelope& env) { return addEnvelope(pitchenvs, env, numPitchEnvsAlloc, numPitchEnvs); } 588 589 /////////////////////////////////////////////////////// 590 // convert volume from range [0..64] to [0..255] // 591 /////////////////////////////////////////////////////// vol64to255(mp_sint32 vol)592 static mp_sint32 vol64to255(mp_sint32 vol) { return ((vol>64?64:vol)*261120+65535)>>16; } 593 594 /////////////////////////////////////////////////////// 595 // convert volume from range [0..255] to [0..64] // 596 /////////////////////////////////////////////////////// vol255to64(mp_uint32 vol)597 static mp_uint32 vol255to64(mp_uint32 vol) { return (vol*64)/255; } 598 599 /////////////////////////////////////////////////////// 600 // convert volume from range [0..127] to [0..255] // 601 /////////////////////////////////////////////////////// vol127to255(mp_sint32 vol)602 static mp_sint32 vol127to255(mp_sint32 vol) { return ((vol>127?127:vol)*131588+65535)>>16; } 603 604 /////////////////////////////////////////////////////// 605 // convert volume from range [0..128] to [0..255] // 606 /////////////////////////////////////////////////////// vol128to255(mp_sint32 vol)607 static mp_sint32 vol128to255(mp_sint32 vol) { return ((vol>128?128:vol)*130560+65535)>>16; } 608 pan15to255(mp_sint32 pan)609 static mp_sint32 pan15to255(mp_sint32 pan) { return pan>=0xF?0xFF:(pan<<4); } 610 611 /////////////////////////////////////////////////// 612 // Allocate necessary memory for song structures // 613 /////////////////////////////////////////////////// 614 XModule(); 615 616 /////////////////////////////////////////////////// 617 // Clean up // 618 /////////////////////////////////////////////////// 619 ~XModule(); 620 621 /////////////////////////////////////////////////// 622 // Get type of module // 623 /////////////////////////////////////////////////// getType()624 ModuleTypes getType() const { return type; } 625 626 /////////////////////////////////////////////////// 627 // identify module type // 628 // IMPORTANT: buffer MUST contain // 629 // eIdentifyBufferSize bytes from the beginning // 630 // of the file // 631 /////////////////////////////////////////////////// 632 static const char* identifyModule(const mp_ubyte* buffer); 633 634 /////////////////////////////////////////////////// 635 // generic module loader // 636 /////////////////////////////////////////////////// 637 mp_sint32 loadModule(XMFileBase& f, bool scanForSubSongs = false); 638 mp_sint32 loadModule(const SYSCHAR* fileName, bool scanForSubSongs = false); 639 640 /////////////////////////////////////////////////// 641 // Module exporters // 642 /////////////////////////////////////////////////// 643 mp_sint32 saveExtendedModule(const SYSCHAR* fileName); // FT2 (.XM) 644 mp_sint32 saveProtrackerModule(const SYSCHAR* fileName); // Protracker compatible (.MOD) 645 646 /////////////////////////////////////////////////// 647 // module loaded? // 648 /////////////////////////////////////////////////// isModuleLoaded()649 bool isModuleLoaded() const { return moduleLoaded; } 650 651 /////////////////////////////////////////////////// 652 // string processing // 653 /////////////////////////////////////////////////// 654 static void convertStr(char* strIn, const char* strOut, mp_sint32 nLen, bool filter = true); 655 656 void getTitle(char* str, bool filter = true) const; 657 void getSignature(char* str, bool filter = true) const; 658 void getTracker(char* str, bool filter = true) const; 659 660 /////////////////////////////////////////////////// 661 // dealing with song message // 662 /////////////////////////////////////////////////// 663 664 // allocate empty song message 665 void allocateSongMessage(mp_uint32 initialSize = 512); 666 667 // add one more line of text to the song message 668 void addSongMessageLine(const char* line); 669 670 // start iterating text lines (get size of line) 671 mp_sint32 getFirstSongMessageLineLength(); 672 // get next size text line 673 mp_sint32 getNextSongMessageLineLength(); 674 // get line 675 void getSongMessageLine(char* line); 676 677 void buildSubSongTable(); 678 getNumSubSongs()679 mp_sint32 getNumSubSongs() const { return numSubSongs; } 680 681 mp_sint32 getSubSongPosStart(mp_sint32 i) const; 682 mp_sint32 getSubSongPosEnd(mp_sint32 i) const; 683 684 /////////////////////////////////////////////////// 685 // various post processing and analyzing // 686 /////////////////////////////////////////////////// 687 // Remove stupid empty = 0xFE orders 688 void removeOrderSkips(); 689 // Remove unused patterns 690 mp_sint32 removeUnusedPatterns(bool evaluate); 691 692 // these are located in ExporterXM.cpp 693 mp_sint32 getNumUsedPatterns(); 694 mp_sint32 getNumUsedInstruments(); 695 696 // Analyse various things, for example if there is an old Protracker instrument change 697 void postLoadAnalyser(); 698 699 // MilkyTracker additions 700 void createEmptySong(bool clearPatterns = true, bool clearInstruments = true, mp_sint32 numChannels = 8); 701 702 enum IsPTCompatibleErrorCodes 703 { 704 IsPTCompatibleErrorCodeNoError = 0, 705 IsPTCompatibleErrorCodeTooManyInstruments, 706 IsPTCompatibleErrorCodeLinearFrequencyUsed, 707 IsPTCompatibleErrorCodeIncompatibleSamples, 708 IsPTCompatibleErrorCodeIncompatibleInstruments, 709 IsPTCompatibleErrorCodeIncompatiblePatterns 710 }; 711 712 IsPTCompatibleErrorCodes isPTCompatible(); 713 }; 714 715 #endif 716