freqout

 
/*  freqout(freq, t)  // freq in hz, t in ms
*   Paul Badger 2007
*   a simple tone generation function
*   generates square waves of arbitrary frequency and duration
*   program also includes a top-octave lookup table & transposition function
*/

#include <math.h>  // requires an Atmega168 chip 

#define outpin 4   // audio out to speaker or amp
int ptime;
int   k,  x, dur, freq, t; 
int i, j;


float ps;         // variable for pow pitchShift routine

float noteval;

// note values for two octave scale
// divide them by powers of two to generate other octaves
float A     = 14080;
float AS    = 14917.2;
float B     = 15804.3;
float C     = 16744;
float CS    = 17739.7;
float D     = 18794.5;
float DS    = 19912.1;
float E     = 21096.2;
float F     = 22350.6;
float FS    = 23679.6;
float G     = 25087.7;
float GS    = 26579.5;
float A2    = 28160;
float A2S   = 29834.5;
float B2    = 31608.5;
float C2    = 33488.1;
float C2S   = 35479.4;
float D2    = 37589.1;
float D2S   = 39824.3;
float E2    = 42192.3;
float F2    = 44701.2;
float F2S   = 47359.3;
float G2    = 50175.4;
float G2S   = 53159;
float A3    = 56320;

//octaves  - corresponds to piano octaves
float oct8 = 4;
float oct7 = 8;
float oct6 = 16;
float oct5 = 32;
float oct4 = 64;
float oct3 = 128;
float oct2 = 256;
float oct1 = 512;
float oct0 = 1024;

//rhythm values
int wh = 1024;
int h  = 512;
int dq = 448;
int q = 256;
int qt = 170;
int de = 192;
int e = 128;
int et = 85;
int dsx = 96;
int sx = 64;
int thx = 32;

// major scale just for demo, hack this

float majScale[] = {
  A,  B,  CS,  D,  E,  FS,  GS,  A2,   B2,  C2S,  D2,  E2,  F2S,  G2S,  A3};

void setup() { 
  Serial.begin(9600);
} 


void loop(){ 
 for(i= 0; i<=11; i++){ 
    ps = (float)i / 12;         // choose new transpose interval every loop
    for(x= 0; x<=15; x++){                      
      noteval = (majScale[x] / oct4) * pow(2,ps);    // transpose scale up 12 tones
// pow function generates transposition
// eliminate " * pow(2,ps) " to cut out transpose routine

      dur = 100;
      freqout((int)noteval, dur);

      delay(10);
    }
  }
} 

void freqout(int freq, int t)  // freq in hz, t in ms
{
  int hperiod;                               //calculate 1/2 period in us
  long cycles, i;
  pinMode(outpin, OUTPUT);                   // turn on output pin

  hperiod = (500000 / freq) - 7;             // subtract 7 us to make up for digitalWrite overhead

  cycles = ((long)freq * (long)t) / 1000;    // calculate cycles
 // Serial.print(freq);
 // Serial.print((char)9);                   // ascii 9 is tab - you have to coerce it to a char to work 
 // Serial.print(hperiod);
 // Serial.print((char)9);
 // Serial.println(cycles);

  for (i=0; i<= cycles; i++){              // play note for t ms 
    digitalWrite(outpin, HIGH); 
    delayMicroseconds(hperiod);
    digitalWrite(outpin, LOW); 
    delayMicroseconds(hperiod - 1);     // - 1 to make up for digitaWrite overhead
  }
pinMode(outpin, INPUT);                // shut off pin to avoid noise from other operations

}

--- Duration extension

Here's some minor tweaks to the above to extend it just a bit. I left the above untouched cause it's simplicity is great. Basically, I changed the array to have durations and added a sentinel to mark the end.

  float EIGHTH = 1;
  float QUARTER = 2;
  float DOTTED_QUARTER =3;
  float HALF = 4;
  float ETERNITY =-1;

  float TEMPO = 150;

  float majScale[] = { A,QUARTER,  B,QUARTER,  CS,QUARTER,  D,QUARTER,  E,QUARTER,  FS,QUARTER,  GS,QUARTER,  A2,QUARTER,  B2,QUARTER,  C2S,QUARTER,  D2,QUARTER,  E2,QUARTER,  F2S,QUARTER,  G2S,QUARTER,  A3,QUARTER, REST,ETERNITY};
  float odeToJoy[] = {F2S,QUARTER, F2S,QUARTER, G2,QUARTER, A3,QUARTER, A3,QUARTER, G2,QUARTER, F2S,QUARTER, E2,QUARTER, D2,QUARTER, D2,QUARTER, 
                    E2,QUARTER, F2S,QUARTER, F2S,DOTTED_QUARTER, E2,EIGHTH, E2,HALF, F2S,QUARTER, F2S,QUARTER, G2,QUARTER, A3,QUARTER, A3,QUARTER,
                    G2,QUARTER, F2S,QUARTER, E2,QUARTER, D2,QUARTER, D2,QUARTER, E2,QUARTER, F2S,QUARTER, E2,DOTTED_QUARTER, D2,EIGHTH, D2,HALF, 
                    E2,QUARTER, E2,QUARTER, F2S,QUARTER, D2,QUARTER, E2,QUARTER, F2S,EIGHTH, G2,EIGHTH, F2S,QUARTER, D2,QUARTER, E2,QUARTER,
                    F2S,EIGHTH, G2,EIGHTH,  F2S,QUARTER, E2,QUARTER, D2,QUARTER, E2,QUARTER, A,QUARTER, REST,ETERNITY};

  void play(float song[])
  {
    for(x= 0; x<10000; x=x+2)
    {                      
      noteval = (song[x] / 64);
      dur = TEMPO * song[x+1];
      if(dur < 0)
        break;
      freqout((int)noteval, dur);
      delay(10);
    }
  }

--- Examples

HappyBirthdayHack

Function Library

Share