jonof / jfduke3d

Port of the 3D Realms game "Duke Nukem 3D"
http://www.jonof.id.au/jfduke3d
110 stars 18 forks source link

Music on GNU/Linux #10

Closed vanfanel closed 2 years ago

vanfanel commented 3 years ago

Hi there,

I have just built jfduke3d on SDL2/KMSDRM, and it works fine, but I am still missing music. Well, it works, but not perfectly.

So far I got the music to play if I load a SoundFont with Fluidsynth like this:

fluidsynth --audio-driver=alsa -s UHD3.sf2

Then the tittle screen music plays, but the game hangs when I start a level and sound effects are missing. My guess is that fluidsynth takes over ALSA PCM channels. But then, what would be the correct way to do it with FluidSynth?

Thanks!

vanfanel commented 3 years ago

Also, is OGG music supposed to work on GNU/Linux?

libvorbis-dev is of course present on my system, and in fact, jfduke is linked aganst it:


pi@raspberrypi:~/duke $ ldd duke3d
        linux-vdso.so.1 (0x0000007f8a1d8000)
        libSDL2-2.0.so.0 => /usr/local/lib/libSDL2-2.0.so.0 (0x0000007f8946f000)
        libvorbisfile.so.3 => /usr/lib/aarch64-linux-gnu/libvorbisfile.so.3 (0x0000007f89456000)
        libasound.so.2 => /usr/lib/aarch64-linux-gnu/libasound.so.2 (0x0000007f89347000)
        libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007f89318000)
        libfluidsynth.so.2 => /usr/lib/libfluidsynth.so.2 (0x0000007f89246000)
        libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007f890bb000)
        libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007f88ffe000)
        libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007f88fda000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007f88e68000)
        libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000007f88e54000)
        libdrm.so.2 => /usr/local/lib/aarch64-linux-gnu/libdrm.so.2 (0x0000007f88e33000)
        libgbm.so.1 => /usr/local/lib/aarch64-linux-gnu/libgbm.so.1 (0x0000007f88e15000)
        librt.so.1 => /lib/aarch64-linux-gnu/librt.so.1 (0x0000007f88dfb000)
        libvorbis.so.0 => /usr/lib/aarch64-linux-gnu/libvorbis.so.0 (0x0000007f88dc2000)
        libogg.so.0 => /usr/lib/aarch64-linux-gnu/libogg.so.0 (0x0000007f88daa000)
        /lib/ld-linux-aarch64.so.1 (0x0000007f8a1aa000)
        libgthread-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libgthread-2.0.so.0 (0x0000007f88d98000)
        libglib-2.0.so.0 => /usr/lib/aarch64-linux-gnu/libglib-2.0.so.0 (0x0000007f88c65000)
        libgomp.so.1 => /usr/lib/aarch64-linux-gnu/libgomp.so.1 (0x0000007f88c29000)
        libexpat.so.1 => /lib/aarch64-linux-gnu/libexpat.so.1 (0x0000007f88be8000)
        libpcre.so.3 => /lib/aarch64-linux-gnu/libpcre.so.3 (0x0000007f88b75000)

But providing music packs in the same directory as the duke3d executable, or in ./music, the game won't play any music at all.

So are OGG supposed to play on GNU/Linux when jfduke is linked against libvorbis?

jonof commented 3 years ago

MIDI playback on Linux can be slightly fiddly. With FluidSynth you probably need to give it extra configuration options by adding an entry to the duke3d.cfg file, e.g.:

[Sound Setup]
MusicParams = "audio.driver=alsa synth.default-soundfont=/path/to/font.sf2"

I probably ought to document that...

The game will also look for .ogg files that have the same base name as the .mid version, e.g. dethtoll.ogg substitutes for dethtoll.mid. They should be put into the same directory as duke3d.grp.

vanfanel commented 3 years ago

@jonof

Thanks for taking the time to answer :) I had to add these two lines to get FluidSynth music working:

[Sound Setup]
MusicDevice = 6
MusicParams = "audio.driver=alsa synth.default-soundfont=/path/to/font.sf2"

However, I believe audio.driver=alsa isn't right because I am seeing this on startup:

FluidSynthDrv: using soundfont /usr/share/sounds/sf2/fluid.sf2
fluidsynth: warning: SDL2 not initialized, SDL2 audio driver won't be usable
FluidSynthDrv: setting 'audio.driver' to 'alsa'
FluidSynthDrv: error setting 'audio.driver' to 'alsa'
FluidSynthDrv: setting 'synth.default-soundfont' to '/usr/share/sounds/sf2/fluid.sf2'
FluidSynthDrv: error setting 'synth.default-soundfont' to '/usr/share/sounds/sf2/fluid.sf2'
fluidsynth: warning: sequencer: Usage of the system timer has been deprecated!
fluidsynth: warning: Failed to set thread to high priority
fluidsynth: warning: Failed to set thread to high priority
Checking sound inits.
SDL_GetCurrentAudioDriver: alsa
fluidsynth: warning: Failed to set thread to high priority
fluidsynth: warning: Failed to set thread to high priority

...So it seems to be failing on: 1 - Setting audio.driver to alsa 2 - Setting synth.default-soundfont to /usr/share/sounds/sf2/fluid.sf2 3 - Setting the fluidsynth thread to high priority

At least the fail at setting audio.driver to alsa seems to be caused by audio.driver=alsa But not putting that makes music initialization to fail too. So I am a bit puzzled that it even works...

Also, seems to me that jfduke3d is only able to find fonts on /usr/share/sounds/sf2/, right? It won't find any fonts in, let's say, ~/duke, for example, even if I specify that path on the line MusicParams = "audio.driver=alsa synth.default-soundfont=~/duke/font.sf2"

jonof commented 3 years ago

FluidSynthDrv: error setting 'audio.driver' to 'alsa' FluidSynthDrv: error setting 'synth.default-soundfont' to '/usr/share/sounds/sf2/fluid.sf2'

Curious. I'll test on my end.

It won't find any fonts in, let's say, ~/duke

You would need to expand the ~ yourself to whatever your home directory actually is.

Posiris commented 3 years ago

I'm having issues with music as well. I copied the "midi" folder from the iso over to the .jfduke3d folder, and added these to the duke3d.cfg under [Sound Setup]:

MusicDevice = 0 (1 works but anything else will result in an error that the music device can't be loaded) MusicParams = "audio.driver=alsa synth.default-soundfont=home/user/Music/Sound Fonts/Scc1t2.sf2"

I launch the game and there is not music, just SFX. When I quit the game and check the terminal, it shows that it's loading pulseaudio instead of alsa (I do have alsa-utils installed). I also notice that the RTS Manager fails to find duke.rts. I tried copying it off the iso to .jfduke3d but that message still comes up as well.

jonof commented 3 years ago

I guess I'm going to have to merge the recent JFAudioLib changes that updated Fluidsynth and autodetection and just hope I haven't broken anything. I'll update here once I do.

vanfanel commented 3 years ago

@jonof Can you please merge this one too? --> https://github.com/jonof/jfduke3d/pull/11

jonof commented 3 years ago

@Posiris wrote: I copied the "midi" folder from the iso over to the .jfduke3d folder

You can delete that. The MIDI music is already contained in the duke3d.grp file.

and added these to the duke3d.cfg under [Sound Setup]

Because the MusicParams parser isn't (presently) capable of handling spaces in the file path, I suggest symlinking your Scc1t2.sf2 soundfont into the ~/.jfduke3d directory and then trying the code now in the master branch it with these options in the .cfg file:

MusicDevice = 0 MusicParams = "audio.driver=alsa soundfont=Scc1t2.sf2"

I also notice that the RTS Manager fails to find duke.rts.

It's looking for DUKE.RTS in uppercase. I never did lowercase the filename in the code that it looks for by default.

@vfanel wrote: Can you please merge this one too?

I may consider a variant of that patch, but I'm not going to merge it how it's written at the moment.

vanfanel commented 3 years ago

@jonof Oh, so can you please fix it to your liking? Consistency on the filenames is very much needed.

vanfanel commented 3 years ago

@jonof I have just built the updated sources with your new audio lib version.

Can you please tell me how to setup jfduke3d so it loads the .ogg soundtrack? I have tried both uppercase and lowercase names, and have them in the same directory as the duke3d executable. I suppose they should be uppercase because I extracted duke3d.grp and .mid files are all consistently name uppercase.

However, I am seeing this during jfduke3d initialization:


Checking music inits.
MUSIC_Init: trying FluidSynth
fluidsynth: error: fluid_sfloader_load(): Failed to open '/usr/share/soundfonts/default.sf2': File does not exist.
fluidsynth: error: Unable to open file '/usr/share/soundfonts/default.sf2'
fluidsynth: error: Failed to load SoundFont "/usr/share/soundfonts/default.sf2"
MUSIC_Init: trying ALSA
ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory
ALSA snd_seq_open err -2
Checking sound inits.

So it seems to be trying to load MIDI music via fluidsynth, instead of the OGG music. How can I tell it to load the OGG music instead? I think I have tried everything...

jonof commented 3 years ago

@vanfanel: Since you're using Linux, the least-effort way to avoid fiddling around with filename case is to just ZIP up your OggVorbis files (e.g. as music.zip), put that ZIP file wherever you've put duke3d.grp, then run the game with duke3d -gmusic.zip. The ZIP loading code is case-insensitive, so it will iron out the differences.

Otherwise, if you really want to have all the substitute files loose on disk, then you're going to have to work for it given the current code. Put the OggVorbis files in the directory beside duke3d.grp, and ensure that the filenames match the base filename case as it appears in USER.CON but with a lowercase .ogg extension. Here's what that looks like in the CON file for Duke3D Atomic Edition:

// Music for title and end music 0 GRABBAG.MID BRIEFING.MID

// Music for the individual levels music 1 stalker.mid dethtoll.mid streets.mid watrwld1.mid snake1.mid thecall.mid ahgeez.mid dethtoll.mid streets.mid watrwld1.mid snake1.mid

music 2 futurmil.mid storm.mid gutwrnch.mid robocrep.mid stalag.mid pizzed.mid alienz.mid xplasma.mid alfredh.mid gloomy.mid intents.mid

music 3 inhiding.mid FATCMDR.mid NAMES.MID subway.mid invader.mid gotham.mid 233c.mid lordofla.mid urban.mid spook.mid whomp.mid

music 4 missimp.mid prepd.mid bakedgds.mid cf.mid lemchill.mid pob.mid warehaus.mid layers.mid floghorn.mid depart.mid restrict.mid

So, following that process, your filenames would need to be:

GRABBAG.ogg BRIEFING.ogg

stalker.ogg dethtoll.ogg streets.ogg watrwld1.ogg snake1.ogg thecall.ogg ahgeez.ogg dethtoll.ogg streets.ogg watrwld1.ogg snake1.ogg

futurmil.ogg storm.ogg gutwrnch.ogg robocrep.ogg stalag.ogg pizzed.ogg alienz.ogg xplasma.ogg alfredh.ogg gloomy.ogg intents.ogg

inhiding.ogg FATCMDR.ogg NAMES.ogg subway.ogg invader.ogg gotham.ogg 233c.ogg lordofla.ogg urban.ogg spook.ogg whomp.ogg

missimp.ogg prepd.ogg bakedgds.ogg cf.ogg lemchill.ogg pob.ogg warehaus.ogg layers.ogg floghorn.ogg depart.ogg restrict.ogg

I will eventually make the music loading code try some filename permutations when it tries opening files to account for trivial case-sensitivity mismatches (i.e. .ogg extension replacement, lowercased, uppercased, as defined). I may consider having it try those combinations under a 'music' subdirectory. Note though I'm not particularly interested in having Ogg substitutes for game sounds be supported. So for now, if you want fancy substitute music and you're on a case-sensitive system, you'll just have to name the files as the game expects them and deal with those quirks, or patch the code to your liking until I get around to doing it.

It wouldn't be a bad idea to also just grab a small but decent soundfont like this to drop in the directory alongside duke3d.grp as a failsafe.

Jonathon

vanfanel commented 3 years ago

@jonof Whoa! Thanks a LOT for the -g parameter! It works perfect with this ogg music pack: https://sc55.duke4.net

Having the music files in a ZIP is very convenient for me, also, so that's what I will do from now on. Thanks a lot, really!

For MIDI: I knew about merlin gold, such a good soundfont for Scummvm, too. I have copied it to the same directory where the duke3d.grp file lives, as merlin.sf2, but the game doesn't have any music this way. Should I also pass a parameter or something?

jonof commented 3 years ago

If you're seeing a message like fluidsynth: error: Failed to connect to Jack server then you should try editing duke3d.cfg and adding MusicParams = "audio.driver=alsa" to the [Sound Setup] section of the file. There are other drivers like 'pulseaudio' and 'portaudio' you can try if 'alsa' doesn't work either.