Yamaha DX7 chip reverse-engineering, part 6: the control registers
righto.com
righto.com
Being latency sensitive here is definitely key.
> The digital implementation of frequency modulation starts with a lookup table that holds a digitized sine wave.
> The next step is to modulate the output by adding a modulation signal to the index.
In those paragraphs, you're saying that you start with a table of sine-function values.
This table has (for the sake of example) 4096 different values. I suppose in real life there may be many more.
then you read this table by incrementing an index between 1 and 4096. this happens many times per second and every time you increment the index by one unit. This will output a sine wave at a specific frequency determined by how quickly you increment this index (i.e. how often the table is read out).
So far alright, if you're adding 1 to the index 40960 times every second you'll a sine wave with a 10hz frequency (is this correct?)
but then, instead of adding 1 to the index 40960 times per second, you add 100 every single one of those 40.1k reads of the table? and this generates a sine with a frequency of 1000hz!?
this is quite frankly very surprising to me. The kind of thing I don't see myself coming up with easily; referring to the fact that it's possible to change the output frequency just by jumping around the table (instead of reading it all out one by one jump the index by 100 table entries) while keeping the number of times per second the table is read the same.
Finally, if the index increments themselves are read out from another sine wavetable, you get FM modulation... this is more reasonable but it depends on the previous very surprising (to me) way to change the frequency of a sine wave.
thanks for the great write-ups.
One additional thing about the DX7 index is that you can think of the index as having 10 fractional bits, so you have much more accuracy in the increments. Otherwise, the frequency resolution is pretty bad because the frequency changes in big jumps when the index step changes by 1.
In practice it's common to have non-exact sine/etc. waves, or not advance by an integer number of waveform samples on each output sample (generating output samples using various interpolation methods), both of which introduce high harmonics which get aliased to the wrong output frequency.
For more information on discrete-to-continuous frequencies and reconstruction, you can watch Xiph's "Digital Show & Tell" (https://xiph.org/video/vid2.shtml).
If we let t be time in seconds, and f be frequency in Hz, the sine wave formula is y = sin(2pitf). The 2pi is the periodicity of the sine function. If f is 1, we sweep through 2pi once per second. If we let f be 2, then it sweeps through two times per second, and so on.
So, you can think of the lookup index as being the tf part, but with t counting in integer fractions of a second, with the caveat that you'll want to perform some interpolation between values.
If the waveform were more complex than a sine wave, then in the general case this "skipping agead" could cause distortion. A sine wave is one of a couple special cases (square wave being another, and arguably it's "cheating") where you're not skipping "too far" to cause distortion. (That relates to the Nyquist sampling theorem and low-pass filtering, as kens mentions)
In practice, only the first few odd harmonics are strong enough to really matter, but with a high-pitched square wave you still need oversampling and lowpass filtering to get rid of those in the general case without aliasing[1].
However, if you choose the frequency of your square wave right (to make the sample rate an integer multiple), the aliasing products will just be reflected back to be exactly on top of the "actual" harmonics, neatly sounding like a perfect square wave again (in theory). Matching well with our intuition of what happens with the actual signal, if you do the "skipping" for such a square wave.
[1] Or maybe not if your goal is really only generating square waves: Just don’t generate these harmonics. Your 16kHz square wave without aliasing will just sound like a sine wave anyway, because your ear cannot hear its harmonics.
You can then use that to:
- verify that the emulators indeed get it all correct
- test your assumptions about how you thought it worked
- maybe program it to do things it wasn't strictly speaking meant to do
4 times the DAC frequency.
Or, actually, 49096 * 16 * 4
http://yates.ca/dx7/Schematics%20&%20PCBs/DX7%20Schematic%20...
Top right of the diagram.
To me, you give up a little in basically sound quality(and that is probably debatable or depends on your taste) for a massively improved programming interface.
You can't go back to a hardware interface after that unless you just want to stick with presets.
--
So the chips allowed multitimbral operation, but the DX7 didn't support it?
This demonstrates the factory patches; the train patch (#31) seems to have several different distinct timbres: https://www.youtube.com/watch?v=F3rrjQtQe5A