Help with setting FM patch values

For anything related to sound (YM2612, PSG, Z80, PCM...)

Moderator: BigEvilCorporation

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Help with setting FM patch values

Post by MrD » Sun Jan 26, 2014 5:18 pm

Hi, I'm writing a music player for the Mega Drive, but I'm having some unusual problems that I don't understand.

I've written a simple FM patch editor which exposes all the values for the operator lines so I can make new instruments and see what they sound like. (zip) A and B increase or decrease the values. C does a note on. Start does a note off. (screenshot)

My problem is that the values for the operators don't seem to be matching up with what I expect the note to sound like.

Read from top to bottom on my grid, the topmost line is operator 1 (the self-feedback line) and the bottommost line is operator 4, corresponding to M1 C1 M2 and C2 on the normal FM algorithm diagrams. The default values should give a note that's clear and loud and eventually decays.

If I enable just operator 4 by itself and trigger note on, I get the sine tone which is expected. If I enable lines 3 and 4 together, I don't get the effect I expect. With the values in this screenshot, I'm expecting to get the unmodulated sine tone I would get if only line 4 were enabled (because the TL for line 3 is 127 so it should be silent), but it appears that when line 3 is enabled, it's using all the values from line 2. It seems that the values for lines 2 and 3 are swapped perhaps?

I'm confident that my code is swizzling together the correct values, as the YM debugger in Regen is showing that the FM registers all contain what I'm expecting. (EN is operator line enable = Key at the bottom. AE = Amp Mode?, TL = Total Level, AR = Attack Rate, D1R = First Decay, D1L = Sub Level, D2R = Second Decay, RR = Release Rate, RS = Rate Scaling, MUL = Multiple, DT1 = Detune), but I might not be putting them into the correct registers.

Here is how I'm assigning the values. Could somebody tell me if I've mixed something up along the way?

My code assembles all the necessary FM register values and loads them into [$30...$8C] for channel 0:
The first operator (M1) line's values go into $30, $40, $50...
The second operator (C1) line's values into $34, $44, $54...
The third operator (M2) line's values into $38, $48, $58...
The fourth operator (C2) line's values into $3C, $4C, $5C...

The EN column refers to the operator bitmask used when sending a 'note on' in FM register $28, with the lines in the bitmask arranged as %4321xccc. (ccc is channel and is always zero in this program)

Cheers.

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Sun Jan 26, 2014 6:11 pm

Okie dokie, so the DT1 MUL...SSG-EG value block has the operators 2 and 3 switched round. I was working from this when I wrote the original program, which doesn't say that.

Here's the fixed version if anybody is curious and wants to quickly poke some FM values.

Aly James
Very interested
Posts: 74
Joined: Sun Mar 31, 2013 11:34 pm
Location: FRANCE
Contact:

Post by Aly James » Tue Jan 28, 2014 3:21 pm

Great! I was working on something similar with SGDK but never finished it :)
Yeah operator 3 and 2 are swapped sometimes in the docs which had caused some confusion...

First, you need to add the LFO on/off register (0x22 bit 3) if not AM and FMS will have no effect.

Also I tried to change TL levels while key on and your code seems to disregard changing here..

SSG registers are also per operator and it would be cool to have!
(you can for example put the "enable EN" column as an horizontal line at the bottom and use this place to put the SSG column instead...)

if you want to go further you could also add these registers for "special modes"
// disable timer & set channel 3 to normal mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x00);

// disable timer & set channel 3 to special mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x40);

// enable timer A & set channel 3 to csm mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x81);

note that : (you might double check that because it is what I remember as is... :) )
//If Channel 3 is in special mode (different frequencies available per operator):
C2 // Operator 4′s frequency is in A2 and A6
M2 //Operator 3′s frequency is in A8 and AC
C1 // Operator 2′s frequency is in A9 and AD
M1 //Operator 1′s frequency is in AA and AE

When in CSM mode, the frequency of the auto note retriggering is controlled by TIMER A (0x24 MSB and 0x25 LSB)

on a last note you could save the current setting in some arrays which could be recalled by the second pad...

I could make you a background just for the fun if you are in 320x240 :)

hope that helps

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Tue Jan 28, 2014 4:16 pm

Yep, I figured it out, but thanks for taking a look at it anyway. I hope it's useful to anybody who quickly needs to be able to test basic static FM voice patches on the real-deal system. I use a free VST called VOPM to do this in Windows (and a free program called vsthost to run the VST like a standalong program), but because I'd gotten the operators switched, my VOPM created sounds weren't sounding right on the system when I copied over the constants, so I figured I needed a patch test program to make sure I was putting the values in correctly.
Aly James wrote:Great! I was working on something similar with SGDK but never finished it :)
Yeah operator 3 and 2 are swapped sometimes in the docs which had caused some confusion...
Whyyyy, Sega? Um... I mean, Yamaha? Whyyyyy?
First, you need to add the LFO on/off register (0x22 bit 3) if not AM and FMS will have no effect.
Yep, that's true. I was thinking of just setting the LFO to enabled and the freq to some arbitrary constant so I had something to work with. Because there's only one LFO, it doesn't make sense to put it in with the instrument patch values array, it would be a per-song setting (if songs were able to set it at all). I don't really want to think about how I'd express that in my player binary format right now, so I'll probably just make it so that if you use LFO, you're getting frequency F and you're gonna like it.
Also I tried to change TL levels while key on and your code seems to disregard changing here..
Yeah, it only loads the parameter set the instant you press the C button, not every X ms. If you're keen enough to get into making your own programmatic envelopes on top of the default FM model, you're probably going to need something more feature filled than this test prog. :)
SSG registers are also per operator and it would be cool to have!
(you can for example put the "enable EN" column as an horizontal line at the bottom and use this place to put the SSG column instead...)
I had no idea that they actually worked! I'm just working from the most easy to read docs, and they say 'nope, zero, ignore it'. If there's a plain English description of what it does so I can understand what it's supposed to do, then I can put it in.
if you want to go further you could also add these registers for "special modes"
// disable timer & set channel 3 to normal mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x00);

// disable timer & set channel 3 to special mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x40);

// enable timer A & set channel 3 to csm mode
YM2612_writeSafe(0, 0x27);
YM2612_writeSafe(1, 0x81);

note that : (you might double check that because it is what I remember as is... :) )
//If Channel 3 is in special mode (different frequencies available per operator):
C2 // Operator 4′s frequency is in A2 and A6
M2 //Operator 3′s frequency is in A8 and AC
C1 // Operator 2′s frequency is in A9 and AD
M1 //Operator 1′s frequency is in AA and AE

When in CSM mode, the frequency of the auto note retriggering is controlled by TIMER A (0x24 MSB and 0x25 LSB)p.
Special channel 3 mode is a bit of a conundrum for me. I can think of uses for it, but every thing my player format supports is another complication in the format. You'd end up with channels musical fm1,fm2,fm3 (which may be 3.1 3.2 3.3 3.4),fm4,fm5,fm6 (which may be DAC), psg1, psg2, psg3 and psgN, all with their own slightly different note on conventions, some programmatic envelope code for the PSG channels, and even more envelopes for sound effects (whichever channels they end up using), with some other state-aware things to allow for the music channels to nicely come back in when the sound effect (s?) expire. (Keeping track of the last desired note as the player cursor comes across it, and only triggering new notes when the channel is clear, and only copying in new instrument patch parameter blocks on note pitch changes OR channel invalidations due to sound effects taking over the channel in the meantime.)
on a last note you could save the current setting in some arrays which could be recalled by the second pad...
I only have one pad though. :P I'm surprised you didn't ask me to save it to PC over a serial link instead. :)
I could make you a background just for the fun if you are in 320x240 :)

hope that helps
Go right ahead :) but I'm not planning on making this into any big thing. I only want to be able to make and test voices on the real system super quick. I'll put up the source tonight so you can just compile in whatever you like, there's no super secrets in here.

Aly James
Very interested
Posts: 74
Joined: Sun Mar 31, 2013 11:34 pm
Location: FRANCE
Contact:

Post by Aly James » Tue Jan 28, 2014 4:39 pm

I am personally looking at it in terms of a quick fun tool, I already made my tools for complete music :)
In case you didn't know I am the person behind FMDrive 2612 VST and SPSG VST :) which is more accurate than VOPM that is YM2151 based...
tracks can be converted into vgm as well..

PM me if you are interested!

>> http://www.alyjameslab.com

btw: SSG looping envelopes definitely works!
I will make a background once you will release your updated version so I can see where is what :)

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Tue Jan 28, 2014 11:14 pm

I had no idea. It's good to know that I'm in the presence of an expert. :)

I only briefly looked at the available FM related tools when I started porting my Master System Z80 player (anybody play Gravity Beam Master Gaiden? :P) to the Mega Drive a few days ago. I wanted the smallest, easy to use option available and unfortunately paying wasn't an option.

I've updated my patch editor with SSG-EG and LFO options. SSG is really clever! I can't believe that something that powerful would simply be labelled 'unused: zero' in any docs...

There's also a new option labelled CONST. If it's enabled, it reloads the FM registers every frame, so you can trigger the note and then alter the options in real-time if you want. If it's disabled, you trigger the note once and the registers stay the same until you trigger the note again.

http://www.mrdictionary.net/stuff/2014/ ... maker2.zip (Binary and source. Assembles with VASM pretty straightforwardly.)

Please excuse the long label names. ;) I prefer the WLA-DX style anonymous +/- labels, but VASM doesn't support them.

Aly James
Very interested
Posts: 74
Joined: Sun Mar 31, 2013 11:34 pm
Location: FRANCE
Contact:

Post by Aly James » Wed Jan 29, 2014 12:24 am

Awesome :)
runs fine in Gens Kmod, crash on Regen (probably rom size..?)
should run fine on hardware, I am going to test it in a few hours.

here is a quickly made background, you can add this if you want
Image

link to background file 16 color 4bit .bmp >> http://www.alyjameslab.com/tempdata/FMe ... r_4bit.bmp

EDIT: Tested on hardware (with everdrive)
-early Model 1 non TMSS = display fine but do not respond to the controller pad or maybe crash internally.

-later Model TMSS = do not display fine, screen mostly filed with cursor tiles all around. do not work either

It should be related to your last v2 added code because the first version loads fine in Regen and Hardware :)

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Wed Jan 29, 2014 2:22 pm

Wow, that background looks amazing! I'll get to work in integrating it right away.

Thank you very much for the test in hardware as well! I noticed that I'd done something that made Regen unhappy, but it worked in Fusion. A Regen crash usually means I've not balanced the stack correctly or somehow executed a bad 68000 instruction. Lots of work to do! :)

I've not yet been able to make rom that works on my own hardware (on my custom EEPROM pcb, not Everdrive). I've seen the 'screen is filled with [ tiles bug' on my PAL Mega Drive 1 when I wrote a simple test code that wrote some text tiles and used the D pad to scroll the screen. The logic, pad reading and scrolling worked, but the screen was filled with [. I'm still working on figuring that out, but it's slow going.

Edit - I'd missed out the .b on one of my instructions, meaning that the 68000 was trying to do a default word-sized access on an odd address. Bang.

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Wed Jan 29, 2014 5:03 pm

This version has the background and won't crash in Regen.

http://www.mrdictionary.net/stuff/2014/ ... tmaker.zip

Aly James
Very interested
Posts: 74
Joined: Sun Mar 31, 2013 11:34 pm
Location: FRANCE
Contact:

Post by Aly James » Wed Jan 29, 2014 5:52 pm

MrD wrote:This version has the background and won't crash in Regen.

http://www.mrdictionary.net/stuff/2014/ ... tmaker.zip
awesome, loads fine and works fine on MD1 :)
If you need or want to improve this at some point, adding pages for CH3 special modes or csm and even CH6 PCM...let me know I will adapt backgrounds.
For now it will be useful to directly test a patch on the hardware without needing a special communication tool like GenMDM or GEMS.!
Image

On a side note, I don't know if the Everdrive is capable of creating a file based on some memory... but it will be awesome if we could dump the FM channel registers as a text file or directly .tfi format (42 bytes), so we could load them later in FMDrive or compatible trackers like Deflemask or VGMM.

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Wed Jan 29, 2014 7:08 pm

Aly James wrote:On a side note, I don't know if the Everdrive is capable of creating a file based on some memory... but it will be awesome if we could dump the FM channel registers as a text file or directly .tfi format (42 bytes), so we could load them later in FMDrive or compatible trackers like Deflemask or VGMM.
I don't know about the regular Everdrive, but on the Mega Everdrive ROMs that are booted in "OS" mode can write files to the SD card.

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Wed Jan 29, 2014 7:11 pm

Where would be the best place to read about that interface?

Mask of Destiny
Very interested
Posts: 615
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Wed Jan 29, 2014 7:31 pm

Krikzz has a small SDK of sorts for the Mega ED on his site. Take a look in the edos.h header in that 7z archive.

EDIT: Fixed link
Last edited by Mask of Destiny on Thu Jan 30, 2014 3:20 am, edited 1 time in total.

MrD
Very interested
Posts: 70
Joined: Sun Jan 26, 2014 4:29 pm

Post by MrD » Wed Jan 29, 2014 7:46 pm

Thanks, I'll take a look. I don't have a MED so I probably won't implement it though.

Aly James
Very interested
Posts: 74
Joined: Sun Mar 31, 2013 11:34 pm
Location: FRANCE
Contact:

Post by Aly James » Wed Jan 29, 2014 8:36 pm

I think I will get me a MegaEverdrive at some point, USB in/out features sounds interesting...
Worth mentioning that Regen or GenKmod can already save dumped channels as .tfi format :)

IIRC the Basic Everdrive features a SRAM save function and will save a .srm file onto the SD card, then it should be a matter of retrieving the relevant 42 bytes of YM2612 data to make a .tfi...

You probably have to enable the SRAM saves option in the ROM header first :)

Post Reply