This note is about ex03_beep.cpp.
The goal is not to make a rich instrument yet. The goal is to understand one simple YM2612 beep by starting from the final sound and then tracing how that sound is configured.
Before reading the code, open this page and hear the target result:
That demo applies the same YM2612 settings as ex03_beep.cpp.
So the main question of this tutorial is:
How do we describe that beep in FM terms, and how do we send those settings to ymfm or to the real chip?
Before looking at register numbers, it helps to describe the beep like this:
channel 1algorithm 7DT/MULTI settingsBLOCK + F-NumberKey ONThis is the real idea behind the beep. The register writes are only the chip-specific way to express that idea.
The YM2612 has 6 FM channels. Each channel has 4 operators.
An operator is a small tone generator. Operators can modulate each other, or they can directly contribute to the final output.
In ex03_beep.cpp, we use channel 1.
In FM synthesis, one channel is basically built from 4 operators.
That is why ranges such as 0x30-0x3c exist: the settings are repeated for the 4 operators.
In Algorithm 7, all 4 operators work as carriers. This is a simple starting point because every operator directly contributes to the output.
It is not the only way to make a sound, but it is easy to understand.
For this beep, the intended setup is roughly:
17More concretely:
DT=0, MULTI=1TL=0x7fTL=0x00AR0xa4 = 0x220xa0 = 0x690x28 = 0xf0Without Key ON, the chip is configured but the note does not actually begin.
Once the FM-side idea is clear, we can look at the chip-side expression.
Each register write follows this pattern:
For example:
chip.write(0, 0x30);
chip.write(1, 0x01);
This means:
0x30.0x01 into register 0x30.So ex03_beep.cpp is really doing two things at once:
ex03_beep.cpp0x30-0x3c: operator detune and multiple0x40-0x4c: operator total level0x50-0x5c: operator attack rate0x80-0x8c: operator sustain level and release rate0xb0: channel algorithm and feedback0xb4: left/right output enable0xa4 and 0xa0: frequency0x28: key on / key offThese registers control detune and frequency multiple for each operator.
0x30, 0x34, 0x38, 0x3cIn ex03_beep.cpp, they are all set to 0x01.
What happens:
1More detail:
Detune (DT) slightly shifts the pitchMultiple (MUL) changes the frequency by integer ratios such as 1x, 2x, 3x, and 4xMUL=2 is about one octave above the base frequency, and MUL=4 is about two octaves aboveThese registers control the output level of each operator.
0x40, 0x44, 0x48, 0x4cIn ex03_beep.cpp, operator 4 is louder than the others:
0x40 = 0x7f0x44 = 0x7f0x48 = 0x7f0x4c = 0x00What happens:
More detail:
Total Level (TL) is the final output level of an operatorThese registers control how quickly the sound rises.
0x50, 0x54, 0x58, 0x5cIn ex03_beep.cpp, they are all set to 0x1f.
What happens:
More detail:
Attack Rate (AR) is how fast the sound reaches its peak after Key OnThese registers are part of the envelope settings.
0x80, 0x84, 0x88, 0x8cIn ex03_beep.cpp, they are all set to 0x0f.
What happens:
More detail:
Sustain Level (SL) is the level held after the decay stageRelease Rate (RR) is how fast the sound disappears after Key OffRR makes the sound stop quicklyRR leaves a longer tail0xb0 = 0x07This selects Algorithm 7 for channel 1.
What happens:
More detail:
Algorithm (ALG) defines how the 4 operators are connected0xb0 also contains Feedback (FB)Feedback routes an operator output back into itself, which can add sharpness, noise, or distorted character0xb4 = 0xc0This enables both left and right output.
What happens:
MOL and MORMore detail:
PAN0xa4 = 0x220xa0 = 0x69These two registers set the pitch.
What happens:
More detail:
0xa4 contains upper information such as BLOCK0xa0 contains the lower F-Number bits0x28 = 0xf0This turns on operators 1-4 for channel 1.
What happens:
More detail:
0x28 is the actual note triggerIf you want to understand the YM2612 more deeply and write your own setup by yourself,
it is a good idea to read ymfm source code directly.
In this repository, src/ymfm_opn.h:209 is a very useful register dictionary.
These lines are especially helpful:
src/ymfm_opn.h:221
0x30 range -> op_detune, op_multiplesrc/ymfm_opn.h:223
0x40 range -> op_total_levelsrc/ymfm_opn.h:224
0x50 range -> op_ksr, op_attack_ratesrc/ymfm_opn.h:229
0x80 range -> op_sustain_level, op_release_ratesrc/ymfm_opn.h:210
0xb0 -> ch_feedback, ch_algorithmsrc/ymfm_opn.h:212
0xb4 -> channel output / pan related fieldssrc/ymfm_opn.h:209
0xa4 + 0xa0 -> ch_block_freqFor 0x28 key on/key off handling, src/ymfm_opn.cpp:176 is the place to read.
Once you can connect ex03_beep.cpp with these definitions, you are already very close to being able to build your own YM2612 beep setup.
The beep is not made by one special “beep command”.
The sound appears because:
Key ON starts the note