--- /dev/null
+/* 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
--- /dev/null
+#ifndef _DOSLIB_SND_H_\r
+#define _DOSLIB_SND_H_\r
+/* C Header File: ADLIB *****************************************************\r
+\r
+Author: Kevin A. Lee\r
+\r
+Last Amended: 27th April, 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
+\r
+Compiled succesfully under Turbo C, Borland C++,\r
+and Microsoft Quick C (all latest versions).\r
+\r
+****************************************************************************/\r
+#include "src\lib\lib_com.h"\r
+\r
+#define NUMVOICE 11\r
+#define FACTOR 1193180\r
+#define OCTAVE 4
+\r
+#define MIN_REGISTER 0x01\r
+#define MAX_REGISTER 0xF5\r
+#define ADLIB_FM_ADDRESS 0x388 /* adlib address/status register */\r
+#define ADLIB_FM_DATA 0x389 /* adlib data register */\r
+\r
+/*\r
+static int percussiveMode = 0,currentBDContents = 0;\r
+//static int opTable[18] = {0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21};\r
+static int voiceModulator[11] = {0,1,2,6,7,8,12,16,14,17,13};\r
+static int voiceCarrier[9] = {3,4,5,9,10,11,15,16,17};\r
+*/\r
+\r
+/*\r
+* FM Instrument definition for .SBI files - SoundBlaster instrument\r
+* - these are the important parts - we will skip the header, but since\r
+* I am not sure where it starts and ends so I have had to guess.\r
+* However it SEEMS! to work. Each array has two values, one for\r
+* each operator.\r
+*/\r
+typedef struct{\r
+ byte SoundCharacteristic[2]; /* modulator frequency multiple... */\r
+ byte Level[2]; /* modulator frequency level... */\r
+ byte AttackDecay[2]; /* modulator attack/decay... */\r
+ byte SustainRelease[2]; /* modulator sustain/release... */\r
+ byte WaveSelect[2]; /* output waveform distortion */\r
+ byte Feedback; /* feedback algorithm and strength */\r
+} FMInstrument;\r
+\r
+/*\r
+* Enumerated F-Numbers (in octave 4) for the chromatic scale.\r
+*/\r
+/*enum oct{\r
+ B4 = 493.88,\r
+ B4b = 466.16,\r
+ A4 = 440,\r
+ A4b = 415.3,\r
+ G4 = 392,\r
+ G4b = 369.99,\r
+ F4 = 349.23,\r
+ E4 = 329.63,\r
+ E4b = 311.13,\r
+ D4 = 293.66,\r
+ D4b = 277.18,\r
+ C4 = 261.63,\r
+ A0 = 27.50\r
+};*/\r
+enum SCALE{\r
+ B4 = 0x1EE,\r
+ B4b = 0x1D2,\r
+ A4 = 440,\r
+ A4b = 0x19F,\r
+ G4 = 0x188,\r
+ G4b = 0x172,\r
+ F4 = 0x15D,\r
+ E4 = 0x14A,\r
+ E4b = 0x137,\r
+ D4 = 0x126,\r
+ D4b = 0x115,\r
+ C4 = 0x106,\r
+ A0 = 0x7F2\r
+};
+\r
+/* function prototyping */\r
+void WriteFM(int reg, int value);\r
+int ReadFM(void);\r
+int AdlibExists(void);\r
+void FMReset(/*int percusiveMode*/); /* Resets the card, quiets all voices, sets the percussive mode state */\r
+void FMKeyOff(int voice);\r
+void FMKeyOn(int voice, int freq, int octave);\r
+void FMVoiceVolume(int voice, int vol);\r
+void FMSetVoice(int voiceNum, FMInstrument *ins);\r
+/* Remember: percussion instruments must be assigned only to the correct voice number. */\r
+//void FMSetPercusiveMode(int state);\r
+//int LoadSBI(char filename[], FMInstrument *ins);\r
+void fmtest(void);
+int soundtest();\r
+#endif/*_DOSLIB_SND_H_*/
\ No newline at end of file