diff -urN midi_prog-/pitch.c midi_prog/pitch.c --- midi_prog-/pitch.c 2015-09-11 00:00:00.000000000 +0900 +++ midi_prog/pitch.c 2015-09-25 00:00:00.000000000 +0900 @@ -1,73 +1,5 @@ #include "pitch.h" -double -pitch_wn(double freq, double next_freq) -{ - /* - wn / (2 * freq) = (wn + 1) / (2 * next_freq) - - next_freq * wn = freq * wn + freq - (next_freq - freq) * wn = freq - - wn = freq / (next_freq - freq) - = 1 / (next_freq / freq - 1) - - - 440 * e( (69-69)/12 * l(2) ) = 440.00000000000000000000 - 440 * e( (70-69)/12 * l(2) ) = 466.16376151808991640200 - - wn = 1 / (466.163761518089916402 / 440 - 1) - = 16.81715374510576755683 - */ - - return freq / (next_freq - freq); -} - -double -pitch_wsec(double freq, double wn) -{ - return 0.5 * wn / freq; -} - -double -pitch_freq(double wsec, double wn) -{ - /* - T = 2 * wsec / wn - f = wn / (2 * wsec) - = 0.5 * wn / wsec - - wsec = 0.5 * wn / freq - freq = 0.5 * wn / wsec - - */ - return 0.5 * wn / wsec; -} - -void -pitch_init(struct pitch *p, double smp_freq, double freq, int wn, - double tick_freq, double abuf_wsec) -{ - p->freq = freq; - p->wn = wn; - sbuf_init(&p->sb, smp_freq, pitch_wsec(p->freq, wn)); - abuf_init(&p->ab, tick_freq, abuf_wsec); -} - -void -pitch_add(struct pitch *p, double v) -{ - struct tbuf *stb = &p->sb.tb; - double sec = tbuf_next_sec(stb); - double complex arg = I * 2 * M_PI * p->freq * sec; - - sbuf_add(&p->sb, v * cexp(-arg)); - - if(tbuf_is_over_sec(&p->ab.tb, sec - stb->wsec * 0.5)){ - abuf_add(&p->ab, cabs( sbuf_sum_mean_all(&p->sb) ) ); - } -} - void onoff_stat_init(struct onoff_stat *ost, struct abuf *ab, int ac, char **av) { @@ -100,8 +32,7 @@ int onoff_stat_add_sec(struct onoff_stat *ost, double sec, double max_v) { - struct tbuf *tb = &ost->ab->tb; - double v = tbuf_get_dbl(tb, sec); + double v = abuf_get(ost->ab, sec); int onoff = v >= max_v * ost->thres; int chg = chatt_add(&ost->ct, sec, onoff), chg2, chg_v = -1; @@ -139,3 +70,73 @@ if(chg_v >= 0) ost->v = chg_v; return chg_v; } + +double +pitch_wn(double freq, double next_freq) +{ + /* + wn / (2 * freq) = (wn + 1) / (2 * next_freq) + + next_freq * wn = freq * wn + freq + (next_freq - freq) * wn = freq + + wn = freq / (next_freq - freq) + = 1 / (next_freq / freq - 1) + + + 440 * e( (69-69)/12 * l(2) ) = 440.00000000000000000000 + 440 * e( (70-69)/12 * l(2) ) = 466.16376151808991640200 + + wn = 1 / (466.163761518089916402 / 440 - 1) + = 16.81715374510576755683 + */ + + return freq / (next_freq - freq); +} + +double +pitch_wsec(double freq, double wn) +{ + return 0.5 * wn / freq; +} + +double +pitch_freq(double wsec, double wn) +{ + /* + T = 2 * wsec / wn + f = wn / (2 * wsec) + = 0.5 * wn / wsec + + wsec = 0.5 * wn / freq + freq = 0.5 * wn / wsec + + */ + return 0.5 * wn / wsec; +} + +void +pitch_init(struct pitch *p, double smp_freq, double freq, int wn, + double tick_freq, double abuf_wsec, int ac, char **av) +{ + p->freq = freq; + p->wn = wn; + sbuf_init(&p->sb, smp_freq, pitch_wsec(p->freq, wn)); + abuf_init(&p->ab, tick_freq, abuf_wsec); + + onoff_stat_init(&p->ost, &p->ab, ac, av); +} + +void +pitch_add(struct pitch *p, double v) +{ + struct tbuf *stb = &p->sb.tb; + double sec = tbuf_next_sec(stb); + double complex arg = I * 2 * M_PI * p->freq * sec; + + sbuf_add(&p->sb, v * cexp(-arg)); + + if(tbuf_is_over_sec(&p->ab.tb, sec - stb->wsec * 0.5)){ + abuf_add(&p->ab, cabs( sbuf_sum_mean_all(&p->sb) ) ); + } +} diff -urN midi_prog-/pitch.h midi_prog/pitch.h --- midi_prog-/pitch.h 2015-09-11 00:00:00.000000000 +0900 +++ midi_prog/pitch.h 2015-09-25 00:00:00.000000000 +0900 @@ -3,21 +3,6 @@ #include "buf.h" -struct pitch{ - double freq; - int wn; - struct sbuf sb; - struct abuf ab; -}; - -double pitch_wn(double freq, double next_freq); -double pitch_wsec(double freq, double wn); -double pitch_freq(double wsec, double wn); - -void pitch_init(struct pitch *p, double smp_freq, double freq, int wn, - double tick_freq, double abuf_wsec); -void pitch_add(struct pitch *p, double v); - struct onoff_stat{ struct abuf *ab; struct chatt ct, ct2; @@ -35,4 +20,21 @@ int onoff_stat_add(struct onoff_stat *ost, double v, double max_v); int onoff_stat_add_sec(struct onoff_stat *ost, double sec, double max_v); +struct pitch{ + double freq; + int wn; + struct sbuf sb; + struct abuf ab; + + struct onoff_stat ost; +}; + +double pitch_wn(double freq, double next_freq); +double pitch_wsec(double freq, double wn); +double pitch_freq(double wsec, double wn); + +void pitch_init(struct pitch *p, double smp_freq, double freq, int wn, + double tick_freq, double abuf_wsec, int ac, char **av); +void pitch_add(struct pitch *p, double v); + #endif diff -urN midi_prog-/pitdet.c midi_prog/pitdet.c --- midi_prog-/pitdet.c 2015-09-09 00:00:00.000000000 +0900 +++ midi_prog/pitdet.c 2015-09-25 00:00:00.000000000 +0900 @@ -37,7 +37,7 @@ if(pd->lmt_sec > 0) while(wn > 1 && wn / (2 * freq) > pd->lmt_sec) wn--; - pitch_init(&pd->arr[j], smp_freq, freq, wn, pd->tick_freq, pd->abuf_wsec); + pitch_init(&pd->arr[j], smp_freq, freq, wn, pd->tick_freq, pd->abuf_wsec, ac, av); } pd->oldest.sec = -1; @@ -51,6 +51,9 @@ pd->save = fp_get("-pd_save", ac, av, NULL, "w", NULL); pd->load = fp_get("-pd_load", ac, av, NULL, "r", NULL); + pd->fin_sec = -1; + + pd->cut_over_tone = opt_idx("-cut_over_tone", ac, av) > 0; } void @@ -137,16 +140,157 @@ if(!pd->newest.update || pd->newest.sec < 0) return; - if(pd->save) pitdet_save(pd); + if(pd->save && pd->fin_sec < 0) pitdet_save(pd); + + pitdet_add_after(pd); +} + +void +pitdet_add_after(struct pitdet *pd) +{ + int j, chg_v; pitdet_shadow_cut(pd, pd->newest.sec); + + for(j=0; jm; j++){ + struct pitch *p = &pd->arr[j]; + chg_v = onoff_stat_add_sec(&p->ost, pd->newest.sec, pd->max_v); + if(pd->cut_over_tone && chg_v == 0) pitdet_cut_overtone(pd, j); + } +} + +static int +freq_n_idx(struct pitdet *pd, int j, double n) +{ + double freq = pd->arr[j].freq * n; + int ret_j = 0; + double ret_d; + + if(freq < pd->arr[0].freq || pd->arr[pd->m-1].freq < freq) return -1; + + ret_d = pd->arr[ ret_j ].freq - freq; + for(j=1; jm; j++){ + double d = pd->arr[j].freq - freq; + if(ABS(d) < ABS(ret_d)){ + ret_d = d; + ret_j = j; + } + } + return ret_j; +} + +struct corr_info{ + double n; + int j; + struct pitch *p; + struct abuf *ab; + struct a2buf t; + double corr; +}; + +static void +corr_info_get(struct pitdet *pd, int j, struct a2buf *a2b, struct onoff_stat *ost, struct corr_info *ci) +{ + if((ci->j = freq_n_idx(pd, j, ci->n)) < 0) return; + ci->p = &pd->arr[ci->j]; + ci->ab = &ci->p->ab; + a2buf_init(&ci->t, ci->ab, NULL, 0,0,0,1,0,0); + ci->corr = a2buf_correlation(a2b, &ci->t, ost->on_sec, ost->off_sec, NULL); +} + +static void +cut_tone(struct a2buf *low, struct a2buf *hi, struct onoff_stat *ost) +{ + int from_i, to_i, i; + struct a2buf t; + struct tbuf *tb; + double k = a2buf_corr_k(low, hi, ost->on_sec, ost->off_sec, NULL); + + a2buf_init(&t, &low->ab, &hi->ab, 0,0,0,-k,1,0); + tb = hi->tb; + tbuf_from_to_num(hi->tb, ost->on_sec, ost->off_sec, &from_i, &to_i); + for(i=from_i; irb, i, v); + } + +#if 0 + a2buf_init(&t, &low->ab, NULL, 0,0,0,1+k,0,0); + tb = low->tb; + tbuf_from_to_num(tb, ost->on_sec, ost->off_sec, &from_i, &to_i); + for(i=from_i; irb, i, v); + } +#endif +} + +static void +recalc_onoff_stat(struct pitdet *pd, struct pitch *p) +{ + struct tbuf *tb = &p->ab.tb; + int from_i, to_i, i; + struct onoff_stat *ost = &p->ost; + + ost->v = 0; + ost->on_sec = -1; + ost->off_sec = 0; + ost->sum = -1; + ost->n = 0; + + tbuf_from_to_num(tb, pd->oldest.sec, pd->newest.sec, &from_i, &to_i); + for(i=from_i; i<=to_i; i++){ + double sec = tbuf_sridx_to_sec(tb, i); + onoff_stat_add_sec(ost, sec, pd->max_v); + } +} + +void +pitdet_cut_overtone(struct pitdet *pd, int j) +{ + struct corr_info ci[] = { + //{ 1.0/2 }, { 1.0/3 }, { 1.0/4 }, + { 2 }, { 3 }, { 4 } + }; + int i, n = ARR_N(ci); + struct pitch *p = &pd->arr[j]; + struct onoff_stat *ost = &p->ost; + struct a2buf a2b; + + a2buf_init(&a2b, &p->ab, NULL, 0,0,0,1,0,0); + + for(;;){ + int near_i = -1; + double near_v; + + for(i=0; iarr[j]; - return tbuf_get_dbl(&p->ab.tb, sec); + return abuf_get(&p->ab, sec); } static void @@ -174,8 +318,8 @@ } } -int -pitdet_load(struct pitdet *pd) +static int +pitdet_load_inner(struct pitdet *pd) { int j; @@ -187,6 +331,32 @@ if(rd_dbl(pd->load, &v) == EOF) return EOF; abuf_add(&p->ab, v); } + pd->oldest.sec = tbuf_oldest_sec(&pd->arr[0].ab.tb); + return 0; +} + +static void +pitdet_load_dmy(struct pitdet *pd) +{ + int j; + + pd->newest.sec += 1.0 / pd->tick_freq; + for(j=0; jm; j++){ + struct pitch *p = &pd->arr[j]; + abuf_add(&p->ab, 0); + } + pd->oldest.sec = tbuf_oldest_sec(&pd->arr[0].ab.tb); +} + +int +pitdet_load(struct pitdet *pd) +{ + if(pd->fin_sec < 0){ + if(pitdet_load_inner(pd) == EOF) pd->fin_sec = pd->newest.sec; + return 0; + } + if(pd->oldest.sec >= pd->fin_sec) return EOF; + pitdet_load_dmy(pd); return 0; } diff -urN midi_prog-/pitdet.h midi_prog/pitdet.h --- midi_prog-/pitdet.h 2015-09-08 00:00:00.000000000 +0900 +++ midi_prog/pitdet.h 2015-09-25 00:00:00.000000000 +0900 @@ -30,6 +30,9 @@ } *wk; FILE *save, *load; + double fin_sec; + + int cut_over_tone; }; double pitdet_note_to_freq(struct pitdet *pd, double note); @@ -38,6 +41,8 @@ void pitdet_init(struct pitdet *pd, double smp_freq, int ac, char **av); void pitdet_shadow_cut(struct pitdet *pd, double sec); void pitdet_add(struct pitdet *pd, double v); +void pitdet_add_after(struct pitdet *pd); +void pitdet_cut_overtone(struct pitdet *pd, int j); double pitdet_get(struct pitdet *pd, int j, double sec); void pitdet_save(struct pitdet *pd); diff -urN midi_prog-/tool.c midi_prog/tool.c --- midi_prog-/tool.c 2015-09-11 00:00:00.000000000 +0900 +++ midi_prog/tool.c 2015-09-25 00:00:00.000000000 +0900 @@ -105,7 +105,6 @@ struct pitdet *pd; int note; double pre_release; - int cut_over_tone; int onoff; } note_onoff[ NOTE_N ]; @@ -117,7 +116,6 @@ nto->pd = pd; nto->note = note; nto->pre_release = opt_double("-pre_release", ac, av, 0); - nto->cut_over_tone = opt_idx("-cut_over_tone", ac, av) > 0; nto->onoff = 0; } @@ -162,7 +160,7 @@ } void -note_onoff_add(struct note_onoff *nto, double sec, int onoff, double v, int ch) +note_onoff_add(struct note_onoff *nto, double sec, double v, int ch) { double on_sec, off_sec; int tick, velo, chg_v; @@ -185,7 +183,6 @@ } if((velo = note_onoff_velo(nto, on_sec, off_sec)) == 0) return; - if(nto->cut_over_tone && note_onoff_is_overtone(nto, on_sec, off_sec)) return; tick = pitdet_sec_to_tick(nto->pd, on_sec); printf("abs=%08d %s ch=%d note=%d velo=%d\n", @@ -201,22 +198,37 @@ static void midi_out(struct pitdet *pd) { - double sec = pd->newest.sec; + double sec = pd->oldest.sec; int i, k; int ch = 0; + if(sec < 0) return; + for(i=0; idiv; k++){ int j = i * pd->div + k; v = pitdet_get(pd, j, sec); - int o = pitdet_onoff_judge(pd, v); - onoff |= o; - if(o) sum += MAX(v, 0); + sum += MAX(v, 0); } v = sum; - note_onoff_add(¬e_onoff[i], sec, onoff, v, ch); + note_onoff_add(¬e_onoff[i], sec, v, ch); + } +} + +static void +show_sec(struct pitdet *pd) +{ + static int osec = -1, nsec = -1; + int os, ns; + + os = (int)pd->oldest.sec; + ns = (int)pd->newest.sec; + + if(os != osec || ns != nsec){ + osec = os; + nsec = ns; + fprintf(stderr, "%d..%d sec \r", osec, nsec); } } @@ -226,12 +238,10 @@ in_rec_t in; double v; int i; - struct pitdet pd; int show = opt_idx("-show", ac, av) > 0; int midi = opt_idx("-midi", ac, av) > 0; int abuf_wsec_chk = opt_idx("-abuf_wsec_chk", ac, av) > 0; - int sec, s; FILE *pd_load = fp_get("-pd_load", ac, av, NULL, "r", NULL); in_init(&in, ac, av, NULL); @@ -251,25 +261,26 @@ while(pd_load){ if(pitdet_load(&pd) == EOF) return 0; - pitdet_shadow_cut(&pd, pd.newest.sec); + pitdet_add_after(&pd); - if((s = (int)pd.newest.sec) != sec){ - sec = s; - fprintf(stderr, "%d sec \r", sec); - } + show_sec(&pd); if(show) show_spectre(&pd, ac, av); if(midi) midi_out(&pd); } - while(in_do_mono(&in, &v) != EOF){ + for(;;){ + if(pd.fin_sec < 0){ + if(in_do_mono(&in, &v) == EOF) pd.fin_sec = pd.newest.sec; + }else{ + if(pd.oldest.sec >= pd.fin_sec) break; + v = 0; + } + pitdet_add(&pd, v); if(!pd.newest.update) continue; - if((s = (int)pd.newest.sec) != sec){ - sec = s; - fprintf(stderr, "%d sec \r", sec); - } + show_sec(&pd); if(pd.newest.sec < 0) continue;