📄 load_imf.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_imf.c,v 1.12 1999/10/25 16:31:41 miod Exp $ Imago Orpheus (IMF) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "unimod_priv.h"/*========== Module structure *//* module header */typedef struct IMFHEADER { CHAR songname[32]; UWORD ordnum; UWORD patnum; UWORD insnum; UWORD flags; UBYTE initspeed; UBYTE inittempo; UBYTE mastervol; UBYTE mastermult; UBYTE orders[256]; }IMFHEADER;/* channel settings */typedef struct IMFCHANNEL { CHAR name[12]; UBYTE chorus; UBYTE reverb; UBYTE pan; UBYTE status; }IMFCHANNEL;/* instrument header */#define IMFNOTECNT (10*OCTAVE)#define IMFENVCNT (16*2)typedef struct IMFINSTHEADER { CHAR name[32]; UBYTE what[IMFNOTECNT]; UWORD volenv[IMFENVCNT]; UWORD panenv[IMFENVCNT]; UWORD pitenv[IMFENVCNT]; UBYTE volpts; UBYTE volsus; UBYTE volbeg; UBYTE volend; UBYTE volflg; UBYTE panpts; UBYTE pansus; UBYTE panbeg; UBYTE panend; UBYTE panflg; UBYTE pitpts; UBYTE pitsus; UBYTE pitbeg; UBYTE pitend; UBYTE pitflg; UWORD volfade; UWORD numsmp; ULONG signature; }IMFINSTHEADER;/* sample header */typedef struct IMFWAVHEADER { CHAR samplename[13]; ULONG length; ULONG loopstart; ULONG loopend; ULONG samplerate; UBYTE volume; UBYTE pan; UBYTE flags; }IMFWAVHEADER;typedef struct IMFNOTE { UBYTE note, ins, eff1, dat1, eff2, dat2; }IMFNOTE;/*========== Loader variables */static CHAR IMF_Version[] = "Imago Orpheus";static IMFNOTE *imfpat = NULL;static IMFHEADER *mh = NULL;/*========== Loader code */BOOL IMF_Test (void){ UBYTE id[4]; _mm_fseek (modreader, 0x3c, SEEK_SET); if (!_mm_read_UBYTES (id, 4, modreader)) return 0; if (!memcmp (id, "IM10", 4)) return 1; return 0;}BOOL IMF_Init (void){ if (!(imfpat = (IMFNOTE *) _mm_malloc (32 * 256 * sizeof (IMFNOTE)))) return 0; if (!(mh = (IMFHEADER *) _mm_malloc (sizeof (IMFHEADER)))) return 0; return 1;}void IMF_Cleanup (void){ FreeLinear (); _mm_free (imfpat); _mm_free (mh);}static BOOL IMF_ReadPattern (SLONG size, UWORD rows){ int row = 0, flag, ch; IMFNOTE *n, dummy; /* clear pattern data */ memset (imfpat, 255, 32 * 256 * sizeof (IMFNOTE)); while ((size > 0) && (row < rows)) { flag = _mm_read_UBYTE (modreader); size--; if (_mm_eof (modreader)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } if (flag) { ch = remap[flag & 31]; if (ch != -1) n = &imfpat[256 * ch + row]; else n = &dummy; if (flag & 32) { n->note = _mm_read_UBYTE (modreader); if (n->note >= 0xa0) n->note = 0xa0; /* note off */ n->ins = _mm_read_UBYTE (modreader); size -= 2; } if (flag & 64) { size -= 2; n->eff2 = _mm_read_UBYTE (modreader); n->dat2 = _mm_read_UBYTE (modreader); } if (flag & 128) { n->eff1 = _mm_read_UBYTE (modreader); n->dat1 = _mm_read_UBYTE (modreader); size -= 2; } } else row++; } if ((size) || (row != rows)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } return 1;}static void IMF_ProcessCmd (UBYTE eff, UBYTE inf){ if ((eff) && (eff != 255)) switch (eff) { case 0x01: /* set tempo */ UniEffect (UNI_S3MEFFECTA, inf); break; case 0x02: /* set BPM */ if (inf >= 0x20) UniEffect (UNI_S3MEFFECTT, inf); break; case 0x03: /* tone portamento */ UniEffect (UNI_ITEFFECTG, inf); break; case 0x04: /* porta + volslide */ UniEffect (UNI_ITEFFECTG, inf); UniEffect (UNI_S3MEFFECTD, 0); break; case 0x05: /* vibrato */ UniPTEffect (0x4, inf); break; case 0x06: /* vibrato + volslide */ UniPTEffect (0x4, inf); UniEffect (UNI_S3MEFFECTD, 0); break; case 0x07: /* fine vibrato */ UniEffect (UNI_ITEFFECTU, inf); break; case 0x08: /* tremolo */ UniEffect (UNI_S3MEFFECTR, inf); break; case 0x09: /* arpeggio */ UniPTEffect (0x0, inf); break; case 0x0a: /* panning */ UniPTEffect (0x8, (inf >= 128) ? 255 : (inf << 1)); break; case 0x0b: /* pan slide */ UniEffect (UNI_XMEFFECTP, inf); break; case 0x0c: /* set channel volume */ if (inf <= 64) UniPTEffect (0xc, inf); break; case 0x0d: /* volume slide */ UniEffect (UNI_S3MEFFECTD, inf); break; case 0x0e: /* fine volume slide */ if (inf) { if (inf >> 4) UniEffect (UNI_S3MEFFECTD, 0x0f | inf); else UniEffect (UNI_S3MEFFECTD, 0xf0 | inf); } else UniEffect (UNI_S3MEFFECTD, 0); break; case 0x0f: /* set finetune */ UniPTEffect (0xe, 0x50 | (inf >> 4)); break;#ifdef MIKMOD_DEBUG case 0x10: /* note slide up */ case 0x11: /* not slide down */ fprintf (stderr, "\rIMF effect 0x10/0x11 (note slide)" " not implemented (eff=%2X inf=%2X)\n", eff, inf); break;#endif case 0x12: /* slide up */ UniEffect (UNI_S3MEFFECTF, inf); break; case 0x13: /* slide down */ UniEffect (UNI_S3MEFFECTE, inf); break; case 0x14: /* fine slide up */ if (inf) { if (inf < 0x40) UniEffect (UNI_S3MEFFECTF, 0xe0 | (inf / 4)); else UniEffect (UNI_S3MEFFECTF, 0xf0 | (inf >> 4)); } else UniEffect (UNI_S3MEFFECTF, 0); break; case 0x15: /* fine slide down */ if (inf) { if (inf < 0x40) UniEffect (UNI_S3MEFFECTE, 0xe0 | (inf / 4)); else UniEffect (UNI_S3MEFFECTE, 0xf0 | (inf >> 4)); } else UniEffect (UNI_S3MEFFECTE, 0); break; /* 0x16 set filter cutoff (awe32) */ /* 0x17 filter side + resonance (awe32) */ case 0x18: /* sample offset */ UniPTEffect (0x9, inf); break;#ifdef MIKMOD_DEBUG case 0x19: /* set fine sample offset */ fprintf (stderr, "\rIMF effect 0x19 (fine sample offset)" " not implemented (inf=%2X)\n", inf); break;#endif case 0x1a: /* keyoff */ UniWriteByte (UNI_KEYOFF); break; case 0x1b: /* retrig */ UniEffect (UNI_S3MEFFECTQ, inf); break; case 0x1c: /* tremor */ UniEffect (UNI_S3MEFFECTI, inf); break; case 0x1d: /* position jump */ UniPTEffect (0xb, inf); break; case 0x1e: /* pattern break */ UniPTEffect (0xd, (inf >> 4) * 10 + (inf & 0xf)); break; case 0x1f: /* set master volume */ if (inf <= 64) UniEffect (UNI_XMEFFECTG, inf); break; case 0x20: /* master volume slide */ UniEffect (UNI_XMEFFECTH, inf); break; case 0x21: /* extended effects */ switch (inf >> 4) { case 0x1: /* set filter */ case 0x5: /* vibrato waveform */ case 0x8: /* tremolo waveform */ UniPTEffect (0xe, inf - 0x10); break; case 0xa: /* pattern loop */ UniPTEffect (0xe, 0x60 | (inf & 0xf)); break; case 0xb: /* pattern delay */ UniPTEffect (0xe, 0xe0 | (inf & 0xf)); break; case 0x3: /* glissando */ case 0xc: /* note cut */ case 0xd: /* note delay */ case 0xf: /* invert loop */ UniPTEffect (0xe, inf); break; case 0xe: /* ignore envelope */ UniEffect (UNI_ITEFFECTS0, 0x77); /* vol */ UniEffect (UNI_ITEFFECTS0, 0x79); /* pan */ UniEffect (UNI_ITEFFECTS0, 0x7b); /* pit */ break; } break; /* 0x22 chorus (awe32) */ /* 0x23 reverb (awe32) */ }}static UBYTE *IMF_ConvertTrack (IMFNOTE * tr, UWORD rows){ int t; UBYTE note, ins; UniReset (); for (t = 0; t < rows; t++) { note = tr[t].note; ins = tr[t].ins; if ((ins) && (ins != 255)) UniInstrument (ins - 1); if (note != 255) { if (note == 0xa0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -