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

📄 munitrk.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: munitrk.c,v 1.27 1999/10/25 16:31:41 miod Exp $  All routines dealing with the manipulation of UNITRK streams==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "unimod_priv.h"#include <string.h>/* Unibuffer chunk size */#define BUFPAGE  128UWORD unioperands[UNI_LAST] ={  0,				/* not used */  1,				/* UNI_NOTE */  1,				/* UNI_INSTRUMENT */  1,				/* UNI_PTEFFECT0 */  1,				/* UNI_PTEFFECT1 */  1,				/* UNI_PTEFFECT2 */  1,				/* UNI_PTEFFECT3 */  1,				/* UNI_PTEFFECT4 */  1,				/* UNI_PTEFFECT5 */  1,				/* UNI_PTEFFECT6 */  1,				/* UNI_PTEFFECT7 */  1,				/* UNI_PTEFFECT8 */  1,				/* UNI_PTEFFECT9 */  1,				/* UNI_PTEFFECTA */  1,				/* UNI_PTEFFECTB */  1,				/* UNI_PTEFFECTC */  1,				/* UNI_PTEFFECTD */  1,				/* UNI_PTEFFECTE */  1,				/* UNI_PTEFFECTF */  1,				/* UNI_S3MEFFECTA */  1,				/* UNI_S3MEFFECTD */  1,				/* UNI_S3MEFFECTE */  1,				/* UNI_S3MEFFECTF */  1,				/* UNI_S3MEFFECTI */  1,				/* UNI_S3MEFFECTQ */  1,				/* UNI_S3MEFFECTR */  1,				/* UNI_S3MEFFECTT */  1,				/* UNI_S3MEFFECTU */  0,				/* UNI_KEYOFF */  1,				/* UNI_KEYFADE */  2,				/* UNI_VOLEFFECTS */  1,				/* UNI_XMEFFECT4 */  1,				/* UNI_XMEFFECTA */  1,				/* UNI_XMEFFECTE1 */  1,				/* UNI_XMEFFECTE2 */  1,				/* UNI_XMEFFECTEA */  1,				/* UNI_XMEFFECTEB */  1,				/* UNI_XMEFFECTG */  1,				/* UNI_XMEFFECTH */  1,				/* UNI_XMEFFECTL */  1,				/* UNI_XMEFFECTP */  1,				/* UNI_XMEFFECTX1 */  1,				/* UNI_XMEFFECTX2 */  1,				/* UNI_ITEFFECTG */  1,				/* UNI_ITEFFECTH */  1,				/* UNI_ITEFFECTI */  1,				/* UNI_ITEFFECTM */  1,				/* UNI_ITEFFECTN */  1,				/* UNI_ITEFFECTP */  1,				/* UNI_ITEFFECTT */  1,				/* UNI_ITEFFECTU */  1,				/* UNI_ITEFFECTW */  1,				/* UNI_ITEFFECTY */  2,				/* UNI_ITEFFECTZ */  1,				/* UNI_ITEFFECTS0 */  2,				/* UNI_ULTEFFECT9 */  2,				/* UNI_MEDSPEED */  0,				/* UNI_MEDEFFECTF1 */  0,				/* UNI_MEDEFFECTF2 */  0				/* UNI_MEDEFFECTF3 */};/* Sparse description of the internal module format   ------------------------------------------------   A UNITRK stream is an array of bytes representing a single track of a pattern.   It's made up of 'repeat/length' bytes, opcodes and operands (sort of a assembly   language):   rrrlllll   [REP/LEN][OPCODE][OPERAND][OPCODE][OPERAND] [REP/LEN][OPCODE][OPERAND]..   ^                                         ^ ^   |-------ROWS 0 - 0+REP of a track---------| |-------ROWS xx - xx+REP of a track...   The rep/len byte contains the number of bytes in the current row, _including_   the length byte itself (So the LENGTH byte of row 0 in the previous example   would have a value of 5). This makes it easy to search through a stream for a   particular row. A track is concluded by a 0-value length byte.   The upper 3 bits of the rep/len byte contain the number of times -1 this row   is repeated for this track. (so a value of 7 means this row is repeated 8 times)   Opcodes can range from 1 to 255 but currently only opcodes 1 to 52 are being   used. Each opcode can have a different number of operands. You can find the   number of operands to a particular opcode by using the opcode as an index into   the 'unioperands' table. *//*========== Reading routines */static UBYTE *rowstart;		/* startadress of a row */static UBYTE *rowend;		/* endaddress of a row (exclusive) */static UBYTE *rowpc;		/* current unimod(tm) programcounter */void UniSetRow (UBYTE * t){  rowstart = t;  rowpc = rowstart;  rowend = t ? rowstart + (*(rowpc++) & 0x1f) : t;}UBYTE UniGetByte (void){  return (rowpc < rowend) ? *(rowpc++) : 0;}UWORD UniGetWord (void){  return ((UWORD) UniGetByte () << 8) | UniGetByte ();}void UniSkipOpcode (UBYTE op){  if (op < UNI_LAST)    {      UWORD t = unioperands[op];      while (t--)	UniGetByte ();    }}/* Finds the address of row number 'row' in the UniMod(tm) stream 't' returns   NULL if the row can't be found. */UBYTE *UniFindRow (UBYTE * t, UWORD row){  UBYTE c, l;  if (t)    while (1)      {	c = *t;			/* get rep/len byte */	if (!c)	  return NULL;		/* zero ? -> end of track.. */	l = (c >> 5) + 1;	/* extract repeat value */	if (l > row)	  break;		/* reached wanted row? -> return pointer */	row -= l;		/* haven't reached row yet.. update row */	t += c & 0x1f;		/* point t to the next row */      }  return t;}/*========== Writing routines */static UBYTE *unibuf;		/* pointer to the temporary unitrk buffer */static UWORD unimax;		/* buffer size */static UWORD unipc;		/* buffer cursor */static UWORD unitt;		/* current row index */static UWORD lastp;		/* previous row index *//* Resets index-pointers to create a new track. */void UniReset (void){  unitt = 0;			/* reset index to rep/len byte */  unipc = 1;			/* first opcode will be written to index 1 */  lastp = 0;			/* no previous row yet */  unibuf[0] = 0;		/* clear rep/len byte */}/* Expands the buffer */static BOOL UniExpand (int wanted){  if ((unipc + wanted) >= unimax)    {      UBYTE *newbuf;      /* Expand the buffer by BUFPAGE bytes */      newbuf = (UBYTE *) realloc (unibuf, (unimax + BUFPAGE) * sizeof (UBYTE));      /* Check if realloc succeeded */      if (newbuf)	{	  unibuf = newbuf;	  unimax += BUFPAGE;	  return 1;	}      else	return 0;    }  return 1;}/* Appends one byte of data to the current row of a track. */void UniWriteByte (UBYTE data){  if (UniExpand (1))    /* write byte to current position and update */    unibuf[unipc++] = data;}void UniWriteWord (UWORD data){  if (UniExpand (2))    {      unibuf[unipc++] = data >> 8;      unibuf[unipc++] = data & 0xff;    }}static BOOL MyCmp (UBYTE * a, UBYTE * b, UWORD l){  UWORD t;  for (t = 0; t < l; t++)    if (*(a++) != *(b++))      return 0;  return 1;}/* Closes the current row of a unitrk stream (updates the rep/len byte) and sets   pointers to start a new row. */void UniNewline (void){  UWORD n, l, len;  n = (unibuf[lastp] >> 5) + 1;	/* repeat of previous row */  l = (unibuf[lastp] & 0x1f);	/* length of previous row */  len = unipc - unitt;		/* length of current row */  /* Now, check if the previous and the current row are identical.. when they     are, just increase the repeat field of the previous row */  if (n < 8 && len == l && MyCmp (&unibuf[lastp + 1], &unibuf[unitt + 1], len - 1))    {      unibuf[lastp] += 0x20;      unipc = unitt + 1;    }  else    {      if (UniExpand (unitt - unipc))	{	  /* current and previous row aren't equal... update the pointers */	  unibuf[unitt] = len;	  lastp = unitt;	  unitt = unipc++;	}    }}/* Terminates the current unitrk stream and returns a pointer to a copy of the   stream. */UBYTE *UniDup (void){  UBYTE *d;  if (!UniExpand (unitt - unipc))    return NULL;  unibuf[unitt] = 0;  if (!(d = (UBYTE *) _mm_malloc (unipc)))    return NULL;  memcpy (d, unibuf, unipc);  return d;}BOOL UniInit (void){  unimax = BUFPAGE;  if (!(unibuf = (UBYTE *) _mm_malloc (unimax * sizeof (UBYTE))))    return 0;  return 1;}void UniCleanup (void){  if (unibuf)    free (unibuf);  unibuf = NULL;}/* ex:set ts=4: */

⌨️ 快捷键说明

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