Midi Output

224 views
Skip to first unread message

Goatboy

unread,
May 9, 2009, 11:52:41 AM5/9/09
to Auduino
Fantastic!! I now have Midi Out for the pentatonic scale implemented
as "pentatonicTable3" and it works in perfect sync with the Auduino's
audio output however it is constantly outputting Midi (from
pentatonicTable3) even when I toggle the other scales. What I want is
for "pentatnicTable3" to begin only when it's equivalent Auduino scale
(pentatonicTable2) is toggled! In the code for my toggling between
scales this would be (mapMode == 3). I've tried messing with some
ways to do this but it's just not happening.Which is the best or
simplest way to implement this? Thanks Peter, Goatboy

// 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>
// Middle C (MIDI note value 60) is the lowest note we'll play:
#define middleC 60
#define switchPin1 10



// Variables:
char note = 0; // The MIDI note value to be played
int AnalogValue = 0; // value from the analog input
int lastNotePlayed = 0; // note turned on when you press the switch
int lastSwitchState = 0; // state of the switch during previous time
through the main loop
int currentSwitchState = 0;
int value;
int input = analogRead(0);

int switchPin = 2;
//button stuff
int val;
int val2;
int buttonState;
int mapMode = 0;
int phaseMode = 0; //What phase mode mapping are we
using?
char* myMap[4] = {
"Midi", "SmLog", "Penta"};

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;

// Map Analogue channels
#define SYNC_CONTROL (4)
#define GRAIN_FREQ_CONTROL (0)
#define GRAIN_DECAY_CONTROL (2)
#define GRAIN2_FREQ_CONTROL (3)
#define GRAIN2_DECAY_CONTROL (1)


// 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 8
//#define LED_PIN 13 Originally uncommented!
#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]);
}

// Stepped Pentatonic mapping 2
//
uint16_t pentatonicTable2 [55] = {

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 mapPentatonic2(uint16_t input) {
uint8_t value = (1023-input) / (1024/53);
return (pentatonicTable2[value]);
}

// Stepped Pentatonic mapping 3
//
uint16_t pentatonicTable3 [56] = {

0,2,4,7,9,11,14,16,19,21,23,26,28,31,33,35,38,40,43,45,47,50,52,55,57,59,62,64,67,69,71,74,76,79,81,83,86,88,91,93,95,98,100,103,105,107,110,112,115,117,119,122,124,127

};

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


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() {
Serial.begin(31250);
//buttonState = int(val);
buttonState = digitalRead(switchPin); // read the initial state

pinMode(switchPin, INPUT);
pinMode(switchPin1, INPUT);

pinMode(PWM_PIN,OUTPUT);
audioOn();
pinMode(LED_PIN,OUTPUT);

}

void loop() {

// My potentiometer gave a range from 0 to 1023:
pentatonicTable3[value] = (mapPentatonic3(analogRead
(SYNC_CONTROL)));
// convert to a range from 0 to 127:
note = (pentatonicTable3[value]);
currentSwitchState = (pentatonicTable3[value]) ;
// Check to see that the switch is pressed:

if (currentSwitchState > 0) {
// check to see that the switch wasn't pressed last time
// through the main loop:
if (lastSwitchState > 0) {
// set the note value based on the analog value, plus a couple
octaves:
//note = note + 60;
// start a note playing:
noteOn(0x90, note, 0x40);
// save the note we played, so we can turn it off:
lastNotePlayed = note;

}
}
else { // if the switch is not pressed:
// but the switch was pressed last time through the main loop:
if (lastSwitchState > 0) {
// stop the last note played:
noteOn(0x90, lastNotePlayed, 0x00);

}
}

// save the state of the switch for next time
// through the main loop:
lastSwitchState = currentSwitchState;
}


// plays a MIDI note. Doesn't check to see that
// cmd is greater than 127, or that data values are less than 127:

void noteOn(char cmd, char data1, char data2) {
Serial.print(cmd, BYTE);
Serial.print(data1, BYTE);
Serial.print(data2, BYTE);








// Serial.println(digitalRead(switchPin)); // Read the pin and
display the value


//syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL)) / 4;
//syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));
//syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));
//syncPhaseInc = mapPentatonic2(analogRead(SYNC_CONTROL));



val = int(digitalRead(switchPin)); // Read the pin and display
the value); // read input value and store it in val
delay(10); // 10 milliseconds is a good
amount of time
val2 = int(digitalRead(switchPin)); // read the input again to
check for bounces
if (val == val2) { // make sure we got 2 consistant
readings!
if (val != buttonState) { // the button state has changed!
if (val == 0) { // check if the button is pressed
if (mapMode == 0) { // if set to MIDI mapping
mapMode = 1; // switch to smoothfreq mapping
}
else {
if (mapMode == 1) { // if its smoothfreq mapping
mapMode = 2; // switch to pentatonic mapping
}
else {
if (mapMode == 2) { // if its pentatonic mapping
mapMode = 3; // switch to pentatonic mapping2
}

else {
if (mapMode == 3) { // if its pentatonic mapping2
mapMode = 0; // switch to midi mapping
}



}
}
}
}
}
buttonState = val; // save the new state in our
variable
}




// 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.
// Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
if (mapMode == 0) {
syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));
}

if (mapMode == 1) {
syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL))/4;
}


// Stepped pentatonic mapping: D, E, G, A, B
if (mapMode == 2) {
syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));
}

if (mapMode == 3) {
syncPhaseInc = mapPentatonic2(analogRead(SYNC_CONTROL));


}

switch (mapPentatonic3(analogRead(SYNC_CONTROL))) {
case 62:
digitalWrite(8, HIGH);
break;

case 64:
digitalWrite(8,HIGH);
break;

case 67:
digitalWrite(8,HIGH);
break;

case 69:
digitalWrite(8,HIGH);
break;

case 71:
digitalWrite(8,HIGH);
break;

case 74:
digitalWrite(8,HIGH);
break;

case 76:
digitalWrite(8,HIGH);
break;

case 79:
digitalWrite(8,HIGH);
break;

case 81:
digitalWrite(8,HIGH);
break;

case 83:
digitalWrite(8,HIGH);
break;

default:
digitalWrite(8,LOW);
}



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;
}






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;
}
Reply all
Reply to author
Forward
0 new messages