#include #include #include #include #include #include #include #include #define ALSA_PCM_NEW_HW_PARAMS_API #include void mid_log(char *format, ...) { va_list ap; va_start(ap, format); char msg[1024]; msg[0] = 0; vsprintf(msg, format, ap); fprintf(stderr, "%s\n", msg); va_end(ap); } #include "strings.h" #include "opl3.h" #include "dmx.h" #include "bank.h" #include "audio.h" #define ARGPARSE_DE #include "argparse.h" bool tst_note(aud_handle *dev, bank_instr *instr, opl3_chip *chip, bank_handle *bank, uint32_t samplerate, uint8_t prog, uint8_t note, uint32_t len, uint32_t pause) { if(instr[prog].op == b_op0) { return false; } uint8_t drum = prog >= 128; if(drum) { note = prog - 128; } int16_t buf[2]; if(drum) { mid_log(STR_TST_DRUM, note, instr[128+note].name); bank_noteon(bank, chip, 9, note, 127); } else { mid_log(STR_TST_INSTR, note, prog, instr[prog].name); bank_progchange(bank, chip, 0, prog); bank_noteon(bank, chip, 0, note, 127); } for(int i = 0; i < ((samplerate*len)/1000); i++) { OPL3_GenerateResampled(chip, buf); aud_push(dev, buf); } bank_noteoff(bank, chip, drum ? 9 : 0, note, 0); for(int i = 0; i < ((samplerate*pause)/1000); i++) { OPL3_GenerateResampled(chip, buf); aud_push(dev, buf); } return true; } bool tst_play(uint32_t samplerate, const char *dmxname, const char *drumname, uint8_t usedrum, const char *device, uint32_t fsize, uint32_t bufsize, uint8_t widefmt, uint8_t prog, uint8_t note, uint16_t offset, uint32_t len, uint32_t pause) { bank_instr *instr = bnk_read_banks(dmxname, drumname, usedrum); if(instr == NULL) { return false; } if((offset == 256) && (instr[prog].op == b_op0)) { fprintf(stderr, STR_BNK_UNDEF"\n", prog); free(instr); return false; } opl3_chip *chip = OPL3_Alloc(samplerate, 2); bank_handle *bank = bank_alloc(chip, instr, 0, 0, 0); aud_handle dev; if(aud_open_dev(&dev, device, samplerate, 2, fsize, bufsize, widefmt) ^ 1) { free(instr); free(chip); free(bank); return false; } samplerate = dev.samplerate; OPL3_Rate(chip, samplerate); bool played = false; if(offset != 256) { for(int z = offset; z < 256; z++) { played |= tst_note(&dev, instr, chip, bank, samplerate, z, note, len, pause); } } else { played = tst_note(&dev, instr, chip, bank, samplerate, prog, note, len, pause); } if(played ^ 1) { fprintf(stderr, STR_BNK_NONE"\n"); } aud_flush(&dev); aud_close(&dev); free(instr); free(chip); free(bank); return played; } int main(int argc, char **argv) { int32_t samplerate = 48000; char *device = "default"; int32_t bufsize = 0; int32_t fsize = 32; int32_t widefmt = 0; char *dmxname = NULL; char *drumname = NULL; int32_t usedrum = 0; int32_t prog = 256; int32_t dprog = 256; int32_t mprog = 256; int32_t note = 36; int32_t len = 750; int32_t pause = 250; int32_t offset = 256; argp_t *argspec = arg_alloc(15); arg_add_nstr(argspec, STR_ARGS_BANK, true, &dmxname); arg_add_nint(argspec, STR_ARGS_OFFSET, false, 0, 255, &offset); arg_add_int(argspec, 'r', STR_ARGS_SRATE, 8000, 384000, &samplerate); arg_add_str(argspec, 'd', STR_ARGS_DEVICE, &device); arg_add_int(argspec, 'b', STR_ARGS_BUFFER, 0, 1048576, &bufsize); arg_add_int(argspec, 'f', STR_ARGS_FRAMES, 2, 8192, &fsize); arg_add_bool(argspec, 'w', STR_ARGS_WIDEFT, &widefmt); arg_add_int(argspec, 'n', STR_ARGS_NOTE, 0, 127, ¬e); arg_add_int(argspec, 'l', STR_ARGS_LENGTH, 10, 60000, &len); arg_add_int(argspec, 'p', STR_ARGS_PAUSE, 10, 60000, &pause); arg_add_int(argspec, 'i', STR_ARGS_INSTR, 0, 255, &prog); arg_add_int(argspec, 'm', STR_ARGS_PERC, 0, 127, &mprog); arg_add_int(argspec, 'g', STR_ARGS_DPERC, 0, 46, &dprog); arg_add_str(argspec, 'q', STR_ARGS_DBANK, &drumname); arg_add_bool(argspec, 'Q', STR_ARGS_USEDRM, &usedrum); if(arg_parse(argspec, argc, argv) ^ 1) { return 1; } if(dprog != 256) { if((prog != 256) || (mprog != 256)) { fprintf(stderr, STR_TST_NDDRUM"\n"); return 1; } prog = dprog + 128 + 35; } else if(mprog != 256) { if((prog != 256) || (dprog != 256)) { fprintf(stderr, STR_TST_NMDRUM"\n"); return 1; } prog = mprog + 128; } if((offset != 256) && (prog != 256)) { fprintf(stderr, STR_TST_NOFFS"\n"); return 1; } else if((offset == 256) && (prog == 256)) { offset = 0; } if(tst_play(samplerate, dmxname, drumname, usedrum, device, fsize, bufsize, widefmt, prog, note, offset, len, pause) ^ 1) { return 1; } return 0; }