📄 mlutil.c
字号:
/* MikMod sound library (c) 1998, 1999, 2000, 2001 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: mlutil.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $ Utility functions for the module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <string.h>#include "mikmod_internals.h"#ifdef SUNOSextern int fprintf(FILE *, const char *, ...);#endif/*========== Shared tracker identifiers */CHAR *STM_Signatures[STM_NTRACKERS] = { "!Scream!", "BMOD2STM", "WUZAMOD!"};CHAR *STM_Version[STM_NTRACKERS] = { "Screamtracker 2", "Converted by MOD2STM (STM format)", "Wuzamod (STM format)"};/*========== Shared loader variables */SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */UBYTE* poslookup=NULL; /* lookup table for pattern jumps after blank pattern removal */UBYTE poslookupcnt;UWORD* origpositions=NULL;BOOL filters; /* resonant filters in use */UBYTE activemacro; /* active midi macro number for Sxx,xx<80h */UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings *//*========== Linear periods stuff */int* noteindex=NULL; /* remap value for linear period modules */static int noteindexcount=0;int *AllocLinear(void){ if(of.numsmp>noteindexcount) { noteindexcount=of.numsmp; noteindex=realloc(noteindex,noteindexcount*sizeof(int)); } return noteindex;}void FreeLinear(void){ if(noteindex) { free(noteindex); noteindex=NULL; } noteindexcount=0;}int speed_to_finetune(ULONG speed,int sample){ int ctmp=0,tmp,note=1,finetune=0; speed>>=1; while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) { ctmp=tmp; note++; } if(tmp!=speed) { if((tmp-speed)<(speed-ctmp)) while(tmp>speed) tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune)); else { note--; while(ctmp<speed) ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++finetune)); } } noteindex[sample]=note-4*OCTAVE; return finetune;}/*========== Order stuff *//* handles S3M and IT orders */void S3MIT_CreateOrders(BOOL curious){ int t; of.numpos = 0; memset(of.positions,0,poslookupcnt*sizeof(UWORD)); memset(poslookup,-1,256); for(t=0;t<poslookupcnt;t++) { int order=origpositions[t]; if(order==255) order=LAST_PATTERN; of.positions[of.numpos]=order; poslookup[t]=of.numpos; /* bug fix for freaky S3Ms / ITs */ if(origpositions[t]<254) of.numpos++; else /* end of song special order */ if((order==LAST_PATTERN)&&(!(curious--))) break; }}/*========== Effect stuff *//* handles S3M and IT effects */void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags){ UBYTE hi,lo; lo=inf&0xf; hi=inf>>4; /* process S3M / IT specific command structure */ if(cmd!=255) { switch(cmd) { case 1: /* Axx set speed to xx */ UniEffect(UNI_S3MEFFECTA,inf); break; case 2: /* Bxx position jump */ if (inf<poslookupcnt) { /* switch to curious mode if necessary, for example sympex.it, deep joy.it */ if(((SBYTE)poslookup[inf]<0)&&(origpositions[inf]!=255)) S3MIT_CreateOrders(1); if(!((SBYTE)poslookup[inf]<0)) UniPTEffect(0xb,poslookup[inf]); } break; case 3: /* Cxx patternbreak to row xx */ if ((flags & S3MIT_OLDSTYLE) && !(flags & S3MIT_IT)) UniPTEffect(0xd,(inf>>4)*10+(inf&0xf)); else UniPTEffect(0xd,inf); break; case 4: /* Dxy volumeslide */ UniEffect(UNI_S3MEFFECTD,inf); break; case 5: /* Exy toneslide down */ UniEffect(UNI_S3MEFFECTE,inf); break; case 6: /* Fxy toneslide up */ UniEffect(UNI_S3MEFFECTF,inf); break; case 7: /* Gxx Tone portamento, speed xx */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x3,inf); else UniEffect(UNI_ITEFFECTG,inf); break; case 8: /* Hxy vibrato */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x4,inf); else UniEffect(UNI_ITEFFECTH,inf); break; case 9: /* Ixy tremor, ontime x, offtime y */ if (flags & S3MIT_OLDSTYLE) UniEffect(UNI_S3MEFFECTI,inf); else UniEffect(UNI_ITEFFECTI,inf); break; case 0xa: /* Jxy arpeggio */ UniPTEffect(0x0,inf); break; case 0xb: /* Kxy Dual command H00 & Dxy */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x4,0); else UniEffect(UNI_ITEFFECTH,0); UniEffect(UNI_S3MEFFECTD,inf); break; case 0xc: /* Lxy Dual command G00 & Dxy */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x3,0); else UniEffect(UNI_ITEFFECTG,0); UniEffect(UNI_S3MEFFECTD,inf); break; case 0xd: /* Mxx Set Channel Volume */ UniEffect(UNI_ITEFFECTM,inf); break; case 0xe: /* Nxy Slide Channel Volume */ UniEffect(UNI_ITEFFECTN,inf); break; case 0xf: /* Oxx set sampleoffset xx00h */ UniPTEffect(0x9,inf); break; case 0x10: /* Pxy Slide Panning Commands */ UniEffect(UNI_ITEFFECTP,inf); break; case 0x11: /* Qxy Retrig (+volumeslide) */ UniWriteByte(UNI_S3MEFFECTQ); if(inf && !lo && !(flags & S3MIT_OLDSTYLE)) UniWriteByte(1); else UniWriteByte(inf); break; case 0x12: /* Rxy tremolo speed x, depth y */ UniEffect(UNI_S3MEFFECTR,inf); break; case 0x13: /* Sxx special commands */ if (inf>=0xf0) { /* change resonant filter settings if necessary */ if((filters)&&((inf&0xf)!=activemacro)) { activemacro=inf&0xf; for(inf=0;inf<0x80;inf++) filtersettings[inf].filter=filtermacros[activemacro]; } } else { /* Scream Tracker does not have samples larger than 64 Kb, thus doesn't need the SAx effect */ if ((flags & S3MIT_SCREAM) && ((inf & 0xf0) == 0xa0)) break; UniEffect(UNI_ITEFFECTS0,inf); } break; case 0x14: /* Txx tempo */ if(inf>=0x20) UniEffect(UNI_S3MEFFECTT,inf); else { if(!(flags & S3MIT_OLDSTYLE)) /* IT Tempo slide */ UniEffect(UNI_ITEFFECTT,inf); } break; case 0x15: /* Uxy Fine Vibrato speed x, depth y */ if(flags & S3MIT_OLDSTYLE) UniEffect(UNI_S3MEFFECTU,inf); else UniEffect(UNI_ITEFFECTU,inf); break; case 0x16: /* Vxx Set Global Volume */ UniEffect(UNI_XMEFFECTG,inf); break; case 0x17: /* Wxy Global Volume Slide */ UniEffect(UNI_ITEFFECTW,inf); break; case 0x18: /* Xxx amiga command 8xx */ if(flags & S3MIT_OLDSTYLE) { if(inf>128) UniEffect(UNI_ITEFFECTS0,0x91); /* surround */ else UniPTEffect(0x8,(inf==128)?255:(inf<<1)); } else UniPTEffect(0x8,inf); break; case 0x19: /* Yxy Panbrello speed x, depth y */ UniEffect(UNI_ITEFFECTY,inf); break; case 0x1a: /* Zxx midi/resonant filters */ if(filtersettings[inf].filter) { UniWriteByte(UNI_ITEFFECTZ); UniWriteByte(filtersettings[inf].filter); UniWriteByte(filtersettings[inf].inf); } break; } }}/*========== Unitrk stuff *//* Generic effect writing routine */void UniEffect(UWORD eff,UWORD dat){ if((!eff)||(eff>=UNI_LAST)) return; UniWriteByte(eff); if(unioperands[eff]==2) UniWriteWord(dat); else UniWriteByte(dat);}/* Appends UNI_PTEFFECTX opcode to the unitrk stream. */void UniPTEffect(UBYTE eff, UBYTE dat){#ifdef MIKMOD_DEBUG if (eff>=0x10) fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff); else#endif if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat);}/* Appends UNI_VOLEFFECT + effect/dat to unistream. */void UniVolEffect(UWORD eff,UBYTE dat){ if((eff)||(dat)) { /* don't write empty effect */ UniWriteByte(UNI_VOLEFFECTS); UniWriteByte(eff);UniWriteByte(dat); }}/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -