I was having a look at the manual for the Yamaha YM3812 and YMF262 and wanting to build a small software synthesizer in C++ and JS.
You can have a look at what I've made so far of a small FM Tone Generator in JS on CodePen here:
https://codepen.io/john-ernest/pen/LYXpNKr
Here are links to the manuals for the YM3812 and YMF262 for reference:
YM3812: https://c64.xentax.com/images/LSI-2438124-Yamaha-YM3812-OPL2-Application-Manual.pdf
YMF262: https://map.grauw.nl/resources/sound/yamaha_ymf262.pdf
The YM3812 manual on page 2 shows 2 equations:
F = A*sin(wct + I*sin(wmt))
The Feedback equation is:
F = A*sin(wct + BF)
where B I presume comes from a range of values on page 19:
0, pi/16, pi/8, pi/4, pi/2, pi, 2pi, 4pi
If you'll look in the "Output PCM Code" textarea section of the FM Tone Generator you'll see a piece of JS code that gets eval'd and it looks like so:
let x2p = x*2.0*Math.PI;
let m1 = mWaveform(x2p*mFreq, A1);
let c1 = cWaveform(x2p*cFreq + m1, A2);
let f1 = cWaveform(x2p*cFreq + feedback*c1, A2);
if (feedback != 0) {
value = f1;
}
else {
value = c1;
}
if the modulator and carrier waveforms are both sine waves and feedback is set to 7 (4*PI) then the above would be equivalent to:
let value = A2*Math.sin(x*2.0*Math.PI*cFreq + A1*Math.sin(x*2.0*Math.PI*mFreq));
value = A2*Math.sin(x*2.0*Math.PI*cFreq + 4*Math.PI*value);
That doesn't sound right for feedback though, I should be getting noise at feedback 7 (4*PI), with modulator and carrier set to sine waves at 130.81Hz (C-3), going by an AdLib tracker I'm comparing to in DosBox.
This sounds closer to what I hear in DosBox but doesn't seem right since no documentation seems to mention re-running the feedback multiple times, I made it do 10 iterations at the selected feedback on the modulator:
let x2p = x*2.0*Math.PI;
let m1 = mWaveform(x2p*mFreq, A1);
let iterations = 10;
if (feedback != 0) {
for(let i = 0; i < iterations; i++) {
m1 = mWaveform(x2p*mFreq + feedback*m1);
}
}
let c1 = cWaveform(x2p*cFreq + m1, A2);
value = c1;
I've had a look at some emulator sources e.g. Mame but it's a tad hard to follow since they use lookup tables to emulate the YM3812 exactly, and I don't have anything set up for said projects for step debugging, whereas I'm making a more generalized synth and later tracker or MML interpreter that can do pulse, triangle, and other waveforms.