📄 mplayer.c
字号:
/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//*============================================================================== $Id: mplayer.c 937 2003-02-12 04:54:31Z slouken $ The Protracker Player Driver The protracker driver supports all base Protracker 3.x commands and features.==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include <stdarg.h>#ifdef SUNOSextern long int random(void);#endif#ifdef SRANDOM_IN_MATH_H#include <math.h>#else#include <stdlib.h>#endif#include "mikmod_internals.h"/* Set forbid to 1 when you want to modify any of the pf->sngpos, pf->patpos etc variables and clear it when you're done. This prevents getting strange results due to intermediate interrupts. */ MODULE *pf=NULL; /* modfile being played */static SWORD mp_channel; /* channel we're working on */static MP_CONTROL *a; /* current AUDTMP we're working on */static int explicitslides;static UWORD oldperiods[OCTAVE*2]={ 1712*16,1664*16,1616*16,1570*16,1524*16,1480*16, 1438*16,1396*16,1356*16,1318*16,1280*16,1244*16, 1208*16,1174*16,1140*16,1108*16,1076*16,1046*16, 1016*16, 988*16, 960*16, 932*16, 906*16, 880*16};static UBYTE VibratoTable[32]={ 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24};static UBYTE avibtab[128]={ 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63, 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59, 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46, 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25, 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1};/* Triton's linear periods to frequency translation table (for XM modules) */static ULONG lintab[768]={ 535232,534749,534266,533784,533303,532822,532341,531861, 531381,530902,530423,529944,529466,528988,528511,528034, 527558,527082,526607,526131,525657,525183,524709,524236, 523763,523290,522818,522346,521875,521404,520934,520464, 519994,519525,519057,518588,518121,517653,517186,516720, 516253,515788,515322,514858,514393,513929,513465,513002, 512539,512077,511615,511154,510692,510232,509771,509312, 508852,508393,507934,507476,507018,506561,506104,505647, 505191,504735,504280,503825,503371,502917,502463,502010, 501557,501104,500652,500201,499749,499298,498848,498398, 497948,497499,497050,496602,496154,495706,495259,494812, 494366,493920,493474,493029,492585,492140,491696,491253, 490809,490367,489924,489482,489041,488600,488159,487718, 487278,486839,486400,485961,485522,485084,484647,484210, 483773,483336,482900,482465,482029,481595,481160,480726, 480292,479859,479426,478994,478562,478130,477699,477268, 476837,476407,475977,475548,475119,474690,474262,473834, 473407,472979,472553,472126,471701,471275,470850,470425, 470001,469577,469153,468730,468307,467884,467462,467041, 466619,466198,465778,465358,464938,464518,464099,463681, 463262,462844,462427,462010,461593,461177,460760,460345, 459930,459515,459100,458686,458272,457859,457446,457033, 456621,456209,455797,455386,454975,454565,454155,453745, 453336,452927,452518,452110,451702,451294,450887,450481, 450074,449668,449262,448857,448452,448048,447644,447240, 446836,446433,446030,445628,445226,444824,444423,444022, 443622,443221,442821,442422,442023,441624,441226,440828, 440430,440033,439636,439239,438843,438447,438051,437656, 437261,436867,436473,436079,435686,435293,434900,434508, 434116,433724,433333,432942,432551,432161,431771,431382, 430992,430604,430215,429827,429439,429052,428665,428278, 427892,427506,427120,426735,426350,425965,425581,425197, 424813,424430,424047,423665,423283,422901,422519,422138, 421757,421377,420997,420617,420237,419858,419479,419101, 418723,418345,417968,417591,417214,416838,416462,416086, 415711,415336,414961,414586,414212,413839,413465,413092, 412720,412347,411975,411604,411232,410862,410491,410121, 409751,409381,409012,408643,408274,407906,407538,407170, 406803,406436,406069,405703,405337,404971,404606,404241, 403876,403512,403148,402784,402421,402058,401695,401333, 400970,400609,400247,399886,399525,399165,398805,398445, 398086,397727,397368,397009,396651,396293,395936,395579, 395222,394865,394509,394153,393798,393442,393087,392733, 392378,392024,391671,391317,390964,390612,390259,389907, 389556,389204,388853,388502,388152,387802,387452,387102, 386753,386404,386056,385707,385359,385012,384664,384317, 383971,383624,383278,382932,382587,382242,381897,381552, 381208,380864,380521,380177,379834,379492,379149,378807, 378466,378124,377783,377442,377102,376762,376422,376082, 375743,375404,375065,374727,374389,374051,373714,373377, 373040,372703,372367,372031,371695,371360,371025,370690, 370356,370022,369688,369355,369021,368688,368356,368023, 367691,367360,367028,366697,366366,366036,365706,365376, 365046,364717,364388,364059,363731,363403,363075,362747, 362420,362093,361766,361440,361114,360788,360463,360137, 359813,359488,359164,358840,358516,358193,357869,357547, 357224,356902,356580,356258,355937,355616,355295,354974, 354654,354334,354014,353695,353376,353057,352739,352420, 352103,351785,351468,351150,350834,350517,350201,349885, 349569,349254,348939,348624,348310,347995,347682,347368, 347055,346741,346429,346116,345804,345492,345180,344869, 344558,344247,343936,343626,343316,343006,342697,342388, 342079,341770,341462,341154,340846,340539,340231,339924, 339618,339311,339005,338700,338394,338089,337784,337479, 337175,336870,336566,336263,335959,335656,335354,335051, 334749,334447,334145,333844,333542,333242,332941,332641, 332341,332041,331741,331442,331143,330844,330546,330247, 329950,329652,329355,329057,328761,328464,328168,327872, 327576,327280,326985,326690,326395,326101,325807,325513, 325219,324926,324633,324340,324047,323755,323463,323171, 322879,322588,322297,322006,321716,321426,321136,320846, 320557,320267,319978,319690,319401,319113,318825,318538, 318250,317963,317676,317390,317103,316817,316532,316246, 315961,315676,315391,315106,314822,314538,314254,313971, 313688,313405,313122,312839,312557,312275,311994,311712, 311431,311150,310869,310589,310309,310029,309749,309470, 309190,308911,308633,308354,308076,307798,307521,307243, 306966,306689,306412,306136,305860,305584,305308,305033, 304758,304483,304208,303934,303659,303385,303112,302838, 302565,302292,302019,301747,301475,301203,300931,300660, 300388,300117,299847,299576,299306,299036,298766,298497, 298227,297958,297689,297421,297153,296884,296617,296349, 296082,295815,295548,295281,295015,294749,294483,294217, 293952,293686,293421,293157,292892,292628,292364,292100, 291837,291574,291311,291048,290785,290523,290261,289999, 289737,289476,289215,288954,288693,288433,288173,287913, 287653,287393,287134,286875,286616,286358,286099,285841, 285583,285326,285068,284811,284554,284298,284041,283785, 283529,283273,283017,282762,282507,282252,281998,281743, 281489,281235,280981,280728,280475,280222,279969,279716, 279464,279212,278960,278708,278457,278206,277955,277704, 277453,277203,276953,276703,276453,276204,275955,275706, 275457,275209,274960,274712,274465,274217,273970,273722, 273476,273229,272982,272736,272490,272244,271999,271753, 271508,271263,271018,270774,270530,270286,270042,269798, 269555,269312,269069,268826,268583,268341,268099,267857};#define LOGFAC 2*16static UWORD logtab[104]={ LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887, LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838, LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814, LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791, LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768, LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746, LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725, LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704, LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684, LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665, LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646, LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628, LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610, LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592, LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575, LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559, LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543, LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528, LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513, LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498, LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484, LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470, LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457, LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443, LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431};static SBYTE PanbrelloTable[256]={ 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2, 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23, -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2};/* returns a random value between 0 and ceil-1, ceil must be a power of two */static int getrandom(int ceil){#ifdef HAVE_SRANDOM return random()&(ceil-1);#else return (int)((rand()*ceil)/(RAND_MAX+1.0));#endif}/* New Note Action Scoring System : --------------------------------1) total-volume (fadevol, chanvol, volume) is the main scorer.2) a looping sample is a bonus x23) a foreground channel is a bonus x44) an active envelope with keyoff is a handicap -x2 */static int MP_FindEmptyChannel(void){ MP_VOICE *a; ULONG t,k,tvol,pp; for (t=0;t<md_sngchn;t++) if (((pf->voice[t].kick==KICK_ABSENT)||(pf->voice[t].kick==KICK_ENV))&& Voice_Stopped_internal(t)) return t; tvol=0xffffffUL;t=0;a=pf->voice; for (k=0;k<md_sngchn;k++,a++) if ((a->kick==KICK_ABSENT)||(a->kick==KICK_ENV)) { pp=a->totalvol<<((a->s->flags&SF_LOOP)?1:0); if ((a->master)&&(a==a->master->slave)) pp<<=2; if (pp<tvol) { tvol=pp; t=k; } } if (tvol>8000*7) return -1; return t;}static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2){ if ((p1==p2)||(p==p1)) return v1; return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));}UWORD getlinearperiod(UWORD note,ULONG fine){ UWORD t; t=(20L*OCTAVE+2-note)*32L-(fine>>1); return t;}static UWORD getlogperiod(UWORD note,ULONG fine){ UWORD n,o; UWORD p1,p2; ULONG i; n=note%(2*OCTAVE); o=note/(2*OCTAVE); i=(n<<2)+(fine>>4); /* n*8 + fine/16 */ p1=logtab[i]; p2=logtab[i+1]; return (Interpolate(fine>>4,0,15,p1,p2)>>o);}static UWORD getoldperiod(UWORD note,ULONG speed){ UWORD n,o; if (!speed) {#ifdef MIKMOD_DEBUG fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);#endif return 4242; /* <- prevent divide overflow.. (42 hehe) */ } n=note%(2*OCTAVE); o=note/(2*OCTAVE); return ((8363L*(ULONG)oldperiods[n])>>o)/speed;}static UWORD GetPeriod(UWORD note,ULONG speed){ if (pf->flags & UF_XMPERIODS) return (pf->flags&UF_LINEAR)?getlinearperiod(note,speed):getlogperiod(note,speed); return getoldperiod(note,speed);}static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b){ return (Interpolate(p,a->pos,b->pos,a->val,b->val));}static SWORD DoPan(SWORD envpan,SWORD pan){ int newpan; newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128); return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);}static void StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff){ t->flg=flg; t->pts=pts; t->susbeg=susbeg; t->susend=susend; t->beg=beg; t->end=end; t->env=p; t->p=0; t->a=0; t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1; /* Imago Orpheus sometimes stores an extra initial point in the envelope */ if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) { t->a++;t->b++; } if (t->b>=t->pts) t->b=t->pts-1;}/* This procedure processes all envelope types, include volume, pitch, and panning. Envelopes are defined by a set of points, each with a magnitude [relating either to volume, panning position, or pitch modifier] and a tick position. Envelopes work in the following manner: (a) Each tick the envelope is moved a point further in its progression. For an accurate progression, magnitudes between two envelope points are interpolated. (b) When progression reaches a defined point on the envelope, values are shifted to interpolate between this point and the next, and checks for loops or envelope end are done. Misc: Sustain loops are loops that are only active as long as the keyoff flag is clear. When a volume envelope terminates, so does the current fadeout. */static SWORD ProcessEnvelope(ENVPR *t,SWORD v,UBYTE keyoff){ if (t->flg & EF_ON) { UBYTE a,b; /* actual points in the envelope */ UWORD p; /* the 'tick counter' - real point being played */ a=t->a; b=t->b; p=t->p; /* if sustain loop on one point (XM type), don't move and don't interpolate when the point is reached */ if ((t->flg & EF_SUSTAIN)&&(t->susbeg==t->susend)&& (!(keyoff&KEY_OFF))&&(p==t->env[t->susbeg].pos)) v=t->env[t->susbeg].val; else { /* compute the current envelope value between points a and b */ if (a==b) v=t->env[a].val; else v=InterpolateEnv(p,&t->env[a],&t->env[b]); p++; /* pointer reached point b? */ if (p>=t->env[b].pos) { a=b++; /* shift points a and b */ /* Check for loops, sustain loops, or end of envelope. */ if ((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF))&&(b>t->susend)) { a=t->susbeg; b=(t->susbeg==t->susend)?a:a+1; p=t->env[a].pos; } else if ((t->flg & EF_LOOP)&&(b>t->end)) { a=t->beg; b=(t->beg==t->end)?a:a+1; p=t->env[a].pos; } else { if (b>=t->pts) { if ((t->flg & EF_VOLENV)&&(mp_channel!=-1)) { pf->voice[mp_channel].keyoff|=KEY_FADE; if (!v) pf->voice[mp_channel].fadevol=0; } b--;p--; } } } t->a=a; t->b=b; t->p=p; } } return v;}/* XM linear period to frequency conversion */ULONG getfrequency(UBYTE flags,ULONG period){ if (flags & UF_LINEAR) return lintab[period%768]>>(period/768); else return (8363L*1712L)/(period?period:1);}/*========== Protracker effects */static void DoEEffects(UBYTE dat){ UBYTE nib=dat&0xf; switch (dat>>4) { case 0x0: /* hardware filter toggle, not supported */ break; case 0x1: /* fineslide up */ if (a->period) if (!pf->vbtick) a->tmpperiod-=(nib<<2); break; case 0x2: /* fineslide dn */ if (a->period) if (!pf->vbtick) a->tmpperiod+=(nib<<2); break; case 0x3: /* glissando ctrl */ a->glissando=nib; break; case 0x4: /* set vibrato waveform */ a->wavecontrol&=0xf0; a->wavecontrol|=nib; break; case 0x5: /* set finetune */ if (a->period) { if (pf->flags&UF_XMPERIODS) a->speed=nib+128; else a->speed=finetune[nib]; a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed); } break; case 0x6: /* set patternloop */ if (pf->vbtick) break; if (nib) { /* set reppos or repcnt ? */ /* set repcnt, so check if repcnt already is set, which means we are already looping */ if (a->pat_repcnt) a->pat_repcnt--; /* already looping, decrease counter */ else {#if 0 /* this would make walker.xm, shipped with Xsoundtracker, play correctly, but it's better to remain compatible with FT2 */ if ((!(pf->flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))#endif a->pat_repcnt=nib; /* not yet looping, so set repcnt */ } if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */ if (a->pat_reppos==POS_NONE) a->pat_reppos=pf->patpos-1; if (a->pat_reppos==-1) { pf->pat_repcrazy=1; pf->patpos=0; } else pf->patpos=a->pat_reppos; } else a->pat_reppos=POS_NONE; } else a->pat_reppos=pf->patpos-1; /* set reppos - can be (-1) */ break; case 0x7: /* set tremolo waveform */ a->wavecontrol&=0x0f; a->wavecontrol|=nib<<4; break; case 0x8: /* set panning */ if (pf->panflag) { if (nib<=8) nib<<=4; else nib*=17; a->panning=pf->panning[mp_channel]=nib; } break; case 0x9: /* retrig note */ /* only retrigger if data nibble > 0 */ if (nib) { if (!a->retrig) { /* when retrig counter reaches 0, reset counter and restart the sample */ if (a->period) a->kick=KICK_NOTE; a->retrig=nib; } a->retrig--; /* countdown */ } break; case 0xa: /* fine volume slide up */ if (pf->vbtick) break; a->tmpvolume+=nib; if (a->tmpvolume>64) a->tmpvolume=64; break; case 0xb: /* fine volume slide dn */ if (pf->vbtick) break; a->tmpvolume-=nib; if (a->tmpvolume<0) a->tmpvolume=0; break; case 0xc: /* cut note */ /* When pf->vbtick reaches the cut-note value, turn the volume to zero ( Just like on the amiga) */ if (pf->vbtick>=nib) a->tmpvolume=0; /* just turn the volume down */ break; case 0xd: /* note delay */ /* delay the start of the sample until pf->vbtick==nib */ if (!pf->vbtick) a->notedelay=nib;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -