0 Sound-Blaster für C (das war die Quelle!!!) Der Zauberleerling Listings #define STEREO #define OPL3 #include #include #include #include #include #define KEYON 0x20 /* These are offsets from the base I/O address. */ #define FM 8 #define PROFM1 0 #define PROFM2 2 #ifdef OPL3 #define LEFT 0x10 #define RIGHT 0x20 #endif unsigned IOport; void mydelay(unsigned long clocks) { unsigned long elapsed=0; unsigned int last,next,ncopy,diff; outp(0x43,0); last=inp(0x40); last=~((inp(0x40)<< 8) + last); do { outp(0x43,0); next=inp(0x40); ncopy=next=~((inp(0x40)<< 8) + next); next-=last; elapsed += next; last=ncopy; } while (elapsed= '0' && c <= '9') digit = c - '0'; else if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; else return 1; *val = *val * 16 + digit; (*str)++; } return 0; } int base10(char **str, unsigned *val) { char c; int digit; *val = 0; while ( **str != ' ') { c = toupper(**str); if (c >= '0' && c <= '9') digit = c - '0'; else return 1; *val = *val * 10 + digit; (*str)++; } return 0; } unsigned ReadBlasterEnv(unsigned *port, unsigned *irq, unsigned *dma8, unsigned *dma16) /* Meldet: * 0 erfolgreich * 1 Adress-Port-Lesefehler. * 2 IRQ-Nummer-Lesefehler. * 3 8-bit DMA Channel-Lesefehler. * 4 16-bit DMA Channel-Lesefehler. */ { char *env; unsigned val; int digit; env = getenv("BLASTER"); while (*env) { switch(toupper( *(env++) )) { case 'A': if (base16(&env, port)) return 1; break; case 'I': if (base10(&env, irq)) return 2; break; case 'D': if (base10(&env, dma8)) return 3; break; case 'H': if (base10(&env, dma16)) return 4; break; default: break; } } return 0; } void FMoutput(unsigned port, int reg, int val) { outp(port, reg); mydelay(8); outp(port+1, val); mydelay(55); } void fm(int reg, int val) { FMoutput(IOport+FM, reg, val); } void Profm1(int reg, int val) { FMoutput(IOport+PROFM1, reg, val); } void Profm2(int reg, int val) { FMoutput(IOport+PROFM2, reg, val); } void main(void) { int i,val1,val2; int block,b,m,f,fn; unsigned dummy; clrscr(); ReadBlasterEnv(&IOport, &dummy, &dummy, &dummy); #ifdef STEREO #ifdef OPL3 printf("Program compiled for Sound Blaster Pro ver. 2 (CT-1600) and SB16 cards.\n"); #else printf("Program compiled for Sound Blaster Pro ver. 1 (CT-1330) cards.\n"); #endif #else printf("Program compiled for Sound Blaster 1.0 - 2.0 cards (monaural).\n"); #endif fm(1,0); #ifdef OPL3 Profm2(5, 1); fm(0xC0,LEFT | RIGHT | 1); #else fm(0xC0, 1); #endif fm(0x23,0x21); /* no amplitude modulation (D7=0), no vibrato (D6=0), * sustained envelope type (D5=1), KSR=0 (D4=0), * frequency multiplier=1 (D4-D0=1) */ fm(0x43,0x0); /* no volume decrease with pitch (D7-D6=0), * no attenuation (D5-D0=0) */ fm(0x63,0xff); /* fast attack (D7-D4=0xF) and decay (D3-D0=0xF) */ fm(0x83,0x05); /* high sustain level (D7-D4=0), slow release rate (D3-D0=5) */ /***************************************** * Set parameters for the modulator cell * *****************************************/ fm(0x20,0x20); /* sustained envelope type, frequency multiplier=0 */ fm(0x40,0x3f); /* maximum attenuation, no volume decrease with pitch */ /* Since the modulator signal is attenuated as much as possible, these * next two values shouldn't have any effect. */ fm(0x60,0x44); /* slow attack and decay */ fm(0x80,0x05); /* high sustain level, slow release rate */ /*********************************************** ** * Generate tone from values looked up in table. * ************************************************ */ printf("440 Hz tone, values looked up in table.\n"); fm(0xa0,0x41); /* 440 Hz */ fm(0xb0,0x32); /* 440 Hz, block 0, key on */ getche(); fm(0xb0,0x12); /* key off */ /****************************************** * Generate tone from a calculated value. * ******************************************/ printf("440 Hz tone, values calculated.\n"); block=4; /* choose block=4 and m=1 */ m=1; /* m is the frequency multiple number */ f=440; /* want f=440 Hz */ b= 1 << block; /* This is the equation to calculate frequency number from frequency. */ fn=(long)f * 1048576 / b / m /50000L; fm(0x23,0x20 | (m & 0xF)); /* 0x20 sets sustained envelope, low nibble * is multiple number */ fm(0xA0,(fn & 0xFF)); fm(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); getche(); /*********************************************** ********** * Generate a range of octaves by changing block number. * ************************************************ *********/ printf("Range of frequencies created by changing block number.\n"); for (block=0; block<=7; block++) { printf("f=%5ld Hz (press Enter)\n",(long)440*(1 << block)/16); fm(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); getche(); } /*********************************************** ****************** * Generate a range of frequencies by changing frequency number. * ************************************************ *****************/ printf("Range of frequencies created by changing frequency number.\n"); block=4; for (fn=0; fn<1024; fn++) { fm(0xA0,(fn & 0xFF)); fm(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); delay(1); } /*********************************************** ********************* * Single tone again. Both channels, then if on stereo board, * * play tone in just the left channel, then just the right channel. * ************************************************ ********************/ printf("440 Hz again, both channels.\n"); block=4; fn=577; /* This number makes 440 Hz when block=4 and m=1 */ fm(0xA0,(fn & 0xFF)); fm(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); #ifdef STEREO #ifdef OPL3 /* This left and right channel stuff is the only part of this program * that uses OPL3 mode. Everything else is available on the OPL2. */ getche(); printf("Left channel only\n"); fm(0xC0,LEFT | 1); /* set left channel only, parallel connection */ getche(); printf("Right channel only\n"); fm(0xC0,RIGHT | 1); /* set right channel only, parallel connection */ #else getche(); fm(0xB0,((fn >> 8) & 0x3) + (block << 2)); // key off printf("Left channel only\n"); Profm1(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); getche(); Profm1(0xB0,((fn >> 8) & 0x3) + (block << 2)); // key off printf("Right channel only\n"); Profm2(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); #endif #endif /********************************* * Attenuate the signal by 3 dB. * *********************************/ getche(); fm(0xB0,((fn >> 8) & 0x3) + (block << 2) | KEYON); printf("Attenuated by 3 dB.\n"); fm(0x43,4); /* attenuate by 3 dB */ getche(); fm(0xB0,((fn >> 8) & 0x3) + (block << 2)); #ifdef OPL3 /* Set OPL-3 back to OPL-2 mode, because if the next program to run was * written for the OPL-2, then it won't set the LEFT and RIGHT bits to * one, so no sound will be heard. */ Profm2(5, 0); /* set back to OPL2 mode */ #endif }