Using An AdLib-Compatible Sound Card's FM Chip: The FM chip's register port is BaseAddress + 8. The chip's data port is BaseAddress + 9. So, for example, if your sound card's base address is 220h (as most sound cards are set by default to be), your FM chip's register port is 228h and the data port is 229h. Wasn't that easy! (The AdLib card's base address was 380h, and so most Sound Blaster cards will also work with addresses 388h and 389h for backward compatibility.) To set a register on the chip, all you have to do is first send the value of the register you want to set to the register port; Then you send the new value for that register to the data port. It's that simple. For example, if you want to set register 20 to equal 15, then you'd send 20h to port 388h, and then 15h to port 389h. There are 224 registers on the basic Sound Blaster (or compatible) card's FM chip. If you memorize all of them and their functions, you are a very boring person. The most important registers the actual note registers, where the actual notes are sent. Because the notes are 10 bits, and the registers are only 8 bits wide, two registers are required for each. Registers A0h (for channel 1) to A8h (for channel 9) hold the 8 least significant bits (LSBs), while the last two bits of registers B0h (for channel 1) to B8h (for channel 9) hold the two most significant bits (MSBs) for the notes. The next 3 bits of those registers (B0 to B8) hold the octave number, the next bit is a switch (when set to 1, the channel is on; when set to 0, the channel is off), and the final two bits are unused. In theory, you can play a monotone melody by simply sending values to registers A0 and B0; In practice, unfortunately, some preparation must be done before you can start playing notes. This preparation involves arcane concepts like "carriers" and "modulators", which are the very basis for FM synthesis. If you've done much work with MIDI using Windows programs, you've probably gotten used to the concept of having big lists of instruments which you can choose from and make individual notes out of. Well, FM synthesis doesn't use instruments; The concept of picking an instrument from a list is only possible with wave-table synthesis, in which a ROM chip on the sound card simply holds a bunch of instrument sounds and you can pick from them. FM synthesis uses sine waves to create an approximation of an instrument's sound, and it doesn't come with pre-defined instruments built into the hardware; You have to make your own instrument sounds using the sine waves. Below are listed the primary registers for the FM chip. Registers are shown in the following format: Channel: Carrier register/Modulator register For example, if you want the key scaling level/output level registers for channel 4, the carrier register for that channel is 48h, and the modulator register is 4Bh. (All register numbers are given in hexadecimal.) Amplitude modulation/Vibrato/EG type/Key scaling/Octave shift registers: 1: 20/23 2: 21/24 3: 22/25 4: 28/2B 5: 29/2C 6: 2A/2D 7: 30/33 8: 31/34 9: 32/35 Key scaling level/Output level registers: 1: 40/43 2: 41/44 3: 42/45 4: 48/4B 5: 49/4C 6: 4A/4D 7: 50/53 8: 51/54 9: 52/55 Attack rate/Decay rate registers: 1: 60/63 2: 61/64 3: 62/65 4: 68/6B 5: 69/6C 6: 6A/6D 7: 70/73 8: 71/74 9: 72/75 Sustain level/Release time registers: 1: 80/83 2: 81/84 3: 82/85 4: 88/8B 5: 89/8C 6: 8A/8D 7: 90/93 8: 91/94 9: 92/95 And now for the formats of all those registers. (All registers are 8 bits in size): Amplitude modulation/Vibrato/EG type/Key scaling/Octave shift register format: First bit: If on, amplitude modulation (AM) is enabled. Second bit: If on, vibratio is enabled. Third bit: EG type. (?) Fourth bit: Key scaling. (?) Last four bits: Octave. If set to 1, the note is played at the specified octave. If set to 0, the note is played one octave below. If set to 2, the note is played one octave above. Key scaling level/Output level register format: First two bits: Scaling level. Last six bits: Output level. How loud the note is. Attack rate/Decay rate register format: First four bits: Attack rate. (First stage in an FM note.) Last four bits: Decay rate. (Second stage in an FM note.) Sustain level/Release time register format: First four bits: Sustain level. (Third stage in an FM note.) Last four bits: Release time. (Fourth and last stage in an FM note.) Actual note values for all musical notes are as follows: C# (Db): 16Bh (0101101011) D: 181h (0110000001) D# (Eb): 198h (0110011000) E: 1B0h (0110110000) F: 1CAh (0111001010) F# (Gb): 1E5h (0111100101) G: 202h (1000000010) G# (Ab): 220h (1000100000) A: 241h (1001000001) A# (Bb): 263h (1001100011) B: 287h (1010000111) C: 2AEh (1010101110) Remember, the notes are 10 bits, but the registers are only 8 bits, so the first 2 bits of the note make the last 2 bits of the B register (B0 to B8, depending on what channel the note is for), and the last 8 bits of the note go to the A register (A0 to A8). Once again, the format for the B register is: First two bits: Unused. Third bit: Switch (turns channel on or off). Fourth to sixth bits: Octave. Last two bits: First two bits of note. Thus, when calculating what value to send to the B register to make a note, you must add 20h (100000) (to turn on the channel), plus the octave number times 4 (this will correctly set the octave), plus the actual first two bits of the note. So the formula for the value to send to the B register is: 20h + (octave * 4) + the first two bit values Why do we multiply the octave by 4? Because it perfectly sets the octave bits to the way we need them. Suppose that we wanted to set the octave to 2. 2 * 4 is 8, or 1000 in binary. If we set the B register to 8, then the octave bits form 010, which is 8 in binary. Another example: If we want to make the octave 5, we multiply 5 * 4, which is 20, or 10100 in binary, making the octave bits 101, which is 5. See how it works? Now for some note-sending examples. To make the note C, which has a note value of 1010101110, and use octave 1, we would calculate: 20h + (1 * 4) + 2 (...Because 2 is 10 is binary.) This equals 26h, or 00100110. So we would send 26h to the B register, and then the remaining 8 bits of the note (10101110, or AEh) to the A register. One more example: To make the note E (0110110000) and use octave 3... 20h + (3 * 4) + 1 ...Which equals 2Dh, or 00101101. So we send 2Dh to the B register, and 10110000 (B0h) to the A register. Simple, isn't it?