With bonus - C version of TFM MM music player (*.tfc), which maybe slow (you can fix that by rewriting in M68K asm;) but free from 'not cross bank boundary' limitation.
I already have some thoughts about small improvements of channel manager, which I'll try later (may reduce some sound skips if many effects plays at once, but not significantly).
Temporary link is here.
Making of effects
I used recent version of Mod2PSG2 to make effects (I made all example effects from scratch). Making of effects is same like making music. You must only keep few things in mind.
Use only PAL (50Hz) and 1x divider mode in Mod2PSG2. You can't play 60Hz effects on PAL console, but you can play 50Hz effects on NTSC console (simply by skipping of each 10th frame).
You must separate effects with GG stereo pan change. Converter detects end of effect by two pan changes. I use ST01 ST10 sequence in the end of each effect. Check sfxbank.psgmod file to see how it must be.
If you use channels 2 and 3 (noise), player will always use same channels to replay (because there is only one noise channel, and channel 2 can contain information for noise channel too). If you use channels 0 or 1, player will select one of these channels, depending which one is free. So don't use channel 2 in melodic effects if your effect uses only one or two tone channels without noise.
Don't forget to mute sound in the end of each effect.
Player usage
Check example code. I think, there is nothing to explain (just three simple functions). Don't forget that both PSG and FM players assume that you call 'frame' function at 50Hz. Check 'COMP.60HZ' option in example for solution (lines 60..80 in psgfx.c).
Sound effects bank format
You don't need to know this if you will only use player, but if may be useful if you plan to modify something. All two-bytes values stored in HSB/MSB format.
Code: Select all
Bank format:
+0 2 Total count of sound effects in bank (N, up to 65536)
+2 N*2 Offsets to effects descriptors
+2+N*2 ? Descriptors:
+0 1 Channels count (M)
+1 2*M Offsets to channels
+? ? Effects data
Effect format:
First goes one-byte number of original channel (bits 0..1). Next goes markers:
One-byte:
00xxxxxx - wait xxxxxx frames (1..31) or end of effect (0)
01--vvvv - change volume only (bits 0..3)
Two-byte:
10----ff - change frequency only (bits 0..1 is top bits, then lower 8 bits in second byte)
11vvvvff - change volume and frequency (same as prev. but with volume in bits 2..5)
Channel manager algorithm
Again, you don't need to know this if you will only use player. Manager works that way. Every physical channel has 'slots' - virtual channels (4 in this example). All 'slots' processed simultaneously, output values (volume, freq. divider) stored in variables. After all slots in frame is processed, manager selects most loud ones and sends their values to soundchip. So, loud effects will sounds over silent ones. For tone channels, manager first tries to select less busy real channel. Empty channels selects first. If there is no empty channels, manager take that one which have less slots in use. If there is no empty slots at all, manager replaces oldest one.
Current problems
- Seems that noise algorithm differs on SMD and SMS, because sometimes noise sounds very different in Mod2PSG2 and SMD emulators.
- Hard to make right balance between FM and PSG volumes. I think I'll add export volume scaler into next version of TFM MM.