diff -urN midi_prog-/buf.c midi_prog/buf.c --- midi_prog-/buf.c Wed Sep 9 00:00:00 2015 +++ midi_prog/buf.c Fri Sep 11 00:00:00 2015 @@ -242,6 +242,17 @@ rbuf_set_dbl(&tb->rb, (int)sridx, v); } +int +tbuf_from_to_num(struct tbuf *tb, double from_sec, double to_sec, int *from_sridx, int *to_sridx) +{ + int from_i = (int) tbuf_sec_to_sridx(tb, from_sec); + int to_i = (int) tbuf_sec_to_sridx(tb, to_sec); + int n = to_i - from_i; + if(from_sridx) *from_sridx = from_i; + if(to_sridx) *to_sridx = to_i; + return MAX(n, 0); +} + /* sbuf */ @@ -292,6 +303,7 @@ tbuf_init(&ab->tb, smp_freq, wsec, is_complex); ab->max_v = 0; ab->sum = 0; + ab->type = 0; } void @@ -307,17 +319,30 @@ } double -abuf_mean(struct abuf *ab, double from_sec, double to_sec) +abuf_get(struct abuf *ab, double sec) +{ + return tbuf_get_dbl(&ab->tb, sec); +} + +double +abuf_sum(struct abuf *ab, double from_sec, double to_sec, int *ret_n) { struct tbuf *tb = &ab->tb; struct rbuf *rb = &tb->rb; - int from_i = (int) tbuf_sec_to_sridx(tb, from_sec); - int to_i = (int) tbuf_sec_to_sridx(tb, to_sec); - int i; + int i, from_i, to_i, n = tbuf_from_to_num(tb, from_sec, to_sec, &from_i, &to_i); double sum = 0; - if(from_i >= to_i) return 0; + if(ret_n) *ret_n = n; for(i=from_i; i 0 ? sum / n : 0; } double @@ -325,11 +350,12 @@ { struct tbuf *tb = &ab->tb; struct rbuf *rb = &tb->rb; - int from_i = (int) tbuf_sec_to_sridx(tb, from_sec); - int to_i = (int) tbuf_sec_to_sridx(tb, to_sec); - int i = from_i, t = i; - double v, tv = rbuf_get_dbl(rb, i); + int from_i, to_i, i, t; + double v, tv; + tbuf_from_to_num(tb, from_sec, to_sec, &from_i, &to_i); + t = i = from_i; + tv = rbuf_get_dbl(rb, i); for(i++; i tv){ tv = v; @@ -338,4 +364,123 @@ } if(ret_sec) *ret_sec = tbuf_sridx_to_sec(tb, t); return tv; +} + + +/* a2buf */ + +void +a2buf_init(struct a2buf *a2b, struct abuf *a, struct abuf *b, + double A2, double B2, double AB, double A, double B, double C) +{ + struct abuf *c = a ? a : b; + + a2b->a = a; + a2b->b = b; + a2b->A2 = A2; + a2b->B2 = B2; + a2b->AB = AB; + a2b->A = A; + a2b->B = B; + a2b->C = C; + + a2b->ab.type = 1; + + a2b->tb = c->type == 0 ? &c->tb : ((struct a2buf *)c)->tb; +} + +static double +a2buf_abuf_get(struct abuf *ab, double sec) +{ + return ab->type == 0 ? abuf_get(ab, sec) : a2buf_get( (struct a2buf *)ab, sec); +} + +double +a2buf_get(struct a2buf *a2b, double sec) +{ + double v_a = a2b->a ? a2buf_abuf_get(a2b->a, sec) : 0; + double v_b = a2b->b ? a2buf_abuf_get(a2b->b, sec) : 0; + double sum = a2b->C; + + if(a2b->A != 0 && v_a != 0) sum += a2b->A * v_a; + if(a2b->B != 0 && v_b != 0) sum += a2b->B * v_b; + + if(a2b->AB != 0 && v_a != 0 && v_b != 0) sum += a2b->AB * v_a * v_b; + + if(a2b->A2 != 0 && v_a != 0) sum += a2b->A2 * v_a * v_a; + if(a2b->B2 != 0 && v_b != 0) sum += a2b->B2 * v_b * v_b; + + return sum; +} + +double +a2buf_sum(struct a2buf *a2b, double from_sec, double to_sec, int *ret_n) +{ + struct tbuf *tb = a2b->tb; + int i, from_i, to_i, n = tbuf_from_to_num(tb, from_sec, to_sec, &from_i, &to_i); + double sum = 0; + if(ret_n) *ret_n = n; + for(i=from_i; i 0 ? sum / n : 0; +} + +double +a2buf_stdev(struct a2buf *a2b, double from_sec, double to_sec, int *ret_n, double *ret_mean) +{ + double mean = a2buf_mean(a2b, from_sec, to_sec, ret_n); + struct a2buf t, t2; + + if(ret_mean) *ret_mean = mean; + a2buf_init(&t, &a2b->ab, NULL, 0,0,0,1,0,mean); + a2buf_init(&t2, &t.ab, NULL, 1,0,0,0,0,0); + return sqrt(a2buf_mean(&t2, from_sec, to_sec, NULL)); +} + +double +a2buf_correlation(struct a2buf *a2b_a, struct a2buf *a2b_b, double from_sec, double to_sec, int *ret_n) +{ + double mean_a, stdev_a = a2buf_stdev(a2b_a, from_sec, to_sec, ret_n, &mean_a); + double mean_b, stdev_b = a2buf_stdev(a2b_b, from_sec, to_sec, NULL, &mean_b); + double div = stdev_a * stdev_b; + struct a2buf ta, tb, t; + + if(div == 0) return 0; + + a2buf_init(&ta, &a2b_a->ab, NULL, 0,0,0,1,0,mean_a); + a2buf_init(&tb, &a2b_b->ab, NULL, 0,0,0,1,0,mean_b); + a2buf_init(&t, &ta.ab, &tb.ab, 0,0,1,0,0,0); + return a2buf_mean(&t, from_sec, to_sec, NULL) / div; +} + +double +a2buf_corr_k(struct a2buf *a2b_a, struct a2buf *a2b_b, double from_sec, double to_sec, int *ret_n) +{ + double stdev_a = a2buf_stdev(a2b_a, from_sec, to_sec, ret_n, NULL); + double stdev_b = a2buf_stdev(a2b_b, from_sec, to_sec, NULL, NULL); + double k_r = 0; + double k_l = stdev_b / stdev_a * 1.2; // !!! + double k, v; + struct a2buf t; + + do{ + k = (k_l + k_r) * 0.5; + a2buf_init(&t, &a2b_a->ab, &a2b_b->ab, 0,0,0,-k,1,0); + v = a2buf_correlation(a2b_a, &t, from_sec, to_sec, NULL); + + if(v < 0) k_l = k; + else k_r = k; + }while(ABS(v) > 0.001); // !!! + return k; } diff -urN midi_prog-/buf.h midi_prog/buf.h --- midi_prog-/buf.h Wed Sep 9 00:00:00 2015 +++ midi_prog/buf.h Fri Sep 11 00:00:00 2015 @@ -63,6 +63,7 @@ double complex tbuf_get_cpx(struct tbuf *tb, double sec); void tbuf_set_dbl(struct tbuf *tb, double sec, double v); +int tbuf_from_to_num(struct tbuf *tb, double from_sec, double to_sec, int *from_sridx, int *to_sridx); struct sbuf{ @@ -81,11 +82,33 @@ struct tbuf tb; double max_v; double sum; + int type; }; void abuf_init(struct abuf *ab, double smp_freq, double wsec); void abuf_add(struct abuf *ab, double v); -double abuf_mean(struct abuf *ab, double from_sec, double to_sec); +double abuf_get(struct abuf *ab, double sec); +double abuf_sum(struct abuf *ab, double from_sec, double to_sec, int *ret_n); +double abuf_mean(struct abuf *ab, double from_sec, double to_sec, int *ret_n); double abuf_max(struct abuf *ab, double from_sec, double to_sec, double *ret_sec); + + +struct a2buf{ + struct abuf ab, *a, *b; + struct tbuf *tb; + + /* A2 * a^2 + B2 * b^2 + AB * a*b + A * a + B * b + C */ + double A2, B2, AB, A, B, C; +}; + +void a2buf_init(struct a2buf *a2b, struct abuf *a, struct abuf *b, + double A2, double B2, double AB, double A, double B, double C); +double a2buf_get(struct a2buf *a2b, double sec); + +double a2buf_sum(struct a2buf *a2b, double from_sec, double to_sec, int *ret_n); +double a2buf_mean(struct a2buf *a2b, double from_sec, double to_sec, int *ret_n); +double a2buf_stdev(struct a2buf *a2b, double from_sec, double to_sec, int *ret_n, double *ret_mean); +double a2buf_correlation(struct a2buf *a2b_a, struct a2buf *a2b_b, double from_sec, double to_sec, int *ret_n); +double a2buf_corr_k(struct a2buf *a2b_a, struct a2buf *a2b_b, double from_sec, double to_sec, int *ret_n); #endif diff -urN midi_prog-/pitch.c midi_prog/pitch.c --- midi_prog-/pitch.c Thu Sep 10 00:00:00 2015 +++ midi_prog/pitch.c Fri Sep 11 00:00:00 2015 @@ -82,7 +82,8 @@ ost->thres = opt_double("-thres", ac, av, 0.03); ost->mean_thres = opt_double("-mean_thres", ac, av, 0.1); - ost->mean = -1; + ost->sum = -1; + ost->n = 0; } int @@ -104,20 +105,24 @@ int onoff = v >= max_v * ost->thres; int chg = chatt_add(&ost->ct, sec, onoff), chg2, chg_v = -1; - if(ost->mean >= 0){ - ost->mean = abuf_mean(ost->ab, ost->on_sec, sec); - chg2 = chatt_add(&ost->ct2, sec, v >= ost->mean * ost->mean_thres); + if(ost->sum >= 0){ + int onoff2; + + ost->sum += v; + ost->n++; + onoff2 = v * ost->n >= ost->sum * ost->mean_thres; + chg2 = chatt_add(&ost->ct2, sec, onoff2); } if(!ost->v){ - if(ost->mean >= 0 && chg2 && ost->ct2.onoff){ + if(ost->sum >= 0 && chg2 && ost->ct2.onoff){ ost->on_sec = ost->ct2.sec; chg_v = 1; }else if(chg && ost->ct.onoff){ ost->on_sec = ost->ct.sec; chg_v = 1; - ost->mean = abuf_mean(ost->ab, ost->on_sec, sec); + ost->sum = abuf_sum(ost->ab, ost->on_sec, sec, &ost->n); chatt_set(&ost->ct2, 1); } }else{ @@ -125,7 +130,7 @@ ost->off_sec = ost->ct.sec; chg_v = 0; - ost->mean = -1; + ost->sum = -1; }else if(chg2 && !ost->ct2.onoff){ ost->off_sec = ost->ct2.sec; chg_v = 0; diff -urN midi_prog-/pitch.h midi_prog/pitch.h --- midi_prog-/pitch.h Thu Sep 10 00:00:00 2015 +++ midi_prog/pitch.h Fri Sep 11 00:00:00 2015 @@ -27,7 +27,8 @@ double thres; double mean_thres; - double mean; + double sum; + int n; }; void onoff_stat_init(struct onoff_stat *ost, struct abuf *ab, int ac, char **av); diff -urN midi_prog-/tool.c midi_prog/tool.c --- midi_prog-/tool.c Thu Sep 10 00:00:00 2015 +++ midi_prog/tool.c Fri Sep 11 00:00:00 2015 @@ -124,7 +124,7 @@ double note_onoff_v(struct note_onoff *nto, double on_sec, double off_sec) { - return abuf_mean(&nto->ab, on_sec, off_sec); + return abuf_mean(&nto->ab, on_sec, off_sec, NULL); } int