load_xm.c
来自「SDL_mixer 是一个基于 SDL 的混音器」· C语言 代码 · 共 739 行 · 第 1/2 页
C
739 行
} for(v=0;v<of.numchn;v++) of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows); free(xmpat);xmpat=NULL; } else { for(v=0;v<of.numchn;v++) of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows); } } if(dummypat) { of.pattrows[t]=64; if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0; for(v=0;v<of.numchn;v++) of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64); free(xmpat);xmpat=NULL; } return 1;}static BOOL LoadInstruments(void){ int t,u; INSTRUMENT *d; ULONG next=0; UWORD wavcnt=0; if(!AllocInstruments()) return 0; d=of.instruments; for(t=0;t<of.numins;t++,d++) { XMINSTHEADER ih; long headend; memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD)); /* read instrument header */ headend = _mm_ftell(modreader); ih.size = _mm_read_I_ULONG(modreader); headend += ih.size; _mm_read_string(ih.name, 22, modreader); ih.type = _mm_read_UBYTE(modreader); ih.numsmp = _mm_read_I_UWORD(modreader); d->insname = DupStr(ih.name,22,1); if((SWORD)ih.size>29) { ih.ssize = _mm_read_I_ULONG(modreader); if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) { XMPATCHHEADER pth; int p; _mm_read_UBYTES (pth.what,XMNOTECNT,modreader); _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader); _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader); pth.volpts = _mm_read_UBYTE(modreader); pth.panpts = _mm_read_UBYTE(modreader); pth.volsus = _mm_read_UBYTE(modreader); pth.volbeg = _mm_read_UBYTE(modreader); pth.volend = _mm_read_UBYTE(modreader); pth.pansus = _mm_read_UBYTE(modreader); pth.panbeg = _mm_read_UBYTE(modreader); pth.panend = _mm_read_UBYTE(modreader); pth.volflg = _mm_read_UBYTE(modreader); pth.panflg = _mm_read_UBYTE(modreader); pth.vibflg = _mm_read_UBYTE(modreader); pth.vibsweep = _mm_read_UBYTE(modreader); pth.vibdepth = _mm_read_UBYTE(modreader); pth.vibrate = _mm_read_UBYTE(modreader); pth.volfade = _mm_read_I_UWORD(modreader); /* read the remainder of the header (2 bytes for 1.03, 22 for 1.04) */ for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader); /* we can't trust the envelope point count here, as some modules have incorrect values (K_OSPACE.XM reports 32 volume points, for example). */ if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2; if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2; if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) { if(nextwav) { free(nextwav);nextwav=NULL; } if(wh) { free(wh);wh=NULL; } _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } for(u=0;u<XMNOTECNT;u++) d->samplenumber[u]=pth.what[u]+of.numsmp; d->volfade = pth.volfade;memcpy(d->volenv,pth.volenv,XMENVCNT);if (pth.volflg&1) d->volflg|=EF_ON;if (pth.volflg&2) d->volflg|=EF_SUSTAIN;if (pth.volflg&4) d->volflg|=EF_LOOP;d->volsusbeg=d->volsusend=pth.volsus; d->volbeg=pth.volbeg;d->volend=pth.volend;d->volpts=pth.volpts;/* scale envelope */for (p=0;p<XMENVCNT/2;p++) d->volenv[p].val<<=2;if ((d->volflg&EF_ON)&&(d->volpts<2)) d->volflg&=~EF_ON;memcpy(d->panenv,pth.panenv,XMENVCNT);if (pth.panflg&1) d->panflg|=EF_ON;if (pth.panflg&2) d->panflg|=EF_SUSTAIN;if (pth.panflg&4) d->panflg|=EF_LOOP;d->pansusbeg=d->pansusend=pth.pansus; d->panbeg=pth.panbeg;d->panend=pth.panend;d->panpts=pth.panpts;/* scale envelope */for (p=0;p<XMENVCNT/2;p++) d->panenv[p].val<<=2;if ((d->panflg&EF_ON)&&(d->panpts<2)) d->panflg&=~EF_ON; /* Samples are stored outside the instrument struct now, so we have to load them all into a temp area, count the of.numsmp along the way and then do an AllocSamples() and move everything over */ if(mh->version>0x0103) next = 0; for(u=0;u<ih.numsmp;u++,s++) { /* Allocate more room for sample information if necessary */ if(of.numsmp+u==wavcnt) { wavcnt+=XM_SMPINCR; if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){ if(wh) { free(wh);wh=NULL; } _mm_errno = MMERR_OUT_OF_MEMORY; return 0; } if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) { free(nextwav);nextwav=NULL; _mm_errno = MMERR_OUT_OF_MEMORY; return 0; } s=wh+(wavcnt-XM_SMPINCR); } s->length =_mm_read_I_ULONG (modreader); s->loopstart =_mm_read_I_ULONG (modreader); s->looplength =_mm_read_I_ULONG (modreader); s->volume =_mm_read_UBYTE (modreader); s->finetune =_mm_read_SBYTE (modreader); s->type =_mm_read_UBYTE (modreader); s->panning =_mm_read_UBYTE (modreader); s->relnote =_mm_read_SBYTE (modreader); s->vibtype = pth.vibflg; s->vibsweep = pth.vibsweep; s->vibdepth = pth.vibdepth*4; s->vibrate = pth.vibrate; s->reserved =_mm_read_UBYTE (modreader); _mm_read_string(s->samplename, 22, modreader); nextwav[of.numsmp+u]=next; next+=s->length; if(_mm_eof(modreader)) { free(nextwav);free(wh); nextwav=NULL;wh=NULL; _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } } if(mh->version>0x0103) { for(u=0;u<ih.numsmp;u++) nextwav[of.numsmp++]+=_mm_ftell(modreader); _mm_fseek(modreader,next,SEEK_CUR); } else of.numsmp+=ih.numsmp; } else { /* read the remainder of the header */ for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader); if(_mm_eof(modreader)) { free(nextwav);free(wh); nextwav=NULL;wh=NULL; _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } } } } /* sanity check */ if(!of.numsmp) { if(nextwav) { free(nextwav);nextwav=NULL; } if(wh) { free(wh);wh=NULL; } _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } return 1;}BOOL XM_Load(BOOL curious){ INSTRUMENT *d; SAMPLE *q; int t,u; BOOL dummypat=0; char tracker[21],modtype[60]; /* try to read module header */ _mm_read_string(mh->id,17,modreader); _mm_read_string(mh->songname,21,modreader); _mm_read_string(mh->trackername,20,modreader); mh->version =_mm_read_I_UWORD(modreader); if((mh->version<0x102)||(mh->version>0x104)) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } mh->headersize =_mm_read_I_ULONG(modreader); mh->songlength =_mm_read_I_UWORD(modreader); mh->restart =_mm_read_I_UWORD(modreader); mh->numchn =_mm_read_I_UWORD(modreader); mh->numpat =_mm_read_I_UWORD(modreader); mh->numins =_mm_read_I_UWORD(modreader); mh->flags =_mm_read_I_UWORD(modreader); mh->tempo =_mm_read_I_UWORD(modreader); mh->bpm =_mm_read_I_UWORD(modreader); if(!mh->bpm) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } _mm_read_UBYTES(mh->orders,256,modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* set module variables */ of.initspeed = (UBYTE)mh->tempo; of.inittempo = (UBYTE)mh->bpm; strncpy(tracker,mh->trackername,20);tracker[20]=0; for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0; /* some modules have the tracker name empty */ if (!tracker[0]) strcpy(tracker,"Unknown tracker");#ifdef HAVE_SNPRINTF snprintf(modtype,60,"%s (XM format %d.%02d)", tracker,mh->version>>8,mh->version&0xff);#else sprintf(modtype,"%s (XM format %d.%02d)", tracker,mh->version>>8,mh->version&0xff);#endif of.modtype = strdup(modtype); of.numchn = mh->numchn; of.numpat = mh->numpat; of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */ of.songname = DupStr(mh->songname,20,1); of.numpos = mh->songlength; /* copy the songlength */ of.reppos = mh->restart<mh->songlength?mh->restart:0; of.numins = mh->numins; of.flags |= UF_XMPERIODS|UF_INST|UF_NOWRAP|UF_FT2QUIRKS; if(mh->flags&1) of.flags |= UF_LINEAR; memset(of.chanvol,64,of.numchn); /* store channel volumes */ if(!AllocPositions(of.numpos+1)) return 0; for(t=0;t<of.numpos;t++) of.positions[t]=mh->orders[t]; /* We have to check for any pattern numbers in the order list greater than the number of patterns total. If one or more is found, we set it equal to the pattern total and make a dummy pattern to workaround the problem */ for(t=0;t<of.numpos;t++) { if(of.positions[t]>=of.numpat) { of.positions[t]=of.numpat; dummypat=1; } } if(dummypat) { of.numpat++;of.numtrk+=of.numchn; } if(mh->version<0x0104) { if(!LoadInstruments()) return 0; if(!LoadPatterns(dummypat)) return 0; for(t=0;t<of.numsmp;t++) nextwav[t]+=_mm_ftell(modreader); } else { if(!LoadPatterns(dummypat)) return 0; if(!LoadInstruments()) return 0; } if(!AllocSamples()) { free(nextwav);free(wh); nextwav=NULL;wh=NULL; return 0; } q = of.samples; s = wh; for(u=0;u<of.numsmp;u++,q++,s++) { q->samplename = DupStr(s->samplename,22,1); q->length = s->length; q->loopstart = s->loopstart; q->loopend = s->loopstart+s->looplength; q->volume = s->volume; q->speed = s->finetune+128; q->panning = s->panning; q->seekpos = nextwav[u]; q->vibtype = s->vibtype; q->vibsweep = s->vibsweep; q->vibdepth = s->vibdepth; q->vibrate = s->vibrate; if(s->type & 0x10) { q->length >>= 1; q->loopstart >>= 1; q->loopend >>= 1; } q->flags|=SF_OWNPAN; if(s->type&0x3) q->flags|=SF_LOOP; if(s->type&0x2) q->flags|=SF_BIDI; if(s->type&0x10) q->flags|=SF_16BITS; q->flags|=SF_DELTA|SF_SIGNED; } d=of.instruments; s=wh; for(u=0;u<of.numins;u++,d++) for(t=0;t<XMNOTECNT;t++) { if (d->samplenumber[t]>=of.numsmp) d->samplenote[t]=255; else { int note=t+s[d->samplenumber[t]].relnote; d->samplenote[t]=(note<0)?0:note; } } free(wh);free(nextwav); wh=NULL;nextwav=NULL; return 1;}CHAR *XM_LoadTitle(void){ CHAR s[21]; _mm_fseek(modreader,17,SEEK_SET); if(!_mm_read_UBYTES(s,21,modreader)) return NULL; return(DupStr(s,21,1));}/*========== Loader information */MIKMODAPI MLOADER load_xm={ NULL, "XM", "XM (FastTracker 2)", XM_Init, XM_Test, XM_Load, XM_Cleanup, XM_LoadTitle};/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?