## FM Synthesis

An investigation into the behaviour of the Yamaha OPL3 chipset.
With a view to a more accurate emulator

### FM Synthesis

It's well documented that the OPL synthesisers use phase modulation as a primary synthesis technique. Yamaha have always called this FM which can be a little misleading.

The amplitude of the modulator wave is used to vary the phase of the carrier wave. This carrier wave is generated by calculating a phase value from the operator clock (the frequency of which is controlled by the f-number / block values) and passing that phase value to the wave lookup table. Modulation occurs simply by adding a modulation component derived from the amplitude of the modulating wave, to that phase value which is fed into the carrier's wave lookup.

Last night I did a series of tests with the aim of determining exactly how the amplitude of the modulator is related to the depth of modulation. In other words how do we get from the modulator amplitude to that additional phase value.

I selected 4-operator algorithm 4 which looks something like this:

Code: Select all
`     -----------------     |               |     v     -------   |-----+---->| OP1 |--------------------           -------                   |                                     |           -------       -------     v---------->| OP2 |------>| OP3 |-----+---->           -------       -------     ^                                     |           -------                   |---------->| OP4 |--------------------           -------`

I set operator 1 and operator 4 to a square wave with a high attenuation.
These will serve as a reference signal. The square waves can be easily recognised and removed from the output signal, but the rising and falling edges of the waves provides represent the start and midpoint of the modulator wave as well. Operator 2 is also a square wave, and the attenuation for this wave is varied in the experiment. It is this variation which will be compared to the output result. Finaly operator 3 is a sine wave with a low attenuation. This is the carrier wave and the distinct phase shift which occurs twice in each cycle is caused by the square wave modulator.

I haven't had a chance to study the results yet, but a cursory examination shows that the data appears to be good. I Have a distinctive sine wave shape, with a discontinuity in two places as the phase shifts abruptly.

When I get a chance to go through the figures, I should get a clear answer as to how the wave amplitude is converted to a phase shift value.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

I've started looking through this data properly.

At first glance it looks as though the phase shift modulator is taken from the previous sample. This would make sense architecturally but I'll need some more time to confirm this.
It might be worth doing some more tests modulating a square wave with a squave wave. If this suspicion is correct, then the discontinuities will cover two samples, as first the carrier switches, then the modulator switch becomes apparent in the following sample.

The simplest approach in building a software model for this, would be to store the output of each operator. Then process all 36 (18) operators in reverse order for each sample. There is no connection plan which results in a higher numbered operator feeding into the phase generator of a lower numbered operator.

More later.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

So far, the results show that the modulator amplitude is simply added unchanged in the phase generator stage.

A TL of 0x3F for the modulator, should give a peak amplitude of 17, and this is consistent with what appears to be a 17 step shift in the phase of the carrier.
A TL of 0x20 for the modulator, should give a peak amplitude of 256, and this is consistent with a 256 step shift.
A TL of 0x00 should give a peak amplitude of 4084, which is almost 4 cycles of phase shift. I'm seeing a 12 step retrograde phase shift, which is consistent with this

The results have shown up some confusion with actual output levels, varying by 1 or 2 from what I expect. At the moment my hypothesis is that this is the result of accumulating the +ve and -ve parts of the waves. I'm going to try and come up with some experiments to prove/disprove this hypothesis, before I can be confident in modelling the fm-sythesis stage.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

In your exponent table lookup code you use two's complement based on sign which would explain the negative part being off by one when converted to PCM output.

So if you still use the code posted on the forum, you should try one's complement if it matches.
opl3

Posts: 55
Joined: Sun Sep 26, 2010 8:11 pm

### Re: FM Synthesis

Thanks,

that's not my problem, but I had forgotten that the exponent code did the two's complement form. At some point I have to decide what kind of output to deliver.

I'm convinced from the simple outputs that I've got out of the chip already, that the amplitude and sign are carried separately for at least part of the pathway in the chip. The question is exactly what results do you get when you add together +ve and -ve values. This has to happen at some point, but not necessarily until the very last stages. Combining waveform 0 and waveform 2, the full sine wave and the rectified sine wave, should result in a double amplitude half sine wave; the big question is what kind of zero do I get in the remainder of the waveform.

There is clearly a discrepancy between the output of the YMF262 and the input expectations of the yac512. The latter clearly expects a 16-bit offset value, while the actual ymf262 output exhibits this so-called off by one issue in the -ve. At the end of the day, the difference should be marginal, and the yac512 is not actually delivering 16-bit accuracy on the analogue side, because internally it's a 10-bit d/a with a 7 step shift.

Anyway, I'm glad to see that someone is listening, even if I'v been quiet for months.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

Just a thought, but if you see that the values are off by one (or two) very rarely, have you taken into account that in the attack phase the waveform is ramped from 0 to maximum, and this ramp ends up from the modulator output into phase accumulator of the carrier? I don't remember if AR=15 results the attack waveform to be a step function without any intermediate values between 0 and max, or was there even something seemingly random when the attack was very steep. So in the end your code might be always adding correct increment but the phase accumulator in your code just has a very small constant offset compared to phase accumulator in real chip.

If it is of any help, the operator type bit (sum or FM) can be changed when the wave is playing, so you could start a sound, wait for things to settle and then switch into FM mode. Setting FNUM to 0 guarantees that the wave does not advance, but it would have to be analyzed if the phase accumulator is reset to zero when key-on bit is set.

carbon14 wrote:I'm convinced from the simple outputs that I've got out of the chip already, that the amplitude and sign are carried separately for at least part of the pathway in the chip. The question is exactly what results do you get when you add together +ve and -ve values. This has to happen at some point, but not necessarily until the very last stages.

I think the amplitude and sign are very much separated. If I recall correctly, if you start a sine wave with FNUM=1, BLOCK=0, MULTI=0 (meaning *0.5), you should see that the sine wave does not advance at all, but the sign still changes. This would imply that the internal phase increment for table lookup is then 0, but the internal phase increment for sign is 1 or at least non-zero.

I also recall testing the output sum with eight square waves, only that they all had TL=0. And if I am right, the PCM values of separate channels are just summed for output, so the conversion to PCM is done before sum to actual output accumulator. The output should then be from 8*4084=32672 to 8*(-4085)=−32680, but I don't remember any more the results. Since the square waves were started in a bit different phase, you could see a staircase waveform, and I recall the output values still matched when any combination of positive and negative channel was summed. Outval=N*4084-(8-N)*4085, N being count of positive channels and thus 8-N is count of negative channels.

carbon14 wrote:There is clearly a discrepancy between the output of the YMF262 and the input expectations of the yac512. The latter clearly expects a 16-bit offset value, while the actual ymf262 output exhibits this so-called off by one issue in the -ve. At the end of the day, the difference should be marginal, and the yac512 is not actually delivering 16-bit accuracy on the analogue side, because internally it's a 10-bit d/a with a 7 step shift.

I think the internal operation and output of a specific DAC should not matter. Any DAC does its best to work with the 16-bit PCM value it is given. What is important is the 16-bit PCM value what comes out from OPL chip. And this again depends on how the float is converted to PCM and summed together.

carbon14 wrote:Anyway, I'm glad to see that someone is listening, even if I'v been quiet for months.

I visit here every day for updates.
opl3

Posts: 55
Joined: Sun Sep 26, 2010 8:11 pm

### Re: FM Synthesis

There's a lot of useful information in that post.

Thank you.

I might have time to get back into the workshop tonight.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

I take it all back.

My latest results suggest that there really is an off-by one error in there. Or perhaps it might be reasonably to suggest that the minimum amplitude of any waveform is 0.5

When we add together the +ve and -ve maxima, to get a peak amplitude range it comes to 8169. I had taken this to be an artifact of two's complement arithmetic. but adding multiple waveforms together really does seem to be producing swings of 8169 PER WAVEFORM. If it were simply a two's complement artifact, the discrepancy would surely be just 1 no matter how many waves were used.

This looks as though it will go a long way toward explaining my results so far. For a square wave with a peak amplitude of +/- 17 the phase displacement that results is +17 and -18.

I'm going to have to come up with a better way of describing the numbers involved when I write stuff like this, because this post is too confusing already.

Let's try this again:

The modulator wave has an offset output varying from 32750 to 32785. That's a total range of 35. The phase displacement varies from -18 to +17 which is also a total range of 35.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

Given the above it seems more likely that the carrier wave phase is modulated by the modulator value of the same sample, rather than by that of the previous sample.

I suggest that the strange arrangement of slots into sound units is explained by this. Where a sound unit is made of a pair of operators which are three slots apart. I think that the operators are processed on the chip in the order of the slots.

I posit that they cannot be all processed in parallel, they each have to use the lookup tables and that cannot be realistically done in parallel.
But by processing the slot 1 lookup, then slot 2, slot 3 and slot 4 etc. You have time to do more processing on the slot 1 operator while slots 2 and 3 are using the lookup, so that you can have a value ready to feed into the slot 4 phase generator prior to it's lookup.

There are 288 clock cycles between each sample, and during those 288 clock cycles all 36 operators potentially need to access the lookup tables.

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

### Re: FM Synthesis

This fragment of code seems to produce good results.

This recreates the values I'm getting from this set of experiments, varying just the waveform and the total level.

Code: Select all
`#define WS1   6#define WS2   6#define WS3   6#define WS4 6#define TL1   0#define TL2 0x3D#define TL3   0#define TL4   0int main(int argc, char *argv[]){   unsigned int i;   unsigned short int l;   signed short int op1, op2, op3, op4;   for (i = 0; i < 1024; i++)   {      op1 = Exp(WaveSelect(WS1, i      ) + (TL1 << 5));      op2 = Exp(WaveSelect(WS2, i      ) + (TL2 << 5));      op3 = Exp(WaveSelect(WS3, i + op2) + (TL3 << 5));      op4 = Exp(WaveSelect(WS4, i      ) + (TL4 << 5));      printf("%05d\n", op1 + op3 + op4 + 32768);   }}`

carbon14

Posts: 124
Joined: Tue Aug 05, 2008 9:11 am
Location: York, England

Next