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

📄 load_gdm.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_gdm.c,v 1.5 1999/10/25 16:31:41 miod Exp $  General DigiMusic (GDM) module loader==============================================================================*//*   Written by Kev Vance<kvance@zeux.org>   based on the file format description written by 'MenTaLguY'   <mental@kludge.org> */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <string.h>#include "unimod_priv.h"typedef struct GDMNOTE  {    UBYTE note;    UBYTE samp;    struct      {	UBYTE effect;	UBYTE param;      }    effect[4];  }GDMNOTE;typedef GDMNOTE GDMTRACK[64];typedef struct GDMHEADER  {    CHAR id1[4];    CHAR songname[32];    CHAR author[32];    CHAR eofmarker[3];    CHAR id2[4];    UBYTE majorver;    UBYTE minorver;    UWORD trackerid;    UBYTE t_majorver;    UBYTE t_minorver;    UBYTE pantable[32];    UBYTE mastervol;    UBYTE mastertempo;    UBYTE masterbpm;    UWORD flags;    ULONG orderloc;    UBYTE ordernum;    ULONG patternloc;    UBYTE patternnum;    ULONG samhead;    ULONG samdata;    UBYTE samnum;    ULONG messageloc;    ULONG messagelen;    ULONG scrollyloc;    UWORD scrollylen;    ULONG graphicloc;    UWORD graphiclen;  }GDMHEADER;typedef struct GDMSAMPLE  {    CHAR sampname[32];    CHAR filename[13];    UBYTE ems;    ULONG length;    ULONG loopbeg;    ULONG loopend;    UBYTE flags;    UWORD c4spd;    UBYTE vol;    UBYTE pan;  }GDMSAMPLE;static GDMHEADER *mh = NULL;	/* pointer to GDM header */static GDMNOTE *gdmbuf = NULL;	/* pointer to a complete GDM pattern */CHAR GDM_Version[] = "General DigiMusic 1.xx";BOOL GDM_Test (void){  /* test for gdm magic numbers */  UBYTE id[4];  _mm_fseek (modreader, 0x00, SEEK_SET);  if (!_mm_read_UBYTES (id, 4, modreader))    return 0;  if (!memcmp (id, "GDM\xfe", 4))    {      _mm_fseek (modreader, 71, SEEK_SET);      if (!_mm_read_UBYTES (id, 4, modreader))	return 0;      if (!memcmp (id, "GMFS", 4))	return 1;    }  return 0;}BOOL GDM_Init (void){  if (!(gdmbuf = (GDMNOTE *) _mm_malloc (32 * 64 * sizeof (GDMNOTE))))    return 0;  if (!(mh = (GDMHEADER *) _mm_malloc (sizeof (GDMHEADER))))    return 0;  return 1;}void GDM_Cleanup (void){  _mm_free (mh);  _mm_free (gdmbuf);}BOOL GDM_ReadPattern (void){  int pos, flag, ch, i, maxch;  GDMNOTE n;  UWORD length, x = 0;  /* get pattern length */  length = _mm_read_I_UWORD (modreader) - 2;  /* clear pattern data */  memset (gdmbuf, 255, 32 * 64 * sizeof (GDMNOTE));  pos = 0;  maxch = 0;  while (x < length)    {      memset (&n, 255, sizeof (GDMNOTE));      flag = _mm_read_UBYTE (modreader);      x++;      if (_mm_eof (modreader))	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 0;	}      ch = flag & 31;      if (ch > maxch)	maxch = ch;      if (!flag)	{	  pos++;	  continue;	}      if (flag & 0x60)	{	  if (flag & 0x20)	    {	      /* new note */	      n.note = _mm_read_UBYTE (modreader) & 127;	      n.samp = _mm_read_UBYTE (modreader);	      x += 2;	    }	  if (flag & 0x40)	    {	      do		{		  /* effect channel set */		  i = _mm_read_UBYTE (modreader);		  n.effect[i >> 6].effect = i & 31;		  n.effect[i >> 6].param = _mm_read_UBYTE (modreader);		  x += 2;		}	      while (i & 32);	    }	  memcpy (gdmbuf + (64U * ch) + pos, &n, sizeof (n));	}    }  return 1;}UBYTE *GDM_ConvertTrack (GDMNOTE * tr){  int t, i = 0;  UBYTE note, ins;  UniReset ();  for (t = 0; t < 64; t++)    {      note = tr[t].note;      ins = tr[t].samp;      if ((ins) && (ins != 255))	UniInstrument (ins - 1);      if (note != 255)	{	  UniNote (((note >> 4) * OCTAVE) + (note & 0xf) - 1);	}      for (i = 0; i < 4; i++)	{	  switch (tr[t].effect[i].effect)	    {	    case 1:		/* toneslide up */	      UniEffect (UNI_S3MEFFECTF, tr[t].effect[i].param);	      break;	    case 2:		/* toneslide down */	      UniEffect (UNI_S3MEFFECTE, tr[t].effect[i].param);	      break;	    case 3:		/* glissando to note */	      UniEffect (UNI_ITEFFECTG, tr[t].effect[i].param);	      break;	    case 4:		/* vibrato */	      UniEffect (UNI_ITEFFECTH, tr[t].effect[i].param);	      break;	    case 5:		/* portamento+volslide */	      UniEffect (UNI_ITEFFECTG, 0);	      UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);	      break;	    case 6:		/* vibrato+volslide */	      UniEffect (UNI_ITEFFECTH, 0);	      UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);	      break;	    case 7:		/* tremolo */	      UniEffect (UNI_S3MEFFECTR, tr[t].effect[i].param);	      break;	    case 8:		/* tremor */	      UniEffect (UNI_S3MEFFECTI, tr[t].effect[i].param);	      break;	    case 9:		/* offset */	      UniPTEffect (0x09, tr[t].effect[i].param);	      break;	    case 0x0a:		/* volslide */	      UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);	      break;	    case 0x0b:		/* jump to order */	      UniPTEffect (0x0b, tr[t].effect[i].param);	      break;	    case 0x0c:		/* volume set */	      UniPTEffect (0x0c, tr[t].effect[i].param);	      break;	    case 0x0d:		/* pattern break */	      UniPTEffect (0x0d, tr[t].effect[i].param);	      break;	    case 0x0e:		/* extended */	      switch (tr[t].effect[i].param & 0xf0)		{		case 0x10:	/* fine portamento up */		  UniEffect (UNI_S3MEFFECTF,			     0x0f | ((tr[t].effect[i].param << 4) & 0x0f));		  break;		case 0x20:	/* fine portamento down */		  UniEffect (UNI_S3MEFFECTE,			     0xf0 | (tr[t].effect[i].param & 0x0f));		  break;		case 0x30:	/* glissando control */		  UniEffect (SS_GLISSANDO,			     tr[t].effect[i].param & 0x0f);		  break;		case 0x40:	/* vibrato waveform */		  UniEffect (SS_VIBWAVE,			     tr[t].effect[i].param & 0x0f);		  break;		case 0x50:	/* set c4spd */		  UniEffect (SS_FINETUNE,			     tr[t].effect[i].param & 0x0f);		  break;		case 0x60:	/* loop fun */		  UniEffect (UNI_ITEFFECTS0,			     (tr[t].effect[i].param & 0x0f) | 0xb0);		  break;		case 0x70:	/* tremolo waveform */		  UniEffect (SS_TREMWAVE,			     tr[t].effect[i].param & 0x0f);		  break;		case 0x80:	/* extra fine porta up */		  UniEffect (UNI_S3MEFFECTF,			     0x0e | ((tr[t].effect[i].param << 4) & 0x0f));		  break;		case 0x90:	/* extra fine porta down */		  UniEffect (UNI_S3MEFFECTE,			     0xe0 | (tr[t].effect[i].param & 0x0f));		  break;		case 0xa0:	/* fine volslide up */		  UniEffect (UNI_S3MEFFECTD,			     0x0f | ((tr[t].effect[i].param << 4) & 0x0f));		  break;		case 0xb0:	/* fine volslide down */		  UniEffect (UNI_S3MEFFECTE,			     0xf0 | (tr[t].effect[i].param & 0x0f));		  break;		case 0xc0:	/* note cut */		case 0xd0:	/* note delay */		case 0xe0:	/* extend row */		  UniPTEffect (0xe, tr[t].effect[i].param);		  break;		}	      break;	    case 0x0f:		/* set tempo */	      UniEffect (UNI_S3MEFFECTA, tr[t].effect[i].param);	      break;	    case 0x10:		/* arpeggio */	      UniPTEffect (0x0, tr[t].effect[i].param);	      break;	    case 0x12:		/* retrigger */	      UniEffect (UNI_S3MEFFECTQ, tr[t].effect[i].param);	      break;	    case 0x13:		/* set global volume */	      UniEffect (UNI_XMEFFECTG, tr[t].effect[i].param);	      break;	    case 0x14:		/* fine vibrato */	      UniEffect (UNI_ITEFFECTU, tr[t].effect[i].param);	      break;	    case 0x1e:		/* special */	      switch (tr[t].effect[i].param & 0xf0)		{		case 8:	/* set pan position */		  if (tr[t].effect[i].param >= 128)		    UniPTEffect (0x08, 255);		  else		    UniPTEffect (0x08, tr[t].effect[i].param << 1);		  break;		}	      break;	    case 0x1f:		/* set bpm */	      if (tr[t].effect[i].param >= 0x20)		UniEffect (UNI_S3MEFFECTT, tr[t].effect[i].param);	      break;	    }	}      UniNewline ();    }  return UniDup ();}BOOL GDM_Load (BOOL curious){  int i, x, u, track;  SAMPLE *q;  GDMSAMPLE s;  ULONG position;  /* read header */  _mm_read_string (mh->id1, 4, modreader);  _mm_read_string (mh->songname, 32, modreader);  _mm_read_string (mh->author, 32, modreader);  _mm_read_string (mh->eofmarker, 3, modreader);  _mm_read_string (mh->id2, 4, modreader);  mh->majorver = _mm_read_UBYTE (modreader);  mh->minorver = _mm_read_UBYTE (modreader);  mh->trackerid = _mm_read_I_UWORD (modreader);  mh->t_majorver = _mm_read_UBYTE (modreader);  mh->t_minorver = _mm_read_UBYTE (modreader);  _mm_read_UBYTES (mh->pantable, 32, modreader);  mh->mastervol = _mm_read_UBYTE (modreader);  mh->mastertempo = _mm_read_UBYTE (modreader);  mh->masterbpm = _mm_read_UBYTE (modreader);  mh->flags = _mm_read_I_UWORD (modreader);  mh->orderloc = _mm_read_I_ULONG (modreader);  mh->ordernum = _mm_read_UBYTE (modreader);  mh->patternloc = _mm_read_I_ULONG (modreader);  mh->patternnum = _mm_read_UBYTE (modreader);  mh->samhead = _mm_read_I_ULONG (modreader);  mh->samdata = _mm_read_I_ULONG (modreader);  mh->samnum = _mm_read_UBYTE (modreader);  mh->messageloc = _mm_read_I_ULONG (modreader);  mh->messagelen = _mm_read_I_ULONG (modreader);  mh->scrollyloc = _mm_read_I_ULONG (modreader);  mh->scrollylen = _mm_read_I_UWORD (modreader);  mh->graphicloc = _mm_read_I_ULONG (modreader);  mh->graphiclen = _mm_read_I_UWORD (modreader);  /* have we ended abruptly? */  if (_mm_eof (modreader))    {      _mm_errno = MMERR_LOADING_HEADER;      return 0;    }  /* any orders? */  if (mh->ordernum == 255)    {      _mm_errno = MMERR_LOADING_PATTERN;      return 0;    }  /* now we fill */  of.modtype = strdup (GDM_Version);  of.modtype[18] = mh->majorver + '0';  of.modtype[20] = mh->minorver / 10 + '0';  of.modtype[21] = mh->minorver % 10 + '0';  of.songname = DupStr (mh->songname, 32, 0);  of.numpat = mh->patternnum + 1;  of.reppos = 0;  of.numins = of.numsmp = mh->samnum + 1;  of.initspeed = mh->mastertempo;  of.inittempo = mh->masterbpm;  of.initvolume = mh->mastervol << 1;  of.flags |= UF_S3MSLIDES;  /* read the order data */  if (!AllocPositions (mh->ordernum + 1))    {      _mm_errno = MMERR_OUT_OF_MEMORY;      return 0;    }  _mm_fseek (modreader, mh->orderloc, SEEK_SET);  for (i = 0; i < mh->ordernum + 1; i++)    of.positions[i] = _mm_read_UBYTE (modreader);  of.numpos = 0;  for (i = 0; i < mh->ordernum + 1; i++)    {      of.positions[of.numpos] = of.positions[i];      if (of.positions[i] < 254)	of.numpos++;    }  /* have we ended abruptly yet? */  if (_mm_eof (modreader))    {      _mm_errno = MMERR_LOADING_HEADER;      return 0;    }  /* time to load the samples */  if (!AllocSamples ())    {      _mm_errno = MMERR_OUT_OF_MEMORY;      return 0;    }  q = of.samples;  position = mh->samdata;  /* seek to instrument position */  _mm_fseek (modreader, mh->samhead, SEEK_SET);  for (i = 0; i < of.numins; i++)    {      /* load sample info */      _mm_read_UBYTES (s.sampname, 32, modreader);      _mm_read_UBYTES (s.filename, 12, modreader);      s.ems = _mm_read_UBYTE (modreader);      s.length = _mm_read_I_ULONG (modreader);      s.loopbeg = _mm_read_I_ULONG (modreader);      s.loopend = _mm_read_I_ULONG (modreader);      s.flags = _mm_read_UBYTE (modreader);      s.c4spd = _mm_read_I_UWORD (modreader);      s.vol = _mm_read_UBYTE (modreader);      s.pan = _mm_read_UBYTE (modreader);      if (_mm_eof (modreader))	{	  _mm_errno = MMERR_LOADING_SAMPLEINFO;	  return 0;	}      q->samplename = DupStr (s.sampname, 32, 0);      q->speed = s.c4spd;      q->length = s.length;      q->loopstart = s.loopbeg;      q->loopend = s.loopend;      q->volume = s.vol;      q->panning = s.pan;      q->seekpos = position;      position += s.length;      if (s.flags & 1)	q->flags |= SF_LOOP;      if (s.flags & 2)	q->flags |= SF_16BITS;      if (s.flags & 16)	q->flags |= SF_STEREO;      q++;    }  /* set the panning */  for (i = x = 0; i < 32; i++)    {      of.panning[i] = mh->pantable[i];      if (!of.panning[i])	of.panning[i] = PAN_LEFT;      else if (of.panning[i] == 8)	of.panning[i] = PAN_CENTER;      else if (of.panning[i] == 15)	of.panning[i] = PAN_RIGHT;      else if (of.panning[i] == 16)	of.panning[i] = PAN_SURROUND;      else if (of.panning[i] == 255)	of.panning[i] = 128;      else	of.panning[i] <<= 3;      of.panning[i] = PAN_CENTER;      if (mh->pantable[i] != 255)	x = i;    }  of.numchn = x + 1;  if (of.numchn < 1)    of.numchn = 1;		/* for broken counts */  /* load the pattern info */  of.numtrk = of.numpat * of.numchn;  /* jump to patterns */  _mm_fseek (modreader, mh->patternloc, SEEK_SET);  if (!AllocTracks ())    {      _mm_errno = MMERR_OUT_OF_MEMORY;      return 0;    }  if (!AllocPatterns ())    {      _mm_errno = MMERR_OUT_OF_MEMORY;      return 0;    }  for (i = track = 0; i < of.numpat; i++)    {      if (!GDM_ReadPattern ())	{	  _mm_errno = MMERR_LOADING_PATTERN;	  return 0;	}      for (u = 0; u < of.numchn; u++, track++)	{	  of.tracks[track] = GDM_ConvertTrack (&gdmbuf[u << 6]);	  if (!of.tracks[track])	    {	      _mm_errno = MMERR_LOADING_TRACK;	      return 0;	    }	}    }  return 1;}CHAR *GDM_LoadTitle (void){  CHAR s[32];  _mm_fseek (modreader, 4, SEEK_SET);  if (!_mm_read_UBYTES (s, 32, modreader))    return NULL;  return DupStr (s, 28, 0);}MLOADER load_gdm ={  NULL,  "GDM",  "GDM (General DigiMusic)",  GDM_Init,  GDM_Test,  GDM_Load,  GDM_Cleanup,  GDM_LoadTitle};/* ex:set ts=4: */

⌨️ 快捷键说明

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