diff options
Diffstat (limited to 'src/iemlib1/f2note.c')
-rw-r--r-- | src/iemlib1/f2note.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/iemlib1/f2note.c b/src/iemlib1/f2note.c new file mode 100644 index 0000000..4df6612 --- /dev/null +++ b/src/iemlib1/f2note.c @@ -0,0 +1,189 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iemlib1 written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2003 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include <math.h> +#include <stdio.h> +#include <string.h> + +/* ------ frequency to note plus cents converter --------- */ + +typedef struct _f2note +{ + t_object x_obj; + void *x_outlet_midi; + void *x_outlet_note; + void *x_outlet_cent; + int x_centomidi; + float x_refhz; + float x_refexp; + float x_reflog; + t_symbol *x_set; +} t_f2note; + +static t_class *f2note_class; + +float f2note_mtof(t_f2note *x, float midi) +{ + return(x->x_refexp * exp(0.057762265047 * midi)); +} + +float f2note_ftom(t_f2note *x, float freq) +{ + return (freq > 0 ? 17.31234049 * log(x->x_reflog * freq) : -1500); +} + +void f2note_calc_ref(t_f2note *x) +{ + float ln2=log(2.0); + + x->x_refexp = x->x_refhz*exp(-5.75*ln2); + x->x_reflog = 1.0/x->x_refexp; +} + +static void f2note_make_note(char *str, int midi) +{ + int j,k,l=0; + + j = midi / 12; + k = midi % 12; + if(k <= 5) + { + if(k <= 2) + { + if(k==0) + str[l]='c'; + else if(k==1) + { + str[l++]='#'; + str[l]='c'; + } + else + str[l]='d'; + } + else + { + if(k==3) + { + str[l++]='#'; + str[l]='d'; + } + else if(k==4) + str[l]='e'; + else + str[l]='f'; + } + } + else + { + if(k <= 8) + { + if(k==6) + { + str[l++]='#'; + str[l]='f'; + } + else if(k==7) + str[l]='g'; + else + { + str[l++]='#'; + str[l]='g'; + } + } + else + { + if(k==9) + str[l]='a'; + else if(k==10) + { + str[l++]='#'; + str[l]='a'; + } + else + str[l]='h'; + } + } + + if(j < 4) + { + str[l] -= 'a'; + str[l] += 'A'; + } + l++; + if(j < 3) + { + str[l++] = '0' + (char)(3 - j); + } + else if(j > 4) + { + str[l++] = '0' + (char)(j - 4); + } + str[l] = 0; +} + +static void f2note_bang(t_f2note *x) +{ + int i,j; + t_atom at; + char s[4]; + + i = (x->x_centomidi + 50)/100; + j = x->x_centomidi - 100*i; + outlet_float(x->x_outlet_cent, (float)j); + f2note_make_note(s, i); + SETSYMBOL(&at, gensym(s)); + outlet_anything(x->x_outlet_note, x->x_set, 1, &at); + outlet_float(x->x_outlet_midi, 0.01*(float)(x->x_centomidi)); +} + +static void f2note_float(t_f2note *x, t_floatarg freq) +{ + x->x_centomidi = (int)(100.0*f2note_ftom(x, freq) + 0.5); + f2note_bang(x); +} + +void f2note_ref(t_f2note *x, t_floatarg ref) +{ + x->x_refhz = ref; + f2note_calc_ref(x); +} + +static void *f2note_new(t_floatarg ref) +{ + t_f2note *x = (t_f2note *)pd_new(f2note_class); + + if(ref == 0.0) + ref=440.0; + x->x_refhz = ref; + x->x_centomidi = (int)(100.0*ref + 0.499); + f2note_calc_ref(x); + x->x_outlet_midi = outlet_new(&x->x_obj, &s_float); + x->x_outlet_note = outlet_new(&x->x_obj, &s_list); + x->x_outlet_cent = outlet_new(&x->x_obj, &s_float); + x->x_set = gensym("set"); + return (x); +} + +static void f2note_free(t_f2note *x) +{ +} + +void f2note_setup(void) +{ + f2note_class = class_new(gensym("f2note"), (t_newmethod)f2note_new, (t_method)f2note_free, + sizeof(t_f2note), 0, A_DEFFLOAT, 0); + class_addbang(f2note_class,f2note_bang); + class_addfloat(f2note_class,f2note_float); + class_addmethod(f2note_class, (t_method)f2note_ref, gensym("ref"), A_FLOAT, 0); + class_sethelpsymbol(f2note_class, gensym("iemhelp/help-f2note")); +} |