diff -urN midi_prog-/Makefile midi_prog/Makefile --- midi_prog-/Makefile Mon Apr 20 00:00:00 2015 +++ midi_prog/Makefile Tue Apr 21 00:00:00 2015 @@ -6,7 +6,7 @@ OBJS += cui_tone.o CFLAGS += -Wall -I.. -VCD_OBJS = vcd.o in.o filter.o out.o util.o +VCD_OBJS = vcd.o in.o filter.o out.o wrt.o util.o all: $(TARG) vcd diff -urN midi_prog-/vcd.c midi_prog/vcd.c --- midi_prog-/vcd.c Mon Apr 20 00:00:00 2015 +++ midi_prog/vcd.c Tue Apr 21 00:00:00 2015 @@ -3,14 +3,28 @@ #include "filter.h" #include "out.h" #include "ch.h" +#include "wrt.h" struct vcd_rec{ struct filter_rec fl; struct filter_stat_rec stat; struct out_rec *ot; - FILE *ofp; + + int ch, tempo, div4; + int smp_cnt, tm, cnt; + double abs_sum; + int last_v; } vcd_inf[ MIDI_CH_N ]; +int last_tm = 0; + +void +out_delta(int tm) +{ + wrt_delta(tm - last_tm); + last_tm = tm; +} + double vcd_freq(int ch) { @@ -21,32 +35,54 @@ } void -vcd_init(struct vcd_rec *vcd, int ch, double fl_Q, struct out_rec *ot, char *name) +vcd_init(struct vcd_rec *vcd, int ch, double fl_Q, struct out_rec *ot, int tempo, int div4) { - char fname[1024]; - vcd->fl.type = BPF; vcd->fl.freq = vcd_freq(ch); vcd->fl.Q = fl_Q; filter_init(&vcd->fl, &vcd->stat, ot->smp_t); vcd->ot = ot; - sprintf(fname, "%s-%d", name, ch); - vcd->ofp = fopen(fname, "w"); + vcd->ch = ch; + vcd->tempo = tempo; + vcd->div4 = div4; + vcd->smp_cnt = vcd->tm = vcd->cnt = 0; + vcd->abs_sum = 0; + vcd->last_v = 0; } -void -vcd_fini(struct vcd_rec *vcd) +int +is_update_vcd_tm(struct vcd_rec *vcd) { - fclose(vcd->ofp); + int bak = vcd->tm; + vcd->tm = (int)(1000000.0 * vcd->smp_cnt * vcd->div4 * vcd->ot->smp_t / vcd->tempo); + return vcd->tm != bak; } void vcd_out(struct vcd_rec *vcd, double v) { + int vol; + v = filter_out(&vcd->stat, v); - vcd->ot->fp = vcd->ofp; - out_do(vcd->ot, v); + + vcd->smp_cnt++; + vcd->cnt++; + vcd->abs_sum += v < 0 ? -v : v; + + if(!is_update_vcd_tm(vcd)) return; + + v = vcd->abs_sum / vcd->cnt; + vcd->abs_sum = 0; + vcd->cnt = 0; + if(v > 1) v = 1; + + vol = (int)(127 * v); + if(vol == vcd->last_v) return; + + out_delta(vcd->tm); + wrt_vol(vcd->ch, vol); + vcd->last_v = vol; } int @@ -54,18 +90,34 @@ { struct out_rec otr; in_rec_t irec; - char *name = opt_str("-name", ac, av, "test"); double v, fl_Q = opt_double("-Q", ac, av, 1.0); + int tempo = opt_int("-tempo", ac, av, 500000); + int div4 = opt_int("-div4", ac, av, 96); + int note = opt_int("-note", ac, av, 69); int i; out_init(&otr, ac, av); irec = otr; irec.fp = stdin; - for(i=0; i> n*8) & 0xff); +} + +void +set_char2_wrt(char c1, char c2) +{ + set_char(c1); + set_char(c2); +} + +void +set_char3_wrt(char c1, char c2, char c3) +{ + set_char(c1); + set_char(c2); + set_char(c3); +} + +void +wrt_header(int div4) +{ + set_str("MThd"); + set_int(4, 6); + set_int(2, 0); + set_int(2, 1); + set_int(2, div4); + set_str("MTrk"); + set_int(4, 0); +} + +void +wrt_note_onoff(int ch, int note, int onoff, int velo) +{ + int hi = onoff ? 9 : 8; + int low = ch; + set_char3_wrt((hi<<4) | low, note, velo); +} + +void +wrt_prog(int ch, int prog) +{ + int hi = 0xc; + int low = ch; + set_char2_wrt((hi<<4) | low, prog); +} + +void +wrt_ctl_chg(int ch, int type, int v) +{ + int hi = 0xb; + int low = ch; + set_char3_wrt((hi<<4) | low, type, v); +} + +void +wrt_vol(int ch, int vol) +{ + wrt_ctl_chg(ch, 7, vol); +} + +void +wrt_set_tempo(int ch, int tempo) +{ + int hi = 0xf; + int low = ch; + set_char2_wrt((hi<<4) | low, 3); + set_int(3, tempo); +} + +void +wrt_delta(int v) +{ + char buf[8], *bp; + + if(v < 0 || v > 100){ + fprintf(stderr, "v=%d", v); + exit(1); + } + + if(v == 0){ + putchar(0); + return; + } + bp = buf; + while(v){ + *bp++ = v & 0x7f; + v >>= 7; + } + while(--bp != buf) putchar(0x80 | *bp); + putchar(*bp); +} diff -urN midi_prog-/wrt.h midi_prog/wrt.h --- midi_prog-/wrt.h Thu Jan 1 09:00:00 1970 +++ midi_prog/wrt.h Tue Apr 21 00:00:00 2015 @@ -0,0 +1,18 @@ +#ifndef __WRT_H__ + +#include "util.h" + +void set_char(char c); +void set_str(char *s); +void set_int(int n, int v); +void set_char2_wrt(char c1, char c2); +void set_char3_wrt(char c1, char c2, char c3); +void wrt_header(int div4); +void wrt_note_onoff(int ch, int note, int onoff, int velo); +void wrt_prog(int ch, int prog); +void wrt_ctl_chg(int ch, int type, int v); +void wrt_vol(int ch, int vol); +void wrt_set_tempo(int ch, int tempo); +void wrt_delta(int v); + +#endif