Using a variable from one function in a timer called function

I am trying to use a variable generated in one function that creates an envelope to modulate a sine wave over time - the sine wave generation/modulation occurs in a function that is periodically ran by a timer. The code as it is builds correctly but does not modulate the sine wave over time as intended. I've searched over a number of forum posts/websites and so have seen information on similar problems however when I've tried to implement these I've received errors.

I believe the areas of interest in the code are void synthesis() and void osc_envelopes().

Nb inside the 'synthesis' function, the code for 'OSC1' is how I had it before, with constant modulation from a fixed variable, and the code for 'OSC2' is what I am trying to implement, with the variable 'osc1_inc' being used, as generated in the osc_envelopes function.

I'll just add that I'm pretty new to C++/arduino, as may be evident from looking at the code below, and have been piecing it together as I've gone along.

I think my problem may be something to do with me using void functions and not specifying the variable I'm using, eg unsigned short function(unsigned short x). Any advice about where I'm going wrong would be much appreciated!

/*inital setups*/
#include <SPI.h>

/*digital outs*/
int ledPin = 33;
int latch = 34;
int SCKO = 13;
int SDOO = 11;

/*definitions*/
//sine generation*
unsigned short samp_index1 = 0;
unsigned short samp_index2 = 0;
unsigned short samp_index_mod = 0;
unsigned short KEY_midi = 500;
unsigned short midikeyselect = 500;
unsigned short fm1 = 0;
unsigned short fm2 = 0;

//envelope gubbins
unsigned char env_select = 0;
///filter
unsigned short f_inc = 0;
unsigned char f_attackrate = 0;
unsigned char f_decayrate = 0;
unsigned short f_sustainlevel = 0;
unsigned char f_releaserate = 0;
///amplifier
unsigned short a_inc = 0;
unsigned char a_attackrate = 0;
unsigned char a_decayrate = 0;
unsigned short a_sustainlevel = 0;
unsigned char a_releaserate = 0;
///osc1
unsigned short osc1_inc = 0;
unsigned char osc1_attackrate = 0;
unsigned char osc1_decayrate = 0;
unsigned short osc1_sustainlevel = 0;
unsigned char osc1_releaserate = 0;
///osc2
unsigned short osc2_inc = 0;
unsigned char osc2_attackrate = 0;
unsigned char osc2_decayrate = 0;
unsigned short osc2_sustainlevel = 0;
unsigned char osc2_releaserate = 0;

//misc
int note;
IntervalTimer Srate;
unsigned short note_on = 0;

//envelope definitions
#define f_idlestate 1
#define f_attackstate 2
#define f_decaystate 3
#define f_sustainstate 4
#define f_releasestate 5

#define a_idlestate 6
#define a_attackstate 7
#define a_decaystate 8
#define a_sustainstate 9
#define a_releasestate 10

#define osc_idlestate 11
#define osc_attackstate 12
#define osc_decaystate 13
#define osc_sustainstate 14
#define osc_releasestate 15

/*lookup table*/
unsigned char lookup[256] = {
  128, 130, 133, 135, 138, 140, 143, 145, 148,
  150, 152, 155, 157, 159, 162, 164, 166, 169,
  171, 173, 175, 177, 179, 181, 184, 186, 188,
  190, 191, 193, 195, 197, 199, 200, 202, 204,
  205, 207, 208, 210, 211, 212, 214, 215, 216,
  217, 218, 219, 220, 221, 222, 223, 224, 224,
  225, 226, 226, 227, 227, 227, 228, 228, 228,
  228, 228, 228, 228, 228, 228, 227, 227, 227,
  226, 226, 225, 224, 224, 223, 222, 221, 220,
  219, 218, 217, 216, 215, 214, 212, 211, 210,
  208, 207, 205, 204, 202, 200, 199, 197, 195,
  193, 191, 190, 188, 186, 184, 181, 179, 177,
  175, 173, 171, 169, 166, 164, 162, 159, 157,
  155, 152, 150, 148, 145, 143, 140, 138, 135,
  133, 130, 128, 126, 123, 121, 118, 116, 113,
  111, 108, 106, 104, 101, 99, 97, 94, 92, 90,
  87, 85, 83, 81, 79, 77, 75, 72, 70, 68, 66,
  65, 63, 61, 59, 57, 56, 54, 52, 51, 49, 48,
  46, 45, 44, 42, 41, 40, 39, 38, 37, 36, 35,
  34, 33, 32, 32, 31, 30, 30, 29, 29, 29, 28,
  28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29,
  30, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38,
  39, 40, 41, 42, 44, 45, 46, 48, 49, 51, 52,
  54, 56, 57, 59, 61, 63, 65, 66, 68, 70, 72,
  75, 77, 79, 81, 83, 85, 87, 90, 92, 94, 97,
  99, 101, 104, 106, 108, 111, 113, 116, 118,
  121, 123, 126};

/*assigned possible notes, A0 to A3..*/
unsigned short KEY[] = {
  181, 192, 203, 215, 228,
  241, 256, 271, 287, 304,
  322, 341, 362, 383, 406,
  430, 456, 483, 511, 542,
  574, 608, 644, 683, 723,
  766, 812, 860, 911, 965,
  1023, 1084, 1148, 1216};

/*USB-MIDI setup code*/
///////////////////////////////////////////////////////////////////
void setup(void)
{
  /*pin outs*/
  pinMode(ledPin, OUTPUT);    //LED flash
  pinMode(latch, OUTPUT);
  pinMode(A22, OUTPUT);   //analogue out
  pinMode(SCKO, OUTPUT);
  pinMode(SDOO, OUTPUT);
  digitalWrite(latch, HIGH);

  /*midi setups*/
  usbMIDI.setHandleNoteOff(OnNoteOff);  //midi note on function
  usbMIDI.setHandleNoteOn(OnNoteOn) ;   //midi note off function
  note = (usbMIDI.getData1());    //assign note information

  /*misc setups*/
  analogWriteResolution(8);     //analogue out resolution
  Srate.begin(synthesis, 20);   //synthesis function to run every 25 us
  note_on = 0;
}

/*note on/off functions*/
void OnNoteOn(byte channel, byte note, byte velocity)
{
  digitalWrite(ledPin, HIGH);
  if (note >= 36 && note <= 69)
  {
    KEY_midi = note - 36;
  }
  f_inc = 0;
  a_inc = 0;
  note_on = 1;
}

void OnNoteOff(byte channel, byte note, byte velocity)
{
  digitalWrite(ledPin, LOW);
  note_on = 0;
}

void loop()
{
  usbMIDI.read();
  midikeyselect = KEY_midi;
  digitalWrite(latch, HIGH);
  dac_envelopes();
  osc_envelopes();
}
//////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////
/*main synth gubbins*/
void synthesis()
{
  fm1 = 0;
  
  /*OSC1*/
  samp_index_mod += KEY[midikeyselect];
  samp_index1 += KEY[midikeyselect] + (((unsigned short)lookup[samp_index_mod >> 8]) * fm1) - (256 * fm1);
  analogWrite(A22, lookup[samp_index1 >> 8]);

  /*OSC2*/
  samp_index2 += KEY[midikeyselect] + (((unsigned short)lookup[samp_index_mod >> 8]) * (osc1_inc << 8)) - ( 256 * (osc1_inc << 8));
  analogWrite(A21, lookup[samp_index2 >> 8]);
}

void dac_envelopes()
{
...removed due to post length
}

void osc_envelopes()
{
  osc1_attackrate = 1;
  osc1_decayrate = 1;
  osc1_sustainlevel = 0x8000;
  osc1_releaserate = 1;
  static short fm2 = 10000;

  static char osc_env_state = osc_idlestate;

  switch (osc_env_state)
  {
    case osc_idlestate:
      osc1_inc = 0;
      if (note_on == 1)
      {
        osc_env_state = osc_attackstate;
      }
      else(osc_env_state = osc_idlestate);
      break;

    case osc_attackstate:
      if ((osc1_inc += osc1_attackrate) < (fm2))
      {
        osc1_inc += osc1_attackrate;
      }
      else if (note_on == 0)
      {
        osc_env_state = osc_releasestate;
      }
      else(osc_env_state = osc_decaystate);
      //do note off
      break;

    case osc_decaystate:
      if ((osc1_inc -= osc1_decayrate) > (osc1_sustainlevel))
      {
        osc1_inc -= osc1_decayrate;
      }
      else if (note_on == 0)
      {
        osc_env_state = osc_releasestate;
      }
      else(osc_env_state = osc_sustainstate);
      break;

    case osc_sustainstate:
      if (note_on == 1)
      {
        osc1_inc = osc1_sustainlevel;
      }
      if (note_on == 0)
      {
        osc_env_state = osc_releasestate;
      }
      break;

    case osc_releasestate:
      if (osc1_inc >= osc1_releaserate)
      {
        (osc1_inc -= osc1_releaserate);
      }
      else(osc_env_state = osc_idlestate);
      break;

    default:
      osc1_inc = 0;
      break;
  }
}

its great to compress code and do complicated sums until there's a problem. Some numbers are defined others are reset in functions and a few are created with a preset. There's also "note" that's created inside a function and created in a global which adds to the confusion. A22 is in setup pinmode but A21 isn't. Not sure what arduino has a A21 or A22 pin.

You can either sit down and try to calculate what the arduino is seeing or add a few serial prints to see what the arduino is seeing.

void synthesis()
{
  fm1 = 0;
  
  /*OSC1*/
  samp_index_mod += KEY[midikeyselect];
  samp_index1 += KEY[midikeyselect] + (((unsigned short)lookup[samp_index_mod >> 8]) * fm1) - (256 * fm1);
  analogWrite(A22, lookup[samp_index1 >> 8]);

  /*OSC2*/
  samp_index2 += KEY[midikeyselect] + (((unsigned short)lookup[samp_index_mod >> 8]) * (osc1_inc << 8)) - ( 256 * (osc1_inc << 8));
  analogWrite(A21, lookup[samp_index2 >> 8]);
}

does the code compile ?

Thanks for the response. With regards to 'note', my line of thinking was that I create it as a global variable and then set its value in the setup() - however this works as intended as I have received note information based on this. I should have probably added that I'm using a teensy board with teensyduino so those two pins are analogue outputs. A22 doesn't actually need to be in the setup which is why A21 isn't listed there - they both work correctly without being defined as outputs.

The code compiles fine and, until I created the osc_envelopes() function, the whole code was working exactly as intended. The code for 'OSC1', in void_synthesis(), is how it was when the multiplier is a fixed value, 'fm1' - i.e. a sine wave whose frequency changes depending on the midi key pressed. With 'fm1' changed to a value other than zero, the sine wave becomes frequency modulated. I've attached a screenshot from my oscilloscope displaying both analogue outputs with different values of 'fm'.

I wish to make the modulation occur over time, using the variable 'osc1_inc' that is created and changes in the state machine in void osc_envelopes() - I've attached a screenshot of the same envelope function that outputs to a DAC in void dac_envelopes(), for reference. So it will rise from zero up to a value, then fall, settle and eventually fall back to zero.

Looking at the analogue output shows that it is not operating correctly when multiplied by 'osc1_inc', rather than the fixed value. I'm still getting a sine wave out and it does change upon a key press but not as intended and it doesn't follow the envelope shape - I'd take a screenshot of this but it happens too fast and my oscilloscope isn't great!

I think the problem is because the synthesis() function does not know what 'osc1_inc' is, however I may be wrong about that.

fm-nonefm.JPG

env.JPG