mybin

my ~/bin
git clone https://a3nm.net/git/mybin/
Log | Files | Refs | README

commit b39d78e207dcbebee9ed48dbc0c3be62143a7757
parent 2f656be8e0b89051a4c2b3ffe4cc4c4e5934731e
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Wed, 29 Oct 2014 20:05:10 +0100

+a2freq

Diffstat:
a2freq.c | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 146 insertions(+), 0 deletions(-)

diff --git a/a2freq.c b/a2freq.c @@ -0,0 +1,146 @@ +/* a2freq - convert MIDI note numbers or scientific pitch notations to frequencies */ +/* by Antoine Amarilli (2011) */ +/* licence: public domain */ +/* compilation: cc -lm -o a2freq a2freq.c */ + +#include <stdio.h> +#include <math.h> +#include <ctype.h> + +#define E_ARGS 1 +#define E_PARSE 2 + +int atoi(const char *nptr); + + +float key2freq(int n) +{ + /* Return frequency of midi note number n, inspired by the "Piano key + * frequencies" article on wikipedia */ + + return 440*pow(2, ((float) (n - 69))/12); +} + + +int name2num(char name) +{ + /* Return note number adjustment for upper case scientific pitch + * notation note name name. Return <0 on error. */ + + switch(name) + { + case 'C': + return 0; + case 'D': + return 2; + case 'E': + return 4; + case 'F': + return 5; + case 'G': + return 7; + case 'A': + return 9; + case 'B': + return 11; + default: + return -1; + } +} + + +int accid2num(char accid) +{ + /* Return note number adjustment for scientific pitch notation note + * accidental. Return 0 on error. */ + + switch (accid) { + case 'b': + return -1; + case '#': + return 1; + default: + return 0; + } +} + + +int note2num(int octave, int note) +{ + /* Return MIDI note number for octave and note. */ + + return (octave + 1)*12 + note; +} + + +float pitch2freq(char* a) +{ + /* Return frequency of scientific pitch notation note a, by converting + * it to a key number and using key2freq. Return <0 on parse error. */ + + // octavepos position where octave indication is expected + int note, octave = 4, accid, octavepos = 1; + + /* parse note name */ + if (!a[0]) return -1; + note = name2num(toupper(a[0])); + if (note < 0) return note; + + /* parse accidental */ + if (a[octavepos] && !isdigit(a[octavepos])) { + accid = accid2num(a[octavepos]); + if (!accid) return -1; + note += accid; + octavepos++; + } + + /* parse octave */ + return key2freq(!a[octavepos]? + note2num(octave, note): + note2num(atoi(a + octavepos), note)); +} + + +float do_one(char* a) +{ + int result; + + if ((result = atoi(a))) + return key2freq(result); + else return pitch2freq(a); +} + + +int main(int argc, char** argv) +{ + int i; + double result; + + if (argc <= 1) { + fprintf(stderr, + "Usage: %s [NOTE]...\n", argv[0]); + fprintf(stderr, + "Convert MIDI note numbers or scientific pitch notations to " + "frequencies.\n"); + fprintf(stderr, + "NOTE is either a MIDI note number or a key in scientific pitch " + "notation.\n"); + fprintf(stderr, + "Scientific pitch notation examples: \"A4\", \"C#2\", " "\"Bb6\"\n"); + return E_ARGS; + } + + for (i=1; i<argc; i++) + { + result = do_one(argv[i]); + if (result >= 0) + printf("%f\n", result); + else { + fprintf(stderr, "a2freq: cannot parse %s\n", argv[i]); + return E_PARSE; + } + } + + return 0; +} +