auduino - no pots, just midi cc data!

1,096 views
Skip to first unread message

mat

unread,
Dec 3, 2010, 12:13:23 PM12/3/10
to Auduino
Hi,
I've rewritten the auduino code to read midi cc values which are used
instead of the potentiometers.
So I've spent an hour learning stuff instead of getting it wired in 5
mins with pots I have upstairs.
While playing around with automation and fast short duration notes I
made it sound like an old drum machine.
I think my change in the code could have caused some artefacts in the
sound, but I can't compare it until I wire up some pots and restore
the original auduino code. It has been working using the spikenzieLabs
serial midi convertor, but that convertor crashes when i send it huge
amounts of cc data, but the auduino is fine !!
I can upload my dodgy (but working) code, if anyone wants to try it or
edit it unto correctness...
It sounds great, very glitchy with fast midi sequences.
thanks,
mat

Eugene Ventimiglia

unread,
Dec 3, 2010, 4:10:09 PM12/3/10
to aud...@googlegroups.com
I'm definitely interested  


--
You received this message because you are subscribed to the Google Groups "Auduino" group.
To post to this group, send email to aud...@googlegroups.com.
To unsubscribe from this group, send email to auduino+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/auduino?hl=en.


mat

unread,
Dec 5, 2010, 9:22:52 AM12/5/10
to Auduino
// Auduino, the Lo-Fi granular synthesiser
//
// by Peter Knight, Tinker.it http://tinker.it
//
// Help: http://code.google.com/p/tinkerit/wiki/Auduino
// More help: http://groups.google.com/group/auduino
//
// Analog in 0: Grain 1 pitch
// Analog in 1: Grain 2 decay
// Analog in 2: Grain 1 decay
// Analog in 3: Grain 2 pitch
// Analog in 4: Grain repetition frequency
//
// Digital 3: Audio out (Digital 11 on ATmega8)
//
// Changelog:
// 19 Nov 2008: Added support for ATmega8 boards
// 21 Mar 2009: Added support for ATmega328 boards
// 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
// 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)


#include <avr/io.h>
#include <avr/interrupt.h>

uint16_t syncPhaseAcc;
uint16_t syncPhaseInc;
uint16_t grainPhaseAcc;
uint16_t grainPhaseInc;
uint16_t grainAmp;
uint8_t grainDecay;
uint16_t grain2PhaseAcc;
uint16_t grain2PhaseInc;
uint16_t grain2Amp;
uint8_t grain2Decay;
uint8_t grainPhaseIncMidiCC;
uint8_t grainDecayMidiCC;
uint8_t grain2PhaseIncMidiCC;
uint8_t grain2DecayMidiCC;
uint8_t midiCCno;
uint8_t midiCCReceive;
uint8_t midiCCflag;

// These used to be the pin numbers to
// Map Analogue channels
// these are now the midi control channels
// i.e midi cc 0 is the grain freq control
// change them to whatever cc numbers you want to control it with.
// #define SYNC_CONTROL (4) // pitch now controlled by
midi notes
#define GRAIN_FREQ_CONTROL (1)
#define GRAIN_DECAY_CONTROL (2)
#define GRAIN2_FREQ_CONTROL (3)
#define GRAIN2_DECAY_CONTROL (4)


// Changing these will also requires rewriting audioOn()

#if defined(__AVR_ATmega8__)
//
// On old ATmega8 boards.
// Output is on pin 11
//
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 5
#define PWM_PIN 11
#define PWM_VALUE OCR2
#define PWM_INTERRUPT TIMER2_OVF_vect
#elif defined(__AVR_ATmega1280__)
//
// On the Arduino Mega
// Output is on pin 3
//
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 7
#define PWM_PIN 3
#define PWM_VALUE OCR3C
#define PWM_INTERRUPT TIMER3_OVF_vect
#else
//
// For modern ATmega168 and ATmega328 boards
// Output is on pin 3
//
#define PWM_PIN 3
#define PWM_VALUE OCR2B
#define LED_PIN 13
#define LED_PORT PORTB
#define LED_BIT 5
#define PWM_INTERRUPT TIMER2_OVF_vect
#endif

// Smooth logarithmic mapping
//
uint16_t antilogTable[] = {

64830,64132,63441,62757,62081,61413,60751,60097,59449,58809,58176,57549,56929,56316,55709,55109,

54515,53928,53347,52773,52204,51642,51085,50535,49991,49452,48920,48393,47871,47356,46846,46341,

45842,45348,44859,44376,43898,43425,42958,42495,42037,41584,41136,40693,40255,39821,39392,38968,

38548,38133,37722,37316,36914,36516,36123,35734,35349,34968,34591,34219,33850,33486,33125,32768
};
uint16_t mapPhaseInc(uint16_t input) {
return (antilogTable[input & 0x3f]) >> (input >> 6);
}

// Stepped chromatic mapping
//
uint16_t midiTable[] = {

17,18,19,20,22,23,24,26,27,29,31,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,

77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,

244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,

732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,

1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,

4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,

10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
22121,23436,24830,26306
};
uint16_t mapMidi(uint16_t input) {
return (midiTable[(1023-input) >> 3]);
}

// Stepped Pentatonic mapping
//
uint16_t pentatonicTable[54] = {

0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,

411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,

3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
};

uint16_t mapPentatonic(uint16_t input) {
uint8_t value = (1023-input) / (1024/53);
return (pentatonicTable[value]);
}

// midi control variables
// ---------------------------
int midi_note = 0;
int get_note = 0;
int key_pressed = 0;

void audioOn() {
#if defined(__AVR_ATmega8__)
// ATmega8 has different registers
TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
TIMSK = _BV(TOIE2);
#elif defined(__AVR_ATmega1280__)
TCCR3A = _BV(COM3C1) | _BV(WGM30);
TCCR3B = _BV(CS30);
TIMSK3 = _BV(TOIE3);
#else
// Set up PWM to 31.25kHz, phase accurate
TCCR2A = _BV(COM2B1) | _BV(WGM20);
TCCR2B = _BV(CS20);
TIMSK2 = _BV(TOIE2);
#endif
}


void setup() {
pinMode(PWM_PIN,OUTPUT);
audioOn();
pinMode(LED_PIN,OUTPUT);
Serial.begin(38400); // added for midi i/o
}

void loop() {
// The loop is pretty simple - it just updates the parameters for
the oscillators.
//
// Avoid using any functions that make extensive use of interrupts,
or turn interrupts off.
// They will cause clicks and poops in the audio.

// Smooth frequency mapping
//syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL)) / 4;

// Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
// syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));

// Stepped pentatonic mapping: D, E, G, A, B
//syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));

// could add switch here to choose between midiIn() and the twisty-
pot pitch control
midiIn();

// grainPhaseInc = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
// grainDecay = analogRead(GRAIN_DECAY_CONTROL) / 8;
// grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
// grain2Decay = analogRead(GRAIN2_DECAY_CONTROL) / 4;

grainPhaseInc = mapPhaseInc(grainPhaseIncMidiCC); // midi
controller data is 7 bits analog in is 8 bit ... so 1/2 the range
grainDecay = (grainDecayMidiCC + 4) / 4; // original
is above +4 is to stop whistling
grain2PhaseInc = mapPhaseInc(grain2PhaseIncMidiCC);
grain2Decay = (grain2DecayMidiCC + 4) * 2;
}

SIGNAL(PWM_INTERRUPT)
{
uint8_t value;
uint16_t output;

syncPhaseAcc += syncPhaseInc;
if (syncPhaseAcc < syncPhaseInc) {
// Time to start the next grain
grainPhaseAcc = 0;
grainAmp = 0x7fff;
grain2PhaseAcc = 0;
grain2Amp = 0x7fff;
LED_PORT ^= 1 << LED_BIT; // Faster than using digitalWrite
}

// Increment the phase of the grain oscillators
grainPhaseAcc += grainPhaseInc;
grain2PhaseAcc += grain2PhaseInc;

// Convert phase into a triangle wave
value = (grainPhaseAcc >> 7) & 0xff;
if (grainPhaseAcc & 0x8000) value = ~value;
// Multiply by current grain amplitude to get sample
output = value * (grainAmp >> 8);

// Repeat for second grain
value = (grain2PhaseAcc >> 7) & 0xff;
if (grain2PhaseAcc & 0x8000) value = ~value;
output += value * (grain2Amp >> 8);

// Make the grain amplitudes decay by a factor every sample
(exponential decay)
grainAmp -= (grainAmp >> 8) * grainDecay;
grain2Amp -= (grain2Amp >> 8) * grain2Decay;

// Scale output to the available range, clipping if necessary
output >>= 9;
if (output > 255) output = 255;

// Output to PWM (this is faster than using analogWrite)
PWM_VALUE = output;
}

// auduino simple midi input routine - should work with midi shields,
// definately works with the serial-midi software interface
downloadable
// from http://www.spikenzielabs.com/SpikenzieLabs/Serial_MIDI.html
// allows midi without extra cabling (other than usual USB).
// Tested on freeduino board, don't have the others to test with.
// Also tested on atmega128 board.. md
// note: if you use the serial<>midi converter above, remember to
select
// 38400 bps when you set it going.
// by Tel Bonic
void midiIn()
{
// read a byte from the serial/midi input
byte incByte = 0;

if (Serial.available() > 0) {
// read an incoming byte out of the stack
incByte = Serial.read();
// un-comment to echo midi data back out if required
// Serial.print(incByte);

// start playing note now we have the byte
if (get_note == 1) {
midi_note = incByte;
get_note = 0;
syncPhaseInc = midiTable[midi_note];
}

// make sure no sounds if nothing playing
if (key_pressed == 0) {
syncPhaseInc = 0;
}

if (midiCCflag == 1) { // is data available
midiCCflag = 0; // reset Control Channel flag
midiCCReceive = 0; // reset CCreceive flag
switch (midiCCno) { // switch on midi controller number

case GRAIN_FREQ_CONTROL:
grainPhaseIncMidiCC = incByte;
break;

case GRAIN_DECAY_CONTROL:
grainDecayMidiCC = incByte;
break;

case GRAIN2_FREQ_CONTROL:
grain2PhaseIncMidiCC = incByte;
break;

case GRAIN2_DECAY_CONTROL:
grain2DecayMidiCC = incByte;
break;
}
}

if (midiCCReceive == 1) {
midiCCno = incByte;
midiCCflag = 1;
}

// Check whats playing
switch (incByte) {
// key pressed on channel 1 - look up a midi table via google if
planning to expand
// Control byte is 144 decimal if "start note on channel 0" is
received.
case 144:
key_pressed = 1;
get_note = 1;
break;
// key up on channel 1
case 128:
key_pressed = 0;
break;
// Midi Controller data on midi Channel 1
case 176:
midiCCReceive = 1;
break;
}
}
}
Reply all
Reply to author
Forward
0 new messages