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(¬e_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; ionoff || note_is_fix(nt)) continue; + if(abs_cent(nt->note_pbend, ¬e) > 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; ich != 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, ¬e) > 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