MOD-Player [C++, RealMode]
SBOUT.H
int InitBlaster (int,int,int); void DeinitBlaster (void); void SetBlasterRate (unsigned int); void PlayBlaster (long,unsigned int); void StopBlaster (void); void SetBlasterHandler (void far*);
MOD.H
typedef struct Module
{unsigned int ChannelNumber;
unsigned int PatternsToPlay;
unsigned char PatternArragement[128];
unsigned char *PatternData[128];
unsigned char *SampleData[31];
unsigned int SampleLength[31];
unsigned int SampleLoopStart[31];
unsigned int SampleLoopLength[31];
unsigned char SampleVolume[31];
int sampleFineTune[31];
};
typedef struct MODsample
{char Name[22];
unsigned int Length;
unsigned char Finetune;
unsigned char Volume;
unsigned int LoopStart;
unsigned int LoopLength;
};
typedef struct MODheader
{char Name[20];
MODsample Samples[31];
unsigned char OrderLen;
unsigned char Dummy;
unsigned char Order[128];
unsigned long Sign;
};
unsigned int xchg( unsigned int data)
{return ((data>8));
}
unsigned int freqTable[296]=
{907, 900, 894, 887, 881, 875, 868, 862, 856,
850, 844, 838, 832, 826, 820, 814, 808,
802, 796, 791, 785, 779, 774, 768, 762,
757, 752, 746, 741, 736, 730, 725, 720,
715, 709, 704, 699, 694, 689, 684, 678,
675, 670, 665, 660, 655, 651, 646, 640,
636, 632, 628, 623, 619, 614, 610, 604,
601, 597, 592, 588, 584, 580, 575, 570,
567, 563, 559, 555, 551, 547, 543, 538,
535, 532, 528, 524, 520, 516, 513, 508,
505, 502, 498, 494, 491, 487, 484, 480,
477, 474, 470, 467, 463, 460, 457, 453,
450, 447, 444, 441, 437, 434, 431, 428,
425, 422, 419, 416, 413, 410, 407, 404,
401, 398, 395, 392, 390, 387, 384, 381,
379, 376, 373, 370, 368, 365, 363, 360,
357, 355, 352, 350, 347, 345, 342, 339,
337, 335, 332, 330, 328, 325, 323, 320,
318, 316, 314, 312, 309, 307, 305, 302,
300, 298, 296, 294, 292, 290, 288, 285,
284, 282, 280, 278, 276, 274, 272, 269,
268, 266, 264, 262, 260, 258, 256, 254,
253, 251, 249, 247, 245, 244, 242, 240,
238, 237, 235, 233, 232, 230, 228, 226,
225, 223, 222, 220, 219, 217, 216, 214,
212, 211, 209, 208, 206, 205, 203, 202,
200, 199, 198, 196, 195, 193, 192, 190,
189, 188, 187, 185, 184, 183, 181, 180,
179, 177, 176, 175, 174, 172, 171, 170,
169, 167, 166, 165, 164, 163, 161, 160,
159, 158, 157, 156, 155, 154, 152, 151,
150, 149, 148, 147, 146, 145, 144, 143,
142, 141, 140, 139, 138, 137, 136, 135,
134, 133, 132, 131, 130, 129, 128, 127,
126, 125, 125, 123, 123, 122, 121, 120,
119, 118, 118, 117, 116, 115, 114, 113,
113, 112, 111, 110, 109, 109, 108
};
int sineTable[32]=
{ 0, 24, 49, 74, 97, 120, 141, 161,
180, 197, 212, 224, 235, 244, 250, 253,
255, 253, 250, 244, 235, 224, 212, 197,
180, 161, 141, 120, 97, 74, 49, 24
};
SB_LO.CPP
#includeint sb_base_port; int sb_irq_num; int sb_dma_chan; int dma_maskport; int dma_clrport; int dma_modeport; int dma_addrport; int dma_pageport; int dma_countport; //unsigned char dma_page; //unsigned int dma_offset; //unsigned int dma_size; void (*user_handler) (void); void interrupt (*oldvector)(...); void dsp_write (unsigned char value) { while (inportb(sb_base_port+0xC)&0x80); outportb(sb_base_port+0xC,value); } unsigned char dsp_read (void) { while (!(inportb(sb_base_port+0xE)&0x80)); return (inportb(sb_base_port+0xA)); } int dsp_reset (void) { int i; outportb(sb_base_port+6,1); outportb(sb_base_port+6,0); i=100; while ((dsp_read()!=0xAA)&&i--); return i; } void interrupt sb_handler (...) { //dsp_read (); user_handler (); inportb(sb_base_port+0xE); outportb (0x20,0x20); } int InitBlaster (int sb_port,int sb_irq,int sb_dma) { sb_base_port=sb_port; sb_irq_num=sb_irq; sb_dma_chan=sb_dma; dma_maskport=0xA; dma_clrport=0xC; dma_modeport=0xB; dma_addrport=sb_dma_chan*2; dma_countport=sb_dma_chan*2+1; switch (sb_dma_chan) { case 0:dma_pageport=0x87;break; case 1:dma_pageport=0x83;break; case 3:dma_pageport=0x82;break; } if (dsp_reset()) { oldvector=getvect(sb_irq_num+8); setvect(sb_irq_num+8,sb_handler); outportb(0x21,inportb(0x21)&~(1>8)&0xFF)); outportb (dma_pageport,((addr>>16)&0xFF)); outportb (dma_countport,((size)&0xFF)); outportb (dma_countport,(((size)>>8)&0xFF)); outportb (dma_maskport,1); dsp_write (0x14); dsp_write ((size&0xFF)); dsp_write (((size>>8)&0xFF)); //dsp_write (0x48); //dsp_write ((size&0xFF)); //dsp_write (((size>>8)&0xFF)); //dsp_write (0x1C); } void StopBlaster (void) { dsp_write (0xDA); }
MODPLAY.CPP
#include#include #include #include #include "mod.h" #include "sbout.h" //#pragma inline .386 #define MOD_4CH 0x2E4B2E4D #define MOD_6CH 0x4E484336 #define MOD_8CH 0x4E484338 #define CH_active 0x0001 #define CH_looped 0x0002 #define NONE 0xFF #define ARPEGGIO 0x00 #define PORTA_UP 0x01 #define PORTA_DOWN 0x02 #define PORTA_TO_NOTE 0x03 #define CUT_NOTE 0x04 #define VOLUME_SLIDE 0x05 #define VIBRATO 0x06 #define PORTA_VOLUME_SLIDE 0x07 #define VIBRATO_VOLUME_SLIDE 0x08 #define TREMOLO 0x09 #define RETRIG_NOTE 0x0A #define mixBuffSize 0x80 #define mixFreq 44100 typedef struct channelInfo {unsigned char sample; unsigned char *sampleData; int sampleVolume; unsigned long sampleLength; unsigned long sampleLoopStart; unsigned long sampleLoopLength; unsigned long samplePosition; unsigned long sampleIncrement; unsigned int sampleNote; unsigned int sampleFreq; unsigned int flags; int effect; int effectCounter; int effectParam; unsigned int portaSpeed; unsigned int freqToPortaTo; unsigned int vibratoSpeed; unsigned int vibratoDepth; unsigned int vibratoNegative; unsigned int vibratoIndex; unsigned int tremoloSpeed; unsigned int tremoloDepth; unsigned int tremoloNegative; unsigned int tremoloIndex; }; channelInfo ci[8]; unsigned int channels; unsigned char bpm; unsigned char tempo; unsigned int mixRate; unsigned int speed; unsigned long magic; unsigned int currientRow; unsigned int currientPattern; unsigned int tickCount; unsigned int oneTick; unsigned int needToJump; unsigned int rowToJumpTo; unsigned int patternToJumpTo; int volumeTable[65][256]; unsigned char outputTable[2048]; unsigned int startOutput; unsigned char *mixBuff[2]; unsigned long mixBuffAddr[2]; unsigned char flipFlag; Module *mod; Module *MODloadModule( char *name) {Module *mod; FILE *in; MODheader header; int i,j,r,d,totalch; unsigned char *note; unsigned int sampleNum,periodFreq,effectNum,effectParam,temp; if ((mod=new Module)==NULL) return 0; if ((in=fopen( name, "rb"))==NULL) return 0; if ((fread( &header, 1, sizeof(header), in))!=sizeof( header)) return 0; if (header.Sign==MOD_4CH) mod->ChannelNumber=totalch=4; else if (header.Sign==MOD_6CH) mod->ChannelNumber=totalch=6; else if (header.Sign==MOD_8CH) mod->ChannelNumber=totalch=8; else return 0; mod->PatternsToPlay=header.OrderLen; for (i=0;iSampleLength[i]=xchg( header.Samples[i].Length)*2; mod->SampleLoopStart[i]=xchg( header.Samples[i].LoopStart)*2; mod->SampleLoopLength[i]=xchg( header.Samples[i].LoopLength)*2; mod->SampleVolume[i]=header.Samples[i].Volume; mod->sampleFineTune[i]=header.Samples[i].Finetune; if (mod->sampleFineTune[i]>7) mod->sampleFineTune[i]-=16; } for (i=j=0;iPatternArragement[i]=header.Order[i]; if (header.Order[i]>j) j=header.Order[i]; } j++; for (i=0;i PatternData[i]=new unsigned char[64*4*totalch]; fread( mod->PatternData[i], 1, 64*4*totalch, in); } for (i=0;i PatternData[i]; for (r=0;r>4); periodFreq=(((unsigned int)note[0]&0x0F)freqTable[d*8]-2)&&(periodFreq =freqTable[d*8]) {temp=d*8; break; } } */ periodFreq=temp; note[0]=sampleNum; note[1]=(effectNum>8); note[2]=periodFreq&0xFF; note[3]=effectParam; } } for (i=0;iSampleLength[i]) {mod->SampleData[i]=new unsigned char[mod->SampleLength[i]]; fread( mod->SampleData[i], 1, mod->SampleLength[i], in); for (j=0;j SampleLength[i];j++) mod->SampleData[i][j]^=0x80; if (mod->SampleLoopLength[i]>2) {if (mod->SampleLoopStart[i]+mod->SampleLoopLength[i] > mod->SampleLength[i]) {if (mod->SampleLoopLength[i] > mod->SampleLength[i]) {mod->SampleLoopLength[i]=mod->SampleLength[i]-3; mod->SampleLoopStart[i]=3; } else {mod->SampleLoopStart[i]-=mod->SampleLoopLength[i]+mod->SampleLoopStart[i]-mod->SampleLength[i]; } } } } } fclose( in); return mod; } void MODinit( unsigned int freq, unsigned int ch) {int i,j; bpm=125; tempo=6; mixRate=freq; speed=(double)mixRate/(((24.0*bpm)/tempo)/60.0); oneTick=speed/tempo; magic=(3579545.25/(double)mixRate)*65536.0; currientRow=0; currientPattern=0; needToJump=0; tickCount=1; startOutput=ch*128; channels=ch; for (i=0;i effectParam>>4); y=(ch->effectParam&0xF); switch (ch->effect) {case ARPEGGIO: if (ch->effectCounter==1) ch->sampleFreq=freqTable[ch->sampleNote+(x*8)+mod->sampleFineTune[ch->sample]]; else if (ch->effectCounter==2) ch->sampleFreq=freqTable[ch->sampleNote+(y*8)+mod->sampleFineTune[ch->sample]]; else ch->sampleFreq=freqTable[ch->sampleNote+mod->sampleFineTune[ch->sample]]; if (ch->sampleFreq!=0) ch->sampleIncrement=magic/ch->sampleFreq; ch->effectCounter++; if (ch->effectCounter>2) ch->effectCounter=0; break; case PORTA_UP: if (ch->effectCounter) ch->effectCounter--; else {ch->sampleFreq-=ch->effectParam; if (ch->sampleFreqsampleFreq=113; ch->sampleIncrement=magic/ch->sampleFreq; } break; case PORTA_DOWN: if (ch->effectCounter) ch->effectCounter--; else {ch->sampleFreq+=ch->effectParam; if (ch->sampleFreq>856) ch->sampleFreq=856; ch->sampleIncrement=magic/ch->sampleFreq; } break; case PORTA_TO_NOTE: case PORTA_VOLUME_SLIDE: if (ch->sampleFreq freqToPortaTo) {ch->sampleFreq+=ch->portaSpeed; if (ch->sampleFreq>ch->freqToPortaTo) ch->sampleFreq=ch->freqToPortaTo; } else if (ch->sampleFreq>ch->freqToPortaTo) {ch->sampleFreq-=ch->portaSpeed; if (ch->sampleFreq freqToPortaTo) ch->sampleFreq=ch->freqToPortaTo; } ch->sampleIncrement=magic/ch->sampleFreq; if (ch->effect==PORTA_VOLUME_SLIDE) goto doVolume; break; case VIBRATO: case VIBRATO_VOLUME_SLIDE: t=(ch->vibratoDepth*sineTable[ch->vibratoIndex])>>7; if (ch->vibratoNegative) ch->sampleFreq+=t; else ch->sampleFreq-=t; ch->sampleIncrement=magic/ch->sampleFreq; ch->vibratoIndex+=ch->vibratoSpeed; if (ch->vibratoIndex>31) {ch->vibratoIndex-=32; ch->vibratoNegative^=1; } if (ch->effect==VIBRATO_VOLUME_SLIDE) goto doVolume; break; case TREMOLO: t=(ch->tremoloDepth*sineTable[ch->tremoloIndex])>>6; if (ch->tremoloNegative) {ch->sampleVolume-=t; if (ch->sampleVolumesampleVolume=0; } else {ch->sampleVolume+=t; if (ch->sampleVolume>0x40) ch->sampleVolume=0x40; } ch->tremoloIndex+=ch->tremoloSpeed; if (ch->tremoloIndex>31) {ch->tremoloIndex-=32; ch->tremoloNegative^=1; } break; case VOLUME_SLIDE: doVolume: if (ch->effectCounter) ch->effectCounter--; else {ch->sampleVolume=ch->sampleVolume+x-y; if (ch->sampleVolumesampleVolume=0; else if (ch->sampleVolume>64) ch->sampleVolume=64; } break; } } } void UpdateRow( void) {int sample,note,effectNum,effectParam; int i; unsigned char *noteptr; unsigned int temp; channelInfo *ch; /*if (needToJump) {if (needToJump==1) {currientPattern=patternToJumpTo; } if (needToJump==2) {currientPattern=patternToJumpTo; currientRow=rowToJumpTo; } needToJump=0; }*/ noteptr=(unsigned char*)(mod->PatternData[mod->PatternArragement[currientPattern]]+ currientRow*4*channels); needToJump=0; for (i=0,ch=ci;i >4); note=(((unsigned int)(noteptr[1]&0x0F))effectParam=noteptr[3]; if ((sample)&&(effectNum!=3)&&(effectNum!=5)) {ch->effect=NONE; ch->flags=0; sample--; ch->sample=sample; ch->sampleData=mod->SampleData[sample]; ch->sampleLength=((unsigned long)mod->SampleLength[sample]samplePosition=0; ch->sampleVolume=mod->SampleVolume[sample]; if (mod->SampleLoopLength[sample]>2) {ch->flags|=CH_looped; ch->sampleLoopStart=((unsigned long)mod->SampleLoopStart[sample]sampleLoopLength=((unsigned long)mod->SampleLoopLength[sample]flags|=CH_active; } if ((note!=0x0FFF)&&(effectNum!=3)&&(effectNum!=5)) {ch->effect=NONE; ch->sampleNote=note; ch->sampleFreq=freqTable[mod->sampleFineTune[ch->sample]+note]; ch->sampleIncrement=magic/ch->sampleFreq; ch->vibratoNegative=0; ch->vibratoIndex=0; ch->tremoloNegative=0; ch->tremoloIndex=0; ch->flags|=CH_active; } switch (effectNum) {case 0x00: //arpeggio if ((ch->effect==NONE)&&(ch->effectParam!=0)) {ch->effect=ARPEGGIO; ch->effectCounter=0; } break; case 0x01: //porta up ch->effect=PORTA_UP; ch->effectCounter=1; break; case 0x02: //porta down ch->effect=PORTA_DOWN; ch->effectCounter=1; break; case 0x03: //porta_to_note ch->effect=PORTA_TO_NOTE; if (ch->effectParam) ch->portaSpeed=ch->effectParam; if (note!=0x0FFF) ch->freqToPortaTo=freqTable[mod->sampleFineTune[ch->sample]+note]; break; case 0x04: //vibrato ch->effect=VIBRATO; if (ch->effectParam) {ch->vibratoSpeed=(ch->effectParam>>4); ch->vibratoDepth=(ch->effectParam&0x0F); } break; case 0x05: //porta + volume slide ch->effect=PORTA_VOLUME_SLIDE; break; case 0x06: ch->effect=VIBRATO_VOLUME_SLIDE; break; case 0x07: ch->effect=TREMOLO; if (ch->effectParam) {ch->tremoloSpeed=(ch->effectParam>>4); ch->tremoloDepth=(ch->effectParam&0x0F); } break; case 0x09: //sample offset ch->samplePosition=((unsigned long)ch->effectParameffect=VOLUME_SLIDE; ch->effectCounter=1; break; case 0x0B: //needToJump=1; //patternToJumpTo=ch->effectParam; currientRow=63; currientPattern=ch->effectParam-1; break; case 0xC: ch->sampleVolume=(ch->effectParam>64)?64:ch->effectParam; break; case 0xD: /*if (needToJump!=1) patternToJumpTo=currientPattern+1; needToJump=2; temp=((ch->effectParam>>4)*10)+(ch->effectParam&0x0F); rowToJumpTo=(tempeffectParam>>4)*10)+(ch->effectParam&0x0F)-1; currientPattern++; } break; case 0xE: switch (ch->effectParam>>4) {case 0x01: ch->sampleFreq-=(ch->effectParam&0x0F); ch->sampleIncrement=magic/ch->sampleFreq; break; case 0x02: ch->sampleFreq+=(ch->effectParam&0x0F); ch->sampleIncrement=magic/ch->sampleFreq; break; case 0x05: mod->sampleFineTune[sample]=ch->effectParam&0x0F; if (mod->sampleFineTune[sample]>7) mod->sampleFineTune[sample]-=16; break; case 0xA: ch->sampleVolume+=(ch->effectParam&0x0F); if (ch->sampleVolume>0x40) ch->sampleVolume=0x40; break; case 0xB: ch->sampleVolume-=(ch->effectParam&0x0F); if (ch->sampleVolumesampleVolume=0; break; } break; case 0xF: if (ch->effectParameffectParam; else bpm=ch->effectParam; speed=(double)mixRate/(((24.0*bpm)/tempo)/60.0); oneTick=speed/tempo; break; default: ch->effect=NONE; break; } } currientRow++; if (currientRow==64) {currientRow=0; currientPattern++; if (currientPattern>mod->PatternsToPlay) currientPattern=0; } } /*void UpdateNoLoop( Channel *ch) {asm push es asm push di asm push eax asm push ebx asm push ecx asm les di,[bp+6] asm mov eax,dword ptr es:[di+16] asm mov ecx,dword ptr es:[di+20] asm add eax,ecx asm mov ebx,dword ptr es:[di+4] asm cmp eax,ebx asm jb l1: asm mov word ptr es:[di+23],0 asm jmp l2: l1: asm add dword ptr es:[di+16],ecx l2: asm pop ecx asm pop ebx asm pop eax asm pop di asm pop es } void UpdateLooped( Channel *ch) {asm push es asm push di asm push eax asm push ebx asm push ecx asm les di,[bp+6] asm mov eax,dword ptr es:[di+16] asm mov ecx,dword ptr es:[di+20] asm add eax,ecx asm mov ebx,dword ptr es:[di+8] asm add ebx,dword ptr es:[di+12] asm cmp eax,ebx asm jb looped1 asm mov ecx,dword ptr es:[di+8] asm mov dword ptr es:[di+16],ecx asm jmp looped2 looped1: asm add dword ptr es:[di+16],ecx looped2: asm pop ecx asm pop ebx asm pop eax asm pop di asm pop es } */ void Mix8bitMono( int MixLength, char *buffer) {channelInfo *chptr; int MixCount; int i,j; int output; MixCount=MixLength; while (MixCount) {chptr=ci; output=startOutput; oneTick--; if (oneTick==0) {BitTrack(); oneTick=speed/tempo; } tickCount--; if (tickCount==0) {UpdateRow(); tickCount=speed; } for (i=0;i flags&CH_active) {output+=volumeTable[chptr->sampleVolume][chptr->sampleData[(chptr->samplePosition>>16)]]; if (chptr->flags&CH_looped) {if ((chptr->samplePosition+chptr->sampleIncrement) sampleLoopStart+chptr->sampleLoopLength)) {chptr->samplePosition+=chptr->sampleIncrement; } else {chptr->samplePosition=chptr->sampleLoopStart; } //UpdateLooped( chptr); } else {if ((chptr->samplePosition+chptr->sampleIncrement) sampleLength) {chptr->samplePosition+=chptr->sampleIncrement; } else {chptr->flags=0; } //UpdateNoLoop( chptr); } } } *(buffer++)=outputTable[output]; MixCount--; } } void MyHandler( void) {PlayBlaster( mixBuffAddr[!flipFlag], mixBuffSize); //MixBuffer(MixBuf[!flag],MixBuffSize); flipFlag=!flipFlag; } void main (int,char *argv[]) { int i; if ((mod=MODloadModule( argv[1]))==0) return; MODinit( mixFreq, mod->ChannelNumber); InitBlaster( 0x220, 5, 1); SetBlasterRate( mixFreq); SetBlasterHandler( (void far*)MyHandler); mixBuff[0]=new unsigned char[mixBuffSize]; mixBuff[1]=new unsigned char[mixBuffSize]; mixBuffAddr[0]=FP_SEG( mixBuff[0])*16L+FP_OFF( mixBuff[0]); mixBuffAddr[1]=FP_SEG( mixBuff[1])*16L+FP_OFF( mixBuff[1]); Mix8bitMono( mixBuffSize, mixBuff[0]); Mix8bitMono( mixBuffSize, mixBuff[1]); flipFlag=i=0; PlayBlaster( mixBuffAddr[0], mixBuffSize); while (!kbhit()) {if (i!=flipFlag) {Mix8bitMono( mixBuffSize, mixBuff[i]); i=flipFlag; } } getch(); StopBlaster(); DeinitBlaster(); }
Оставить комментарий
Оставлять комментарии могут только зарегистрированные пользователи.
Если вы не являетесь зарегистрированным пользователем, то вам необходимо зарегистрироваться. Регистрация бесплатна. Если вы уже зарегистрированы на CodeNet, то вам необходимо ввести логин и пароль в верхней (Alt-U) части страницы.
