From b957923561ea1a887afed8a2845f214bd02ed749 Mon Sep 17 00:00:00 2001 From: jonyluke Date: Mon, 17 Jun 2019 17:06:25 +0200 Subject: [PATCH] Sdl2 audio example (#53) --- audio/sdl2-audio/Makefile | 213 ++++++++++++++++++++++++++++++++ audio/sdl2-audio/romfs/test.mp3 | Bin 0 -> 3408 bytes audio/sdl2-audio/source/main.c | 71 +++++++++++ 3 files changed, 284 insertions(+) create mode 100644 audio/sdl2-audio/Makefile create mode 100644 audio/sdl2-audio/romfs/test.mp3 create mode 100644 audio/sdl2-audio/source/main.c diff --git a/audio/sdl2-audio/Makefile b/audio/sdl2-audio/Makefile new file mode 100644 index 0000000..808d038 --- /dev/null +++ b/audio/sdl2-audio/Makefile @@ -0,0 +1,213 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +# +# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .json +# - config.json +# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead +# of a homebrew executable (.nro). This is intended to be used for sysmodules. +# NACP building is skipped as well. +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +ROMFS := romfs + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += -D__SWITCH__ $(INCLUDE) `aarch64-none-elf-pkg-config --cflags SDL2_mixer` + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := `aarch64-none-elf-pkg-config --libs SDL2_mixer` + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking since SDL2 is dependent on libstdc++ +#--------------------------------------------------------------------------------- + export LD := $(CXX) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.jpg) + ifneq (,$(findstring $(TARGET).jpg,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).jpg + else + ifneq (,$(findstring icon.jpg,$(icons))) + export APP_ICON := $(TOPDIR)/icon.jpg + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_ICON)),) + export NROFLAGS += --icon=$(APP_ICON) +endif + +ifeq ($(strip $(NO_NACP)),) + export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp +endif + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... +ifeq ($(strip $(APP_JSON)),) + @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf +else + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf +endif + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +ifeq ($(strip $(APP_JSON)),) + +all : $(OUTPUT).nro + +ifeq ($(strip $(NO_NACP)),) +$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp +else +$(OUTPUT).nro : $(OUTPUT).elf +endif + +else + +all : $(OUTPUT).nsp + +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm + +$(OUTPUT).nso : $(OUTPUT).elf + +endif + +$(OUTPUT).elf : $(OFILES) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/audio/sdl2-audio/romfs/test.mp3 b/audio/sdl2-audio/romfs/test.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..7528384390a97b2a9f1cb31a2ef038685a9cce9b GIT binary patch literal 3408 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 +#include +#include + +// Include the main libnx system header, for Switch development +#include + +// Include sdl2 headers +#include +#include + +// Main program entrypoint +int main(int argc, char *argv[]) +{ + // This example uses sdl2 library to play a mp3 file + + consoleInit(NULL); + + Result rc = romfsInit(); + if (R_FAILED(rc)) + printf("romfsInit: %08X\n", rc); + + else + printf("Press A button to play the sound!\n"); + + // Start SDL with audio support + SDL_Init(SDL_INIT_AUDIO); + + // Load support for the MP3 format + Mix_Init(MIX_INIT_MP3); + + // open 44.1KHz, signed 16bit, system byte order, + // stereo audio, using 4096 byte chunks + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096); + + // Load sound file to use + // Sound from https://freesound.org/people/jens.enk/sounds/434610/ + Mix_Music *audio = Mix_LoadMUS("romfs:/test.mp3"); + + // Main loop + while (appletMainLoop()) + { + // Scan all the inputs. This should be done once for each frame + hidScanInput(); + + // hidKeysDown returns information about which buttons have been + // just pressed in this frame compared to the previous one + u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); + + if (kDown & KEY_PLUS) + break; // break in order to return to hbmenu + + if (kDown & KEY_A) + Mix_PlayMusic(audio, 1); //Play the audio file + + // Update the console, sending a new frame to the display + consoleUpdate(NULL); + } + + // Free the loaded sound + Mix_FreeMusic(audio); + + // Shuts down SDL subsystems + SDL_Quit(); + + // Deinitialize and clean up resources used by the console (important!) + romfsExit(); + consoleExit(NULL); + return 0; +}