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 * \todo Set envelope position -command 00011 * 00012 * $Id: XFuXMPlayer.cpp,v 1.41 2003/06/18 13:18:44 jetro Exp $ 00013 * $Date: 2003/06/18 13:18:44 $ 00014 * $Revision: 1.41 $ 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 DebugPrint(XFcFile *aTextout, char *aFmt, ...) { 00231 #if !defined(XFC_PLATFORM_EPOC) && !defined(XFC_PLATFORM_PALM) 00232 if (aTextout != NULL) 00233 { 00234 va_list ap; 00235 static char buffer[10240]; 00236 va_start(ap, aFmt); 00237 vsprintf(buffer, aFmt, ap); 00238 aTextout->write(buffer, 1, XFcStringToolkit::getLength(buffer)); 00239 va_end(ap); 00240 } 00241 #endif // XFC_PLATFORM_EPOC 00242 } 00243 00244 00245 void XFuXMPlayer::dumpSongParameters(XFcFile *aTextout) 00246 { 00247 INT i = 0, x; 00248 00249 DebugPrint(aTextout, "\n\nParameters for current mSong. \n\n"); 00250 DebugPrint(aTextout, "module type: %s\n", mSong.mTypeString); 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 & ENV_ON)); 00283 DebugPrint(aTextout, " sustain? %d\n", 00284 (ins.mVolEnvType & ENV_SUSTAIN)); 00285 DebugPrint(aTextout, " sustain point: %d\n", (ins.mVolEnvSustain)); 00286 DebugPrint(aTextout, " loop? %d\n", (ins.mVolEnvType & ENV_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 & ENV_ON)); 00297 DebugPrint(aTextout, " loop? %d\n", (ins.mPanEnvType & ENV_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 INT32 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 f->read(mXMHeader.mModuleName, 20, sizeof(UINT8)); 00337 f->readUINT8(mXMHeader.mH1A); 00338 f->read(mXMHeader.mTrackerName, 20, sizeof(UINT8)); 00339 f->readUINT16(mXMHeader.mVersion); 00340 00341 f->readUINT32(mXMHeader.mHeaderSize); 00342 00343 f->readUINT16(mXMHeader.mSongLength); 00344 f->readUINT16(mXMHeader.mRestartPosition); 00345 f->readUINT16(mXMHeader.mNbChannels); 00346 f->readUINT16(mXMHeader.mNbPatterns); 00347 f->readUINT16(mXMHeader.mNbInstruments); 00348 00349 f->readUINT16(mXMHeader.mFlags); 00350 00351 f->readUINT16(mXMHeader.mTempo); 00352 f->readUINT16(mXMHeader.mBpm); 00353 00354 f->read(mXMHeader.mOrderTable, 256, sizeof(UINT8)); 00355 00356 DebugPrint(aTextout, "id string: %s\n", mXMHeader.mIdString); 00357 DebugPrint(aTextout, "module name: %s\n", mXMHeader.mModuleName); 00358 DebugPrint(aTextout, "h1A: %d\n", mXMHeader.mH1A); 00359 DebugPrint(aTextout, "tracker name: %s\n", mXMHeader.mTrackerName); 00360 DebugPrint(aTextout, "tracker version: %d\n", mXMHeader.mVersion); 00361 DebugPrint(aTextout, "header size: %d\n", mXMHeader.mHeaderSize); 00362 DebugPrint(aTextout, "song length: %d\n", mXMHeader.mSongLength); 00363 DebugPrint(aTextout, "restart pos: %d\n", mXMHeader.mRestartPosition); 00364 DebugPrint(aTextout, "nof mChannels: %d\n", mXMHeader.mNbChannels); 00365 DebugPrint(aTextout, "nof patterns: %d\n", mXMHeader.mNbPatterns); 00366 DebugPrint(aTextout, "nof instrument: %d\n", mXMHeader.mNbInstruments); 00367 DebugPrint(aTextout, "flags: %d\n", mXMHeader.mFlags); 00368 DebugPrint(aTextout, "tempo: %d\n", mXMHeader.mTempo); 00369 DebugPrint(aTextout, "bpm: %d\n", mXMHeader.mBpm); 00370 DebugPrint(aTextout, "ordertable: \n"); 00371 00372 // Allocate memory for order list 00373 mSong.mOrderTable = new UINT8[mXMHeader.mSongLength]; 00374 memset(mSong.mOrderTable, 0, mXMHeader.mSongLength * sizeof(UINT8)); 00375 00376 for (i = 0; i < mXMHeader.mSongLength; i++) 00377 { 00378 DebugPrint(aTextout, "%2X->%2X\n", i, mXMHeader.mOrderTable[i]); 00379 mSong.mOrderTable[i] = mXMHeader.mOrderTable[i]; 00380 } 00381 00382 // Save song header 00383 mSong.mTypeString = "XM-module"; 00384 mSong.mNbChannels = mXMHeader.mNbChannels; 00385 mSong.mNbPatterns = mXMHeader.mNbPatterns; 00386 mSong.mNbInstruments = mXMHeader.mNbInstruments; 00387 mSong.mSongLength = mXMHeader.mSongLength; 00388 mSong.mRestartPosition = mXMHeader.mRestartPosition; 00389 mSong.mBpm = mXMHeader.mBpm; 00390 mSong.mTempo = mXMHeader.mTempo; 00391 00392 // Allocate memory for mChannels 00393 mChannels = new XFuXMChannel[mSong.mNbChannels]; 00394 memset(mChannels, 0, mSong.mNbChannels * sizeof(XFuXMChannel)); 00395 00396 // Read pattern headers and pattern data 00397 DebugPrint(aTextout, "\npatterns:\n\n"); 00398 00399 // Allocate memory for pattern headers 00400 mXMPatternHeaders = new XFuXMFormatPatternHeader[mXMHeader.mNbPatterns]; 00401 memset(mXMPatternHeaders, 0, 00402 mXMHeader.mNbPatterns * sizeof(XFuXMFormatPatternHeader)); 00403 00404 // Allocate memory for pattern data blocks 00405 mPatternData = new XFuXMPattern[mXMHeader.mNbPatterns]; 00406 memset(mPatternData, 0, mXMHeader.mNbPatterns * sizeof(XFuXMPattern)); 00407 00408 for (i = 0; i < mXMHeader.mNbPatterns; i++) 00409 { 00410 DebugPrint(aTextout, "pattern %d \n", i); 00411 00412 f->readUINT32(mXMPatternHeaders[i].mHeaderLength); 00413 f->readUINT8(mXMPatternHeaders[i].mPackingType); 00414 f->readUINT16(mXMPatternHeaders[i].mNbRows); 00415 f->readUINT16(mXMPatternHeaders[i].mSize); 00416 00417 DebugPrint(aTextout, "header length: %d \n", 00418 mXMPatternHeaders[i].mHeaderLength); 00419 DebugPrint(aTextout, "packing type: %d \n", 00420 mXMPatternHeaders[i].mPackingType); 00421 DebugPrint(aTextout, "nof rows: %d \n", mXMPatternHeaders[i].mNbRows); 00422 DebugPrint(aTextout, "size: %d \n\n", mXMPatternHeaders[i].mSize); 00423 00424 if (mXMPatternHeaders[i].mSize > 0) 00425 { 00426 // Allocate memory for actual pattern data 00427 mPatternData[i].mData = new UINT8[mXMPatternHeaders[i].mSize]; 00428 mPatternData[i].mRows = new UINT32[mXMPatternHeaders[i].mNbRows]; 00429 f->read(mPatternData[i].mData, mXMPatternHeaders[i].mSize, 1); 00430 00431 UINT8 b = 0; 00432 UINT32 p = 0; 00433 for (j = 0; j < mXMPatternHeaders[i].mNbRows; j++) 00434 { 00435 mPatternData[i].mRows[j] = p; 00436 00437 for (k = 0; k < mSong.mNbChannels; k++) 00438 { 00439 b = *(mPatternData[i].mData + p++); 00440 00441 if ((b & 128) == 128) { 00442 // Packed atom 00443 if ((b & 1) == 1) p++; 00444 if ((b & 2) == 2) p++; 00445 if ((b & 4) == 4) p++; 00446 if ((b & 8) == 8) p++; 00447 if ((b & 16) == 16) p++; 00448 } 00449 else 00450 { 00451 // Normal atom 00452 p += 4; 00453 } 00454 } 00455 } 00456 } 00457 } 00458 00459 // Allocate memory for mInstruments 00460 mInstruments = new XFuXMInstrument[mXMHeader.mNbInstruments]; 00461 memset(mInstruments, 0, mXMHeader.mNbInstruments * sizeof(XFuXMInstrument)); 00462 00463 // Read mInstruments 00464 DebugPrint(aTextout, "mInstruments \n\n"); 00465 for (i = 0; i < mXMHeader.mNbInstruments; i++) 00466 { 00467 DebugPrint(aTextout, "instrument %02x \n", i); 00468 00469 XFuXMInstrument &ins = mInstruments[i]; 00470 00471 memset(&xmInstrumentHeader, 0, sizeof(XFuXMFormatInstrumentHeader)); 00472 00473 f->readUINT32(xmInstrumentHeader.mSize); 00474 f->read(xmInstrumentHeader.mInstrumentName, 22, sizeof(UINT8)); 00475 f->readUINT8(xmInstrumentHeader.mType); 00476 f->readUINT16(xmInstrumentHeader.mNbSamples); 00477 00478 ins.mNbSamples = xmInstrumentHeader.mNbSamples; 00479 00480 DebugPrint(aTextout, "size: %d \n", xmInstrumentHeader.mSize); 00481 DebugPrint(aTextout, "name: %s \n", xmInstrumentHeader.mInstrumentName); 00482 DebugPrint(aTextout, "type: %d \n", xmInstrumentHeader.mType); 00483 DebugPrint(aTextout, "nof samples: %d \n", 00484 xmInstrumentHeader.mNbSamples); 00485 00486 // sizeof(xmInstrumentHeader) could return an ALIGNED value 00487 INT32 skip = xmInstrumentHeader.mSize - 29; 00488 00489 if (xmInstrumentHeader.mNbSamples > 0) 00490 { 00491 memset(&xmInstrument, 0, sizeof(XFuXMFormatInstrument)); 00492 00493 f->readUINT32(xmInstrument.mSampleHeaderSize); 00494 f->read(xmInstrument.mKeyboard, 96, sizeof(UINT8)); 00495 f->read(xmInstrument.mVolumeEnvelope, 24, sizeof(UINT16)); 00496 f->read(xmInstrument.mPanningEnvelope, 24, sizeof(UINT16)); 00497 f->readUINT8(xmInstrument.mNbVolEnvPoints); 00498 f->readUINT8(xmInstrument.mNbPanEnvPoints); 00499 f->readUINT8(xmInstrument.mVolEnvSustain); 00500 f->readUINT8(xmInstrument.mVolEnvLoopStart); 00501 f->readUINT8(xmInstrument.mVolEnvLoopEnd); 00502 f->readUINT8(xmInstrument.mPanEnvSustain); 00503 f->readUINT8(xmInstrument.mPanEnvLoopStart); 00504 f->readUINT8(xmInstrument.mPanEnvLoopEnd); 00505 f->readUINT8(xmInstrument.mVolEnvType); 00506 f->readUINT8(xmInstrument.mPanEnvType); 00507 00508 f->readUINT8(xmInstrument.mVibratoType); 00509 f->readUINT8(xmInstrument.mVibratoSweep); 00510 f->readUINT8(xmInstrument.mVibratoDepth); 00511 f->readUINT8(xmInstrument.mVibratoRate); 00512 00513 f->readUINT16(xmInstrument.mVolumeFadeout); 00514 00515 f->readUINT16(xmInstrument.mReserved); 00516 00517 // sizeof(xmInstrument) could return an ALIGNED value 00518 skip -= 214; 00519 f->seek(skip, SEEK_CUR); 00520 00521 // Allocate memory for samples in instrument 00522 ins.mSamples = new XFuXMSample[xmInstrumentHeader.mNbSamples]; 00523 memset(ins.mSamples, 0, xmInstrumentHeader.mNbSamples * sizeof(XFuXMSample)); 00524 00525 for (j = 0; j < xmInstrumentHeader.mNbSamples; j++) 00526 { 00527 XFuXMSample &smp = ins.mSamples[j]; 00528 00529 memset(&xmSample, 0, sizeof(XFuXMFormatSample)); 00530 00531 f->readUINT32(xmSample.mSampleLength); 00532 f->readUINT32(xmSample.mLoopStart); 00533 f->readUINT32(xmSample.mLoopLength); 00534 f->readUINT8(xmSample.mVolume); 00535 f->readINT8(xmSample.mFinetune); 00536 f->readUINT8(xmSample.mType); 00537 f->readUINT8(xmSample.mPan); 00538 f->readINT8(xmSample.mRelativeNote); 00539 f->readUINT8(xmSample.mReserved); 00540 00541 f->read(xmSample.mSampleName, 22, sizeof(UINT8)); 00542 00543 DebugPrint(aTextout, "Allocating %d bytes for sample %02X in " 00544 "instrument %02X\n", xmSample.mSampleLength, j, i); 00545 DebugPrint(aTextout, "sample length %d \n", 00546 xmSample.mSampleLength); 00547 DebugPrint(aTextout, "loop start %d \n", xmSample.mLoopStart); 00548 DebugPrint(aTextout, "loop length %d \n", xmSample.mLoopLength); 00549 DebugPrint(aTextout, "volume %d \n", xmSample.mVolume); 00550 DebugPrint(aTextout, "finetune %d \n", xmSample.mFinetune); 00551 DebugPrint(aTextout, "type %d \n", xmSample.mType); 00552 DebugPrint(aTextout, " loop fwd? %d\n", 00553 (xmSample.mType & LOOP_FORWARD) ? 1 : 0); 00554 DebugPrint(aTextout, " loop pingpong? %d\n", 00555 (xmSample.mType & LOOP_PINGPONG) ? 1 : 0); 00556 DebugPrint(aTextout, " 16 bit? %d\n", 00557 (xmSample.mType & XMFORMAT_SAMPLE_16BIT) ? 1 : 0); 00558 DebugPrint(aTextout, "pan %d \n", xmSample.mPan); 00559 DebugPrint(aTextout, "relative note %d \n", 00560 xmSample.mRelativeNote); 00561 xmSample.mSampleName[21] = '\0'; 00562 DebugPrint(aTextout, "sample name %s \n", xmSample.mSampleName); 00563 00564 smp.mSize = xmSample.mSampleLength; 00565 smp.mVolume = xmSample.mVolume; 00566 smp.mPan = xmSample.mPan; 00567 smp.mLoopForward = (UINT8)((xmSample.mType & LOOP_FORWARD) ? 1 : 0); 00568 smp.mLoopPingpong = (UINT8)((xmSample.mType & LOOP_PINGPONG) ? 1 : 0); 00569 smp.m16Bit = (UINT8)((xmSample.mType & XMFORMAT_SAMPLE_16BIT) ? 1 : 0); 00570 smp.mLoopStart = xmSample.mLoopStart; 00571 smp.mLoopEnd = xmSample.mLoopStart + xmSample.mLoopLength - 1; 00572 00573 if (smp.mLoopStart == smp.mLoopEnd) 00574 { 00575 smp.mLoopPingpong = 0; 00576 smp.mLoopForward = 0; 00577 } 00578 00579 smp.mRelativeNote = xmSample.mRelativeNote; 00580 smp.mFinetune = xmSample.mFinetune; 00581 } 00582 00583 // Read samples 00584 for (j = 0; j < xmInstrumentHeader.mNbSamples; j++) 00585 { 00586 XFuXMSample &smp = ins.mSamples[j]; 00587 00588 if (smp.mSize > 0) 00589 { 00590 smp.mOffset = new INT8[smp.mSize]; 00591 memset((INT8 *)smp.mOffset, 0, smp.mSize * sizeof(INT8)); 00592 00593 if (smp.mOffset == NULL) 00594 { 00595 DebugPrint(aTextout, "! Memory allocation for sample " 00596 "%02X in instrument %02X failed \n", j, i); 00597 return 1; 00598 } 00599 00600 DebugPrint(aTextout, "Reading sample \n"); 00601 f->read((INT8 *)smp.mOffset, smp.mSize, 1); 00602 00603 if (smp.m16Bit) 00604 { 00605 INT16 os, ns; 00606 INT16 *temp = (INT16 *)smp.mOffset; 00607 os = 0; 00608 00609 smp.mSize >>= 1; 00610 smp.mLoopStart >>= 1; 00611 smp.mLoopEnd >>= 1; 00612 00613 if (mFlags & XFCAUDIO_16BIT) 00614 { 00615 UINT32 a; 00616 for (a = 0; a < smp.mSize; ++a) 00617 { 00618 ns = (INT16)(os + *(temp + a)); 00619 *((INT16 *)smp.mOffset + a) = ns; 00620 os = ns; 00621 } 00622 } 00623 else 00624 { 00625 UINT32 a; 00626 for (a = 0; a < smp.mSize; ++a) 00627 { 00628 ns = (INT16)(os + *(temp + a)); 00629 *((INT8 *)smp.mOffset + a) = (INT8)(ns >> 8); 00630 os = ns; 00631 } 00632 00633 smp.m16Bit = 0; 00634 00635 INT8 *temp = new INT8[smp.mSize]; 00636 memcpy(temp, smp.mOffset, smp.mSize); 00637 delete[] (INT8 *)smp.mOffset; 00638 smp.mOffset = temp; 00639 } 00640 } 00641 else 00642 { 00643 INT8 os, ns; 00644 os = 0; 00645 UINT32 a; 00646 for (a = 0; a < smp.mSize; a++) 00647 { 00648 ns = (INT8)(os + *((INT8 *)smp.mOffset + a)); 00649 *((INT8 *)smp.mOffset + a) = ns; 00650 os = ns; 00651 } 00652 } 00653 } 00654 } 00655 00656 ins.mVolumeFadeout = REALf(xmInstrument.mVolumeFadeout / 65536.0f); 00657 00658 if (xmInstrument.mVibratoRate) 00659 ins.mIsVibrato = 1; 00660 else 00661 ins.mIsVibrato = 0; 00662 00663 ins.mVibratoType = xmInstrument.mVibratoType; 00664 ins.mVibratoSweep = xmInstrument.mVibratoSweep; 00665 ins.mVibratoDepth = xmInstrument.mVibratoDepth; 00666 ins.mVibratoRate = xmInstrument.mVibratoRate; 00667 00668 DebugPrint(aTextout, "sampleheader size: %d \n", xmInstrument.mSampleHeaderSize); 00669 00670 DebugPrint(aTextout, "keyboard: "); 00671 00672 for (ii = 0; ii < 96; ii++) 00673 { 00674 DebugPrint(aTextout, "%d, ", xmInstrument.mKeyboard[ii]); 00675 if (((ii + 1) % 20) == 0) 00676 DebugPrint(aTextout, "\n "); 00677 } 00678 00679 memcpy(ins.mKeyboard, xmInstrument.mKeyboard, 96); 00680 00681 DebugPrint(aTextout, "\n"); 00682 DebugPrint(aTextout, "volume. envelope: "); 00683 00684 // if (xmInstrument.mVolEnvType & ENV_LOOP) 00685 // xmInstrument.mNbVolEnvPoints = 00686 // xmInstrument.mVolEnvLoopEnd + 1; 00687 00688 for (ii = 0; ii < xmInstrument.mNbVolEnvPoints * 2; ii++) 00689 { 00690 DebugPrint(aTextout, "%d, ", xmInstrument.mVolumeEnvelope[ii]); 00691 00692 if (((ii + 1) % 20) == 0) 00693 DebugPrint(aTextout, "\n "); 00694 } 00695 00696 DebugPrint(aTextout, "\n"); 00697 DebugPrint(aTextout, "pan. envelope: "); 00698 00699 // if (xmInstrument.mPanEnvType & ENV_LOOP) 00700 // xmInstrument.mNbPanEnvPoints = 00701 // xmInstrument.mPanEnvLoopEnd + 1; 00702 00703 for (ii = 0; ii < xmInstrument.mNbPanEnvPoints * 2; ii++) 00704 { 00705 DebugPrint(aTextout, "%d, ", xmInstrument.mPanningEnvelope[ii]); 00706 00707 if (((ii + 1) % 20) == 0) 00708 DebugPrint(aTextout, "\n "); 00709 } 00710 00711 // Volume envelope 00712 ins.mVolEnvType = xmInstrument.mVolEnvType; 00713 00714 if (xmInstrument.mVolEnvLoopStart != xmInstrument.mVolEnvLoopEnd) 00715 { 00716 ins.mVolEnvLoopStart = xmInstrument.mVolumeEnvelope[ 00717 xmInstrument.mVolEnvLoopStart * 2]; 00718 ins.mVolEnvLoopEnd = xmInstrument.mVolumeEnvelope[ 00719 xmInstrument.mVolEnvLoopEnd * 2]; 00720 } 00721 memset(ins.mVolumeEnvelope, 0, XMFORMAT_SIZEOF_ENVELOPE); 00722 00723 if (xmInstrument.mNbVolEnvPoints == 1) 00724 { 00725 // Volume envelope fix for trackers that don't follow FT2 standard 00726 ins.mVolumeEnvelope[0] = REALf(xmInstrument.mVolumeEnvelope[1] / 64.0f); 00727 } 00728 else 00729 { 00730 for (ii = 0; ii < xmInstrument.mNbVolEnvPoints - 1; ii++) 00731 { 00732 x1 = xmInstrument.mVolumeEnvelope[(ii * 2)]; 00733 y1 = xmInstrument.mVolumeEnvelope[(ii * 2) + 1]; 00734 x2 = xmInstrument.mVolumeEnvelope[((ii + 1) * 2)]; 00735 y2 = xmInstrument.mVolumeEnvelope[((ii + 1) * 2) + 1]; 00736 00737 dx = (y2 - y1) / (x2 - x1); 00738 00739 for (xx = x1; xx <= x2; xx++) 00740 { 00741 ins.mVolumeEnvelope[xx] = REALf(y1 / 64.0f); 00742 y1 += dx; 00743 } 00744 } 00745 } 00746 00747 if (xmInstrument.mVolEnvType & ENV_SUSTAIN) 00748 ins.mVolEnvSustain = xmInstrument.mVolumeEnvelope[ 00749 xmInstrument.mVolEnvSustain * 2]; 00750 00751 if (xmInstrument.mNbVolEnvPoints > 0) 00752 ins.mVolEnvEnd = xmInstrument.mVolumeEnvelope[ 00753 (xmInstrument.mNbVolEnvPoints - 1) * 2]; 00754 00755 // Panning envelope 00756 ins.mPanEnvType = xmInstrument.mPanEnvType; 00757 00758 if (xmInstrument.mPanEnvLoopStart != xmInstrument.mPanEnvLoopEnd) 00759 { 00760 ins.mPanEnvLoopStart = xmInstrument.mPanningEnvelope[ 00761 xmInstrument.mPanEnvLoopStart * 2]; 00762 ins.mPanEnvLoopEnd = xmInstrument.mPanningEnvelope[ 00763 xmInstrument.mPanEnvLoopEnd * 2]; 00764 } 00765 memset(ins.mPanningEnvelope, 0, XMFORMAT_SIZEOF_ENVELOPE); 00766 00767 if (xmInstrument.mNbPanEnvPoints == 1) 00768 { 00769 // Panning envelope fix for trackers that don't follow FT2 standard 00770 ins.mPanningEnvelope[0] = (UINT8)xmInstrument.mPanningEnvelope[1]; 00771 } 00772 else 00773 { 00774 for (ii = 0; ii < xmInstrument.mNbPanEnvPoints - 1; ii++) 00775 { 00776 x1 = xmInstrument.mPanningEnvelope[(ii * 2)]; 00777 y1 = xmInstrument.mPanningEnvelope[(ii * 2) + 1]; 00778 x2 = xmInstrument.mPanningEnvelope[((ii + 1) * 2)]; 00779 y2 = xmInstrument.mPanningEnvelope[((ii + 1) * 2) + 1]; 00780 00781 dx = (y2 - y1) / (x2 - x1); 00782 00783 for (xx = x1; xx < x2; xx++) 00784 { 00785 ins.mPanningEnvelope[xx] = (UINT8)((INT8)y1); 00786 y1 += dx; 00787 } 00788 } 00789 } 00790 00791 ins.mPanEnvSustain = xmInstrument.mPanningEnvelope[ 00792 xmInstrument.mPanEnvSustain * 2]; 00793 00794 if (xmInstrument.mNbPanEnvPoints > 0) 00795 ins.mPanEnvEnd = xmInstrument.mPanningEnvelope[ 00796 (xmInstrument.mNbPanEnvPoints - 1) * 2]; 00797 00798 DebugPrint(aTextout, "\n"); 00799 00800 DebugPrint(aTextout, "nof volpoints %d\n", 00801 xmInstrument.mNbVolEnvPoints); 00802 DebugPrint(aTextout, "nof panpoints %d\n", 00803 xmInstrument.mNbPanEnvPoints); 00804 DebugPrint(aTextout, "volume. sustain %d\n", 00805 xmInstrument.mVolEnvSustain); 00806 DebugPrint(aTextout, "volume. loop start %d\n", 00807 xmInstrument.mVolEnvLoopStart); 00808 DebugPrint(aTextout, "volume. loop end %d\n", 00809 xmInstrument.mVolEnvLoopEnd); 00810 DebugPrint(aTextout, "pan. sustain %d\n", 00811 xmInstrument.mPanEnvSustain); 00812 DebugPrint(aTextout, "pan. loop start %d\n", 00813 xmInstrument.mPanEnvLoopStart); 00814 DebugPrint(aTextout, "pan. loop end %d\n", 00815 xmInstrument.mPanEnvLoopEnd); 00816 DebugPrint(aTextout, "volume. type %d\n", xmInstrument.mVolEnvType); 00817 DebugPrint(aTextout, " env. on? %d\n", 00818 (xmInstrument.mVolEnvType & ENV_ON) ? 1 : 0); 00819 DebugPrint(aTextout, " env. sustain? %d\n", 00820 (xmInstrument.mVolEnvType & ENV_SUSTAIN) ? 1 : 0); 00821 DebugPrint(aTextout, " env. loop? %d \n", 00822 (xmInstrument.mVolEnvType & ENV_LOOP) ? 1 : 0); 00823 DebugPrint(aTextout, "pan. type %d\n", 00824 xmInstrument.mPanEnvType); 00825 00826 DebugPrint(aTextout, " env. on? %d\n", 00827 (xmInstrument.mPanEnvType & ENV_ON) ? 1 : 0); 00828 DebugPrint(aTextout, " env. sustain? %d\n", 00829 (xmInstrument.mPanEnvType & ENV_SUSTAIN) ? 1 : 0); 00830 DebugPrint(aTextout, " env. loop? %d \n", 00831 (xmInstrument.mPanEnvType & ENV_LOOP) ? 1 : 0); 00832 00833 DebugPrint(aTextout, "vibr. type %d \n", 00834 xmInstrument.mVibratoType); 00835 DebugPrint(aTextout, "vibr. sweep %d \n", 00836 xmInstrument.mVibratoSweep); 00837 DebugPrint(aTextout, "vibr. depth %d \n", 00838 xmInstrument.mVibratoDepth); 00839 DebugPrint(aTextout, "vibr. rate %d \n", 00840 xmInstrument.mVibratoRate); 00841 DebugPrint(aTextout, "volume. fadeout %d \n\n", 00842 xmInstrument.mVolumeFadeout); 00843 } 00844 else 00845 { 00846 f->seek(skip, SEEK_CUR); 00847 } 00848 00849 DebugPrint(aTextout, "-----\n\n"); 00850 } 00851 00852 mSong.mNbInstruments = mXMHeader.mNbInstruments; 00853 00854 DebugPrint(aTextout, "XM read. \n"); 00855 DebugPrint(aTextout, "Not changing pattern structure yet.. \n"); 00856 00857 f->close(); 00858 00859 return 0; 00860 } 00861 00862 00863 UINT32 XFuXMPlayer::getPeriod(INT8 aNote, INT8 aFinetune) 00864 { 00865 if (aNote < 0) aNote = 0; 00866 if (aNote > 96) aNote = 96; 00867 00868 return (7680 - (aNote << 6) - (aFinetune >> 1)); 00869 } 00870 00871 00872 UINT32 XFuXMPlayer::getSpeed(UINT32 aPeriod, FLOAT32 aSamplingRate) 00873 { 00874 INT32 freq; 00875 INT32 shift = (INT32)(aPeriod / 768); 00876 00877 if (shift >= 0) 00878 freq = linearFrequencyTable[aPeriod - (shift << 9) - (shift << 8)] >> shift; 00879 //return linearFrequencyTable[aPeriod % 768] >> shift; 00880 else 00881 freq = linearFrequencyTable[aPeriod - (shift << 9) - (shift << 8)] << (-shift); 00882 //return linearFrequencyTable[aPeriod % 768] << (-shift); 00883 00884 /* 00885 FLOAT32 freq = (FLOAT32)(8363.0f * pow(2.0f, (4608.f - (FLOAT32)period) / 768.0f)); 00886 */ 00887 00888 return (INT32)((freq / aSamplingRate) * FP_VALUE); 00889 } 00890 00891 00892 XFuXMFormatAtom XFuXMPlayer::getAtom() 00893 { 00894 UINT8 *XMFORMAT_pa = mPatternData[mPatternNb].mData; 00895 XFuXMFormatAtom ta; 00896 char b; 00897 ta.mNote = 0; 00898 ta.mVolume = 0; 00899 ta.mInstrumentNb = 0; 00900 ta.mEffectType = 0; 00901 ta.mEffectValue = 0; 00902 00903 b = *(XMFORMAT_pa + mPpoint++); 00904 if ((b & 128) == 128) 00905 { 00906 // Packed atom 00907 if ((b & 1) == 1) 00908 ta.mNote = *(XMFORMAT_pa + mPpoint++); 00909 if ((b & 2) == 2) 00910 ta.mInstrumentNb = *(XMFORMAT_pa + mPpoint++); 00911 if ((b & 4) == 4) 00912 ta.mVolume = *(XMFORMAT_pa + mPpoint++); 00913 if ((b & 8) == 8) 00914 ta.mEffectType = *(XMFORMAT_pa + mPpoint++); 00915 if ((b & 16) == 16) 00916 ta.mEffectValue = *(XMFORMAT_pa + mPpoint++); 00917 } 00918 else 00919 { 00920 // Normal atom 00921 ta.mNote = b; 00922 ta.mInstrumentNb = *(XMFORMAT_pa + mPpoint++); 00923 ta.mVolume = *(XMFORMAT_pa + mPpoint++); 00924 ta.mEffectType = *(XMFORMAT_pa + mPpoint++); 00925 ta.mEffectValue = *(XMFORMAT_pa + mPpoint++); 00926 } 00927 00928 return ta; 00929 } 00930 00931 00932 void XFuXMPlayer::initChannel(XFuXMChannel &aCh) 00933 { 00934 aCh.mIsValid = 1; 00935 aCh.mInitSample = 0; 00936 00937 // Initialize sample if valid note 00938 if ((aCh.mTa.mNote > 0) && (aCh.mTa.mNote < 97)) 00939 { 00940 aCh.mNote = (INT8)(aCh.mTa.mNote - 1); 00941 aCh.mInitSample = 1; 00942 00943 aCh.mTremorTicker = 0; 00944 aCh.mMultiRetrigTicker = 0; 00945 } 00946 else if (aCh.mTa.mNote != 0) 00947 aCh.mIsValid = 0; 00948 00949 aCh.mVolumeColumn = aCh.mTa.mVolume; 00950 00951 if (aCh.mTa.mInstrumentNb != 0) 00952 { 00953 // New instrument 00954 aCh.mInstrumentNb = (INT16)(aCh.mTa.mInstrumentNb - 1); 00955 00956 if (aCh.mInstrumentNb < mSong.mNbInstruments) 00957 { 00958 aCh.mCurrentInstrument = mInstruments[aCh.mInstrumentNb]; 00959 00960 if (aCh.mCurrentInstrument.mKeyboard[aCh.mNote] < aCh.mCurrentInstrument.mNbSamples) 00961 { 00962 if (aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]].mOffset != NULL) 00963 { 00964 aCh.mCurrentSample = aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]]; 00965 } 00966 else aCh.mIsValid = 0; 00967 } 00968 else aCh.mIsValid = 0; 00969 } 00970 else aCh.mIsValid = 0; 00971 00972 aCh.mVolume = aCh.mCurrentSample.mVolume; 00973 aCh.mBaseVolume = aCh.mVolume; 00974 00975 aCh.mPan = aCh.mCurrentSample.mPan; 00976 } 00977 else 00978 { 00979 if ((aCh.mInstrumentNb != -1) && (aCh.mInstrumentNb < mSong.mNbInstruments)) 00980 { 00981 aCh.mCurrentInstrument = mInstruments[aCh.mInstrumentNb]; 00982 00983 if (aCh.mCurrentInstrument.mKeyboard[aCh.mNote] < aCh.mCurrentInstrument.mNbSamples) 00984 { 00985 if (aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]].mOffset != NULL) 00986 { 00987 aCh.mCurrentSample = aCh.mCurrentInstrument.mSamples[aCh.mCurrentInstrument.mKeyboard[aCh.mNote]]; 00988 } 00989 else aCh.mIsValid = 0; 00990 } 00991 else aCh.mIsValid = 0; 00992 } 00993 else aCh.mIsValid = 0; 00994 } 00995 00996 aCh.mOldPeriod = aCh.mPeriod; 00997 00998 // Do not initialize sound if note delay or pattern delay effect on 00999 if ((aCh.mInitSample) || (mPatternDelayCounter != 0)) 01000 initSound(aCh); 01001 } 01002 01003 01004 void XFuXMPlayer::initSound(XFuXMChannel &aCh) 01005 { 01006 if (aCh.mIsValid) 01007 { 01008 // Initialize sample 01009 if (aCh.mInitSample) aCh.mIsSample = 1; 01010 01011 // New note 01012 aCh.mDirection = 1; 01013 01014 // Init vibrato 01015 /* Instrument vibrato is independent 01016 aCh.mIsVibrato = aCh.mCurrentInstrument.mIsVibrato; 01017 if (aCh.mCurrentInstrument.mVibratoDepth != 0) 01018 aCh.mVibratoDepth = aCh.mCurrentInstrument.mVibratoDepth; 01019 if (aCh.mCurrentInstrument.mVibratoRate != 0) 01020 aCh.mVibratoRate = aCh.mCurrentInstrument.mVibratoRate; 01021 */ 01022 aCh.mIsVibrato = 0; 01023 01024 if ((aCh.mVibratoWaveform & WAVEFORM_NO_RETRIG) == 0) aCh.mVibratoPointer = 0; 01025 if ((aCh.mTremoloWaveform & WAVEFORM_NO_RETRIG) == 0) aCh.mTremoloPointer = 0; 01026 01027 // Init volume envelope 01028 aCh.mVolEnvType = aCh.mCurrentInstrument.mVolEnvType; 01029 aCh.mVolEnvPointer = 0; 01030 aCh.mVolEnvSpeed = 1; 01031 aCh.mVolEnvLoopStart = aCh.mCurrentInstrument.mVolEnvLoopStart; 01032 aCh.mVolEnvLoopEnd = aCh.mCurrentInstrument.mVolEnvLoopEnd; 01033 aCh.mVolEnvSustain = aCh.mCurrentInstrument.mVolEnvSustain; 01034 01035 aCh.mVolumeFadeout = aCh.mCurrentInstrument.mVolumeFadeout; 01036 aCh.mVolumeFadeoutValue = REAL(1); 01037 01038 // Init panning envelope 01039 aCh.mPanEnvType = aCh.mCurrentInstrument.mPanEnvType; 01040 aCh.mPanEnvPointer = 0; 01041 aCh.mPanEnvSpeed = 1; 01042 aCh.mPanEnvLoopStart = aCh.mCurrentInstrument.mPanEnvLoopStart; 01043 aCh.mPanEnvLoopEnd = aCh.mCurrentInstrument.mPanEnvLoopEnd; 01044 aCh.mPanEnvSustain = aCh.mCurrentInstrument.mPanEnvSustain; 01045 01046 aCh.mSustainReleased = 0; 01047 01048 aCh.mOffset = aCh.mCurrentSample.mOffset; 01049 aCh.mFinetune = aCh.mCurrentSample.mFinetune; 01050 01051 if ((aCh.mEffectType != 0x3) && // No tone portamento 01052 (aCh.mEffectType != 0x5) && // No tone portamento + volume slide 01053 (aCh.mVolumeColumn < 0xF0)) // No volume column tone portamento 01054 aCh.mPointer = 0; // Reset pointer if no tone effect 01055 01056 aCh.mLength = (aCh.mCurrentSample.mSize << FP_BITS); 01057 aCh.mPeriod = getPeriod((INT8)(aCh.mNote + aCh.mCurrentSample.mRelativeNote), aCh.mFinetune); 01058 aCh.mBasePeriod = aCh.mPeriod; 01059 01060 aCh.mLoop = 0; 01061 if (aCh.mCurrentSample.mLoopForward) aCh.mLoop = LOOP_FORWARD; 01062 if (aCh.mCurrentSample.mLoopPingpong) aCh.mLoop = LOOP_PINGPONG; 01063 aCh.mLoopStart = (aCh.mCurrentSample.mLoopStart << FP_BITS); 01064 aCh.mLoopEnd = (aCh.mCurrentSample.mLoopEnd << FP_BITS); 01065 } 01066 else 01067 aCh.mIsSample = 0; 01068 } 01069 01070 01071 void XFuXMPlayer::notifyHandlers(XFuXMChannel &aCh) 01072 { 01073 XFuXMPlayerEvent event; 01074 01075 event.mNote = aCh.mNote; 01076 event.mInstrumentNb = aCh.mInstrumentNb; 01077 event.mVolume = aCh.mVolume; 01078 01079 if ((aCh.mEffectType != 0xE) && (aCh.mEffectType != 0x21)) 01080 { 01081 event.mEffectType = aCh.mEffectType; 01082 event.mEffectValue = aCh.mEffectValue; 01083 } 01084 else 01085 { 01086 event.mEffectType = (INT16)((aCh.mEffectType << 4) | (aCh.mEffectValue >> 4)); 01087 event.mEffectValue = (INT16)(aCh.mEffectValue & 0xF); 01088 } 01089 01090 event.mPlayer = this; 01091 01092 XFcLinkedList<XFuXMPlayerEventHandlerSlot>::forwardIterator i; 01093 XFuXMPlayerEventHandlerSlot temp; 01094 01095 for (i = mEventHandlers->forwardBegin(); i != mEventHandlers->forwardEnd(); ++i) 01096 { 01097 temp = i.getData(); 01098 01099 if (((temp.mEvent.mNote != -1) && (temp.mEvent.mNote == event.mNote)) || 01100 ((temp.mEvent.mInstrumentNb != -1) && (temp.mEvent.mInstrumentNb == event.mInstrumentNb)) || 01101 ((temp.mEvent.mEffectType != -1) && (temp.mEvent.mEffectType == event.mEffectType))) 01102 { 01103 temp.mHandler->handleXMPlayerEvent(event); 01104 } 01105 } 01106 } 01107 01108 01109 void XFuXMPlayer::initSong(INT16 aStartOrder) 01110 { 01111 INT i; 01112 01113 if ((aStartOrder < 0) || (aStartOrder >= mSong.mSongLength)) aStartOrder = 0; 01114 mCurrentOrder = (INT16)(aStartOrder - 1); 01115 01116 mPatternNb = mSong.mOrderTable[aStartOrder]; 01117 if (mPatternNb >= mSong.mNbPatterns) mPatternNb = mSong.mOrderTable[0]; 01118 01119 mCurrentRow = 1024; 01120 01121 mPatternDelayCounter = 0; 01122 mPatternDelayCounterTemp = 0; 01123 mJumpFlag = 0; 01124 mIsRead = 1; 01125 01126 mTickRate = (2.0f * mSong.mBpm / 5.0f); 01127 01128 mSamplesPerTick = (INT32)(mSampleRate / mTickRate); 01129 01130 mCurrentTick = (UINT8)(mSong.mTempo - 1); // Playing starts from last tick 01131 mSamplePointer = mSamplesPerTick - 1; // Playing starts from last sample of last tick 01132 01133 mTotalTicks = 0; 01134 01135 mSong.mGlobalVolume = 64; 01136 01137 for (i = 0; i < mSong.mNbChannels; i++) 01138 { 01139 XFuXMChannel &ch = mChannels[i]; 01140 01141 ch.mOffset = NULL; 01142 ch.mPointer = 0; 01143 ch.mLength = 0; 01144 ch.mInstrumentNb = -1; 01145 ch.mSpeed = 0; 01146 ch.mPeriod = 0; 01147 01148 ch.mLoop = 0; 01149 ch.mLoopStart = 0; 01150 ch.mLoopEnd = 0; 01151 01152 ch.mIsSample = 0; 01153 01154 ch.mVolume = 0; 01155 ch.mBaseVolume = 0; 01156 ch.mFinalOldVolume = 0; 01157 ch.mFinalVolumeSpeed = 0; 01158 01159 ch.mNote = 0; 01160 01161 ch.mDirection = 1; 01162 01163 ch.mVolEnvType = 0; 01164 ch.mVolEnvPointer = 0; 01165 ch.mVolEnvSpeed = 0; 01166 ch.mVolEnvLoopStart = 0; 01167 ch.mVolEnvLoopEnd = 0; 01168 ch.mVolEnvSustain = 0; 01169 ch.mVolEnvValue = 0; 01170 01171 ch.mPanEnvType = 0; 01172 ch.mPanEnvPointer = 0; 01173 ch.mPanEnvSpeed = 0; 01174 ch.mPanEnvLoopStart = 0; 01175 ch.mPanEnvLoopEnd = 0; 01176 ch.mPanEnvSustain = 0; 01177 ch.mPanEnvValue = 0; 01178 01179 ch.mVolumeFadeout = 0; 01180 ch.mVolumeFadeoutValue = 0; 01181 01182 ch.mSustainReleased = 0; 01183 01184 ch.mVolumeColumn = 0; 01185 01186 ch.mEffectType = 0; 01187 ch.mEffectValue = 0; 01188 ch.mTonePortamentoV = 0; 01189 ch.mVolumeSlideV = 0; 01190 ch.mGlobalVolumeSlideV = 0; 01191 ch.mFineVolumeSlideUpV = 0; 01192 ch.mFineVolumeSlideDownV = 0; 01193 ch.mFinePortamentoUpV = 0; 01194 ch.mFinePortamentoDownV = 0; 01195 ch.mFineVolumeSlideUpV = 0; 01196 ch.mFineVolumeSlideDownV = 0; 01197 ch.mGlobalVolumeSlideV = 0; 01198 ch.mMultiRetrigVolumeV = 0; 01199 ch.mMultiRetrigRateV = 0; 01200 ch.mTremorV = 0; 01201 ch.mExtraFinePortamentoUpV = 0; 01202 ch.mExtraFinePortamentoDownV = 0; 01203 01204 ch.mMultiRetrigTicker = 0; 01205 ch.mTremorTicker = 0; 01206 01207 ch.mPeriod = 0; 01208 ch.mBasePeriod = 0; 01209 ch.mOldPeriod = 0; 01210 ch.mDestPeriod = 0; 01211 01212 ch.mIsVibrato = 0; 01213 ch.mVibratoDepth = 0; 01214 ch.mVibratoRate = 0; 01215 ch.mVibratoPointer = 0; 01216 ch.mVibratoWaveform = WAVEFORM_SINEWAVE; 01217 01218 ch.mTremoloDepth = 0; 01219 ch.mTremoloRate = 0; 01220 ch.mTremoloPointer = 0; 01221 ch.mTremoloWaveform = WAVEFORM_SINEWAVE; 01222 } 01223 } 01224 01225 01226 INT32 XFuXMPlayer::getTick() 01227 { 01228 return (INT32)((mTotalTicks * 1000) / mSampleRate); 01229 } 01230 01231 01232 INT16 XFuXMPlayer::getCurrentOrder() 01233 { 01234 return mCurrentOrder; 01235 } 01236 01237 01238 void XFuXMPlayer::addHandler(XFuXMPlayerEvent aEvent, XFuXMPlayerEventHandler *aHandler) 01239 { 01240 if (aHandler != NULL) 01241 { 01242 XFuXMPlayerEventHandlerSlot temp; 01243 temp.mEvent = aEvent; 01244 temp.mHandler = aHandler; 01245 01246 mEventHandlers->addLast(temp); 01247 } 01248 } 01249 01250 01251 INT XFuXMPlayer::removeHandler(XFuXMPlayerEventHandler *aHandler) 01252 { 01253 if (aHandler != NULL) 01254 { 01255 XFuXMPlayerEventHandlerSlot temp; 01256 temp.mHandler = aHandler; 01257 01258 return mEventHandlers->remove(temp); 01259 } 01260 01261 return 0; 01262 } 01263 01264 01265 void XFuXMPlayer::removeHandlers() 01266 { 01267 XFcLinkedList<XFuXMPlayerEventHandlerSlot>::forwardIterator i = mEventHandlers->forwardBegin(); 01268 XFuXMPlayerEventHandlerSlot temp; 01269 01270 while (i.isValid()) 01271 { 01272 mEventHandlers->remove(i); 01273 } 01274 } 01275 01276 01277 void XFuXMPlayer::stop() 01278 { 01279 initSong(0); 01280 } 01281 01282 01283 // For MSVC 01284 #pragma warning(disable:4244) 01285 01286 UINT32 XFuXMPlayer::stream(void *aBuf, INT32 aSamples) 01287 { 01288 INT32 c = 0; 01289 INT32 cLeft = 0, cRight = 0; 01290 01291 INT32 chan; 01292 01293 INT32 index; 01294 INT32 counter; 01295 INT32 indicesLeft; 01296 INT32 ticksLeft; 01297 INT32 samplesToRender; 01298 01299 INT32 delta; 01300 INT32 val1, val2; 01301 INT32 value; 01302 INT32 temp; 01303 01304 XFuXMFormatAtom ta; 01305 INT16 *vibratoTable = mSineWaveTable; 01306 INT16 *tremoloTable = mSineWaveTable; 01307 01308 for (index = 0; index < aSamples; ) 01309 { 01310 if (++mSamplePointer == mSamplesPerTick) 01311 { 01312 // Tick finished 01313 mSamplePointer = 0; 01314 01315 mRamp = 0; 01316 01317 if (mIsRead && (++mCurrentTick == mSong.mTempo)) 01318 { 01319 // Row finished 01320 mCurrentTick = 0; 01321 01322 if (mPatternDelayCounter == 0) mCurrentRow++; 01323 else mPatternDelayCounter--; 01324 01325 if ((mCurrentRow >= mXMPatternHeaders[mPatternNb].mNbRows) || (mJumpFlag != 0)) 01326 { 01327 // Pattern finished 01328 mCurrentOrder++; 01329 if (mCurrentOrder >= mSong.mSongLength) mCurrentOrder = mSong.mRestartPosition; 01330 01331 mPatternNb = mSong.mOrderTable[mCurrentOrder]; 01332 if (mPatternNb >= mSong.mNbPatterns) mPatternNb = mSong.mOrderTable[0]; 01333 01334 if (mJumpFlag == 0) mCurrentRow = 0; 01335 mPpoint = mPatternData[mPatternNb].mRows[mCurrentRow]; 01336 01337 mJumpFlag = 0; 01338 } 01339 01340 for (chan = 0; chan < mSong.mNbChannels; chan++) 01341 { 01342 XFuXMChannel &ch = mChannels[chan]; 01343 01344 if (mPatternDelayCounter == 0) 01345 { 01346 ta = getAtom(); // Get track data 01347 01348 ch.mTa = ta; 01349 01350 ch.mEffectType = ta.mEffectType; 01351 ch.mEffectValue = ta.mEffectValue; 01352 01353 if (!((ch.mEffectType == 0xE) && 01354 // No change if note delay effect 01355 (((ch.mEffectValue >> 4) & 0xF) == 0xD))) 01356 { 01357 initChannel(ch); 01358 } 01359 } 01360 01361 // Volume column effects 01362 if (ch.mVolumeColumn != 0) 01363 { 01364 // Set volume 01365 if ((ch.mVolumeColumn >= 0x10) && (ch.mVolumeColumn <= 0x50)) 01366 { 01367 ch.mVolume = (INT8)(ch.mVolumeColumn - 0x10); 01368 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01369 ch.mBaseVolume = ch.mVolume; 01370 } 01371 else 01372 { 01373 switch (ch.mVolumeColumn >> 4) 01374 { 01375 case 0x8: // Fine volume slide down (arrow down) 01376 if (ch.mVolume > 0) ch.mVolume -= (ch.mVolumeColumn & 0xF); 01377 ch.mBaseVolume = ch.mVolume; 01378 break; 01379 01380 case 0x9: // Fine volume slide up (arrow up) 01381 if (ch.mVolume < 0x40) ch.mVolume += (ch.mVolumeColumn & 0xF); 01382 ch.mBaseVolume = ch.mVolume; 01383 break; 01384 01385 case 0xA: // Set vibrato speed (Sxy) 01386 if ((ch.mVolumeColumn & 0xF) != 0) 01387 ch.mVibratoRate = (UINT8)(ch.mVolumeColumn & 0xF); 01388 break; 01389 01390 case 0xB: // Set vibrato depth (Vxy) 01391 if ((ch.mVolumeColumn & 0xF) != 0) 01392 { 01393 ch.mVibratoDepth = (UINT8)((ch.mVolumeColumn & 0xF) * 4); 01394 ch.mIsVibrato = 1; 01395 } 01396 break; 01397 01398 case 0xC: // Set panning (Pxy) 01399 ch.mPan = (UINT8)((ch.mVolumeColumn & 0xF) << 4); 01400 break; 01401 01402 case 0xD: // Panning slide left (left arrow) 01403 if (ch.mPan > 0) ch.mPan -= (ch.mVolumeColumn & 0xF); 01404 break; 01405 01406 case 0xE: // Panning slide right (right arrow) 01407 if (ch.mPan < 0xFF) ch.mPan += (ch.mVolumeColumn & 0xF); 01408 break; 01409 01410 case 0xF: // Tone portamento (Mxy) 01411 if ((ch.mVolumeColumn & 0xF) != 0) 01412 ch.mTonePortamentoV = (UINT8)((ch.mVolumeColumn & 0xF) << 4); 01413 01414 if ((ch.mTa.mNote != 0) && (ch.mTa.mNote != 97)) 01415 { 01416 ch.mDestPeriod = ch.mPeriod; 01417 ch.mPeriod = ch.mOldPeriod; 01418 } 01419 break; 01420 } 01421 } 01422 } 01423 01424 // Row effects 01425 switch (ch.mEffectType) 01426 { 01427 case 0x0: // Arpeggio (0xy) 01428 if (ch.mEffectValue != 0) ch.mPeriod = ch.mBasePeriod; 01429 break; 01430 01431 case 0x1: // Portamento up (1xy) 01432 if (ch.mEffectValue != 0) ch.mPortamentoUpV = ch.mEffectValue; 01433 break; 01434 01435 case 0x2: // Portamento down (2xy) 01436 if (ch.mEffectValue != 0) ch.mPortamentoDownV = ch.mEffectValue; 01437 break; 01438 01439 case 0x3: // Tone portamento (3xy) 01440 if (ch.mOldPeriod != 0) 01441 { 01442 if (ch.mEffectValue != 0) ch.mTonePortamentoV = ch.mEffectValue; 01443 01444 if ((ch.mTa.mNote != 0) && (ch.mTa.mNote != 97)) 01445 { 01446 ch.mDestPeriod = ch.mPeriod; 01447 ch.mPeriod = ch.mOldPeriod; 01448 ch.mBasePeriod = ch.mPeriod; 01449 } 01450 } 01451 break; 01452 01453 case 0x4: // Vibrato (4xy) 01454 if ((ch.mEffectValue & 0xF) != 0) 01455 ch.mVibratoDepth = (UINT8)((ch.mEffectValue & 0xF) * 4); 01456 01457 if ((ch.mEffectValue >> 4) != 0) 01458 ch.mVibratoRate = (UINT8)(ch.mEffectValue >> 4); 01459 01460 ch.mIsVibrato = 1; 01461 break; 01462 01463 case 0x5: // Tone portamento + volume slide (5xy) 01464 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01465 break; 01466 01467 case 0x6: // Vibrato + volume slide (6xy) 01468 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01469 01470 ch.mIsVibrato = 1; 01471 break; 01472 01473 case 0x7: // Tremolo (7xy) 01474 if ((ch.mEffectValue & 0xF) != 0) 01475 ch.mTremoloDepth = (UINT8)(ch.mEffectValue & 0xF); 01476 01477 if ((ch.mEffectValue >> 4) != 0) 01478 ch.mTremoloRate = (UINT8)(ch.mEffectValue >> 4); 01479 break; 01480 01481 case 0x8: // Set panning (8xy) 01482 ch.mPan = ch.mEffectValue; 01483 break; 01484 01485 case 0x9: // Sample offset (9xy) 01486 ch.mPointer = ch.mEffectValue << (8 + FP_BITS); 01487 XFCASSERT(ch.mPointer < ch.mLength); 01488 // FastTracker2 behaviour when not in debug mode, 01489 // if offset is beyond sample length, stop sample 01490 if (ch.mPointer >= ch.mLength) ch.mIsSample = 0; 01491 break; 01492 01493 case 0xA: // Volume slide (Axy) 01494 if (ch.mEffectValue != 0) ch.mVolumeSlideV = ch.mEffectValue; 01495 break; 01496 01497 case 0xB: // Jump to pattern (Bxy) 01498 if (mJumpFlag == 0) 01499 { 01500 mCurrentRow = -1; 01501 mCurrentOrder = (INT16)(ch.mEffectValue - 1); 01502 mJumpFlag = 1; 01503 } 01504 break; 01505 01506 case 0xC: // Volume (Cxy) 01507 ch.mVolume = ch.mEffectValue; 01508 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01509 ch.mBaseVolume = ch.mVolume; 01510 break; 01511 01512 case 0xD: // Pattern break (Dxy) 01513 if (mJumpFlag == 0) 01514 { 01515 mCurrentRow = (INT16)(ch.mEffectValue - 1); 01516 mJumpFlag = 1; 01517 } 01518 break; 01519 01520 case 0xE: // Extra effects (Exy) 01521 switch ((ch.mEffectValue >> 4)) 01522 { 01523 case 0x1: // Fine portamento up (E1y) 01524 if ((ch.mEffectValue & 0xF) != 0) 01525 ch.mFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01526 01527 ch.mPeriod -= ch.mFinePortamentoUpV * 4; 01528 ch.mBasePeriod = ch.mPeriod; 01529 break; 01530 01531 case 0x2: // Fine portamento down (E2y) 01532 if ((ch.mEffectValue & 0xF) != 0) 01533 ch.mFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01534 01535 ch.mPeriod += ch.mFinePortamentoUpV * 4; 01536 ch.mBasePeriod = ch.mPeriod; 01537 break; 01538 01539 case 0x3: // Glissando control (E3y), FIX ME! 01540 break; 01541 01542 case 0x4: // Vibrato waveform (E4y) 01543 if ((ch.mEffectValue & 0xF) < 7) 01544 ch.mVibratoWaveform = (UINT8)(ch.mEffectValue & 0xF); 01545 break; 01546 01547 case 0x5: // Set finetune (E5y) 01548 ch.mFinetune = (INT8)((ch.mEffectValue & 0xF) << 1); 01549 break; 01550 01551 case 0x6: // Pattern loop (E6y), FIX ME! 01552 break; 01553 01554 case 0x7: // Tremolo waveform (E7y) 01555 if ((ch.mEffectValue & 0xF) < 7) 01556 ch.mTremoloWaveform = (UINT8)(ch.mEffectValue & 0xF); 01557 break; 01558 01559 case 0xA: // Fine volume slide up (EAy) 01560 if ((ch.mEffectValue & 0xF) != 0) 01561 ch.mFineVolumeSlideUpV = (UINT8)(ch.mEffectValue & 0xF); 01562 01563 if (ch.mVolume < 0x40) ch.mVolume += ch.mFineVolumeSlideUpV; 01564 ch.mBaseVolume = ch.mVolume; 01565 break; 01566 01567 case 0xB: // Fine volume slide down (EBy) 01568 if ((ch.mEffectValue & 0xF) != 0) 01569 ch.mFineVolumeSlideDownV = (UINT8)(ch.mEffectValue & 0xF); 01570 01571 if (ch.mVolume > 0) ch.mVolume -= ch.mFineVolumeSlideDownV; 01572 ch.mBaseVolume = ch.mVolume; 01573 break; 01574 01575 case 0xE: // Pattern delay (EEy) 01576 if (mPatternDelayCounter == 0) 01577 mPatternDelayCounterTemp = (UINT8)(ch.mEffectValue & 0xF); 01578 break; 01579 01580 } 01581 break; 01582 01583 case 0xF: // Tempo or BPM change (Fxy) 01584 if (ch.mEffectValue < 32) 01585 { 01586 mSong.mTempo = ch.mEffectValue; 01587 if (mSong.mTempo == 0) mIsRead = 0; 01588 } 01589 else 01590 { // BPM 01591 mSong.mBpm = ch.mEffectValue; 01592 mTickRate = 2.0f * mSong.mBpm / 5.0f; 01593 01594 mSamplesPerTick = (INT)(mSampleRate / mTickRate); 01595 } 01596 break; 01597 01598 case 0x10: // Global volume (Gxy) 01599 mSong.mGlobalVolume = ch.mEffectValue; 01600 01601 if (mSong.mGlobalVolume > 0x40) mSong.mGlobalVolume = 0x40; 01602 break; 01603 01604 case 0x11: // Global volume slide (Hxy) 01605 if (ch.mEffectValue != 0) ch.mGlobalVolumeSlideV = ch.mEffectValue; 01606 01607 if (mSong.mGlobalVolume < 0x40) 01608 mSong.mGlobalVolume += (ch.mGlobalVolumeSlideV >> 4) << 1; 01609 if (mSong.mGlobalVolume > 0) 01610 mSong.mGlobalVolume -= (ch.mGlobalVolumeSlideV & 0xF) << 1; 01611 break; 01612 01613 case 0x15: // Set envelope position (Lxy), FIX ME! 01614 break; 01615 01616 case 0x19: // Panning slide (Pxy) 01617 if (ch.mEffectValue != 0) ch.mPanningSlideV = ch.mEffectValue; 01618 break; 01619 01620 case 0x1B: // Multi retrig note (Rxy) 01621 if ((ch.mEffectValue >> 4) != 0) 01622 ch.mMultiRetrigVolumeV = (UINT8)(ch.mEffectValue >> 4); 01623 01624 if ((ch.mEffectValue & 0xF) != 0) 01625 ch.mMultiRetrigRateV = (UINT8)(ch.mEffectValue & 0xF); 01626 01627 if (ch.mMultiRetrigRateV != 0) 01628 { 01629 if ((ch.mMultiRetrigTicker % ch.mMultiRetrigRateV) == 0) 01630 { 01631 ch.mInitSample = 1; 01632 initSound(ch); 01633 01634 if ((ch.mMultiRetrigVolumeV != 8) && (ch.mMultiRetrigTicker != 0)) 01635 { 01636 // Don't affect volume on first tick 01637 switch (ch.mMultiRetrigVolumeV) 01638 { 01639 case 0x1: 01640 ch.mVolume -= 1; 01641 break; 01642 case 0x2: 01643 ch.mVolume -= 2; 01644 break; 01645 case 0x3: 01646 ch.mVolume -= 4; 01647 break; 01648 case 0x4: 01649 ch.mVolume -= 8; 01650 break; 01651 case 0x5: 01652 ch.mVolume -= 16; 01653 break; 01654 case 0x6: 01655 ch.mVolume = (INT8)((ch.mVolume * 2) / 3); 01656 break; 01657 case 0x7: 01658 ch.mVolume >>= 1; 01659 break; 01660 case 0x9: 01661 ch.mVolume += 1; 01662 break; 01663 case 0xA: 01664 ch.mVolume += 2; 01665 break; 01666 case 0xB: 01667 ch.mVolume += 4; 01668 break; 01669 case 0xC: 01670 ch.mVolume += 8; 01671 break; 01672 case 0xD: 01673 ch.mVolume += 16; 01674 break; 01675 case 0xE: 01676 ch.mVolume = (INT8)((ch.mVolume * 3) / 2); 01677 break; 01678 case 0xF: 01679 ch.mVolume <<= 1; 01680 break; 01681 } 01682 01683 ch.mBaseVolume = ch.mVolume; 01684 } 01685 } 01686 } 01687 01688 ch.mMultiRetrigTicker++; 01689 break; 01690 01691 case 0x1D: // Tremor (Txy) 01692 if (ch.mEffectValue != 0) ch.mTremorV = ch.mEffectValue; 01693 01694 if (ch.mTremorV != 0) 01695 { 01696 if ((unsigned char)(ch.mTremorTicker % 01697 ((ch.mTremorV >> 4) + (ch.mTremorV & 0xF) + 2)) < 01698 (ch.mTremorV >> 4) + 1) 01699 ch.mVolume = ch.mBaseVolume; 01700 else 01701 ch.mVolume = 0; 01702 } 01703 break; 01704 01705 case 0x21: // Extra fine portamento up/down (X1y/X2y) 01706 switch(ch.mEffectValue >> 4) 01707 { 01708 case 0x1: // Extra fine portamento up (X1y) 01709 if ((ch.mEffectValue & 0xF) != 0) 01710 ch.mExtraFinePortamentoUpV = (UINT8)(ch.mEffectValue & 0xF); 01711 01712 ch.mPeriod -= ch.mExtraFinePortamentoUpV; 01713 ch.mBasePeriod = ch.mPeriod; 01714 break; 01715 case 0x2: // Extra fine portamento down (X2y) 01716 if ((ch.mEffectValue & 0xF) != 0) 01717 ch.mExtraFinePortamentoDownV = (UINT8)(ch.mEffectValue & 0xF); 01718 01719 ch.mPeriod -= ch.mExtraFinePortamentoUpV; 01720 ch.mBasePeriod = ch.mPeriod; 01721 break; 01722 } 01723 break; 01724 } 01725 01726 notifyHandlers(ch); 01727 01728 // Key off (Kxy) 01729 if ((ch.mEffectType == 0x14) || (ch.mTa.mNote == 97)) 01730 { 01731 if (ch.mSustainReleased == 0) 01732 { 01733 ch.mSustainReleased = 1; 01734 if (ch.mVolEnvType & ENV_SUSTAIN) 01735 ch.mVolEnvSpeed = 1; // Start envelope 01736 01737 if (ch.mVolEnvType == 0) 01738 ch.mVolume = 0; 01739 01740 // FIX ME!!! PANNING ENVELOPE STUFF MISSING!!! 01741 } 01742 } 01743 } 01744 01745 if (mPatternDelayCounterTemp != 0) 01746 { 01747 mPatternDelayCounter = mPatternDelayCounterTemp; 01748 mPatternDelayCounterTemp = 0; 01749 } 01750 } 01751 else if (mSong.mTempo != 0) 01752 { 01753 // Tick effects 01754 for (chan = 0; chan < mSong.mNbChannels; chan++) 01755 { 01756 XFuXMChannel &ch = mChannels[chan]; 01757 01758 if (ch.mVolumeColumn != 0) 01759 { 01760 switch(ch.mVolumeColumn >> 4) 01761 { 01762 case 0x6: // Volume slide down (-xy) 01763 ch.mVolume -= (ch.mVolumeColumn & 0xF); 01764 ch.mBaseVolume = ch.mVolume; 01765 break; 01766 01767 case 0x7: // Volume slide up (+xy) 01768 ch.mVolume += (ch.mVolumeColumn & 0xF); 01769 ch.mBaseVolume = ch.mVolume; 01770 break; 01771 01772 case 0xF: // Tone portamento (Mxy) 01773 if (ch.mOldPeriod != 0) 01774 { 01775 if (ch.mDestPeriod > ch.mPeriod) 01776 { 01777 ch.mPeriod += (ch.mTonePortamentoV * 4); 01778 if (ch.mPeriod > ch.mDestPeriod) 01779 ch.mPeriod = ch.mDestPeriod; 01780 } 01781 else if (ch.mDestPeriod < ch.mPeriod) 01782 { 01783 ch.mPeriod -= (ch.mTonePortamentoV * 4); 01784 if (ch.mPeriod < ch.mDestPeriod) 01785 ch.mPeriod = ch.mDestPeriod; 01786 } 01787 01788 ch.mBasePeriod = ch.mPeriod; 01789 } 01790 break; 01791 } 01792 } 01793 01794 switch (ch.mEffectType) 01795 { 01796 case 0x0: // Arpeggio (0xy) 01797 if (ch.mEffectValue != 0) 01798 { 01799 switch (mCurrentTick % 3) 01800 { 01801 case 0: 01802 ch.mPeriod = ch.mBasePeriod; 01803 break; 01804 case 1: 01805 ch.mPeriod = ch.mBasePeriod - (ch.mEffectValue >> 4) * 64; 01806 break; 01807 case 2: 01808 ch.mPeriod = ch.mBasePeriod - (ch.mEffectValue & 0xF) * 64; 01809 break; 01810 } 01811 } 01812 break; 01813 01814 case 0x1: // Portamento up (1xy) 01815 ch.mPeriod -= (ch.mPortamentoUpV * 4); 01816 ch.mBasePeriod = ch.mPeriod; 01817 break; 01818 01819 case 0x2: // Portamento down (2xy) 01820 ch.mPeriod += (ch.mPortamentoDownV * 4); 01821 ch.mBasePeriod = ch.mPeriod; 01822 break; 01823 01824 case 0x7: // Tremolo (7xy), FIX ME! 01825 if (ch.mTremoloWaveform & WAVEFORM_SINEWAVE) 01826 tremoloTable = mSineWaveTable; 01827 else if (ch.mTremoloWaveform & WAVEFORM_SQUAREWAVE) 01828 tremoloTable = mSquareWaveTable; 01829 else if (ch.mTremoloWaveform & WAVEFORM_RAMPDOWN) 01830 tremoloTable = mRampDownTable; 01831 // FIX ME! Random waveform not supported 01832 01833 ch.mVolume = (INT8)(ch.mBaseVolume + 01834 ((tremoloTable[ch.mTremoloPointer] * ch.mTremoloDepth) >> 6)); 01835 ch.mTremoloPointer = (UINT8)( 01836 (ch.mTremoloPointer + ch.mTremoloRate) % XMFORMAT_SIZEOF_WAVEFORM); 01837 break; 01838 01839 case 0xE: // Extra effects (Exy) 01840 switch ((ch.mEffectValue >> 4)) 01841 { 01842 case 0x9: // Retrig note (E9y) 01843 if (((ch.mEffectValue & 0xF) != 0) && 01844 ((mCurrentTick % (ch.mEffectValue & 0xF)) == 0)) 01845 { 01846 ch.mInitSample = 1; 01847 initSound(ch); 01848 } 01849 break; 01850 01851 case 0xC: // Note cut (ECy) 01852 if (mCurrentTick == (ch.mEffectValue & 0xF)) 01853 { 01854 ch.mVolume = 0; 01855 ch.mBaseVolume = ch.mVolume; 01856 } 01857 break; 01858 01859 case 0xD: // Note delay (EDy) 01860 if (mCurrentTick == (ch.mEffectValue & 0xF)) 01861 { 01862 initChannel(ch); 01863 } 01864 break; 01865 } 01866 break; 01867 01868 case 0x19: // Panning slide (Pxy) 01869 ch.mPan += (ch.mPanningSlideV >> 4); 01870 if (ch.mPan > 0xFF) ch.mPan = 0xFF; 01871 01872 ch.mPan -= (ch.mPanningSlideV & 0xF); 01873 if (ch.mPan < 0) ch.mPan = 0; 01874 01875 break; 01876 01877 case 0x1B: // Multi retrig note (Rxy) 01878 if (ch.mMultiRetrigRateV != 0) 01879 { 01880 if ((ch.mMultiRetrigTicker % ch.mMultiRetrigRateV) == 0) 01881 { 01882 ch.mInitSample = 1; 01883 initSound(ch); 01884 01885 if ((ch.mMultiRetrigVolumeV != 8) && (ch.mMultiRetrigTicker != 0)) 01886 { 01887 // Don't affect volume on first tick 01888 switch (ch.mMultiRetrigVolumeV) 01889 { 01890 case 0x1: 01891 ch.mVolume -= 1; 01892 break; 01893 case 0x2: 01894 ch.mVolume -= 2; 01895 break; 01896 case 0x3: 01897 ch.mVolume -= 4; 01898 break; 01899 case 0x4: 01900 ch.mVolume -= 8; 01901 break; 01902 case 0x5: 01903 ch.mVolume -= 16; 01904 break; 01905 case 0x6: 01906 ch.mVolume = (INT8)(ch.mVolume * 2.0f / 3.0f); 01907 break; 01908 case 0x7: 01909 ch.mVolume >>= 1; 01910 break; 01911 case 0x9: 01912 ch.mVolume += 1; 01913 break; 01914 case 0xA: 01915 ch.mVolume += 2; 01916 break; 01917 case 0xB: 01918 ch.mVolume += 4; 01919 break; 01920 case 0xC: 01921 ch.mVolume += 8; 01922 break; 01923 case 0xD: 01924 ch.mVolume += 16; 01925 break; 01926 case 0xE: 01927 ch.mVolume = (INT8)(ch.mVolume * 3.0f / 2.0f); 01928 break; 01929 case 0xF: 01930 ch.mVolume <<= 1; 01931 break; 01932 } 01933 01934 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01935 else if (ch.mVolume < 0) ch.mVolume = 0; 01936 01937 ch.mBaseVolume = ch.mVolume; 01938 } 01939 } 01940 } 01941 01942 ch.mMultiRetrigTicker++; 01943 break; 01944 01945 case 0x1D: // Tremor (Txy) 01946 if (ch.mTremorV != 0) 01947 { 01948 if ((unsigned char)(ch.mTremorTicker % 01949 ((ch.mTremorV >> 4) + (ch.mTremorV & 0xF) + 2)) < 01950 (ch.mTremorV >> 4) + 1) 01951 ch.mVolume = ch.mBaseVolume; 01952 else 01953 ch.mVolume = 0; 01954 } 01955 01956 ch.mTremorTicker++; 01957 break; 01958 01959 } 01960 01961 // Tone portamento (3xy) / 01962 // tone portamento + volume slide (5xy) / 01963 // volume column tone portamento (Mxy) 01964 if ((ch.mEffectType == 0x3) || (ch.mEffectType == 0x5)) 01965 { 01966 if (ch.mOldPeriod != 0) 01967 { 01968 if (ch.mDestPeriod > ch.mPeriod) 01969 { 01970 ch.mPeriod += (ch.mTonePortamentoV * 4); 01971 if (ch.mPeriod > ch.mDestPeriod) ch.mPeriod = ch.mDestPeriod; 01972 } 01973 else if (ch.mDestPeriod < ch.mPeriod) 01974 { 01975 ch.mPeriod -= (ch.mTonePortamentoV * 4); 01976 if (ch.mPeriod < ch.mDestPeriod) ch.mPeriod = ch.mDestPeriod; 01977 } 01978 01979 ch.mBasePeriod = ch.mPeriod; 01980 } 01981 } 01982 01983 // Volume slide (Axy) / 01984 // tone portamento + volume slide (5xy) / 01985 // vibrato + volume slide (6xy) 01986 if ((ch.mEffectType == 0xA) || (ch.mEffectType == 0x5) || (ch.mEffectType == 0x6)) 01987 { 01988 ch.mVolume += (ch.mVolumeSlideV >> 4); 01989 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 01990 01991 ch.mVolume -= (ch.mVolumeSlideV & 0xF); 01992 if (ch.mVolume < 0) ch.mVolume = 0; 01993 01994 ch.mBaseVolume = ch.mVolume; 01995 } 01996 01997 // Vibrato 01998 if (ch.mIsVibrato) 01999 { 02000 if (ch.mVibratoWaveform & WAVEFORM_SINEWAVE) 02001 vibratoTable = mSineWaveTable; 02002 else if (ch.mVibratoWaveform & WAVEFORM_SQUAREWAVE) 02003 vibratoTable = mSquareWaveTable; 02004 else if (ch.mVibratoWaveform & WAVEFORM_RAMPDOWN) 02005 vibratoTable = mRampDownTable; 02006 // FIX ME! Random waveform not supported 02007 02008 ch.mPeriod = ch.mBasePeriod + 02009 ((vibratoTable[ch.mVibratoPointer] * ch.mVibratoDepth) >> 7); 02010 ch.mVibratoPointer = (UINT8)( 02011 (ch.mVibratoPointer + ch.mVibratoRate) % XMFORMAT_SIZEOF_WAVEFORM); 02012 } 02013 } 02014 } 02015 02016 for (chan = 0; chan < mSong.mNbChannels; chan++) 02017 { 02018 XFuXMChannel &ch = mChannels[chan]; 02019 XFuXMInstrument *in = NULL; 02020 02021 if ((ch.mInstrumentNb != -1) && (ch.mInstrumentNb < mSong.mNbInstruments)) 02022 { 02023 in = &mInstruments[ch.mInstrumentNb]; 02024 02025 ch.mFinalOldVolume = ch.mFinalVolume; 02026 02027 // Volume envelope 02028 if (ch.mVolEnvType & ENV_ON) 02029 { 02030 ch.mVolEnvValue = in->mVolumeEnvelope[ch.mVolEnvPointer]; 02031 02032 if ((ch.mVolEnvType & ENV_SUSTAIN) && 02033 (ch.mVolEnvPointer == ch.mVolEnvSustain) && 02034 (ch.mSustainReleased == 0)) 02035 { 02036 // Sustain point, stop envelope 02037 ch.mVolEnvSpeed = 0; 02038 } 02039 02040 // Fix for trackers which don't follow FT2 standard in envelopes 02041 if (in->mVolEnvEnd != 0) ch.mVolEnvPointer += ch.mVolEnvSpeed; 02042 02043 if (ch.mVolEnvType & ENV_LOOP) 02044 { 02045 // Envelope loop 02046 if (ch.mVolEnvPointer == ch.mVolEnvLoopEnd) 02047 ch.mVolEnvPointer = ch.mVolEnvLoopStart; 02048 } 02049 else 02050 { 02051 if (ch.mVolEnvPointer == in->mVolEnvEnd) 02052 ch.mVolEnvSpeed = 0; 02053 } 02054 02055 if (ch.mSustainReleased) 02056 { 02057 ch.mVolumeFadeoutValue -= (ch.mVolumeFadeout * 2); 02058 if (ch.mVolumeFadeoutValue < 0) ch.mVolumeFadeoutValue = 0; 02059 } 02060 } else ch.mVolEnvValue = REALf(1.0f); // No volume envelope 02061 02062 // Panning envelope 02063 if (ch.mPanEnvType) 02064 { 02065 ch.mPanEnvValue = in->mPanningEnvelope[ch.mPanEnvPointer]; 02066 02067 if ((ch.mPanEnvType & ENV_SUSTAIN) && 02068 (ch.mPanEnvPointer == ch.mPanEnvSustain) && 02069 (ch.mSustainReleased == 0)) 02070 { 02071 // Sustain point, stop envelope 02072 ch.mPanEnvSpeed = 0; 02073 } 02074 02075 // Fix for trackers which don't follow FT2 standard in envelopes 02076 if (in->mPanEnvEnd != 0) ch.mPanEnvPointer += ch.mPanEnvSpeed; 02077 02078 if (ch.mPanEnvType & ENV_LOOP) 02079 { 02080 // Envelope loop 02081 if (ch.mPanEnvPointer == ch.mPanEnvLoopEnd) 02082 ch.mPanEnvPointer = ch.mPanEnvLoopStart; 02083 } 02084 else 02085 { 02086 if (ch.mPanEnvPointer == in->mPanEnvEnd) ch.mPanEnvSpeed = 0; 02087 } 02088 } else ch.mPanEnvValue = 0x20; // No panning envelope 02089 02090 if (ch.mVolume > 0x40) ch.mVolume = 0x40; 02091 if (ch.mVolume < 0) ch.mVolume = 0; 02092 02093 INT32 intVolume = (ch.mVolume * mSong.mGlobalVolume); 02094 REAL volumeTemp; 02095 volumeTemp.mValue = (intVolume << 3) + (intVolume << 1); 02096 ch.mFinalVolume = (volumeTemp * ch.mVolEnvValue * ch.mVolumeFadeoutValue); 02097 02098 volumeTemp = (ch.mFinalVolume - ch.mFinalOldVolume); 02099 ch.mFinalVolumeSpeed = (volumeTemp * mVolumeRampDivOpt); 02100 02101 /* 02102 REAL volumeTemp; 02103 volumeTemp.mValue = (ch.mVolume * mSong.mGlobalVolume * ch.mVolumeFadeoutValue) >> 13; 02104 ch.mFinalVolume = (volumeTemp * ch.mVolEnvValue); 02105 02106 volumeTemp = (ch.mFinalVolume - ch.mFinalOldVolume); 02107 ch.mFinalVolumeSpeed = (volumeTemp * mVolumeRampDivOpt); 02108 */ 02109 /* 02110 FLOAT32 volumeReal; 02111 volumeReal = (((FLOAT32)ch.mVolume / 65.0f) * (FLOAT32)ch.mVolEnvValue * 02112 (FLOAT32)ch.mVolumeFadeoutValue * ((FLOAT32)mSong.mGlobalVolume / 65.0f)); 02113 02114 ch.mFinalVolume = REALf(volumeReal); 02115 02116 ch.mFinalVolumeSpeed = (ch.mFinalVolume - ch.mFinalOldVolume) / REALf(32); 02117 */ 02118 /* 02119 volumeReal = (ch.mVolume * (FLOAT32)ch.mVolEnvValue * 02120 ch.mVolumeFadeoutValue * mSong.mGlobalVolume) * 02121 VOLUME_DIV_OPT; 02122 02123 ch.mFinalVolume = (INT32)volumeReal; 02124 02125 ch.mFinalVolumeSpeed = (INT32)((ch.mFinalVolume - ch.mFinalOldVolume) * 02126 VOLUME_RAMP_WIDTH_OPT); 02127 */ 02128 02129 ch.mFinalPan = (INT16)(ch.mPan + (((ch.mPanEnvValue - 0x20) * 02130 (0x80 - ABS(ch.mPan - 0x80))) >> 5)); 02131 if (ch.mFinalPan > 0xFF) ch.mFinalPan = 0xFF; 02132 else if (ch.mFinalPan < 0) ch.mFinalPan = 0; 02133 02134 ch.mSpeed = getSpeed(ch.mPeriod, mSampleRate); 02135 } 02136 } 02137 } 02138 02139 ticksLeft = (mSamplesPerTick - mSamplePointer); 02140 indicesLeft = (aSamples - index); 02141 02142 if (ticksLeft < indicesLeft) samplesToRender = ticksLeft; 02143 else samplesToRender = indicesLeft; 02144 02145 INT startChan = 0; 02146 INT endChan = mSong.mNbChannels; 02147 if (mFlags & XFCAUDIO_16BIT) // 16bit 02148 { 02149 if (mFlags & XFCAUDIO_STEREO) // 16bit stereo 02150 { 02151 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02152 { 02153 cLeft = cRight = 0; 02154 02155 for (chan = startChan; chan < endChan; chan++) 02156 { 02157 XFuXMChannel &ch = mChannels[chan]; 02158 02159 if (ch.mIsSample) 02160 { 02161 delta = ch.mPointer & (FP_VALUE - 1); 02162 02163 val1 = 0; 02164 val2 = 0; 02165 02166 if (ch.mCurrentSample.m16Bit) 02167 { 02168 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02169 02170 if (ch.mLoop == 0) 02171 { 02172 interpolateLinear16(ch, val1, val2); 02173 addPointer(ch); 02174 } 02175 else 02176 { 02177 temp = (ch.mPointer + FP_VALUE); 02178 02179 if (ch.mLoop == LOOP_FORWARD) 02180 { 02181 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02182 addPointerForwardLoop(ch); 02183 } 02184 else if (ch.mLoop == LOOP_PINGPONG) 02185 { 02186 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02187 addPointerBidirectionalLoop(ch); 02188 } 02189 } 02190 } 02191 else 02192 { 02193 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02194 02195 if (ch.mLoop == 0) 02196 { 02197 interpolateLinear8(ch, val1, val2); 02198 addPointer(ch); 02199 } 02200 else 02201 { 02202 temp = (ch.mPointer + FP_VALUE); 02203 02204 if (ch.mLoop == LOOP_FORWARD) 02205 { 02206 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02207 addPointerForwardLoop(ch); 02208 } 02209 else if (ch.mLoop == LOOP_PINGPONG) 02210 { 02211 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02212 addPointerBidirectionalLoop(ch); 02213 } 02214 } 02215 02216 val1 <<= 8; 02217 val2 <<= 8; 02218 } 02219 02220 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02221 02222 value = (INT16)(value * ch.mFinalOldVolume); 02223 cLeft += ((value * (0xFF - (UINT8)ch.mFinalPan)) >> 8); 02224 cRight += ((value * (UINT8)ch.mFinalPan) >> 8); 02225 02226 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02227 } 02228 } 02229 02230 if (cLeft < -32768) cLeft = -32768; 02231 else if (cLeft > 32767) cLeft = 32767; 02232 if (cRight < -32768) cRight = -32768; 02233 else if (cRight > 32767) cRight = 32767; 02234 02235 *((INT16 *)aBuf + (index << 1)) = (INT16)(cLeft ^ mTgtXor); 02236 *((INT16 *)aBuf + (index << 1) + 1) = (INT16)(cRight ^ mTgtXor); 02237 02238 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02239 } 02240 } 02241 else // 16bit mono 02242 { 02243 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02244 { 02245 c = 0; 02246 02247 for (chan = startChan; chan < endChan; chan++) 02248 { 02249 XFuXMChannel &ch = mChannels[chan]; 02250 02251 if (ch.mIsSample) 02252 { 02253 delta = ch.mPointer & (FP_VALUE - 1); 02254 02255 val1 = 0; 02256 val2 = 0; 02257 02258 if (ch.mCurrentSample.m16Bit) 02259 { 02260 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02261 02262 if (ch.mLoop == 0) 02263 { 02264 interpolateLinear16(ch, val1, val2); 02265 addPointer(ch); 02266 } 02267 else 02268 { 02269 temp = (ch.mPointer + FP_VALUE); 02270 02271 if (ch.mLoop == LOOP_FORWARD) 02272 { 02273 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02274 addPointerForwardLoop(ch); 02275 } 02276 else if (ch.mLoop == LOOP_PINGPONG) 02277 { 02278 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02279 addPointerBidirectionalLoop(ch); 02280 } 02281 } 02282 } 02283 else 02284 { 02285 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02286 02287 if (ch.mLoop == 0) 02288 { 02289 interpolateLinear8(ch, val1, val2); 02290 addPointer(ch); 02291 } 02292 else 02293 { 02294 temp = (ch.mPointer + FP_VALUE); 02295 02296 if (ch.mLoop == LOOP_FORWARD) 02297 { 02298 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02299 addPointerForwardLoop(ch); 02300 } 02301 else if (ch.mLoop == LOOP_PINGPONG) 02302 { 02303 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02304 addPointerBidirectionalLoop(ch); 02305 } 02306 } 02307 02308 val1 <<= 8; 02309 val2 <<= 8; 02310 } 02311 02312 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02313 02314 c += (INT16)(value * ch.mFinalOldVolume); 02315 02316 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02317 } 02318 } 02319 02320 if (c > 32767) c = 32767; 02321 else if (c < -32768) c = -32768; 02322 02323 *((INT16 *)aBuf + index) = (INT16)(c ^ mTgtXor); 02324 02325 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02326 } 02327 } 02328 } 02329 else // 8bit 02330 { 02331 if (mFlags & XFCAUDIO_STEREO) // 8bit stereo 02332 { 02333 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02334 { 02335 cLeft = cRight = 0; 02336 02337 for (chan = startChan; chan < endChan; chan++) 02338 { 02339 XFuXMChannel &ch = mChannels[chan]; 02340 02341 if (ch.mIsSample) 02342 { 02343 delta = ch.mPointer & (FP_VALUE - 1); 02344 02345 val1 = 0; 02346 val2 = 0; 02347 02348 if (ch.mCurrentSample.m16Bit) 02349 { 02350 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02351 02352 if (ch.mLoop == 0) 02353 { 02354 interpolateLinear16(ch, val1, val2); 02355 addPointer(ch); 02356 } 02357 else 02358 { 02359 temp = (ch.mPointer + FP_VALUE); 02360 02361 if (ch.mLoop == LOOP_FORWARD) 02362 { 02363 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02364 addPointerForwardLoop(ch); 02365 } 02366 else if (ch.mLoop == LOOP_PINGPONG) 02367 { 02368 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02369 addPointerBidirectionalLoop(ch); 02370 } 02371 } 02372 02373 val1 >>= 8; 02374 val2 >>= 8; 02375 } 02376 else 02377 { 02378 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02379 02380 if (ch.mLoop == 0) 02381 { 02382 interpolateLinear8(ch, val1, val2); 02383 addPointer(ch); 02384 } 02385 else 02386 { 02387 temp = (ch.mPointer + FP_VALUE); 02388 02389 if (ch.mLoop == LOOP_FORWARD) 02390 { 02391 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02392 addPointerForwardLoop(ch); 02393 } 02394 else if (ch.mLoop == LOOP_PINGPONG) 02395 { 02396 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02397 addPointerBidirectionalLoop(ch); 02398 } 02399 } 02400 } 02401 02402 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02403 02404 value = (INT8)(value * ch.mFinalOldVolume); 02405 cLeft += ((value * (0xFF - (UINT8)ch.mFinalPan)) >> 8); 02406 cRight += ((value * (UINT8)ch.mFinalPan) >> 8); 02407 02408 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02409 } 02410 } 02411 02412 if (cLeft < -128) cLeft = -128; 02413 else if (cLeft > 127) cLeft = 127; 02414 if (cRight < -128) cRight = -128; 02415 else if (cRight > 127) cRight = 127; 02416 02417 *((INT8 *)aBuf + (index << 1)) = (INT8)(cLeft ^ mTgtXor); 02418 *((INT8 *)aBuf + (index << 1) + 1) = (INT8)(cRight ^ mTgtXor); 02419 02420 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02421 } 02422 } 02423 else // 8bit mono 02424 { 02425 for (counter = 0; counter < samplesToRender; ++counter, ++index) 02426 { 02427 c = 0; 02428 02429 for (chan = startChan; chan < endChan; chan++) 02430 { 02431 XFuXMChannel &ch = mChannels[chan]; 02432 02433 if (ch.mIsSample) 02434 { 02435 delta = ch.mPointer & (FP_VALUE - 1); 02436 02437 val1 = 0; 02438 val2 = 0; 02439 02440 if (ch.mCurrentSample.m16Bit) 02441 { 02442 val1 = *((INT16 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02443 02444 if (ch.mLoop == 0) 02445 { 02446 interpolateLinear16(ch, val1, val2); 02447 addPointer(ch); 02448 } 02449 else 02450 { 02451 temp = (ch.mPointer + FP_VALUE); 02452 02453 if (ch.mLoop == LOOP_FORWARD) 02454 { 02455 interpolateLinearForwardLoop16(ch, val1, val2, temp); 02456 addPointerForwardLoop(ch); 02457 } 02458 else if (ch.mLoop == LOOP_PINGPONG) 02459 { 02460 interpolateLinearBidirectionalLoop16(ch, val1, val2, temp); 02461 addPointerBidirectionalLoop(ch); 02462 } 02463 } 02464 02465 val1 >>= 8; 02466 val2 >>= 8; 02467 } 02468 else 02469 { 02470 val1 = *((INT8 *)ch.mOffset + (ch.mPointer >> FP_BITS)); 02471 02472 if (ch.mLoop == 0) 02473 { 02474 interpolateLinear8(ch, val1, val2); 02475 addPointer(ch); 02476 } 02477 else 02478 { 02479 temp = (ch.mPointer + FP_VALUE); 02480 02481 if (ch.mLoop == LOOP_FORWARD) 02482 { 02483 interpolateLinearForwardLoop8(ch, val1, val2, temp); 02484 addPointerForwardLoop(ch); 02485 } 02486 else if (ch.mLoop == LOOP_PINGPONG) 02487 { 02488 interpolateLinearBidirectionalLoop8(ch, val1, val2, temp); 02489 addPointerBidirectionalLoop(ch); 02490 } 02491 } 02492 } 02493 02494 value = (((val2 * delta) + (val1 * (FP_VALUE - delta))) >> FP_BITS); 02495 02496 c += (INT8)(value * ch.mFinalOldVolume); 02497 02498 if (mRamp < VOLUME_RAMP_WIDTH) ch.mFinalOldVolume += ch.mFinalVolumeSpeed; 02499 } 02500 } 02501 02502 if (c > 127) c = 127; 02503 else if (c < -128) c = -128; 02504 02505 *((INT8 *)aBuf + index) = (INT8)(c ^ mTgtXor); 02506 02507 if (mRamp < VOLUME_RAMP_WIDTH) mRamp++; 02508 } 02509 } 02510 } 02511 02512 mSamplePointer += (samplesToRender - 1); 02513 } 02514 02515 mTotalTicks += aSamples; 02516 02517 return 1; 02518 } 02519 02520 // For MSVC 02521 #pragma warning(default:4244) 02522 02523 02524 XFuXMPlayer::XFuXMPlayer(FLOAT32 aSampleRate, UINT32 aFlags) 02525 { 02526 mSampleRate = aSampleRate; 02527 mFlags = aFlags; 02528 02529 mTgtXor = 0; 02530 if (!(mFlags & XFCAUDIO_SIGNED)) 02531 { 02532 if (mFlags & XFCAUDIO_16BIT) mTgtXor = -32768; 02533 else mTgtXor = -128; 02534 } 02535 02536 /* Sinewave table */ 02537 mSineWaveTable[0] = 0; 02538 mSineWaveTable[1] = 24; 02539 mSineWaveTable[2] = 49; 02540 mSineWaveTable[3] = 74; 02541 mSineWaveTable[4] = 97; 02542 mSineWaveTable[5] = 120; 02543 mSineWaveTable[6] = 141; 02544 mSineWaveTable[7] = 161; 02545 mSineWaveTable[8] = 180; 02546 mSineWaveTable[9] = 197; 02547 mSineWaveTable[10] = 212; 02548 mSineWaveTable[11] = 224; 02549 mSineWaveTable[12] = 235; 02550 mSineWaveTable[13] = 244; 02551 mSineWaveTable[14] = 250; 02552 mSineWaveTable[15] = 253; 02553 mSineWaveTable[16] = 255; 02554 mSineWaveTable[17] = 253; 02555 mSineWaveTable[18] = 250; 02556 mSineWaveTable[19] = 244; 02557 mSineWaveTable[20] = 235; 02558 mSineWaveTable[21] = 224; 02559 mSineWaveTable[22] = 212; 02560 mSineWaveTable[23] = 197; 02561 mSineWaveTable[24] = 180; 02562 mSineWaveTable[25] = 161; 02563 mSineWaveTable[26] = 141; 02564 mSineWaveTable[27] = 120; 02565 mSineWaveTable[28] = 97; 02566 mSineWaveTable[29] = 74; 02567 mSineWaveTable[30] = 49; 02568 mSineWaveTable[31] = 24; 02569 02570 INT i; 02571 02572 for (i = 32; i < 64; i++) 02573 { 02574 mSineWaveTable[i] = (INT16)-mSineWaveTable[i - 32]; 02575 } 02576 02577 /* Squarewave table */ 02578 for (i = 0; i < 32; i++) mSquareWaveTable[i] = -255; 02579 for (i = 32; i < 64; i++) mSquareWaveTable[i] = 255; 02580 02581 /* Ramp up/down tables */ 02582 for (i = 0; i < 32; i++) 02583 { 02584 mRampUpTable[i] = (INT16)(255.0f - (FLOAT32)i * (510.0f / 32.0f)); 02585 mRampUpTable[i + 32] = (INT16)(255.0f - (FLOAT32)i * (510.0f / 32.0f)); 02586 02587 mRampDownTable[i] = (INT16)(-255.0f + (FLOAT32)i * (510.0f / 32.0f)); 02588 mRampDownTable[i + 32] = 02589 (INT16)(-255.0f + (FLOAT32)i * (510.0f / 32.0f)); 02590 } 02591 02592 mSong.mOrderTable = NULL; 02593 mXMPatternHeaders = NULL; 02594 mPatternData = NULL; 02595 mInstruments = NULL; 02596 mChannels = NULL; 02597 02598 mEventHandlers = NULL; 02599 } 02600 02601 02602 XFuXMPlayer::~XFuXMPlayer() 02603 { 02604 INT i, j; 02605 02606 delete[] mSong.mOrderTable; 02607 02608 delete[] mXMPatternHeaders; 02609 02610 if (mPatternData != NULL) 02611 { 02612 for (i = 0; i < mSong.mNbPatterns; i++) 02613 { 02614 delete[] mPatternData[i].mData; 02615 delete[] mPatternData[i].mRows; 02616 } 02617 02618 delete[] mPatternData; 02619 } 02620 02621 if (mInstruments != NULL) 02622 { 02623 for (i = 0; i < mSong.mNbInstruments; i++) 02624 { 02625 XFuXMInstrument &ins = mInstruments[i]; 02626 02627 if (ins.mSamples != NULL) 02628 { 02629 for (j = 0; j < ins.mNbSamples; j++) 02630 { 02631 delete[] (INT8 *)ins.mSamples[j].mOffset; 02632 } 02633 02634 delete[] ins.mSamples; 02635 } 02636 } 02637 02638 delete[] mInstruments; 02639 } 02640 02641 delete[] mChannels; 02642 02643 delete mEventHandlers; 02644 } 02645 02646 02647 XFuXMPlayer * XFuXMPlayer::create(const CHAR *aTunename, 02648 FLOAT32 aSampleRate, UINT32 aFlags) 02649 { 02650 XFcFile *textout = NULL; 02651 02652 XFuXMPlayer *pl = new XFuXMPlayer(aSampleRate, aFlags); 02653 02654 if (pl != NULL) 02655 { 02656 pl->initialize(aSampleRate, aFlags, 1.0, 0.5, 0); 02657 02658 pl->mEventHandlers = new XFcLinkedList<XFuXMPlayerEventHandlerSlot>(); 02659 02660 if (pl->mEventHandlers == NULL) 02661 { 02662 delete pl; 02663 return NULL; 02664 } 02665 02666 #ifdef OUTPUT_XM_INFO 02667 XFuXMFormatAtom ta; 02668 02669 textout = XFcFile::open("xmoutput.txt","wt"); 02670 #endif 02671 02672 if (pl->loadXM(aTunename, textout) != 0) 02673 { 02674 // file not found 02675 delete pl; 02676 return NULL; 02677 } 02678 02679 #ifdef OUTPUT_XM_INFO 02680 pl->dumpSongParameters(textout); 02681 02682 pl->mPatternNb = -1; 02683 INT i; 02684 for (i = 0; i < pl->mXMHeader.mNbPatterns; i++) 02685 { 02686 pl->mPatternNb++; 02687 if (pl->mXMPatternHeaders[i].mSize > 0) 02688 { 02689 DebugPrint(textout, "* Pattern: %02X\n", pl->mPatternNb); 02690 { 02691 INT row, channel; 02692 pl->mPpoint = 0; 02693 for (row = 0; row < pl->mXMPatternHeaders[i].mNbRows; row++) 02694 { 02695 DebugPrint(textout, "%02X: ", row); 02696 for (channel = 0; channel < pl->mXMHeader.mNbChannels; channel++) 02697 { 02698 ta = pl->getAtom(); 02699 02700 if (ta.mNote == 0) 02701 { 02702 if (ta.mVolume != 0) 02703 DebugPrint(textout, "--- %02X %02X %1X%02X ; ", 02704 ta.mInstrumentNb, ta.mVolume - 0x10, 02705 ta.mEffectType, ta.mEffectValue); 02706 else 02707 DebugPrint(textout, "--- %02X -- %1X%02X ; ", 02708 ta.mInstrumentNb, ta.mEffectType, 02709 ta.mEffectValue); 02710 } 02711 else 02712 { 02713 if (ta.mVolume != 0) 02714 DebugPrint(textout, 02715 "%s%1d %02X %02X %1X%02X ; ", 02716 notes[(ta.mNote - 1) % 12], 02717 (INT)((ta.mNote - 1) / 12), 02718 ta.mInstrumentNb, ta.mVolume - 0x10, 02719 ta.mEffectType, ta.mEffectValue); 02720 else 02721 DebugPrint(textout, "%s%1d %02X -- %1X%02X ; ", 02722 notes[(ta.mNote - 1) % 12], 02723 (INT)((ta.mNote - 1) / 12), 02724 ta.mInstrumentNb, ta.mEffectType, 02725 ta.mEffectValue); 02726 } 02727 } 02728 02729 DebugPrint(textout, "\n"); 02730 } 02731 } 02732 } 02733 } 02734 02735 if (textout != NULL) textout->close(); 02736 #endif 02737 02738 pl->initSong(0); 02739 pl->mVolumeRampDivOpt = REALf(1.0f / VOLUME_RAMP_WIDTH); 02740 } 02741 02742 return pl; 02743 }
![]() | ||||
![]() |
Confidential Copyright © 2002-2003 Fathammer | with doxygen by Dimitri van Heesch |