00001 /*! \file 00002 * X-Forge Util <br> 00003 * Copyright 2000-2003 Fathammer Ltd 00004 * 00005 * \brief XM player. 00006 * \todo doxygen comments 00007 * \todo Panning envelope support on "key off" 00008 * \todo Random waveform support for vibrato and tremolo 00009 * \todo Set glissando control -command 00010 * 00011 * $Id: XFuXMPlayer.cpp,v 1.55 2003/10/10 11:34:51 toni Exp $ 00012 * $Date: 2003/10/10 11:34:51 $ 00013 * $Revision: 1.55 $ 00014 */ 00015 00016 #include <stdlib.h> // \ needed for 00017 #include <stdarg.h> // / va_args 00018 #include <xfcore/XFcCore.h> 00019 #include <xfcore/XFcAudioFlags.h> 00020 #include <xfcore/XFcLinkedList.h> 00021 #include <xfutil/XFuXMPlayer.h> 00022 #include <xfutil/XFuXMPlayer_internal.h> 00023 #include <xfutil/XFuXMPlayerEventHandler.h> 00024 00025 00026 const static INT32 linearFrequencyTable[768] = 00027 { 00028 535232,534749,534266,533784,533303,532822,532341,531861, 00029 531381,530902,530423,529944,529466,528988,528511,528034, 00030 527558,527082,526607,526131,525657,525183,524709,524236, 00031 523763,523290,522818,522346,521875,521404,520934,520464, 00032 519994,519525,519057,518588,518121,517653,517186,516720, 00033 516253,515788,515322,514858,514393,513929,513465,513002, 00034 512539,512077,511615,511154,510692,510232,509771,509312, 00035 508852,508393,507934,507476,507018,506561,506104,505647, 00036 505191,504735,504280,503825,503371,502917,502463,502010, 00037 501557,501104,500652,500201,499749,499298,498848,498398, 00038 497948,497499,497050,496602,496154,495706,495259,494812, 00039 494366,493920,493474,493029,492585,492140,491696,491253, 00040 490809,490367,489924,489482,489041,488600,488159,487718, 00041 487278,486839,486400,485961,485522,485084,484647,484210, 00042 483773,483336,482900,482465,482029,481595,481160,480726, 00043 480292,479859,479426,478994,478562,478130,477699,477268, 00044 476837,476407,475977,475548,475119,474690,474262,473834, 00045 473407,472979,472553,472126,471701,471275,470850,470425, 00046 470001,469577,469153,468730,468307,467884,467462,467041, 00047 466619,466198,465778,465358,464938,464518,464099,463681, 00048 463262,462844,462427,462010,461593,461177,460760,460345, 00049 459930,459515,459100,458686,458272,457859,457446,457033, 00050 456621,456209,455797,455386,454975,454565,454155,453745, 00051 453336,452927,452518,452110,451702,451294,450887,450481, 00052 450074,449668,449262,448857,448452,448048,447644,447240, 00053 446836,446433,446030,445628,445226,444824,444423,444022, 00054 443622,443221,442821,442422,442023,441624,441226,440828, 00055 440430,440033,439636,439239,438843,438447,438051,437656, 00056 437261,436867,436473,436079,435686,435293,434900,434508, 00057 434116,433724,433333,432942,432551,432161,431771,431382, 00058 430992,430604,430215,429827,429439,429052,428665,428278, 00059 427892,427506,427120,426735,426350,425965,425581,425197, 00060 424813,424430,424047,423665,423283,422901,422519,422138, 00061 421757,421377,420997,420617,420237,419858,419479,419101, 00062 418723,418345,417968,417591,417214,416838,416462,416086, 00063 415711,415336,414961,414586,414212,413839,413465,413092, 00064 412720,412347,411975,411604,411232,410862,410491,410121, 00065 409751,409381,409012,408643,408274,407906,407538,407170, 00066 406803,406436,406069,405703,405337,404971,404606,404241, 00067 403876,403512,403148,402784,402421,402058,401695,401333, 00068 400970,400609,400247,399886,399525,399165,398805,398445, 00069 398086,397727,397368,397009,396651,396293,395936,395579, 00070 395222,394865,394509,394153,393798,393442,393087,392733, 00071 392378,392024,391671,391317,390964,390612,390259,389907, 00072 389556,389204,388853,388502,388152,387802,387452,387102, 00073 386753,386404,386056,385707,385359,385012,384664,384317, 00074 383971,383624,383278,382932,382587,382242,381897,381552, 00075 381208,380864,380521,380177,379834,379492,379149,378807, 00076 378466,378124,377783,377442,377102,376762,376422,376082, 00077 375743,375404,375065,374727,374389,374051,373714,373377, 00078 373040,372703,372367,372031,371695,371360,371025,370690, 00079 370356,370022,369688,369355,369021,368688,368356,368023, 00080 367691,367360,367028,366697,366366,366036,365706,365376, 00081 365046,364717,364388,364059,363731,363403,363075,362747, 00082 362420,362093,361766,361440,361114,360788,360463,360137, 00083 359813,359488,359164,358840,358516,358193,357869,357547, 00084 357224,356902,356580,356258,355937,355616,355295,354974, 00085 354654,354334,354014,353695,353376,353057,352739,352420, 00086 352103,351785,351468,351150,350834,350517,350201,349885, 00087 349569,349254,348939,348624,348310,347995,347682,347368, 00088 347055,346741,346429,346116,345804,345492,345180,344869, 00089 344558,344247,343936,343626,343316,343006,342697,342388, 00090 342079,341770,341462,341154,340846,340539,340231,339924, 00091 339618,339311,339005,338700,338394,338089,337784,337479, 00092 337175,336870,336566,336263,335959,335656,335354,335051, 00093 334749,334447,334145,333844,333542,333242,332941,332641, 00094 332341,332041,331741,331442,331143,330844,330546,330247, 00095 329950,329652,329355,329057,328761,328464,328168,327872, 00096 327576,327280,326985,326690,326395,326101,325807,325513, 00097 325219,324926,324633,324340,324047,323755,323463,323171, 00098 322879,322588,322297,322006,321716,321426,321136,320846, 00099 320557,320267,319978,319690,319401,319113,318825,318538, 00100 318250,317963,317676,317390,317103,316817,316532,316246, 00101 315961,315676,315391,315106,314822,314538,314254,313971, 00102 313688,313405,313122,312839,312557,312275,311994,311712, 00103 311431,311150,310869,310589,310309,310029,309749,309470, 00104 309190,308911,308633,308354,308076,307798,307521,307243, 00105 306966,306689,306412,306136,305860,305584,305308,305033, 00106 304758,304483,304208,303934,303659,303385,303112,302838, 00107 302565,302292,302019,301747,301475,301203,300931,300660, 00108 300388,300117,299847,299576,299306,299036,298766,298497, 00109 298227,297958,297689,297421,297153,296884,296617,296349, 00110 296082,295815,295548,295281,295015,294749,294483,294217, 00111 293952,293686,293421,293157,292892,292628,292364,292100, 00112 291837,291574,291311,291048,290785,290523,290261,289999, 00113 289737,289476,289215,288954,288693,288433,288173,287913, 00114 287653,287393,287134,286875,286616,286358,286099,285841, 00115 285583,285326,285068,284811,284554,284298,284041,283785, 00116 283529,283273,283017,282762,282507,282252,281998,281743, 00117 281489,281235,280981,280728,280475,280222,279969,279716, 00118 279464,279212,278960,278708,278457,278206,277955,277704, 00119 277453,277203,276953,276703,276453,276204,275955,275706, 00120 275457,275209,274960,274712,274465,274217,273970,273722, 00121 273476,273229,272982,272736,272490,272244,271999,271753, 00122 271508,271263,271018,270774,270530,270286,270042,269798, 00123 269555,269312,269069,268826,268583,268341,268099,267857 00124 }; 00125 00126 00127 #define ABS(x) (((x) < 0) ? -(x) : (x)) 00128 00129 #define interpolateLinear8(ch, val1, val2) \ 00130 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00131 \ 00132 if ((ch.mPointer + FP_VALUE) < ch.mLength) \ 00133 val2 = *((INT8 *)ch.mOffset + ((ch.mPointer + FP_VALUE) >> FP_BITS)); \ 00134 else \ 00135 val2 = 0; 00136 00137 00138 #define interpolateLinear16(ch, val1, val2) \ 00139 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00140 \ 00141 if ((ch.mPointer + FP_VALUE) < ch.mLength) \ 00142 val2 = *((INT16 *)ch.mOffset + ((ch.mPointer + FP_VALUE) >> FP_BITS)); \ 00143 else \ 00144 val2 = 0; 00145 00146 00147 #define interpolateLinearForwardLoop8(ch, val1, val2, temp) \ 00148 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00149 \ 00150 temp = (ch.mPointer + FP_VALUE); \ 00151 if ((temp >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00152 temp = ch.mLoopStart + (temp - (ch.mLoopEnd + FP_VALUE)); \ 00153 \ 00154 val2 = *((INT8 *)ch.mOffset + (temp >> FP_BITS)); 00155 00156 00157 #define interpolateLinearForwardLoop16(ch, val1, val2, temp) \ 00158 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00159 \ 00160 temp = (ch.mPointer + FP_VALUE); \ 00161 if ((temp >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00162 temp = ch.mLoopStart + (temp - (ch.mLoopEnd + FP_VALUE)); \ 00163 \ 00164 val2 = *((INT16 *)ch.mOffset + (temp >> FP_BITS)); 00165 00166 00167 #define interpolateLinearBidirectionalLoop8(ch, val1, val2, temp) \ 00168 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00169 \ 00170 temp = (ch.mPointer + FP_VALUE); \ 00171 if ((temp >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00172 temp = ch.mLoopEnd - (temp - (ch.mLoopEnd + FP_VALUE)); \ 00173 \ 00174 val2 = *((INT8 *)ch.mOffset + (temp >> FP_BITS)); \ 00175 00176 00177 #define interpolateLinearBidirectionalLoop16(ch, val1, val2, temp) \ 00178 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); \ 00179 \ 00180 temp = (ch.mPointer + FP_VALUE); \ 00181 if ((temp >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00182 temp = ch.mLoopEnd - (temp - (ch.mLoopEnd + FP_VALUE)); \ 00183 \ 00184 val2 = *((INT16 *)ch.mOffset + (temp >> FP_BITS)); 00185 00186 00187 #define addPointer(ch) \ 00188 ch.mPointer += ch.mSpeed; \ 00189 if (ch.mPointer > (ch.mLength - FP_VALUE)) \ 00190 ch.mIsSample = 0; 00191 00192 00193 #define addPointerForwardLoop(ch) \ 00194 ch.mPointer += ch.mSpeed; \ 00195 if ((ch.mPointer >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00196 ch.mPointer = ch.mLoopStart + (ch.mPointer - (ch.mLoopEnd + FP_VALUE)); 00197 00198 00199 #define addPointerBidirectionalLoop(ch) \ 00200 if (ch.mDirection == 1) \ 00201 { \ 00202 ch.mPointer += ch.mSpeed; \ 00203 \ 00204 if ((ch.mPointer >> FP_BITS) > (ch.mLoopEnd >> FP_BITS)) \ 00205 { \ 00206 ch.mDirection = -1; \ 00207 ch.mPointer = ch.mLoopEnd - (ch.mPointer - (ch.mLoopEnd + FP_VALUE)); \ 00208 } \ 00209 } \ 00210 else \ 00211 { \ 00212 ch.mPointer -= ch.mSpeed; \ 00213 \ 00214 if ((ch.mPointer >> FP_BITS) < (ch.mLoopStart >> FP_BITS)) \ 00215 { \ 00216 ch.mDirection = 1; \ 00217 ch.mPointer = ch.mLoopStart + (ch.mLoopStart - ch.mPointer); \ 00218 } \ 00219 } 00220 00221 00222 //#define OUTPUT_XM_INFO 00223 00224 #ifdef OUTPUT_XM_INFO 00225 static const CHAR *notes[12] = 00226 {"C-","C#","D-","D#","E-","F-","F#","G-","G#","A-","A#","B-"}; 00227 #endif // OUTPUT_XM_INFO 00228 00229 00230 void XFuXMPlayer::debugPrint(XFcFile *aTextout, CHAR *aFmt, ...) 00231 { 00232 #if !defined(XFC_PLATFORM_EPOC) && !defined(XFC_PLATFORM_PALM) 00233 if (aTextout != NULL) 00234 { 00235 va_list ap; 00236 static CHAR buffer[10240]; 00237 va_start(ap, aFmt); 00238 vsprintf(buffer, aFmt, ap); 00239 aTextout->write(buffer, 1, XFcStringToolkit::getLength(buffer)); 00240 va_end(ap); 00241 } 00242 #endif // XFC_PLATFORM_EPOC 00243 } 00244 00245 00246 void XFuXMPlayer::dumpSongParameters(XFcFile *aTextout) 00247 { 00248 INT i = 0, x; 00249 00250 debugPrint(aTextout, "\n\nParameters for current mSong. \n\n"); 00251 debugPrint(aTextout, "song length: %d\n", mSong.mSongLength); 00252 debugPrint(aTextout, "song restart: %d\n", mSong.mRestartPosition); 00253 debugPrint(aTextout, "order: "); 00254 00255 for (i = 0; i < mSong.mSongLength; i++) 00256 debugPrint(aTextout, "%d ", mSong.mOrderTable[i]); 00257 00258 debugPrint(aTextout, "\n"); 00259 debugPrint(aTextout, "nof patterns: %d\n", mSong.mNbPatterns); 00260 debugPrint(aTextout, "nof channels: %d\n", mSong.mNbChannels); 00261 debugPrint(aTextout, "nof instrument: %d\n", mSong.mNbInstruments); 00262 debugPrint(aTextout, "tempo: %d\n", mSong.mTempo); 00263 debugPrint(aTextout, "bpm: %d\n", mSong.mBpm); 00264 debugPrint(aTextout, "\nmInstruments: \n"); 00265 00266 for (i = 0; i < mSong.mNbInstruments; i++) 00267 { 00268 XFuXMInstrument &ins = mInstruments[i]; 00269 00270 debugPrint(aTextout, "\ninstr %02X \n", i); 00271 00272 debugPrint(aTextout, "is vibrato? %d \n", ins.mIsVibrato); 00273 debugPrint(aTextout, "vibratoType: %d \n", ins.mVibratoType); 00274 debugPrint(aTextout, "vibratoSweep: %d \n", ins.mVibratoSweep); 00275 debugPrint(aTextout, "vibratoDepth: %d \n", ins.mVibratoDepth); 00276 debugPrint(aTextout, "vibratoRate: %d \n", ins.mVibratoRate); 00277 00278 debugPrint(aTextout, "\nvolume envelope: \n"); 00279 debugPrint(aTextout, " fadeout: %d \n", ins.mVolumeFadeout); 00280 debugPrint(aTextout, " end point: %d\n", ins.mVolEnvEnd); 00281 debugPrint(aTextout, " type: %d\n", ins.mVolEnvType); 00282 debugPrint(aTextout, " on? %d\n", (ins.mVolEnvType & ENVELOPE_ON)); 00283 debugPrint(aTextout, " sustain? %d\n", 00284 (ins.mVolEnvType & ENVELOPE_SUSTAIN)); 00285 debugPrint(aTextout, " sustain point: %d\n", (ins.mVolEnvSustain)); 00286 debugPrint(aTextout, " loop? %d\n", (ins.mVolEnvType & ENVELOPE_LOOP)); 00287 debugPrint(aTextout, " loop start: %d\n", ins.mVolEnvLoopStart); 00288 debugPrint(aTextout, " loop end: %d\n", ins.mVolEnvLoopEnd); 00289 debugPrint(aTextout, " envelope: "); 00290 00291 for (x = 0; x < ins.mVolEnvEnd; x++) 00292 debugPrint(aTextout,"%2.2f ", ins.mVolumeEnvelope[x]); 00293 00294 debugPrint(aTextout, "\n"); 00295 debugPrint(aTextout, "\npanning envelope: \n"); 00296 debugPrint(aTextout, " on? %d\n", (ins.mPanEnvType & ENVELOPE_ON)); 00297 debugPrint(aTextout, " loop? %d\n", (ins.mPanEnvType & ENVELOPE_LOOP)); 00298 debugPrint(aTextout, " loop start: %d\n", ins.mPanEnvLoopStart); 00299 debugPrint(aTextout, " loop end: %d\n", ins.mPanEnvLoopEnd); 00300 debugPrint(aTextout, " envelope: "); 00301 00302 for (x = 0; x < ins.mPanEnvEnd; x++) 00303 debugPrint(aTextout, "%d ", ins.mPanningEnvelope[x]); 00304 00305 debugPrint(aTextout,"\n-----\n"); 00306 } 00307 } 00308 00309 00310 INT XFuXMPlayer::loadXM(const CHAR *aFilename, XFcFile *aTextout) 00311 { 00312 XFcFile *f; 00313 00314 INT i, j, k, ii; 00315 FLOAT32 y1, y2, dx; 00316 INT xx, x1, x2; 00317 00318 XFuXMFormatInstrumentHeader xmInstrumentHeader; 00319 XFuXMFormatInstrument xmInstrument; 00320 XFuXMFormatSample xmSample; 00321 00322 debugPrint(aTextout, "Fathammer XM-player debug file.\n"); 00323 debugPrint(aTextout, "Opening %s.\n", aFilename); 00324 00325 f = XFcFile::open(aFilename, "rb"); 00326 if (f == 0) { 00327 debugPrint(aTextout, "error opening file.\n"); 00328 if (aTextout != NULL) aTextout->close(); 00329 return 1; 00330 } 00331 00332 debugPrint(aTextout, "opened.\n"); 00333 00334 debugPrint(aTextout, "reading header...\n\n"); 00335 f->read(mXMHeader.mIdString, 17, sizeof(UINT8)); 00336 mXMHeader.mIdString[17] = 0; 00337 00338 // Check id string 00339 INT wrongId = XFcStringToolkit::compare((const CHAR *)mXMHeader.mIdString, "Extended Module: "); 00340 if (wrongId) return 1; 00341 00342 f->read(mXMHeader.mModuleName, 20, sizeof(UINT8)); 00343 mXMHeader.mModuleName[20] = 0; 00344 00345 // Check $1A byte 00346 f->readUINT8(mXMHeader.mH1A); 00347 if (mXMHeader.mH1A != 0x1A) return 1; 00348 00349 f->read(mXMHeader.mTrackerName, 20, sizeof(UINT8)); 00350 mXMHeader.mTrackerName[20] = 0; 00351 00352 f->readUINT16(mXMHeader.mVersion); 00353 00354 f->readUINT32(mXMHeader.mHeaderSize); 00355 00356 f->readUINT16(mXMHeader.mSongLength); 00357 f->readUINT16(mXMHeader.mRestartPosition); 00358 f->readUINT16(mXMHeader.mNbChannels); 00359 f->readUINT16(mXMHeader.mNbPatterns); 00360 f->readUINT16(mXMHeader.mNbInstruments); 00361 00362 f->readUINT16(mXMHeader.mFlags); 00363 00364 f->readUINT16(mXMHeader.mTempo); 00365 f->readUINT16(mXMHeader.mBpm); 00366 00367 f->read(mXMHeader.mOrderTable, 256, sizeof(UINT8)); 00368 00369 debugPrint(aTextout, "id string: %s\n", mXMHeader.mIdString); 00370 debugPrint(aTextout, "module name: %s\n", mXMHeader.mModuleName); 00371 debugPrint(aTextout, "h1A: %d\n", mXMHeader.mH1A); 00372 debugPrint(aTextout, "tracker name: %s\n", mXMHeader.mTrackerName); 00373 debugPrint(aTextout, "tracker version: %d\n", mXMHeader.mVersion); 00374 debugPrint(aTextout, "header size: %d\n", mXMHeader.mHeaderSize); 00375 debugPrint(aTextout, "song length: %d\n", mXMHeader.mSongLength); 00376 debugPrint(aTextout, "restart pos: %d\n", mXMHeader.mRestartPosition); 00377 debugPrint(aTextout, "nof mChannels: %d\n", mXMHeader.mNbChannels); 00378 debugPrint(aTextout, "nof patterns: %d\n", mXMHeader.mNbPatterns); 00379 debugPrint(aTextout, "nof instrument: %d\n", mXMHeader.mNbInstruments); 00380 debugPrint(aTextout, "flags: %d\n", mXMHeader.mFlags); 00381 debugPrint(aTextout, "tempo: %d\n", mXMHeader.mTempo); 00382 debugPrint(aTextout, "bpm: %d\n", mXMHeader.mBpm); 00383 debugPrint(aTextout, "ordertable: \n"); 00384 00385 // Allocate memory for order list 00386 mSong.mOrderTable = new UINT8[mXMHeader.mSongLength]; 00387 memset(mSong.mOrderTable, 0, mXMHeader.mSongLength * sizeof(UINT8)); 00388 00389 for (i = 0; i < mXMHeader.mSongLength; i++) 00390 { 00391 debugPrint(aTextout, "%2X->%2X\n", i, mXMHeader.mOrderTable[i]); 00392 mSong.mOrderTable[i] = mXMHeader.mOrderTable[i]; 00393 } 00394 00395 // Save song header 00396 mSong.mNbChannels = mXMHeader.mNbChannels; 00397 mSong.mNbPatterns = mXMHeader.mNbPatterns; 00398 mSong.mNbInstruments = mXMHeader.mNbInstruments; 00399 mSong.mSongLength = mXMHeader.mSongLength; 00400 mSong.mRestartPosition = mXMHeader.mRestartPosition; 00401 mSong.mBpm = mXMHeader.mBpm; 00402 mSong.mTempo = mXMHeader.mTempo; 00403 00404 // Allocate memory for mChannels 00405 mChannels = new XFuXMChannel[mSong.mNbChannels]; 00406 memset(mChannels, 0, mSong.mNbChannels * sizeof(XFuXMChannel)); 00407 00408 // Read pattern headers and pattern data 00409 debugPrint(aTextout, "\npatterns:\n\n"); 00410 00411 // Allocate memory for pattern headers 00412 mXMPatternHeaders = new XFuXMFormatPatternHeader[mXMHeader.mNbPatterns]; 00413 memset(mXMPatternHeaders, 0, mXMHeader.mNbPatterns * sizeof(XFuXMFormatPatternHeader)); 00414 00415 // Allocate memory for pattern data blocks 00416 mPatternData = new XFuXMPattern[mXMHeader.mNbPatterns]; 00417 memset(mPatternData, 0, mXMHeader.mNbPatterns * sizeof(XFuXMPattern)); 00418 00419 for (i = 0; i < mXMHeader.mNbPatterns; i++) 00420 { 00421 debugPrint(aTextout, "pattern %d \n", i); 00422 00423 f->readUINT32(mXMPatternHeaders[i].mHeaderLength); 00424 f->readUINT8(mXMPatternHeaders[i].mPackingType); 00425 f->readUINT16(mXMPatternHeaders[i].mNbRows); 00426 f->readUINT16(mXMPatternHeaders[i].mSize); 00427 00428 debugPrint(aTextout, "header length: %d \n", mXMPatternHeaders[i].mHeaderLength); 00429 debugPrint(aTextout, "packing type: %d \n", mXMPatternHeaders[i].mPackingType); 00430 debugPrint(aTextout, "nof rows: %d \n", mXMPatternHeaders[i].mNbRows); 00431 debugPrint(aTextout, "size: %d \n\n", mXMPatternHeaders[i].mSize); 00432 00433 if (mXMPatternHeaders[i].mSize > 0) 00434 { 00435 // Allocate memory for actual pattern data 00436 mPatternData[i].mData = new UINT8[mXMPatternHeaders[i].mSize]; 00437 mPatternData[i].mRows = new UINT32[mXMPatternHeaders[i].mNbRows]; 00438 f->read(mPatternData[i].mData, mXMPatternHeaders[i].mSize, 1); 00439 00440 UINT8 b = 0; 00441 UINT32 p = 0; 00442 for (j = 0; j < mXMPatternHeaders[i].mNbRows; j++) 00443 { 00444 mPatternData[i].mRows[j] = p; 00445 00446 for (k = 0; k < mSong.mNbChannels; k++) 00447 { 00448 b = *(mPatternData[i].mData + p++); 00449 00450 if ((b & 128) == 128) { 00451 // Packed atom 00452 if ((b & 1) == 1) p++; 00453 if ((b & 2) == 2) p++; 00454 if ((b & 4) == 4) p++; 00455 if ((b & 8) == 8) p++; 00456 if ((b & 16) == 16) p++; 00457 } 00458 else 00459 { 00460 // Normal atom 00461 p += 4; 00462 } 00463 } 00464 } 00465 } 00466 } 00467 00468 // Allocate memory for mInstruments 00469 mInstruments = new XFuXMInstrument[mXMHeader.mNbInstruments]; 00470 memset(mInstruments, 0, mXMHeader.mNbInstruments * sizeof(XFuXMInstrument)); 00471 00472 // Read mInstruments 00473 debugPrint(aTextout, "mInstruments \n\n"); 00474 for (i = 0; i < mXMHeader.mNbInstruments; i++) 00475 { 00476 debugPrint(aTextout, "instrument %02x \n", i); 00477 00478 XFuXMInstrument &ins = mInstruments[i]; 00479 00480 memset(&xmInstrumentHeader, 0, sizeof(XFuXMFormatInstrumentHeader)); 00481 00482 f->readUINT32(xmInstrumentHeader.mSize); 00483 00484 f->read(xmInstrumentHeader.mInstrumentName, 22, sizeof(UINT8)); 00485 xmInstrumentHeader.mInstrumentName[22] = 0; 00486 00487 f->readUINT8(xmInstrumentHeader.mType); 00488 f->readUINT16(xmInstrumentHeader.mNbSamples); 00489 00490 ins.mNbSamples = xmInstrumentHeader.mNbSamples; 00491 00492 debugPrint(aTextout, "size: %d \n", xmInstrumentHeader.mSize); 00493 debugPrint(aTextout, "name: %s \n", xmInstrumentHeader.mInstrumentName); 00494 debugPrint(aTextout, "type: %d \n", xmInstrumentHeader.mType); 00495 debugPrint(aTextout, "nof samples: %d \n", 00496 xmInstrumentHeader.mNbSamples); 00497 00498 // sizeof(xmInstrumentHeader) could return an ALIGNED value 00499 INT32 skip = xmInstrumentHeader.mSize - 29; 00500 00501 if (xmInstrumentHeader.mNbSamples > 0) 00502 { 00503 memset(&xmInstrument, 0, sizeof(XFuXMFormatInstrument)); 00504 00505 f->readUINT32(xmInstrument.mSampleHeaderSize); 00506 f->read(xmInstrument.mKeyboard, 96, sizeof(UINT8)); 00507 f->read(xmInstrument.mVolumeEnvelope, 24, sizeof(UINT16)); 00508 f->read(xmInstrument.mPanningEnvelope, 24, sizeof(UINT16)); 00509 f->readUINT8(xmInstrument.mNbVolEnvPoints); 00510 f->readUINT8(xmInstrument.mNbPanEnvPoints); 00511 f->readUINT8(xmInstrument.mVolEnvSustain); 00512 f->readUINT8(xmInstrument.mVolEnvLoopStart); 00513 f->readUINT8(xmInstrument.mVolEnvLoopEnd); 00514 f->readUINT8(xmInstrument.mPanEnvSustain); 00515 f->readUINT8(xmInstrument.mPanEnvLoopStart); 00516 f->readUINT8(xmInstrument.mPanEnvLoopEnd); 00517 f->readUINT8(xmInstrument.mVolEnvType); 00518 f->readUINT8(xmInstrument.mPanEnvType); 00519 00520 f->readUINT8(xmInstrument.mVibratoType); 00521 f->readUINT8(xmInstrument.mVibratoSweep); 00522 f->readUINT8(xmInstrument.mVibratoDepth); 00523 f->readUINT8(xmInstrument.mVibratoRate); 00524 00525 f->readUINT16(xmInstrument.mVolumeFadeout); 00526 00527 f->readUINT16(xmInstrument.mReserved); 00528 00529 // sizeof(xmInstrument) could return an ALIGNED value 00530 skip -= 214; 00531 f->seek(skip, SEEK_CUR); 00532 00533 // Allocate memory for samples in instrument 00534 ins.mSamples = new XFuXMSample[xmInstrumentHeader.mNbSamples]; 00535 memset(ins.mSamples, 0, xmInstrumentHeader.mNbSamples * sizeof(XFuXMSample)); 00536 00537 for (j = 0; j < xmInstrumentHeader.mNbSamples; j++) 00538 { 00539 XFuXMSample &smp = ins.mSamples[j]; 00540 00541 memset(&xmSample, 0, sizeof(XFuXMFormatSample)); 00542 00543 f->readUINT32(xmSample.mSampleLength); 00544 f->readUINT32(xmSample.mLoopStart); 00545 f->readUINT32(xmSample.mLoopLength); 00546 f->readUINT8(xmSample.mVolume); 00547 f->readINT8(xmSample.mFinetune); 00548 f->readUINT8(xmSample.mType); 00549 f->readUINT8(xmSample.mPan); 00550 f->readINT8(xmSample.mRelativeNote); 00551 f->readUINT8(xmSample.mReserved); 00552 00553 f->read(xmSample.mSampleName, 22, sizeof(UINT8)); 00554 xmSample.mSampleName[22] = 0; 00555 00556 debugPrint(aTextout, "Allocating %d bytes for sample %02X in " 00557 "instrument %02X\n", xmSample.mSampleLength, j, i); 00558 debugPrint(aTextout, "sample length %d \n", xmSample.mSampleLength); 00559 debugPrint(aTextout, "loop start %d \n", xmSample.mLoopStart); 00560 debugPrint(aTextout, "loop length %d \n", xmSample.mLoopLength); 00561 debugPrint(aTextout, "volume %d \n", xmSample.mVolume); 00562 debugPrint(aTextout, "finetune %d \n", xmSample.mFinetune); 00563 debugPrint(aTextout, "type %d \n", xmSample.mType); 00564 debugPrint(aTextout, " loop fwd? %d\n", (xmSample.mType & LOOP_FORWARD) ? 1 : 0); 00565 debugPrint(aTextout, " loop pingpong? %d\n", 00566 (xmSample.mType & LOOP_PINGPONG) ? 1 : 0); 00567 debugPrint(aTextout, " 16 bit? %d\n", 00568 (xmSample.mType & XMFORMAT_SAMPLE_16BIT) ? 1 : 0); 00569 debugPrint(aTextout, "pan %d \n", xmSample.mPan); 00570 debugPrint(aTextout, "relative note %d \n", xmSample.mRelativeNote); 00571 debugPrint(aTextout, "sample name %s \n", xmSample.mSampleName); 00572 00573 smp.mSize = xmSample.mSampleLength; 00574 smp.mVolume = xmSample.mVolume; 00575 smp.mPan = xmSample.mPan; 00576 smp.mLoopForward = (UINT8)((xmSample.mType & LOOP_FORWARD) ? 1 : 0); 00577 smp.mLoopPingpong = (UINT8)((xmSample.mType & LOOP_PINGPONG) ? 1 : 0); 00578 smp.m16Bit = (UINT8)((xmSample.mType & XMFORMAT_SAMPLE_16BIT) ? 1 : 0); 00579 smp.mLoopStart = xmSample.mLoopStart; 00580 smp.mLoopEnd = xmSample.mLoopStart + xmSample.mLoopLength - 1; 00581 00582 if (smp.mLoopStart == smp.mLoopEnd) 00583 { 00584 smp.mLoopPingpong = 0; 00585 smp.mLoopForward = 0; 00586 } 00587 00588 smp.mRelativeNote = xmSample.mRelativeNote; 00589 smp.mFinetune = xmSample.mFinetune; 00590 } 00591 00592 // Read samples 00593 for (j = 0; j < xmInstrumentHeader.mNbSamples; j++) 00594 { 00595 XFuXMSample &smp = ins.mSamples[j]; 00596 00597 if (smp.mSize > 0) 00598 { 00599 smp.mOffset = new INT8[smp.mSize]; 00600 memset((INT8 *)smp.mOffset, 0, smp.mSize * sizeof(INT8)); 00601 00602 if (smp.mOffset == NULL) 00603 { 00604 debugPrint(aTextout, "! Memory allocation for sample " 00605 "%02X in instrument %02X failed \n", j, i); 00606 return 1; 00607 } 00608 00609 debugPrint(aTextout, "Reading sample \n"); 00610 f->read((INT8 *)smp.mOffset, smp.mSize, 1); 00611 00612 if (smp.m16Bit) 00613 { 00614 INT16 os, ns; 00615 INT16 *temp = (INT16 *)smp.mOffset; 00616 os = 0; 00617 00618 smp.mSize >>= 1; 00619 smp.mLoopStart >>= 1; 00620 smp.mLoopEnd >>= 1; 00621 00622 if (mFlags & XFCAUDIO_16BIT) 00623 { 00624 UINT32 a; 00625 for (a = 0; a < smp.mSize; ++a) 00626 { 00627 ns = (INT16)(os + *(temp + a)); 00628 *((INT16 *)smp.mOffset + a) = ns; 00629 os = ns; 00630 } 00631 } 00632 else 00633 { 00634 UINT32 a; 00635 for (a = 0; a < smp.mSize; ++a) 00636 { 00637 ns = (INT16)(os + *(temp + a)); 00638 *((INT8 *)smp.mOffset + a) = (INT8)(ns >> 8); 00639 os = ns; 00640 } 00641 00642 smp.m16Bit = 0; 00643 00644 INT8 *temp = new INT8[smp.mSize]; 00645 memcpy(temp, smp.mOffset, smp.mSize); 00646 delete[] (INT8 *)smp.mOffset; 00647 smp.mOffset = temp; 00648 } 00649 } 00650 else 00651 { 00652 INT8 os, ns; 00653 os = 0; 00654 UINT32 a; 00655 for (a = 0; a < smp.mSize; a++) 00656 { 00657 ns = (INT8)(os + *((INT8 *)smp.mOffset + a)); 00658 *((INT8 *)smp.mOffset + a) = ns; 00659 os = ns; 00660 } 00661 } 00662 } 00663 } 00664 00665 ins.mVolumeFadeout = REALf(xmInstrument.mVolumeFadeout / 65536.0f); 00666 00667 if (xmInstrument.mVibratoRate) 00668 ins.mIsVibrato = 1; 00669 else 00670 ins.mIsVibrato = 0; 00671 00672 ins.mVibratoType = xmInstrument.mVibratoType; 00673 ins.mVibratoSweep = xmInstrument.mVibratoSweep; 00674 ins.mVibratoDepth = xmInstrument.mVibratoDepth; 00675 ins.mVibratoRate = xmInstrument.mVibratoRate; 00676 00677 debugPrint(aTextout, "sampleheader size: %d \n", xmInstrument.mSampleHeaderSize); 00678 00679 debugPrint(aTextout, "keyboard: "); 00680 00681 for (ii = 0; ii < 96; ii++) 00682 { 00683 debugPrint(aTextout, "%d, ", xmInstrument.mKeyboard[ii]); 00684 if (((ii + 1) % 20) == 0) 00685 debugPrint(aTextout, "\n "); 00686 } 00687 00688 memcpy(ins.mKeyboard, xmInstrument.mKeyboard, 96); 00689 00690 debugPrint(aTextout, "\n"); 00691 debugPrint(aTextout, "volume. envelope: "); 00692 00693 // if (xmInstrument.mVolEnvType & ENVELOPE_LOOP) 00694 // xmInstrument.mNbVolEnvPoints = 00695 // xmInstrument.mVolEnvLoopEnd + 1; 00696 00697 for (ii = 0; ii < xmInstrument.mNbVolEnvPoints * 2; ii++) 00698 { 00699 debugPrint(aTextout, "%d, ", xmInstrument.mVolumeEnvelope[ii]); 00700 00701 if (((ii + 1) % 20) == 0) 00702 debugPrint(aTextout, "\n "); 00703 } 00704 00705 debugPrint(aTextout, "\n"); 00706 debugPrint(aTextout, "pan. envelope: "); 00707 00708 // if (xmInstrument.mPanEnvType & ENVELOPE_LOOP) 00709 // xmInstrument.mNbPanEnvPoints = 00710 // xmInstrument.mPanEnvLoopEnd + 1; 00711 00712 for (ii = 0; ii < xmInstrument.mNbPanEnvPoints * 2; ii++) 00713 { 00714 debugPrint(aTextout, "%d, ", xmInstrument.mPanningEnvelope[ii]); 00715 00716 if (((ii + 1) % 20) == 0) 00717 debugPrint(aTextout, "\n "); 00718 } 00719 00720 // Volume envelope 00721 ins.mVolEnvType = xmInstrument.mVolEnvType; 00722 00723 if (xmInstrument.mVolEnvLoopStart != xmInstrument.mVolEnvLoopEnd) 00724 { 00725 ins.mVolEnvLoopStart = xmInstrument.mVolumeEnvelope[ 00726 xmInstrument.mVolEnvLoopStart * 2]; 00727 ins.mVolEnvLoopEnd = xmInstrument.mVolumeEnvelope[ 00728 xmInstrument.mVolEnvLoopEnd * 2]; 00729 } 00730 memset(ins.mVolumeEnvelope, 0, XMFORMAT_SIZEOF_ENVELOPE); 00731 00732 if (xmInstrument.mNbVolEnvPoints == 1) 00733 { 00734 // Volume envelope fix for trackers that don't follow FT2 standard 00735 ins.mVolumeEnvelope[0] = REALf(xmInstrument.mVolumeEnvelope[1] / 64.0f); 00736 } 00737 else 00738 { 00739 for (ii = 0; ii < xmInstrument.mNbVolEnvPoints - 1; ii++) 00740 { 00741 x1 = xmInstrument.mVolumeEnvelope[(ii * 2)]; 00742 y1 = xmInstrument.mVolumeEnvelope[(ii * 2) + 1]; 00743 x2 = xmInstrument.mVolumeEnvelope[((ii + 1) * 2)]; 00744 y2 = xmInstrument.mVolumeEnvelope[((ii + 1) * 2) + 1]; 00745 00746 dx = (y2 - y1) / (x2 - x1); 00747 00748 for (xx = x1; xx <= x2; xx++) 00749 { 00750 ins.mVolumeEnvelope[xx] = REALf(y1 / 64.0f); 00751 y1 += dx; 00752 } 00753 } 00754 } 00755 00756 if (xmInstrument.mVolEnvType & ENVELOPE_SUSTAIN) 00757 ins.mVolEnvSustain = xmInstrument.mVolumeEnvelope[ 00758 xmInstrument.mVolEnvSustain * 2]; 00759 00760 if (xmInstrument.mNbVolEnvPoints > 0) 00761 ins.mVolEnvEnd = xmInstrument.mVolumeEnvelope[ 00762 (xmInstrument.mNbVolEnvPoints - 1) * 2]; 00763 00764 // Panning envelope 00765 ins.mPanEnvType = xmInstrument.mPanEnvType; 00766 00767 if (xmInstrument.mPanEnvLoopStart != xmInstrument.mPanEnvLoopEnd) 00768 { 00769 ins.mPanEnvLoopStart = xmInstrument.mPanningEnvelope[ 00770 xmInstrument.mPanEnvLoopStart * 2]; 00771 ins.mPanEnvLoopEnd = xmInstrument.mPanningEnvelope[ 00772 xmInstrument.mPanEnvLoopEnd * 2]; 00773 } 00774 memset(ins.mPanningEnvelope, 0, XMFORMAT_SIZEOF_ENVELOPE); 00775 00776 if (xmInstrument.mNbPanEnvPoints == 1) 00777 { 00778 // Panning envelope fix for trackers that don't follow FT2 standard 00779 ins.mPanningEnvelope[0] = (UINT8)xmInstrument.mPanningEnvelope[1]; 00780 } 00781 else 00782 { 00783 for (ii = 0; ii < xmInstrument.mNbPanEnvPoints - 1; ii++) 00784 { 00785 x1 = xmInstrument.mPanningEnvelope[(ii * 2)]; 00786 y1 = xmInstrument.mPanningEnvelope[(ii * 2) + 1]; 00787 x2 = xmInstrument.mPanningEnvelope[((ii + 1) * 2)]; 00788 y2 = xmInstrument.mPanningEnvelope[((ii + 1) * 2) + 1]; 00789 00790 dx = (y2 - y1) / (x2 - x1); 00791 00792 for (xx = x1; xx < x2; xx++) 00793 { 00794 ins.mPanningEnvelope[xx] = (UINT8)((INT8)y1); 00795 y1 += dx; 00796 } 00797 } 00798 } 00799 00800 ins.mPanEnvSustain = xmInstrument.mPanningEnvelope[ 00801 xmInstrument.mPanEnvSustain * 2]; 00802 00803 if (xmInstrument.mNbPanEnvPoints > 0) 00804 ins.mPanEnvEnd = xmInstrument.mPanningEnvelope[ 00805 (xmInstrument.mNbPanEnvPoints - 1) * 2]; 00806 00807 debugPrint(aTextout, "\n"); 00808 00809 debugPrint(aTextout, "nof volpoints %d\n", 00810 xmInstrument.mNbVolEnvPoints); 00811 debugPrint(aTextout, "nof panpoints %d\n", 00812 xmInstrument.mNbPanEnvPoints); 00813 debugPrint(aTextout, "volume. sustain %d\n", 00814 xmInstrument.mVolEnvSustain); 00815 debugPrint(aTextout, "volume. loop start %d\n", 00816 xmInstrument.mVolEnvLoopStart); 00817 debugPrint(aTextout, "volume. loop end %d\n", 00818 xmInstrument.mVolEnvLoopEnd); 00819 debugPrint(aTextout, "pan. sustain %d\n", 00820 xmInstrument.mPanEnvSustain); 00821 debugPrint(aTextout, "pan. loop start %d\n", 00822 xmInstrument.mPanEnvLoopStart); 00823 debugPrint(aTextout, "pan. loop end %d\n", 00824 xmInstrument.mPanEnvLoopEnd); 00825 debugPrint(aTextout, "volume. type %d\n", xmInstrument.mVolEnvType); 00826 debugPrint(aTextout, " env. on? %d\n", 00827 (xmInstrument.mVolEnvType & ENVELOPE_ON) ? 1 : 0); 00828 debugPrint(aTextout, " env. sustain? %d\n", 00829 (xmInstrument.mVolEnvType & ENVELOPE_SUSTAIN) ? 1 : 0); 00830 debugPrint(aTextout, " env. loop? %d \n", 00831 (xmInstrument.mVolEnvType & ENVELOPE_LOOP) ? 1 : 0); 00832 debugPrint(aTextout, "pan. type %d\n", 00833 xmInstrument.mPanEnvType); 00834 00835 debugPrint(aTextout, " env. on? %d\n", 00836 (xmInstrument.mPanEnvType & ENVELOPE_ON) ? 1 : 0); 00837 debugPrint(aTextout, " env. sustain? %d\n", 00838 (xmInstrument.mPanEnvType & ENVELOPE_SUSTAIN) ? 1 : 0); 00839 debugPrint(aTextout, " env. loop? %d \n", 00840 (xmInstrument.mPanEnvType & ENVELOPE_LOOP) ? 1 : 0); 00841 00842 debugPrint(aTextout, "vibr. type %d \n", 00843 xmInstrument.mVibratoType); 00844 debugPrint(aTextout, "vibr. sweep %d \n", 00845 xmInstrument.mVibratoSweep); 00846 debugPrint(aTextout, "vibr. depth %d \n", 00847 xmInstrument.mVibratoDepth); 00848 debugPrint(aTextout, "vibr. rate %d \n", 00849 xmInstrument.mVibratoRate); 00850 debugPrint(aTextout, "volume. fadeout %d \n\n", 00851 xmInstrument.mVolumeFadeout); 00852 } 00853 else 00854 { 00855 f->seek(skip, SEEK_CUR); 00856 } 00857 00858 debugPrint(aTextout, "-----\n\n"); 00859 } 00860 00861 mSong.mNbInstruments = mXMHeader.mNbInstruments; 00862 00863 debugPrint(aTextout, "XM read. \n"); 00864 debugPrint(aTextout, "Not changing pattern structure yet.. \n"); 00865 00866 f->close(); 00867 00868 return 0; 00869 } 00870 00871 00872 UINT32 XFuXMPlayer::getPeriod(INT8 aNote, INT8 aFinetune) 00873 { 00874 if (aNote < 0) aNote = 0; 00875 if (aNote > 96) aNote = 96; 00876 00877 return (7680 - (aNote << 6) - (aFinetune >> 1)); 00878 } 00879 00880 00881 UINT32 XFuXMPlayer::getSpeed(UINT32 aPeriod, FLOAT32 aSamplingRate) 00882 { 00883 INT32 freq; 00884 INT32 shift = (INT32)(aPeriod / 768); 00885 00886 if (shift >= 0) 00887 freq = linearFrequencyTable[aPeriod - (shift << 9) - (shift << 8)] >> shift; 00888 //return linearFrequencyTable[aPeriod % 768] >> shift; 00889 else 00890 freq = linearFrequencyTable[aPeriod - (shift << 9) - (shift << 8)] << (-shift); 00891 //return linearFrequencyTable[aPeriod % 768] << (-shift); 00892 00893 /* 00894 FLOAT32 freq = (FLOAT32)(8363.0f * pow(2.0f, (4608.f - (FLOAT32)period) / 768.0f)); 00895 */ 00896 00897 return (INT32)((freq / aSamplingRate) * FP_VALUE); 00898 } 00899 00900 00901 XFuXMFormatAtom XFuXMPlayer::getAtom() 00902 { 00903 UINT8 *XMFORMAT_pa = mPatternData[mPatternNb].mData; 00904 XFuXMFormatAtom ta; 00905 UINT8 b; 00906 ta.mNote = 0; 00907 ta.mVolume = 0; 00908 ta.mInstrumentNb = 0; 00909 ta.mEffectType = 0; 00910 ta.mEffectValue = 0; 00911 00912 b = *(XMFORMAT_pa + mPpoint++); 00913 if (b & 0x80) 00914 { 00915 // Packed atom 00916 if (b & 0x1) 00917 ta.mNote = *(XMFORMAT_pa + mPpoint++); 00918 if (b & 0x2) 00919 ta.mInstrumentNb = *(XMFORMAT_pa + mPpoint++); 00920 if (b & 0x4) 00921 ta.mVolume = *(XMFORMAT_pa + mPpoint++); 00922 if (b & 0x8) 00923 ta.mEffectType = *(XMFORMAT_pa + mPpoint++); 00924 if (b & 0x10) 00925 ta.mEffectValue = *(XMFORMAT_pa + mPpoint++); 00926 } 00927 else 00928 { 00929 // Normal atom 00930 ta.mNote = b; 00931 ta.mInstrumentNb = *(XMFORMAT_pa + mPpoint++); 00932 ta.mVolume = *(XMFORMAT_pa + mPpoint++); 00933 ta.mEffectType = *(XMFORMAT_pa + mPpoint++); 00934 ta.mEffectValue = *(XMFORMAT_pa + mPpoint++); 00935 } 00936 00937 return ta; 00938 } 00939 00940 00941 void XFuXMPlayer::initChannel(XFuXMChannel &aCh) 00942 { 00943 aCh.mIsValid = 1; 00944 aCh.mInitSample = 0; 00945 00946 // Initialize sample if valid note 00947 if ((aCh.mTa.mNote > 0) && (aCh.mTa.mNote < 97)) 00948 { 00949 aCh.mNote = (INT8)(aCh.mTa.mNote - 1); 00950 aCh.mInitSample = 1; 00951 00952 aCh.mTremorTicker = 0; 00953 aCh.mMultiRetrigTicker = 0; 00954 } 00955 else if (aCh.mTa.mNote != 0) 00956 aCh.mIsValid = 0; 00957 00958 aCh.mVolumeColumn = aCh.mTa.mVolume; 00959 00960 if (aCh.mTa.mInstrumentNb != 0) 00961 { 00962 // New instrument 00963 aCh.mInstrumentNb = (INT16)(aCh.mTa.mInstrumentNb - 1); 00964 00965 if (aCh.mInstrumentNb < mSong.mNbInstruments) 00966 { 00967 aCh.mCurrentInstrument = mInstruments[aCh.mInstrumentNb]; 00968 00969 if (aCh.mCurrentInstrument.mKeyboard[aCh.mNote] < aCh.mCurrentInstrument.mNbSamples) 00970 { 00971 if (aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]].mOffset != NULL) 00972 { 00973 aCh.mCurrentSample = aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]]; 00974 } 00975 else aCh.mIsValid = 0; 00976 } 00977 else aCh.mIsValid = 0; 00978 } 00979 else aCh.mIsValid = 0; 00980 00981 aCh.mVolume = aCh.mCurrentSample.mVolume; 00982 aCh.mBaseVolume = aCh.mVolume; 00983 00984 aCh.mPan = aCh.mCurrentSample.mPan; 00985 } 00986 else 00987 { 00988 if ((aCh.mInstrumentNb != -1) && (aCh.mInstrumentNb < mSong.mNbInstruments)) 00989 { 00990 aCh.mCurrentInstrument = mInstruments[aCh.mInstrumentNb]; 00991 00992 if (aCh.mCurrentInstrument.mKeyboard[aCh.mNote] < aCh.mCurrentInstrument.mNbSamples) 00993 { 00994 if (aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]].mOffset != NULL) 00995 { 00996 aCh.mCurrentSample = aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]]; 00997 } 00998 else aCh.mIsValid = 0; 00999 } 01000 else aCh.mIsValid = 0; 01001 } 01002 else aCh.mIsValid = 0; 01003 } 01004 01005 aCh.mOldPeriod = aCh.mPeriod; 01006 01007 // Do not initialize sound if note delay or pattern delay effect on 01008 if ((aCh.mInitSample) || (mPatternDelayCounter != 0)) 01009 initSound(aCh); 01010 } 01011 01012 01013 void XFuXMPlayer::initSound(XFuXMChannel &aCh) 01014 { 01015 if (aCh.mIsValid) 01016 { 01017 // Initialize sample 01018 if (aCh.mInitSample) aCh.mIsSample = 1; 01019 01020 // New note 01021 aCh.mDirection = 1; 01022 01023 // Init vibrato 01024 /* Instrument vibrato is independent 01025 aCh.mIsVibrato = aCh.mCurrentInstrument.mIsVibrato; 01026 if (aCh.mCurrentInstrument.mVibratoDepth != 0) 01027 aCh.mVibratoDepth = aCh.mCurrentInstrument.mVibratoDepth; 01028 if (aCh.mCurrentInstrument.mVibratoRate != 0) 01029 aCh.mVibratoRate = aCh.mCurrentInstrument.mVibratoRate; 01030 */ 01031 aCh.mIsVibrato = 0; 01032 01033 if ((aCh.mVibratoWaveform & WAVEFORM_NO_RETRIG) == 0) aCh.mVibratoPointer = 0; 01034 if ((aCh.mTremoloWaveform & WAVEFORM_NO_RETRIG) == 0) aCh.mTremoloPointer = 0; 01035 01036 // Init volume envelope 01037 aCh.mVolEnvType = aCh.mCurrentInstrument.mVolEnvType; 01038 aCh.mVolEnvPointer = 0; 01039 aCh.mVolEnvSpeed = 1; 01040 aCh.mVolEnvLoopStart = aCh.mCurrentInstrument.mVolEnvLoopStart; 01041 aCh.mVolEnvLoopEnd = aCh.mCurrentInstrument.mVolEnvLoopEnd; 01042 aCh.mVolEnvSustain = aCh.mCurrentInstrument.mVolEnvSustain; 01043 01044 aCh.mVolumeFadeout = aCh.mCurrentInstrument.mVolumeFadeout; 01045 aCh.mVolumeFadeoutValue = REAL(1); 01046 01047 // Init panning envelope 01048 aCh.mPanEnvType = aCh.mCurrentInstrument.mPanEnvType; 01049 aCh.mPanEnvPointer = 0; 01050 aCh.mPanEnvSpeed = 1; 01051 aCh.mPanEnvLoopStart = aCh.mCurrentInstrument.mPanEnvLoopStart; 01052 aCh.mPanEnvLoopEnd = aCh.mCurrentInstrument.mPanEnvLoopEnd; 01053 aCh.mPanEnvSustain = aCh.mCurrentInstrument.mPanEnvSustain; 01054 01055 aCh.mSustainReleased = 0; 01056 01057 aCh.mOffset = aCh.mCurrentSample.mOffset; 01058 aCh.mFinetune = aCh.mCurrentSample.mFinetune; 01059 01060 if ((aCh.mEffectType != 0x3) && // No tone portamento 01061 (aCh.mEffectType != 0x5) && // No tone portamento + volume slide 01062 (aCh.mVolumeColumn < 0xF0)) // No volume column tone portamento 01063 aCh.mPointer = 0; // Reset pointer if no tone effect 01064 01065 aCh.mLength = (aCh.mCurrentSample.mSize << FP_BITS); 01066 aCh.mPeriod = getPeriod((INT8)(aCh.mNote + aCh.mCurrentSample.mRelativeNote), aCh.mFinetune); 01067 aCh.mBasePeriod = aCh.mPeriod; 01068 01069 aCh.mLoop = 0; 01070 if (aCh.mCurrentSample.mLoopForward) aCh.mLoop = LOOP_FORWARD; 01071 if (aCh.mCurrentSample.mLoopPingpong) aCh.mLoop = LOOP_PINGPONG; 01072 aCh.mLoopStart = (aCh.mCurrentSample.mLoopStart << FP_BITS); 01073 aCh.mLoopEnd = (aCh.mCurrentSample.mLoopEnd << FP_BITS); 01074 } 01075 else 01076 aCh.mIsSample = 0; 01077 } 01078 01079 01080 void XFuXMPlayer::notifyHandlers(XFuXMChannel &aCh) 01081 { 01082 XFuXMPlayerEvent event; 01083 01084 event.mNote = aCh.mNote; 01085 event.mInstrumentNb = aCh.mInstrumentNb; 01086 event.mVolume = aCh.mVolume; 01087 01088 if ((aCh.mEffectType != 0xE) && (aCh.mEffectType != 0x21)) 01089 { 01090 event.mEffectType = aCh.mEffectType; 01091 event.mEffectValue = aCh.mEffectValue; 01092 } 01093 else 01094 { 01095 event.mEffectType = (INT16)((aCh.mEffectType << 4) | (aCh.mEffectValue >> 4)); 01096 event.mEffectValue = (INT16)(aCh.mEffectValue & 0xF); 01097 } 01098 01099 event.mPlayer = this; 01100 01101 XFcLinkedList<XFuXMPlayerEventHandlerSlot>::forwardIterator i; 01102 XFuXMPlayerEventHandlerSlot temp; 01103 01104 for (i = mEventHandlers->forwardBegin(); i != mEventHandlers->forwardEnd(); ++i) 01105 { 01106 temp = i.getData(); 01107 01108 if (((temp.mEvent.mNote != -1) && (temp.mEvent.mNote == event.mNote)) || 01109 ((temp.mEvent.mInstrumentNb != -1) && (temp.mEvent.mInstrumentNb == event.mInstrumentNb)) || 01110 ((temp.mEvent.mEffectType != -1) && (temp.mEvent.mEffectType == event.mEffectType))) 01111 { 01112 temp.mHandler->handleXMPlayerEvent(event); 01113 } 01114 } 01115 } 01116 01117 01118 void XFuXMPlayer::initSong(INT16 aStartOrder) 01119 { 01120 INT i; 01121 01122 if ((aStartOrder < 0) || (aStartOrder >= mSong.mSongLength)) aStartOrder = 0; 01123 mCurrentOrder = (INT16)(aStartOrder - 1); 01124 01125 mPatternNb = mSong.mOrderTable[aStartOrder]; 01126 if (mPatternNb >= mSong.mNbPatterns) mPatternNb = mSong.mOrderTable[0]; 01127 01128 mCurrentRow = 1024; 01129 01130 mPatternDelayCounter = 0; 01131 mPatternDelayCounterTemp = 0; 01132 mPatternDelaySkip = 0; 01133 mJumpFlag = 0; 01134 mIsRead = 1; 01135 01136 mTickRate = (2.0f * mSong.mBpm / 5.0f); 01137 01138 mSamplesPerTick = (INT32)(mSamplingRate / mTickRate); 01139 01140 mCurrentTick = (UINT8)(mSong.mTempo - 1); // Playing starts from last tick 01141 mSamplePointer = mSamplesPerTick; // Playing starts from last sample of last tick 01142 01143 mTotalTicks = 0; 01144 01145 mSong.mGlobalVolume = 64; 01146 01147 for (i = 0; i < mSong.mNbChannels; i++) 01148 { 01149 XFuXMChannel &ch = mChannels[i]; 01150 01151 ch.mOffset = NULL; 01152 ch.mPointer = 0; 01153 ch.mLength = 0; 01154 ch.mInstrumentNb = -1; 01155 ch.mSpeed = 0; 01156 ch.mPeriod = 0; 01157 01158 ch.mLoop = 0; 01159 ch.mLoopStart = 0; 01160 ch.mLoopEnd = 0; 01161 01162 ch.mIsSample = 0; 01163 01164 ch.mVolume = 0; 01165 ch.mBaseVolume = 0; 01166 ch.mFinalOldVolume = 0; 01167 ch.mFinalVolumeSpeed = 0; 01168 01169 ch.mNote = 0; 01170 01171 ch.mDirection = 1; 01172 01173 ch.mVolEnvType = 0; 01174 ch.mVolEnvPointer = 0; 01175 ch.mVolEnvSpeed = 0; 01176 ch.mVolEnvLoopStart = 0; 01177 ch.mVolEnvLoopEnd = 0; 01178 ch.mVolEnvSustain = 0; 01179 ch.mVolEnvValue = 0; 01180 01181 ch.mPanEnvType = 0; 01182 ch.mPanEnvPointer = 0; 01183 ch.mPanEnvSpeed = 0; 01184 ch.mPanEnvLoopStart = 0; 01185 ch.mPanEnvLoopEnd = 0; 01186 ch.mPanEnvSustain = 0; 01187 ch.mPanEnvValue = 0; 01188 01189 ch.mVolumeFadeout = 0; 01190 ch.mVolumeFadeoutValue = 0; 01191 01192 ch.mSustainReleased = 0; 01193 01194 ch.mVolumeColumn = 0; 01195 01196 ch.mEffectType = 0; 01197 ch.mEffectValue = 0; 01198 ch.mTonePortamentoV = 0; 01199 ch.mVolumeSlideV = 0; 01200 ch.mGlobalVolumeSlideV = 0; 01201 ch.mFineVolumeSlideUpV = 0; 01202 ch.mFineVolumeSlideDownV = 0; 01203 ch.mFinePortamentoUpV = 0; 01204 ch.mFinePortamentoDownV = 0; 01205 ch.mFineVolumeSlideUpV = 0; 01206 ch.mFineVolumeSlideDownV = 0; 01207 ch.mGlobalVolumeSlideV = 0; 01208 ch.mMultiRetrigVolumeV = 0; 01209 ch.mMultiRetrigRateV = 0; 01210 ch.mTremorV = 0; 01211 ch.mExtraFinePortamentoUpV = 0; 01212 ch.mExtraFinePortamentoDownV = 0; 01213 01214 ch.mMultiRetrigTicker = 0; 01215 ch.mTremorTicker = 0; 01216 01217 ch.mPeriod = 0; 01218 ch.mBasePeriod = 0; 01219 ch.mOldPeriod = 0; 01220 ch.mDestPeriod = 0; 01221 01222 ch.mIsVibrato = 0; 01223 ch.mVibratoDepth = 0; 01224 ch.mVibratoRate = 0; 01225 ch.mVibratoPointer = 0; 01226 ch.mVibratoWaveform = WAVEFORM_SINEWAVE; 01227 01228 ch.mTremoloDepth = 0; 01229 ch.mTremoloRate = 0; 01230 ch.mTremoloPointer = 0; 01231 ch.mTremoloWaveform = WAVEFORM_SINEWAVE; 01232 } 01233 } 01234 01235 01236 INT32 XFuXMPlayer::getTick() 01237 { 01238 return (INT32)((mTotalTicks * 1000) / mSamplingRate); 01239 } 01240 01241 01242 INT16 XFuXMPlayer::getCurrentOrder() 01243 { 01244 return mCurrentOrder; 01245 } 01246 01247 01248 void XFuXMPlayer::addHandler(XFuXMPlayerEvent aEvent, XFuXMPlayerEventHandler *aHandler) 01249 { 01250 if (aHandler != NULL) 01251 { 01252 XFuXMPlayerEventHandlerSlot temp; 01253 temp.mEvent = aEvent; 01254 temp.mHandler = aHandler; 01255 01256 mEventHandlers->addLast(temp); 01257 } 01258 } 01259 01260 01261 INT XFuXMPlayer::removeHandler(XFuXMPlayerEventHandler *aHandler) 01262 { 01263 if (aHandler != NULL) 01264 { 01265 XFuXMPlayerEventHandlerSlot temp; 01266 temp.mHandler = aHandler; 01267 01268 return mEventHandlers->remove(temp); 01269 } 01270 01271 return 0; 01272 } 01273 01274 01275 void XFuXMPlayer::removeHandlers() 01276 { 01277 XFcLinkedList<XFuXMPlayerEventHandlerSlot>::forwardIterator i = mEventHandlers->forwardBegin(); 01278 XFuXMPlayerEventHandlerSlot temp; 01279 01280 while (i.isValid()) 01281 { 01282 mEventHandlers->remove(i); 01283 } 01284 } 01285 01286 01287 void XFuXMPlayer::stop() 01288 { 01289 initSong(0); 01290 } 01291 01292 // For MSVC 01293 #pragma warning(disable:4244) 01294 01295 UINT32 XFuXMPlayer::stream(void *aBuffer, INT32 aTargetSamples, INT32 aOffset, 01296 INT32 aSamples) 01297 { 01298 INT32 cLeft, cRight; 01299 01300 INT32 chan; 01301 01302 INT32 index; 01303 INT32 targetOffset = aOffset; 01304 INT32 counter; 01305 INT32 indicesLeft; 01306 INT32 ticksLeft; 01307 INT32 samplesToRender; 01308 01309 INT32 delta; 01310 INT32 val1, val2; 01311 INT32 value; 01312 INT32 temp; 01313 01314 XFuXMFormatAtom ta; 01315 INT16 *vibratoTable = mSineWaveTable; 01316 INT16 *tremoloTable = mSineWaveTable; 01317 01318 for (index = 0; index < aSamples; ) 01319 { 01320 if (mSamplePointer == mSamplesPerTick) 01321 { 01322 // Tick finished 01323 mSamplePointer = 0; 01324 01325 mRamp = 0; 01326 01327 if (mIsRead && (++mCurrentTick == mSong.mTempo)) 01328 { 01329 // Row finished 01330 mCurrentTick = 0; 01331 01332 if (mPatternDelayCounter == 0) 01333 { 01334 mCurrentRow++; 01335 mPatternDelaySkip = 0; 01336 } 01337 else 01338 mPatternDelayCounter--; 01339 01340 if ((mCurrentRow >= mXMPatternHeaders[mPatternNb].mNbRows) || (mJumpFlag != 0)) 01341 { 01342 // Pattern finished 01343 mCurrentOrder++; 01344 if (mCurrentOrder >= mSong.mSongLength) mCurrentOrder = mSong.mRestartPosition; 01345 01346 mPatternNb = mSong.mOrderTable[mCurrentOrder]; 01347 if (mPatternNb >= mSong.mNbPatterns) mPatternNb = mSong.mOrderTable[0]; 01348 01349 if (mJumpFlag == 0) mCurrentRow = 0; 01350 01351 mJumpFlag = 0; 01352 } 01353 01354 mPpoint = mPatternData[mPatternNb].mRows[mCurrentRow]; 01355 01356 for (chan = 0; chan < mSong.mNbChannels; chan++) 01357 { 01358 XFuXMChannel &ch = mChannels[chan]; 01359 01360 if (mPatternDelayCounter == 0) 01361 { 01362 ta = getAtom(); // Get track data 01363 01364 ch.mTa = ta; 01365 01366 ch.mEffectType = ta.mEffectType; 01367 ch.mEffectValue = ta.mEffectValue; 01368 01369 if (!((ch.mEffectType == 0xE) && 01370 // No change if note delay effect 01371 (((ch.mEffectValue >> 4) & 0xF) == 0xD))) 01372 { 01373 initChannel(ch); 01374 } 01375 } 01376 01377 // Volume column effects 01378 if (ch.mVolumeColumn != 0) 01379 { 01380 // Set volume 01381 if ((ch.mVolumeColumn >= 0x10) && (ch.mVolumeColumn <= 0x50)) 01382 { 01383 ch.mVolume = (INT8)(ch.mVolumeColumn - 0x10); 01384 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01385 ch.mBaseVolume = ch.mVolume; 01386 } 01387 else 01388 { 01389 switch (ch.mVolumeColumn >> 4) 01390 { 01391 case 0x8: // Fine volume slide down (arrow down) 01392 if (ch.mVolume > 0) ch.mVolume -= (ch.mVolumeColumn & 0xF); 01393 ch.mBaseVolume = ch.mVolume; 01394 break; 01395 01396 case 0x9: // Fine volume slide up (arrow up) 01397 if (ch.mVolume < 0x40) ch.mVolume += (ch.mVolumeColumn & 0xF); 01398 ch.mBaseVolume = ch.mVolume; 01399 break; 01400 01401 case 0xA: // Set vibrato speed (Sxy) 01402 if ((ch.mVolumeColumn & 0xF) != 0) 01403 ch.mVibratoRate = (UINT8)(ch.mVolumeColumn & 0xF); 01404 break; 01405 01406 case 0xB: // Set vibrato depth (Vxy) 01407 if ((ch.mVolumeColumn & 0xF) != 0) 01408 { 01409 ch.mVibratoDepth = (UINT8)((ch.mVolumeColumn & 0xF) * 4); 01410 ch.mIsVibrato = 1; 01411 } 01412 break; 01413 01414 case 0xC: // Set panning (Pxy) 01415 ch.mPan = (UINT8)((ch.mVolumeColumn & 0xF) << 4); 01416 break; 01417 01418 case 0xD: // Panning slide left (left arrow) 01419 if (ch.mPan > 0) ch.mPan -= (ch.mVolumeColumn & 0xF); 01420 break; 01421 01422 case 0xE: // Panning slide right (right arrow) 01423 if (ch.mPan < 0xFF) ch.mPan += (ch.mVolumeColumn & 0xF); 01424 break; 01425 01426 case 0xF: // Tone portamento (Mxy) 01427 if ((ch.mVolumeColumn & 0xF) != 0) 01428 ch.mTonePortamentoV = (UINT8)((ch.mVolumeColumn & 0xF) << 4); 01429 01430 if ((ch.mTa.mNote != 0) && (ch.mTa.mNote != 97)) 01431 { 01432 ch.mDestPeriod = ch.mPeriod; 01433 ch.mPeriod = ch.mOldPeriod; 01434 ch.mBasePeriod = ch.mPeriod; 01435 } 01436 break; 01437 } 01438 } 01439 } 01440 01441 // Row effects 01442 switch (ch.mEffectType) 01443 { 01444 case 0x0: // Arpeggio (0xy) 01445 ch.mPeriod = ch.mBasePeriod; 01446 break; 01447 01448 case 0x1: // Portamento up (1xy) 01449 if (ch.mEffectValue != 0) ch.mPortamentoUpV = ch.mEffectValue; 01450 break; 01451 01452 case 0x2: // Portamento down (2xy) 01453 if (ch.mEffectValue != 0) ch.mPortamentoDownV = ch.mEffectValue; 01454 break; 01455 01456 case 0x3: // Tone portamento (3xy) 01457 if (ch.mOldPeriod != 0) 01458 { 01459 if (ch.mEffectValue != 0) ch.mTonePortamentoV = ch.mEffectValue; 01460 01461 if ((ch.mTa.mNote != 0) && (ch.mTa.mNote != 97)) 01462 { 01463 ch.mDestPeriod = ch.mPeriod; 01464 ch.mPeriod = ch.mOldPeriod; 01465 ch.mBasePeriod = ch.mPeriod; 01466 } 01467 } 01468 break; 01469 01470 case 0x4: // Vibrato (4xy) 01471 if ((ch.mEffectValue & 0xF) != 0) 01472 ch.mVibratoDepth = (UINT8)((ch.mEffectValue & 0xF) * 4); 01473 01474 if ((ch.mEffectValue >> 4) != 0) 01475 ch.mVibratoRate = (UINT8)(ch.mEffectValue >> 4); 01476 01477 ch.mIsVibrato = 1; 01478 break; 01479 01480 case 0x5: // Tone portamento + volume slide (5xy) 01481 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01482 break; 01483 01484 case 0x6: // Vibrato + volume slide (6xy) 01485 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01486 01487 ch.mIsVibrato = 1; 01488 break; 01489 01490 case 0x7: // Tremolo (7xy) 01491 if ((ch.mEffectValue & 0xF) != 0) 01492 ch.mTremoloDepth = (UINT8)(ch.mEffectValue & 0xF); 01493 01494 if ((ch.mEffectValue >> 4) != 0) 01495 ch.mTremoloRate = (UINT8)(ch.mEffectValue >> 4); 01496 break; 01497 01498 case 0x8: // Set panning (8xy) 01499 ch.mPan = ch.mEffectValue; 01500 break; 01501 01502 case 0x9: // Sample offset (9xy) 01503 ch.mPointer = ch.mEffectValue << (8 + FP_BITS); 01504 XFCASSERT(ch.mPointer < ch.mLength); 01505 // FastTracker2 behaviour when not in debug mode, 01506 // if offset is beyond sample length, stop sample 01507 if (ch.mPointer >= ch.mLength) ch.mIsSample = 0; 01508 break; 01509 01510 case 0xA: // Volume slide (Axy) 01511 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01512 break; 01513 01514 case 0xB: // Jump to pattern (Bxy) 01515 if (mJumpFlag == 0) 01516 { 01517 mCurrentRow = -1; 01518 mCurrentOrder = (INT16)(ch.mEffectValue - 1); 01519 mJumpFlag = 1; 01520 } 01521 break; 01522 01523 case 0xC: // Volume (Cxy) 01524 ch.mVolume = ch.mEffectValue; 01525 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01526 ch.mBaseVolume = ch.mVolume; 01527 break; 01528 01529 case 0xD: // Pattern break (Dxy) 01530 if (mJumpFlag == 0) 01531 { 01532 mCurrentRow = (INT16)(ch.mEffectValue - 1); 01533 mJumpFlag = 1; 01534 } 01535 break; 01536 01537 case 0xE: // Extra effects (Exy) 01538 switch ((ch.mEffectValue >> 4)) 01539 { 01540 case 0x1: // Fine portamento up (E1y) 01541 if ((ch.mEffectValue & 0xF) != 0) 01542 ch.mFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01543 01544 ch.mPeriod -= ch.mFinePortamentoUpV * 4; 01545 ch.mBasePeriod = ch.mPeriod; 01546 break; 01547 01548 case 0x2: // Fine portamento down (E2y) 01549 if ((ch.mEffectValue & 0xF) != 0) 01550 ch.mFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01551 01552 ch.mPeriod += ch.mFinePortamentoUpV * 4; 01553 ch.mBasePeriod = ch.mPeriod; 01554 break; 01555 01556 case 0x3: // Glissando control (E3y), FIX ME! 01557 break; 01558 01559 case 0x4: // Vibrato waveform (E4y) 01560 if ((ch.mEffectValue & 0xF) < 7) 01561 ch.mVibratoWaveform = (UINT8)(ch.mEffectValue & 0xF); 01562 break; 01563 01564 case 0x5: // Set finetune (E5y) 01565 ch.mFinetune = (INT8)((ch.mEffectValue & 0xF) << 1); 01566 break; 01567 01568 case 0x6: // Pattern loop (E6y), FIX ME! 01569 break; 01570 01571 case 0x7: // Tremolo waveform (E7y) 01572 if ((ch.mEffectValue & 0xF) < 7) 01573 ch.mTremoloWaveform = (UINT8)(ch.mEffectValue & 0xF); 01574 break; 01575 01576 case 0xA: // Fine volume slide up (EAy) 01577 if ((ch.mEffectValue & 0xF) != 0) 01578 ch.mFineVolumeSlideUpV = (UINT8)(ch.mEffectValue & 0xF); 01579 01580 if (ch.mVolume < 0x40) ch.mVolume += ch.mFineVolumeSlideUpV; 01581 ch.mBaseVolume = ch.mVolume; 01582 break; 01583 01584 case 0xB: // Fine volume slide down (EBy) 01585 if ((ch.mEffectValue & 0xF) != 0) 01586 ch.mFineVolumeSlideDownV = (UINT8)(ch.mEffectValue & 0xF); 01587 01588 if (ch.mVolume > 0) ch.mVolume -= ch.mFineVolumeSlideDownV; 01589 ch.mBaseVolume = ch.mVolume; 01590 break; 01591 01592 case 0xE: // Pattern delay (EEy) 01593 if ((mPatternDelayCounter == 0) && (mPatternDelaySkip == 0)) 01594 mPatternDelayCounterTemp = (UINT8)(ch.mEffectValue & 0xF); 01595 break; 01596 01597 } 01598 break; 01599 01600 case 0xF: // Tempo or BPM change (Fxy) 01601 if (ch.mEffectValue < 32) 01602 { 01603 mSong.mTempo = ch.mEffectValue; 01604 if (mSong.mTempo == 0) mIsRead = 0; 01605 } 01606 else 01607 { // BPM 01608 mSong.mBpm = ch.mEffectValue; 01609 mTickRate = 2.0f * mSong.mBpm / 5.0f; 01610 01611 mSamplesPerTick = (INT)(mSamplingRate / mTickRate); 01612 } 01613 break; 01614 01615 case 0x10: // Global volume (Gxy) 01616 mSong.mGlobalVolume = ch.mEffectValue; 01617 01618 if (mSong.mGlobalVolume > 0x40) mSong.mGlobalVolume = 0x40; 01619 break; 01620 01621 case 0x11: // Global volume slide (Hxy) 01622 if (ch.mEffectValue != 0) ch.mGlobalVolumeSlideV = ch.mEffectValue; 01623 01624 if (mSong.mGlobalVolume < 0x40) 01625 mSong.mGlobalVolume += (ch.mGlobalVolumeSlideV >> 4) << 1; 01626 if (mSong.mGlobalVolume > 0) 01627 mSong.mGlobalVolume -= (ch.mGlobalVolumeSlideV & 0xF) << 1; 01628 break; 01629 01630 case 0x15: // Set envelope position (Lxy) 01631 ch.mVolEnvPointer = ch.mPanEnvPointer = ch.mEffectValue; 01632 break; 01633 01634 case 0x19: // Panning slide (Pxy) 01635 if (ch.mEffectValue != 0) ch.mPanningSlideV = ch.mEffectValue; 01636 break; 01637 01638 case 0x1B: // Multi retrig note (Rxy) 01639 if ((ch.mEffectValue >> 4) != 0) 01640 ch.mMultiRetrigVolumeV = (UINT8)(ch.mEffectValue >> 4); 01641 01642 if ((ch.mEffectValue & 0xF) != 0) 01643 ch.mMultiRetrigRateV = (UINT8)(ch.mEffectValue & 0xF); 01644 01645 if (ch.mMultiRetrigRateV != 0) 01646 { 01647 if ((ch.mMultiRetrigTicker % ch.mMultiRetrigRateV) == 0) 01648 { 01649 ch.mInitSample = 1; 01650 initSound(ch); 01651 01652 if ((ch.mMultiRetrigVolumeV != 8) && (ch.mMultiRetrigTicker != 0)) 01653 { 01654 // Don't affect volume on first tick 01655 switch (ch.mMultiRetrigVolumeV) 01656 { 01657 case 0x1: 01658 ch.mVolume -= 1; 01659 break; 01660 case 0x2: 01661 ch.mVolume -= 2; 01662 break; 01663 case 0x3: 01664 ch.mVolume -= 4; 01665 break; 01666 case 0x4: 01667 ch.mVolume -= 8; 01668 break; 01669 case 0x5: 01670 ch.mVolume -= 16; 01671 break; 01672 case 0x6: 01673 ch.mVolume = (INT8)((ch.mVolume * 2) / 3); 01674 break; 01675 case 0x7: 01676 ch.mVolume >>= 1; 01677 break; 01678 case 0x9: 01679 ch.mVolume += 1; 01680 break; 01681 case 0xA: 01682 ch.mVolume += 2; 01683 break; 01684 case 0xB: 01685 ch.mVolume += 4; 01686 break; 01687 case 0xC: 01688 ch.mVolume += 8; 01689 break; 01690 case 0xD: 01691 ch.mVolume += 16; 01692 break; 01693 case 0xE: 01694 ch.mVolume = (INT8)((ch.mVolume * 3) / 2); 01695 break; 01696 case 0xF: 01697 ch.mVolume <<= 1; 01698 break; 01699 } 01700 01701 ch.mBaseVolume = ch.mVolume; 01702 } 01703 } 01704 } 01705 01706 ch.mMultiRetrigTicker++; 01707 break; 01708 01709 case 0x1D: // Tremor (Txy) 01710 if (ch.mEffectValue != 0) ch.mTremorV = ch.mEffectValue; 01711 01712 if (ch.mTremorV != 0) 01713 { 01714 if ((UINT8)(ch.mTremorTicker % 01715 ((ch.mTremorV >> 4) + (ch.mTremorV & 0xF) + 2)) < 01716 (ch.mTremorV >> 4) + 1) 01717 ch.mVolume = ch.mBaseVolume; 01718 else 01719 ch.mVolume = 0; 01720 } 01721 break; 01722 01723 case 0x21: // Extra fine portamento up/down (X1y/X2y) 01724 switch(ch.mEffectValue >> 4) 01725 { 01726 case 0x1: // Extra fine portamento up (X1y) 01727 if ((ch.mEffectValue & 0xF) != 0) 01728 ch.mExtraFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01729 01730 ch.mPeriod -= ch.mExtraFinePortamentoUpV; 01731 ch.mBasePeriod = ch.mPeriod; 01732 break; 01733 case 0x2: // Extra fine portamento down (X2y) 01734 if ((ch.mEffectValue & 0xF) != 0) 01735 ch.mExtraFinePortamentoDownV = (UINT8)(ch.mEffectValue & 0xF); 01736 01737 ch.mPeriod -= ch.mExtraFinePortamentoUpV; 01738 ch.mBasePeriod = ch.mPeriod; 01739 break; 01740 } 01741 break; 01742 } 01743 01744 notifyHandlers(ch); 01745 01746 // Key off (Kxy) 01747 if ((ch.mEffectType == 0x14) || (ch.mTa.mNote == 97)) 01748 { 01749 if (ch.mSustainReleased == 0) 01750 { 01751 ch.mSustainReleased = 1; 01752 if (ch.mVolEnvType & ENVELOPE_SUSTAIN) 01753 ch.mVolEnvSpeed = 1; // Start envelope 01754 01755 if (ch.mVolEnvType == 0) 01756 ch.mVolume = 0; 01757 01758 // FIX ME!!! PANNING ENVELOPE STUFF MISSING!!! 01759 } 01760 } 01761 } 01762 01763 if (mPatternDelayCounterTemp != 0) 01764 { 01765 mPatternDelayCounter = mPatternDelayCounterTemp; 01766 mPatternDelayCounterTemp = 0; 01767 mPatternDelaySkip = 1; 01768 } 01769 } 01770 else if (mSong.mTempo != 0) 01771 { 01772 // Tick effects 01773 for (chan = 0; chan < mSong.mNbChannels; chan++) 01774 { 01775 XFuXMChannel &ch = mChannels[chan]; 01776 01777 if (ch.mVolumeColumn != 0) 01778 { 01779 switch(ch.mVolumeColumn >> 4) 01780 { 01781 case 0x6: // Volume slide down (-xy) 01782 ch.mVolume -= (ch.mVolumeColumn & 0xF); 01783 ch.mBaseVolume = ch.mVolume; 01784 break; 01785 01786 case 0x7: // Volume slide up (+xy) 01787 ch.mVolume += (ch.mVolumeColumn & 0xF); 01788 ch.mBaseVolume = ch.mVolume; 01789 break; 01790 01791 case 0xF: // Tone portamento (Mxy) 01792 if (ch.mOldPeriod != 0) 01793 { 01794 if (ch.mDestPeriod > ch.mPeriod) 01795 { 01796 ch.mPeriod += (ch.mTonePortamentoV * 4); 01797 if (ch.mPeriod > ch.mDestPeriod) 01798 ch.mPeriod = ch.mDestPeriod; 01799 } 01800 else if (ch.mDestPeriod < ch.mPeriod) 01801 { 01802 ch.mPeriod -= (ch.mTonePortamentoV * 4); 01803 if (ch.mPeriod < ch.mDestPeriod) 01804 ch.mPeriod = ch.mDestPeriod; 01805 } 01806 01807 ch.mBasePeriod = ch.mPeriod; 01808 } 01809 break; 01810 } 01811 } 01812 01813 switch (ch.mEffectType) 01814 { 01815 case 0x0: // Arpeggio (0xy) 01816 if (ch.mEffectValue != 0) 01817 { 01818 switch (mCurrentTick % 3) 01819 { 01820 case 0: 01821 ch.mPeriod = ch.mBasePeriod; 01822 break; 01823 case 1: 01824 ch.mPeriod = ch.mBasePeriod - (ch.mEffectValue >> 4) * 64; 01825 break; 01826 case 2: 01827 ch.mPeriod = ch.mBasePeriod - (ch.mEffectValue & 0xF) * 64; 01828 break; 01829 } 01830 } 01831 break; 01832 01833 case 0x1: // Portamento up (1xy) 01834 ch.mPeriod -= (ch.mPortamentoUpV * 4); 01835 ch.mBasePeriod = ch.mPeriod; 01836 break; 01837 01838 case 0x2: // Portamento down (2xy) 01839 ch.mPeriod += (ch.mPortamentoDownV * 4); 01840 ch.mBasePeriod = ch.mPeriod; 01841 break; 01842 01843 case 0x7: // Tremolo (7xy), FIX ME! 01844 if (ch.mTremoloWaveform & WAVEFORM_SINEWAVE) 01845 tremoloTable = mSineWaveTable; 01846 else if (ch.mTremoloWaveform & WAVEFORM_SQUAREWAVE) 01847 tremoloTable = mSquareWaveTable; 01848 else if (ch.mTremoloWaveform & WAVEFORM_RAMPDOWN) 01849 tremoloTable = mRampDownTable; 01850 // FIX ME! Random waveform not supported 01851 01852 ch.mVolume = (INT8)(ch.mBaseVolume + 01853 ((tremoloTable[ch.mTremoloPointer] * ch.mTremoloDepth) >> 6)); 01854 ch.mTremoloPointer = (UINT8)( 01855 (ch.mTremoloPointer + ch.mTremoloRate) % XMFORMAT_SIZEOF_WAVEFORM); 01856 break; 01857 01858 case 0xE: // Extra effects (Exy) 01859 switch ((ch.mEffectValue >> 4)) 01860 { 01861 case 0x9: // Retrig note (E9y) 01862 if (((ch.mEffectValue & 0xF) != 0) && 01863 ((mCurrentTick % (ch.mEffectValue & 0xF)) == 0)) 01864 { 01865 ch.mInitSample = 1; 01866 initSound(ch); 01867 } 01868 break; 01869 01870 case 0xC: // Note cut (ECy) 01871 if (mCurrentTick == (ch.mEffectValue & 0xF)) 01872 { 01873 ch.mVolume = 0; 01874 ch.mBaseVolume = ch.mVolume; 01875 } 01876 break; 01877 01878 case 0xD: // Note delay (EDy) 01879 if (mCurrentTick == (ch.mEffectValue & 0xF)) 01880 { 01881 initChannel(ch); 01882 } 01883 break; 01884 } 01885 break; 01886 01887 case 0x19: // Panning slide (Pxy) 01888 ch.mPan += (ch.mPanningSlideV >> 4); 01889 if (ch.mPan > 0xFF) ch.mPan = 0xFF; 01890 01891 ch.mPan -= (ch.mPanningSlideV & 0xF); 01892 if (ch.mPan < 0) ch.mPan = 0; 01893 01894 break; 01895 01896 case 0x1B: // Multi retrig note (Rxy) 01897 if (ch.mMultiRetrigRateV != 0) 01898 { 01899 if ((ch.mMultiRetrigTicker % ch.mMultiRetrigRateV) == 0) 01900 { 01901 ch.mInitSample = 1; 01902 initSound(ch); 01903 01904 if ((ch.mMultiRetrigVolumeV != 8) && (ch.mMultiRetrigTicker != 0)) 01905 { 01906 // Don't affect volume on first tick 01907 switch (ch.mMultiRetrigVolumeV) 01908 { 01909 case 0x1: 01910 ch.mVolume -= 1; 01911 break; 01912 case 0x2: 01913 ch.mVolume -= 2; 01914 break; 01915 case 0x3: 01916 ch.mVolume -= 4; 01917 break; 01918 case 0x4: 01919 ch.mVolume -= 8; 01920 break; 01921 case 0x5: 01922 ch.mVolume -= 16; 01923 break; 01924 case 0x6: 01925 ch.mVolume = (INT8)(ch.mVolume * 2.0f / 3.0f); 01926 break; 01927 case 0x7: 01928 ch.mVolume >>= 1; 01929 break; 01930 case 0x9: 01931 ch.mVolume += 1; 01932 break; 01933 case 0xA: 01934 ch.mVolume += 2; 01935 break; 01936 case 0xB: 01937 ch.mVolume += 4; 01938 break; 01939 case 0xC: 01940 ch.mVolume += 8; 01941 break; 01942 case 0xD: 01943 ch.mVolume += 16; 01944 break; 01945 case 0xE: 01946 ch.mVolume = (INT8)(ch.mVolume * 3.0f / 2.0f); 01947 break; 01948 case 0xF: 01949 ch.mVolume <<= 1; 01950 break; 01951 } 01952 01953 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01954 else if (ch.mVolume < 0) ch.mVolume = 0; 01955 01956 ch.mBaseVolume = ch.mVolume; 01957 } 01958 } 01959 } 01960 01961 ch.mMultiRetrigTicker++; 01962 break; 01963 01964 case 0x1D: // Tremor (Txy) 01965 if (ch.mTremorV != 0) 01966 { 01967 if ((UINT8)(ch.mTremorTicker % 01968 ((ch.mTremorV >> 4) + (ch.mTremorV & 0xF) + 2)) < 01969 (ch.mTremorV >> 4) + 1) 01970 ch.mVolume = ch.mBaseVolume; 01971 else 01972 ch.mVolume = 0; 01973 } 01974 01975 ch.mTremorTicker++; 01976 break; 01977 01978 } 01979 01980 // Tone portamento (3xy) / 01981 // tone portamento + volume slide (5xy) / 01982 // volume column tone portamento (Mxy) 01983 if ((ch.mEffectType == 0x3) || (ch.mEffectType == 0x5)) 01984 { 01985 if (ch.mOldPeriod != 0) 01986 { 01987 if (ch.mDestPeriod > ch.mPeriod) 01988 { 01989 ch.mPeriod += (ch.mTonePortamentoV * 4); 01990 if (ch.mPeriod > ch.mDestPeriod) ch.mPeriod = ch.mDestPeriod; 01991 } 01992 else if (ch.mDestPeriod < ch.mPeriod) 01993 { 01994 ch.mPeriod -= (ch.mTonePortamentoV * 4); 01995 if (ch.mPeriod < ch.mDestPeriod) ch.mPeriod = ch.mDestPeriod; 01996 } 01997 01998 ch.mBasePeriod = ch.mPeriod; 01999 } 02000 } 02001 02002 // Volume slide (Axy) / 02003 // tone portamento + volume slide (5xy) / 02004 // vibrato + volume slide (6xy) 02005 if ((ch.mEffectType == 0xA) || (ch.mEffectType == 0x5) || (ch.mEffectType == 0x6)) 02006 { 02007 ch.mVolume += (ch.mVolumeSlideV >> 4); 02008 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 02009 02010 ch.mVolume -= (ch.mVolumeSlideV & 0xF); 02011 if (ch.mVolume < 0) ch.mVolume = 0; 02012 02013 ch.mBaseVolume = ch.mVolume; 02014 } 02015 02016 // Vibrato 02017 if (ch.mIsVibrato) 02018 { 02019 if (ch.mVibratoWaveform & WAVEFORM_SINEWAVE) 02020 vibratoTable = mSineWaveTable; 02021 else if (ch.mVibratoWaveform & WAVEFORM_SQUAREWAVE) 02022 vibratoTable = mSquareWaveTable; 02023 else if (ch.mVibratoWaveform & WAVEFORM_RAMPDOWN) 02024 vibratoTable = mRampDownTable; 02025 // FIX ME! Random waveform not supported 02026 02027 ch.mPeriod = ch.mBasePeriod + 02028 ((vibratoTable[ch.mVibratoPointer] * ch.mVibratoDepth) >> 7); 02029 ch.mVibratoPointer = (UINT8)( 02030 (ch.mVibratoPointer + ch.mVibratoRate) % XMFORMAT_SIZEOF_WAVEFORM); 02031 } 02032 } 02033 } 02034 02035 for (chan = 0; chan < mSong.mNbChannels; chan++) 02036 { 02037 XFuXMChannel &ch = mChannels[chan]; 02038 XFuXMInstrument *in = NULL; 02039 02040 if ((ch.mInstrumentNb != -1) && (ch.mInstrumentNb < mSong.mNbInstruments)) 02041 { 02042 in = &mInstruments[ch.mInstrumentNb]; 02043 02044 ch.mFinalOldVolume = ch.mFinalVolume; 02045 02046 // Volume envelope 02047 if (ch.mVolEnvType & ENVELOPE_ON) 02048 { 02049 if (ch.mVolEnvPointer >= in->mVolEnvEnd) 02050 { 02051 // Not normal behavior but can happen when using 02052 // set envelope position (Lxy) command with a value 02053 // which is bigger than the last envelope point 02054 ch.mVolEnvPointer = in->mVolEnvEnd; 02055 ch.mVolEnvSpeed = 0; 02056 } 02057 02058 ch.mVolEnvValue = in->mVolumeEnvelope[ch.mVolEnvPointer]; 02059 02060 if ((ch.mVolEnvType & ENVELOPE_SUSTAIN) && 02061 (ch.mVolEnvPointer == ch.mVolEnvSustain) && 02062 (ch.mSustainReleased == 0)) 02063 { 02064 // Sustain point, stop envelope 02065 ch.mVolEnvSpeed = 0; 02066 } 02067 02068 // Fix for trackers which don't follow FT2 standard in envelopes 02069 if (in->mVolEnvEnd != 0) ch.mVolEnvPointer += ch.mVolEnvSpeed; 02070 02071 if (ch.mVolEnvType & ENVELOPE_LOOP) 02072 { 02073 // Envelope loop 02074 // The loop check is faulty and should check whether 02075 // the pointer has passed the end point instead, but 02076 // as the bug is in FT2, it is also here for the sake 02077 // of compatibility 02078 if ((ch.mVolEnvSpeed) && (ch.mVolEnvPointer == ch.mVolEnvLoopEnd)) 02079 ch.mVolEnvPointer = ch.mVolEnvLoopStart; 02080 } 02081 else 02082 { 02083 if (ch.mVolEnvPointer == in->mVolEnvEnd) 02084 ch.mVolEnvSpeed = 0; 02085 } 02086 02087 if (ch.mSustainReleased) 02088 { 02089 ch.mVolumeFadeoutValue -= (ch.mVolumeFadeout * 2); 02090 if (ch.mVolumeFadeoutValue < 0) ch.mVolumeFadeoutValue = 0; 02091 } 02092 } else ch.mVolEnvValue = REALf(1.0f); // No volume envelope 02093 02094 // Panning envelope 02095 if (ch.mPanEnvType & ENVELOPE_ON) 02096 { 02097 if (ch.mPanEnvPointer >= in->mPanEnvEnd) 02098 { 02099 // Not normal behavior but can happen when using 02100 // set envelope position (Lxy) command with a value 02101 // which is bigger than the last envelope point 02102 ch.mPanEnvPointer = in->mPanEnvEnd; 02103 ch.mPanEnvSpeed = 0; 02104 } 02105 02106 ch.mPanEnvValue = in->mPanningEnvelope[ch.mPanEnvPointer]; 02107 02108 if ((ch.mPanEnvType & ENVELOPE_SUSTAIN) && 02109 (ch.mPanEnvPointer == ch.mPanEnvSustain) && 02110 (ch.mSustainReleased == 0)) 02111 { 02112 // Sustain point, stop envelope 02113 ch.mPanEnvSpeed = 0; 02114 } 02115 02116 // Fix for trackers which don't follow FT2 standard in envelopes 02117 if (in->mPanEnvEnd != 0) ch.mPanEnvPointer += ch.mPanEnvSpeed; 02118 02119 if (ch.mPanEnvType & ENVELOPE_LOOP) 02120 { 02121 // Envelope loop 02122 // The loop check is faulty and should check whether 02123 // the pointer has passed the end point instead, but 02124 // as the bug is in FT2, it is also here for the sake 02125 // of compatibility 02126 if ((ch.mPanEnvSpeed) && (ch.mPanEnvPointer == ch.mPanEnvLoopEnd)) 02127 ch.mPanEnvPointer = ch.mPanEnvLoopStart; 02128 } 02129 else 02130 { 02131 if (ch.mPanEnvPointer == in->mPanEnvEnd) ch.mPanEnvSpeed = 0; 02132 } 02133 } else ch.mPanEnvValue = 0x20; // No panning envelope 02134 02135 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 02136 if (ch.mVolume < 0) ch.mVolume = 0; 02137 02138 INT32 intVolume = (ch.mVolume * mSong.mGlobalVolume); 02139 REAL volumeTemp; 02140 volumeTemp.mValue = (intVolume << 3) + (intVolume << 1); 02141 ch.mFinalVolume = (volumeTemp * ch.mVolEnvValue * ch.mVolumeFadeoutValue); 02142 02143 volumeTemp = (ch.mFinalVolume - ch.mFinalOldVolume); 02144 ch.mFinalVolumeSpeed = (volumeTemp * mVolumeRampDivOpt); 02145 02146 /* 02147 REAL volumeTemp; 02148 volumeTemp.mValue = (ch.mVolume * mSong.mGlobalVolume * ch.mVolumeFadeoutValue) >> 13; 02149 ch.mFinalVolume = (volumeTemp * ch.mVolEnvValue); 02150 02151 volumeTemp = (ch.mFinalVolume - ch.mFinalOldVolume); 02152 ch.mFinalVolumeSpeed = (volumeTemp * mVolumeRampDivOpt); 02153 */ 02154 /* 02155 FLOAT32 volumeReal; 02156 volumeReal = (((FLOAT32)ch.mVolume / 65.0f) * (FLOAT32)ch.mVolEnvValue * 02157 (FLOAT32)ch.mVolumeFadeoutValue * ((FLOAT32)mSong.mGlobalVolume / 65.0f)); 02158 02159 ch.mFinalVolume = REALf(volumeReal); 02160 02161 ch.mFinalVolumeSpeed = (ch.mFinalVolume - ch.mFinalOldVolume) / REALf(32); 02162 */ 02163 /* 02164 volumeReal = (ch.mVolume * (FLOAT32)ch.mVolEnvValue * 02165 ch.mVolumeFadeoutValue * mSong.mGlobalVolume) * 02166 VOLUME_DIV_OPT; 02167 02168 ch.mFinalVolume = (INT32)volumeReal; 02169 02170 ch.mFinalVolumeSpeed = (INT32)((ch.mFinalVolume - ch.mFinalOldVolume) * 02171 VOLUME_RAMP_WIDTH_OPT); 02172 */ 02173 02174 ch.mFinalPan = (INT16)(ch.mPan + (((ch.mPanEnvValue - 0x20) * 02175 (0x80 - ABS(ch.mPan - 0x80))) >> 5)); 02176 if (ch.mFinalPan > 0xFF) ch.mFinalPan = 0xFF; 02177 else if (ch.mFinalPan < 0) ch.mFinalPan = 0; 02178 02179 ch.mSpeed = getSpeed(ch.mPeriod, mSamplingRate); 02180 } 02181 } 02182 } 02183 02184 ticksLeft = (mSamplesPerTick - mSamplePointer); 02185 indicesLeft = (aSamples - index); 02186 02187 if (ticksLeft < indicesLeft) samplesToRender = ticksLeft; 02188 else samplesToRender = indicesLeft; 02189 02190 INT startChan = 0; 02191 INT endChan = mSong.mNbChannels; 02192 if (mFlags & XFCAUDIO_16BIT) // 16bit 02193 { 02194 if (mFlags & XFCAUDIO_STEREO) // 16bit stereo 02195 { 02196 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02197 { 02198 cLeft = cRight = 0; 02199 02200 for (chan = startChan; chan < endChan; chan++) 02201 { 02202 XFuXMChannel &ch = mChannels[chan]; 02203 02204 if (ch.mIsSample) 02205 { 02206 delta = ch.mPointer & (FP_VALUE - 1); 02207 02208 val1 = 0; 02209 val2 = 0; 02210 02211 if (ch.mCurrentSample.m16Bit) 02212 { 02213 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02214 02215 if (ch.mLoop == 0) 02216 { 02217 interpolateLinear16(ch, val1, val2); 02218 addPointer(ch); 02219 } 02220 else 02221 { 02222 temp = (ch.mPointer + FP_VALUE); 02223 02224 if (ch.mLoop == LOOP_FORWARD) 02225 { 02226 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02227 addPointerForwardLoop(ch); 02228 } 02229 else if (ch.mLoop == LOOP_PINGPONG) 02230 { 02231 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02232 addPointerBidirectionalLoop(ch); 02233 } 02234 } 02235 } 02236 else 02237 { 02238 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02239 02240 if (ch.mLoop == 0) 02241 { 02242 interpolateLinear8(ch, val1, val2); 02243 addPointer(ch); 02244 } 02245 else 02246 { 02247 temp = (ch.mPointer + FP_VALUE); 02248 02249 if (ch.mLoop == LOOP_FORWARD) 02250 { 02251 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02252 addPointerForwardLoop(ch); 02253 } 02254 else if (ch.mLoop == LOOP_PINGPONG) 02255 { 02256 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02257 addPointerBidirectionalLoop(ch); 02258 } 02259 } 02260 02261 val1 <<= 8; 02262 val2 <<= 8; 02263 } 02264 02265 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02266 02267 value = (INT16)(value * ch.mFinalOldVolume); 02268 cLeft += ((value * (0xFF - (UINT8)ch.mFinalPan)) >> 8); 02269 cRight += ((value * (UINT8)ch.mFinalPan) >> 8); 02270 02271 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02272 } 02273 } 02274 02275 if (cLeft < -32768) cLeft = -32768; 02276 else if (cLeft > 32767) cLeft = 32767; 02277 if (cRight < -32768) cRight = -32768; 02278 else if (cRight > 32767) cRight = 32767; 02279 02280 *((INT16 *)aBuffer + (targetOffset << 1)) = (INT16)(cLeft ^ mTgtXor); 02281 *((INT16 *)aBuffer + (targetOffset << 1) + 1) = (INT16)(cRight ^ mTgtXor); 02282 02283 targetOffset++; 02284 if (targetOffset == aTargetSamples) targetOffset = 0; 02285 02286 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02287 } 02288 } 02289 else // 16bit mono 02290 { 02291 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02292 { 02293 cLeft = 0; 02294 02295 for (chan = startChan; chan < endChan; chan++) 02296 { 02297 XFuXMChannel &ch = mChannels[chan]; 02298 02299 if (ch.mIsSample) 02300 { 02301 delta = ch.mPointer & (FP_VALUE - 1); 02302 02303 val1 = 0; 02304 val2 = 0; 02305 02306 if (ch.mCurrentSample.m16Bit) 02307 { 02308 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02309 02310 if (ch.mLoop == 0) 02311 { 02312 interpolateLinear16(ch, val1, val2); 02313 addPointer(ch); 02314 } 02315 else 02316 { 02317 temp = (ch.mPointer + FP_VALUE); 02318 02319 if (ch.mLoop == LOOP_FORWARD) 02320 { 02321 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02322 addPointerForwardLoop(ch); 02323 } 02324 else if (ch.mLoop == LOOP_PINGPONG) 02325 { 02326 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02327 addPointerBidirectionalLoop(ch); 02328 } 02329 } 02330 } 02331 else 02332 { 02333 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02334 02335 if (ch.mLoop == 0) 02336 { 02337 interpolateLinear8(ch, val1, val2); 02338 addPointer(ch); 02339 } 02340 else 02341 { 02342 temp = (ch.mPointer + FP_VALUE); 02343 02344 if (ch.mLoop == LOOP_FORWARD) 02345 { 02346 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02347 addPointerForwardLoop(ch); 02348 } 02349 else if (ch.mLoop == LOOP_PINGPONG) 02350 { 02351 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02352 addPointerBidirectionalLoop(ch); 02353 } 02354 } 02355 02356 val1 <<= 8; 02357 val2 <<= 8; 02358 } 02359 02360 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02361 02362 cLeft += (INT16)(value * ch.mFinalOldVolume); 02363 02364 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02365 } 02366 } 02367 02368 if (cLeft > 32767) cLeft = 32767; 02369 else if (cLeft < -32768) cLeft = -32768; 02370 02371 *((INT16 *)aBuffer + targetOffset) = (INT16)(cLeft ^ mTgtXor); 02372 02373 targetOffset++; 02374 if (targetOffset == aTargetSamples) targetOffset = 0; 02375 02376 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02377 } 02378 } 02379 } 02380 else // 8bit 02381 { 02382 if (mFlags & XFCAUDIO_STEREO) // 8bit stereo 02383 { 02384 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02385 { 02386 cLeft = cRight = 0; 02387 02388 for (chan = startChan; chan < endChan; chan++) 02389 { 02390 XFuXMChannel &ch = mChannels[chan]; 02391 02392 if (ch.mIsSample) 02393 { 02394 delta = ch.mPointer & (FP_VALUE - 1); 02395 02396 val1 = 0; 02397 val2 = 0; 02398 02399 if (ch.mCurrentSample.m16Bit) 02400 { 02401 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02402 02403 if (ch.mLoop == 0) 02404 { 02405 interpolateLinear16(ch, val1, val2); 02406 addPointer(ch); 02407 } 02408 else 02409 { 02410 temp = (ch.mPointer + FP_VALUE); 02411 02412 if (ch.mLoop == LOOP_FORWARD) 02413 { 02414 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02415 addPointerForwardLoop(ch); 02416 } 02417 else if (ch.mLoop == LOOP_PINGPONG) 02418 { 02419 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02420 addPointerBidirectionalLoop(ch); 02421 } 02422 } 02423 02424 val1 >>= 8; 02425 val2 >>= 8; 02426 } 02427 else 02428 { 02429 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02430 02431 if (ch.mLoop == 0) 02432 { 02433 interpolateLinear8(ch, val1, val2); 02434 addPointer(ch); 02435 } 02436 else 02437 { 02438 temp = (ch.mPointer + FP_VALUE); 02439 02440 if (ch.mLoop == LOOP_FORWARD) 02441 { 02442 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02443 addPointerForwardLoop(ch); 02444 } 02445 else if (ch.mLoop == LOOP_PINGPONG) 02446 { 02447 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02448 addPointerBidirectionalLoop(ch); 02449 } 02450 } 02451 } 02452 02453 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02454 02455 value = (INT8)(value * ch.mFinalOldVolume); 02456 cLeft += ((value * (0xFF - (UINT8)ch.mFinalPan)) >> 8); 02457 cRight += ((value * (UINT8)ch.mFinalPan) >> 8); 02458 02459 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02460 } 02461 } 02462 02463 if (cLeft < -128) cLeft = -128; 02464 else if (cLeft > 127) cLeft = 127; 02465 if (cRight < -128) cRight = -128; 02466 else if (cRight > 127) cRight = 127; 02467 02468 *((INT8 *)aBuffer + (targetOffset << 1)) = (INT8)(cLeft ^ mTgtXor); 02469 *((INT8 *)aBuffer + (targetOffset << 1) + 1) = (INT8)(cRight ^ mTgtXor); 02470 02471 targetOffset++; 02472 if (targetOffset == aTargetSamples) targetOffset = 0; 02473 02474 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02475 } 02476 } 02477 else // 8bit mono 02478 { 02479 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02480 { 02481 cLeft = 0; 02482 02483 for (chan = startChan; chan < endChan; chan++) 02484 { 02485 XFuXMChannel &ch = mChannels[chan]; 02486 02487 if (ch.mIsSample) 02488 { 02489 delta = ch.mPointer & (FP_VALUE - 1); 02490 02491 val1 = 0; 02492 val2 = 0; 02493 02494 if (ch.mCurrentSample.m16Bit) 02495 { 02496 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02497 02498 if (ch.mLoop == 0) 02499 { 02500 interpolateLinear16(ch, val1, val2); 02501 addPointer(ch); 02502 } 02503 else 02504 { 02505 temp = (ch.mPointer + FP_VALUE); 02506 02507 if (ch.mLoop == LOOP_FORWARD) 02508 { 02509 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02510 addPointerForwardLoop(ch); 02511 } 02512 else if (ch.mLoop == LOOP_PINGPONG) 02513 { 02514 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02515 addPointerBidirectionalLoop(ch); 02516 } 02517 } 02518 02519 val1 >>= 8; 02520 val2 >>= 8; 02521 } 02522 else 02523 { 02524 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02525 02526 if (ch.mLoop == 0) 02527 { 02528 interpolateLinear8(ch, val1, val2); 02529 addPointer(ch); 02530 } 02531 else 02532 { 02533 temp = (ch.mPointer + FP_VALUE); 02534 02535 if (ch.mLoop == LOOP_FORWARD) 02536 { 02537 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02538 addPointerForwardLoop(ch); 02539 } 02540 else if (ch.mLoop == LOOP_PINGPONG) 02541 { 02542 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02543 addPointerBidirectionalLoop(ch); 02544 } 02545 } 02546 } 02547 02548 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02549 02550 cLeft += (INT8)(value * ch.mFinalOldVolume); 02551 02552 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02553 } 02554 } 02555 02556 if (cLeft > 127) cLeft = 127; 02557 else if (cLeft < -128) cLeft = -128; 02558 02559 *((INT8 *)aBuffer + targetOffset) = (INT8)(cLeft ^ mTgtXor); 02560 02561 targetOffset++; 02562 if (targetOffset == aTargetSamples) targetOffset = 0; 02563 02564 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02565 } 02566 } 02567 } 02568 02569 mSamplePointer += samplesToRender; 02570 } 02571 02572 mTotalTicks += aSamples; 02573 02574 return 1; 02575 } 02576 02577 // For MSVC 02578 #pragma warning(default:4244) 02579 02580 02581 XFuXMPlayer::XFuXMPlayer(FLOAT32 aSamplingRate, UINT32 aFlags) 02582 { 02583 mSamplingRate = aSamplingRate; 02584 mFlags = aFlags; 02585 02586 mTgtXor = 0; 02587 if (!(mFlags & XFCAUDIO_SIGNED)) 02588 { 02589 if (mFlags & XFCAUDIO_16BIT) mTgtXor = -32768; 02590 else mTgtXor = -128; 02591 } 02592 02593 /* Sinewave table */ 02594 mSineWaveTable[0] = 0; 02595 mSineWaveTable[1] = 24; 02596 mSineWaveTable[2] = 49; 02597 mSineWaveTable[3] = 74; 02598 mSineWaveTable[4] = 97; 02599 mSineWaveTable[5] = 120; 02600 mSineWaveTable[6] = 141; 02601 mSineWaveTable[7] = 161; 02602 mSineWaveTable[8] = 180; 02603 mSineWaveTable[9] = 197; 02604 mSineWaveTable[10] = 212; 02605 mSineWaveTable[11] = 224; 02606 mSineWaveTable[12] = 235; 02607 mSineWaveTable[13] = 244; 02608 mSineWaveTable[14] = 250; 02609 mSineWaveTable[15] = 253; 02610 mSineWaveTable[16] = 255; 02611 mSineWaveTable[17] = 253; 02612 mSineWaveTable[18] = 250; 02613 mSineWaveTable[19] = 244; 02614 mSineWaveTable[20] = 235; 02615 mSineWaveTable[21] = 224; 02616 mSineWaveTable[22] = 212; 02617 mSineWaveTable[23] = 197; 02618 mSineWaveTable[24] = 180; 02619 mSineWaveTable[25] = 161; 02620 mSineWaveTable[26] = 141; 02621 mSineWaveTable[27] = 120; 02622 mSineWaveTable[28] = 97; 02623 mSineWaveTable[29] = 74; 02624 mSineWaveTable[30] = 49; 02625 mSineWaveTable[31] = 24; 02626 02627 INT i; 02628 02629 for (i = 32; i < 64; i++) 02630 { 02631 mSineWaveTable[i] = (INT16)-mSineWaveTable[i - 32]; 02632 } 02633 02634 /* Squarewave table */ 02635 for (i = 0; i < 32; i++) mSquareWaveTable[i] = -255; 02636 for (i = 32; i < 64; i++) mSquareWaveTable[i] = 255; 02637 02638 /* Ramp up/down tables */ 02639 for (i = 0; i < 32; i++) 02640 { 02641 mRampUpTable[i] = (INT16)(255.0f - (FLOAT32)i * (510.0f / 32.0f)); 02642 mRampUpTable[i + 32] = (INT16)(255.0f - (FLOAT32)i * (510.0f / 32.0f)); 02643 02644 mRampDownTable[i] = (INT16)(-255.0f + (FLOAT32)i * (510.0f / 32.0f)); 02645 mRampDownTable[i + 32] = 02646 (INT16)(-255.0f + (FLOAT32)i * (510.0f / 32.0f)); 02647 } 02648 02649 mSong.mOrderTable = NULL; 02650 mXMPatternHeaders = NULL; 02651 mPatternData = NULL; 02652 mInstruments = NULL; 02653 mChannels = NULL; 02654 02655 mEventHandlers = NULL; 02656 } 02657 02658 02659 XFuXMPlayer::~XFuXMPlayer() 02660 { 02661 INT i, j; 02662 02663 delete[] mSong.mOrderTable; 02664 02665 delete[] mXMPatternHeaders; 02666 02667 if (mPatternData != NULL) 02668 { 02669 for (i = 0; i < mSong.mNbPatterns; i++) 02670 { 02671 delete[] mPatternData[i].mData; 02672 delete[] mPatternData[i].mRows; 02673 } 02674 02675 delete[] mPatternData; 02676 } 02677 02678 if (mInstruments != NULL) 02679 { 02680 for (i = 0; i < mSong.mNbInstruments; i++) 02681 { 02682 XFuXMInstrument &ins = mInstruments[i]; 02683 02684 if (ins.mSamples != NULL) 02685 { 02686 for (j = 0; j < ins.mNbSamples; j++) 02687 { 02688 delete[] (INT8 *)ins.mSamples[j].mOffset; 02689 } 02690 02691 delete[] ins.mSamples; 02692 } 02693 } 02694 02695 delete[] mInstruments; 02696 } 02697 02698 delete[] mChannels; 02699 02700 delete mEventHandlers; 02701 } 02702 02703 02704 XFuXMPlayer * XFuXMPlayer::create(const CHAR *aTunename, FLOAT32 aSampleRate, UINT32 aFlags) 02705 { 02706 XFcFile *textout = NULL; 02707 02708 XFuXMPlayer *pl = new XFuXMPlayer(aSampleRate, aFlags); 02709 02710 if (pl != NULL) 02711 { 02712 pl->initialize(aSampleRate, aFlags, 1.0, 0.5, 0); 02713 02714 pl->mEventHandlers = new XFcLinkedList<XFuXMPlayerEventHandlerSlot>(); 02715 02716 if (pl->mEventHandlers == NULL) 02717 { 02718 delete pl; 02719 return NULL; 02720 } 02721 02722 #ifdef OUTPUT_XM_INFO 02723 XFuXMFormatAtom ta; 02724 02725 textout = XFcFile::open("xmoutput.txt","wt"); 02726 #endif 02727 02728 if (pl->loadXM(aTunename, textout) != 0) 02729 { 02730 // file not found 02731 delete pl; 02732 return NULL; 02733 } 02734 02735 #ifdef OUTPUT_XM_INFO 02736 pl->dumpSongParameters(textout); 02737 02738 pl->mPatternNb = -1; 02739 INT i; 02740 for (i = 0; i < pl->mXMHeader.mNbPatterns; i++) 02741 { 02742 pl->mPatternNb++; 02743 if (pl->mXMPatternHeaders[i].mSize > 0) 02744 { 02745 debugPrint(textout, "* Pattern: %02X\n", pl->mPatternNb); 02746 { 02747 INT row, channel; 02748 pl->mPpoint = 0; 02749 for (row = 0; row < pl->mXMPatternHeaders[i].mNbRows; row++) 02750 { 02751 debugPrint(textout, "%02X: ", row); 02752 for (channel = 0; channel < pl->mXMHeader.mNbChannels; channel++) 02753 { 02754 ta = pl->getAtom(); 02755 02756 if (ta.mNote == 0) 02757 { 02758 if (ta.mVolume != 0) 02759 debugPrint(textout, "--- %02X %02X %1X%02X ; ", 02760 ta.mInstrumentNb, ta.mVolume - 0x10, 02761 ta.mEffectType, ta.mEffectValue); 02762 else 02763 debugPrint(textout, "--- %02X -- %1X%02X ; ", 02764 ta.mInstrumentNb, ta.mEffectType, 02765 ta.mEffectValue); 02766 } 02767 else 02768 { 02769 if (ta.mVolume != 0) 02770 debugPrint(textout, 02771 "%s%1d %02X %02X %1X%02X ; ", 02772 notes[(ta.mNote - 1) % 12], 02773 (INT)((ta.mNote - 1) / 12), 02774 ta.mInstrumentNb, ta.mVolume - 0x10, 02775 ta.mEffectType, ta.mEffectValue); 02776 else 02777 debugPrint(textout, "%s%1d %02X -- %1X%02X ; ", 02778 notes[(ta.mNote - 1) % 12], 02779 (INT)((ta.mNote - 1) / 12), 02780 ta.mInstrumentNb, ta.mEffectType, 02781 ta.mEffectValue); 02782 } 02783 } 02784 02785 debugPrint(textout, "\n"); 02786 } 02787 } 02788 } 02789 } 02790 02791 if (textout != NULL) textout->close(); 02792 #endif 02793 02794 pl->initSong(0); 02795 pl->mVolumeRampDivOpt = REALf(1.0f / VOLUME_RAMP_WIDTH); 02796 } 02797 02798 return pl; 02799 } 02800
![]() | ||||
![]() |
Confidential Copyright © 2002-2003 Fathammer | with doxygen by Dimitri van Heesch |