ipatix / agbplay

Music player for the most common GBA sound format
GNU Lesser General Public License v3.0
119 stars 20 forks source link

agbplay

agbplay is a music player with Terminal interface for GBA ROMs that use the most common (mp2k/m4a) sound engine format. The code itself is written in C++.

Quick overview

agbplay

Controls

Current state of things

To do

Dependencies

Debian Arch Cygwin
build-essential base-devel make, gcc-g++
libboost-all-dev boost libboost-devel
portaudio19-dev portaudio libportaudio-devel
libncursesw5-dev ncurses5-compat-libs AUR libncurses-devel
libsndfile1-dev libsndfile libsndfile-devel
libjsoncpp-dev jsoncpp libjsoncpp-devel

Configuration JSON

Since 21.10.2020, agbplay uses a standard JSON format for storing playlists and other configuration data.

Take a look at this sample scheme:

{
    "id" : "agbplay",
    "cgb-polyphony" : "mono-strict",
    "wave-output-dir" : "/home/misterx/Music/agbplay",
    "max-loops-export" : 1,
    "max-loops-playlist" : 1,
    "playlists" : 
    [
        {
            "games" : 
            [
                "BPED", "BPEE"
            ],
            "pcm-fixed-rate-resampling-algo" : "blep",
            "pcm-master-volume" : 12,
            "pcm-resampling-algo" : "linear",
            "pcm-reverb-buffer-len" : 1584,
            "pcm-reverb-level" : 0,
            "pcm-reverb-type" : "normal",
            "pcm-samplerate" : 4,
            "song-track-limit" : 10,
            "songs" : 
            [
                {
                    "index" : 414,
                    "name" : "Intro Video"
                },
                {
                    "index" : 442,
                    "name" : "The Pokemon"
                },
                {
                    "index" : 413,
                    "name" : "Title Screen"
                },
            ]
        },
        {
            "games" :
            [
                "AGSE"
            ],
            ...
        }
    ]
}

The root element in the JSON has the following properties:

Each playlist entry in the array contains the following properties:

Sound formatting notes

On Nintendo's engine (that runs on the hardware) it allows the developer to set a master volume for PCM sound from 0 to 15. This doesn't affect CGB sounds and changing it will result in a different volume ratio between PCM and CGB sounds.

As for the reverb level, you can globally set it from 0 to 127. This overrides the song's reverb settings in their song header.

The 'magic' samplerate values are listed below. Note that the 'magic' values correspond to the values like they are used by m4aSoundMode (values: 1-12). agbplay will use this 'magic' value to get the sample rate for so-called "fixed frequency sounds".

Magic values (in Hz): 5734, 7884, 10512, 13379, 15768, 18157, 21024, 26758, 31536, 36314, 40137, 42048

One more thing about reverb: Most games just use Nintendo's default reverb algorithm (or reverb of 0 for no reverb at all). However, some games have implemented their own algorithms. You can use the following values in combination with the option pcm-reverb-type to set it:

Last but not least, agbplay now supports different resampling algorithms which can be set in the JSON-File. There is a setting for normal PCM sounds pcm-resampling-algo and pcm-fixed-rate-resampling-algo for fixed frequency sounds (mostly used for drums). They sypport the following values:

Importing tags from GSF files

Manually creating playlists/tags for some games can be avoided if you can find an existing GSF set for that particular game.

Use the supplied playlist_from_gsf.py script and pass it a set of .minigsf files. The script will then parse the song names and song numbers from those files and will output a JSON formatted array that then can be used for the property songs, which is explained above. So you can copy that JSON array into your agbplay.json for that particular game.

Additional information

Debian portaudio issues

If you have issues installing portaudio19-dev on Debian (conflicting packages) make sure to install "libjack-jackd2-dev" before. The reason for this is that portaudio on Debian depends on either the old dev package for jack or the jack2 dev package. By default apt wants to install the old one which for some reason causes problems on a lot of systems.

"Missing DLLs"

If you happen to get errors about missing DLLs and you compiled agbplay under the Cygwin environement, you also have to run agbplay from the Cygwin environment. Cygwin compiled software does require the Cygwin runtime for 99% of the programs, so please accept that you have to do this for agbplay as well.

Terminal Colors

agbplay requires 256 color terminal support. If you happen to see the message Terminal does not support 256 colors, you may have to use a different terminal emulator or you have to fix your TERM variable.

If you are using the Cygwin environment, you can do the following:

Another option is to use the Windows Terminal from the Windows Store (although it sometimes still seems to have a few graphical issues).

Never ever set your TERM variable in your .bashrc or equivalent. This will cause issues if you are running your shell from the wrong terminal emulator. The TERM string required depends on the terminal emulator you use and thus should only be set by it.

Building

Install all dependencies (listed above) and run make.

Ideally the code should compile fine if all dependencies are installed.

It has been tested on Cygwin (Windows), Debian and Arch Linux, all on x86-64. Native Windows is currently NOT supported. I did some compilation tests with the MinGW 64 compiler (MSYS2). However, even when compiling the code, getting native 256 colors to work and getting all the unicode characters to display properly wasn't something I was able to achieve during a long day.

Contributing

If you have any suggestions feel free to open up a pull request or just an issue with some basic information. For issues I'm mostly focused on fixing bugs and not really on any new features.

Please be reminded that this was a "C++ learning project" for me and therefore the code is quite weird and probably contains a lot of "bad practices" in a few places.