Wohlstand / libADLMIDI

A Software MIDI Synthesizer library with OPL3 (YMF262) emulator
GNU Lesser General Public License v3.0
170 stars 17 forks source link

Descent Banks Configuration #280

Closed worleydl closed 1 month ago

worleydl commented 1 month ago

I've been freshening up some parts of dxx-rebirth recently. I'm able to build a libADLMidi.dll and bundle it with the project but I'm struggling to find any configuration that works to produce the desired output.

Problem Example (Not producing correct output)

You can try running dxx-rebirth with adlmidi enabled, alternatively visit here and enable adlib in the settings. It is producing the same sound I'm experiencing which has odd sounds coming from the synth drum channel.

Expected Examples

Example of parent project running producing desired output

Actual output from real soundblaster

Wohlstand commented 1 month ago

Hello! Since some moment I implemented Descent banks to behave like the original game does including channel allocation algorithm and the volume scaling model. The original ADLMIDI used the only "Generic" volume model and "sounding delay" channels allocation algorithm and in result, some Descent songs sounded very inaccurate (for example, the GAME03's bass).

If you want the thing sound like the original libADLMIDI, then set the volume model to Generic and the channels allocation algorithm to "sounding delay". Otherwise, if you want thing to sound like in the original game, then set the volume model to HMI, the channels allocation to "any released", and enable the full panning stereo (original game used this trick).

Wohlstand commented 1 month ago

Also: The "AdLib drums mode" in original project is a dirty workaround that was done without of the proper logic. Right now this option is no longer works, and instead, when certain bank do really uses rhyth mode of OPL2/OPL3 chip, then the rhythm mode gets bein enabled and used. In other cases, every instrument including drums do use the melodic voices. Descent and the HMI library used by the game, never used rhythm mode, and played every voice via melodic voice. To show the difference between libADLMIDI and Descent's music, I could run both on my 486DX2 computer to show the thing in work.

worleydl commented 1 month ago

Thank you for the information! The code just needed to be updated to set the channel allocation and volume model as you mentioned. Seems to be working great now :)

Marking this as closed.

Wohlstand commented 1 month ago

Actually, the current default behaviour of latest libADLMIDI already uses the close to original HMI SOS behaviour for Descent banks, so, you don't need to bother so much about this. The behaviour of the original ADLMIDI was totally incorrect compared to original Descent, and even more, I received a suitable issue #223 that reports this incorrectness to my libADLMIDI and I resolved it later and now libADLMIDI plays Descent banks close to the HMI SOS.

worleydl commented 1 month ago

I spoke too soon, I had an issue loading the library and it was falling back to a very adlib sounding midi soundfont.

I'm still picking up an almost steeldrum sound from the synth drum channel at about 7.5s on DESCENT.MID, here is the init code I was trying in case I missed something obvious:

adl_switchEmulator(adlmidi, ADLMIDI_EMU_DOSBOX);
adl_setNumChips(adlmidi, CGameCfg.ADLMIDI_num_chips);
adl_setBank(adlmidi, CGameCfg.ADLMIDI_bank);
adl_setSoftPanEnabled(adlmidi, 1);
adl_setChannelAllocMode(adlmidi, ADLMIDI_ChanAlloc_AnyReleased);
adl_setVolumeRangeModel(adlmidi, ADLMIDI_VolumeModel_HMI);
current_adlmidi.reset(adlmidi);
Wohlstand commented 1 month ago

current_adlmidi.reset(adlmidi);

What this call actually does? Probably because it's a problem?

worleydl commented 1 month ago

That's a unique_ptr to the ADL_MidiPlayer, calling reset saves out the configured player and deletes the existing one if there was one.

Wohlstand commented 1 month ago

I see. Anyway, can you record the sound output of the game on your end?

Anyway, I took a look into the code, and it potins incorrect bank: https://github.com/dxx-rebirth/dxx-rebirth/blob/ea01f707d539b99e537b54afe67705c5e8443dbc/common/main/config.h#L65

There are different banks needed to be supplied for different songs. In a case of descent theme the HAM is needed (the bank 4), some other banks will require the INT bank and GAME08 will need the Rick. GM songs will require the bank 2. Also, important: these HMI files do have device filters (different tracks to be played on GM or OPL3 device output), and without applying that filtering, the mess will appear (currently, it just plays incorrect instruments on GM songs are not exclusive to FM).

worleydl commented 1 month ago

This site replicates the sound I'm hearing identically. Select DESCENT.MID, then enable Adlib and pick any of the descent banks. Maybe a build config issue?

I'm looking into updating dxx-rebirth to grab the banks from the sng files if I can get the output sounding right. But so far no luck just manually swapping the bank in the config.

Wohlstand commented 1 month ago

Ye, and it sounds correct (close to sounding how it sounds in the game) изображение

Actually, as I noted, every song requires different bank and game actually switches these banks on the fly. The descent song needs the bank 4 (HAM). With other banks some instruments will be missing or incorrect. That site actually uses the same libADLMIDI as this, it built.

The original game use the HMI SOS library, and banks are in the own BNK format. These banks 1:1 had been included into original ADLMIDI and then into libADLMIDI. Songs in HMI format doesn't include bank data at all, these banks are separated files, and as I remember, every bank is assigned manually by resource filename:

Wohlstand commented 1 month ago

Also, libADLMIDI right now can't play HMI files (the original music format used by Descent game) directly right now (there are future plans to implement this support), and therefore, right now, dxx-rebirth converts HMI into MIDI on the fly and passes the MIDI data into the libADLMIDI thing.

worleydl commented 1 month ago

Thank you for all the information! I just noticed I've been playing the regular MID files on that site and not the ones inside the FM folder (doh!). But interesting enough the non fm MID output was identical so I need to look into what that dxx conversion is doing or if it's just sending the actual midi file data. I believe we can call this closed as it's work that needs to be done inside of dxx and the root cause has been identified.

Wohlstand commented 1 month ago

Songs out of "FM" directory are GeneralMIDI music files that used by game to play music via MIDI Out interface (I speak about original DOS Descent). Sone songs has different version to be played on OPL chips exclusively, and they appear at FM sub-directory. If song is not presented at FM directory, then the shared GM song is used to play on OPL2/3 too. And again, GM songs should be played with the libADLMIDI's bank 2, and, some tracks should be filtered as they marked to be played on MIDI Out when on FM are different tracks being supposed. You may want to take a look on this repo that contains a simple DOS demo that plays HMI files via the same library as Descent game uses: https://github.com/Wohlstand/SOSPLAY. Also, there is a documentation inside that tells about these track filters. Look at the document https://github.com/Wohlstand/SOSPLAY/blob/master/sos/sos40.doc, find the "Track Mapping and Assigning Track Priorities" title, it's the page 129. HMI files do have these markers being set per track, and I may guess, hmi2mid may ignore them, but they are very important here.

worleydl commented 1 month ago

Quick update: The dxx code was only loading hmp files which only contain the general midi music. If you point the loader at hmq files it works beautifully. I believe it only needs the bank swapping added now.