Making Music

 

// Overview

The music in Mixolumia changes as the player progresses through a game, and the game’s sound effects harmonize with the music being played.

Soundpacks are loaded from external files, which means anyone can make and distribute or sell their own soundpacks for Mixolumia.

In a nutshell, a soundpack is a folder with one JSON file and a bunch of Ogg Vorbis audio files. A composer can create a series of sections comprised of loops. Each loop has associated sound effects, which are organized into progressions to aid in harmonization.

There are four important sections to make the progression trick work: The start, middle, outro, and end. When the player hits certain numbers of clears, the next section is queued to play after the currently playing loop. The final section, end, is a short finisher when the game ends.


 

// Sections and Soundpack Structure

Soundpack structure diagram

Here’s an example of how a soundpack could be structured. Each block in this example diagram represents a loop. Loops that start a section (start, middle, outro, end) must be named correctly, but any other names are up to you.

You can use fewer or more loops depending on how you want to structure the soundpack, and loops can link to any other loop in the progression. The diagram above is just a few examples of how a soundpack might flow.

Note: I am considering allowing for some randomization if you link a loop to multiple other loops to make songs more unpredictable.

The end section may interrupt the currently playing loop at any time because the player could win before hitting the outro during some game modes. The music should be designed to work, even if the transition is abrupt.

When composing your soundpack, keep in mind that the game will be moving faster as the player progresses, so in a typical Marathon game, the outro will likely last a shorter amount of time than the start or middle sections.


 

// Loops

Loops are comprised of the following:

  • "audio" - an audio file in the .ogg format
  • "bpm" - the bpm of this file. Different loops can have different speeds if you wanna get wild
  • "length" - the length of the loop in beats. One measure in 4/4 time would have a length of 4. This is NOT in measures, because there is no assumption for time signature
  • "progression" - the associated sfx progression
  • "next" - the name of the next loop

The bpm and length of each loop is used so that the loop audio files can contain reverb tails that overlap the next loop instead of abruptly switching.

Diagram showing loops overlapping

An example loop might look like:

"start": {
	"audio": "intro.ogg",
	"bpm": 140,
	"length": 32,
	"progression": "prog_0",
	"next": "loop_0"
}

The end loop doesn’t require any information except for the audio file. It might look like:

"end": {
	"audio": "end.ogg",
}


 

// Progressions

Progressions are what allow the sound effects to harmonize with a loop. You can use the same progression on any number of loops.

Let’s take a simplified example. Let’s say a loop is just a C major chord. You can define a progression that is just C.

Let’s say a loop is 1 measure of C, then 1 measure of F. Your progression would be C/F because a progression divides the time for each step equally.

What if your loop is unequal? Say we have 3 beats in C, and 1 beat in F. Your progression could be C/C/C/F. The length of the progression is not defined, so if this was applied to a 4 measure loop instead of a 1 measure loop, it would mean 3 measures of C and 1 measure of F.

Diagram of progressions

Progressions are a little more than that in practice because instead of just “C” you actually define a drop group, move group, clear group, and combo group for each step. So an example progression might look like:

"progression_0": [
	["drop_0", "move_C", "clear_C", "combo_0"],
	["drop_0", "move_C", "clear_C_alt", "combo_0"],
	["drop_1", "move_F", "clear_F", "combo_0"],
	["drop_1", "move_A", "clear_A", "combo_0"]
]


 

// Drop Groups

This is the sound that plays when the player’s tetrad lands. I used a deep bass thud in Tessellation and a snap sound in Minimum, but it’s open to your musical inspiration.

You can only specify one drop sound per progression.

The JSON for drop groups looks like this:

"drop_0": "drop.ogg"


 

// Move Groups

Move groups define the sounds that will play when the player twists or moves the tetrad.

They work kind of like a mini progression within themselves, so you could define a sort of melody or arpeggio as the player plays. You can make this as simple or as complex as you like.

The movement sounds won’t necessarily play in the order you write them, but will play depending on where in the progression the player happens to trigger a sound while playing. The way this happens is through magic and nonsense and no one should attempt to understand it.

Move groups diagram

The JSON for move groups looks like this:

"move_C": [
	"move_C_0.ogg",
	"move_C_2.ogg",
	"move_C_1.ogg",
	"move_C_3.ogg",
	"move_C_1.ogg",
	"move_C_3.ogg",
	"move_C_2.ogg",
	"move_C_4.ogg",
	"move_C_0.ogg",
	"move_C_2.ogg",
	"move_C_1.ogg",
	"move_C_3.ogg",
	"move_C_1.ogg",
	"move_C_3.ogg",
	"move_C_2.ogg",
	"move_C_5.ogg",
]

As you can see, you can reuse sounds as much as you need to, even across groups. The game will only load each audio file into memory once, so don’t worry about that.


 

// Clear Groups

Clear groups define the sounds that will play when the player clears blocks.

Because we want to give feedback when the player clears a lot of blocks, or if they have a really strong combo going, clear groups are made up of exactly 3 sound files. Think of them as a small clear, medium clear, and big clear. The JSON for a clear group looks like this:

"clear_C": [
	"clear_C_0.ogg",
	"clear_C_1.ogg",
	"clear_C_2.ogg"
]

I’ve been adding notes to make fuller chords for bigger clear sounds, but how you want to use it is up to you. You could use short riffs, or nontonal sound effects, or anything you dream up.


 

// Combo Groups

Combo groups define the sounds that will play when the player starts a chain reaction and gets multiple sets of clears with one drop. When the board has finally settled, a visual effect and sound will be triggered.

Like clear groups, combo groups are made up of exactly 3 sound files, for small, medium, and big combos. The JSON for a combo group looks like this:

"combo_0": [
	"combo_0_0.ogg",
	"combo_0_1.ogg",
	"combo_0_2.ogg"
]


 

// Gain Adjustment

Sometimes you want to adjust your mix after you’ve exported all your sound effects, and you don’t want to have to go back and do it again. The good news is that you can adjust the gain for sounds in the JSON in a section that looks like this:

"gain": {
	"master": 0.7,
	"drop": 0.9,
	"move": 0.5,
	"clear": 1,
	"combo": 0.6,
	"loop": 1
}

This allows you to lower the volume of sets of sounds, or of the track as a whole, to easily adjust the mix of your soundpack and keep its levels in line with other soundpacks in Mixolumia.

Keep in mind that this number adjusts the gain of sounds linearly. Human perception of sounds is not linear, so a change from 0.1 to 0.2 is going to sound more drastic than a change from 0.9 to 1.0. It’s weird, I know! Just keep it in mind as you adjust, and consider using a percentage to decibel conversion tool online if you need to be precise.


 

// Soundpack Info

Finally, there’s a place to put the title of the soundpack and the author’s name. This defines exactly what is displayed in the track selection screen. Simple enough!

"info": {
	"title": "Track Title",
	"author": "Your Name"
}

Rush mode tracks have an extra field in the soundpack info section. See the Rush mode section in this doc to learn more.


 

// Cover Art

Soundpack cover art example

Cover art for your soundpack is a 96x96 pixel square image called cover.png in the soundpack folder. I suggest using only black and white (1-bit), no grays, or you may see unexpected results in-game. The game will automatically display the album art in the player’s currently selected palette. If the user selects a “light” palette, cover art will be inverted automatically. If you don’t provide a cover, the game will show some default art.


 

// File Location

There are soundpacks included in the game’s install directory, and it’s fine to look at those for reference, but it’s best to put user-created soundpacks in the working directory to avoid bugs, especially if you’re using zip files.

The correct soundpack directory on Windows is:

%LOCALAPPDATA%/Mixolumia/data/music/

On Mac it’s:

~/Library/Application Support/com.davemakes.mixolumia/data/music

You may need to create this directory if it doesn’t already exist.

If you add a folder with a custom soundpack in the soundpack directory, it will be added to the sound selection screen. Mixolumia will load custom soundpacks when the game starts, and you will be able to use the left and right arrow buttons to choose a soundpack.


 

// JSON

It’s super important to format the JSON right and use {} or [], commas in the right places, and quotation marks correctly. JSON is a pain to read and write but it works really well on the programming side.

I recommend taking a look at the included soundpack to get a feel for how it’s structured. There’s a handy visual JSON editor online that will help you avoid errors, so consider giving that a shot when creating your soundpack.

If your soundpack is breaking in some way, try pasting your JSON into a website that will check it for syntax errors. A missing comma can throw the whole thing off.

You can download an example JSON file to see how things might work or dig into existing soundpacks. If you’re an advanced user, the community has put together a JSON schema to help.


 

// Ogg Vorbis

Ogg Vorbis (.ogg) files are compressed audio files like MP3, but the format is open source. Mixolumia uses this format because it’s what Game Maker Studio 2 supports for streaming audio from outside the game executable.

Your DAW likely doesn’t support exporting to Ogg Vorbis, but there’s a quick way to convert a bunch of WAV files quickly using the free program Audacity. Simply drag your WAV files into an Audacity project and they will be added as separate tracks. Choose File > Export > Export Multiple and set the Format to Ogg Vorbis Files. I set the quality to 3, which seems fine for my purposes, but if your ears are more attuned to audio compression than mine, feel free to experiment.


 

// Sound Test

It can be difficult and time consuming to test soundpacks in Mixolumia, especially if you’re not an expert player. I highly suggest enabling sound test when building a track. All you have to do is add a line to the game settings file.

The game settings file location on Windows is:

%LOCALAPPDATA%/Mixolumia/game_settings.ini

On Mac it should be:

~/Library/Application Support/com.davemakes.mixolumia/game_settings.ini

Open that file and add the line:

soundtest=1

You can change this value to 0 and restart the game to disable sound test.

Soundtest screenshot

When sound test is enabled, you will see a readout along the left side showing you the name of the current loop, the loop that’s queued to play next, and the current drop/move/clear/combo groups. Along the top is a progress bar showing how long until the next loop will be played.

Sound test also enables a few extra keyboard commands.

  • Keys 1, 2, and 3: Play clear sounds
  • Keys 3, 4, and 5: Play combo sounds
  • Enter: Advances to the next section.

If you press enter three times total, the you will reach the end section and the game will conclude.


 

// Rush Mode

In Mixolumia, there is a game mode called Rush in which the player tries to score as many points as possible in two minutes. This creates a very different musical experience, which is why the Rush soundpack selection is different from other modes.

Rush mode structure diagram

Rush soundpacks begin from the start section like any other soundpack in Mixolumia, but no other sections are ever triggered by gameplay, and are not required in your JSON file. Progression of a Rush track is based on time instead of clears, and should be designed to reach its climax at the 2 minute mark when the player runs out of time. Your soundpack structure will likely be much more linear than in other modes.

To mark a soundpack so that it is included in the selection of Rush mode music, the soundpack info section of the JSON needs the line "mode": "rush" added to the info section.

"info": {
	"title": "Example Title",
	"author": "Author Name",
	"mode": "rush"
}


 

// Copyrighted Samples

Just a quick note: Be wary of using copyrighted samples for sound effects outside of your loops. It’s a good idea to make sure you’ve transformed them enough that you aren’t doing anything to break the license by redistributing them since they’re essentially just sound files in a folder.


 

// Distributing Soundpacks

So, you made a soundpack, and want other Mixolumia players to be able to play it! I would love to be able to pay folks for their work and include more soundpacks with the game, and if enough people buy Mixolumia, maybe that dream will come true (please tell your friends about Mixolumia).

However, Mixolumia is set up so that anyone can make and distribute/sell their own soundpacks. Obviously please don’t bundle and redistribute the game itself, that would really hurt my ability to add cool features to Mixolumia and make more games in the future, but any Mixolumia soundpacks you create belong to you and you can do with them as you wish! Nothing would make me happier than seeing fans making money off their musical creations on Itch.io or elsewhere.

As far as the technical side of things, you can distribute your soundpack as a folder, or you can bundle the files as a zip and the game will automatically extract it. The player just needs to drop your soundpack into the data/music directory and it will be available the next time they start the game.

Note: I would like for this process to be easier for players, and I’m working on it!


 

// Future Plans

I would like to make a companion app to help generate the JSON files and test soundpacks, but that’s kind of a big investment, and I’m not sure if I’ll have the resources to get to it.

I am open to feedback and ideas, so please let me know if you think of anything.

Thanks!