Let's Design and Build a (mostly) Digital Theremin!

Posted: 5/2/2020 8:18:40 PM

From: Northern NJ, USA

Joined: 2/17/2012

Triple Oscillator With FM

Above is the modified phase modulation (PM) unit.  Frequency is A8 scaled (not shown, a simple multiplication), phase accumulated (NCO), added to the output phase modulation, converted to sine, delayed one cycle (to make it causal you need at least one delay in a loop), and split with the upper branch divided by 2, the lower branch squared, and the two branches cross mixed, the control of which is the odd knob.  Output of the cross mix is fed to a comb filter, and attenuated, giving us the phase modulation output.  The attenuation factor is the input A8 frequency passed through a lookup table (LUT) to scale it, multiplied by the harmonic content to scale it again, then scaled a final time by the odd knob passed through a simple second order polynomial.  The squaring of the sine function gives us the second harmonic and also divides the amplitude by 2.  Note that we're not dealing with the squaring offset of +1/8, as this seems unnecessary in practice.  I like the odd / all sine sources to be phase locked like this, no need to worry about phase offsets throwing the thing out of whack (like several of my previous designs).

Above is the triple oscillator employing three PM units.  The lower two PM units have individual [-127:127] +/-1 octave multiplicative offsets, and share an additive offset control that drives one sharp and the other flat, with different ratios.  The sine and PM outputs of the bottom two units are cross mixed, with the results cross mixed with the sine and PM outputs of the top unit.  The final PM signal is added to the NCO of the top unit and converted to sine to give us an FM signal.  This is cross mixed with the final sine signal to give us the audio output, which is further attenuated and filtered (not shown).  All PM units share a common odd knob, harmonic level knob (which is PV modulated), and octave knob.

Above is the odd knob polynomial procedure.  The harmonic level at the ends of the all / odd cross mix tend to be stronger than the middle, so this polynomial compensates for that.  The odd knob value has its sign bit flipped, which effectively subtracts 1/2 the range.  This is squared, which flips the negative portion up, divides the max by 2, and makes the ends curve up.  The bits of this are negated, which is very much like subtracting it from one, giving us a gain function we can apply to the cross mix.  The ends get 0.75 gain, the center 1.  The LUT was gained up 1.25 to compensate for the gain lost in the polynomial.  This and the LUT are the ugly bits of "sausage making" in the PM unit.

I played around various PV modulation schemes, first I modulated the odd knob, then the fm knob, but neither seemed all that meaningful or profound.  In the end I replaced the PV knobs with bass and treble controls, which seem considerably more useful.  Toyed with the idea of removing the "LEVELS" UI page and giving this real estate over to the oscillator section, but am holding off.

Will post sound samples soon...

[EDIT] And of course I'm repeating semi-failed experiments that I'd forgotten that I did long ago.  The crossfade works OK at maximum harmonic content, but accentuates the middle with lower harmonic content.  So I'm going back to separate all and odd sines and crossfeeding those, and have some more FM ideas to try out.

Posted: 5/6/2020 6:22:24 PM

From: Northern NJ, USA

Joined: 2/17/2012

Triple PM Oscillator

OK, this (finally! pretty sure!) is good stuff:

Above is the new PM (phase modulated) oscillator.  It has the usual all and odd internal phase modulation feedback loops, which share a common externally phase modulated NCO (numerically controlled oscillator = phase accumulator).  The all and odd audio outputs are cross mixed, as are the all and odd PM outputs.  The PM output is registered for use during PM mixing.  I was running out of real-time, so I worked on the harmonic scaling polynomial approach instead of using a LUT (look up table) and really nailed it using only 6 cycles instead of the 15 (max) for the LUT.  The oscillator subroutine itself (which includes all of the functionality shown in the above diagram) takes 77 cycles (not counting external setup & I/O mixing & such).

I spent the day interconnecting three oscillators in various ways, and finally settled on the above.  The PM inputs and outputs form a simple loop; the audio mix is a hierarchical arrangement favoring oscillator 0 (been doing this for a while now).

The rest of my day appears to be going sideways, will post sound samples soon.

Posted: 5/7/2020 8:48:23 PM

From: Northern NJ, USA

Joined: 2/17/2012

FM Woo-Woo

Some samples of the new PM oscillator arrangement: [MP3].  Surprisingly it can do semi-passable squeaky wheel, record scratch, and elephant (eat your heart out Eddie Van Halen!) - as well as the expected buzz saw & UFO invasion type sounds.

I added some odd knob polynomial (as described two posts back) to tame the harmonic level at the ends of the all / odd PM cross mix, which tend to be stronger than the middle.  The strength reduction on the ends is -1/8, and it's not perfect, but it helps.  This is applied to the external FM feeds, not internal (internal is fine because the cross mix is of actual waveforms, not PM).

Lots of the new oscillator bass and treble slathered on (it's weird how super useful bass and treble controls are) as well as the usual resonator pseudo-stereo. 

Posted: 5/11/2020 7:01:35 PM

From: Northern NJ, USA

Joined: 2/17/2012

Spiderweb Tennis Racket In Ray Charles' Head

Don't know why but spent most of yesterday printing another human skull.  This time I picked 15% fill "lines" which go one way for even passes and perpendicular for the odd passes.  The fill isn't necessary for strength, but to support the horizontal beginnings of upper features.  Looks kinda like a tennis racket:

My first skull is on the left, printed 1/2 size.  This new one is full size for the pattern, but still nowhere near human, not even new-born!  The line fill is rather fragile, and you can see some filaments looking a bit ragged after I sanded the two sides flat.  Today I glued them together using epoxy, but I would prefer to use some sort of solvent here.  I used two wooden dowel bits wrapped in a bit of tape and stuck in the holes to align things during the gluing.  I also glued the jaw on.  It's weird watching it form all the details, particularly the teeth.  Took ~8 hours to print, and for some reason I sat and watched most of it.

Very Theremin related!

Posted: 5/11/2020 7:27:32 PM

From: Germany

Joined: 8/30/2014

Now you have til October to install
- orange, superbright LEDs + electronics that make them flicker madly when someone approaches, into the eye sockets
- bonus: manic laughter from a little speaker behind the teeth

Ok ok, not very Theremin indeed, but wouldn't it be neat

The FM sounds: Interesting how the first ones produce some typically PWM sounds of different degrees as found in subtractive setups.

Posted: 5/13/2020 1:46:54 AM

From: Northern NJ, USA

Joined: 2/17/2012

Alas, Poor Yorick(s) (or: The Jawbone Of An Ass)

Some perspective on the relative sizes re. my hand.  So very Thereminy! ;-)

"The FM sounds: Interesting how the first ones produce some typically PWM sounds of different degrees as found in subtractive setups."  - tinkeringdude

Yes, it seems there are all sorts of similarities within simple synthesis.  Manipulating the phase of a sine wave is pretty close to ring modulation, or sync, or even just adding waveforms.

Today I implemented full muting between preset changes.  Much of it is just zeroing out NCO's, filter accumulators, etc. but the trickiest was the inharmonic resonator delay, which took a bit of thought.  So no more "Blazing Saddles" clanging between patches.  I also made the volume, bass, and treble system / global parameters, seeing as how I've got separate sets of these for the oscillator bank and noise generator.

I'm trying to get back to my "UFO TOFU" patch with the current oscillators and I can't seem to nail it.  It's so smooth, and so close to that "Fantastic Planet" Louis & Bebe Barron sound, I'd like to have it or something very similar in the presets.  It's really helpful to make short recordings during your sonic spelunking expeditions, can't leave much to the (and by "the" I mean "my") faulty memory.

Posted: 5/14/2020 10:57:38 PM

From: Northern NJ, USA

Joined: 2/17/2012

Another Day, Another Oscillator

Got an interesting variant running yesterday, nothing super new but the specific take and arrangement are:

I've struggled with the modularity of my oscillator code, and this is the most practical and efficient arrangement of the subroutines so far.

At top is the sine unit, just a phase accumulator, PM (phase modulation) input, and polynomial-based sine calculation, 22 cycles. 

In the middle is the PM unit, which instantiates a sine unit, cross mixes a 1/2 scaled version of the sine with a squared and offset version of the sine, and then comb filters the result.  The squaring doubles the frequency, the offset removes the offset from squaring.  I found the offset to be troublesome to leave in, indeed I believe it caused me to previously abandon this route prematurely.  There is some favoring of the "all" harmonics path via the "odd" control, and some interaction with it and the "harm" control, but I think I can live with it.  This takes 35 cycles.

At bottom is the full-blown oscillator, incorporating a PM unit and another sine unit.  The PM output is modulated by the operating frequency (through a polynomial, to prevent aliasing) and the harmonic level.  The external PM input is cross mixed with the PM output, and this forms the PM input into the PM unit.  The oscillator PM output is the PM input to the sine unit, which gives us our audio.  The PM unit frequency is multiplied by 2, then multiplied by [0.25:1) hmul, giving a range of [0.5:2) or +/-1 octave.  Total is 81 cycles.

Above shows the frequency offsets and audio mixing.  Oscillator 0 and 1 can be additively offset from each other (to give a steady beat between them regardless of pitch), and the internal PM units can be shifted together +/-1 octave via hmul off of the offsets.  This combination gives a lot of swirly / harsh sounds.  Oscillator 2 can be entirely offset +/-1 octave, as can it's PM unit from this with a separate hmul control knob.  Osc 0 & 1 are mixed with a fixed 0.5:0.5 ratio, and cross mixed with Osc 2 via a knob.

Above shows the interconnection of the oscillator PM I/O.  Tried a bunch of configurations, this one seems the most useful.  Breaking the loop somewhere can give mellower results when cranked up, but in the end the difference wasn't enough for me to want to include it.  It's also somewhat problematic breaking the PM loop and still having the knobs remain functional through all possible settings (particularly the osc 0 & 1 and osc 2 cross mix).

The more "normal" knobs are on the first UI page, with all the "crazy" offsets and such on the second page.  This is 6 operator FM, maybe 9 if you count the squaring operation (there are a total of 9 sine waves "in play").  I don't think anyone can accuse the D-Lev of not being able to do buzz-saw / spacey sounds!  You need 3 oscillators to sound fairly complex, anything over that is heading into mush territory.


Some further progress with the new oscillator, and with the noise pulsing code:

- Fixed the odd knob harmonic droop @ center.
- Touched up the fm knob harmonic droop @ center also.
- Noise puls knob now [-63:63], where neg values use NCO + PM.
- Doubled noise puls knob range: 48dB => 96dB.
- Moved osc noise pulse code over to thread 4.

Posted: 5/16/2020 7:47:16 PM

From: Northern NJ, USA

Joined: 2/17/2012

New Oscillator : The Knobbing

Spent even more time perceptually linearizing things:

The top path does a ~, ^2, ~ to accentuate the odd end of the all|odd harmonics "odd" knob.  The center of this is is pulled down to the x axis and squared to give a "bathtub" type response (0 in the center, +1/4 at the ends) which is then multiplied by the harm knob to scale it down with lower "harm" knob settings.  This is flipped to give a "curved roof" type structure (1 in the center, 3/4 minimum at the ends) which scales the "harm" output.  The "fm" knob is given similar treatment, where the center is pulled down to the x axis and squared to give a "bathtub" type response, shifted right twice to divide by 4 (0 in the center, +1/16 at the ends) which is then inverted to give a "curved roof" (1 in the center, +15/16 at the ends) which further scales the harm output over the various fm settings.

This code is now in a separate subroutine which takes 14 cycles.  I know I've said this too many times, but it feels like the oscillator section is finally done.  So of course I'm taking another look at pulsed noise.

Posted: 5/20/2020 4:22:10 PM

From: Northern NJ, USA

Joined: 2/17/2012

Oscillator Changes

It occurred to me yesterday that it might be better to not have a PM (phase modulation) path going through the oscillator, but instead originating (out) and terminating (in):

At top is the new oscillator.  All I did was change the location of the PM_i / PM_o xmix block, which prevents the PM input from making its way to the PM output.

At lower left is the new multi-oscillator arrangement, where osc0 is the main oscillator, and osc1 & 2 each have independent multiplicative pitch offsets (+/- 1 octave), independent harmonic multiplier offsets (+/- 1 octave), and share a single additive +/- pitch offset, one going sharp and the other flat.  The osc1 & 2 audio outputs are summed, then cross mixed with oscillator 0.  I had to remove the OSC level knob to gain another offset knob, but the level is on the oscillator filter UI page so no big deal.

At lower right is the new multi-oscillator PM arrangement, where osc1 & 2 PM outputs are summed and fed to the PM input of osc0, and the PM output of osc0 feeds the PM inputs of osc1 & 2.  Since there is no feedthrough, there can be no looping issues, and the "squeak" sound has disappeared.

A big plus here is hmul and offs are fixed at 1 for osc0, which means the all / odd PM phase is locked to the NCO phase, so you can always get a repeatable basic sound from osc0 even if you've twiddled the knobs some.  It doesn't get quite as harsh as the previous multi-oscillator, but does "wobbly" type sounds better I think.  Overall it seems more straightforward and versatile.

I'm still dicking around with the noise pulse, thought I had a good solution yesterday but it eluded me.

Posted: 5/23/2020 9:09:48 PM

From: Northern NJ, USA

Joined: 2/17/2012

Noise Modulation

Windowing (pulse width modulating, or "bursting") noise at the oscillator rate can make it more "well integrated" into acoustic voices.  Typical examples are the breath that escapes through the vibrating lips of trumpet player, the vocal chords of a singer, or the scraping of a cello bow across the string.  The phase is important, you want the start of the noise burst to coincide with the high harmonic content portion of the oscillator waveform (i.e. where the waveform has the highest slope).  Also important is the width of the active window, and to a lesser extent its envelope.

For weeks now I've been playing around with various approaches to noise modulation, and some seemed promising but all ended up dead ends until today.  What you need in order to do this sort of business is a waveform that is properly phased to the oscillator NCO with a stable amplitude, and I finally realized that the oscillator PM signal is the ideal candidate:

Above is the PM signal (post comb filter, pre harm attenuation).  When the harmonic content is zero you get a sine wave.  When the harmonic content is increased and the odd control is minimized you get a rounded sawtooth.  When the odd control is maximized you get a 2x frequency rounded sawtooth that is biased up.  I thought the -1/4 odd bias removal was important to the all/odd mixing, but now know that it isn't, and not removing the bias is necessary to obtain the above waveforms.  Notice that all waves touch the +1/2 point regardless of harm or odd setting.  If we invert the most significant bit this makes the wave unsigned and places the maximum at 1.  Inverting all the bits flips it down to the x axis, where we can apply gain to make it shrink or grow, and then use it subtractively (in the linear domain).

Above is the current noise modulation scheme.  The upper main section simply modulates the overall noise envelope with the volume and pitch axes.  The lower section is new, and uses the PM process just discussed.  We modulate the flipped PM signal with a knob that sets the static PM gain, and vary this with the volume axis number.  This is subtracted from the noise level, exponentiated, and used to finally modulate the noise level.

It's working well!  For the trumpet sound I can get that transition between just breath to breath and lips vibrating to all lips.  Will post a sample soon.

[EDIT] It can be a bit confusing switching between the linear and exponential domains, but it's nice to have that option, and you do indeed have that option when doing this stuff digitally.  Exponents and logs can be done in analog, but it tends to be a fiddly, expensive, temperature sensitive, pain in the ass.  So many things are much more straightforward to do linearly and then finally exponentiate.

Here's a trumpet sound with the new noise modulation: [MP3].  Pulsed noise is one of those "incidental sounds" that actually degrades the purity of the voice, but can add to the realism if not applied too heavily or robotically.  There are levels of usefulness to these sorts of things, guitar fret noise being somewhere near the bottom I suppose (though if you're on the fence about whether you're listening to a real or synthesized guitar, a bit of realistic fret noise might push you over to the edge, though a bit of fake sounding fret noise will definitely pull you back, and for good).

You must be logged in to post a reply. Please log in or register for a new account.