top of page
Search
  • Writer's picture1/4" Jack Of All Trades

Physical Computing Christmas 4: Last Minute Mozzi Tweaks and Starting the Soldering

Updated: Jan 8, 2021

Multi Voiced Oscillator Mk.II


I began making the final adjustments to the Mozzi code, opting to move away from the FM synth that I had been making, as I was unsatisfied with it sonically and did not feel that it changed enough from the original example code for me to be truly happy with it. The use of multiple FM voices in the old patch was also the source of a weird clicking sound. I have instead ended pursuing the goal of mulitple oscillator voices, some to be controlled by the first 5 potentiometers (analog inputs 0 - 4) and a bank of identical oscillators with an additional variation parameter (controlled by analog input 5) that adds a small amount to the frequency to cause interesting beating effects. I am much happier with the sonic results and the only thing remaining now for the coding is to add some delay to the output (something I did it previous iterations of the FM synth, but forgot at time of writing to add to the beating synth) and to experiment with different oscillator tables (full list of tables here) or maybe experiment with making my own.


One thing I have noticed is that the LEDs lighting up seem to be audible through the amplifier I was using. However, I do not entirely hate it, as it adds an interesting percussive layer that synchronises with LEDs and strengthens the feeling of audiovisual interaction.




Here is the updated code:

#include <MozziGuts.h>
#include <Oscil.h>
#include <tables/cos8192_int8.h>
#include <AutoMap.h>
#include <FastLED.h>
#include <EventDelay.h>

//FAST LED Stuff
FASTLED_USING_NAMESPACE
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#warning "Requires FastLED 3.1 or later; check github for latest code."
#endif
#define DATA_PIN    3
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    111
CRGB leds[NUM_LEDS];
#define BRIGHTNESS          96
#define FRAMES_PER_SECOND  120

// main oscillators - note to self expierment with different oscil tables.
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos1(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos2(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos3(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos4(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos5(COS8192_DATA);

// duplicate oscillators to be combined with variation param to create beating effect.
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos1b(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos2b(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos3b(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos4b(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos5b(COS8192_DATA);

const int KNOB_PIN_1 = 0; // set the first voice pitch to analog pin 0
const int KNOB_PIN_2 = 1; // set the second voice pitch to analog pin 1
const int KNOB_PIN_3 = 2; // set the third voice pitch to analog pin 2
const int KNOB_PIN_4 = 3; // set the fourth voice pitch to analog pin 3
const int KNOB_PIN_5 = 4; // set the fifth voice pitch to analog pin 4
const int KNOB_PIN_6 = 5; // set variaton to analog pin 5

const int PITCH_MIN = 22;
const int PITCH_MAX = 500;
const int MIN_VARY = 1;
const int MAX_VARY = 50;
const int MINLED= 10;
const int MAXLED = 50;
const int MINCOL = 50; // I found that a min 0 can look ruin percieved AV interaction with some settings that otherwise sound good
const int MAXCOL = 255;
AutoMap kMapPitch(0,1023,PITCH_MIN,PITCH_MAX);
AutoMap kMapVary(0,1023,MIN_VARY,MAX_VARY);
AutoMap kMapLEDs(0,1023,MINLED,MAXLED);
AutoMap kMapColor(0,1023,MINCOL,MAXCOL);

EventDelay EvDel;

void setup()
{
  delay(3000); // 3 second delay for recovery
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  startMozzi();
  EvDel.set(1000/FRAMES_PER_SECOND);
}

void loop()
{
  audioHook();
}

void updateControl()
{
  int knob_value_1 = mozziAnalogRead(KNOB_PIN_1);
  int knob_value_2 = mozziAnalogRead(KNOB_PIN_2); 
  int knob_value_3 = mozziAnalogRead(KNOB_PIN_3);
  int knob_value_4 = mozziAnalogRead(KNOB_PIN_4);
  int knob_value_5 = mozziAnalogRead(KNOB_PIN_5);
  int knob_value_6 = mozziAnalogRead(KNOB_PIN_6);

  int f1 = kMapPitch(knob_value_1);
  int f2 = kMapPitch(knob_value_2)*2; //<
  int f3 = kMapPitch(knob_value_3)/2; //<may remove/change these
  int f4 = kMapPitch(knob_value_4)/4; //<
  int f5 = kMapPitch(knob_value_5);
  int variation = kMapVary(knob_value_6);

  aCos1.setFreq(f1);
  aCos2.setFreq(f2);
  aCos3.setFreq(f3);
  aCos4.setFreq(f4);
  aCos5.setFreq(f5);

  aCos1b.setFreq(f1+variation);
  aCos2b.setFreq(f2+variation);
  aCos3b.setFreq(f3+variation);
  aCos4b.setFreq(f4+variation);
  aCos5b.setFreq(f5+variation);

  int led_speed = kMapLEDs(knob_value_6);
  int red = kMapColor(knob_value_3);
  int green = kMapColor(knob_value_4);
  int blue = kMapColor(knob_value_5);
  
  //FastLED Stuff
  if(EvDel.ready())
    { 
      FastLED.show();
      EvDel.start();
    }

  if (knob_value_1 > 500 && knob_value_2 > 500)
    {
      confetti(led_speed, red, green, blue);
    }
    
  else if (knob_value_1 < 500 && knob_value_2 < 500) 
    {
      sinelon(led_speed, red, green, blue);
    }
    
  else
    {
      juggle(led_speed, red, green, blue);
    }
 
}

int updateAudio(){

  int asig =
    aCos1.next() + aCos1b.next() +
    aCos2.next() + aCos2b.next() +
    aCos3.next() + aCos3b.next() +
    aCos4.next() + aCos4b.next() +
    aCos5.next() + aCos5b.next();

  return asig >> 3;
}


void sinelon(int speed, int r, int g, int b)
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, speed);
  int pos = beatsin16( 13, 0, NUM_LEDS-1 );
  leds[pos] += CHSV( g, r, b);
}

void confetti(int speed, int r, int g, int b) 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, speed);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( g + random8(64), r + random8(64), b + random8(64));
}

void juggle(int speed, int r, int g, int b) {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, speed);
  //byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(g, r, b);
    //dothue += 32;
  }
}

 

Starting the Soldering and Further Enclosure Preparations


I began the soldering process by attaching my potentiometers to a small strip of protoboard and soldering colour coded hook up wire from the potentiometers (Red power, black ground, blue data). Doing it in this manner allowed me to continue to test on the breadboard, whilst also moving towards the final iteration of the design.


I also used Fritzing to create a schematic of the build, adding in a power switch as the final build will be powered by a 9V battery.


 

Above: Project Schematic & Parts List.

Above & Below: Soldering the potentiometers to a strip protoboard.

 

Above: The prepared project enclosure.

3 views0 comments
bottom of page