#include #include #include #include #define MSG(s) fprintf(stderr, "%s() %s L%d : %s\n", __func__, __FILE__, __LINE__, s) #define ERR(s) do{ fprintf(stderr, "ERR "); MSG(s); exit(1); }while(0) int bk_buf = -1; int rd(void) { int v; if((v = bk_buf) < 0) return getchar(); bk_buf = -1; return v; } void bk(int v) { if(bk_buf >= 0) ERR("give up"); bk_buf = v; } void rd_str(int n, char *s) { int i; for(i=0; i= ac) return def; return strtol(av[i+1], NULL, 0); } struct out_rec{ int smp_freq, smp_cnt; int bit_len; int sign; int ch_num; int base; int amp; int iv_min; int iv_max; }; void out_init(struct out_rec *ot, int ac, char **av) { ot->smp_freq = opt_int("-r", ac, av, 8000); ot->smp_cnt = 0; ot->bit_len = opt_int("-b", ac, av, 8); if(ot->bit_len != 8 && ot->bit_len != 16) ERR("bit_len"); ot->sign = (opt_idx("-s", ac, av) >= 0); ot->ch_num = opt_int("-c", ac, av, 1); ot->amp = ot->bit_len == 8 ? 127 : 32767; ot->base = ot->sign ? 0 : ot->amp + 1; ot->iv_min = ot->base - (ot->amp + 1); ot->iv_max = ot->base + ot->amp; } void out_do(struct out_rec *ot, double v) { int iv; iv = ot->base + (int)(v *ot->amp); if(iv > ot->iv_max) iv = ot->iv_max; if(iv < ot->iv_min) iv = ot->iv_min; switch(ot->bit_len){ case 8: putchar(iv); break; case 16: putchar(iv & 0xff); putchar((iv >> 8) & 0xff); break; } } void note_onoff(struct out_rec *ot, int onoff, double evt_sec, int ch, int note) { double v, sec, freq, dsec; double vl, vr, pan; double release; int i; if(ch == 9) return; release = 0.3; while((sec = (double)ot->smp_cnt / ot->smp_freq) < evt_sec){ vl = vr = 0; for(i=0; i= release) note_buf_free(i); } if(ot->ch_num == 1){ vl += v; }else{ pan = note_buf[i].ch / 15.0; vl += (1 - pan) * v; vr += pan * v; } } out_do(ot, vl / 16); if(ot->ch_num > 1) out_do(ot, vr / 16); ot->smp_cnt++; } if(onoff){ if((i = note_buf_search(-1, -1, -1)) < 0){ MSG("note_buf full"); return; } note_buf[i].note = note; note_buf[i].ch = ch; note_buf[i].onoff = 1; note_buf[i].on_sec = evt_sec; }else{ if((i = note_buf_search(ch, note, 1)) < 0) return; note_buf[i].onoff = 0; note_buf[i].off_sec = evt_sec; } } int main(int ac, char **av) { int div4, delta_sum; int i, n, v, hi, low, note; double sec; struct out_rec otr; out_init(&otr, ac, av); note_buf_init(); div4 = header(); if(!rd_str_chk(4, "MTrk")) ERR("track id"); v = rd_int(4); /* skip */ hi = low = 0; delta_sum = 0; while((v = rd_delta()) != EOF){ delta_sum += v; sec = (double)delta_sum / div4 * 0.5; if((v = rd()) & 0x80){ hi = (v >> 4) & 0xf; low = v & 0xf; }else bk(v); switch(hi){ case 8: case 9: note = rd(); rd(); /* skip velo */ note_onoff(&otr, hi == 9, sec, low, note); break; case 0xa: case 0xb: case 0xe: rd(); rd(); break; case 0xc: case 0xd: rd(); break; case 0xf: rd(); switch(low){ case 0: while(rd() != 0xf7); break; case 1: case 3: rd(); break; case 2: rd(); rd(); break; case 0xf: n = rd(); for(i=0; i