-
Notifications
You must be signed in to change notification settings - Fork 1
FAQ
Welcome to the skysongbuilder wiki!
The first step to using SkySongBuilder is to create the configuration file. Now there are many options provided by SkySongBuilder for maximum customizability, but you will generally be using only a few of these.
Here's a quick-start guide:
- Extract the
bgm.swd
file from your EoS ROM. Put it somewhere and set setmainbank
to point to it. Importantly, always make a copy of the original cleanbgm.swd
file and set this option to point to the copy; this is to avoid the build-up of samples. See How do I extract the bgm.swd file? if you're not sure how to do this. - Add your soundfonts into
soundfonts
like so (only if you are using the in-engine song building feature):
soundfonts:
A name for the soundfont: the/path/to/the/soundfont
Multiple soundfonts can be added: the/path/to/the/second/soundfont
- Add your songs into
songs
like so:
songs:
# In-engine examples:
A name for the song:
i: 1
mid: The path to the midi file for the song
uses: [The name you gave to the soundfont] # Inside `uses`, specify the soundfonts used by that specific song using the soundfont name you set earlier.
A second song:
i: 2
mid: 2_B_SYS_MENU.mid
uses: [The name you gave to the soundfont, Multiple soundfonts can be added]
# Streamed:
A name for the streamed song:
i: 3
raw: The path to the audio file (most common audio formats are supported, but if there's ever a format that SkySongBuilder can't read, re-export the audio file as a WAVE file through Audacity first)
loop_point: 100000 # Loop start position in samples. If you omit this option, the song is not looped.
formats: [Wav4BitAdpcmNDSPlanarStereoLooped] # This is what you would want for stereo music. See the options dictionary below or the example configuration for other options.
dsp:
adpcm_block_size: 16377 # Default is good
resample_at: 32728 # Streamed songs must be resampled to a sample rate lower than 32728Hz since that's the highest supported by the Nintendo DS's sound chip.
flags: SND_STREAM # Default is good, required for playback using the patch
For more details about what each entry in the configuration file does, take a look at the dictionary down below, or alternatively, the example configuration file here and specifically at the comments on each line.
You can build as many songs as you'd like by adding more and more entries into this file! In fact, it's recommended that you use one really big config file to build all of your songs, because SkySongBuilder's optimizations work best when it can optimize across the entire soundtrack.
The easiest way is to use DSLazy. After downloading it:
- Open the file picker and choose your ROM.
- Click on "nds unpack".
- The folder with all the unpacked files should pop up!
- From here, go to
data > SOUND > BGM
, and you'll find thebgm.swd
file there. This is also where all the individual songs are!
How do multiple soundfonts work? Can I specify which preset from which soundfont I want to use in the MIDI?
MIDI doesn't include the built-in ability to specify which soundfont to use for a specified bank/program number, so you can't pick presets from soundfonts arbitrarily. The feature is currently similar to how most soundfont players implement multiple soundfonts, basically, whenever there's a bank/program that is needed by a track, SkySongBuilder will look through the list of soundfonts one by one, and the first soundfont containing the preset will be used.
OK here we go:
-
outputdir: ./out
(path to any folder, existing or not)
This is pretty straightforward, it's where SkySongBuilder will output your final music files that you can use in-game! -
The
dsp:
section contains configuration options related to the audio processing.-
resample_threshold: 22050
(integer)
As you make more songs, you'll start noticing the memory limit of the Nintendo DS, and how you can't put as many samples that you would like in memory for each track. For reference, most built-in tracks use only 2 or 3 samples per preset! This is then what you should also aim for, but there are also other things that can be done to conserve memory that are hard to do manually that SkySongBuilder will help with. One of those things is the sample rate of the samples.What is Sample Rate?
- Digital audio is a series of measurements taken over time of air pressure represented as numbers. Sample Rate is how often to take these measurements. 44,100Hz sample rate means the audio file contains 44,100 samples in one second. You might also realize though that this means a higher sample rate means more space taken.
SkySongBuilder has a built-in feature to reduce sample rate; this is one of those ways you can conserve memory space easily, a good first-step to try when you hit memory problems. The
resample_threshold
specifies the threshold at which SkySongBuilder will determine if a sample needs resampling or not: if a sample has a sample rate above this threshold, it will lower the sample rate.Note: Memory restrictions do not apply for streamed songs, but keep in mind that streamed songs will take up around 1/3 of the total sound memory of the game, which you should keep in mind when using BGM2 to playback in-engine songs at the same time. This is not something special that happens for streamed songs, playing two in-engine tracks at once can also potentially cause the game to run out of memory allocated for sound.
-
resample_at: 22050
(integer)
Continuing onresample_threshold
,resample_at
sets the sample rate to resample to if a sample has a sample rate that's above the threshoold. -
adpcm_encoder_lookahead: 3
(integer from 0-8)
Another way that SkySongBuilder can help you cut down on memory usage is by converting 16-bit PCM samples to 4-bit ADPCM. This leads to a 4-fold decrease in file size. This option in particular is one provided by the encoder, and a higher value will allow it to look further ahead into future samples to encode audio files more accurately, since ADPCM doesn't encode sample values, but encodes the differences between adjacent ones (which is why it can save space so much). A practical way to understand this option is that the higher it is, the better, but also the higher it is, the slower. Keep this as the default when you're composing and testing, then change it to 6 when releasing, and go take a nice long break. -
adpcm_block_size: 16377
(integer 1 greater than a multiple of 8)
Another, more advanced, setting related to ADPCM compression, this applies only to streamed songs where ADPCM audio is split into blocks of independently decodable data. This allows for streaming long files while maintaining quality. The setting specifies the number of samples to pack into ADPCM blocks, which is why it has the restriction on it that it has to be 1 greater than a multiple of 8; this way when the block is converted into ADPCM, it gets neatly packed into good byte-aligned chunks. The default of 16377 creates ADPCM blocks of length 8192 bytes (or 0x2000 bytes).
-
-
mainbank: bgm.swd
(path to a file, must exist)
If you've opened thedata > SOUND > BGM
folder before, you might have seen what the music files in EoS look like: there's thebgm.swd
, and then there's thebgm0001.swd/bgm0001.smd
,bgm0002.swd/bgm0002.smd
, ... and so on. The way it works is that all the actual sample data is placed insidebgm.swd
which is the main bank. This is genius, because then you won't need to include the same sample twice for songs that use the same instruments! However this also means that in order for SkySongBuilder to not break the whole built-in soundtrack, it needs the original cleanbgm.swd
as a "base" of sorts to keep adding samples into!
When setting this, always make a copy of the original cleanbgm.swd
file and set this to point to the copy; this is to avoid the build-up of samples. -
decoupled: false
(boolean true/false)
Remember how all the samples are placed in the shared main bank filebgm.swd
? Well, DSE supports not doing that too! In this mode, all the samples are placed into each track's ownbgm####.swd
files directly, which has the benefit of portability. Keep in mind that enabling this will make your ROM size bigger since duplicate instruments cannot share samples between different songs. You'll also still need to setmainbank
, as it is crucial to a lot of the internal processes of SkySongBuilder.A Brief Note on an Edge Case
- There are slightly harder memory restrictions that apply when
decoupled
is enabled and the samples are stored in each track's SWD files. The way to think about the difference is that while for the main bank, the samples just need to fit into the RAM, for decoupled SWD files, the entire SWD file needs to fit in the RAM. The technical explanation is that while main bank files are read partially to save space, track SWD files are read in their entirety by the function call at 020199d8(us) insidePlayBGM
, and for larger files, this crashes the system.
- There are slightly harder memory restrictions that apply when
-
sample_rate_adjustment_curve: 1
(integer from 1-3)
If you have a 44,100Hz audio file and play it back two times fast, the pitch goes up by an octave, since all frequencies are now twice as frequent! Since samples can be any sample rate but has to be played back at the NDS's internal sample rate of around 32,768Hz, if no pitch adjustments are made, the final song will sound very weird indeed. An interesting tidbit about DSE is that this sample-rate based pitch adjustment is not done in code, but done beforehand as tuning values, and placed in the audio files. SkySongBuilder provides a few different ways to calculate the sample-rate adjustment necessary, and here's a description of each one. Bare in mind that the default 1 is good, so only change it if you are feeling experimental.- 1 - The ideal sample correction curve for a fixed 32728.5Hz hardware output rate
- 2 - A discrete lookup table based on the original EoS main bank (all samples must have or be converted to a sample rate matching one of the entries in this lookup table!)
- 3 - A fitted curve based on the original EoS main bank
-
pitch_adjust: 0
(signed integer)
A global pitch adjustment value in cents. -
flags: # WAVI_POINTER_EXTENSION | PRGI_POINTER_EXTENSION
(bitflags)
These are advanced options, use with care. Leave it as it is for normal usage. These flags can be set using standard bitflag syntax. Available flags:-
WAVI_POINTER_EXTENSION
This flag extends the 16-bit pointers used by the sample bank WAVI chunks to use 32-bit pointers instead. Only generated files are modified, input swd files can have either, and SkySongBuilder will read them accordingly.
Effects: Increases the number of samples allowed in each bank file to around 65,535 samples (theoretical, untested). (applicable to the massive main bank)
Requirements: The MoreSamplesAndPresets patch (requires ExtraSpace) -
PRGI_POINTER_EXTENSION
This flag extends the 16-bit pointers used by the sample bank PRGI chunks to use 32-bit pointers instead. Only generated files are modified, input swd files can have either, and SkySongBuilder will read them accordingly.
Effects: Increases the number and size of presets allowed in each bank file.
Requirements: The MoreSamplesAndPresets patch (requires ExtraSpace)
-
-
The
soundfonts:
section then contains a list of soundfonts you wanna use, and thesongs:
section then contains the actual songs!
Once you've finished making the configuration file, download the latest release here, and run the exe in the same folder as the configuration file!
They will all be in the folder you specified in outputdir
, which by default is just a folder named "out" in the same folder as the exe.
SkySongBuilder creates the following files:
-
bgm.swd
: The new main bank for the entire game. None of the samples used for the base game music are removed! So the entire built-in soundtrack will still play after you replace the old main bank in your ROM. (Note: will not be output if you setdecoupled
to true) -
bgm####.swd/bgm####.smd pairs
: These are the files for the individual songs. Thei
you specify for a song in the config will replace the####
part. -
bgm####_left.wav/bgm####_right.wav pairs
: These are the encoded audio files for the individual streamed songs. Like before thei
you specify for a song in the config will replace the####
part. Since these wave files are encoded in the IMA-ADPCM format, you can't play it back using the built-in media player inside of Windows; however you can actually listen to these files in supported players like VLC or mpv.
Note that swd and smd files are also generated for any streamed songs! This allows the assembly patch to preserve the built-in music engine, allowing the engine to keep doing its thing while the streamed song plays on the side.
The configuration file needs to be named soundtrack.yml
. Also, make sure you are running SkySongBuilder from the same folder as the configuration file!
Here are some things to keep in mind for writing paths which might be why the path isn't being read as you intended it to:
- If there's just a filename or if it starts with a
./
(e.g.bgm.swd
or./bgm.swd
), it means it's a file in the current folder (the same folder as the config file).
- You can also point to any file on your computer with a full path, such as
C:/Users/user/Downloads/file.sf2
orC:\Users\user\Downloads\file.sf2
or/home/user/file.sf2
You must have less than 16 channels in the MIDI, and only 16 voices can be active at a time!
What's a voice?
- A single sample playing on the hardware is a voice. If you have 5 samples playing on the hardware at one time, then we say that there are "5 voices active". Keep in mind that a sample could still be playing when you thought it must have ended already, if, for example, you set a really high release! This is important to keep in mind because the number of MIDI notes being pressed might not match the number of voices playing.
You also need to set MIDI Bank Select/Program Change messages to tell SkySongBuilder which Soundfont presets you're using (see What are MIDI Bank Select/Program Change messages?).
And finally if you'd like your track to loop, you also need to add a MIDI marker named "LoopStart" at the position where you would like the track to loop back to once its finished playing! (Optional) (See How do I loop?)
SkySongBuilder might not work for in-engine tracks if any of the above is missing!
Each preset in a soundfont has a bank/program number as an identifier:
MIDI Bank Select/Program Change messages are how MIDI tells the soundfont player which preset each channel should be using. Most DAW's have a functionality for doing this, which you can find information on through a quick search on Google for "midi bank select program change messages [name of music software]"
In short, you'll want to change the MSB and leave the LSB as 0.
A more technical explanation is that, in MIDI, there are two standard CC's used for bank select messages, CC0 and CC32.
Since CC values are limited in range from 0-127, historically CC0 and CC32 has been combined as CC0*128+CC32
in order to extend the number of presets a song could use to 0-16383. This calculation is also where the MSB LSB terminology was born.
In Soundfonts however the bank number only goes up until 127 anyways, so soundfont players usually use CC0 standalone, ignoring CC32, as seen here for example in FluidSynth.
You might want to change the volume, the panning, or some other parameters of a song's instruments while the song plays. Maybe you want to do a Ba-Sing-Se style panning effect? Or you want the flute to slowly get quieter. If you've used a DAW before, you might have used "automation" to do this. MIDI CC's are MIDI's version of that. Here's a list of the most common MIDI CC's (Bare in mind that not everything on the list is supported in SkySongBuilder).
Most DAW's have a way to edit this, which you can find through a quick search on Google for "add midi cc [name of music software]"
Currently, only the following CC's are handled:
- CC0 Bank Select MSB
- CC7 Volume MSB
- CC10 Pan Position MSB
- CC11 Expression MSB
In addition, pitch bend is supported as well.
Set a MIDI marker with the name "LoopStart" where you want the song to loop back to once it finishes playing. Note that there's no loop end in DSE, so MIDI files will just loop when the files end. However sometimes MIDI software add blank space at the end of files, leading to unclean looping, so the "LoopEnd" marker can be used to end the MIDI file early.
Before moving on to the ROM patching process, first you will need to turn your music files into a format supported by the music streaming patch. To do this, see Section 1 - The Configuration File. The process is very similar to how in-engine music is configured and built.
There's a few things you need to do on the ROM's side to make these files work since streamed music functionality isn't built into the game. Here's a step-by-step guide:
-
Apply the
ExtraSpace
patch
You can do this through SkyTemple as usual through the ASM patches section. -
Apply the
FifoHooks
patch
The new music streaming patch utilizes the arm7 sub-processor for decoding so that the game can continue to run smoothly while the sub-processor chugs away at decoding in real-time. This patch helps the game's main arm9 processor in communicating with the arm7.
The patch can be found here: https://github.com/adakite1/Asm-patches
SkyTemple Versions 1.6+ adds support for arm7 binary patching, the skypatch can now be used directly on all 3 game editions. The next patch after this still requires manual patching as per How do I apply a patch manually using armips? througharmips
. -
Apply the music streaming patch
You can find this patch under #community-patches inside of the SkyTemple discord server.
Note: The patch requires ExtraSpace and patches Overlay 36! Make sure to follow the additional instructions for overlay patching. See How do I apply a patch manually using armips? for how to do the patch.
**Always back-up your ROM when you're patching! That way there's always a clean point of recovery if anything goes wrong!!
- Unpack the ROM using dslazy. (see How do I extract the bgm.swd file? It's the same steps except you can stop once it's past the extraction part)
[Alternatively] On macOS and Linux where dslazy isn't available, follow these instructions. - In the unpacked directory, you should see the
arm7.bin
andarm9.bin
files.
- If the patch you are applying requires patching an overlay, copy the required overlay files from the
overlay
directory into the same place where thearm7.bin
andarm9.bin
files are. (If the patch you are applying usesExtraSpace
, then Overlay 36 must be patched!) - While most patches that use Overlay 36 write into their assigned areas, some patches write into the common area which starts at
0x23D7FF0
(on all editions). When applying these patches, make sure that the patch does not overwrite other ASM already patched into the same locations!
- Copy all the files of the asm patch into this folder. Importantly, the main patch should be in the same directory as the arm9 and arm7 binaries that are to be patched.
- [Only if this file exists. If not, the patch creator might have a different mechanism for region selection, or the patch might be single region only] Open the
regionSelect.asm
file, which should now also be in the same folder as the binaries, in a text editor. At the top you will find a line that says_REGION equ "US"
. Change "US" here to your ROM's region. Supported regions are "US", "EU", and "JP". - Download the latest version of armips from https://buildbot.orphis.net/armips/.
- Extract, then move the
armips.exe
file into the directory where thearm7.bin
andarm9.bin
files are. - Open a PowerShell or Terminal window inside of that same directory. If you don't know how to do this, see How do I open PowerShell or the Terminal inside of a directory? How do I run an executable in that directory?.
- Type
./armips.exe <name of the patch file>
on Windows or./armips <name of the patch file>
on macOS or Linux. - If it doesn't show any errors, continue.
- Now, if this patch involved patching any overlay files, move the overlay files back into the
overlay
folder, overwriting the originals. - The patching is done but we need to build a new
nds
rom with those patched files inside. Go back to where you had thedslazy
executable, in the same folder you should also seendstool.exe
. Copy that into the folder with all the patching happening. - Back inside of the PowerShell or Terminal window, type
.\ndstool -c <name for patched rom file>.nds -9 arm9.bin -7 arm7.bin -y9 y9.bin -y7 y7.bin -d data -y overlay -t banner.bin -h header.bin
and hit enter, changing the angle bracket values to your own. - Now, a brand new ROM should be present in the directory with the name you've specified. The patching is complete.
How do I open PowerShell or the Terminal inside of a directory? How do I run an executable in that directory?
-
Windows 10/11: See this tutorial. Once you have the command prompt or PowerShell open inside the folder where you have an executable, type
./name_of_executable_file.exe
and hit enter. -
macOS: Open the
Terminal
app, and then typecd
(with a space at the end) (do not hit enter!). Drag the folder you want the Terminal to be in into the Terminal window, this will automatically fill in the path to that folder into the terminal window. Now hit enter to change directories into the directory. Then type./name_of_executable_file
and hit enter. - Linux: You know the drill.
A black screen is an indication that the memory limit has been reached! Try setting the resample_threshold
and the resample_at
parameters, or if you have to degrade the audio quality too much to make it work with that, try manually using less samples by removing some notes.
You might be using a bgm number greater than 201! In that case, you will need to apply Adex's PlayMoreBgm
patch here: https://github.com/Adex-8x/jam-patches/blob/master/strung-up-by-sketches/PlayMoreBgm.skypatch
This is a very large piece of software with many moving parts, and so bugs can sometimes slip by despite my best efforts. If you find any bugs, reporting it here with details necessary for me to reproduce them helps immensely in helping me eliminate them!
General (including streamed music)
- Head to https://github.com/adakite1/skysongbuilder/issues and create a new issue as usual.
In-engine music sound differences
- Confirm that with a specific combination of sf2, midi, and soundtrack.yml files, the note pitch, note length, timbre, automation, or other musical element sound correct in an sf2 player (standards are VirtualMIDISynth, FluidSynth, and BassMIDI without any DAW intervention) but sound incorrect in SkySongBuilder.
- Head to https://github.com/adakite1/skysongbuilder/issues and create a new issue with a description of the mismatch, with a recording of the correct and incorrect playback.