miércoles, 25 de septiembre de 2013

bit$hifter [algorithmic 8bit synthesizer]









Inspired on minimal algorithmic symphonies, this synth-box/noise-machine uses a set of powerful manipulation rules to operate over a stream of 8bit words on PIC16F873A microcontroller. The output of such manipulations is transformed to signal audio by an onboard digital-to-analog converter and buffered to drive both line/headphones output.

The controlls allows to modificate parameters in the manipulation procedures:
  • main wheel stochastocally select operation mode (from available in firmware). the sound pattern generated heavily depends on which procedure generate them so minimal variations of the controll may result in deep changes in sound tonality/patterns
  • wheel a modifyes sampling rate over the bit stream or the velocity of time for generating the patterns
  • wheel b modifyes the bit-shifting performed in post processing stage and acts like a fine tuning of patterns generation
  • volume ctrl controll the sound intensity
Here is a really long jamming with this little noisy beast and a minikaosspad for recording and some effects here and there: 



[DIY |*---*|]:

Build your own bit$hifter!, they are open, free and totally customizable if your interested in experiment with sound patterns. Next there is a list with the components, schematic and mikroC source. Soldering and programming skills requiered.

Material:
  • 1 x PIC16F873A
  • 1 x TLC081 low power opamp
  • 4 x 100 KΩ potentiometers
  • 1 x 20 Mhz xtal resonator
  • 2 x 33 pF capacitors
  • 25 x 1k resistors
  • 10 uF capacitor
  • 1 led
  • male usb power connector
  • 3.5'' audio jack
  • some cable
  • optional pcb circuit and case or protoboard (breadboard) to mount all the things
Schematic:




Code:

/*
Bit$hifter 0.1
--------------

$·device: pic16f873a
$·clock: 20 mhz

$·pic version of minimal algorithmic symphonies 
$·main loop uses A/D 10-bit conversion of A0-A2 as input parameters
$ that changes the way functions are evaluated and post processed.
$.i think the switch-case selector causes the loop to go slower so a different optimized implementation must accelerate the stream generation. 

unsigned long i;
unsigned int aux00, aux01, aux02, other_i;
unsigned char Pot00, Pot01, Pot02;

void main()
  {
  ADCON1 = 0x00;   // porta is in full analogue mode
  TRISA  = 0xFF;   // porta is input
  TRISC = 0;       // port c as output
  PORTC = 0;       // initialize portc  

  
  aux00 = Adc_Read(0);
  aux01 = Adc_Read(1);
  aux02 = Adc_Read(2);
  while (1)
    {
    // preprocess to acceptable ranges
    Pot00 = aux00&0x0F;   // function selector [0..16]
    Pot01 = aux01>>0x02;  // scale range

    Pot02 = aux02>>0x07;  // output shifting [0..7]
    for (i=65535; i<=131027; i+=(1+Pot01))
      {
      switch (Pot00)
        {
        case 0x00:
             other_i=i;
        case 0x01:
             other_i=i&i>>8;
        case 0x02:
             other_i=i*(42&i>>10);
        case 0x03:
             other_i=i|i%255|i%257;
        case 0x04:
             other_i=i>>6&1?i>>5:-i>>4;
        case 0x05:
             other_i=i*(i>>9|i>>13)&16;
        case 0x06:
             other_i=(i&i>>12)*(i>>4|i>>8);
        case 0x07:
             other_i=(i*5&i>>7)|(i*3&i>>10);
        case 0x08:
             other_i=(i*(i>>5|i>>8))>>(i>>16);
        case 0x09:
             other_i=i*5&(i>>7)|i*3&(i*4>>10);
        case 0x0A:
             other_i=(i>>13|i%24)&(i>>7|i%19);
        case 0x0B:
             other_i=(i*((i>>9|i>>13)&15))&129;
        case 0x0C:
             other_i=(i&i%255)-(i*3&i>>13&i>>6);
        case 0x0D:
             other_i=(i&i>>12)*(i>>4|i>>8)^i>>6;
        case 0x0E:
             other_i=i*(((i>>9)^((i>>9)-1)^1)%13);
        case 0x0F:
             other_i=i*(0xCA98>>(i>>9&14)&15)|i>>8;
        default:
             other_i = i* ((i>>11|i>>8)&Pot01&i>>3);
             }
      PORTC = other_i>>Pot02;
      }
    aux00 = Adc_Read(0);
    aux01 = Adc_Read(1);
    aux02 = Adc_Read(2);
    }
  }


Comments:
  • Faster if switch-case replaced.
  • Changing deeper parameters from inside equations causes more interesting variations in sound patterns.
  • It takes a complete for cycle to refresh all parameters, some different loop distribution could add interesting modulations.