Square wave FAIL

dnealelo's icon

I'm trying to build an additive synth (sort of a learning project as well as, eventually, a useful instrument). By way of testing my design, I want to output a square wave by summing sines, but I can't seem to get it to work. I have the [cycle~] objects set up so that their frequency represents a harmonic, e.g., 1st is fundamental (first harmonic), say 100Hz, 2nd is second harmonic at 200Hz, etc., up to the 25th harmonic. The amplitude of each of these is set to alternate between zero and 1/h, where h = the number of the harmonic, e.g., the third harmonic is 1/3 the amplitude of the first/fundamental. It is my understanding that this is how one builds a square wave out of sines (see, for example, http://en.wikipedia.org/wiki/Square_wave#Examining_the_square_wave).

Max Patch
Copy patch and select New From Clipboard in Max.

What I'm getting is not a square; it's weird, more like a triangle than a square wave, and clearly wrong. I haven't been able to figure out where I'm screwing up, so I built a simplified version for troubleshooting and it illustrates the problem well.

I've only used the first seven harmonics here, just to keep it simple, but, as I said, the math replicates what I'm doing in the more elaborate synth patch. You'll note I inserted a [rect~] object as a comparison, to make sure there wasn't something I was misunderstanding about how to use or read a [scope~].

Can anyone tell me what I'm doing wrong?

Chris Muir's icon

I don't have time to look at your patch right now, but I have an example of this sort of thing, called PartialWorkshop that can be found here: http://xfade.com/max/examples/

leafcutter's icon

I wanted to see how this should work so I had a look at http://www.mathworks.co.uk/products/matlab/examples.html?file=/products/demos/shipping/matlab/xfourier.html to get things straight in my mind. I put their code:

y = sin(t) + sin(3*t)/3 + sin(5*t)/5 + sin(7*t)/7 + sin(9*t)/9;

into gen~ and checked it with scope~ then tried to engineer it with regular max objects.

Try it out...

Max Patch
Copy patch and select New From Clipboard in Max.
Chris Muir's icon
Max Patch
Copy patch and select New From Clipboard in Max.

OK, I finally had a look at your patch. The issue was phase. cycle~ objects start rolling phase as soon as they're created, so adding them as you were doing is borderline non-deterministic. Here's your patch with phasor~s added so that the oscillators can be brought into sync.

dnealelo's icon

Leafcutter: Thanks much for the breakout/illustration patch. That confirmed that I had the math right.

Chris: I looked at the PartialWorkshop patch on your site and dug down to where you had the sine stacks (64 harmonics: nice!). That was useful, but your modification of my patch nailed it -- thanks very much! I played with a bit to see if I understood what was happening and, as an experiment, I removed the [phasor~] objects and sent the phase synch directly to the [cycle~] objects; it had the same effect. This is useful given the design of the synth on which this patch is based. So that clearly solved the problem.

But, I want to clarify my understanding of what you did: I see that you synched phases of the [cycle~] objects by sending the output of the [phasor~] objects to the [cycle~]'s right (phase) input, but I'm not sure I understand why that works. First, wouldn't the ramp wave of the [phasor~] cause the phase of the [cycle~] output to shift back and forth from -1 to 1 at the frequency of the [phasor~]? Maybe this is the same as restarting the sine every [phasor~] cycle? If so, why does this not introduce sharp "edges" to the sine (I am assuming it doesn't because the square waves look and sound right).

More broadly, you can probably see that my questions reflect my lack of understanding of the nature and uses of the [phasor~] object; I thought it was a ramp wave generator like one would find in an analog synth, but I see it used all over the place for timing applications, as you have used it here (and the maxhelp for the object indicates that it's better for that than for audio applications). So, do I understand correctly then that hooking up a [phasor~] to the phase input for wave-generating objects is a general-use means of synching them?

Regardless, thanks again for your help and input.

dnealelo's icon

Update: I took this information back to the actual additive synth project and attempted to plug it in and it didn't work. It turns out there were two issues that the simplified model did not replicate (even though its output was the same as the big project). The first was that the two default phase settings I had were the two that would produce the waveform I was getting: 0 and 0.5. Chris used .75; this, along with .25, will produce a square waveform. (I didn't know this -- my math basically stops at statistics.) The second issue was a pretty embarrassingly rookie mistake: I was dividing the output of the gain sliders by the harmonic number, but gain sliders are non-linear. As a consequence, the harmonics were way below the amplitudes they need to be to produce a square wave. With the phases synched at .75 (or .25) I can now tweak the sliders by hand to produce a square wave. I'll need to rethink how to get the sliders set correctly (i.e., not by hand), but this answers the question of what was happening. Thanks to both of you for your help.