66 lines
1.2 KiB
C
66 lines
1.2 KiB
C
/*
|
|
* arngment - random music generator
|
|
*
|
|
* Written in 2020 by Lucas
|
|
*
|
|
* To the extent possible under law, the author(s) have dedicated all
|
|
* copyright and related and neighboring rights to this software to the
|
|
* public domain worldwide. This software is distributed without any
|
|
* warranty.
|
|
*
|
|
* You should have received a copy of the CC0 Public Domain Dedication
|
|
* along with this software. If not, see
|
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include "note.h"
|
|
|
|
static int
|
|
midi(struct note n)
|
|
{
|
|
/* C0 is MIDI note 12 */
|
|
return 12 * (n.octave + 1) + n.offset + n.accident;
|
|
}
|
|
|
|
double
|
|
note_pitch(struct note n)
|
|
{
|
|
int m = midi(n);
|
|
return 440.0 * pow(2.0, (m - 69) / 12.0);
|
|
}
|
|
|
|
int
|
|
note_parse(struct note *note, const char *s)
|
|
{
|
|
/* Semitones from C, starting at A */
|
|
static int offsets[] = {9, 11, 0, 2, 4, 5, 7};
|
|
struct note n;
|
|
|
|
if (*s < 'A' || *s > 'G')
|
|
return 0;
|
|
n.offset = offsets[*s - 'A'];
|
|
s++;
|
|
|
|
if (*s == 'b') {
|
|
n.accident = ACCIDENT_FLAT;
|
|
s++;
|
|
} else if (*s == '#') {
|
|
n.accident = ACCIDENT_SHARP;
|
|
s++;
|
|
} else
|
|
n.accident = ACCIDENT_NATURAL;
|
|
|
|
if (*s < '0' || *s > '9')
|
|
return 0;
|
|
n.octave = *s - '0';
|
|
s++;
|
|
|
|
if (*s != '\0')
|
|
return 0;
|
|
*note = n;
|
|
|
|
return 1;
|
|
}
|