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