📄 load_imf.c
字号:
/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 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.2 2004/02/06 19:29:03 raph Exp $ Imago Orpheus (IMF) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <string.h>#include "mikmod_internals.h"#ifdef SUNOSextern int fprintf(FILE *, const char *, ...);#endif/*========== 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 */ UniEffect(UNI_XMEFFECT4,inf); break; case 0x06: /* vibrato + volslide */ UniEffect(UNI_XMEFFECT6,inf); 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>>2)); 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>>2)); 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<<1); 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) { UniPTEffect(0xc,0); /* Note cut */ if(tr[t].eff1==0x0c) tr[t].eff1=0; if(tr[t].eff2==0x0c) tr[t].eff2=0; } else UniNote(((note>>4)*OCTAVE)+(note&0xf));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -