a2freq.c (2872B)
1 /* a2freq - convert MIDI note numbers or scientific pitch notations to frequencies */ 2 /* by Antoine Amarilli (2011) */ 3 /* licence: public domain */ 4 /* compilation: cc -o a2freq a2freq.c -lm */ 5 6 #include <stdio.h> 7 #include <math.h> 8 #include <ctype.h> 9 10 #define E_ARGS 1 11 #define E_PARSE 2 12 13 int atoi(const char *nptr); 14 15 16 float key2freq(int n) 17 { 18 /* Return frequency of midi note number n, inspired by the "Piano key 19 * frequencies" article on wikipedia */ 20 21 return 440*pow(2, ((float) (n - 69))/12); 22 } 23 24 25 int name2num(char name) 26 { 27 /* Return note number adjustment for upper case scientific pitch 28 * notation note name name. Return <0 on error. */ 29 30 switch(name) 31 { 32 case 'C': 33 return 0; 34 case 'D': 35 return 2; 36 case 'E': 37 return 4; 38 case 'F': 39 return 5; 40 case 'G': 41 return 7; 42 case 'A': 43 return 9; 44 case 'B': 45 return 11; 46 default: 47 return -1; 48 } 49 } 50 51 52 int accid2num(char accid) 53 { 54 /* Return note number adjustment for scientific pitch notation note 55 * accidental. Return 0 on error. */ 56 57 switch (accid) { 58 case 'b': 59 return -1; 60 case '#': 61 return 1; 62 default: 63 return 0; 64 } 65 } 66 67 68 int note2num(int octave, int note) 69 { 70 /* Return MIDI note number for octave and note. */ 71 72 return (octave + 1)*12 + note; 73 } 74 75 76 float pitch2freq(char* a) 77 { 78 /* Return frequency of scientific pitch notation note a, by converting 79 * it to a key number and using key2freq. Return <0 on parse error. */ 80 81 // octavepos position where octave indication is expected 82 int note, octave = 4, accid, octavepos = 1; 83 84 /* parse note name */ 85 if (!a[0]) return -1; 86 note = name2num(toupper(a[0])); 87 if (note < 0) return note; 88 89 /* parse accidental */ 90 if (a[octavepos] && !isdigit(a[octavepos])) { 91 accid = accid2num(a[octavepos]); 92 if (!accid) return -1; 93 note += accid; 94 octavepos++; 95 } 96 97 /* parse octave */ 98 return key2freq(!a[octavepos]? 99 note2num(octave, note): 100 note2num(atoi(a + octavepos), note)); 101 } 102 103 104 float do_one(char* a) 105 { 106 int result; 107 108 if ((result = atoi(a))) 109 return key2freq(result); 110 else return pitch2freq(a); 111 } 112 113 114 int main(int argc, char** argv) 115 { 116 int i; 117 double result; 118 119 if (argc <= 1) { 120 fprintf(stderr, 121 "Usage: %s [NOTE]...\n", argv[0]); 122 fprintf(stderr, 123 "Convert MIDI note numbers or scientific pitch notations to " 124 "frequencies.\n"); 125 fprintf(stderr, 126 "NOTE is either a MIDI note number or a key in scientific pitch " 127 "notation.\n"); 128 fprintf(stderr, 129 "Scientific pitch notation examples: \"A4\", \"C#2\", " "\"Bb6\"\n"); 130 return E_ARGS; 131 } 132 133 for (i=1; i<argc; i++) 134 { 135 result = do_one(argv[i]); 136 if (result >= 0) 137 printf("%f\n", result); 138 else { 139 fprintf(stderr, "a2freq: cannot parse %s\n", argv[i]); 140 return E_PARSE; 141 } 142 } 143 144 return 0; 145 } 146