tirsdag 20. januar 2015

On voltages and other practicalities

While dreaming up the OMM I have for some reason constantly kept thinking about the output from the DACs as 5V, with a OMM value of 0 corresponding to 0V and 65536 to 5V while at the same time intending to use a 1V/octave VCOs and having the pitch CV controlled from the OMM.

This, of course, leads to a severe limitation: the synth would not be able to span more than 5 octaves, and no tuning or modulation would be possible for the highest and lowest notes.

There are a few different solutions to this problem:

1) one could use a separate output as octave selector. By keeping this at 2.5V normally, we could add or subtract 2 octaves and still have 0.5V left for tuning and modulation. This will however lead to having to do some tricks when receiving notes outsidere the normal 5 octaves.

2) one can use 10V instead of 5V for the DACs. This gives us the same 10 octaves as adding an octave selector CV. However, this requires a redesign of some modules such as the VCA.

3) one can change the input resistor on the VCOs so their response is 1/2V per octave, again giving us the same 10 octaves.

I am not sure which one to choose. I will have a closer look at how other midi-2-CV converters do this.

I also need to figure out how many octaves to support. If it should be possible to do one-octave pitch bends 10 volts only allows 8 full octaves, and even then other modulations and tuning must be kept separate.

LFOs and modulation

Our numerical LFOs will have an amplitude from 0 to 64k. But when using the LFO to modulate the pitch CV, to get a vibrato effect, we want it to increase the pitch for half the cycle and lower it for the other half. In essence, we would be better off using a signed int. In other cases, and for other operators, we are only interested in the positive parts of the waveform. And in any case the DACs would normally only output a single-polarity signal (though this can be fixed).

Again, I need to check how others are doing this.

Other things to think about when it comes to LFOs is that it should be possible to adjust their starting point and direction (up/down), as well as to choose whether or not to reset the cycle at the start of a note and to sync it to an external clock.

Multiplication vs attenuation/scaling - virtual VCAs

I've realized that we need an additional function, one that treats the inputs like they are between 0 and 1 when multiplying them. This is analogous to how a VCA works, when the CV is at max, the output is the same as the input. When the CV is half of its Max, the output is attentatet by 50% etc. In other words, the output is scaled depending on the CV, between 0 and 1 times the input.

mandag 19. januar 2015

Ramp generation

If the running time of the matrix calculations is constant and triggered by a timer, generating a ramp is simply the task of adding the same number to an accumulator variable every cycle.

But since the number added is never exactly the number necessary for a correct ramp progression (we are dealing with integers after all), we will accumulate an error. This may be ok, but we should keep control of how big the error may become and take actions to prevent it from becoming too big.

If we work with 16 bit numbers, we will get an error of maximum 1/65536 per cycle. But assuming we are running at 44.1kHz, this will accumulate to an error of 44100/65535 = 67% in one second! Not very accurate I'd say.

Lets do the cslculation the opposite way. If we decide that yhe maximum acceptable error is 1% per second, what resolution do we need for our interval?

Well, in one second, we should be at most 0.01 * 65536 = 655 away from the correct answer.  At 44.1kHz, this means that the maximum error per cycle must be less than 655/44100 = 0.015, or 1/67th of the error we get from using an integer.

To remedy this, we may store the accumulator and the value to add as a number with more bits (in doing this, we will multiply the interval, or rather, calculate it differently) and divide the accumulator down to 16 bits when the output is needed.

To get the necessary precision we need to be able to store 1/67ths. By adding 6 bits to the number we can store 1/64 fractions, which is not quite 1/64 but may be good enough, or we can add an additional two bits and get a 1/256 precision, making the accumulator and interval variables 24bit (it may be practical to make them 32bit while at it, not sure).

Converting the accumulator back to 16bit is simply a matter of shifting it 8bits to the right.

Looping or multi stage ramps (envelopes)

When the ramp reaches the desired height, we want to stop adding to it, reset it or even start subtracting from it. This means that every time we have added something to the accumulator, we should check its value and possibly perform an action. We may even have to keep track of state, as what stage of an envelope we are in. The state, as well as the accumulator and value to add should be stored within the ramp node's struct if we want a truly node-type agnostic algorithm that lets us have any number of any type of node (unlike the Matrix 12 which has a fixed number of ramps, LFOs etc).

Maximising clock speeds

Just a short note on chrystals, clocks and instructions. On the PIC24 and PIC32 you have very high maximum MIPS, million instructions per second, counts. To reach these speeds, you should not use an extremely fast chrystal. Instead, you use what is called a PLL, phase locked loop module that is found within the mcu. This expects an input clock of between 4 and 5MHz, but multiplies this to get a much higher internal frequency. You may use a faster external chrystal, but this has to be divided down to be in the interval that the PLL expects by a prescaler (also found in the mcu).

Polysynth voice controller

The hardest thing right now is getting hold of paper. Fake t-shirts, booze and other crap, no problem, but finding a decent notebook is nearly impossible in the town of Patong. I found this at last (the killer bunny in the background is the daily art left by the cleaners):

So, we've looked at some of the tings we want to do on the voice card mcu, but what mcu should we use?

We have some initial requirements:
- dual SPI/I2C interface
- data flowing through the matrix should be 16 bit
- we want the run-through of the matrix to be fast to achieve a high output update rate, maybe as close to 44.1kHz as possible.

This last requirement may not be possible with "home made" samle and hold outputs but let's for the moment assume it is.

So far i have almost exclusively worked with the Microchip PIC16 and PIC18 MCU families. These are 8 bit, but it is still possible to work on 16 bit numbers. However, when it comes to multiplication of 16 bit integers, tings start taking a loooong time. In our matrix we want to do a lot of multiplications, so this is bad. To speed tings up we may precalculate a lookup table, but this would have too many entries to be possible, as the amount of ram available is very limited"

Another limitation is the maximum speed possible. From memory I think the maximum clock frequency for the 18F is around 40MHz. But each instruction takes 4 clock cycles, so the maximum speed is 10MIPS (million instructions per second). If we are aming for 44.1kHz, this leaves us with 226 instructions per refresh! Takling into account that multiplications take a lot of these and you quickly realize that the PIC18 doesn't quite cut it. I know the Matrix 12 probably does not have a lot more power than this, but it used 8 bit variables. If we did the same we could possibly make tings work, but we won't.

If we want to stick with the PIC family this leaves us three options - the dsPIC and PIC24, both 16 bit, and PIC32 which is 32 bit.

The PIC32 runs at up to 200MIPS, 20 times faster than the PIC18F. It packs a whooping 512kB of ram and has plenty of serial i/o and whatnot. It even has built in support for ethernet. Also, it can do 16bit x 16bit and 32bit x 16bit multiplications in 1 instruction! With 200MIPS we get 4535 instructions per update, so we should be able to use a quite large matrix.

So what are we waiting for? The PIC32 wins the shootout, right? Well, there are two things worth considering. First of all, the price. A PIC32 running at 200MIPS and with 512kB Ram costs close to $9 in quantities of 5000 and up. Not something that breaks the bank, but considering we need one per voice, it gets a bit expensive.

More importantly though, the PIC32 comes in surface mountable versions only. This makes it harder to prototype things. We may of course add in-circuit programming posibilities (and this is such a good idea that I would consider doing it any way) but it still is a bit of a hassle.

That leaves us with the PIC24 and the dsPIC. These are so similar that they share the same data sheet. The difference is that the dsPIC has a set of instructions specialised for digital signal processing, like doing large sum-products in a single instruction. Right now I see no use for this in our matrix (funny, as matrix multiplication is possibly something the dsPIC is very good at), so lets see if the PIC24 can do the job.

The PIC24 runs at up to 70MIPS, 7 times faster than the PIC18, so we get 1587 instructions per update. Not as much as we may have hoped for but still something. The PIC24 can also do 16bit x 16bit multiplication in one cycle (though i need to get this confirmed). It has two SPI interfaces and it comes in (among others) a 28pin through-hole version.  The cost is  around $3.50, which is a lot cheaper than the PIC32. All in all I am willing to give it a try. Except for having to redo the digital voice pcb much of the code and circuitry from a PIC24 version can be reused for a PIC32 version. One could also reduce the update frequency to get more time between updates. Besides, part of the fun is using a mcu with limited resources, you have to be clever :-)

søndag 18. januar 2015


I mentioned in the previous post that I want the synth to be like the Oberheim Matrix line with its software modulation matrix. Here is my take on it: The OMM (open modulation matrix) and its counterpart, the OMMNoM (OMM Node Manager).

The OMM is a piece of firmware running inside the mcu of each voice. It takes a set of inputs, constants, ramps/envelopes and function generators, and through a series of transformations calculates the CVs that control the voice. It is open in the sense that it is possible and easy to add input sources and transformations to the code and it has an open protocol so anything able to generate a simple string stream may be used to create the OMM model.

The OMMNoM is a program used to create the matrix. I envision this as a graphical tool running on a tablet. Through dragging and dropping nodes representing sources and transformations onto a canvas, and then connecting their inputs and outputs to each other and to cv outputs, one creates modulation matrices as advanced as the ones in the Oberheim Matrix line through a much more intuitive user interface.

In the matrix, any output may be connected to any input. Some nodes, such as summing and multiplication accept multiple inputs, while others, for example linear-to-exponential converters and cv outputs only have a single input. All nodes have one output, except the cv outputs which have none (or rather, they have a physical output that connects to the analog part of the voice). An output may of course be connected to any number of inputs.

So far I've thought of the following nodes:

External inputs
- midi controller messages
- keyboard pitch
- keyboard trigger/gate
- pitch bend wheel
- modulation wheel
- physical input switches
- physical input potmeters
- virtual input switches
- virtual input potmeters
- noise input connected to physical noise module of the analog card (use with sample and hold for example).

Controllable functions/function generators
- ramp generators (inc looping?)
- multi stage envelopes (inc looping?)
- LFOs
- Sample and Hold
- Trigger (sends trigger pulse if input is high)
- Comparator - sets output high when one input is higher than the other
- switch - turns on or off a signal when input is high or low)

Mathematical expressions
- sum
- multiply
- divide
- maximum
- minimum
- average
- exponentiation (possibly with dB control)

Logical operators, all with adjustable thresholds (with defaults)
- and
- or
- not
- xor

- CV
- trigger pulse (for analog envelope)
- gate (for analog envelope)
- other binary pins (controlling switches etc)

- numerical constants - these may be entered directly on a node input instead of being a separate node.

The outputs will most likely be named after what they connect to on the analog voice card, but this is not a necessity for the OMM model which just maps the output to a pin or DAC address.

Usage example:

To create an echo with diminishing volume,
an LFO may be connected to the trigger and gate input of an envelope, which in turn is multiplied with a down-sloping ramp. The output from the multiplier should be run through an exponentiation and then connected to the output CV going to the voice's output VCA.

lørdag 17. januar 2015

Polysynth voice cards


I intend to spilt the voice cards into two physically separate PCBs, one containing the mcu and DACs for the various required control voltages, and one with the analog parts like VCOs, VCFs, VCAs etc. This way i may develop the two cards separately and change only parts of a voice if i need to. In short, it reduces the consequences should something go wrong or if i want changes. I may even consider a separate filter card.

(Mostly) analog card

At the moment the analog cards should contain the following:
- noise, switchable between white, pink and red, with its own separate VCA.
- three VCOs, each with saw, triangle and pulse outputs. Each waveform should have a separate VCAS.
- one 2 pole state variable filter (HP/BP/LP and possibly notch)
- one 4 pole LP filter
- one sample player/digital oscillator. This can be used for sampled attacks (Roland D-50 style) or digital waveforms.
- cross modulation between oscillator 1 and 2
- sync (soft and maybe hard) between 1 and 2/3
- a separate output VCA connected to the main envelope.

All these elements will be built as separate, chip-style PCBs, once again reducing the complexity and simplifying testing.

I strongly consider making this an Oberheim Matrix-style synth. More about that in a separate post, but this means that I will move LFOs, envelope/ramp generators, sample and hold and other modulation stuff into the digital domain. A consequence of this is that each waveform may possibly have a separate envelope or have its amplitude modulated in other ways.

 A note on the VCAs as well: if possible, I want to keep them linear. This will make them far less temperature sensitive, as well as slightly easier to build. They may also be turned fully off. It does also mean that exponential conversion will have to be done in software. I have to test this to see if it is feasible and if the result is good enough.

In addition to the necessary CV and switch control inputs, the voice should have the following connectors:
- External sound input (possibly with it's own VCA)
- Feedback from noise to mcu for random/sample & hold functionality
- Feedback from VCOs for tuning
- Separate analog ground for each voice card

Filter section

I have thoughts about making it possible to merge two voices into a six (eight) oscillator monster voice to do super saw-like stuff. Originally I only intended a voice to have a single filter, and in the case of voice merging, which would happen before the filter, I would get a spare filter for each voice.

I'm concidering two ways of using this filter, switchable from software:
- in series with the first one, but with separate filter controls
- in parallel, but with separate output VCAs.

As a wrap up for the post, I have sone other ideal and thoughts that may or may not make their way into the voice cards:

- Move the sample player to the digital board to keep nasty digital transients away from the analog board? (Still required for switches, but they will hopefully not be switched in the middle of playing.
- Suboscillators for each VCO
- Analog envelopes for the filter and/or voice outputs. May use both analog and digital.
- Saw polarity switch or separate VCAs for each polarity?
- Filter cassettes to be able to switch between famous filters. Maybe one cassette per voice card?
- FX busses. I want to include at least a juno-106 chorus module, but possibly also a digital effects module.
- ring modulation


Polysynth and digital communication

Life is hard. But not right now. We're on a babymoon, a relaxing two-weeks holiday to sunny Thailand preparing ourselves for the stress of having a baby (thanks for the idea, Theresa). Nothing much happens here, so what better to do while sunbathing by the pool than drink a cold beer and dream about homemade polysynths, eh?

Today's topic: ic-to-ic communication. There are three viable options: parallel diy protocols, spi and i2c. They each require different nummer of communication pins, from 8+ for the parallel, 4+ for spi and 2 for i2c.

I2c, while seemingly the best in terms of the number of pins it requires, has a few attributes worth looking at. First of all, each device on the i2c bus has a unique address. While this is often a good thing, there are times when you want to send the same data to multiplum devices. Secondly, the transfer rate is limited, often to 100kHz or 400kHz. This may not pose much of a problem if your microcontroller cannot handle higher speeds anyway, but it is worth remembering.

Spi on the other hand usually has an address bit input for each device. When this is high, the device receives whatever data comes through the pipe. This means that multiple devices may receive the same data at the same time.

So, which one should we choose?

For my polysynth i imagine 8 voices. If possible I intend to control two voices at the same time from one mcu, if not, they will each have their own mcu. I want separate mcu's to be able to have a fully multitimbral synth, as well as being able to combine two voices into a more complex voice.

Using spi for the master mcu to the voice mcu's means I can send the same data to multiple voices at the same time, which is nice when doing polyphony.

For the voice mcu to dac, port expander etc, the choice is not as clear. First of all, if one wants separate external (master-to-voicecards) and internal (within voice) busses, one either needs a mcu with two serial interfaces or either use bit banging or do parallel communication within the voice.

I think i will use a combination of spi and separate pins for the internal communication. For example, i want to transfer data to a sample player/digital oscillator on the voice card. However, i also want to trigget its envelope  or start its sample at an exact time. Using a single dedicated pin for this may give me tighter controll timewise.

The same goes for DACs and shift registers. Data as spi and clocking as dedicated pins. Maybe. I'll have to test this.

Oh well, time for a drink. Iced coffee maybe?

søndag 11. januar 2015

Exponential VCA with temperature correction

As promised in the previous post, here is a new take on the exponential VCA. This time the CV input has been modified and a tempco resistor added. This is the same scheme used in many VCOs for the pitch CV.

As the 1k 3300ppm tempco resistor is the most used tempco resistor in DIY designs, possibly making it easier to get hold of, I have decided to use it for this design as well. This, however, means that the input CV has to be amplified before it is attenuated by the resistor voltage divider formed by R21 and TR1.

There are two ways to build this circuit - trimmable and not trimmable. For the not-trimmable version, use the exact values found in the diagram - 57k (47k + 10k) on the CVTRIM input and 23k (22k + 1k) in the feedback loop. All resistors should be 1% or better metal film resistors.

For a trimmable version you may replace the CVTRIM input resistors with a 10k resistor. The input voltage should be around -2.6V, and you may connect a 20k or 25k potmeter between 0 and -15V to achieve this. This potmeter will subtract a voltage from the input CV, which affects the maximum and minimum amplification possible. Both move in the same direction, if the maximum drops, the minimum will also get lower.

You may also change R11 to a 18k resistor and R19 to a 10k potentiometer. This pot will affect the "distance" between the maximum and minimum amplification. Turning the potmeter to the right and increasing the resistance of R19 will make the maximum amplification drop, but at the same time the minimum gets higher (i.e. you will not be able to attenuate the signal as much).

CV (linear) and response (Exponential) without trimming. No tempco used but temperature is 24 degrees celcius. Trim voltage is -15V, not 15V as it says in the picture.

The maths behind this

The maximum input to the transistor base when no correction CV is added should be -0.2072V. Using the R21/TR1 resistor voltage divider means that the output from the IC1A opamp must be -11.8V.

This voltage should be reached when the CV is 5V, which means that the CV has to be amplified -11.8V/5V = -2.362 times.

We will almost achieve this if we select a 23k feedback resistor and a 10k input resistor.

To reach -70dB, the correction CV must be 0.106V at the transistor input. This means it has to be 6.042V at the opamp output due to the resistor voltage divider. If we  choose to input -15V at the CVTRIM input, we need an input resistor (R1+R3) = 23k * -15V/6,042V = 57.1k


If we choose a 10k CVTRIM resistor, the input correction CV must be 6.042V * -10k/23k = -2.63V

UPDATE: As pointed out by MB in the comments, there is an error in the schematics. The output from IC1A/B should go to the top of the 56k resistor and the Q1/Q2 transistor bases should be connected to where the 56k meets the 1k tempco, as shown in my original sketch here:

lørdag 3. januar 2015

Exponential VCA, first try

After getting a very good result from the linear VCA, I felt like making an exponential version as well. The Lockbox VCA has an exponential converter, so why not try to use the same thing here?

I have written a long text about the exponential converter and learned a lot about it, so I had everything I needed in terms of theory ready. Reading this will give good insight to why the exponential converter is like it is and how it works, but it is not necessary to follow the reasoning in this post.

The most important result from the document is that the output current from the converter, Ic, can be written as:

   Ic = Is * e^(Vb/Vt)


  • Is is a constant reference current
  • Vb is the voltage at the base of a transistor in the converter, which is a fraction of the CV.
  • Vt is a constant that - unfortunately - changes with temperature.

The exponential curve

My big question when I started looking at the exponential VCA was how exactly the exponential curve should be. Where should it start?

Now, this may sound strange, one would always like the control current to be 0A when the CV is 0V, and at its maximum when the CV is at max. Unfortunately, the formula above will NEVER be zero. When the CV is 0V, e^(Vb/Vt) equals 1, and so Ic = Is. We may add a negative voltage so that e^(Vb/Vt) becomes less than one, but it will still never be zero.

The question then is, how close to zero do we have to get before we cannot hear the signal passing through the VCA any more?


I tried some component values and looked at the result on the scope. It looked good, but when I tried connecting the output to an amplifier, I could easily hear the sound even when the CV was 0V. After some googling, and realising that I had what I needed in my bookshelf, I discovered a few nice rules.

Douglas Self writes about this in the chapter "Volume and Balance control" of his book "Small signal audio design".

He states that a good volume control should cover at least 50dB, and at least -70dB attenuation is needed to get a good "offness", where you cannot hear much of the signal any more. But what the heck does that mean?

I will not go into details about decibels, but here is a rule of thumb: If you increase a signal 10 times, you have raised the volume by 20dB. Increase it a 100 times and you have raised it by 40dB. Similarly, divide the signal 10 times and you have decreased it by -20dB. Divide it by 100 and you have decreased it by -40dB.

Volume controls (and VCAs) work by attenuating the input signal. The input should be at its highest and the volume control only "pinches off" parts of it, reducing the volume. So, as a consequence of the previous paragraph, when the volume is reduced to 1/10th of the initial volume, it has been reduced by -20dB.

To figure out how much -50dB and -70dB are, we can use the formula

   Change in dB = 20 * log(Output/Input)

Where log is the 10-logarithm.

Refactoring the formula gives us that

   Output = Input * 10^(Change in dB / 20)

At -50 dB:

   Output = Input * 10^(-50 / 20) = Input * 0,00316

At -70 dB:

   Output = Input * 10^(-70 / 20) = Input * 0,000316

In other words, the output is 0.00316 times the input when reduced by -50dB and 0.000316 times the input when reduced by -70dB. So, now we got something to aim for.

What attenuation to aim for

So, should you go for the -50dB or -70dB slope? Well, that depends of course. I have build both, and there is a significant difference in the offness. There is a faint but clearly audible sound from the -50dB VCA even when the CV is at 0. With the -70dB VCA I had to walk up to the speaker and put my ear next to it, and even then could only hear an extremely low sound (my wife actually heard it before me).

The problem with the -70dB contra the -50dB is that what you gain in offness, you lose in fine control of the higher-volume parts. You have to turn the volume pot of the -70dB one a bit before you reach the starting point of the -50dB one so you get less pot travel for controlling the rest. The difference is not extreme but it's necessary to be aware of it.

I would probably go for the -70dB, but if you do not need the output to be completely off (maybe the output is masked by the output of other sounds?) you may choose the -50dB version.

-50dB curve. Straight line is CV, 0 to 5V. Curve is response of a 5V input signal. Note: not finely adjusted so top misses 5V a bit.
-70dB curve. Straight line is CV, 0 to 5V. Curve is response of a 5V input signal. Notice how the bend is sharper and starts later than on the -5dB one.

Calculating vital parameters

We already know from the linear VCA that a maximum control current of 1.515mA will give unity gain within the circuit used, so we'll use that as a starting point. I will only show calculations for -70dB, but it is similar for -50dB and -100dB.

With a maximum current of 1.515mA, the minimum current must be

   0.000316 * 1.515mA = 0.479 uA for -70dB attenuation.

To see what this means for input CV voltage, we need to use the exponential formula again.


   Ic = Is * e^(Vb/Vt)

which means that

   Vb = Vt * (ln(Ic) - ln(Is))

Vt varies with temperature, it is in fact

   Vt = ((degrees in celcius +273.16)*1.38*10^-23) / (1.6*10^-19)

This means that at 20 degrees celcius ("room temperature"), Vt = 25.3mV

Is is a constant that we choose ourselves. From my initial trials I found that an Is of 15V / 510kOhm = 29.4uA worked fairly well, so I chose that for my further calculations

Now we  can find Vb:

   At 0.479uA, Vb = 25.3 * 10^-3 * (ln(0.479*10-6) - ln(29.4*10^-6)) = -100.6mV

   At 1.515mA, Vb = 25.3 * 10^-3 * (ln(1.515*10-3) - ln(29.4*10^-6)) = 96.27mV

In other words, the voltage span needed to control the VCA from 0 to -70dB is

   96.27mV - (-100.6mV) = 196.8mV

Ah, but our CV spans 5V, and it starts from 0, not -100.6mV? Well, that can easily be corrected by an opamp summer with gain < 1.

By using a 1k feedback resistor and a 25k input resistor, our 5V CV is reduced to a 0.2V CV. To move the starting point to -100mV we only need to add a negative voltage. If we use the negative supply rail, -15V, we have to divide it by 150 to get to -100mV. As it has to run through the same 1k feedback resistor, we need to run it through a 150k resistor to get this attenutation.

A word of confusion

I have neglected to mention one thing. The exponential converter described above requires a positive Vb and it has its positive reference current Is and control current Ic running down into the collectors of the exponential converter transistors.

The output of the opamp summer connected to the CV circuit however, inverts the voltage giving us a negative CV. At the same time, the LM13700 requires a positive current running INTO pin1.

Fortunately, a PNP-transistor based exponential converter works exactly opposite of the NPN based one described in my texts about the exponential converter. Instead of a positive Vb it requires a negative one, and its reference current Is must run out of the collector. So by connecting the reference current generating resistor to -15V instead of 15V we are good to go.

Temperature is a bastard

Although we now have a working exponential VCA, it only responds accurately to the CV when the temperature is exactly 20 degrees celcius. This is because of the Vt mentioned earlier.

To see just how bad this gets, we can do some quick calculations:

TemperatureVtIc maxPercentage of 20 degrees

This may pose a bit of a problem. It is likely that the temperature will be higher rather than lower than 20 degrees, so the current will probably never be too high. Still, it may be a good idea to add a trimpot to the voltage that moves the starting point so that you can adjust your VCA to work best at your desired temperature. This will also alter the maximum attenuation, but not dramatically.

An exponential converter that works better with temperature changes will be suggested later.

Suggested resistor values for -50dB, -70dB and -100dB:

attenuationGain, R15CV, R4Trim, R3Trim if variable voltage/pot.

If a trim pot or variable voltage is connected to the CVTRIM input, use the resistor value in the last column. If not, connect CVTRIM to -15V.
Dual exponential VCA with -50dB attenuation, 0-5V CV

The Xonik VCA revisited

I have spent some time tweaking the LM13700 based linear VCA. I read somewhere that one should aim to use the highest possible value for the control current I_abc, which makes sense:

The way the VCA works is

  • The input voltage is divided down to something the LM13700 can handle
  • The voltage is attenuated/amplified by the LM13700, the highest output signal is found when the control current is at its highest.
  • The output current from the LM13700 is converted into a voltage and amplified by the output opamp.

Now, the lower the maximum controlling current is, the higher the output amplification must be. The higher the amplification, the more noise you amplify as well.

With this in mind, I took a closer look at the circuit and the LM13700 datasheet.

The datasheet states that the maximum Iabc the IC can handle is 2mA. Any more than this and the device self destructs.This is why some circuits out there have a 10k resistor connected between the transistor collector and the IC. The Iabc input (pin 1) of the LM13700 will stay close to the negative power rail, and the collector can never move above 0V (more than this and it would turn off as the collector has to be more negative than the emitter, and the emitter is connected to the CV inputs opamp's virtual ground). This gives a maximum voltage across the resistor of 15V, and a current through the resistor and into the LM13700 of 15V/10k = 1.5mA.

This can safely be changed to a 8.2k resistor which will give a maximum current of 1.83mA. It could actually be reduced even further, from my experience the Iabc input never goes much below -14V, but at least this is still on the safe side.

After some experimentation I decided to use a 3k3 resistor on the CV input, R2, when using a 0 to 5V CV. The maximum input current will then be 5V/3.3k = 1.515mA (A higher CV input will make this go higher, but it will be limited by the 8.2k resistor on the LM13700 input so we will never break the LM13700).

With a CV of 5V, I then tried different values for the input and output signal resistors. Assuming we want the input signal to be allowed to swing as much as possible, I added a 15V signal through a potmeter to the input and watched when the LM13700 started clipping. I ended up using a 27k input resistor, R1. To get the output signal back to the same amplitude (The opamp will start clipping with an input signal of about 13V, so I tried this with a 10V signal) I had to use a combination of a 22k and a 1.2k resistor in the feedback of the output amplifier, R15 and R17.

I also tried various other configurations. One may want to use a 0 to 10V CV instead of the 0 to 5V (the CV has to be positive, so if you want to use a -5 to 5V CV you have to bias it into 0 to 10V first. A negative CV will not harm the VCA in any way, it will just be fully turned off when the CV is less than 0V). If you are certain your input signal will never be above 5V or 10V you can also get away with less attenuation/amplification and thus less noise.

Here is a table of good values to use:
CVSignal swingInput resistor R1Output resistor R15 (+R17)CV input resistor R2
+/-10V12k10k + 560R3.3k
Max27k22k + 560R3.3k
0-10V+/-5V5.6k4.7k + 680R6.8k
+/-10V12k10k + 1k6.8k
Max27k22k + 1.2k6.8k

You can of course use a potentiometer instead of the output resistors, this will let you tweak the output perfectly. My experience however is that this is unnecessary as long as you use 1% resistors and the values above.

Dual VCA circuit using 0-5V CV

Ps: The additional input resistors are changed from two 510R resistors to one combination of 470R + 22R and one 510R. While this adds an additional resistor, it is well worth it in terms of balance / centering. Alternatively use a 1k potentiometer instead, with one side connected to the positive input and the other to the negative input. The center pin should be connected to ground.

Input vs output signal. The topmost wave is the input. The output wave is slightly off center.

Input vs output signal with a different balance - the waves overlap nicely.

PPS: The output buffer inverts the phase of the signal, this can be remedied by adding a second opamp with unity gain.

Disclaimer: The Xonik VCA is mainly inspired by the LM13600 VCA found on the Bergfotron pages and the linear Lockbox VCA 2 found on the Lockbox Synth pages