opl3_fpga
opl3_fpga copied to clipboard
[feature request] User-defined waveforms
The OPL3 core has 8 hardcoded waveforms in ROM. It would be great if a small improvement could be done to this core: to allow the programmer to rewrite the waveforms with new ones at any given time, just like the Konami SCC/SCC+ soundchips (and the similar PC-Engine soundchip). This way much richer sounds could be created at very little additional cost.
Expand E0h~F5h register to allow 16 waveforms, or even 256 waveforms wouldn't be bad too.
Backwards compatibility would be maintained, since the usual waveforms would be loaded on reset, and existing software could even take advantage of the new waveforms if the user loads a new set of waveforms before running the old software.
References: http://en.wikipedia.org/wiki/Konami_SCC http://en.wikipedia.org/wiki/Konami_Sound_Cartridge http://bifi.msxnet.org/msxnet/tech/scc http://bifi.msxnet.org/msxnet/tech/soundcartridge
Some clarification on the 6 waveforms in the OPL3:
- There are only two ROM tables in the OPL3: 1/4 of a log-sine wave and an exponential function
- The first table is used for all sine-based waveforms, taking advantage of quadrant symmetry to reconstruct a full period the wave (this is common to most direct digital synthesis implementations).
- The second table is a trick to avoid multiplication in applying the gain, as well as for the exponential waveform
- The 6 waveforms are created using simple mathematical manipulation of values from these tables
There is a lot of block RAM left in the FPGA for introducing new waveforms. These block RAMs can be configured as ROMs using hardcoded values, which is how the two existing ROM tables are implemented (see https://github.com/gtaylormb/opl3_fpga/blob/master/fpga/modules/operator/src/opl3_log_sine_lut.sv for an example). The easiest way to implement additional waveforms would be to hardcode them in the same way, then introduce an additional register to select them.
I think what you want however is the ability to write ROMs after FPGA configuration using a software interface. This is a fairly more complicated approach from a hardware standpoint. Definitely a cool project idea.
Thanks for your quick reply!
I've read the nice "OPLx decapsulated" document some time ago, and was aware that the waveforms were stored somewhat compressed in the ROMs. Very nifty! :)
You deduced it correctly: I would like to allow client software to write new waveforms using a software interface. This single modification is able to vastly improve the OPL3 capability of producing incredible synthetic sounds. I wonder why Yamaha themselves haven't done this for the FM block of the OPL4.
Keeping all that and the backward compatibility in mind, I humbly suggest the custom-waveform extension to be implemented in the following way:
-
Modify the engine a bit, to play all waveforms uncompressed, from RAM instead of the ROM. Each waveform should be 1024 words long. (thus 2KB)
-
Expand the E0h~F5h registers (Waveform select) to allow selection of as many waveforms as the FPGA has enough RAM to contain, up to 256 IDs.
-
Upon reset, the original OPL3 waveforms are decompressed from the waveform-ROM to their respective positions in waveform-RAM.
- To support badly written software that write garbage in the bits 3~7 of the Waveform select registers, the extra waveforms (IDs > 7) will be filled on reset with the ROM contents of the waveform-ID & 7 waveform.
- To allow client-software to modify the waveforms in RAM, 4 new registers must be created
1FCh: Set the waveform address LSB 1FDh: Set the waveform address MSB (bit9~bit10) 1FEh: Select the waveform to be written. 1FFh: Waveform data (LSB, then MSB). Each MSB written here will autoincrement the waveform address
Of course this is only still a draft, maybe there are some issues that I'm not aware. Feel free to throw your tomatoes. :)