welcome: please sign in
location: Diff for "MiniArDSP"
Differences between revisions 8 and 10 (spanning 2 versions)
Revision 8 as of 2013-01-18 06:48:19
Size: 1867
Editor: guest
Comment:
Revision 10 as of 2013-01-18 06:52:56
Size: 6085
Editor: guest
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
=== Minimalist Arduino DSP === === Minimalist Arduino DSP (MiniArDSP)===
Line 15: Line 15:
The following is an Arduino library (just a first rev, nothing fancy). Download the zipped file, and uncompress it. The entire folder needs to be placed in you ''libraries'' folder in your user directory. If you are not sure where this is, check out our description in the [[http://wiki.openmusiclabs.com/wiki/AudioCodecShield|CodecShield Wiki]].  Right now there is only one example in the library, and it is a tremolo effect. The following is an Arduino library (just a first rev, nothing fancy). Download the zipped file, and uncompress it. The entire folder needs to be placed in you ''libraries'' folder in your user directory. If you are not sure where this is, check out our description in the [[http://wiki.openmusiclabs.com/wiki/AudioCodecShield|CodecShield Wiki]].
Line 17: Line 17:
 * [[attachement:MiniArDSP.zip|MiniArDSP library]]  * [[attachment:MiniArDSP.zip|MiniArDSP library]]
Line 20: Line 20:

Right now there is only one example in the library, and it is a tremolo effect. It has two buttons, one to increase the tremolo rate, the other to decrease it. It is a full depth tremolo, so you will have to mix some of the original signal back in to get a lower depth. The buttons are very hacked at this point, they need to be tapped rather quickly to make small changes.

{{{#!highlight c
// mini_tremolo.pde
// minimalisitic tremelo program
// guest - openmusiclabs.com - 1.13.13
// takes in audio data from the ADC and plays it out on
// Timer1 PWM. 16b, Phase Correct, 31.25kHz. applies a variable
// frequency tremolo to the sound.

#include "MiniArDSP.h"

#define PWM_FREQ 0x00FF // pwm frequency - see table
#define PWM_MODE 0 // Fast (1) or Phase Correct (0)
#define PWM_QTY 2 // number of pwms, either 1 or 2

// create sinewave lookup table
// PROGMEM stores the values in the program memory
// it is automatically included with MiniArDSP.h
PROGMEM prog_int16_t sinewave[] = {
  // this file is stored in MiniArDSP and is a 1024 value
  // sinewave lookup table of signed 16bit integers
  // you can replace it with your own waveform if you like
  #include <sinetable.inc>
};
unsigned int location; // lookup table value location

byte rate = 5; // tremolo rate
byte rate_counter; // modifiable version of rate
unsigned int amplitude; // current tremolo amplitude
unsigned int button;

void setup() {
  // setup button pins
  PORTD |= 0x0c; // turn on pullups for pins 2 and 3
  
  // setup ADC
  ADMUX = 0x60; // left adjust, adc0, internal vcc
  ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
  ADCSRB =0x07; // t1 capture for trigger
  DIDR0 = 0x01; // turn off digital inputs for adc0
  
  // setup PWM
  TCCR1A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); //
  TCCR1B = ((PWM_MODE << 3) | 0x11); // ck/1
  TIMSK1 = 0x20; // interrupt on capture interrupt
  ICR1H = (PWM_FREQ >> 8);
  ICR1L = (PWM_FREQ & 0xff);
  DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs
  
  TIMSK0 = 0; // turn of t0 - no delay() or millis()
  sei(); // turn on interrupts - not really necessary with arduino
}

void loop() {
  while(1); // gets rid of jitter
  // nothing happens up here. if you want to put code up here
  // get rid of the ISR_NAKED and the reti(); below
}

ISR(TIMER1_CAPT_vect, ISR_NAKED) { // ISR_NAKED is used to save
// clock cycles, but prohibits code in the loop() section.
  
  // get ADC data
  byte temp1 = ADCL; // you need to fetch the low byte first
  byte temp2 = ADCH; // yes it needs to be done this way
  int input = (temp2 << 8) | temp1; // make a signed 16b value
  
  button--; // check buttons every so often
  if (button == 0) {
    byte temp3 = PIND & 0x0c; // get pin 2 and 3 values
    if (temp3 == 0) { // both buttons pressed
    } // do nothing
    else if (temp3 == 0x08) { // up button pressed
      if (rate == 1); // do nothing
      else rate--; // make tremolo faster
    }
    else if (temp3 == 0x04) { // down button pressed
      if (rate == 255); // do nothing
      else rate++; // make tremolo slower
    }
    button = 0x0400; // reset counter
  }

  rate_counter--; // decrement our counter
  if (rate_counter == 0) {
    // create a variable frequency and amplitude sinewave
    // fetch a sample from the lookup table
    amplitude = pgm_read_word_near(sinewave + location) + 0x8000;
    // the + 0x8000 turns the signed value to unsigned
    location++;
    // if weve gone over the table boundary -> loop back
    // around to the other side.
    location &= 0x03ff; // fast way of doing rollover for 2^n numbers
    rate_counter = rate; // reset rate counter
  }
  
 
  // multiply our input by the sinewave value
  // note the use of the special multiply macro
  // this is faster than the normal * method
  // this is a signed * unsigned, returning the high 16 bits
  int output; // define variable before using it
  MultiSU16X16toH16(output, input, amplitude);
  
  // output data
  OCR1AL = (output + 0x8000) >> 8; // convert to unsigned
  // and only output the top byte
  OCR1BL = output; // output the bottom byte
  reti(); // return from interrupt - required because of ISR_NAKED
}
}}}

=== Minimalist Arduino DSP (MiniArDSP)===

About Minimalist Arduino DSP

This is the the most basic setup for doing decent quality audio effects with an Arduino. The system is based upon both our PWM tutorial and our ATmega ADC tutorial. The basic setup is a 10 bit value read in from ADC0, and played out via a 16 bit, Dual PWM on pins 9 and 10. there are 2 buttons, on pins 2 and 3, which can be used to modify parameters. The reason for buttons and not knobs, is that the ADC is already completely consumed with the analog audio signal coming in. This is a more focused version of our basic Arduino PWM setup, targetted at effects pedals.

Hardware setup

The following schematic is the basic version to get started. There will eventually be a better version with a dual opamp, and gain, mix, feedback, and level knobs. But that might take a bit to finish. The 3.9k and 1M resistors should be 1% (or better) if possible. Also, the input signal needs to be from a mixer or other powered device with a low output impedance and strong signal. Plugging a guitar in won't work with this version.

pwm_basic_sm.jpg

Arduino library

The following is an Arduino library (just a first rev, nothing fancy). Download the zipped file, and uncompress it. The entire folder needs to be placed in you libraries folder in your user directory. If you are not sure where this is, check out our description in the CodecShield Wiki.

Example code

Right now there is only one example in the library, and it is a tremolo effect. It has two buttons, one to increase the tremolo rate, the other to decrease it. It is a full depth tremolo, so you will have to mix some of the original signal back in to get a lower depth. The buttons are very hacked at this point, they need to be tapped rather quickly to make small changes.

   1 // mini_tremolo.pde
   2 // minimalisitic tremelo program
   3 // guest - openmusiclabs.com - 1.13.13
   4 // takes in audio data from the ADC and plays it out on
   5 // Timer1 PWM.  16b, Phase Correct, 31.25kHz.  applies a variable
   6 // frequency tremolo to the sound.
   7 
   8 #include "MiniArDSP.h"
   9 
  10 #define PWM_FREQ 0x00FF // pwm frequency - see table
  11 #define PWM_MODE 0 // Fast (1) or Phase Correct (0)
  12 #define PWM_QTY 2 // number of pwms, either 1 or 2
  13 
  14 // create sinewave lookup table
  15 // PROGMEM stores the values in the program memory
  16 // it is automatically included with MiniArDSP.h
  17 PROGMEM  prog_int16_t sinewave[]  = {
  18   // this file is stored in MiniArDSP and is a 1024 value
  19   // sinewave lookup table of signed 16bit integers
  20   // you can replace it with your own waveform if you like
  21   #include <sinetable.inc>
  22 };
  23 unsigned int location; // lookup table value location
  24 
  25 byte rate = 5; // tremolo rate
  26 byte rate_counter; // modifiable version of rate
  27 unsigned int amplitude; // current tremolo amplitude
  28 unsigned int button;
  29 
  30 void setup() {
  31   // setup button pins
  32   PORTD |= 0x0c; // turn on pullups for pins 2 and 3
  33   
  34   // setup ADC
  35   ADMUX = 0x60; // left adjust, adc0, internal vcc
  36   ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
  37   ADCSRB =0x07; // t1 capture for trigger
  38   DIDR0 = 0x01; // turn off digital inputs for adc0
  39   
  40   // setup PWM
  41   TCCR1A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); // 
  42   TCCR1B = ((PWM_MODE << 3) | 0x11); // ck/1
  43   TIMSK1 = 0x20; // interrupt on capture interrupt
  44   ICR1H = (PWM_FREQ >> 8);
  45   ICR1L = (PWM_FREQ & 0xff);
  46   DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs
  47   
  48   TIMSK0 = 0; // turn of t0 - no delay() or millis()
  49   sei(); // turn on interrupts - not really necessary with arduino
  50 }
  51 
  52 void loop() {
  53   while(1); // gets rid of jitter
  54   // nothing happens up here.  if you want to put code up here
  55   // get rid of the ISR_NAKED and the reti(); below
  56 }
  57 
  58 ISR(TIMER1_CAPT_vect, ISR_NAKED) { // ISR_NAKED is used to save
  59 // clock cycles, but prohibits code in the loop() section.
  60   
  61   // get ADC data
  62   byte temp1 = ADCL; // you need to fetch the low byte first
  63   byte temp2 = ADCH; // yes it needs to be done this way
  64   int input = (temp2 << 8) | temp1; // make a signed 16b value
  65   
  66   button--; // check buttons every so often
  67   if (button == 0) {
  68     byte temp3 = PIND & 0x0c; // get pin 2 and 3 values
  69     if (temp3 == 0) { // both buttons pressed
  70     } // do nothing
  71     else if (temp3 == 0x08) { // up button pressed
  72       if (rate == 1); // do nothing
  73       else rate--; // make tremolo faster
  74     }
  75     else if (temp3 == 0x04) { // down button pressed
  76       if (rate == 255); // do nothing
  77       else rate++; // make tremolo slower
  78     }
  79     button = 0x0400; // reset counter
  80   }
  81 
  82   rate_counter--; // decrement our counter
  83   if (rate_counter == 0) {
  84     // create a variable frequency and amplitude sinewave
  85     // fetch a sample from the lookup table
  86     amplitude = pgm_read_word_near(sinewave + location) + 0x8000;
  87     // the + 0x8000 turns the signed value to unsigned
  88     location++;
  89     // if weve gone over the table boundary -> loop back
  90     // around to the other side.
  91     location &= 0x03ff; // fast way of doing rollover for 2^n numbers
  92     rate_counter = rate; // reset rate counter
  93   }
  94   
  95  
  96   // multiply our input by the sinewave value
  97   // note the use of the special multiply macro
  98   // this is faster than the normal * method
  99   // this is a signed * unsigned, returning the high 16 bits
 100   int output; // define variable before using it
 101   MultiSU16X16toH16(output, input, amplitude);
 102   
 103   // output data
 104   OCR1AL = (output + 0x8000) >> 8; // convert to unsigned
 105   // and only output the top byte
 106   OCR1BL = output; // output the bottom byte
 107   reti(); // return from interrupt - required because of ISR_NAKED
 108 }
 109 

MiniArDSP (last edited 2013-09-16 16:48:45 by guest)