I have been investigating the issue in more detail. My approach was to hack into the code using the software installed on WindowsXP and using the Syser debugger. I can setup the Moog synth to generate 32 polyphonic voices that play continuously, and this bogs down the cpu. Then I can interrupt the system with the Syser debugger, and the chances are very good that at the moment of interruption the cpu is busy inside the number crunching of the Arturia synthesizer.
Here is one section of code I dug into:
001533F0 8B 56 38 mov edx, [esi+0x38]
001533F3 F3 0F 10 0C 8A movss xmm1, [edx+ecx*4]
001533F8 8B 54 24 20 mov edx, [esp+0x20]
001533FC 0F 5A E1 cvtps2pd xmm4, xmm1
001533FF F2 0F 59 E7 mulsd xmm4, xmm7
00153403 F2 0F 5C E7 subsd xmm4, xmm7
00153407 66 0F 5A E4 cvtpd2ps xmm4, xmm4
0015340B F3 0F 58 24 83 addss xmm4, [ebx+eax*4]
00153410 F3 0F 11 24 83 movss [ebx+eax*4], xmm4
00153415 0F 28 E0 movaps xmm4, xmm0
00153418 F3 0F 59 E1 mulss xmm4, xmm1
0015341C F3 0F 5C E0 subss xmm4, xmm0
00153420 F3 0F 58 24 82 addss xmm4, [edx+eax*4]
00153425 F3 0F 11 24 82 movss [edx+eax*4], xmm4
0015342A 03 4E 30 add ecx, [esi+0x30]
0015342D 40 inc eax
0015342E 23 86 DC 02 00 00 and eax, [esi+0x2DC]
00153434 3B 4E 40 cmp ecx, [esi+0x40]
00153437 7C B7 jl 0x001533F0
Notes: In the cases I explored:
[esi+0x40] is 0x4000
[esi+2dc] is 0xff
[esi+30] is 0x200
A typical value for ecx on entry is 0x2d14.
There is a 16384 entry table of single precision floats pointed to by [esi+0x38]. The table is a precomputed square wave with about 15 overtones, but it includes only from 25% to 50% of the complete cycle. That is, if we're dealing with a waveform where the first 50% is at one extreme and the last 50% is at the other extreme, they only bother to store the central 50%. The stored waveform gets scanned in reverse to generate a complete waveform.
Just to make that clear, in the case of a cosine wave, going from 0 to pi takes you through the entire range of +1 to -1. If you've stored a cosine in a table, you don't need to store the values from pi to 2*pi, you could just scan your table in the reverse direction to go from -1 to +1.
Their table consists of the transition of a square wave from the minimum value to the maximum value. It starts out flat then we see some ringing, then it sweeps to the maximum value with ringing, then the ringing dies down. The low value centers aroung 0.0, and the high value centers around 1.0. That is, the range goes from 0 to 1 as opposed to +/- 1 or +/- .5, which I found odd. I'd have expected a waveform to be centered around 0... Here's an image:
Now it's important to note the waveform only has overtones up to around 15 times the base frequency. I counted 7 minima on the left half. I located other similiar waveforms stored but they're even bigger (more than 16384 samples) and can have fewer overtones. So it's clear their approach involves waveform tables but they carefully eliminate higher frequencies in order to avoid the aliasing issue.
I'm uncertain exactly how Arturia uses the stored transition table. I didn't find any other recognizable waveform (sine, pulse, triangle for example) although I looked. It did occur to me they could create a pulse of variable duty cycle by just sitting on a steady level for some arbitrary time before sweeping through the waveform data. They can also create a triangle wave by sweeping slowly through the transition part. But I didn't confirm they're doing this approach.
My take, though, is they're not doing anything magical about emulating the analog circuitry. I had hoped there was some deep insight into the theoretical side that I could learn, but I'm no longer convinced they're doing anything impressive. The key insight I'm convinced of is that they make sure there are no high frequency components introduced into the waveforms in the first place, so there is no chance for aliasing. My attempts to synthesize audio all had that problem, as I never realized one has to avoid that issue.
Example: Suppose you've got a sine wave table stored in 1024 samples. It repeats, so you can generate a sequence of audio samples by just stepping through your table and outputing the samples to a digital to analog converter and then to an amplified speaker. You can change the frequency by changing your step through the waveform.
It ought to be clear that this will work fine as long as your step is comfortably less than 512 samples. But if your step goes beyond 512, the effect is to create an alias frequency instead of the intended frequency. I believe the step would be identical to 1024 minus the large step. So a step of 600 would be as if your step is 424. Essentially you're stepping backwards through the sinewave table instead of forwards, but that's irrelevant since the sine is symmetric.
Now if your waveform table has higher frequency components, say a sine at 2x the base frequency, you can't use any step bigger than 256 because *that* would cause aliasing distortion. The limits get worse very quickly as you add higher frequency components into your wave table. If you've got an 16x frequency component, you can't even step more than 16 samples at a time, which is small compared to the 512 step we were permitted with the original sine wave.
Digital filtering is very easy in terms of cpu power. A 2 pole butterworth filter involves just a few multiplies and additions. The moog synthesizer worked by having various oscillators (sawtooth, triangle, sine, pulse/square) which were then fed through a low pass filter where the cutoff frequency changed with an ADSR envelope. I believe if you create your oscillator sources carefully without introducing alias distortion, performing the final digital low-pass filter is trivial and won't introduce any distortion itself.
My error was always in ignoring the introduction of unwanted aliased noise frequencies. Avoid that and the sound will remain perfectly clean. The rest of Arturia's software is just detail, as in user interface and whatnot, as well as an attempt to replicate the behaviour of the real moog synthesizer precisely. That's not something I'm so hung up on. It is very easy with a little bit of coding to create moog-like sounds.
Hope this comment is useful to someone.