mirror of
https://github.com/VARCem/munt.git
synced 2026-07-08 18:16:13 +00:00
Further improved DOSBox patches:
- definitions of newly added options moved to a separate file src/mt32options.h to facilitate merge - types of many options changed to more appropriate - introduced two options mt32.chunk and mt32.prebuffer to control rendering in threading mode - fixed memory leak when the synth fails to open
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
commit c941deb824acd8c5f40e420ed077015f0d3f38e8
|
||||
commit 826a8c8b41a9c37a1de358321636510027a28469
|
||||
Author: sergm <sergm@bigmir.net>
|
||||
Date: Tue Dec 2 09:18:57 2014 +0200
|
||||
Date: Tue Dec 2 21:43:35 2014 +0200
|
||||
|
||||
mt32emu patch
|
||||
|
||||
@@ -15,7 +15,7 @@ index 184469e..286638d 100644
|
||||
-
|
||||
+LIBS += -lmt32emu
|
||||
diff --git a/src/dosbox.cpp b/src/dosbox.cpp
|
||||
index a4bf564..6d7f1e8 100644
|
||||
index a4bf564..ad65fe6 100644
|
||||
--- a/src/dosbox.cpp
|
||||
+++ b/src/dosbox.cpp
|
||||
@@ -467,7 +467,7 @@ void DOSBOX_Init(void) {
|
||||
@@ -27,91 +27,11 @@ index a4bf564..6d7f1e8 100644
|
||||
Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent");
|
||||
Pstring->Set_values(mputypes);
|
||||
Pstring->Set_help("Type of MPU-401 to emulate.");
|
||||
@@ -480,6 +480,88 @@ void DOSBOX_Init(void) {
|
||||
@@ -480,6 +480,8 @@ void DOSBOX_Init(void) {
|
||||
Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n"
|
||||
" See the README/Manual for more details.");
|
||||
|
||||
+ Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,"");
|
||||
+ Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n"
|
||||
+ " Accepted file names are as follows:\n"
|
||||
+ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n"
|
||||
+ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file.\n");
|
||||
+
|
||||
+ const char *mt32ReverseStereo[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.reverse.stereo",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32ReverseStereo);
|
||||
+ Pstring->Set_help("Reverse stereo channels for MT-32 output");
|
||||
+
|
||||
+ const char *mt32log[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.verbose",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32log);
|
||||
+ Pstring->Set_help("MT-32 debug logging");
|
||||
+
|
||||
+ const char *mt32thread[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.thread",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32thread);
|
||||
+ Pstring->Set_help("MT-32 rendering in separate thread");
|
||||
+
|
||||
+ const char *mt32DACModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.dac",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32DACModes);
|
||||
+ Pstring->Set_help("MT-32 DAC input emulation mode\n"
|
||||
+ "Nice = 0 - default\n"
|
||||
+ "Produces samples at double the volume, without tricks.\n"
|
||||
+ "Higher quality than the real devices\n\n"
|
||||
+
|
||||
+ "Pure = 1\n"
|
||||
+ "Produces samples that exactly match the bits output from the emulated LA32.\n"
|
||||
+ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
|
||||
+ "Much less likely to overdrive than any other mode.\n"
|
||||
+ "Half the volume of any of the other modes.\n"
|
||||
+ "Perfect for developers while debugging :)\n\n"
|
||||
+
|
||||
+ "GENERATION1 = 2\n"
|
||||
+ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
|
||||
+
|
||||
+ "GENERATION2 = 3\n"
|
||||
+ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14\n");
|
||||
+
|
||||
+ const char *mt32analogModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.analog",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32analogModes);
|
||||
+ Pstring->Set_help("MT-32 analogue output emulation mode\n"
|
||||
+ "Digital = 0\n"
|
||||
+ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n"
|
||||
+ "Fastest mode.\n\n"
|
||||
+
|
||||
+ "Coarse = 1\n"
|
||||
+ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n"
|
||||
+ "A bit better sounding but also a bit slower.\n\n"
|
||||
+
|
||||
+ "Accurate = 2 - default\n"
|
||||
+ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n"
|
||||
+ "which is passed through the LPF circuit without significant attenuation.\n"
|
||||
+ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n"
|
||||
+
|
||||
+ "Oversampled = 3\n"
|
||||
+ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n"
|
||||
+ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer.\n");
|
||||
+
|
||||
+ const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32reverbModes);
|
||||
+ Pstring->Set_help("MT-32 reverb mode");
|
||||
+
|
||||
+ const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+ Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
|
||||
+ Pint->Set_values(mt32reverbTimes);
|
||||
+ Pint->Set_help("MT-32 reverb decaying time");
|
||||
+
|
||||
+ const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+ Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
|
||||
+ Pint->Set_values(mt32reverbLevels);
|
||||
+ Pint->Set_help("MT-32 reverb level");
|
||||
+#include "mt32options.h"
|
||||
+
|
||||
#if C_DEBUG
|
||||
secprop=control->AddSection_prop("debug",&DEBUG_Init);
|
||||
@@ -145,10 +65,10 @@ index 61d15e5..0ec8ebc 100644
|
||||
Bitu cmd_len;
|
||||
diff --git a/src/gui/midi_mt32.cpp b/src/gui/midi_mt32.cpp
|
||||
new file mode 100644
|
||||
index 0000000..902651e
|
||||
index 0000000..82bcc96
|
||||
--- /dev/null
|
||||
+++ b/src/gui/midi_mt32.cpp
|
||||
@@ -0,0 +1,247 @@
|
||||
@@ -0,0 +1,248 @@
|
||||
+#include <SDL_thread.h>
|
||||
+#include <SDL_timer.h>
|
||||
+#include <SDL_endian.h>
|
||||
@@ -161,8 +81,6 @@ index 0000000..902651e
|
||||
+#include "midi_mt32.h"
|
||||
+
|
||||
+static const Bitu MILLIS_PER_SECOND = 1000;
|
||||
+static const Bitu MINIMUM_RENDER_MILLIS = 16;
|
||||
+static const Bitu AUDIO_LATENCY_MILLIS = 2 * MINIMUM_RENDER_MILLIS;
|
||||
+
|
||||
+MidiHandler_mt32 &MidiHandler_mt32::GetInstance() {
|
||||
+ static MidiHandler_mt32 midiHandler_mt32;
|
||||
@@ -227,13 +145,12 @@ index 0000000..902651e
|
||||
+ const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile);
|
||||
+ const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile);
|
||||
+
|
||||
+ MT32Emu::AnalogOutputMode analogOutputMode = MT32Emu::AnalogOutputMode_ACCURATE;
|
||||
+ if (strcmp(section->Get_string("mt32.analog"), "auto") != 0) {
|
||||
+ analogOutputMode = (MT32Emu::AnalogOutputMode)atoi(section->Get_string("mt32.analog"));
|
||||
+ }
|
||||
+ MT32Emu::AnalogOutputMode analogOutputMode = (MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog");
|
||||
+
|
||||
+ synth = new MT32Emu::Synth(&reportHandler);
|
||||
+ if (!synth->open(*controlROMImage, *pcmROMImage, analogOutputMode)) {
|
||||
+ delete synth;
|
||||
+ synth = NULL;
|
||||
+ LOG_MSG("MT32: Error initialising emulation");
|
||||
+ return false;
|
||||
+ }
|
||||
@@ -249,13 +166,11 @@ index 0000000..902651e
|
||||
+ synth->setReverbOverridden(true);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(section->Get_string("mt32.dac"), "auto") != 0) {
|
||||
+ synth->setDACInputMode((MT32Emu::DACInputMode)atoi(section->Get_string("mt32.dac")));
|
||||
+ }
|
||||
+ synth->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
|
||||
+
|
||||
+ synth->setReversedStereoEnabled(strcmp(section->Get_string("mt32.reverse.stereo"), "on") == 0);
|
||||
+ noise = strcmp(section->Get_string("mt32.verbose"), "on") == 0;
|
||||
+ renderInThread = strcmp(section->Get_string("mt32.thread"), "on") == 0;
|
||||
+ synth->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
|
||||
+ noise = section->Get_bool("mt32.verbose");
|
||||
+ renderInThread = section->Get_bool("mt32.thread");
|
||||
+
|
||||
+ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", synth->getStereoOutputSampleRate());
|
||||
+ chan = MIXER_AddChannel(mixerCallBack, synth->getStereoOutputSampleRate(), "MT32");
|
||||
@@ -264,8 +179,14 @@ index 0000000..902651e
|
||||
+ renderPos = 0;
|
||||
+ playPos = 0;
|
||||
+ sampleRateRatio = MT32Emu::SAMPLE_RATE / (double)synth->getStereoOutputSampleRate();
|
||||
+ minimumRenderFrames = (MINIMUM_RENDER_MILLIS * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ framesPerAudioBuffer = (AUDIO_LATENCY_MILLIS * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ int chunkSize = section->Get_int("mt32.chunk");
|
||||
+ minimumRenderFrames = (chunkSize * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ int latency = section->Get_int("mt32.prebuffer");
|
||||
+ if (latency <= chunkSize) {
|
||||
+ latency = 2 * chunkSize;
|
||||
+ LOG_MSG("MT32: chunk length must be less than prebuffer length, prebuffer length reset to %i ms.", latency);
|
||||
+ }
|
||||
+ framesPerAudioBuffer = (latency * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ audioBufferSize = framesPerAudioBuffer << 1;
|
||||
+ audioBuffer = new Bit16s[audioBufferSize];
|
||||
+ render(framesPerAudioBuffer - 1, audioBuffer);
|
||||
@@ -456,3 +377,101 @@ index 0000000..45b20cd
|
||||
+};
|
||||
+
|
||||
+#endif /* DOSBOX_MIDI_MT32_H */
|
||||
diff --git a/src/mt32options.h b/src/mt32options.h
|
||||
new file mode 100644
|
||||
index 0000000..4d67069
|
||||
--- /dev/null
|
||||
+++ b/src/mt32options.h
|
||||
@@ -0,0 +1,92 @@
|
||||
+Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,"");
|
||||
+Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n"
|
||||
+ " Accepted file names are as follows:\n"
|
||||
+ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n"
|
||||
+ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file.\n");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.reverse.stereo",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("Reverse stereo channels for MT-32 output");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.verbose",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("MT-32 debug logging");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.thread",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("MT-32 rendering in separate thread");
|
||||
+
|
||||
+const char *mt32chunk[] = {"2", "3", "16", "99", "100",0};
|
||||
+Pint = secprop->Add_int("mt32.chunk",Property::Changeable::WhenIdle,16);
|
||||
+Pint->Set_values(mt32chunk);
|
||||
+Pint->SetMinMax(2,100);
|
||||
+Pint->Set_help("Minimum milliseconds of data to render at once.\n"
|
||||
+ "Increasing this value reduces rendering overhead which may improve performance but also increases audio lag.\n"
|
||||
+ "Valid for rendering in separate thread only.");
|
||||
+
|
||||
+const char *mt32prebuffer[] = {"3", "4", "32", "199", "200",0};
|
||||
+Pint = secprop->Add_int("mt32.prebuffer",Property::Changeable::WhenIdle,32);
|
||||
+Pint->Set_values(mt32prebuffer);
|
||||
+Pint->SetMinMax(3,200);
|
||||
+Pint->Set_help("How many milliseconds of data to render ahead.\n"
|
||||
+ "Increasing this value may help to avoid underruns but also increases audio lag.\n"
|
||||
+ "Cannot be set less than or equal to mt32.chunk value.\n"
|
||||
+ "Valid for rendering in separate thread only.");
|
||||
+
|
||||
+const char *mt32DACModes[] = {"0", "1", "2", "3",0};
|
||||
+Pint = secprop->Add_int("mt32.dac",Property::Changeable::WhenIdle,0);
|
||||
+Pint->Set_values(mt32DACModes);
|
||||
+Pint->Set_help("MT-32 DAC input emulation mode\n"
|
||||
+ "Nice = 0 - default\n"
|
||||
+ "Produces samples at double the volume, without tricks.\n"
|
||||
+ "Higher quality than the real devices\n\n"
|
||||
+
|
||||
+ "Pure = 1\n"
|
||||
+ "Produces samples that exactly match the bits output from the emulated LA32.\n"
|
||||
+ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
|
||||
+ "Much less likely to overdrive than any other mode.\n"
|
||||
+ "Half the volume of any of the other modes.\n"
|
||||
+ "Perfect for developers while debugging :)\n\n"
|
||||
+
|
||||
+ "GENERATION1 = 2\n"
|
||||
+ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
|
||||
+
|
||||
+ "GENERATION2 = 3\n"
|
||||
+ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14");
|
||||
+
|
||||
+const char *mt32analogModes[] = {"0", "1", "2", "3",0};
|
||||
+Pint = secprop->Add_int("mt32.analog",Property::Changeable::WhenIdle,2);
|
||||
+Pint->Set_values(mt32analogModes);
|
||||
+Pint->Set_help("MT-32 analogue output emulation mode\n"
|
||||
+ "Digital = 0\n"
|
||||
+ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n"
|
||||
+ "Fastest mode.\n\n"
|
||||
+
|
||||
+ "Coarse = 1\n"
|
||||
+ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n"
|
||||
+ "A bit better sounding but also a bit slower.\n\n"
|
||||
+
|
||||
+ "Accurate = 2 - default\n"
|
||||
+ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n"
|
||||
+ "which is passed through the LPF circuit without significant attenuation.\n"
|
||||
+ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n"
|
||||
+
|
||||
+ "Oversampled = 3\n"
|
||||
+ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n"
|
||||
+ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer.");
|
||||
+
|
||||
+const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
|
||||
+Pstring->Set_values(mt32reverbModes);
|
||||
+Pstring->Set_help("MT-32 reverb mode");
|
||||
+
|
||||
+const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
|
||||
+Pint->Set_values(mt32reverbTimes);
|
||||
+Pint->Set_help("MT-32 reverb decaying time");
|
||||
+
|
||||
+const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
|
||||
+Pint->Set_values(mt32reverbLevels);
|
||||
+Pint->Set_help("MT-32 reverb level");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
commit 3dbce2eee06d542ac32bb7e11529286dd8c62af6
|
||||
commit 09287d2a7aece2abe44d5a35161d48b881aa5bc9
|
||||
Author: sergm <sergm@bigmir.net>
|
||||
Date: Tue Dec 2 09:19:32 2014 +0200
|
||||
Date: Tue Dec 2 21:46:05 2014 +0200
|
||||
|
||||
mt32emu patch
|
||||
|
||||
@@ -15,7 +15,7 @@ index 184469e..286638d 100644
|
||||
-
|
||||
+LIBS += -lmt32emu
|
||||
diff --git a/src/dosbox.cpp b/src/dosbox.cpp
|
||||
index 6aad419..9a3f96c 100644
|
||||
index 6aad419..9fec99a 100644
|
||||
--- a/src/dosbox.cpp
|
||||
+++ b/src/dosbox.cpp
|
||||
@@ -483,7 +483,7 @@ void DOSBOX_Init(void) {
|
||||
@@ -27,91 +27,11 @@ index 6aad419..9a3f96c 100644
|
||||
Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent");
|
||||
Pstring->Set_values(mputypes);
|
||||
Pstring->Set_help("Type of MPU-401 to emulate.");
|
||||
@@ -499,6 +499,88 @@ void DOSBOX_Init(void) {
|
||||
@@ -499,6 +499,8 @@ void DOSBOX_Init(void) {
|
||||
" In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n"
|
||||
" See the README/Manual for more details.");
|
||||
|
||||
+ Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,"");
|
||||
+ Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n"
|
||||
+ " Accepted file names are as follows:\n"
|
||||
+ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n"
|
||||
+ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file.\n");
|
||||
+
|
||||
+ const char *mt32ReverseStereo[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.reverse.stereo",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32ReverseStereo);
|
||||
+ Pstring->Set_help("Reverse stereo channels for MT-32 output");
|
||||
+
|
||||
+ const char *mt32log[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.verbose",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32log);
|
||||
+ Pstring->Set_help("MT-32 debug logging");
|
||||
+
|
||||
+ const char *mt32thread[] = {"off", "on",0};
|
||||
+ Pstring = secprop->Add_string("mt32.thread",Property::Changeable::WhenIdle,"off");
|
||||
+ Pstring->Set_values(mt32thread);
|
||||
+ Pstring->Set_help("MT-32 rendering in separate thread");
|
||||
+
|
||||
+ const char *mt32DACModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.dac",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32DACModes);
|
||||
+ Pstring->Set_help("MT-32 DAC input emulation mode\n"
|
||||
+ "Nice = 0 - default\n"
|
||||
+ "Produces samples at double the volume, without tricks.\n"
|
||||
+ "Higher quality than the real devices\n\n"
|
||||
+
|
||||
+ "Pure = 1\n"
|
||||
+ "Produces samples that exactly match the bits output from the emulated LA32.\n"
|
||||
+ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
|
||||
+ "Much less likely to overdrive than any other mode.\n"
|
||||
+ "Half the volume of any of the other modes.\n"
|
||||
+ "Perfect for developers while debugging :)\n\n"
|
||||
+
|
||||
+ "GENERATION1 = 2\n"
|
||||
+ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
|
||||
+
|
||||
+ "GENERATION2 = 3\n"
|
||||
+ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14\n");
|
||||
+
|
||||
+ const char *mt32analogModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.analog",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32analogModes);
|
||||
+ Pstring->Set_help("MT-32 analogue output emulation mode\n"
|
||||
+ "Digital = 0\n"
|
||||
+ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n"
|
||||
+ "Fastest mode.\n\n"
|
||||
+
|
||||
+ "Coarse = 1\n"
|
||||
+ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n"
|
||||
+ "A bit better sounding but also a bit slower.\n\n"
|
||||
+
|
||||
+ "Accurate = 2 - default\n"
|
||||
+ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n"
|
||||
+ "which is passed through the LPF circuit without significant attenuation.\n"
|
||||
+ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n"
|
||||
+
|
||||
+ "Oversampled = 3\n"
|
||||
+ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n"
|
||||
+ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer.\n");
|
||||
+
|
||||
+ const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+ Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
|
||||
+ Pstring->Set_values(mt32reverbModes);
|
||||
+ Pstring->Set_help("MT-32 reverb mode");
|
||||
+
|
||||
+ const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+ Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
|
||||
+ Pint->Set_values(mt32reverbTimes);
|
||||
+ Pint->Set_help("MT-32 reverb decaying time");
|
||||
+
|
||||
+ const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+ Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
|
||||
+ Pint->Set_values(mt32reverbLevels);
|
||||
+ Pint->Set_help("MT-32 reverb level");
|
||||
+#include "mt32options.h"
|
||||
+
|
||||
#if C_DEBUG
|
||||
secprop=control->AddSection_prop("debug",&DEBUG_Init);
|
||||
@@ -143,10 +63,10 @@ index ce4647f..3d289b8 100644
|
||||
void MIDI_RawOutByte(Bit8u data) {
|
||||
diff --git a/src/gui/midi_mt32.cpp b/src/gui/midi_mt32.cpp
|
||||
new file mode 100644
|
||||
index 0000000..902651e
|
||||
index 0000000..82bcc96
|
||||
--- /dev/null
|
||||
+++ b/src/gui/midi_mt32.cpp
|
||||
@@ -0,0 +1,247 @@
|
||||
@@ -0,0 +1,248 @@
|
||||
+#include <SDL_thread.h>
|
||||
+#include <SDL_timer.h>
|
||||
+#include <SDL_endian.h>
|
||||
@@ -159,8 +79,6 @@ index 0000000..902651e
|
||||
+#include "midi_mt32.h"
|
||||
+
|
||||
+static const Bitu MILLIS_PER_SECOND = 1000;
|
||||
+static const Bitu MINIMUM_RENDER_MILLIS = 16;
|
||||
+static const Bitu AUDIO_LATENCY_MILLIS = 2 * MINIMUM_RENDER_MILLIS;
|
||||
+
|
||||
+MidiHandler_mt32 &MidiHandler_mt32::GetInstance() {
|
||||
+ static MidiHandler_mt32 midiHandler_mt32;
|
||||
@@ -225,13 +143,12 @@ index 0000000..902651e
|
||||
+ const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile);
|
||||
+ const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile);
|
||||
+
|
||||
+ MT32Emu::AnalogOutputMode analogOutputMode = MT32Emu::AnalogOutputMode_ACCURATE;
|
||||
+ if (strcmp(section->Get_string("mt32.analog"), "auto") != 0) {
|
||||
+ analogOutputMode = (MT32Emu::AnalogOutputMode)atoi(section->Get_string("mt32.analog"));
|
||||
+ }
|
||||
+ MT32Emu::AnalogOutputMode analogOutputMode = (MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog");
|
||||
+
|
||||
+ synth = new MT32Emu::Synth(&reportHandler);
|
||||
+ if (!synth->open(*controlROMImage, *pcmROMImage, analogOutputMode)) {
|
||||
+ delete synth;
|
||||
+ synth = NULL;
|
||||
+ LOG_MSG("MT32: Error initialising emulation");
|
||||
+ return false;
|
||||
+ }
|
||||
@@ -247,13 +164,11 @@ index 0000000..902651e
|
||||
+ synth->setReverbOverridden(true);
|
||||
+ }
|
||||
+
|
||||
+ if (strcmp(section->Get_string("mt32.dac"), "auto") != 0) {
|
||||
+ synth->setDACInputMode((MT32Emu::DACInputMode)atoi(section->Get_string("mt32.dac")));
|
||||
+ }
|
||||
+ synth->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
|
||||
+
|
||||
+ synth->setReversedStereoEnabled(strcmp(section->Get_string("mt32.reverse.stereo"), "on") == 0);
|
||||
+ noise = strcmp(section->Get_string("mt32.verbose"), "on") == 0;
|
||||
+ renderInThread = strcmp(section->Get_string("mt32.thread"), "on") == 0;
|
||||
+ synth->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
|
||||
+ noise = section->Get_bool("mt32.verbose");
|
||||
+ renderInThread = section->Get_bool("mt32.thread");
|
||||
+
|
||||
+ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", synth->getStereoOutputSampleRate());
|
||||
+ chan = MIXER_AddChannel(mixerCallBack, synth->getStereoOutputSampleRate(), "MT32");
|
||||
@@ -262,8 +177,14 @@ index 0000000..902651e
|
||||
+ renderPos = 0;
|
||||
+ playPos = 0;
|
||||
+ sampleRateRatio = MT32Emu::SAMPLE_RATE / (double)synth->getStereoOutputSampleRate();
|
||||
+ minimumRenderFrames = (MINIMUM_RENDER_MILLIS * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ framesPerAudioBuffer = (AUDIO_LATENCY_MILLIS * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ int chunkSize = section->Get_int("mt32.chunk");
|
||||
+ minimumRenderFrames = (chunkSize * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ int latency = section->Get_int("mt32.prebuffer");
|
||||
+ if (latency <= chunkSize) {
|
||||
+ latency = 2 * chunkSize;
|
||||
+ LOG_MSG("MT32: chunk length must be less than prebuffer length, prebuffer length reset to %i ms.", latency);
|
||||
+ }
|
||||
+ framesPerAudioBuffer = (latency * synth->getStereoOutputSampleRate()) / MILLIS_PER_SECOND;
|
||||
+ audioBufferSize = framesPerAudioBuffer << 1;
|
||||
+ audioBuffer = new Bit16s[audioBufferSize];
|
||||
+ render(framesPerAudioBuffer - 1, audioBuffer);
|
||||
@@ -454,3 +375,101 @@ index 0000000..45b20cd
|
||||
+};
|
||||
+
|
||||
+#endif /* DOSBOX_MIDI_MT32_H */
|
||||
diff --git a/src/mt32options.h b/src/mt32options.h
|
||||
new file mode 100644
|
||||
index 0000000..aebf042
|
||||
--- /dev/null
|
||||
+++ b/src/mt32options.h
|
||||
@@ -0,0 +1,92 @@
|
||||
+Pstring = secprop->Add_string("mt32.romdir",Property::Changeable::WhenIdle,"");
|
||||
+Pstring->Set_help("Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work.\n"
|
||||
+ " Accepted file names are as follows:\n"
|
||||
+ " MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file.\n"
|
||||
+ " MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file.");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.reverse.stereo",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("Reverse stereo channels for MT-32 output");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.verbose",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("MT-32 debug logging");
|
||||
+
|
||||
+Pbool = secprop->Add_bool("mt32.thread",Property::Changeable::WhenIdle,false);
|
||||
+Pbool->Set_help("MT-32 rendering in separate thread");
|
||||
+
|
||||
+const char *mt32chunk[] = {"2", "3", "16", "99", "100",0};
|
||||
+Pint = secprop->Add_int("mt32.chunk",Property::Changeable::WhenIdle,16);
|
||||
+Pint->Set_values(mt32chunk);
|
||||
+Pint->SetMinMax(2,100);
|
||||
+Pint->Set_help("Minimum milliseconds of data to render at once.\n"
|
||||
+ "Increasing this value reduces rendering overhead which may improve performance but also increases audio lag.\n"
|
||||
+ "Valid for rendering in separate thread only.");
|
||||
+
|
||||
+const char *mt32prebuffer[] = {"3", "4", "32", "199", "200",0};
|
||||
+Pint = secprop->Add_int("mt32.prebuffer",Property::Changeable::WhenIdle,32);
|
||||
+Pint->Set_values(mt32prebuffer);
|
||||
+Pint->SetMinMax(3,200);
|
||||
+Pint->Set_help("How many milliseconds of data to render ahead.\n"
|
||||
+ "Increasing this value may help to avoid underruns but also increases audio lag.\n"
|
||||
+ "Cannot be set less than or equal to mt32.chunk value.\n"
|
||||
+ "Valid for rendering in separate thread only.");
|
||||
+
|
||||
+const char *mt32DACModes[] = {"0", "1", "2", "3",0};
|
||||
+Pint = secprop->Add_int("mt32.dac",Property::Changeable::WhenIdle,0);
|
||||
+Pint->Set_values(mt32DACModes);
|
||||
+Pint->Set_help("MT-32 DAC input emulation mode\n"
|
||||
+ "Nice = 0 - default\n"
|
||||
+ "Produces samples at double the volume, without tricks.\n"
|
||||
+ "Higher quality than the real devices\n\n"
|
||||
+
|
||||
+ "Pure = 1\n"
|
||||
+ "Produces samples that exactly match the bits output from the emulated LA32.\n"
|
||||
+ "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
|
||||
+ "Much less likely to overdrive than any other mode.\n"
|
||||
+ "Half the volume of any of the other modes.\n"
|
||||
+ "Perfect for developers while debugging :)\n\n"
|
||||
+
|
||||
+ "GENERATION1 = 2\n"
|
||||
+ "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
|
||||
+
|
||||
+ "GENERATION2 = 3\n"
|
||||
+ "Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).\n"
|
||||
+ "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
|
||||
+ "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14");
|
||||
+
|
||||
+const char *mt32analogModes[] = {"0", "1", "2", "3",0};
|
||||
+Pint = secprop->Add_int("mt32.analog",Property::Changeable::WhenIdle,2);
|
||||
+Pint->Set_values(mt32analogModes);
|
||||
+Pint->Set_help("MT-32 analogue output emulation mode\n"
|
||||
+ "Digital = 0\n"
|
||||
+ "Only digital path is emulated. The output samples correspond to the digital output signal appeared at the DAC entrance.\n"
|
||||
+ "Fastest mode.\n\n"
|
||||
+
|
||||
+ "Coarse = 1\n"
|
||||
+ "Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.\n"
|
||||
+ "A bit better sounding but also a bit slower.\n\n"
|
||||
+
|
||||
+ "Accurate = 2 - default\n"
|
||||
+ "Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,\n"
|
||||
+ "which is passed through the LPF circuit without significant attenuation.\n"
|
||||
+ "Sounding is closer to the analog output from real hardware but also slower than the modes 0 and 1.\n\n"
|
||||
+
|
||||
+ "Oversampled = 3\n"
|
||||
+ "Same as the default mode 2 but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.\n"
|
||||
+ "Even slower than all the other modes but better retains highest frequencies while further resampled in DOSBox mixer.");
|
||||
+
|
||||
+const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
|
||||
+Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
|
||||
+Pstring->Set_values(mt32reverbModes);
|
||||
+Pstring->Set_help("MT-32 reverb mode");
|
||||
+
|
||||
+const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
|
||||
+Pint->Set_values(mt32reverbTimes);
|
||||
+Pint->Set_help("MT-32 reverb decaying time");
|
||||
+
|
||||
+const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
|
||||
+Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
|
||||
+Pint->Set_values(mt32reverbLevels);
|
||||
+Pint->Set_help("MT-32 reverb level");
|
||||
|
||||
Reference in New Issue
Block a user