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

📄 load_s3m.c

📁 MIDI解码程序(用VC编写)
💻 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: load_s3m.c,v 1.32 1999/10/25 16:31:41 miod Exp $  Screamtracker (S3M) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "unimod_priv.h"/*========== Module structure *//* header */typedef struct S3MHEADER  {    CHAR songname[28];    UBYTE t1a;    UBYTE type;    UBYTE unused1[2];    UWORD ordnum;    UWORD insnum;    UWORD patnum;    UWORD flags;    UWORD tracker;    UWORD fileformat;    CHAR scrm[4];    UBYTE mastervol;    UBYTE initspeed;    UBYTE inittempo;    UBYTE mastermult;    UBYTE ultraclick;    UBYTE pantable;    UBYTE unused2[8];    UWORD special;    UBYTE channels[32];  }S3MHEADER;/* sample information */typedef struct S3MSAMPLE  {    UBYTE type;    CHAR filename[12];    UBYTE memsegh;    UWORD memsegl;    ULONG length;    ULONG loopbeg;    ULONG loopend;    UBYTE volume;    UBYTE dsk;    UBYTE pack;    UBYTE flags;    ULONG c2spd;    UBYTE unused[12];    CHAR sampname[28];    CHAR scrs[4];  }S3MSAMPLE;typedef struct S3MNOTE  {    UBYTE note, ins, vol, cmd, inf;  }S3MNOTE;/*========== Loader variables */static S3MNOTE *s3mbuf = NULL;	/* pointer to a complete S3M pattern */static S3MHEADER *mh = NULL;static UWORD *paraptr = NULL;	/* parapointer array (see S3M docs) *//* tracker identifiers */#define NUMTRACKERS 4static CHAR *S3M_Version[] ={  "Screamtracker x.xx",  "Imago Orpheus x.xx (S3M format)",  "Impulse Tracker x.xx (S3M format)",  "Unknown tracker x.xx (S3M format)",  "Impulse Tracker 2.14p3 (S3M format)",  "Impulse Tracker 2.14p4 (S3M format)"};/* version number position in above array */static int numeric[NUMTRACKERS] ={14, 14, 16, 16};/*========== Loader code */BOOL S3M_Test (void){  UBYTE id[4];  _mm_fseek (modreader, 0x2c, SEEK_SET);  if (!_mm_read_UBYTES (id, 4, modreader))    return 0;  if (!memcmp (id, "SCRM", 4))    return 1;  return 0;}BOOL S3M_Init (void){  if (!(s3mbuf = (S3MNOTE *) _mm_malloc (32 * 64 * sizeof (S3MNOTE))))    return 0;  if (!(mh = (S3MHEADER *) _mm_malloc (sizeof (S3MHEADER))))    return 0;  if (!(poslookup = (UBYTE *) _mm_malloc (sizeof (UBYTE) * 256)))    return 0;  memset (poslookup, -1, 256);  return 1;}void S3M_Cleanup (void){  _mm_free (s3mbuf);  _mm_free (paraptr);  _mm_free (poslookup);  _mm_free (mh);  _mm_free (origpositions);}/* Because so many s3m files have 16 channels as the set number used, but really   only use far less (usually 8 to 12 still), I had to make this function, which   determines the number of channels that are actually USED by a pattern.   For every channel that's used, it sets the appropriate array entry of the   global variable 'remap'   NOTE: You must first seek to the file location of the pattern before calling   this procedure.   Returns 1 on fail.                                                         */static BOOL S3M_GetNumChannels (void){  int row = 0, flag, ch;  while (row < 64)    {      flag = _mm_read_UBYTE (modreader);      if (_mm_eof (modreader))	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 1;	}      if (flag)	{	  ch = flag & 31;	  if (mh->channels[ch] < 32)	    remap[ch] = 0;	  if (flag & 32)	    {	      _mm_read_UBYTE (modreader);	      _mm_read_UBYTE (modreader);	    }	  if (flag & 64)	    _mm_read_UBYTE (modreader);	  if (flag & 128)	    {	      _mm_read_UBYTE (modreader);	      _mm_read_UBYTE (modreader);	    }	}      else	row++;    }  return 0;}static BOOL S3M_ReadPattern (void){  int row = 0, flag, ch;  S3MNOTE *n, dummy;  /* clear pattern data */  memset (s3mbuf, 255, 32 * 64 * sizeof (S3MNOTE));  while (row < 64)    {      flag = _mm_read_UBYTE (modreader);      if (_mm_eof (modreader))	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 0;	}      if (flag)	{	  ch = remap[flag & 31];	  if (ch != -1)	    n = &s3mbuf[(64U * ch) + row];	  else	    n = &dummy;	  if (flag & 32)	    {	      n->note = _mm_read_UBYTE (modreader);	      n->ins = _mm_read_UBYTE (modreader);	    }	  if (flag & 64)	    n->vol = _mm_read_UBYTE (modreader);	  if (flag & 128)	    {	      n->cmd = _mm_read_UBYTE (modreader);	      n->inf = _mm_read_UBYTE (modreader);	    }	}      else	row++;    }  return 1;}static UBYTE *S3M_ConvertTrack (S3MNOTE * tr){  int t;  UniReset ();  for (t = 0; t < 64; t++)    {      UBYTE note, ins, vol;      note = tr[t].note;      ins = tr[t].ins;      vol = tr[t].vol;      if ((ins) && (ins != 255))	UniInstrument (ins - 1);      if (note != 255)	{	  if (note == 254)	    {	      UniPTEffect (0xc, 0);	/* note cut command */	      vol = 255;	    }	  else	    UniNote (((note >> 4) * OCTAVE) + (note & 0xf));	/* normal note */	}      if (vol < 255)	UniPTEffect (0xc, vol);      S3MIT_ProcessCmd (tr[t].cmd, tr[t].inf, 1);      UniNewline ();    }  return UniDup ();}BOOL S3M_Load (BOOL curious){  int t, u, track = 0;  SAMPLE *q;  UBYTE pan[32];  /* try to read module header */  _mm_read_string (mh->songname, 28, modreader);  mh->t1a = _mm_read_UBYTE (modreader);  mh->type = _mm_read_UBYTE (modreader);  _mm_read_UBYTES (mh->unused1, 2, modreader);  mh->ordnum = _mm_read_I_UWORD (modreader);  mh->insnum = _mm_read_I_UWORD (modreader);  mh->patnum = _mm_read_I_UWORD (modreader);  mh->flags = _mm_read_I_UWORD (modreader);  mh->tracker = _mm_read_I_UWORD (modreader);  mh->fileformat = _mm_read_I_UWORD (modreader);  _mm_read_string (mh->scrm, 4, modreader);  mh->mastervol = _mm_read_UBYTE (modreader);  mh->initspeed = _mm_read_UBYTE (modreader);  mh->inittempo = _mm_read_UBYTE (modreader);  mh->mastermult = _mm_read_UBYTE (modreader);  mh->ultraclick = _mm_read_UBYTE (modreader);  mh->pantable = _mm_read_UBYTE (modreader);  _mm_read_UBYTES (mh->unused2, 8, modreader);  mh->special = _mm_read_I_UWORD (modreader);  _mm_read_UBYTES (mh->channels, 32, modreader);  if (_mm_eof (modreader))    {      _mm_errno = MMERR_LOADING_HEADER;      return 0;    }  /* set module variables */  of.songname = DupStr (mh->songname, 28, 0);  of.numpat = mh->patnum;  of.reppos = 0;  of.numins = of.numsmp = mh->insnum;  of.initspeed = mh->initspeed;  of.inittempo = mh->inittempo;  of.initvolume = mh->mastervol << 1;  of.flags |= UF_ARPMEM;  if ((mh->tracker == 0x1300) || (mh->flags & 64))    of.flags |= UF_S3MSLIDES;  /* read the order data */  if (!AllocPositions (mh->ordnum))    return 0;  if (!(origpositions = _mm_calloc (mh->ordnum, sizeof (UWORD))))    return 0;  for (t = 0; t < mh->ordnum; t++)    {      origpositions[t] = _mm_read_UBYTE (modreader);      if ((origpositions[t] >= mh->patnum) && (origpositions[t] < 254))	origpositions[t] = 255 /*mh->patnum-1 */ ;    }  if (_mm_eof (modreader))    {      _mm_errno = MMERR_LOADING_HEADER;      return 0;    }  poslookupcnt = mh->ordnum;  S3MIT_CreateOrders (curious);  if (!(paraptr = (UWORD *) _mm_malloc ((of.numins + of.numpat) * sizeof (UWORD))))    return 0;  /* read the instrument+pattern parapointers */  _mm_read_I_UWORDS (paraptr, of.numins + of.numpat, modreader);  if (mh->pantable == 252)    {      /* read the panning table (ST 3.2 addition.  See below for further         portions of channel panning [past reampper]). */      _mm_read_UBYTES (pan, 32, modreader);    }  if (_mm_eof (modreader))    {      _mm_errno = MMERR_LOADING_HEADER;      return 0;    }  /* load samples */  if (!AllocSamples ())    return 0;  q = of.samples;  for (t = 0; t < of.numins; t++)    {      S3MSAMPLE s;      /* seek to instrument position */      _mm_fseek (modreader, ((long) paraptr[t]) << 4, SEEK_SET);      /* and load sample info */      s.type = _mm_read_UBYTE (modreader);      _mm_read_string (s.filename, 12, modreader);      s.memsegh = _mm_read_UBYTE (modreader);      s.memsegl = _mm_read_I_UWORD (modreader);      s.length = _mm_read_I_ULONG (modreader);      s.loopbeg = _mm_read_I_ULONG (modreader);      s.loopend = _mm_read_I_ULONG (modreader);      s.volume = _mm_read_UBYTE (modreader);      s.dsk = _mm_read_UBYTE (modreader);      s.pack = _mm_read_UBYTE (modreader);      s.flags = _mm_read_UBYTE (modreader);      s.c2spd = _mm_read_I_ULONG (modreader);      _mm_read_UBYTES (s.unused, 12, modreader);      _mm_read_string (s.sampname, 28, modreader);      _mm_read_string (s.scrs, 4, modreader);      if (_mm_eof (modreader))	{	  _mm_errno = MMERR_LOADING_SAMPLEINFO;	  return 0;	}      q->samplename = DupStr (s.sampname, 28, 0);      q->speed = s.c2spd;      q->length = s.length;      q->loopstart = s.loopbeg > s.length ? s.length : s.loopbeg;      q->loopend = s.loopend > s.length ? s.length : s.loopend;      q->volume = s.volume;      q->seekpos = (((long) s.memsegh) << 16 | s.memsegl) << 4;      if (s.flags & 1)	q->flags |= SF_LOOP;      if (s.flags & 4)	q->flags |= SF_16BITS;      if (mh->fileformat == 1)	q->flags |= SF_SIGNED;      /* don't load sample if it doesn't have the SCRS tag */      if (memcmp (s.scrs, "SCRS", 4))	q->length = 0;      q++;    }  /* determine the number of channels actually used. */  of.numchn = 0;  memset (remap, -1, 32 * sizeof (UBYTE));  for (t = 0; t < of.numpat; t++)    {      /* seek to pattern position (+2 skip pattern length) */      _mm_fseek (modreader, (long) ((paraptr[of.numins + t]) << 4) + 2, SEEK_SET);      if (S3M_GetNumChannels ())	return 0;    }  /* then we can decide the module type */  t = mh->tracker >> 12;  if ((!t) || (t > 3))    t = NUMTRACKERS - 1;	/* unknown tracker */  else    {      if (mh->tracker >= 0x3217)	t = NUMTRACKERS + 1;	/* IT 2.14p4 */      else if (mh->tracker >= 0x3216)	t = NUMTRACKERS;	/* IT 2.14p3 */      else	t--;    }  of.modtype = strdup (S3M_Version[t]);  if (t < NUMTRACKERS)    {      of.modtype[numeric[t]] = ((mh->tracker >> 8) & 0xf) + '0';      of.modtype[numeric[t] + 2] = ((mh->tracker >> 4) & 0xf) + '0';      of.modtype[numeric[t] + 3] = ((mh->tracker) & 0xf) + '0';    }  /* build the remap array  */  for (t = 0; t < 32; t++)    if (!remap[t])      remap[t] = of.numchn++;  /* set panning positions after building remap chart! */  for (t = 0; t < 32; t++)    if ((mh->channels[t] < 32) && (remap[t] != -1))      {	if (mh->channels[t] < 8)	  of.panning[remap[t]] = 0x20;	/* 0x30 = std s3m val */	else	  of.panning[remap[t]] = 0xd0;	/* 0xc0 = std s3m val */      }  if (mh->pantable == 252)    /* set panning positions according to panning table (new for st3.2) */    for (t = 0; t < 32; t++)      if ((pan[t] & 0x20) && (mh->channels[t] < 32) && (remap[t] != -1))	of.panning[remap[t]] = (pan[t] & 0xf) << 4;  /* load pattern info */  of.numtrk = of.numpat * of.numchn;  if (!AllocTracks ())    return 0;  if (!AllocPatterns ())    return 0;  for (t = 0; t < of.numpat; t++)    {      /* seek to pattern position (+2 skip pattern length) */      _mm_fseek (modreader, (((long) paraptr[of.numins + t]) << 4) + 2, SEEK_SET);      if (!S3M_ReadPattern ())	return 0;      for (u = 0; u < of.numchn; u++)	if (!(of.tracks[track++] = S3M_ConvertTrack (&s3mbuf[u * 64])))	  return 0;    }  return 1;}CHAR *S3M_LoadTitle (void){  CHAR s[28];  _mm_fseek (modreader, 0, SEEK_SET);  if (!_mm_read_UBYTES (s, 28, modreader))    return NULL;  return (DupStr (s, 28, 0));}/*========== Loader information */MLOADER load_s3m ={  NULL,  "S3M",  "S3M (Scream Tracker 3)",  S3M_Init,  S3M_Test,  S3M_Load,  S3M_Cleanup,  S3M_LoadTitle};/* ex:set ts=4: */

⌨️ 快捷键说明

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