From c0d3dcc3c2b6c5e7d5a03b0dc70aa769b2be3810 Mon Sep 17 00:00:00 2001 From: sergm Date: Fri, 24 Mar 2017 21:27:23 +0200 Subject: [PATCH] Further improved mt32emu_alsadrv: - analog emulation mode made configurable - ROM search dir can be specified in command line - ROM search algo is now controlled by a single option, previous behaviour is also retained by default - in the Makefile, added compiler options to suppress various annoying warnings - when installing, roms directory is no longer required (and copied) --- mt32emu_alsadrv/Makefile | 5 +- mt32emu_alsadrv/src/alsadrv.cpp | 120 ++++++++++++++++---------------- mt32emu_alsadrv/src/alsadrv.h | 14 ++-- mt32emu_alsadrv/src/console.cpp | 36 +++++++--- mt32emu_alsadrv/src/xmt32.cpp | 43 +++++++----- 5 files changed, 122 insertions(+), 96 deletions(-) diff --git a/mt32emu_alsadrv/Makefile b/mt32emu_alsadrv/Makefile index 3f27025..a197064 100644 --- a/mt32emu_alsadrv/Makefile +++ b/mt32emu_alsadrv/Makefile @@ -1,4 +1,4 @@ -CXXFLAGS=-O2 -DANALOG_MODE=2 +CXXFLAGS=-O2 -Wno-write-strings -Wno-unused-result -Wno-deprecated-declarations LIBS=-lmt32emu -lm -lasound -lpthread XLIBS=-L/usr/X11R6/lib -lX11 -lXt -lXpm @@ -20,9 +20,6 @@ xmt32: $(OBJS) $(XOBJ) src/xmt32.cpp install: install mt32d /usr/local/bin install xmt32 /usr/local/bin - install -d roms /usr/share/mt32-rom-data - cd roms; install * /usr/share/mt32-rom-data - cd /usr/share/mt32-rom-data; chmod 644 * clean: rm -f *.o *~ diff --git a/mt32emu_alsadrv/src/alsadrv.cpp b/mt32emu_alsadrv/src/alsadrv.cpp index b3f9992..0ba49ef 100644 --- a/mt32emu_alsadrv/src/alsadrv.cpp +++ b/mt32emu_alsadrv/src/alsadrv.cpp @@ -44,7 +44,7 @@ char *recwav_filename = NULL; FILE *recwav_file = NULL; #define PERC_CHANNEL 9 -char rom_path[] = "/usr/share/mt32-rom-data/"; +const char default_rom_dir[] = "/usr/share/mt32-rom-data/"; #include @@ -97,20 +97,11 @@ snd_seq_t *seq_handle = NULL; #define FRAGMENT_SIZE 256 // 2 milliseconds #define PERIOD_SIZE 128 // 1 millisecond -#if ANALOG_MODE == 3 -static const MT32Emu::AnalogOutputMode ANALOG_OUTPUT_MODE = MT32Emu::AnalogOutputMode_OVERSAMPLED; -const int SAMPLE_RATE = 96000; -#elif ANALOG_MODE == 2 -static const MT32Emu::AnalogOutputMode ANALOG_OUTPUT_MODE = MT32Emu::AnalogOutputMode_ACCURATE; -const int SAMPLE_RATE = 48000; -#else -#if ANALOG_MODE == 1 -static const MT32Emu::AnalogOutputMode ANALOG_OUTPUT_MODE = MT32Emu::AnalogOutputMode_COARSE; -#else -static const MT32Emu::AnalogOutputMode ANALOG_OUTPUT_MODE = MT32Emu::AnalogOutputMode_DIGITAL_ONLY; -#endif -const int SAMPLE_RATE = 32000; -#endif +MT32Emu::AnalogOutputMode analog_output_mode = MT32Emu::AnalogOutputMode_ACCURATE; +unsigned int sample_rate = 48000; + +char *rom_dir = NULL; +enum rom_search_type_t rom_search_type; int buffermsec = 100; int minimum_msec = 40; @@ -124,7 +115,7 @@ int events_qd = 0; int tempo = -1, ppq = -1; double timepertick = -1; -double bytespermsec = (double)(SAMPLE_RATE * 2 * 2) / 1000000.0; +double bytespermsec = (double)(sample_rate * 2 * 2) / 1000000.0; int channelmap[16]; int channeluse[16]; @@ -178,7 +169,7 @@ int alsa_set_buffer_time(int msec) unsigned int v, rate, periods; double sec, tpp; - rate = SAMPLE_RATE; + rate = sample_rate; channels = 2; sec = (double)msec / 1000.0; @@ -911,7 +902,7 @@ int init_alsadrv() exit(1); /* create pcm thread if needed */ - alsa_init_pcm(SAMPLE_RATE, 2); + alsa_init_pcm(sample_rate, 2); /* create communication pipe from alsa reader to processor */ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, eventpipe)) @@ -949,7 +940,44 @@ int init_alsadrv() return 0; } -void reload_mt32_core(int rv, int mode) +static bool tryROMFile(const char romDir[], const char filename[], MT32Emu::FileStream &romFile) { + static const int MAX_PATH_LENGTH = 4096; + + if ((strlen(romDir) + strlen(filename) + 1) > MAX_PATH_LENGTH) { + return false; + } + char romPathName[MAX_PATH_LENGTH]; + strcpy(romPathName, romDir); + strcat(romPathName, filename); + return romFile.open(romPathName); +} + +static void openROMFile(const char romDir[], const char romFile1[], const char romFile2[], MT32Emu::FileStream &romFile, const char romType[]) { + switch (rom_search_type) { + case ROM_SEARCH_TYPE_CM32L_ONLY: + if (!tryROMFile(romDir, romFile1, romFile)) { + report(DRV_MT32ROMFAIL, romType); + exit(1); + } + break; + case ROM_SEARCH_TYPE_MT32_ONLY: + if (!tryROMFile(romDir, romFile2, romFile)) { + report(DRV_MT32ROMFAIL, romType); + exit(1); + } + break; + default: + if (!tryROMFile(romDir, romFile1, romFile)) { + if (!tryROMFile(romDir, romFile2, romFile)) { + report(DRV_MT32ROMFAIL, romType); + exit(1); + } + } + break; + } +} + +void reload_mt32_core(int rv) { /* delete core if there is already an instance of it */ if (mt32 != NULL) @@ -965,51 +993,23 @@ void reload_mt32_core(int rv, int mode) MT32Emu::FileStream controlROMFile; MT32Emu::FileStream pcmROMFile; - char controlROMFileName[256]; - if (mode==1) { - strcpy(controlROMFileName, rom_path); - strcat(controlROMFileName, "CM32L_CONTROL.ROM"); - } - else if (mode==2) { - strcpy(controlROMFileName, rom_path); - strcat(controlROMFileName, "MT32_CONTROL.ROM"); - } - else { - report(DRV_MT32ROMFAIL, "Control"); - exit(1); + char romDir[4096]; + if (rom_dir != NULL) { + strcpy(romDir, rom_dir); + strcat(romDir, "/"); + } else { + strcpy(romDir, default_rom_dir); } - if (!controlROMFile.open(controlROMFileName)) { - report(DRV_MT32ROMFAIL, "Control"); - exit(1); - } - - char pcmROMFileName[256]; - - if (mode==1) { - strcpy(pcmROMFileName, rom_path); - strcat(pcmROMFileName, "CM32L_PCM.ROM"); - } - else if (mode==2) { - strcpy(pcmROMFileName, rom_path); - strcat(pcmROMFileName, "MT32_PCM.ROM"); - } - else { - report(DRV_MT32ROMFAIL, "PCM"); - exit(1); - } - - if (!pcmROMFile.open(pcmROMFileName)) { - report(DRV_MT32ROMFAIL, "PCM"); - exit(1); - } + openROMFile(romDir, "CM32L_CONTROL.ROM", "MT32_CONTROL.ROM", controlROMFile, "Control"); + openROMFile(romDir, "CM32L_PCM.ROM", "MT32_PCM.ROM", pcmROMFile, "PCM"); const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile); const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile); /* create MT32Synth object */ mt32 = new MT32Emu::Synth(mt32ReportHandler); - if (mt32->open(*controlROMImage, *pcmROMImage, ANALOG_OUTPUT_MODE) == false) { + if (mt32->open(*controlROMImage, *pcmROMImage, analog_output_mode) == false) { report(DRV_MT32FAIL); exit(1); } @@ -1027,7 +1027,7 @@ void reload_mt32_core(int rv, int mode) mt32->setReverbOutputGain(gain_multiplier); } -int process_loop(int rv, int mode) +int process_loop(int rv) { unsigned char processbuffer[FRAGMENT_SIZE]; unsigned int msg; @@ -1047,7 +1047,7 @@ int process_loop(int rv, int mode) rv_level = 3; consumer_types = 0; - reload_mt32_core(rv, mode); + reload_mt32_core(rv); /* setup poll info */ event_poll.fd = eventpipe[0]; @@ -1201,8 +1201,8 @@ int process_loop(int rv, int mode) break; case EVENT_RESET: - reload_mt32_core(rv, mode); - break; + reload_mt32_core(rv); + break; case EVENT_WAVREC_ON: start_recordwav(); diff --git a/mt32emu_alsadrv/src/alsadrv.h b/mt32emu_alsadrv/src/alsadrv.h index 7c21822..18a4819 100644 --- a/mt32emu_alsadrv/src/alsadrv.h +++ b/mt32emu_alsadrv/src/alsadrv.h @@ -80,19 +80,25 @@ void send_rvtime_sysex(int newtime); void send_rvlevel_sysex(int newlevel); extern int alsa_buffer_size; -extern char rom_path[]; extern int eventpipe[]; extern char *pcm_name; extern double gain_multiplier; +extern MT32Emu::AnalogOutputMode analog_output_mode; +extern unsigned int sample_rate; + +extern char *rom_dir; +extern enum rom_search_type_t { + ROM_SEARCH_TYPE_DEFAULT, + ROM_SEARCH_TYPE_CM32L_ONLY, + ROM_SEARCH_TYPE_MT32_ONLY +} rom_search_type; int init_alsadrv(); -int process_loop(int rv, int mode); +int process_loop(int rv); extern MT32Emu::Synth *mt32; #endif - - diff --git a/mt32emu_alsadrv/src/console.cpp b/mt32emu_alsadrv/src/console.cpp index 62f9588..027c619 100644 --- a/mt32emu_alsadrv/src/console.cpp +++ b/mt32emu_alsadrv/src/console.cpp @@ -134,10 +134,15 @@ void usage(char *argv[]) printf("\n"); printf("-g factor : Gain multiplier (default: 1.0) \n"); + printf("-l mode : Analog emulation mode (0 - Digital, 1 - Coarse," + " 2 - Accurate, 3 - Oversampled 2x, default: 2)\n"); printf("\n"); - printf("-o : Load MT32 Firmware \n"); - printf("-c : Load CM32L Firmware (Default) \n"); + printf("-f romdir : Directory with ROM files to load" + " (default: '/usr/share/mt32-rom-data/')\n"); + printf("-o romsearch : Search algorithm to use when loading ROM files:" + " (0 - try both but CM32-L first, 1 - CM32-L only," + " 2 - MT-32 only, default: 0)\n"); printf("\n"); @@ -149,8 +154,7 @@ int main(int argc, char **argv) { int reverb_switch = 1; int i; - int mode=2; - + /* parse the options */ for (i = 1; i < argc; i++) { @@ -159,12 +163,6 @@ int main(int argc, char **argv) switch(argv[i][1]) { - case 'o': - mode=2; - break; - case 'c': - mode=1; - break; case 'w': i++; if (i == argc) @@ -216,6 +214,22 @@ int main(int argc, char **argv) case 'g': i++; if (i == argc) usage(argv); gain_multiplier = atof(argv[i]); break; + case 'l': i++; if (i == argc) usage(argv); + analog_output_mode = MT32Emu::AnalogOutputMode(atoi(argv[i])); + if (analog_output_mode < MT32Emu::AnalogOutputMode_DIGITAL_ONLY + || MT32Emu::AnalogOutputMode_OVERSAMPLED < analog_output_mode) usage(argv); + sample_rate = MT32Emu::Synth::getStereoOutputSampleRate(analog_output_mode); + break; + + case 'f': i++; if (i == argc) usage(argv); + rom_dir = new char[strlen(argv[i]) + 1]; + strcpy(rom_dir, argv[i]); + break; + case 'o': i++; if (i == argc) usage(argv); + rom_search_type = rom_search_type_t(atoi(argv[i])); + if (rom_search_type < ROM_SEARCH_TYPE_DEFAULT + || ROM_SEARCH_TYPE_MT32_ONLY < rom_search_type) usage(argv); + break; default: usage(argv); @@ -228,7 +242,7 @@ int main(int argc, char **argv) exit(1); } - process_loop(reverb_switch, mode); + process_loop(reverb_switch); return 0; } diff --git a/mt32emu_alsadrv/src/xmt32.cpp b/mt32emu_alsadrv/src/xmt32.cpp index ac5dddf..8916dff 100644 --- a/mt32emu_alsadrv/src/xmt32.cpp +++ b/mt32emu_alsadrv/src/xmt32.cpp @@ -480,14 +480,19 @@ void usage(char *argv[]) printf("-i msec : Minimum (initial) buffer size in milliseconds\n"); printf("\n"); - printf("-d name : ALSA PCM device name (default: \"default\") \n"); + printf("-d name : ALSA PCM device name (default: \"default\")\n"); printf("\n"); printf("-g factor : Gain multiplier (default: 1.0) \n"); + printf("-l mode : Analog emulation mode (0 - Digital, 1 - Coarse," + " 2 - Accurate, 3 - Oversampled 2x, default: 2)\n"); printf("\n"); - printf("-o : Load MT32 Firmware \n"); - printf("-c : Load CM32L Firmware (Default) \n"); + printf("-f romdir : Directory with ROM files to load" + " (default: '/usr/share/mt32-rom-data/')\n"); + printf("-o romsearch : Search algorithm to use when loading ROM files:" + " (0 - try both but CM32-L first, 1 - CM32-L only," + " 2 - MT-32 only, default: 0)\n"); printf("\n"); exit(1); @@ -498,8 +503,7 @@ int main(int argc, char *argv[]) { pthread_t visthread; int i; - int mode=2; - + /* parse the options */ for (i = 1; i < argc; i++) { @@ -508,12 +512,6 @@ int main(int argc, char *argv[]) switch(argv[i][1]) { - case 'o': - mode=2; - break; - case 'c': - mode=1; - break; case 'w': i++; if (i == argc) usage(argv); recwav_filename = (char *)malloc(strlen(argv[i]) + 1); @@ -557,6 +555,22 @@ int main(int argc, char *argv[]) case 'g': i++; if (i == argc) usage(argv); gain_multiplier = atof(argv[i]); break; + case 'l': i++; if (i == argc) usage(argv); + analog_output_mode = MT32Emu::AnalogOutputMode(atoi(argv[i])); + if (analog_output_mode < MT32Emu::AnalogOutputMode_DIGITAL_ONLY + || MT32Emu::AnalogOutputMode_OVERSAMPLED < analog_output_mode) usage(argv); + sample_rate = MT32Emu::Synth::getStereoOutputSampleRate(analog_output_mode); + break; + + case 'f': i++; if (i == argc) usage(argv); + rom_dir = new char[strlen(argv[i]) + 1]; + strcpy(rom_dir, argv[i]); + break; + case 'o': i++; if (i == argc) usage(argv); + rom_search_type = rom_search_type_t(atoi(argv[i])); + if (rom_search_type < ROM_SEARCH_TYPE_DEFAULT + || ROM_SEARCH_TYPE_MT32_ONLY < rom_search_type) usage(argv); + break; default: usage(argv); @@ -581,12 +595,7 @@ int main(int argc, char *argv[]) usleep(10000); } - process_loop(xreverb_switch, mode); + process_loop(xreverb_switch); return 0; } - - - - -