Infinity37 – Poly DIY synth

 

IMG_20170609_190739

Want to build a fully polyphonic synth?

Now you can!

The Infinity37 is based on the new Polytron37 chip.
It is a keyboard DCO with divide down oscillators and polyphonic envelopes per key.

It also features analog pitch modulation and analog pulse width modulation.

And it transmits and receive MIDI for a fully polyphonic MIDI synth.

The audio-DAC is 16-bit for a better dynamics range.

polytron37chip

Polytron37sch

You can just buy the chip and a MIDITECH minikeys keyboard and build it.

Why is it called the Polytron?

Because you can integrate it into a Korg Monotron for a polyphonic version with a filter.
And it will fit inside a Monotron MIDI-fying it with a Polyphonic DCO without changing the original function.

Monotron Duo

If you want the preprogrammed chip you can order it here:

Order the Polytron37 chip $25 including shipping

The DIY version here will run the Polytron DCO on an Arduino Nano so you can follow the code and make one yourself but the chip works the same way.

solina8

So how do you make a fully polyphonic DCO?

You cant have one oscillator for every key? Or can you?

A divide down oscillator or top octave generator is really 12 dividers or counters that counts from a high frequency clock to generate the top octave keys.

TOG

The rest of the octaves are generated by dividing the keys by a modulo of 2 as each octave down is half the frequency.

Most organs in the 70’s worked in this way.

The problem is that they are just organs. No envelope, just key on/off.

You can do it with 12 dividers and use more bits to get the lower octaves but that will give you 37 square waves with no fun or liveness what so ever.

What you really need is 37 independent oscillators and that is a tough job for an ATmega running at 16MHz.

We are going to use 37 NCO’s which will allow us to use arbitrary waveforms and envelope on each key.

But hey, didn’t you just say that the ATmega can’t cope with that many counters?
Yes, but since you most likely never play 37 notes at once we are going to use a trick.

Remember that the Polytron also got 37 EG’s?
We only run the counter when the EG curve or volume is above zero.

That will allow notes to fade away even if you play new notes.

The DCO code for our idea:

ISR(TIMER1_COMPA_vect) { // Timer1 interrupt

//—- PolyTron DCO’s —————————

uint16_t Total=0;

uint16_t Total2=0;

if (VCA[0]) {

FREQ[0]+=8192>>5;

if (FREQ[0]<PW) Total+=VCA[0];

}

if (VCA[1]) {

FREQ[1]+=8679>>5;

if (FREQ[1]<PW) Total+=VCA[1];

}

if (VCA[2]) {

FREQ[2]+=9195>>5;

if (FREQ[2]<PW) Total+=VCA[2];

}

if (VCA[3]) {

FREQ[3]+=9742>>5;

if (FREQ[3]<PW) Total+=VCA[3];

}

if (VCA[4]) {

FREQ[4]+=10321>>5;

if (FREQ[4]<PW) Total+=VCA[4];

}

if (VCA[5]) {

FREQ[5]+=10935>>5;

if (FREQ[5]<PW) Total+=VCA[5];

}

if (VCA[6]) {

FREQ[6]+=11585>>5;

if (FREQ[6]<PW) Total+=VCA[6];

}

if (VCA[7]) {

FREQ[7]+=12274>>5;

if (FREQ[7]<PW) Total+=VCA[7];

}

if (VCA[8]) {

FREQ[8]+=13004>>5;

if (FREQ[8]<PW) Total+=VCA[8];

}

if (VCA[9]) {

FREQ[9]+=13777>>5;

if (FREQ[9]<PW) Total+=VCA[9];

}

if (VCA[10]) {

FREQ[10]+=14596>>5;

if (FREQ[10]<PW) Total+=VCA[10];

}

if (VCA[11]) {

FREQ[11]+=15464>>5;

if (FREQ[11]<PW) Total+=VCA[11];

}

if (VCA[0+12]) {

FREQ[0+12]+=8192>>4;

if (FREQ[0+12]<PW) Total+=VCA[0+12];

}

if (VCA[1+12]) {

FREQ[1+12]+=8679>>4;

if (FREQ[1+12]<PW) Total+=VCA[1+12];

}

if (VCA[2+12]) {

FREQ[2+12]+=9195>>4;

if (FREQ[2+12]<PW) Total+=VCA[2+12];

}

if (VCA[3+12]) {

FREQ[3+12]+=9742>>4;

if (FREQ[3+12]<PW) Total+=VCA[3+12];

}

if (VCA[4+12]) {

FREQ[4+12]+=10321>>4;

if (FREQ[4+12]<PW) Total+=VCA[4+12];

}

if (VCA[5+12]) {

FREQ[5+12]+=10935>>4;

if (FREQ[5+12]<PW) Total+=VCA[5+12];

}

if (VCA[6+12]) {

FREQ[6+12]+=11585>>4;

if (FREQ[6+12]<PW) Total+=VCA[6+12];

}

if (VCA[7+12]) {

FREQ[7+12]+=12274>>4;

if (FREQ[7+12]<PW) Total+=VCA[7+12];

}

if (VCA[8+12]) {

FREQ[8+12]+=13004>>4;

if (FREQ[8+12]<PW) Total+=VCA[8+12];

}

if (VCA[9+12]) {

FREQ[9+12]+=13777>>4;

if (FREQ[9+12]<PW) Total+=VCA[9+12];

}

if (VCA[10+12]) {

FREQ[10+12]+=14596>>4;

if (FREQ[10+12]<PW) Total+=VCA[10+12];

}

if (VCA[11+12]) {

FREQ[11+12]+=15464>>4;

if (FREQ[11+12]<PW) Total+=VCA[11+12];

}

if (VCA[0+24]) {

FREQ[0+24]+=8192>>3;

if (FREQ[0+24]<PW) Total+=VCA[0+24];

}

if (VCA[1+24]) {

FREQ[1+24]+=8679>>3;

if (FREQ[1+24]<PW) Total+=VCA[1+24];

}

if (VCA[2+24]) {

FREQ[2+24]+=9195>>3;

if (FREQ[2+24]<PW) Total+=VCA[2+24];

}

if (VCA[3+24]) {

FREQ[3+24]+=9742>>3;

if (FREQ[3+24]<PW) Total+=VCA[3+24];

}

if (VCA[4+24]) {

FREQ[4+24]+=10321>>3;

if (FREQ[4+24]<PW) Total+=VCA[4+24];

}

if (VCA[5+24]) {

FREQ[5+24]+=10935>>3;

if (FREQ[5+24]<PW) Total+=VCA[5+24];

}

if (VCA[6+24]) {

FREQ[6+24]+=11585>>3;

if (FREQ[6+24]<PW) Total+=VCA[6+24];

}

if (VCA[7+24]) {

FREQ[7+24]+=12274>>3;

if (FREQ[7+24]<PW) Total+=VCA[7+24];

}

if (VCA[8+24]) {

FREQ[8+24]+=13004>>3;

if (FREQ[8+24]<PW) Total+=VCA[8+24];

}

if (VCA[9+24]) {

FREQ[9+24]+=13777>>3;

if (FREQ[9+24]<PW) Total+=VCA[9+24];

}

if (VCA[10+24]) {

FREQ[10+24]+=14596>>3;

if (FREQ[10+24]<PW) Total+=VCA[10+24];

}

if (VCA[11+24]) {

FREQ[11+24]+=15464>>3;

if (FREQ[11+24]<PW) Total+=VCA[11+24];

}

if (VCA[0+36]) {

FREQ[0+36]+=8192>>2;

if (FREQ[0+36]<PW) Total+=VCA[0+36];

}

//—————————————————————–

OCR2A = Total>>5;

}

ISR(TIMER0_COMPA_vect) { // Timer0 interrupt

//——————— ENV block ———————————

for (envcnt=0;envcnt<37;envcnt++) {

if ((MIDItable[envcnt]>0)&&(VCA[envcnt]<255)) {

VCA[envcnt]+=ATTACK;

if (VCA[envcnt]>255) VCA[envcnt]=255;

}

if ((MIDItable[envcnt]==0)&&(VCA[envcnt]>0)) {

VCA[envcnt]-=RELEASE;

if (VCA[envcnt]<0) VCA[envcnt]=0;

}

}

//—————————————————————–

This code runs 37 DCO’s with PWM and 37 ENV’s.

It’s not perfect as it makes the DC component fly all over the place but it’s fast.

FREQ and VCA are arrays for the counters and EGs.

Attack and Release is the polyphonic envelope.

PW is the ratio of the generated pulse wave.

This is what it sounds like:

 

Not what you ordinary hear off an Arduino?

More to come….


%d bloggers like this: