Friday, January 31, 2025

Filters clipping - current situation and solution

All three filters clip but some are more extreme than others.

Juno clipping

The Juno filter has a major flaw, it has an output gain stage that clips for anything above 2V out. It outputs 2V from 10V in, which means that all resonance is clipped if it exceeds the max input signal.

JP6 clipping

The JP6 filter clips in the output selector/gain stage, but also slightly internally

Moog clipping

The moog filter clips the least as it has a fairly good soft clipping built-in. The output gain op amp still clips at extremes.


Fixes

I've worked a lot to find the best solution the last few days, and as such has come up with the following approach:

Bus mixer changes

Reduce amplitude from the bus mixer into the filters from max 10V to max 5V. This requires two changes:

- Double the input resistors to the wet/dry amps in the bus mixer, halving the output of the summer

- When turning on serial instead of parallel filters, disable input from sum B. 

- SVF must still somehow have unity gain, if not, chaining input will be too low.

This alone has a huge effect on most clipping, giving double the headroom. 


Reduce the post filter gain

Moog filter

For the Moog filter, this is simply done by using half the CV. It can be done in software for the current version. This stops any leftover clipping in the Moog filter.

Juno filter

For the Juno filter, we add a resistor to the output. This will end up in series with the 18k resistor in the post juno filter gain stage, and reduce the gain. A 22k resistor reduces gain from 5.5 to 2.5. This takes away most of the clipping, though the filter still clips when the resonance oscillation has the same frequency as the input signal. It does however require modification of the juno filter board. This requires some other mechanism, like soft clipping the signal. More on that later.

JP6 filter

For the JP filter, we need to keep unity gain through the filter, so we do the gain reduction in the output mixer. It does not prevent any clipping but is required to keep max levels the same as for the juno and moog filter. This is the simplest solution for now. 

 

Reducing JP clipping

Unfortunately, the JP filter clips very slightly at highest resonance at the point where oscillation is in sync with the signal. This is not easily changed as it happens inside the filter circuit, but it is also the least serious clipping. I will leave it as is for now. It also goes away if reducing the max input slightly, but requires at least another 20% reduction. Perhaps this is best done in software for now.

To prevent other clipping, we have to change the output gain that happens around the output selector. This can be done in two ways: 

- Changing the voice card. This is the correct solution, and should be done for future versions of the card. Gain for all but the BP2 cell is 100/65 = 1.54, so quite a bit of clipping can be removed here. We still may have to add some kind of soft clipping, though. If soft clipping is added, we may choose to reduce the input by the needed 20% and increase the output gain instead to get around the initial clipping.

- Making a drop-in-replacement for the IC56 DG408 mux that halves the output by adding more input resistors. Unfortunately, the maximum BP2 output is 8.6V, and this is followed by a 1.67x gain stage (IC52A) which immediately clips. This cannot be remedied by the card. Instead, we need to reduce the BP2 gain stage to unity by adding an output resistor > 39k (to make the sum of 56k + 3.9k + x = 100k) to the JP6 BP2 output. It may be possible to do with existing JP6 filter cards or we can order new cards with this modification, and use the current version with new voice cards.


TL;DR - these are the needed fixes

- Double the signal input resistors on the wet/dry mixer on the bus mixer board

- (fix the gain error on the bus mixer board)

- Reduce output amp gain for Moog, JP6 and Sines to 50% (in software)

- Set a max resonance for all filters to keep self resonance oscillation amplitude as low as possible.

 

To save the current voice cards

- Add a 22k resistor to the juno output boards (for this version).

- Double the Moog resonance CV somehow, possibly by adding a parallel resistor to the CV input to double the current.

- Create a drop-in for the DG408 JP output selector that reduces gain (and possibly adds soft clipping?)


For new version

- Replace the 18k juno post filter gain input resistor with a 39k one (or rather, move the post filter gain onboard the Juno filter PCB).

- Add soft clipping to the juno filter

- Fix Moog resonance CV on the moog board

- Update the circuit around the JP filter output selector to prevent clipping. May have to add soft clipping.


PS: Self oscillation with a very high frequency (>20kH<) makes what sounds like digital noise. Not sure exactly what to do with it, maybe a lower frequency output LPF would be a good idea.

PPS: There are a lot of weird things happening that may be caused by the ground plane noise from the waveshaper. 

PPPS: Knocking on the breadboard makes resonance wobble. I hope this is just poor connections but fear that some of the ceramic caps are picking it up. We'll see.

Sunday, January 19, 2025

Gritty noise on panner and oscillator mix volume pots

While testing, I heard a lot of digital sounding noise on the output when turning the volume or pan pots. I first suspected it to be digital noise from the midi connection.

After extensive testing, I've concluded that this is not noise per se, instead it has two causes:
- The midi input is stepped, each pot has max 128 positions
- The CV is linear, so changes are more audible when the volume is low

I tried adding filtering of the output CVs, e.g. making the change take more time even if the midi said to change things instantly. This worked fairly well but when turning the volume pot slowly I could still hear stepping at the lower end.

This is because the steps are of equal size, but audio loudness is exponential. A one unit change when the volume is low is much larger and audible than a one unit change when the volume is high.

I have already added support for response curves, changing to an "exp_1" curve took care of most of the stepping.

As for the filtering, a "max 64 units change per update" gave a good result. 256 is too much. 

Right now the filtering happens at the DAC update, it should be moved to the midi side as the rest of the matrix works as it should.

A simple headphones amp from yusynth.net

To test the output of my synth, I've built and tested the headphone amp found on yusynth.net:

https://yusynth.net/Modular/EN/MIXOUT/index.html



I had no BC327 transistors, so I replaced both the BC337 and BC327 with 2N3904 and 2N3906. Also, as I was unsure of the ratings of my resistors, I used two 330Ohm in place of the 150Ohm 1/2W, and two 220Ohm in place of the 82Ohm 1/2W. The output seems to have unity gain, way too high for my headphones, so I placed a resistor voltage divider plus an op amp buffer in front of the volume pot. I used 100k and 10k resistors for an attenuation from +/-5V to +/-0.45V. The max volume is still very high but at least more controllable.

Oh, and I forgot the electrolytic caps before the volume pots, I will add those and try again.

Thursday, January 9, 2025

Button scanner utility board

I've made a chainable button scanner board, similar to the one for potentiometers. Each one connects up to 64 keys/buttons through 8 connectors. When clocked, button statuses are output on a single pin. 

The button status is inverted, so a pressed button reads as 0/GND, an open as 1/V+ 



In addition, a breakout board is available, converting 8 columns + common row to 8 column pins + 8 row pins, making it easy to connect buttons using Dupont connectors.

The breakout boards are made with surface mount connectors to have a flush back, making it easy to glue/tape them to the back of the panel, close to the switches.



Modulation matrix thoughts

I have a working modulation matrix on my XM8 prototype. But something is missing and I haven't had the time to put my finger on exactly what.

Here is a more thorough walkthrough of what could/should be supported.

1) A destination may be modulated by multiple sources, each with their own amount/weight. The sources are summed (to give for example vibrato by modulating a pitch CV by an LFO and summing it with the original pitch)


2) A source may modulate any number of destinations. Again, for example, the LFO may modulate multiple oscillators at the same time etc.

 

Now, these are dead given. But then we have a more complex one

3) A source may modulate the amount of another source. For example, a separate potentiometer may modulate the amount of LFO applied to the VCO pitch.

 

Then we have a special case

4) Multiple destinations may control a function, which in turn is the source of another modulation. For example, multiple pots may control an envelope. The output of the envelope may modulate the output VCA.


Strictly speaking, we could also let the destination directly act as a source, leading to

5) Any destination may be treated as the source of another modulation

 

6) Any destination may be treated as the amout of another modulation


 

Right here it feels like we're entering FM territory...


Summed up into some general rules:

  • A modulation path consists of a source, an amount multiplier and a destination.
  • A source may modulate a destination or the amount of another source
  • A source may modulate multiple destinations or amounts 
  • A destination may be modulated by multiple sources. The sources are summed after being multiplied by individual amounts
  • Multiple destinations may act together to control a function (LFO, envelope)
  • Pots, destinations and function outputs may all act as sources

It would be a good idea to hardwire most pots to specific destinations

Most amount coefficients in the matrix will be zero. It may be better to have a list of 'active' modulations to reduce the number of coefficientds, but that depends on the MCU and what optimizations it may do on the data.

I think my major mental breakthrough here is that I realized that sources, especially pots, must be able to control the amount.

Things I still wonder about

  • Will it always be correct to add, not multiply, the various modulation paths?
  • For simplicity, should we really allow any destination to act as a source?

Oh, and here are some resources for Teensy math:
- https://forum.pjrc.com/index.php?threads/linear-algebra-library-for-teensy-4-1-robotics-project.69778/
- https://github.com/PaulStoffregen/Audio/blob/master/utility/dspinst.h
 

PS: Multiplying and summing two vectors (or matrices) is called a dotproduct.

Sunday, January 5, 2025

Potentiometer scanner utility board

As I prepare to make a function mockup of the front panel, I've designed a utility board that can scan up to 48 potentiometers. The boards can be chained, allowing for a total of 288 potentiometers on six output pins.

The only input from the mcu is clock, reset, +V and GND.



 
Shown here: two input muxes (left), one per 10p connector. Only six of the eight inputs are used but all are adressed as the clock is sequential. The board has 8 input muxes in total. On the right is a single mux that selects one of the 8 input muxes for output to the MCU. Everything is clocked by a CD4520 six bit binary counter. Before scanning starts, clock is reset to make sure it is at 0. It can also be reset early if some of the input ports are not used.

Testing shows that a single channel can be scanned at 50kSamples/second, the limitation is the speed of the ADC on the microcontroller. The analog output of the on board mux'es stabilize after approximately 2uS. 

I've tested the circuit on a Teensy 4.0, and as it uses a single ADC for multiple channels, scanning six channels takes around 113uS. This means that we can do 185 samples/second per potentiometer when using all channels.

As I'm allergic to soldering, I have been looking for a way to connect the pots without solder. My best and simplest solution this far is to insert the potmeter directly into a 10p IDC connector. It stays fairly firmly in place, with the outer potentiometer pins at pin 1/2 and pin 9/10, and the center pin at pin 5/6. 

 

If I connect +V to pin 1/2 and GND to pin 9/10, I can connect the pots at either the front or rear row of the connector, reading the value from pin 5/6. 


 

 

Front row

Rear row

If I modify the cable a bit, crossing pin 3/4 to center and then 7/8 to center, I can connect six potentiometers to a single 10p ribbon cable!

Crossing two and two wires allows me to connect six potentiometers to one ribbon cable