Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_mixer 2? #3985

Closed
ooxi opened this issue Dec 27, 2015 · 31 comments
Closed

SDL_mixer 2? #3985

ooxi opened this issue Dec 27, 2015 · 31 comments

Comments

@ooxi
Copy link

ooxi commented Dec 27, 2015

Hi,

has there been an attempt to port SDL_mixer 2? It seams like SDL_mixer 1.2 is embedded but does rely one the browser to do the decoding (just like SDL 1 is embedded but the SDL 2 port is far more advanced)

-- ooxi

@iboB
Copy link

iboB commented Jan 20, 2016

Actually you can build SDL2_mixer without the plugins from source just as you would any other library.

To support the mp3 or mod plugins you would need support from libmpeg and libmodplug for emscripten (I don't know whether such exist)

To add ogg support you can use the ogg and vorbis ports by adding -s USE_OGG=1 -s USE_VORBIS=1 to the compiler and linker settings

@fdelapena
Copy link

fdelapena commented Jan 29, 2016

You actually may use all SDL_mixer dependencies, it works as expected.

Update: the following patches are not needed anymore with SDL 2.0.7 and SDL_mixer 2.0.2.

If you want to make MIDI music (internal timidity) and tracker music (libmodplug) work in emscripten, you need to patch SDL2_mixer because timidity and libmodplug drivers in SDL2_mixer don't support 32 bit device mixing (used by Web Audio).

Here is the new proposed custom Mix_OpenAudioDevice() function to properly set the frequency change, unsupported by SDL_mixer, which uses legacy SDL_OpenAudio(). Once the patch is applied, it will work:

#ifdef EMSCRIPTEN
    // Note: this requires a patched SDL_mixer currently
    Mix_OpenAudioDevice(NULL, 0, frequency, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
#else
    Mix_OpenAudio(frequency, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096)
#endif

Another trick: to prevent noise when using wav and ogg, don't use Mix_PlayMus() because it is buggy, use Mix_PlayChannel() in the meanwhile.

Final suggestion: to prevent resampling buffering issues (choppy audio) due to another (SDL2?) bug, you should also patch the audio initialization to get the native browser frequency, e.g.:

#if EMSCRIPTEN
#  include <emscripten.h>
#endif

// (...)
#if EMSCRIPTEN

    int const frequency = EM_ASM_INT_V({
        var context;
        try {
            context = new AudioContext();
        } catch (e) {
            context = new webkitAudioContext();
        }
        return context.sampleRate;
    });
#else
    int const frequency = 44100;
#endif

@ooxi
Copy link
Author

ooxi commented Jan 29, 2016

Thanks for the hints @fdelapena! Do you have SDL2_mixer already compiled? Could you maybe provide the binaries?

@fdelapena
Copy link

fdelapena commented Jan 29, 2016

Thanks for the hints @fdelapena! Do you have SDL2_mixer already compiled? Could you maybe provide the binaries?

We have an automated toolchain with generated .a static files, you might need to rename needed .a to .bc (bitcode) to make them work with emcc.
https://ci.easyrpg.org/view/Toolchains/job/toolchain-emscripten/ws/

Here is the relevant part of our automated build script of SDL2 and SDL2_mixer for Emscripten.

By the way, if you want to play midi files you need to include GUS patches for timidity support and embed them in the dat file.

@fdelapena
Copy link

SDL_mixer from Hg just added Mix_OpenAudioDevice at https://hg.libsdl.org/SDL_mixer/rev/fb0562cc1559 so you don't need to patch SDL_mixer anymore with the current Mercurial version 👍.

@Fighter19
Copy link

I tried builidng my game. But when running it, it fails when using Mix_LoadWAV_RW
Type error: "rwops is null"
Maybe he couldn't find the file, but the html is being loaded in the same folder the executable normally is. And loading a file format it does not support cannot be the problem (tested in an empty directory).
So for me SDL_mixer with SDL2 does not really work.

@hyp1
Copy link

hyp1 commented Oct 22, 2017

@Fighter19 i had the same problem.
Everything worked to the point when, to play .wav files.
I solved it by using the buildscipt from @fdelapena to build the SDL_mixer and coping the SDL_mixer folder to $EMSCRIPTEN/system/include/SDL.
Good luck

@rchaser53
Copy link

I try to convert the rust application to wasm.
And I have the same problem.

Acutually I also want to use the buildscript.
Please give me the buildscript from @fdelapena.
Thank you.

@hyp1
Copy link

hyp1 commented Oct 26, 2017

Hi,
the build script from felapenais in this thread.
Here is the relevant part of our automated build script of SDL2 and SDL2_mixer for Emscripten.*
I managed to get it work for my project (a gamelibrary für sprite based games), but i now believe there is a bug.in the SDL_mixer implementation.
That only affects wenn i try to play audio Mix_L
oadWAV from a class that ist compiled to a library.
Best Regards

@rchaser53
Copy link

Sorry. I missed it.
Honestly I also think it's the bug in the SDL_mixer implementation.
Anyway I'll try the build script.
Thank a lot.

@fdelapena
Copy link

fdelapena commented Oct 26, 2017

By the way, with SDL 2.0.7 and SDL_mixer 2.0.2 have been released, the patch I suggested is not needed anymore, the noise resampling issue has been fixed too, it should work nicely out of the box with Mix_PlayMus() at any audio frequency.

Update: I've updated the CI link to our toolchain build job.

@Shchvova
Copy link

So, is there a way to include SDL2/SDL_mixer.h at this point without rebuilding it myself?

@kripken
Copy link
Member

kripken commented Dec 18, 2017

Not yet. @aidanhs mentioned on the mailing list he might add an emscripten port for it - @aidanhs, any update there?

@aidanhs aidanhs mentioned this issue Dec 28, 2017
@aidanhs
Copy link
Contributor

aidanhs commented Dec 28, 2017

I've made a PR for an initial iteration of SDL2_mixer at #5995 (the test uses the sample detection trick, thanks @fdelapena)

It's pretty rough and is intended as a first attempt for people who actually care about audio to create new PRs on top of - I only built mixer in the first place because it was easier than ripping it out of the program I was porting to emscripten :)

The PR currently:

  • is deliberately configured to just support OGG (supporting WAV may be as easy as just changing a flag and adding a test)
  • is sdl_mixer release 2.0.0 (2.0.2 requires a more recent version of sdl2 than emscripten has available -
    see Merge upstream 2.0.7 emscripten-ports/SDL2#52)

@kripken
Copy link
Member

kripken commented Dec 4, 2018

Fixed by #7599, we now have SDL2_mixer in ports thanks to @aidanhs and @superzazu!

@kripken kripken closed this as completed Dec 4, 2018
@lherman-cs
Copy link

@kripken I'm still getting an error saying that the include file for SDL2/SDL_mixer.h is not there. I've turned on -s USE_SDL_MIXER=2. Also, I tried to use embuilder.py directly to install SDL_mixer. But, I found that the script didn't properly extract the archive from https://github.com/emscripten-ports/SDL2_mixer.

cache:INFO: generating port: libSDL2_image_bmp-png.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libSDL2_image_bmp-png.bc" for subsequent builds)
cache:INFO:  - ok
In file included from src/core/unity.cpp:1:
In file included from src/core/engine.cpp:1:
In file included from include/core/engine.h:4:
In file included from include/global/global.h:5:
In file included from include/global/mixer.h:2:
include/util/audio.h:3:10: fatal error: 'SDL2/SDL_mixer.h' file not found
#include <SDL2/SDL_mixer.h>
         ^~~~~~~~~~~~~~~~~~
1 error generated.
shared:ERROR: compiler frontend failed to generate LLVM bitcode, halting

@hyp1
Copy link

hyp1 commented Apr 16, 2019

@lherman-cs Just copy SDL2/SDL_mixer.h to your include directory.
On my system (Ubuntu) that is /usr/local/SDL2/SDL_mixer.h

@lherman-cs
Copy link

@hyp1 yes, I know that I can do that. But, isn't it a lot nicer if the script already provides that automatically, like it does for SDL_image?

@hyp1
Copy link

hyp1 commented Apr 16, 2019

@lherman-cs What script do you mean by install SDL_Image automaticly.
i just did sudo apt-get install for the SDL libraries and had the same struggle as you.
it did only work for me, by moving that header file (SDL_mixer) by hand to the correct place.

@lherman-cs
Copy link

lherman-cs commented Apr 16, 2019

@hyp1 if you asked which script that caused it, I haven't had a chance to read the code that's responsible for this. So, I can't exactly tell you where. But, if you asked for what script that I ran, it's the embuilder.py

I'm using a custom docker image that is based on https://hub.docker.com/r/trzeci/emscripten/ with sdk-incoming-64bit tag, as my toolchain to build my software. I basically extended this image by running embuilder.py build sdl2 sdl2-image sdl2-image-png sdl2-mixer sdl2-ttf zlib libpng. After the image is built, I just need to compile my codes as if they were on my machine without doing anything extra, like copying the include files from the port.

@hyp1
Copy link

hyp1 commented Apr 16, 2019

@lherman-cs ah ok.
i compiled and installed that all by hand.
in this case you should file an issue to the image creator, that this file is not in place.

@sbc100
Copy link
Collaborator

sbc100 commented Apr 16, 2019

@kripken I'm still getting an error saying that the include file for SDL2/SDL_mixer.h is not there. I've turned on -s USE_SDL_MIXER=2. Also, I tried to use embuilder.py directly to install SDL_mixer. But, I found that the script didn't properly extract the archive from https://github.com/emscripten-ports/SDL2_mixer.

cache:INFO: generating port: libSDL2_image_bmp-png.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libSDL2_image_bmp-png.bc" for subsequent builds)
cache:INFO:  - ok
In file included from src/core/unity.cpp:1:
In file included from src/core/engine.cpp:1:
In file included from include/core/engine.h:4:
In file included from include/global/global.h:5:
In file included from include/global/mixer.h:2:
include/util/audio.h:3:10: fatal error: 'SDL2/SDL_mixer.h' file not found
#include <SDL2/SDL_mixer.h>
         ^~~~~~~~~~~~~~~~~~
1 error generated.
shared:ERROR: compiler frontend failed to generate LLVM bitcode, halting

Can you post the full compiler command and the full output. Certainly looks like bug but I need more info to reproduce it.

@lherman-cs
Copy link

lherman-cs commented Apr 16, 2019

@sbc100 This is the script for compiling, https://github.com/lherman-cs/cs4160/blob/develop/assignment-4/build-wasm.sh.

Note: in build-wasm.sh, -s USE_SDL_MIXER=2 is also added to EMFLAGS. It's not in my repo yet since it's still broken.

This my Dockerfile to create the custom image, https://github.com/lherman-cs/cs4160/blob/develop/assignment-4/Dockerfile.

I'll post the full output as soon as I get home.

@lherman-cs
Copy link

lherman-cs commented Apr 17, 2019

@sbc100 alright, here we go. This is the full output, which is apparently I've posted already... haha

cache:INFO: generating port: libSDL2_image_bmp-png.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libSDL2_image_bmp-png.bc" for subsequent builds)
cache:INFO:  - ok
In file included from src/core/unity.cpp:1:
In file included from src/core/engine.cpp:1:
In file included from include/core/engine.h:4:
In file included from include/global/global.h:5:
In file included from include/global/mixer.h:2:
include/util/audio.h:3:10: fatal error: 'SDL_mixer.h' file not found
#include <SDL_mixer.h>
         ^~~~~~~~~~~~~
1 error generated.
shared:ERROR: compiler frontend failed to generate LLVM bitcode, halting

@sbc100
Copy link
Collaborator

sbc100 commented Apr 17, 2019

Can you post the failing command line?

The lines regarding generating the port should only show up the first time its generated.. can you verify that you don't see those lines when you run the command line for a second time?

Also it looks like the correct way to include that file is either <SDL2/SDL_mixer.h>. which I see in your first failure but not in the second.

@lherman-cs
Copy link

@sbc100 I'm sorry. I was just experimenting with the include path. It should be <SDL2/SDL_mixer.h> as I showed earlier.

I'm sorry. I misunderstood what you're asking for before. Following is the output from the first time I ran the script:

root@770ef5265d3a:/src# /emsdk_portable/sdk/embuilder.py build sdl2 sdl2-image sdl2-image-png sdl2-ttf sdl2-mixer zlib libpng
embuilder:INFO: building and verifying sdl2
system_libs:WARNING: retrieving port: sdl2 from https://github.com/emscripten-ports/SDL2/archive/version_17.zip
system_libs:WARNING: unpacking port: sdl2
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libSDL2.bc
cache:INFO: generating port: libSDL2.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libSDL2.bc" for subsequent builds)
cache:INFO:  - ok
embuilder:INFO: ...success
embuilder:INFO: building and verifying sdl2-image
system_libs:WARNING: retrieving port: sdl2_image from https://github.com/emscripten-ports/SDL2_image/archive/version_4.zip
system_libs:WARNING: unpacking port: sdl2_image
embuilder:INFO: ...success
embuilder:INFO: building and verifying sdl2-image-png
system_libs:WARNING: retrieving port: zlib from https://github.com/emscripten-ports/zlib/archive/version_1.zip
system_libs:WARNING: unpacking port: zlib
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libz.a
cache:INFO: generating port: libz.a... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libz.a" for subsequent builds)
cache:INFO:  - ok
system_libs:WARNING: retrieving port: libpng from https://github.com/emscripten-ports/libpng/archive/version_1.zip
system_libs:WARNING: unpacking port: libpng
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libpng.bc
cache:INFO: generating port: libpng.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libpng.bc" for subsequent builds)
root:INFO: building port: libpng
create_lib /emsdk_portable/data/.cache/asmjs/ports-builds/libpng/libpng.bc
cache:INFO:  - ok
embuilder:INFO: ...success
embuilder:INFO: building and verifying sdl2-ttf
system_libs:WARNING: retrieving port: freetype from https://github.com/emscripten-ports/FreeType/archive/version_1.zip
system_libs:WARNING: unpacking port: freetype
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libfreetype.a
cache:INFO: generating port: libfreetype.a... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libfreetype.a" for subsequent builds)
cache:INFO:  - ok
system_libs:WARNING: retrieving port: sdl2_ttf from https://github.com/emscripten-ports/SDL2_ttf/archive/version_1.zip
system_libs:WARNING: unpacking port: sdl2_ttf
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libSDL2_ttf.bc
cache:INFO: generating port: libSDL2_ttf.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libSDL2_ttf.bc" for subsequent builds)
cache:INFO:  - ok
embuilder:INFO: ...success
embuilder:INFO: building and verifying sdl2-mixer
system_libs:WARNING: retrieving port: ogg from https://github.com/emscripten-ports/ogg/archive/version_1.zip
system_libs:WARNING: unpacking port: ogg
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libogg.bc
cache:INFO: generating system library: libogg.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libogg.bc" for subsequent builds)
root:INFO: building port: ogg
root:INFO: Cache: deleting cached file: /emsdk_portable/data/.cache/asmjs/libvorbis.bc
create_lib /emsdk_portable/data/.cache/asmjs/ports-builds/ogg/libogg.bc
cache:INFO:  - ok
system_libs:WARNING: retrieving port: vorbis from https://github.com/emscripten-ports/vorbis/archive/version_1.zip
system_libs:WARNING: unpacking port: vorbis
cache:INFO: generating system library: libvorbis.bc... (this will be cached in "/emsdk_portable/data/.cache/asmjs/libvorbis.bc" for subsequent builds)
root:INFO: building port: vorbis
create_lib /emsdk_portable/data/.cache/asmjs/ports-builds/vorbis/libvorbis.bc
cache:INFO:  - ok
system_libs:WARNING: retrieving port: sdl2_mixer from https://github.com/emscripten-ports/SDL2_mixer/archive/release-2.0.1.zip
system_libs:WARNING: unpacking port: sdl2_mixer
embuilder:INFO: ...success
embuilder:INFO: building and verifying zlib
embuilder:INFO: ...success
embuilder:INFO: building and verifying libpng
embuilder:INFO: ...success

@sbc100
Copy link
Collaborator

sbc100 commented Apr 17, 2019

So it looks like the embuilder command works fine?

But your errors seem to be coming from a file called unity.cpp .. which ends up including include/global/mixer.h which then tries to include SDL mixer. Presumably unity.cpp and mixer.h are part of your project? Can you include that command line you used to compiler unity.cpp? And perhaps include the output with EMCC_VERBOSE=1 so we can see why that SDL2 mixer include paths don't seem to be added? It maybe not be relevant but that command should not be generating anything in the cache if embuilder has previously been run.

Perhaps I'm misunderstanding and its the embuilder command thats actually failing?

@lherman-cs
Copy link

lherman-cs commented Apr 17, 2019

I'm not sure. I thought that it was coming from embuilder for not properly setting up the sdl2_mixer. As far as I know, there's a system setting that you can set so that, by default, it'll include some folders, like in gcc, you can see the list with gcc -v. (I'm not expert on this...)

Yes, I'm using unity build, which is basically to speed up my compilation time and make it easy to create the makefile (I don't like cmake). unity.cpp basically will just "archive" my source codes for the global module. In the global module, it has mixer.h, which is basically a simple wrapper for SDL_mixer.

This is the script that I run to build my project:

#!/bin/bash

SRCS=`ls src/**/unity.cpp`
CXXFLAGS=(-O3 -std=c++17 -Iinclude -I/vendor/include/expat)
LDFLAGS=(-L/vendor/lib/expat -lexpat)
EMFLAGS=(
    -s TOTAL_MEMORY=1GB
    -s USE_SDL=2
    -s USE_SDL_TTF=2
    -s USE_SDL_IMAGE=2
    -s USE_SDL_MIXER=2
    -s SDL2_IMAGE_FORMATS='["bmp","png"]'
    --preload-file assets
    --closure 1
    --shell-file ./wasm-template.html
)

FLAGS="${CXXFLAGS[@]} ${LDFLAGS[@]} ${EMFLAGS[@]}"
CONFIG=./assets/config.xml

# Turn frameCap for wasm because wasm already has its own frameCap
sed -i 's\<frameCapOn>true</frameCapOn>\<frameCapOn>false</frameCapOn>\g' ${CONFIG}
if [[ -z ${CI} ]]; then
    docker run -e EMCC_DEBUG=1 --rm -v ${PWD}:/src lherman/sdl emcc -o index.html ${FLAGS[@]} ${SRCS[@]}
else
    emcc -o index.html ${FLAGS[@]} ${SRCS[@]}
fi
# Turn the frameCap back on
sed -i 's\<frameCapOn>false</frameCapOn>\<frameCapOn>true</frameCapOn>\g' ${CONFIG}

Here is the output when EMCC_DEBUG=1: https://storage.lukas-coding.us/s/yMJmxwCirZAB8Bg (the output is too big)

@sbc100
Copy link
Collaborator

sbc100 commented Apr 17, 2019

So your sdl2_mixer include path is correctly being passed clang as we can see in your log: -isystem/emsdk_portable/data/.cache/asmjs/ports-builds /freetype/include.

Might be worth checking that the headers do actaully exist in:
/emsdk_portable/data/.cache/asmjs/ports-builds/freetype/include

If they don't then perhaps your cache somehow corrupted and that running emcc with --clear-cache might fix it.

@lherman-cs
Copy link

So, as you suggested, I went ahead and cleared the cache by emcc --clear-cache and, somehow, it compiled fine.

But, this seems strange because I'm using docker and I've tried to recompile my docker image multiple times and still gave the same result.

@ptitSeb
Copy link
Contributor

ptitSeb commented Sep 3, 2019

In current version of emscripten (using emsdk-portable with 1.38.31), SDL2_mixer build without OGG support.
I get

...
checking vorbis/vorbisfile.h usability... yes
checking vorbis/vorbisfile.h presence... no
configure: WARNING: vorbis/vorbisfile.h: accepted by the compiler, rejected by the preprocessor!
configure: WARNING: vorbis/vorbisfile.h: proceeding with the compiler's result
checking for vorbis/vorbisfile.h... yes
checking for ov_open_callbacks in -lvorbisfile -lvorbis -logg -lm... no
configure: WARNING: *** Unable to find Ogg Vorbis library (http://www.xiph.org/)
configure: WARNING: Ogg Vorbis support disabled
configure: WARNING: MP3 support disabled
configure: creating ./config.status
config.status: executing libtool commands
configure: creating ./config.status
...

It seems it needs libvorbisfile, but only libvorbis and libogg are present.

(It seems the included configure tries to link with -lvorbisfile -lvorbis -logg instead of -s USE_OGG=1 -s USE_VORBIS=1... Not sure if it's the source of the issue, but after messing with the configue I got ogg running)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests