afritz1 / OpenTESArena

Open-source re-implementation of The Elder Scrolls: Arena.
MIT License
988 stars 68 forks source link

Reimplement music support with WildMidi #18

Closed kcat closed 8 years ago

kcat commented 8 years ago

This reimplements music playback using WildMidi. For the MSVC project, note the added files (Midi.h, WildMidi.h, WildMidi.cpp, and components/archives/), and HAVE_WILDMIDI should be defined when building with support for it (don't forget the include path and lib too).

Also, there is a new config option Soundfont which should point to the GUS patchset's cfg file for the music to use. The MusicFormat and SoundFormat options have been removed, as they don't have any purpose anymore.

This should still build if you don't have WildMidi (just don't define HAVE_WILDMIDI). WildMidi 0.4 is required for XMI support, which Arena uses.

afritz1 commented 8 years ago

Great work. I read through most of the changes.

There was an interesting thing I noticed in Options::setSoundfont(), where you pass a std::string by value, but then use std::move() on it. I didn't know you could do that.

I don't see WildMIDI 0.4 on the releases page. Is there a newer version not on GitHub?

kcat commented 8 years ago

There was an interesting thing I noticed in Options::setSoundfont(), where you pass a std::string by value, but then use std::move() on it. I didn't know you could do that.

Yeah, moving a value puts the rvalue ("right side") object into a destructable state, so it can be done on any non-const object that has appropriate move constructors/operators. The reason I did it that way was because it ensures only one string copy will be made, and that copy will be moved to storage, regardless if it's being passed another string object or something a string object is constructed from (like a char* or string literal). I should've done the same for setDataPath now that I think about it.

I don't see WildMIDI 0.4 on the releases page. Is there a newer version not on GitHub?

Hmm, weird. The readme mentions Version 0.4 as the latest, with the changelog specifying that version for XMI support. Perhaps @psi29a can answer?

psi29a commented 8 years ago

\o/ :D

0.4 is almost done... waiting on man pages to be updated and some documentation. It has support for XMI, HMI/HMP and MUS.

I've done some experimental work with SF2 and other fileformats but that will be in another release.

Soo... another release to get this release out the door! I'll put the pedal to metal than!

afritz1 commented 8 years ago

@kcat,

Also, there is a new config option Soundfont which should point to the GUS patchset's cfg file for the music to use.

What's an example Soundfont path I might put in options.txt? I don't know what that might be.

kcat commented 8 years ago

It's system-dependent, unfortunately. Windows doesn't come with a GUS patchset, and I don't know of a defacto standard install path one might be in, so it's completely up to wherever the user put one. On Linux, a decent default might be /etc/timidity/freepats.cfg, for users that have installed the "freepats" soundfont package (one of the more ubiquitous GUS patchsets distros will have).

afritz1 commented 8 years ago

I downloaded the freepats .zip file from the freepats website and temporarily put it into a data/sound_fonts folder. The program compiles and runs, however it doesn't play music. The console prints messages

libWildMidi(WM_ParseNewMidi:2433): ERROR Not a midi file

and

Audio Manager: Failed to play PERCNTRO.XMI.

My data/sound_fonts folder has Drum_000, Tone_000, and freepats.cfg in it.

kcat commented 8 years ago

It's system-dependent, unfortunately.

Now that I think about it, perhaps something like C:\ultrasnd\genmidi.cfg would be a decent example setting. The DosBox.conf that comes with DaggerfallSetup has ultradir=C:\ULTRASND as the default for GUS emulation (ArenaSetup's DosBox.conf doesn't set one). So while it quite likely won't work as-is, I guess that's as good of a default/example as any.

The program compiles and runs, however it doesn't play music. The console prints messages

libWildMidi(WM_ParseNewMidi:2433): ERROR Not a midi file

and

Audio Manager: Failed to play PERCINTRO.XMI.

This is due to having an older version of WildMIDI, which doesn't support XMI. XMI is supported in their latest Git version, for the upcoming 0.4 release (although it isn't working right, either; something I'm going to look into fixing if they don't get to it first).

afritz1 commented 8 years ago

So you're using WildMIDI built straight from the repository and not from the releases folder? Mine is still WildMIDI 0.3.9.

I'll try experimenting with a C:\ultrasnd directory with a General MIDI config. Is there anything else that should go in there besides a genmidi.cfg file, like something similar to the Drum_000 and Tone_000 folders that came with freepats?

Edit: The DosBox.conf for the CD version says in the gus section that C:\ULTRASND should contain a MIDI directory with the patch files for GUS playback. There is no ULTRASND folder in there, though. So I think the DosBox version uses General MIDI (as hinted by -Mgenmidi.adv in the command line arguments) but no GUS patches.

kcat commented 8 years ago

So you're using WildMIDI built straight from the repository and not from the releases folder? Mine is still WildMIDI 0.3.9.

Yeah. Unfortunately the only other option currently is to use FluidSynth with a custom XMI parser, which isn't going to be much easier on Windows. Or make my own XMI to MID converter (which is a little more involved than simply parsing the XMI).

I'll try experimenting with a C:\ultrasnd directory with a General MIDI config. Is there anything else that should go in there besides a genmidi.cfg file, like something similar to the Drum_000 and Tone_000 folders that came with freepats?

If you want to distribute something usable, you'll need the cfg and associated pat files. With freepats, the freepats.cfg file specifies instrument information for General MIDI (it specifies which MIDI patch numbers map to which sound files), and the Drum_000 and Tone_000 folders hold the actual sound files for drum bank 0 and melodic bank 0 respectively. The cfg file can be named anything and be placed anywhere, as long as the Drum_000 and Tone_000 folders (with the pat files they contain) are with it.

psi29a commented 8 years ago

My xmi2mid.c from wildmidi is LGPL, so in theory you can link against this without problems.

Also, there is an OPL3 (SB16) soundfont (sf2) you can use: http://zandro.freeunixhost.com/opl3/

You can convert it to a GUS patch with unsf and ship that as well: https://github.com/psi29a/unsf

This is all rough around the edges, I'm trying my best to make this easier for end users as well. ;)

psi29a commented 8 years ago

https://github.com/Mindwerks/wildmidi/releases/tag/wildmidi-0.4.0

It is released and you can use the binaries provided.