Skip to content

Commit 979ab79

Browse files
authored
Add Ogg Vorbis decoding example (#61)
Adapted from the high-quality example for Opus decoding Tested working on n3ds without speedup or cache enabled, thus should work flawlessly on o3ds
1 parent 19581db commit 979ab79

File tree

4 files changed

+604
-0
lines changed

4 files changed

+604
-0
lines changed

audio/ogg-vorbis-decoding/Makefile

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#---------------------------------------------------------------------------------
2+
.SUFFIXES:
3+
#---------------------------------------------------------------------------------
4+
5+
ifeq ($(strip $(DEVKITARM)),)
6+
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
7+
endif
8+
9+
TOPDIR ?= $(CURDIR)
10+
include $(DEVKITARM)/3ds_rules
11+
12+
#---------------------------------------------------------------------------------
13+
# TARGET is the name of the output
14+
# BUILD is the directory where object files & intermediate files will be placed
15+
# SOURCES is a list of directories containing source code
16+
# DATA is a list of directories containing data files
17+
# INCLUDES is a list of directories containing header files
18+
# GRAPHICS is a list of directories containing graphics files
19+
# GFXBUILD is the directory where converted graphics files will be placed
20+
# If set to $(BUILD), it will statically link in the converted
21+
# files as if they were data files.
22+
#
23+
# NO_SMDH: if set to anything, no SMDH file is generated.
24+
# ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional)
25+
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
26+
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
27+
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
28+
# ICON is the filename of the icon (.png), relative to the project folder.
29+
# If not set, it attempts to use one of the following (in this order):
30+
# - <Project name>.png
31+
# - icon.png
32+
# - <libctru folder>/default_icon.png
33+
#---------------------------------------------------------------------------------
34+
TARGET := $(notdir $(CURDIR))
35+
BUILD := build
36+
SOURCES := source
37+
DATA := data
38+
INCLUDES := include
39+
GRAPHICS := gfx
40+
GFXBUILD := $(BUILD)
41+
ROMFS := romfs
42+
#GFXBUILD := $(ROMFS)/gfx
43+
44+
#---------------------------------------------------------------------------------
45+
# options for code generation
46+
#---------------------------------------------------------------------------------
47+
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
48+
49+
CFLAGS := -g -Wall -O2 -mword-relocations \
50+
-ffunction-sections \
51+
$(ARCH)
52+
53+
CFLAGS += $(INCLUDE) -D__3DS__ `$(PREFIX)pkg-config vorbisidec --cflags`
54+
55+
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
56+
57+
ASFLAGS := -g $(ARCH)
58+
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
59+
60+
LIBS := -lctru -lm `$(PREFIX)pkg-config vorbisidec --libs`
61+
62+
#---------------------------------------------------------------------------------
63+
# list of directories containing libraries, this must be the top level containing
64+
# include and lib
65+
#---------------------------------------------------------------------------------
66+
LIBDIRS := $(PORTLIBS) $(CTRULIB)
67+
68+
69+
#---------------------------------------------------------------------------------
70+
# no real need to edit anything past this point unless you need to add additional
71+
# rules for different file extensions
72+
#---------------------------------------------------------------------------------
73+
ifneq ($(BUILD),$(notdir $(CURDIR)))
74+
#---------------------------------------------------------------------------------
75+
76+
export OUTPUT := $(CURDIR)/$(TARGET)
77+
export TOPDIR := $(CURDIR)
78+
79+
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
80+
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \
81+
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
82+
83+
export DEPSDIR := $(CURDIR)/$(BUILD)
84+
85+
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
86+
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
87+
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
88+
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica)))
89+
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
90+
GFXFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.t3s)))
91+
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
92+
93+
#---------------------------------------------------------------------------------
94+
# use CXX for linking C++ projects, CC for standard C
95+
#---------------------------------------------------------------------------------
96+
ifeq ($(strip $(CPPFILES)),)
97+
#---------------------------------------------------------------------------------
98+
export LD := $(CC)
99+
#---------------------------------------------------------------------------------
100+
else
101+
#---------------------------------------------------------------------------------
102+
export LD := $(CXX)
103+
#---------------------------------------------------------------------------------
104+
endif
105+
#---------------------------------------------------------------------------------
106+
107+
#---------------------------------------------------------------------------------
108+
ifeq ($(GFXBUILD),$(BUILD))
109+
#---------------------------------------------------------------------------------
110+
export T3XFILES := $(GFXFILES:.t3s=.t3x)
111+
#---------------------------------------------------------------------------------
112+
else
113+
#---------------------------------------------------------------------------------
114+
export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES))
115+
export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES))
116+
#---------------------------------------------------------------------------------
117+
endif
118+
#---------------------------------------------------------------------------------
119+
120+
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
121+
122+
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \
123+
$(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \
124+
$(addsuffix .o,$(T3XFILES))
125+
126+
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES)
127+
128+
export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) \
129+
$(addsuffix .h,$(subst .,_,$(BINFILES))) \
130+
$(GFXFILES:.t3s=.h)
131+
132+
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
133+
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
134+
-I$(CURDIR)/$(BUILD)
135+
136+
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
137+
138+
export _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh)
139+
140+
ifeq ($(strip $(ICON)),)
141+
icons := $(wildcard *.png)
142+
ifneq (,$(findstring $(TARGET).png,$(icons)))
143+
export APP_ICON := $(TOPDIR)/$(TARGET).png
144+
else
145+
ifneq (,$(findstring icon.png,$(icons)))
146+
export APP_ICON := $(TOPDIR)/icon.png
147+
endif
148+
endif
149+
else
150+
export APP_ICON := $(TOPDIR)/$(ICON)
151+
endif
152+
153+
ifeq ($(strip $(NO_SMDH)),)
154+
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
155+
endif
156+
157+
ifneq ($(ROMFS),)
158+
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
159+
endif
160+
161+
.PHONY: all clean
162+
163+
#---------------------------------------------------------------------------------
164+
all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(T3XHFILES)
165+
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
166+
167+
$(BUILD):
168+
@mkdir -p $@
169+
170+
ifneq ($(GFXBUILD),$(BUILD))
171+
$(GFXBUILD):
172+
@mkdir -p $@
173+
endif
174+
175+
ifneq ($(DEPSDIR),$(BUILD))
176+
$(DEPSDIR):
177+
@mkdir -p $@
178+
endif
179+
180+
#---------------------------------------------------------------------------------
181+
clean:
182+
@echo clean ...
183+
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD)
184+
185+
#---------------------------------------------------------------------------------
186+
$(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s
187+
#---------------------------------------------------------------------------------
188+
@echo $(notdir $<)
189+
@tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x
190+
191+
#---------------------------------------------------------------------------------
192+
else
193+
194+
#---------------------------------------------------------------------------------
195+
# main targets
196+
#---------------------------------------------------------------------------------
197+
$(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS)
198+
199+
$(OFILES_SOURCES) : $(HFILES)
200+
201+
$(OUTPUT).elf : $(OFILES)
202+
203+
#---------------------------------------------------------------------------------
204+
# you need a rule like this for each extension you use as binary data
205+
#---------------------------------------------------------------------------------
206+
%.bin.o %_bin.h : %.bin
207+
#---------------------------------------------------------------------------------
208+
@echo $(notdir $<)
209+
@$(bin2o)
210+
211+
#---------------------------------------------------------------------------------
212+
.PRECIOUS : %.t3x %.shbin
213+
#---------------------------------------------------------------------------------
214+
%.t3x.o %_t3x.h : %.t3x
215+
#---------------------------------------------------------------------------------
216+
$(SILENTMSG) $(notdir $<)
217+
$(bin2o)
218+
219+
#---------------------------------------------------------------------------------
220+
%.shbin.o %_shbin.h : %.shbin
221+
#---------------------------------------------------------------------------------
222+
$(SILENTMSG) $(notdir $<)
223+
$(bin2o)
224+
225+
-include $(DEPSDIR)/*.d
226+
227+
#---------------------------------------------------------------------------------------
228+
endif
229+
#---------------------------------------------------------------------------------------
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Ogg Vorbis decoding example
2+
3+
This is a heavily-commented example of how to carry out fast, threaded Ogg Vorbis audio streaming from the filesystem (in this case, RomFS) on 3DS using libvorbisidec, even on O3DS.
4+
5+
## Necessary packages
6+
7+
This example uses `libvorbisidec` (which in turn depends on `libogg`) to read and decode Ogg Vorbis audio files. The makefile also uses `pkg-config` to discover the necessary include paths and flags for the library.
8+
9+
You can install the necessary packages with the following command:
10+
```bash
11+
pacman -S 3ds-libvorbisidec 3ds-pkg-config
12+
```
13+
14+
Note that on some systems, you may need to use `dkp-pacman` instead of `pacman`, and you may need to prefix the installation commands with `sudo`.
15+
16+
Additionally, if you do not already have `pkg-config` installed on your *host system*, you will need to install it using your package manager.
17+
18+
On Windows:
19+
```bash
20+
pacman -S pkg-config
21+
```
22+
23+
On macOS:
24+
```bash
25+
sudo dkp-pacman -S pkg-config
26+
```
27+
28+
## Further reading
29+
30+
In addition to the detailed comments in `main.c`, see the docs for [libctru](https://libctru.devkitpro.org/) and the not-quite-matching-but-close ones for [libvorbisfile](https://www.xiph.org/vorbis/doc/vorbisfile/index.html).
31+
32+
## Credits
33+
34+
Originally written for Opus decoding by [Lauren Kelly (thejsa)](https://github.com/thejsa), with help from [mtheall](https://github.com/mtheall), adapted to Vorbis decoding by [Théo B. (LiquidFenrir)](https://github.com/LiquidFenrir)
35+
36+
The sample audio included as `sample.ogg` is [The Internet Memory Foundation's recording of Johan Sebastian Bach's Orchestral Suite no. 2 in B minor, BWV 1067 - 7. Badinerie, sourced from Musopen](https://musopen.org/music/3774-orchestral-suite-no-2-in-b-minor-bwv-1067/) and in the public domain (transcoded to mono Ogg Vorbis using Audacity, as ffmpeg's vorbis encoder only supports stereo).
732 KB
Binary file not shown.

0 commit comments

Comments
 (0)