diff -urN midi_prog-/Makefile midi_prog/Makefile
--- midi_prog-/Makefile	Mon May 11 00:00:00 2015
+++ midi_prog/Makefile	Wed Jun  3 00:00:00 2015
@@ -1,6 +1,6 @@
 CC = gcc
 LIB = -lm -lpthread -L../cui -lcui
-TARG = prog58
+TARG = prog59
 OBJS = main.o vcf.o ch.o delay.o stat.o note.o env.o tone.o filter.o lfo.o modu.o vco.o wave.o out.o rd.o util.o
 OBJS += rec.o
 OBJS += cui_tone.o
diff -urN midi_prog-/ch.c midi_prog/ch.c
--- midi_prog-/ch.c	Thu Mar 26 00:00:00 2015
+++ midi_prog/ch.c	Wed Jun  3 00:00:00 2015
@@ -48,4 +48,16 @@
 	*vp |= v;
 }
 
+int
+ch_is_bend(int ch)
+{
+	return ch_inf[ch].bend != 0;
+}
+
+double
+ch_bend_rate(int ch)
+{
+	return ch_is_bend(ch) ? pow(2, ch_inf[ch].bend * ch_inf[ch].bend_range * (1.0 / (8192 * 12))) : 1;
+}
+
 /* EOF */
diff -urN midi_prog-/ch.h midi_prog/ch.h
--- midi_prog-/ch.h	Thu Mar 26 00:00:00 2015
+++ midi_prog/ch.h	Wed Jun  3 00:00:00 2015
@@ -21,4 +21,7 @@
 void msb_set(int *vp, int v);
 void lsb_set(int *vp, int v);
 
+int ch_is_bend(int ch);
+double ch_bend_rate(int ch);
+
 #endif
diff -urN midi_prog-/main.c midi_prog/main.c
--- midi_prog-/main.c	Sat Apr 18 00:00:00 2015
+++ midi_prog/main.c	Wed Jun  3 00:00:00 2015
@@ -78,7 +78,7 @@
 
 	tone_init();
 	out_init(&otr, ac, av);
-	note_buf_init();
+	note_init(ac, av);
 	stat_buf_init();
 	ch_init(ac, av);
 
@@ -156,6 +156,7 @@
 			v = rd();
 			v |= rd() << 7;
 			ch_inf[ch].bend = v - 8192;
+			note_update_bend(ch);
 			break;
 		case 0xc: /* program number */
 			v = rd();
diff -urN midi_prog-/note.c midi_prog/note.c
--- midi_prog-/note.c	Thu Mar 26 00:00:00 2015
+++ midi_prog/note.c	Wed Jun  3 00:00:00 2015
@@ -3,11 +3,44 @@
 #include "ch.h"
 
 struct note_rec note_buf[NOTE_BUF_N];
+static int note_pure = 0, note_base = -1, note_pure_cent = 25;
+static double note_base_freq;
+
+static struct{
+	int h, l;
+} pure_tbl[] = {
+	{    1,    1 },	/* C  2 */
+	{ 1600, 1500 },
+	{    9,    8 },	/* D 17 */
+	{  600,  500 },
+	{    5,    4 },	/* E  9 */
+	{  400,  300 }, /* F */
+	{  700,  500 },
+	{    3,    2 },	/* G  5 */
+	{  800,  500 },
+	{  500,  300 }, /* A */
+	{  900,  500 },
+	{   15,    8 },	/* B 23 */
+};
+
+void
+note_init(int ac, char **av)
+{
+	note_pure = opt_idx("-pure", ac, av) >= 0;
+	note_pure_cent = opt_int("-pure_cent", ac, av, note_pure_cent);
+	note_buf_init();
+}
+
+static int
+note_is_free(struct note_rec *nt)
+{
+	return nt->ch < 0;
+}
 
 int
 note_buf_is_free(int i)
 {
-	return note_buf[i].ch < 0;
+	return note_is_free(&note_buf[i]);
 }
 
 void
@@ -38,17 +71,127 @@
 	return -1;
 }
 
+static int
+note_is_fix(struct note_rec *nt)
+{
+	struct stat_rec *stat;
+	int fix = 0;
+
+	if(ch_inf[nt->ch].prog == 0) return 1;
+
+	for(stat=nt->stat_lst; stat; stat=stat->next){
+		struct tone_compo_rec *tone_compo = stat->tone_compo;
+		if(tone_compo == NULL) continue;
+		if(tone_compo->note < 0) return 0;
+		fix = 1;
+	}
+	return fix;
+}
+
 static double
 note_to_freq(int note)
 {
 	return 440 * pow(2, (note - 69) / 12.0);
 }
 
+static double
+freq_to_note(double freq)
+{
+	return (log(freq / 440) / log(2)) * 12 + 69;
+}
+
+static int
+abs_cent(double note_pbend, int *ret_note)
+{
+	int note = (int)(note_pbend + 0.5);
+	int cent = (int)((note_pbend - note) * 100);
+	if(ret_note) *ret_note = note;
+	return cent < 0 ? -cent : cent;
+}
+
+static int
+base_key_val(int base)
+{
+	int i, j, v = 0, min_note = -1, add;
+
+	for(i=0; i<NOTE_BUF_N; i++){
+		struct note_rec *nt = &note_buf[i];
+		int note;
+
+		if(note_is_free(nt) || !nt->onoff || note_is_fix(nt)) continue;
+		if(abs_cent(nt->note_pbend, &note) > note_pure_cent) continue;
+		j = (note - base) % 12;
+		add = pure_tbl[j].h + pure_tbl[j].l;
+		if(ch_is_bend(nt->ch) && add >= 100) continue;
+		v += add;
+		if(min_note < 0 || note < min_note) min_note = note;
+	}
+	return v;
+}
+
+static void
+note_base_update(struct note_rec *nt)
+{
+	int bs, b, v, min_v = -1;
+
+	bs = -1;
+	for(b=0; b<12; b++){
+		if((v = base_key_val(b)) <= 0) continue;
+		if(min_v == -1 || v < min_v){
+			min_v = v;
+			bs = b;
+		}
+	}
+	if(bs < 0 || note_base == bs) return;
+	note_base = bs;
+	note_base_freq = note_to_freq(note_base);
+}
+
+void
+note_update_bend(int ch)
+{
+	int i;
+
+	for(i=0; i<NOTE_BUF_N; i++){
+		struct note_rec *nt = &note_buf[i];
+		if(note_is_free(nt) || nt->ch != ch) continue;
+		if(note_is_fix(nt)) continue;
+		note_update_bend_note(nt);
+	}
+}
+
+void
+note_update_bend_note(struct note_rec *nt)
+{
+	nt->note_pbend = nt->note;
+	nt->freq_pbend = nt->freq = note_to_freq(nt->note);
+	nt->freq_pbend *= ch_bend_rate(nt->ch);
+	if(note_pure){
+		nt->note_pbend = freq_to_note(nt->freq_pbend);
+		note_base_update(nt);
+	}
+}
+
+static double
+pure_freq(struct note_rec *nt)
+{
+	int note, d, oct, i;
+
+	if(abs_cent(nt->note_pbend, &note) > note_pure_cent) return nt->freq_pbend;
+
+	d = note - note_base;
+	oct = d / 12;
+	i = d % 12;
+	if(pure_tbl[i].h <= 0) return nt->freq_pbend;
+
+	return note_base_freq * pow(2, oct) * pure_tbl[i].h / pure_tbl[i].l;
+}
+
 int
 note_out(struct note_rec *nt, double *vl, double *vr)
 {
 	double v, sum_v, freq, pan, env_v, d_env_v;
-	int nch, cnt;
+	int nch, cnt, fix;
 	struct tone_rec *tn;
 	struct tone_compo_rec *tone_compo;
 	struct stat_rec *stat;
@@ -63,10 +206,11 @@
 		if(tone_compo == NULL) continue;
 		cnt++;
 		tn = tone_compo->tone;
-		freq = note_to_freq(tone_compo->note >= 0 ? tone_compo->note : nt->note);
+		fix = tone_compo->note >= 0;
+		freq = fix ? note_to_freq(tone_compo->note) : nt->freq_pbend;
+		if(!fix && note_pure && note_base >= 0) freq = pure_freq(nt);
 
 		if(stat->fst_smp_cnt < 0) stat->fst_smp_cnt = ot->smp_cnt;
-		if(ch_inf[nch].bend != 0) freq *= pow(2, ch_inf[nch].bend * ch_inf[nch].bend_range * (1.0 / (8192 * 12)));
 
 		env_v = env_out(stat, ot->sec);
 		v = (env_v > 0) ? tone_out(stat, freq, env_v) : 0;
@@ -132,6 +276,7 @@
 		nt->onoff = 0;
 		nt->off_sec = evt_sec;
 	}
+	note_update_bend_note(nt);
 }
 
 /* EOF */
diff -urN midi_prog-/note.h midi_prog/note.h
--- midi_prog-/note.h	Sat Jan 25 00:00:00 2014
+++ midi_prog/note.h	Wed Jun  3 00:00:00 2015
@@ -16,14 +16,18 @@
 
 	struct out_rec *ot;
 	struct stat_rec *stat_lst;
+	double freq, freq_pbend, note_pbend;
 };
 
 extern struct note_rec note_buf[NOTE_BUF_N];
 
+void note_init(int ac, char **av);
 int note_buf_is_free(int i);
 void note_buf_free(int i);
 void note_buf_init(void);
 int note_out(struct note_rec *nt, double *vl, double *vr);
 void note_onoff(int onoff, double evt_sec, int ch, int note, int velo);
+void note_update_bend(int ch);
+void note_update_bend_note(struct note_rec *nt);
 
 #endif