audio quality: max 5 vs max 6, max 6 vs supercollider
Hi everyone,
I've been a max user for years, and I currently use max 5. I've noticed that when I'm doing complex signal rate modulation and filtering, I get lots of undesirable crunchy artifacts -- the synthesis just doesn't sound as good as supercollider. I've been thinking of giving up on max and trying to learn supercollider instead.
But then I learned that max 6 has improved the resolution of their msp objects. Does it sound a lot better? How would you compare max 5, max 6, and supercollider in terms of sound quality for synthesis purposes?
I tend to think that Max 6 sounds better than Max 5. If you're interested in modulation synthesis, then gen~ is a real asset, and you'll also see improvements in cycle~'s sound quality due to the substantially larger table. You'll also find that there are additional filters available to you (shameless plug for free PM.Ladder~)
I can't personally speak to the differences in sound quality between Max and Supercollider. Maybe several years ago it was more of a difference--I've heard some gearheads say that they could really hear it, but their music was also terrible, so...---but I feel Max is pretty capable, and I'm pleased with the results that I get out of it, though I'd add the caveat that the sound quality that you get out (of Max or anything else!) is going to depend on the algorithm that you use. You can certainly do ringmod just with a cycle~ and a *~, but it's going to sound a whole lot nicer if you remove DC offset and upsample it in a poly~ to reduce aliasing. Upsampling will also improve the clarity of FM. You can do a ton of stuff now with gen~. What sort of synthesis are you trying to do? (and any patches you care to post?) I find that little things often make differences; for instance, I prefer exponential amplitude envelopes to linear ones.
Assuming the sound quality is pretty similar, I'd say the major reason for choosing one over the other has to do with workflow. Max encourages happy accidents and experimentation, and I think that's really an asset. I think the important thing is to work with a tool that works well for you.
upsampling is for most processing situations the key, it is far more important than the step to 64 bit audio.
I haven't experimented with upsampling at all -- and yes, my ring mod is just two inlets, a *~ and an outlet and it sounds like garbage :)
The material I'm currently working with is a personal library of objects that all accept signals from -1. to 1. and operate on the metaphor of an analog modular -- all objects have inputs and outputs in the same range, whether they are intended as audio or "control voltage." I open up these modules in bpatchers and then route them around through a matrix~. One of the situations in which i notice bad quality audio is, for example, when I have one vco modulating another vco in the audio rate (a kind of FM).
I'll attach a couple of problematic modules -- the vco, vca, and the wavetable module -- that i've noticed as liable to generate undesirable artifacts. I'd appreciate any suggestions for improving their performance.
Any tips on getting into upsampling? where can I learn about how to do it?
It depends on which oscillators you're using, but saw~, rect~, and tri~ don't handle frequency modulation well, though you can improve the performance with a smaller signal vector size (see below for a tip on this). There are, however, ways of building oscillators that do, but it's definitely something you'd need to do in gen~ or C. I've posted about that topic before, so you might check some of my previous posts for research/patches. (I posted a pwm oscillator that can be modulated at frequency rate)
Your lookup~ patch could really benefit from a larger table. Also, if you do the lookup inside of gen~, you have a lot more options for interpolation. You're going to create a lot of noise with your wavetable if you use functions like the current one. It's got a lot of discontinuities and those produce noise.
The point of upsampling is to provide extra headroom for aliasing. If you do your processing at twice the sample-rate, the aliasing will start twice as high up, and it makes it easier to filter out. (Max does this automatically for you in poly~)
Upsampling in max is actually really simple. Just put whatever code you need to inside a poly~ voice (using in~/out~ etc.; you don't have to worry about thispoly~, since you're only going to use 1 copy of it anyways) and provide the argument "up n", where n is a power of 2. (e.g. 2 for 2x oversampling)
What's going to happen is this:
poly~ takes its input, samples it a higher rate (using upsampling filters (?)), does the processing (e.g. FM, ringmod, what-have-you), then applies a downsampling filter which removes frequencies above the Nyquist frequency for your main patch (e.g. anything about 22050 if your main samplerate is 44100). All you have to do is tell poly~ "up 2", which is damn handy.
In addition to upsampling, note that you can also run a different vector size within a poly~ patch. Saw~ updates its frequency once per vector, so making the vector shorter will make your FM more responsive, though it will make your patch more CPU-heavy.
Just as a follow-up to what I wrote: this will improve the FM, but it's not going to be perfect by a long-shot with the antialiased waveforms. There are tricks, however, where you can use already bandlimited wavetables (e.g. only the first 8 partials of a sawtooth) for FM and that can work quite well. In general, FM with complex waves is a recipe for noisiness and aliasing, since you're going to get A, A±B,A±2B, A±3B, A±4B, etc. for your sideband formula, which will get noisy quick...
tanx peter, this is a really informative discussion!
so i don't have to apply my own downsampling filter with the max 6 version of poly~?
Thanks so much, Peter and Roman. I think I just made a successfully upsampled version of my vco -- take a look below. It already sounds somewhat better to my ears.
I'm going to have to see about eliminating my tri~, rect~, and saw~ oscillators now. :(
peter, any idea about how I could find or create the band-limited wavetable you mentioned above? I guess I have to get hold of the appropriate sound file somehow and simply play it in a cycle~?
You can build them by adding up sine waves. I wrote a java object to do it, but javascript would be easy, too.
Alternatively, you could do an all-Max solution via vexpr like this:
Also, you don't have to provide your own down-sampling filter. Tim Place has worked hard to implement some high-quality downsampling filters so you don't have to...
i'm super impressed peter, but those buffer generators aren't working for me...
Are you on Max 5 or 6? If you're on Max 5, you'll need to set the length of them using the "sizeinsamps 8192" message. (and the @samps attribute I think is pretty new)
yeah, i am on max 6.05 (just upgraded from max 5 today) and i'm getting this message in the max window:
buffer~: "samps" is not a valid attribute argument
maybe i need 6.07? weird that i didn't get the newest version if i just got it today from the cycling74 site.
But I sent the message to resize the buffer as you suggested and IT TOTALLY WORKED. you're a genius.
6.0.7 is not out yet. 6.0.5 is the last public release.
@ peter : Thanks for your explanation.
I wanted to try the up-sampling thing but didn't really know how to start.
Here's a Max 6.0.5-friendly version.