⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mplayer.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	MikMod sound library
	(c) 1998, 1999, 2000, 2001 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,v 1.5 2004/01/31 22:40:22 raph Exp $

  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 SRANDOM_IN_MATH_H
#include <math.h>
#else
#include <stdlib.h>
#endif

#include "mikmod_internals.h"

#ifdef SUNOS
extern int fprintf(FILE *, const char *, ...);
extern long int random(void);
#endif

/* The currently playing module */
/* This variable should better be static, but it would break the ABI, so this
   will wait */
/*static*/ MODULE *pf = NULL;

#define	HIGH_OCTAVE		2	/* number of above-range octaves */

static	UWORD oldperiods[OCTAVE*2]={
	0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
	0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
	0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
	0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
};

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*16
static	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 (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 x2
	3)	a foreground channel is a bonus x4
	4)	an active envelope with keyoff is a handicap -x2
*/
static int MP_FindEmptyChannel(MODULE *mod)
{
	MP_VOICE *a;
	ULONG t,k,tvol,pp;

	for (t=0;t<md_sngchn;t++)
		if (((mod->voice[t].main.kick==KICK_ABSENT)||
			 (mod->voice[t].main.kick==KICK_ENV))&&
		   Voice_Stopped_internal(t))
			return t;

	tvol=0xffffffUL;t=-1;a=mod->voice;
	for (k=0;k<md_sngchn;k++,a++) {
		/* allow us to take over a nonexisting sample */
		if (!a->main.s)
			return k;

		if ((a->main.kick==KICK_ABSENT)||(a->main.kick==KICK_ENV)) {
			pp=a->totalvol<<((a->main.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+2*HIGH_OCTAVE)*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;

	/* This happens sometimes on badly converted AMF, and old MOD */
	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 flags, UWORD note, ULONG speed)
{
	if (flags & UF_XMPERIODS) {
		if (flags & UF_LINEAR)
				return getlinearperiod(note, speed);
		else
				return getlogperiod(note, speed);
	} else
		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 SWORD 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++;
	}

	/* Fit in the envelope, still */
	if (t->a >= t->pts)
		t->a = t->pts - 1;
	if (t->b >= t->pts)
		t->b = t->pts-1;

	return t->env[t->a].val;
}

/* 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(MP_VOICE *aout, ENVPR *t, SWORD v)
{
	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;

		/*
		 * Sustain loop on one point (XM type).
		 * Not processed if KEYOFF.
		 * Don't move and don't interpolate when the point is reached
		 */
		if ((t->flg & EF_SUSTAIN) && t->susbeg == t->susend &&
		   (!(aout->main.keyoff & KEY_OFF) && p == t->env[t->susbeg].pos)) {
			v = t->env[t->susbeg].val;
		} else {
			/*
			 * All following situations will require interpolation between
			 * two envelope points.
			 */

			/*
			 * Sustain loop between two points (IT type).
			 * Not processed if KEYOFF.
			 */
			/* if we were on a loop point, loop now */
			if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) &&
			   a >= t->susend) {
				a = t->susbeg;
				b = (t->susbeg==t->susend)?a:a+1;
				p = t->env[a].pos;
				v = t->env[a].val;
			} else
			/*
			 * Regular loop.
			 * Be sure to correctly handle single point loops.
			 */
			if ((t->flg & EF_LOOP) && a >= t->end) {
				a = t->beg;
				b = t->beg == t->end ? a : a + 1;
				p = t->env[a].pos;
				v = t->env[a].val;
			} else
			/*
			 * Non looping situations.
			 */
			if (a != b)
				v = InterpolateEnv(p, &t->env[a], &t->env[b]);
			else
				v = t->env[a].val;

			/*
			 * Start to fade if the volume envelope is finished.
			 */
			if (p >= t->env[t->pts - 1].pos) {
				if (t->flg & EF_VOLENV) {
					aout->main.keyoff |= KEY_FADE;
					if (!v)
						aout->main.fadevol = 0;
				}
			} else {
				p++;
				/* did pointer reach point b? */
				if (p >= t->env[b].pos)
					a = b++; /* shift points a and b */
			}
			t->a = a;
			t->b = b;
			t->p = p;
		}
	}
	return v;
}

/* XM linear period to frequency conversion */
ULONG getfrequency(UWORD flags,ULONG period)
{
	if (flags & UF_LINEAR) {
		SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE;

		if (shift >= 0)
			return lintab[period % 768] >> shift;
		else
			return lintab[period % 768] << (-shift);
	} else
		return (8363L*1712L)/(period?period:1);
}

/*========== Protracker effects */

static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style)
{
	UBYTE note=a->main.note;

	if (a->arpmem) {
		switch (style) {
		case 0:		/* mod style: N, N+x, N+y */
			switch (tick % 3) {
			/* case 0: unchanged */
			case 1:
				note += (a->arpmem >> 4);
				break;
			case 2:
				note += (a->arpmem & 0xf);
				break;
			}
			break;
		case 3:		/* okt arpeggio 3: N-x, N, N+y */
			switch (tick % 3) {
			case 0:
				note -= (a->arpmem >> 4);
				break;
			/* case 1: unchanged */
			case 2:
				note += (a->arpmem & 0xf);
				break;
			}
			break;
		case 4:		/* okt arpeggio 4: N, N+y, N, N-x */
			switch (tick % 4) {
			/* case 0, case 2: unchanged */
			case 1:
				note += (a->arpmem & 0xf);
				break;
			case 3:
				note -= (a->arpmem >> 4);
				break;
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -