Skip to content

Commit

Permalink
Merge branch 'add-sdl_mixer' into 'main'
Browse files Browse the repository at this point in the history
Add sdl mixer

See merge request tdt4102/vs-code/resources!15
  • Loading branch information
joakibhu committed Nov 2, 2025
2 parents 3d1e788 + 2b3aefb commit cc36130
Show file tree
Hide file tree
Showing 38 changed files with 4,303 additions and 3 deletions.
Binary file added dependencies/song.mp3
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Color.h"
#include "Font.h"
#include "Image.h"
#include "Audio.h"
#include "KeyboardKey.h"
#include "Point.h"
#include "Widget.h"
Expand Down Expand Up @@ -129,5 +130,8 @@ class AnimationWindow {
void setBackgroundColor(TDT4102::Color newBackgroundColor);

float get_delta_mouse_wheel() const;

//
void play_audio(TDT4102::Audio& audio, int loops = 0);
};
} // namespace TDT4102
29 changes: 29 additions & 0 deletions dependencies/subprojects/animationwindow/include/Audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <string>
#include <filesystem>
#include <SDL_mixer.h>

namespace TDT4102 {
struct Audio {
// Allow the audio to be read out and played despite being private
friend class AnimationWindow;

public:
explicit Audio();
explicit Audio(std::filesystem::path pathToAudioFile);
~Audio();


private:
Mix_Chunk *sfx = nullptr;
Mix_Music *mus = nullptr;
bool ready = false; // flag to load audio before playing
bool isMusic = false;

std::filesystem::path src = "non existent file";

void load();
void play(int loops = 0);
};
}
11 changes: 9 additions & 2 deletions dependencies/subprojects/animationwindow/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ project('animationwindow', ['c', 'cpp'], version: '0.01', default_options: ['cpp
if host_machine.system() == 'windows'
sdl2_dep = subproject('sdl2_windows').get_variable('sdl2_windows_dep')
sdl2image_dep = subproject('sdl2_image_windows').get_variable('sdl2_image_windows_dep')
sdl2mixer_dep = subproject('sdl2_mixer_windows').get_variable('sdl2_mixer_windows_dep')
else
sdl2_dep = dependency('sdl2')
sdl2image_dep = dependency('sdl2_image')
sdl2mixer_dep = dependency('SDL2_mixer')
endif


Expand All @@ -23,13 +25,18 @@ build_files = [
'src/AnimationWindow.cpp',
'src/Color.cpp',
'src/Image.cpp',
'src/Audio.cpp',
'src/Widget.cpp']
incdir = include_directories('include')
animationwindow = static_library('animationwindow', build_files, include_directories: incdir, dependencies: [sdl2_dep, sdl2image_dep], install: true)
animationwindow = static_library('animationwindow', build_files, include_directories: incdir, dependencies: [sdl2_dep, sdl2image_dep, sdl2mixer_dep], install: true)
install_subdir('include', install_dir: '.')
install_subdir('src', install_dir: '.')

animationwindow_dep = declare_dependency(link_with: animationwindow, include_directories: incdir)
animationwindow_dep = declare_dependency(
link_with: animationwindow,
include_directories: incdir,
dependencies: [sdl2_dep, sdl2image_dep, sdl2mixer_dep]
)

import('pkgconfig').generate(animationwindow)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ static bool sdlHasBeenInitialised = false;
TDT4102::AnimationWindow::AnimationWindow(int x, int y, int width, int height, const std::string& title) {
// Initialise SDL if it has not already been
if (!sdlHasBeenInitialised) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
throw std::runtime_error("Failed to create an AnimationWindow: The SDL backend could not be initialised.\nError details: " + std::string(SDL_GetError()));
}
sdlHasBeenInitialised = true;
Expand Down Expand Up @@ -415,3 +415,8 @@ void TDT4102::AnimationWindow::setBackgroundColor(TDT4102::Color newBackgroundCo
SDL_SetRenderDrawColor(rendererHandle, backgroundColor.redChannel, backgroundColor.greenChannel, backgroundColor.blueChannel, backgroundColor.alphaChannel);
SDL_RenderClear(rendererHandle);
}

void TDT4102::AnimationWindow::play_audio(TDT4102::Audio& audio, int loops) {
audio.play(loops);
}

69 changes: 69 additions & 0 deletions dependencies/subprojects/animationwindow/src/Audio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "Audio.h"


TDT4102::Audio::Audio() {}

TDT4102::Audio::Audio(const std::filesystem::path pathToAudioFile) {
src = pathToAudioFile;
}

void TDT4102::Audio::load() {
if(!std::filesystem::exists(src)) {
throw std::runtime_error("The audio file located at: " + src.string() + "\ncould not be found.");
}

if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 2048) < 0) {
throw std::runtime_error("Failed to open the audio device.\nError details: " + std::string(Mix_GetError()));
}

if (src.string().ends_with(".wav")) { // assume .wav is sound effect
sfx = Mix_LoadWAV(src.string().c_str());
if (sfx == NULL) {
throw std::runtime_error("Failed to load sound effect. \nError details: " + std::string(Mix_GetError()));
}
} else if (src.string().ends_with(".mp3")) { // assume .mp3 is music
mus = Mix_LoadMUS(src.string().c_str());
if (mus == NULL) {
throw std::runtime_error("Failed to load music. \nError details: " + std::string(Mix_GetError()));
}
isMusic = true;
} else {
throw std::runtime_error("Unrecognized audio format! Please only use .wav or .mp3 files");
}

ready = true;

}

void TDT4102::Audio::play(int loops) {

if (loops < 0) {
throw std::runtime_error("Number of loops must be positive!");
}

if(!ready) {
load();
}
if (isMusic) {
Mix_PlayMusic(mus, loops == 0 ? loops : loops--);
} else {
Mix_PlayChannel(-1, sfx, loops == 0 ? loops-- : loops);
}


}

TDT4102::Audio::~Audio() {
if (sfx != nullptr) {
Mix_FreeChunk(sfx);
sfx = nullptr;
}

if (mus != nullptr) {
Mix_FreeMusic(mus);
mus = nullptr;
}
Mix_CloseAudio();
Mix_Quit();
}

13 changes: 13 additions & 0 deletions dependencies/subprojects/sdl2_mixer.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[wrap-file]
directory = SDL2_mixer-2.6.2
source_url = https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.6.2.tar.gz
source_filename = SDL2_mixer-2.6.2.tar.gz
source_hash = 8cdea810366decba3c33d32b8071bccd1c309b2499a54946d92b48e6922aa371
patch_filename = sdl2_mixer_2.6.2-4_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_mixer_2.6.2-4/get_patch
patch_hash = 127025fa0666dd3ea66fb7c334182c393a748fb78810c6a44cdc1a85d619d934
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_mixer_2.6.2-4/SDL2_mixer-2.6.2.tar.gz
wrapdb_version = 2.6.2-4

[provide]
sdl2_mixer = sdl2_mixer_dep
17 changes: 17 additions & 0 deletions dependencies/subprojects/sdl2_mixer_windows/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
31 changes: 31 additions & 0 deletions dependencies/subprojects/sdl2_mixer_windows/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

SDL_mixer 2.0

The latest version of this library is available from GitHub:
https://github.com/libsdl-org/SDL_mixer/releases

Due to popular demand, here is a simple multi-channel audio mixer.
It supports 8 channels of 16 bit stereo audio, plus a single channel of music. It can load FLAC, MP3, Ogg, VOC, and WAV format audio. It can also load MIDI, MOD, and Opus audio, depending on build options (see the note below for details.)

See the header file SDL_mixer.h and the examples playwave.c and playmus.c for documentation on this mixer library. This documentation is also available online at https://wiki.libsdl.org/SDL2_mixer

The process of mixing MIDI files to wave output is very CPU intensive, so if playing regular WAVE files sound great, but playing MIDI files sound choppy, try using 8-bit audio, mono audio, or lower frequencies.

If you have built with FluidSynth support, you'll need to set the SDL_SOUNDFONTS environment variable to a Sound Font 2 (.sf2) file containing the musical instruments you want to use for MIDI playback.
(On some Linux distributions you can install the fluid-soundfont-gm package)

To play MIDI files using Timidity, you'll need to get a complete set of GUS patches from:
http://www.libsdl.org/projects/mixer/timidity/timidity.tar.gz
and unpack them in /usr/local/lib under UNIX, and C:\ under Win32.

This library is under the zlib license, see the file "LICENSE.txt" for details.

Note:
Support for software MIDI, MOD, and Opus are not included by default because of the size of the decode libraries, but you can get them by running external/download.sh
- When building with CMake, you can enable the appropriate SDL2MIXER_* options defined in CMakeLists.txt. SDL2MIXER_VENDORED allows switching between system and vendored libraries.
- When building with configure/make, you can build and install them normally and the configure script will detect and use them.
- When building with Visual Studio, you will need to build the libraries and then add the appropriate LOAD_* preprocessor define to the Visual Studio project.
- When building with Xcode, you can edit the config at the top of the project to enable them, and you will need to include the appropriate framework in your application.
- For Android, you can edit the config at the top of Android.mk to enable them.

The default MP3 support is provided using minimp3. SDL_mixer also supports using libmpg123: you can enable it by passing --enable-music-mp3-mpg123 to configure.
Binary file not shown.
4 changes: 4 additions & 0 deletions dependencies/subprojects/sdl2_mixer_windows/copy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env python3

import sys, shutil
shutil.copyfile(sys.argv[1], sys.argv[2])
Loading

0 comments on commit cc36130

Please sign in to comment.