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

📄 load_xm.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*      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: load_xm.c,v 1.32 1999/10/25 16:31:41 miod Exp $  Fasttracker (XM) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>extern char *safe_strdup(const char *s);#include "unimod_priv.h"/*========== Module structure */typedef struct XMHEADER  {    CHAR id[17];		/* ID text: 'Extended module: ' */    CHAR songname[21];		/* Module name */    CHAR trackername[20];	/* Tracker name */    UWORD version;		/* Version number */    ULONG headersize;		/* Header size */    UWORD songlength;		/* Song length (in patten order table) */    UWORD restart;		/* Restart position */    UWORD numchn;		/* Number of channels (2,4,6,8,10,...,32) */    UWORD numpat;		/* Number of patterns (max 256) */    UWORD numins;		/* Number of instruments (max 128) */    UWORD flags;    UWORD tempo;		/* Default tempo */    UWORD bpm;			/* Default BPM */    UBYTE orders[256];		/* Pattern order table  */  }XMHEADER;typedef struct XMINSTHEADER  {    ULONG size;			/* Instrument size */    CHAR name[22];		/* Instrument name */    UBYTE type;			/* Instrument type (always 0) */    UWORD numsmp;		/* Number of samples in instrument */    ULONG ssize;  }XMINSTHEADER;#define XMENVCNT (12*2)#define XMNOTECNT (8*OCTAVE)typedef struct XMPATCHHEADER  {    UBYTE what[XMNOTECNT];	/*  Sample number for all notes */    UWORD volenv[XMENVCNT];	/*  Points for volume envelope */    UWORD panenv[XMENVCNT];	/*  Points for panning envelope */    UBYTE volpts;		/*  Number of volume points */    UBYTE panpts;		/*  Number of panning points */    UBYTE volsus;		/*  Volume sustain point */    UBYTE volbeg;		/*  Volume loop start point */    UBYTE volend;		/*  Volume loop end point */    UBYTE pansus;		/*  Panning sustain point */    UBYTE panbeg;		/*  Panning loop start point */    UBYTE panend;		/*  Panning loop end point */    UBYTE volflg;		/*  Volume type: bit 0: On; 1: Sustain; 2: Loop */    UBYTE panflg;		/*  Panning type: bit 0: On; 1: Sustain; 2: Loop */    UBYTE vibflg;		/*  Vibrato type */    UBYTE vibsweep;		/*  Vibrato sweep */    UBYTE vibdepth;		/*  Vibrato depth */    UBYTE vibrate;		/*  Vibrato rate */    UWORD volfade;		/*  Volume fadeout */  }XMPATCHHEADER;typedef struct XMWAVHEADER  {    ULONG length;		/* Sample length */    ULONG loopstart;		/* Sample loop start */    ULONG looplength;		/* Sample loop length */    UBYTE volume;		/* Volume  */    SBYTE finetune;		/* Finetune (signed byte -128..+127) */    UBYTE type;			/* Loop type */    UBYTE panning;		/* Panning (0-255) */    SBYTE relnote;		/* Relative note number (signed byte) */    UBYTE reserved;    CHAR samplename[22];	/* Sample name */    UBYTE vibtype;		/* Vibrato type */    UBYTE vibsweep;		/* Vibrato sweep */    UBYTE vibdepth;		/* Vibrato depth */    UBYTE vibrate;		/* Vibrato rate */  }XMWAVHEADER;typedef struct XMPATHEADER  {    ULONG size;			/* Pattern header length  */    UBYTE packing;		/* Packing type (always 0) */    UWORD numrows;		/* Number of rows in pattern (1..256) */    SWORD packsize;		/* Packed patterndata size */  }XMPATHEADER;typedef struct XMNOTE  {    UBYTE note, ins, vol, eff, dat;  }XMNOTE;/*========== Loader variables */static XMNOTE *xmpat = NULL;static XMHEADER *mh = NULL;/* increment unit for sample array reallocation */#define XM_SMPINCR 64static ULONG *nextwav = NULL;static XMWAVHEADER *wh = NULL, *s = NULL;/*========== Loader code */BOOL XM_Test (void){  UBYTE id[38];  if (!_mm_read_UBYTES (id, 38, modreader))    return 0;  if (memcmp (id, "Extended Module: ", 17))    return 0;  if (id[37] == 0x1a)    return 1;  return 0;}BOOL XM_Init (void){  if (!(mh = (XMHEADER *) _mm_malloc (sizeof (XMHEADER))))    return 0;  return 1;}void XM_Cleanup (void){  _mm_free (mh);}static int XM_ReadNote (XMNOTE * n){  UBYTE cmp, result = 1;  memset (n, 0, sizeof (XMNOTE));  cmp = _mm_read_UBYTE (modreader);  if (cmp & 0x80)    {      if (cmp & 1)	{	  result++;	  n->note = _mm_read_UBYTE (modreader);	}      if (cmp & 2)	{	  result++;	  n->ins = _mm_read_UBYTE (modreader);	}      if (cmp & 4)	{	  result++;	  n->vol = _mm_read_UBYTE (modreader);	}      if (cmp & 8)	{	  result++;	  n->eff = _mm_read_UBYTE (modreader);	}      if (cmp & 16)	{	  result++;	  n->dat = _mm_read_UBYTE (modreader);	}    }  else    {      n->note = cmp;      n->ins = _mm_read_UBYTE (modreader);      n->vol = _mm_read_UBYTE (modreader);      n->eff = _mm_read_UBYTE (modreader);      n->dat = _mm_read_UBYTE (modreader);      result += 4;    }  return result;}static UBYTE *XM_Convert (XMNOTE * xmtrack, UWORD rows){  int t;  UBYTE note, ins, vol, eff, dat;  UniReset ();  for (t = 0; t < rows; t++)    {      note = xmtrack->note;      ins = xmtrack->ins;      vol = xmtrack->vol;      eff = xmtrack->eff;      dat = xmtrack->dat;      if (note)	{	  if (note > XMNOTECNT)	    UniEffect (UNI_KEYFADE, 0);	  else	    UniNote (note - 1);	}      if (ins)	UniInstrument (ins - 1);      switch (vol >> 4)	{	case 0x6:		/* volslide down */	  if (vol & 0xf)	    UniEffect (UNI_XMEFFECTA, vol & 0xf);	  break;	case 0x7:		/* volslide up */	  if (vol & 0xf)	    UniEffect (UNI_XMEFFECTA, vol << 4);	  break;	  /* volume-row fine volume slide is compatible with protracker	     EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as	     opposed to 'take the last sliding value'. */	case 0x8:		/* finevol down */	  UniPTEffect (0xe, 0xb0 | (vol & 0xf));	  break;	case 0x9:		/* finevol up */	  UniPTEffect (0xe, 0xa0 | (vol & 0xf));	  break;	case 0xa:		/* set vibrato speed */	  UniPTEffect (0x4, vol << 4);	  break;	case 0xb:		/* vibrato */	  UniPTEffect (0x4, vol & 0xf);	  break;	case 0xc:		/* set panning */	  UniPTEffect (0x8, vol << 4);	  break;	case 0xd:		/* panning slide left (only slide when data not zero) */	  if (vol & 0xf)	    UniEffect (UNI_XMEFFECTP, vol & 0xf);	  break;	case 0xe:		/* panning slide right (only slide when data not zero) */	  if (vol & 0xf)	    UniEffect (UNI_XMEFFECTP, vol << 4);	  break;	case 0xf:		/* tone porta */	  UniPTEffect (0x3, vol << 4);	  break;	default:	  if ((vol >= 0x10) && (vol <= 0x50))	    UniPTEffect (0xc, vol - 0x10);	}      switch (eff)	{	case 0x4:	  UniEffect (UNI_XMEFFECT4, dat);	  break;	case 0xa:	  UniEffect (UNI_XMEFFECTA, dat);	  break;	case 0xe:		/* Extended effects */	  switch (dat >> 4)	    {	    case 0x1:		/* XM fine porta up */	      UniEffect (UNI_XMEFFECTE1, dat & 0xf);	      break;	    case 0x2:		/* XM fine porta down */	      UniEffect (UNI_XMEFFECTE2, dat & 0xf);	      break;	    case 0xa:		/* XM fine volume up */	      UniEffect (UNI_XMEFFECTEA, dat & 0xf);	      break;	    case 0xb:		/* XM fine volume down */	      UniEffect (UNI_XMEFFECTEB, dat & 0xf);	      break;	    default:	      UniPTEffect (eff, dat);	    }	  break;	case 'G' - 55:		/* G - set global volume */	  UniEffect (UNI_XMEFFECTG, dat > 64 ? 64 : dat);	  break;	case 'H' - 55:		/* H - global volume slide */	  UniEffect (UNI_XMEFFECTH, dat);	  break;	case 'K' - 55:		/* K - keyOff and KeyFade */	  UniEffect (UNI_KEYFADE, dat);	  break;	case 'L' - 55:		/* L - set envelope position */	  UniEffect (UNI_XMEFFECTL, dat);	  break;	case 'P' - 55:		/* P - panning slide */	  UniEffect (UNI_XMEFFECTP, dat);	  break;	case 'R' - 55:		/* R - multi retrig note */	  UniEffect (UNI_S3MEFFECTQ, dat);	  break;	case 'T' - 55:		/* T - Tremor */	  UniEffect (UNI_S3MEFFECTI, dat);	  break;	case 'X' - 55:	  switch (dat >> 4)	    {	    case 1:		/* X1 - Extra Fine Porta up */	      UniEffect (UNI_XMEFFECTX1, dat & 0xf);	      break;	    case 2:		/* X2 - Extra Fine Porta down */	      UniEffect (UNI_XMEFFECTX2, dat & 0xf);	      break;	    }	  break;	default:	  if (eff <= 0xf)	    {	      /* the pattern jump destination is written in decimal,	         but it seems some poor tracker software writes them	         in hexadecimal... (sigh) */	      if (eff == 0xd)		/* don't change anything if we're sure it's in hexa */		if ((((dat & 0xf0) >> 4) <= 9) && ((dat & 0xf) <= 9))		  /* otherwise, convert from dec to hex */		  dat = (((dat & 0xf0) >> 4) * 10) + (dat & 0xf);	      UniPTEffect (eff, dat);	    }	  break;	}      UniNewline ();      xmtrack++;    }  return UniDup ();}static BOOL LoadPatterns (BOOL dummypat){  int t, u, v, numtrk;  if (!AllocTracks ())    return 0;  if (!AllocPatterns ())    return 0;  numtrk = 0;  for (t = 0; t < mh->numpat; t++)    {      XMPATHEADER ph;      ph.size = _mm_read_I_ULONG (modreader);      if (ph.size < (mh->version == 0x0102 ? 8 : 9))	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 0;	}      ph.packing = _mm_read_UBYTE (modreader);      if (ph.packing)	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 0;	}      if (mh->version == 0x0102)	ph.numrows = _mm_read_UBYTE (modreader) + 1;      else	ph.numrows = _mm_read_I_UWORD (modreader);      ph.packsize = _mm_read_I_UWORD (modreader);      ph.size -= (mh->version == 0x0102 ? 8 : 9);      if (ph.size)	_mm_fseek (modreader, ph.size, SEEK_CUR);      of.pattrows[t] = ph.numrows;      if (ph.numrows)	{	  if (!(xmpat = (XMNOTE *) _mm_calloc (ph.numrows * of.numchn, sizeof (XMNOTE))))	    return 0;	  /* when packsize is 0, don't try to load a pattern.. it's empty. */	  if (ph.packsize)	    for (u = 0; u < ph.numrows; u++)	      for (v = 0; v < of.numchn; v++)		{		  if (!ph.packsize)		    break;		  ph.packsize -= XM_ReadNote (&xmpat[(v * ph.numrows) + u]);		  if (ph.packsize < 0)		    {		      free (xmpat);		      xmpat = NULL;		      _mm_errno = MMERR_LOADING_PATTERN;		      return 0;		    }		}	  if (ph.packsize)	    {	      _mm_fseek (modreader, ph.packsize, SEEK_CUR);	    }	  if (_mm_eof (modreader))	    {	      free (xmpat);	      xmpat = NULL;	      _mm_errno = MMERR_LOADING_PATTERN;	      return 0;	    }	  for (v = 0; v < of.numchn; v++)	    of.tracks[numtrk++] = XM_Convert (&xmpat[v * ph.numrows], ph.numrows);	  free (xmpat);	  xmpat = NULL;	}

⌨️ 快捷键说明

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