diff --git a/opl/opl.c b/opl/opl.c index 603a1214..17cff815 100644 --- a/opl/opl.c +++ b/opl/opl.c @@ -32,7 +32,7 @@ static opl_driver_t *drivers[] = static opl_driver_t *driver = NULL; -unsigned int opl_sample_rate = 22050; +unsigned int opl_sample_rate = OPL_SAMPLE_RATE; // // Init/shutdown code. @@ -42,11 +42,11 @@ unsigned int opl_sample_rate = 22050; // true if an OPL is detected. static opl_init_result_t InitDriver(opl_driver_t *_driver, - unsigned int port_base) + unsigned int port_base, int num_chips) { // Initialize the driver. - if (!_driver->init_func(port_base)) + if (!_driver->init_func(port_base, num_chips)) { return OPL_INIT_NONE; } @@ -58,21 +58,21 @@ static opl_init_result_t InitDriver(opl_driver_t *_driver, driver = _driver; - printf("OPL_Init: Using driver '%s'.\n", driver->name); + printf("OPL_Init: Using driver '%s' with %d chip(s).\n", driver->name, num_opl_chips); return OPL_INIT_OPL3; } // Find a driver automatically by trying each in the list. -static opl_init_result_t AutoSelectDriver(unsigned int port_base) +static opl_init_result_t AutoSelectDriver(unsigned int port_base, int num_chips) { int i; opl_init_result_t result; for (i=0; drivers[i] != NULL; ++i) { - result = InitDriver(drivers[i], port_base); + result = InitDriver(drivers[i], port_base, num_chips); if (result != OPL_INIT_NONE) { return result; @@ -87,7 +87,7 @@ static opl_init_result_t AutoSelectDriver(unsigned int port_base) // Initialize the OPL library. Return value indicates type of OPL chip // detected, if any. -opl_init_result_t OPL_Init(unsigned int port_base) +opl_init_result_t OPL_Init(unsigned int port_base, int num_chips) { char *driver_name; int i; @@ -103,7 +103,7 @@ opl_init_result_t OPL_Init(unsigned int port_base) { if (!strcmp(driver_name, drivers[i]->name)) { - result = InitDriver(drivers[i], port_base); + result = InitDriver(drivers[i], port_base, num_chips); if (result) { return result; @@ -123,7 +123,7 @@ opl_init_result_t OPL_Init(unsigned int port_base) } else { - return AutoSelectDriver(port_base); + return AutoSelectDriver(port_base, num_chips); } } @@ -145,7 +145,7 @@ void OPL_SetSampleRate(unsigned int rate) opl_sample_rate = rate; } -void OPL_WritePort(opl_port_t port, unsigned int value) +void OPL_WritePort(int chip, opl_port_t port, unsigned int value) { if (driver != NULL) { @@ -153,11 +153,11 @@ void OPL_WritePort(opl_port_t port, unsigned int value) printf("OPL_write: %i, %x\n", port, value); fflush(stdout); #endif - driver->write_port_func(port, value); + driver->write_port_func(chip, port, value); } } -unsigned int OPL_ReadPort(opl_port_t port) +unsigned int OPL_ReadPort(int chip, opl_port_t port) { if (driver != NULL) { @@ -168,7 +168,7 @@ unsigned int OPL_ReadPort(opl_port_t port) fflush(stdout); #endif - result = driver->read_port_func(port); + result = driver->read_port_func(chip, port); #ifdef OPL_DEBUG_TRACE printf("OPL_read: %i -> %x\n", port, result); @@ -188,24 +188,24 @@ unsigned int OPL_ReadPort(opl_port_t port) // (register write, etc). // -unsigned int OPL_ReadStatus(void) +unsigned int OPL_ReadStatus(int chip) { - return OPL_ReadPort(OPL_REGISTER_PORT); + return OPL_ReadPort(chip, OPL_REGISTER_PORT); } // Write an OPL register value -void OPL_WriteRegister(int reg, int value) +void OPL_WriteRegister(int chip, int reg, int value) { int i; if (reg & 0x100) { - OPL_WritePort(OPL_REGISTER_PORT_OPL3, reg); + OPL_WritePort(chip, OPL_REGISTER_PORT_OPL3, reg); } else { - OPL_WritePort(OPL_REGISTER_PORT, reg); + OPL_WritePort(chip, OPL_REGISTER_PORT, reg); } // For timing, read the register port six times after writing the @@ -213,17 +213,17 @@ void OPL_WriteRegister(int reg, int value) for (i=0; i<6; ++i) { - OPL_ReadPort(OPL_DATA_PORT); + OPL_ReadPort(chip, OPL_DATA_PORT); } - OPL_WritePort(OPL_DATA_PORT, value); + OPL_WritePort(chip, OPL_DATA_PORT, value); // Read the register port 24 times after writing the value to // cause the appropriate delay for (i=0; i<24; ++i) { - OPL_ReadStatus(); + OPL_ReadStatus(chip); } } @@ -231,50 +231,15 @@ void OPL_WriteRegister(int reg, int value) void OPL_InitRegisters(int opl3) { - int r; - - // Initialize level registers - - for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) + for (int c = 0; c < num_opl_chips; ++c) { - OPL_WriteRegister(r, 0x3f); - } - - // Initialize other registers - // These two loops write to registers that actually don't exist, - // but this is what Doom does ... - // Similarly, the <= is also intenational. - - for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) - { - OPL_WriteRegister(r, 0x00); - } - - // More registers ... - - for (r=1; r < OPL_REGS_LEVEL; ++r) - { - OPL_WriteRegister(r, 0x00); - } - - // Re-initialize the low registers: - - // Reset both timers and enable interrupts: - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60); - OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80); - - // "Allow FM chips to control the waveform of each operator": - OPL_WriteRegister(OPL_REG_WAVEFORM_ENABLE, 0x20); - - if (opl3) - { - OPL_WriteRegister(OPL_REG_NEW, 0x01); + int r; // Initialize level registers for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) { - OPL_WriteRegister(r | 0x100, 0x3f); + OPL_WriteRegister(c, r, 0x3f); } // Initialize other registers @@ -284,23 +249,61 @@ void OPL_InitRegisters(int opl3) for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) { - OPL_WriteRegister(r | 0x100, 0x00); + OPL_WriteRegister(c, r, 0x00); } // More registers ... for (r=1; r < OPL_REGS_LEVEL; ++r) { - OPL_WriteRegister(r | 0x100, 0x00); + OPL_WriteRegister(c, r, 0x00); } - } - // Keyboard split point on (?) - OPL_WriteRegister(OPL_REG_FM_MODE, 0x40); + // Re-initialize the low registers: - if (opl3) - { - OPL_WriteRegister(OPL_REG_NEW, 0x01); + // Reset both timers and enable interrupts: + OPL_WriteRegister(c, OPL_REG_TIMER_CTRL, 0x60); + OPL_WriteRegister(c, OPL_REG_TIMER_CTRL, 0x80); + + // "Allow FM chips to control the waveform of each operator": + OPL_WriteRegister(c, OPL_REG_WAVEFORM_ENABLE, 0x20); + + if (opl3) + { + OPL_WriteRegister(c, OPL_REG_NEW, 0x01); + + // Initialize level registers + + for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(c, r | 0x100, 0x3f); + } + + // Initialize other registers + // These two loops write to registers that actually don't exist, + // but this is what Doom does ... + // Similarly, the <= is also intenational. + + for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r) + { + OPL_WriteRegister(c, r | 0x100, 0x00); + } + + // More registers ... + + for (r=1; r < OPL_REGS_LEVEL; ++r) + { + OPL_WriteRegister(c, r | 0x100, 0x00); + } + } + + // Keyboard split point on (?) + OPL_WriteRegister(c, OPL_REG_FM_MODE, 0x40); + + if (opl3) + { + OPL_WriteRegister(c, OPL_REG_NEW, 0x01); + } } } diff --git a/opl/opl.h b/opl/opl.h index a8f3b0ac..7dce7208 100644 --- a/opl/opl.h +++ b/opl/opl.h @@ -38,6 +38,9 @@ typedef enum OPL_REGISTER_PORT_OPL3 = 2 } opl_port_t; +#define OPL_SAMPLE_RATE 49716 +#define OPL_MAX_CHIPS 6 + #define OPL_NUM_OPERATORS 21 #define OPL_NUM_VOICES 9 @@ -68,13 +71,15 @@ typedef enum #define OPL_MS ((uint64_t) 1000) #define OPL_US ((uint64_t) 1) +extern int num_opl_chips; + // // Low-level functions. // // Initialize the OPL subsystem. -opl_init_result_t OPL_Init(unsigned int port_base); +opl_init_result_t OPL_Init(unsigned int port_base, int num_chips); // Shut down the OPL subsystem. @@ -86,11 +91,11 @@ void OPL_SetSampleRate(unsigned int rate); // Write to one of the OPL I/O ports: -void OPL_WritePort(opl_port_t port, unsigned int value); +void OPL_WritePort(int chip, opl_port_t port, unsigned int value); // Read from one of the OPL I/O ports: -unsigned int OPL_ReadPort(opl_port_t port); +unsigned int OPL_ReadPort(int chip, opl_port_t port); // // Higher-level functions. @@ -98,11 +103,11 @@ unsigned int OPL_ReadPort(opl_port_t port); // Read the cuurrent status byte of the OPL chip. -unsigned int OPL_ReadStatus(void); +unsigned int OPL_ReadStatus(int chip); // Write to an OPL register. -void OPL_WriteRegister(int reg, int value); +void OPL_WriteRegister(int chip, int reg, int value); // Initialize all registers, performed on startup. diff --git a/opl/opl_internal.h b/opl/opl_internal.h index 0b948f5f..e32f7010 100644 --- a/opl/opl_internal.h +++ b/opl/opl_internal.h @@ -21,10 +21,10 @@ #include "opl.h" -typedef int (*opl_init_func)(unsigned int port_base); +typedef int (*opl_init_func)(unsigned int port_base, int num_chips); typedef void (*opl_shutdown_func)(void); -typedef unsigned int (*opl_read_port_func)(opl_port_t port); -typedef void (*opl_write_port_func)(opl_port_t port, unsigned int value); +typedef unsigned int (*opl_read_port_func)(int chip, opl_port_t port); +typedef void (*opl_write_port_func)(int chip, opl_port_t port, unsigned int value); typedef void (*opl_set_callback_func)(uint64_t us, opl_callback_t callback, void *data); diff --git a/opl/opl_sdl.c b/opl/opl_sdl.c index 09803a17..83c75ccb 100644 --- a/opl/opl_sdl.c +++ b/opl/opl_sdl.c @@ -50,7 +50,7 @@ static uint64_t pause_offset; // OPL software emulator structure. -static opl3_chip opl_chip; +static opl3_chip opl_chips[OPL_MAX_CHIPS]; static int opl_opl3mode; // Register number that was written. @@ -137,7 +137,23 @@ int OPL_FillBuffer(byte *buffer, int buffer_samples) } // Add emulator output to buffer. - OPL3_GenerateStream(&opl_chip, (Bit16s *)(buffer + filled * 4), nsamples); + Bit16s *cursor = (Bit16s *)(buffer + filled * 4); + for (int s = 0; s < nsamples; ++s) + { + Bit32s mix[2] = {0, 0}; + for (int c = 0; c < num_opl_chips; ++c) + { + Bit16s sample[2]; + OPL3_GenerateResampled(&opl_chips[c], sample); + mix[0] += sample[0]; + mix[1] += sample[1]; + } + + cursor[0] = BETWEEN(-32768, 32767, mix[0]); + cursor[1] = BETWEEN(-32768, 32767, mix[1]); + cursor += 2; + } + //OPL3_GenerateStream(&opl_chip, (Bit16s *)(buffer + filled * 4), nsamples); filled += nsamples; // Invoke callbacks for this point in time. @@ -161,7 +177,7 @@ static void OPL_SDL_Shutdown(void) */ } -static int OPL_SDL_Init(unsigned int port_base) +static int OPL_SDL_Init(unsigned int port_base, int num_chips) { opl_sdl_paused = 0; pause_offset = 0; @@ -179,13 +195,14 @@ static int OPL_SDL_Init(unsigned int port_base) // Create the emulator structure: - OPL3_Reset(&opl_chip, mixing_freq); + for (int c = 0; c < num_opl_chips; ++c) + OPL3_Reset(&opl_chips[c], mixing_freq); opl_opl3mode = 0; return 1; } -static unsigned int OPL_SDL_PortRead(opl_port_t port) +static unsigned int OPL_SDL_PortRead(int chip, opl_port_t port) { unsigned int result = 0; @@ -194,6 +211,9 @@ static unsigned int OPL_SDL_PortRead(opl_port_t port) return 0xff; } + if (chip > 0) + return result; + if (timer1.enabled && current_time > timer1.expire_time) { result |= 0x80; // Either have expired @@ -224,18 +244,26 @@ static void OPLTimer_CalculateEndTime(opl_timer_t *timer) } } -static void WriteRegister(unsigned int reg_num, unsigned int value) +static void WriteRegister(int chip, unsigned int reg_num, unsigned int value) { switch (reg_num) { case OPL_REG_TIMER1: - timer1.value = value; - OPLTimer_CalculateEndTime(&timer1); + // Only allow timers on the first chip + if (chip == 0) + { + timer1.value = value; + OPLTimer_CalculateEndTime(&timer1); + } break; case OPL_REG_TIMER2: - timer2.value = value; - OPLTimer_CalculateEndTime(&timer2); + // Only allow timers on the first chip + if (chip == 0) + { + timer2.value = value; + OPLTimer_CalculateEndTime(&timer2); + } break; case OPL_REG_TIMER_CTRL: @@ -258,19 +286,25 @@ static void WriteRegister(unsigned int reg_num, unsigned int value) OPLTimer_CalculateEndTime(&timer2); } } - break; case OPL_REG_NEW: - opl_opl3mode = value & 0x01; + // Keep all chips synchronized with the first chip's opl3 mode + if (chip == 0) + { + for (int c = 0; c < num_opl_chips; ++c) + OPL3_WriteRegBuffered(&opl_chips[c], reg_num, value); + opl_opl3mode = value & 0x01; + } + break; default: - OPL3_WriteRegBuffered(&opl_chip, reg_num, value); + OPL3_WriteRegBuffered(&opl_chips[chip], reg_num, value); break; } } -static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value) +static void OPL_SDL_PortWrite(int chip, opl_port_t port, unsigned int value) { if (port == OPL_REGISTER_PORT) { @@ -282,7 +316,7 @@ static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value) } else if (port == OPL_DATA_PORT) { - WriteRegister(register_num, value); + WriteRegister(chip, register_num, value); } } diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index ba1e7ac2..7cf73fc9 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -26,6 +26,7 @@ #include "i_printf.h" #include "i_sound.h" #include "m_array.h" +#include "m_config.h" #include "m_io.h" #include "m_swap.h" #include "memio.h" @@ -327,9 +328,9 @@ static char (*percussion_names)[32]; // Voices: -static opl_voice_t voices[OPL_NUM_VOICES * 2]; -static opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2]; -static opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2]; +static opl_voice_t voices[OPL_NUM_VOICES * 2 * OPL_MAX_CHIPS]; +static opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2 * OPL_MAX_CHIPS]; +static opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2 * OPL_MAX_CHIPS]; static int voice_free_num; static int voice_alloced_num; static int opl_opl3mode; @@ -361,6 +362,7 @@ static unsigned int last_perc_count; static char *snd_dmxoption = "-opl3"; // [crispy] default to OPL3 emulation static int opl_io_port = 0x388; +int num_opl_chips = 1; // If true, OPL sound channels are reversed to their correct arrangement // (as intended by the MIDI standard) rather than the backwards one @@ -468,7 +470,7 @@ static void ReleaseVoice(int index) // Load data to the specified operator -static void LoadOperatorData(int operator, genmidi_op_t * data, +static void LoadOperatorData(int chip, int operator, genmidi_op_t * data, boolean max_level, unsigned int *volume) { int level; @@ -489,11 +491,11 @@ static void LoadOperatorData(int operator, genmidi_op_t * data, *volume = level; - OPL_WriteRegister(OPL_REGS_LEVEL + operator, level); - OPL_WriteRegister(OPL_REGS_TREMOLO + operator, data->tremolo); - OPL_WriteRegister(OPL_REGS_ATTACK + operator, data->attack); - OPL_WriteRegister(OPL_REGS_SUSTAIN + operator, data->sustain); - OPL_WriteRegister(OPL_REGS_WAVEFORM + operator, data->waveform); + OPL_WriteRegister(chip, OPL_REGS_LEVEL + operator, level); + OPL_WriteRegister(chip, OPL_REGS_TREMOLO + operator, data->tremolo); + OPL_WriteRegister(chip, OPL_REGS_ATTACK + operator, data->attack); + OPL_WriteRegister(chip, OPL_REGS_SUSTAIN + operator, data->sustain); + OPL_WriteRegister(chip, OPL_REGS_WAVEFORM + operator, data->waveform); } // Set the instrument for a particular voice. @@ -526,16 +528,16 @@ static void SetVoiceInstrument(opl_voice_t *voice, genmidi_instr_t *instr, // is set in SetVoiceVolume (below). If we are not using // modulating mode, we must set both to minimum volume. - LoadOperatorData(voice->op2 | voice->array, &data->carrier, true, + LoadOperatorData(voice->array >> 9, voice->op2 | (voice->array & 0x100), &data->carrier, true, &voice->car_volume); - LoadOperatorData(voice->op1 | voice->array, &data->modulator, !modulating, + LoadOperatorData(voice->array >> 9, voice->op1 | (voice->array & 0x100), &data->modulator, !modulating, &voice->mod_volume); // Set feedback register that control the connection between the // two operators. Turn on bits in the upper nybble; I think this // is for OPL3, where it turns on channel A/B. - OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_FEEDBACK + voice->index) | (voice->array & 0x100), data->feedback | voice->reg_pan); // Calculate voice priority. @@ -571,7 +573,7 @@ static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume) { voice->car_volume = car_volume | (voice->car_volume & 0xc0); - OPL_WriteRegister((OPL_REGS_LEVEL + voice->op2) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_LEVEL + voice->op2) | (voice->array & 0x100), voice->car_volume); // If we are using non-modulated feedback mode, we must set the @@ -591,7 +593,7 @@ static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume) if (mod_volume != voice->mod_volume) { voice->mod_volume = mod_volume; - OPL_WriteRegister((OPL_REGS_LEVEL + voice->op1) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_LEVEL + voice->op1) | (voice->array & 0x100), mod_volume | (opl_voice->modulator.scale & 0xc0)); } } @@ -605,7 +607,7 @@ static void SetVoicePan(opl_voice_t *voice, unsigned int pan) voice->reg_pan = pan; opl_voice = &voice->current_instr->voices[voice->current_instr_voice]; - OPL_WriteRegister((OPL_REGS_FEEDBACK + voice->index) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_FEEDBACK + voice->index) | (voice->array & 0x100), opl_voice->feedback | pan); } @@ -627,7 +629,7 @@ static void InitVoices(void) voices[i].index = i % OPL_NUM_VOICES; voices[i].op1 = voice_operators[0][i % OPL_NUM_VOICES]; voices[i].op2 = voice_operators[1][i % OPL_NUM_VOICES]; - voices[i].array = (i / OPL_NUM_VOICES) << 8; + voices[i].array = (i / OPL_NUM_VOICES) << (opl_opl3mode ? 8 : 9); voices[i].current_instr = NULL; // Add this voice to the freelist. @@ -666,7 +668,7 @@ static void I_OPL_SetMusicVolume(int volume) static void VoiceKeyOff(opl_voice_t *voice) { - OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_FREQ_2 + voice->index) | (voice->array & 0x100), voice->freq >> 8); } @@ -883,9 +885,9 @@ static void UpdateVoiceFrequency(opl_voice_t *voice) if (voice->freq != freq) { - OPL_WriteRegister((OPL_REGS_FREQ_1 + voice->index) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_FREQ_1 + voice->index) | (voice->array & 0x100), freq & 0xff); - OPL_WriteRegister((OPL_REGS_FREQ_2 + voice->index) | voice->array, + OPL_WriteRegister(voice->array >> 9, (OPL_REGS_FREQ_2 + voice->index) | (voice->array & 0x100), (freq >> 8) | 0x20); voice->freq = freq; @@ -1196,9 +1198,9 @@ static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event) { opl_channel_data_t *channel; int i; - opl_voice_t *voice_updated_list[OPL_NUM_VOICES * 2] = {0}; + opl_voice_t *voice_updated_list[OPL_NUM_VOICES * 2 * OPL_MAX_CHIPS] = {0}; unsigned int voice_updated_num = 0; - opl_voice_t *voice_not_updated_list[OPL_NUM_VOICES * 2] = {0}; + opl_voice_t *voice_not_updated_list[OPL_NUM_VOICES * 2 * OPL_MAX_CHIPS] = {0}; unsigned int voice_not_updated_num = 0; // Update the channel bend value. Only the MSB of the pitch bend @@ -1445,9 +1447,9 @@ static boolean I_OPL_InitStream(int device) char *dmxoption; opl_init_result_t chip_type; - OPL_SetSampleRate(SND_SAMPLERATE); + OPL_SetSampleRate(OPL_SAMPLE_RATE); - chip_type = OPL_Init(opl_io_port); + chip_type = OPL_Init(opl_io_port, num_opl_chips); if (chip_type == OPL_INIT_NONE) { I_Printf(VB_ERROR, "Dude. The Adlib isn't responding."); @@ -1457,6 +1459,12 @@ static boolean I_OPL_InitStream(int device) // The DMXOPTION variable must be set to enable OPL3 support. // As an extension, we also allow it to be set from the config file. dmxoption = M_getenv("DMXOPTION"); + + // Secret, undocumented DMXOPTION that reverses the stereo channels + // into their correct orientation. + if (dmxoption != NULL && strstr(dmxoption, "-reverse") != NULL) + opl_stereo_correct = true; + if (dmxoption == NULL) { dmxoption = snd_dmxoption != NULL ? snd_dmxoption : ""; @@ -1465,18 +1473,14 @@ static boolean I_OPL_InitStream(int device) if (chip_type == OPL_INIT_OPL3 && strstr(dmxoption, "-opl3") != NULL) { opl_opl3mode = 1; - num_opl_voices = OPL_NUM_VOICES * 2; + num_opl_voices = OPL_NUM_VOICES * 2 * num_opl_chips; } else { opl_opl3mode = 0; - num_opl_voices = OPL_NUM_VOICES; + num_opl_voices = OPL_NUM_VOICES * num_opl_chips; } - // Secret, undocumented DMXOPTION that reverses the stereo channels - // into their correct orientation. - opl_stereo_correct = strstr(dmxoption, "-reverse") != NULL; - // Initialize all registers. OPL_InitRegisters(opl_opl3mode); @@ -1550,7 +1554,7 @@ static boolean I_OPL_OpenStream(void *data, ALsizei size, ALenum *format, } *format = AL_FORMAT_STEREO16; - *freq = SND_SAMPLERATE; + *freq = OPL_SAMPLE_RATE; *frame_size = 2 * sizeof(short); return true; @@ -1670,7 +1674,10 @@ static const char **I_OPL_DeviceList(void) static void I_OPL_BindVariables(void) { - ; + BIND_NUM(num_opl_chips, 1, 1, OPL_MAX_CHIPS, + "[OPL3 Emulation] Number of chips to emulate (1-6)"); + BIND_BOOL(opl_stereo_correct, false, + "[OPL3 Emulation] Use MIDI-correct stereo channel polarity"); } stream_module_t stream_opl_module =