]> 4ch.mooo.com Git - 16.git/blobdiff - 16/16/opl2.c
refresh wwww
[16.git] / 16 / 16 / opl2.c
diff --git a/16/16/opl2.c b/16/16/opl2.c
new file mode 100755 (executable)
index 0000000..d78ecb3
--- /dev/null
@@ -0,0 +1,304 @@
+/* C Source File: ADLIB *****************************************************\r
+\r
+Author:            Kevin A. Lee\r
+\r
+Last Amended:      27th March, 1993\r
+\r
+Description:        Low-level interface to the Adlib (or compatible)\r
+FM sound card. All information gleaned from\r
+Jeffrey S. Lee's "Programming the Adlib/Sound\r
+Blaster FM Music Chips". See Lee's document for\r
+further information.\r
+Compiled succesfully under Turbo C, Borland C++,\r
+and Microsoft Quick C (all latest versions).\r
+\r
+****************************************************************************/\r
+#include "src\lib\opl2.h"\r
+
+//sound てすと
+int sq = 0;
+\r
+/* Function: WriteFM ********************************************************\r
+*\r
+*     Parameters:        reg - which FM register to write to.\r
+*                         value - value to write.\r
+*\r
+*     Description:        writes a value to the specified register and\r
+*                         waits for the "official" recommended periods.\r
+*\r
+*/\r
+void WriteFM(int reg, int value){\r
+       int i;\r
+\r
+       outp(ADLIB_FM_ADDRESS, (byte)reg);                              /* set up the register  */\r
+       for (i = 0; i < 6; i++) inp(ADLIB_FM_ADDRESS);  /* wait 12 cycles      */\r
+       outp(ADLIB_FM_DATA, (byte)value);                                       /* write out the value */\r
+       for(i = 0; i < 35; i++) inp(ADLIB_FM_ADDRESS);  /* wait 84 cycles      */\r
+} /* End of WriteFM */\r
+\r
+/* Function: ReadFM *********************************************************\r
+*\r
+*     Returns:            the value in the status register.\r
+*\r
+*     Description:        return a value in the status register.\r
+*\r
+*/\r
+int ReadFM(void){\r
+       return(inp(ADLIB_FM_ADDRESS));\r
+} /* End of ReadFM */\r
+\r
+/* Function: AdlibExists ****************************************************\r
+*\r
+*     Returns:            1 (true) if an Adlib compatible sound card\r
+*                         is present, else 0 (false).\r
+*\r
+*     Description:        determines whether an Adlib (or compatible)\r
+*                         sound card is present.\r
+*\r
+*/\r
+int AdlibExists(void){\r
+       int stat1, stat2;\r
+\r
+       WriteFM(0x04, 0x60);            /* reset both timers        */\r
+       WriteFM(0x04, 0x80);            /* enable timer interrupts  */\r
+       stat1 = ReadFM();                       /* read status register     */\r
+       WriteFM(0x02, 0xFF);\r
+       WriteFM(0x04, 0x21);            /* start timer 1            */\r
+//     wait(80);                               /* could do something useful*/\r
+       stat2 = ReadFM();                       /* read status register     */\r
+       WriteFM(0x04, 0x60);            /* reset both timers        */\r
+       WriteFM(0x04, 0x80);            /* enable timer interrupts  */\r
+\r
+       if(((stat1 & 0xE0) == 0x00) && ((stat2 & 0xE0) == 0xC0)) return(1);\r
+       return(0);\r
+} /* End of AdlibExists */\r
+\r
+/* Function: FMResest *******************************************************\r
+*\r
+*     Description:        quick and dirty sound card reset (zeros all\r
+*                         registers).\r
+*\r
+*/\r
+void FMReset(void/*int percusiveMode*/){\r
+       int i;\r
+\r
+       /* zero all registers */\r
+       for(i = MIN_REGISTER; i < MAX_REGISTER+1; i++) WriteFM(i, 0);\r
+\r
+       /* allow FM chips to control the waveform of each operator */\r
+       WriteFM(0x01, 0x20);\r
+\r
+       /* set rhythm enabled (6 melodic voices, 5 percussive) */\r
+       WriteFM(0xBD, 0x20);\r
+\r
+       //FMSetPercusiveMode(percusiveMode);\r
+} /* End of FMReset */\r
+/*\r
+void FMSetPercusiveMode(int state){\r
+       if(state){\r
+               WriteFM(0xBD, 0x20);\r
+               currentBDContents = 0x20;\r
+               percussiveMode = 1;\r
+               voiceModulator[7] = 16;\r
+               voiceModulator[8] = 14;\r
+               // we have to set the freq of voice 7 & 8 for the white noise gen.\r
+               // these frequency choices could certainly be better\r
+               WriteFM(0xa7, 1844 & 0xff);\r
+               WriteFM(0xb7, 1844 >> 8);\r
+               WriteFM(0xa8, 3764 & 0xff);\r
+               WriteFM(0xb8, 3764 >> 8);\r
+       }else{\r
+               WriteFM(0xBD, 0);\r
+               percussiveMode = 0;\r
+               currentBDContents = 0;\r
+               voiceModulator[7] = 13;\r
+               voiceModulator[8] = 14;\r
+       }\r
+}\r
+*/\r
+/* Function: FMKeyOff *******************************************************\r
+*\r
+*     Parameters:        voice - which voice to turn off.\r
+*\r
+*     Description:        turns off the specified voice.\r
+*\r
+*/\r
+void FMKeyOff(int voice){\r
+       int regNum;\r
+\r
+       /* turn voice off */\r
+       regNum = 0xB0 + voice % NUMVOICE;\r
+       WriteFM(regNum, 0x0E);\r
+} /* End of FMKeyOff */\r
+\r
+/* Function: FMKeyOn *******************************************************\r
+*\r
+*     Parameters:        voice - which voice to turn on.\r
+*                         freq - its frequency (note).\r
+*                         octave - its octave.\r
+*\r
+*     Description:        turns on a voice of specfied frequency and\r
+*                         octave.\r
+*\r
+*/\r
+void FMKeyOn(int voice, int freq, int octave){\r
+       int regNum, tmp;\r
+\r
+       regNum = 0xA0 + voice % NUMVOICE;\r
+       WriteFM(regNum, freq & 0xff);\r
+       regNum = 0xB0 + voice % NUMVOICE;\r
+       tmp = (freq >> 8) | (octave << 2) | 0x20;
+       WriteFM(regNum, tmp);\r
+} /* End of FMKeyOn */\r
+\r
+/* Function: FMVoiceVolume **************************************************\r
+*\r
+*     Parameters:        voice - which voice to set volume of\r
+*                         vol - new volume value (experiment).\r
+*\r
+*     Description:        sets the volume of a voice to the specified\r
+*                         value in the range (0-63)?\r
+*\r
+*/\r
+void FMVoiceVolume(int voice, int vol){\r
+       int regNum;\r
+\r
+       regNum = 0x40 + voice % NUMVOICE;\r
+       WriteFM(regNum, vol);\r
+} /* End of FMVoiceVolume */\r
+\r
+/* Function: FMSetVoice *****************************************************\r
+*\r
+*     Parameters:        voiceNum - which voice to set.\r
+*                         ins - instrument to set voice.\r
+*\r
+*     Description:        sets the instrument of a voice.\r
+*\r
+*/\r
+void FMSetVoice(int voiceNum, FMInstrument *ins){\r
+       int opCellNum, cellOffset;\r
+\r
+       voiceNum %= NUMVOICE;\r
+       cellOffset = voiceNum % 3 + ((voiceNum / 3) << 3);\r
+\r
+       /* set sound characteristic */\r
+       opCellNum = 0x20 + (char)cellOffset;\r
+       WriteFM(opCellNum, ins->SoundCharacteristic[0]);\r
+       opCellNum += 3;\r
+       WriteFM(opCellNum, ins->SoundCharacteristic[1]);\r
+\r
+       /* set level/output */\r
+       opCellNum = 0x40 + (char)cellOffset;\r
+       WriteFM(opCellNum, ins->Level[0]);\r
+       opCellNum += 3;\r
+       WriteFM(opCellNum, ins->Level[1]);\r
+\r
+       /* set Attack/Decay */\r
+       opCellNum = 0x60 + (char)cellOffset;\r
+       WriteFM(opCellNum, ins->AttackDecay[0]);\r
+       opCellNum += 3;\r
+       WriteFM(opCellNum, ins->AttackDecay[1]);\r
+\r
+       /* set Sustain/Release */\r
+       opCellNum = 0x80 + (char)cellOffset;\r
+       WriteFM(opCellNum, ins->SustainRelease[0]);\r
+       opCellNum += 3;\r
+       WriteFM(opCellNum, ins->SustainRelease[1]);\r
+\r
+       /* set Wave Select */\r
+       opCellNum = 0xE0 + (char)cellOffset;\r
+       WriteFM(opCellNum, ins->WaveSelect[0]);\r
+       opCellNum += 3;\r
+       WriteFM(opCellNum, ins->WaveSelect[1]);\r
+\r
+       /* set Feedback/Selectivity */\r
+       opCellNum = (byte)0xC0 + (byte)voiceNum;\r
+       WriteFM(opCellNum, ins->Feedback);\r
+} /* End of FMSetVoice */\r
+\r
+/* Function: LoadSBI ********************************************************\r
+*\r
+*     Parameters:        fileName - name of .SBI file.\r
+*                         ins - variable to place data in.\r
+*\r
+*     Description:        loads a .SBI into the instrument structure.\r
+*\r
+*/\r
+//int LoadSBI(char fileName[], FMInstrument *ins){\r
+//  int i;\r
+//  FILE *fp;\r
+//  size_t structSize = sizeof(FMInstrument);\r
+//\r
+//  if ((fp = fopen(fileName, "rb")) == NULL) return (0);\r
+//\r
+//  /* skip the header - or do we? */\r
+//  for (i = 0; i < 36; i++) fgetc(fp);\r
+//\r
+//  /* read the data */\r
+//  fread(ins, structSize, 1, fp);\r
+//\r
+//  fclose(fp);\r
+//  return (1);\r
+//} /* End of LoadSBI */\r
+
+unsigned short Notes[] = {\r
+        19327 ,        /* C b            */\r
+        18242 ,        /* C              */\r
+        17218 ,        /* C #   ( D b )  */\r
+        16252 ,        /* D              */\r
+        15340 ,        /* D #   ( E b )  */\r
+        14479 ,        /* E     ( F b )  */\r
+        13666 ,        /* F     ( E # )  */\r
+        12899 ,        /* F #   ( G b )  */\r
+        12175 ,        /* G              */\r
+        11492 ,        /* G #   ( A b )  */\r
+        10847 ,        /* A              */\r
+        10238 ,        /* A #   ( B b )  */\r
+        9664 ,         /* B     ( C b )  */\r
+        9121 ,         /* B #            */\r
+        0\r
+};
+\r
+/* test of the routines */\r
+void fmtest(){\r
+       enum SCALE test[] = { D4, E4, F4, G4, A4, B4, C4 };\r
+//     enum SCALE oct4[] = { 493.88, 466.16, 440, 415.3, 392, 369.99, 349.23, 329.63, 311.13, 293.66, 277.18, 261.63 };\r
+       static FMInstrument testInst =\r
+{\r
+0x00, 0x01,    /* modulator frequency multiple... 0x20 */\r
+0x00, 0x00,    /* modulator frequency level...    0x40 */\r
+0xF0, 0xF0,    /* modulator attack/decay...       0x60 */\r
+0x73, 0x73,    /* modulator sustain/release...    0x80 */\r
+0x03, 0x00,    /* output waveform distortion      0xE0 */\r
+0x36,                          /* feedback algorithm and strength 0xC0 */\r
+};\r
+       int i;\r
+       printf("Now testing tune....\n");\r
+//     printf("just hit any key 7 times.\n");\r
+       FMReset();\r
+       FMSetVoice(0, &testInst);
+       //extra
+//     WriteFM(0xB0, 0x09);
+//     WriteFM(0xB3, 0x07);
+       //extra
+       for(i = 0; i < 7; i++){\r
+               FMKeyOn(0, test[i], 4);
+               sound(test[i]);\r
+               wait(20);\r
+//             getche();
+               FMKeyOff(0);
+               nosound();\r
+               wait(1);\r
+       }\r
+}
+
+//sound てすと
+int soundtest(){
+       enum SCALE test[] = { D4, E4, F4, G4, A4, B4, C4 };\r
+       //FMKeyOn(0, test[sq], 4);
+       if(sq < 7){\r
+               sq++;\r
+       }else sq = 0;
+       FMKeyOff(0);
+       return sq;
+}
\ No newline at end of file