The wave conversion tool is up and running and looping support is working flawlessly. It’s forward looping only, but I’m gonna add ping-pong loop support soon. Ping-pong support will be hard coded into the wave, since it’s too much cpu overhead, or work, to change how the PCM frequency driver works.
So the tool outputs a specialized format for the player with a small header containing the loop points. Looping on the player side doesn’t take any additional cpu resource, which is nice.
Did you know that Batman on the PCE does precalculated frequency scaled waves of a single bass guitar instrument, and actually has a loop point section? There’s the attack part and the loop part of the waveform. It means a tiny sample can be made out to be a really long sound. IIRC, there’s 2 octaves which means a total of 24 notes or 24 samples. It gives the bass guitar instrument a nice punch-y sound that the normal PCE channels just quite don’t reach when emulating/modeling it (although they do a good job).
Anyway, more on the player itself. So octaves follow a formula of 2^a, with a being the octave. This means the rate of change is increasing in between octaves. Notes are section of frequencies along with octaves, and they are also part of that 2^a format, except they exist in between octaves ranges. It now becomes something along the lines of 2^(a+(b/12)), with b being the note (ranging from 0 to 11). The frequency difference/distance between each note increases as the frequency increases. It’s not linear.
Since octaves are an exponential function with a base of 2, I can simply binary shift the frequency to get my octave range. Therefore I only need to store 12 note frequencies in a table for once octave, and the rest can be derived from there. But I need more than just notes and octaves; I need to be able to slide a frequency up and down. So I increased the table from 12 notes, with 32 frequency steps between each note – for a total of 384 entries. Still not bad. Not only do I now have frequency sliding control with precision that I can track, but I now have a method of fine tuning as well.
It works like this: O:N:S. O is the octave, N is the note, and S is the step. S ranges from 0 to 31, any carry/borrow gets added/subtracted from N. N ranges from 0 to 11 and carry/borrow affects O. O ranges from 0 to 7, with 3 being a 1:1 or rather no binary shifting. I build the frequency divider from O:N:S number, but I only need to do this when there’s a change in frequency. And when it is performed, it’s pretty fast. There’s no multiplication: only one table fetch, a few shifts, and one addition (finetune). The other nice thing is, all inter-note frequency steps are the same ratio for any octave. So if you do a vibrato effect, it has the same strength if the note is high pitch or low pitch – unlike period based music players that rarely ever compensate for this. Under period based players, this presents a problem if you have an instrument where you have vibrato effect going on and you want to slide (portamento-to-note) to a higher frequency note – that vibrato effect that sounded perfect might sound too extreme at a higher frequency. You would have to compensate by having a function scale back the vibrato strength while going up in frequency, and this would be trial/error (I have yet to see a music driver do this, but it’s doable). So this resolves that issue.
Anyway, the player (driver) is done but I’m building what amounts to a small music engine to demo it off. So that takes time. Plus, I’m trying to modularize this into sections; the driver, interface support, music engine example. I need to keep them all separate so it’s easy to pick and use just what you need (assuming anyone uses this).
Do I expect this to revolutionize the PCE sound? No. This is more of a proof of concept. There are definitely strengths and weakness of this approach. Some samples will sound dirty, or unpleasant, so it really depends on the sample itself and I believe that puts a limit on how useful this is. The 5bit resolution of the PCM is also another issue; for some samples it’s fine and for others it can be hiss-y or noisy. Techniques like 1 or 2 point (difference) volume-map to keep noise at a minimum might help, but it really depends on the specific waveform. That said, I think the 6bit PCM player (the other approach) has more promise than this, but this approach, this player, is simpler in both execution and interfacing. I’m also reusing some stuff here for that other driver.