/*
Music Theory - Practice Algorithms
Written by Aaron J. Miller (aaron.miller@axiosoftonline.com), 2010
Octave 1 - 110Hz (1x)
Octave 2 - 220Hz (2x)
Octave 3 - 440Hz (4x)
880Hz (8x)
1760Hz (16x)
3520Hz (32x)
et cetera
A, A#, B, C, C#, D, D#, E, F, F#, G, G#
(1/12)
http://home.cc.umanitoba.ca/~krussll/138/sec4/acoust1.htm
http://www.mindspring.com/~scottr/zmusic/
How to combine waves (probably)
(sin(a) + sin(b)) * 0.5
How to generate a sine wave (perhaps)
y(t) = amplitude * sin(angular_frequency*t + phase)
y = array of points
t = some time interval
amplitude = the amplitude of the wave
angular_frequency = "how many oscillations occur in a unit time interval, in radians per second"
phase = the phase of the wave
http://en.wikipedia.org/wiki/Sine_wave
*/
#define NOTE_A 0
#define NOTE_A_SHARP 1
#define NOTE_B 2
#define NOTE_C 3
#define NOTE_C_SHARP 4
#define NOTE_D 5
#define NOTE_D_SHARP 6
#define NOTE_E 7
#define NOTE_F 8
#define NOTE_F_SHARP 9
#define NOTE_G 10
#define NOTE_G_SHARP 11
/* Algorithm: 440 * 2^(n/12) */
double note_freq(unsigned long note, unsigned long octave)
{
double f;
f = pow(2.0, ((double)(note+(octave*12))-24.0)/12.0);
f = f * 440.0;
return f;
}
/* Test the frequency creating algorithm */
void test_note_freq(void)
{
float e, f_sharp, a;
e = (float)note_freq(NOTE_E, 0);
f_sharp = (float)note_freq(NOTE_F_SHARP, 0);
a = (float)note_freq(NOTE_A, 0);
printf("Frequency of E = %.2f\n", e);
printf("Frequency of F# = %.2f\n", f_sharp);
printf("Frequency of A = %.2f\n", a);
}
typedef struct
{
unsigned int string_note[6];
unsigned int string_octave[6];
} guitar_t;
typedef struct
{
unsigned int fret;
unsigned int string;
unsigned int length[2]; // 0 = numerator, 1 = denominator
} tab_note_t;
guitar_t gtr_eadgbe =
{
{ NOTE_E, NOTE_B, NOTE_G, NOTE_D, NOTE_A, NOTE_E },
{ 5, 4, 4, 4, 3, 3 }
};
tab_note_t gtr_tabs[] =
{
{ 14, 0, { 1, 2 } },
{ 15, 0, { 1, 2 } },
{ 12, 0, { 1, 1 } }
};
double convert_tab_to_freq(const guitar_t *pGtr, const tab_note_t *pNote)
{
unsigned int n, o;
double f;
n = pGtr->string_note[pNote->string];
o = pGtr->string_octave[pNote->string];
n += pNote->fret;
f = note_freq(n, o);
return f;
}
void test_tab_to_freq(void)
{
unsigned int num_notes = sizeof(gtr_tabs) / sizeof(tab_note_t);
unsigned int i;
for(i=0; i<num_notes; i++)
{
double f;
f = convert_tab_to_freq(>r_eadgbe, &(gtr_tabs[i]));
printf("string %u, fret %u = %.3f\n", gtr_tabs[i].string, gtr_tabs[i].fret, (float)f);
}
}
/*
Generate a sine wave of the given frequency and length
-resolution is the number of points in the sine wave for the duration given
-length is in seconds
*/
void generate_sine_wave(double *pOut, unsigned int resolution, double length, double frequency, double amplitude, double phase)
{
const double pi = 3.14159265358979323846;
const double one_second = 1.0;
const double one_radian = pi * 2.0;
double time_unit = (one_second/one_radian)/(length/frequency);
unsigned int t;
for(t=0; t<resolution; t++)
pOut[t] = amplitude * sin(((double)t)*time_unit + phase);
}
void test_sine_generator(void)
{
double freq = 440.0;
const unsigned int resolution = 256;
double wave[resolution];
generate_sine_wave(wave, resolution /* resolution */, 1.0 /* length */, freq, 1.0 /* amplitude */, 0.0 /* phase */);
unsigned int i;
for(i=0; i<resolution; i++) {
printf("%.3f\n", wave[i]);
}
}
/* Main App */
int main()
{
test_note_freq();
test_tab_to_freq();
test_sine_generator();
}